1 | /* |
2 | * This file is part of the MicroPython project, http://micropython.org/ |
3 | * |
4 | * The MIT License (MIT) |
5 | * |
6 | * Copyright (c) 2016 Damien P. George |
7 | * |
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
9 | * of this software and associated documentation files (the "Software"), to deal |
10 | * in the Software without restriction, including without limitation the rights |
11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
12 | * copies of the Software, and to permit persons to whom the Software is |
13 | * furnished to do so, subject to the following conditions: |
14 | * |
15 | * The above copyright notice and this permission notice shall be included in |
16 | * all copies or substantial portions of the Software. |
17 | * |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
24 | * THE SOFTWARE. |
25 | */ |
26 | |
27 | #include <stdio.h> |
28 | #include <stdint.h> |
29 | #include <string.h> |
30 | |
31 | #include "py/mperrno.h" |
32 | #include "py/mphal.h" |
33 | #include "py/runtime.h" |
34 | #include "extmod/machine_i2c.h" |
35 | |
36 | #if MICROPY_PY_MACHINE_I2C |
37 | |
38 | typedef mp_machine_soft_i2c_obj_t machine_i2c_obj_t; |
39 | |
40 | STATIC void mp_hal_i2c_delay(machine_i2c_obj_t *self) { |
41 | // We need to use an accurate delay to get acceptable I2C |
42 | // speeds (eg 1us should be not much more than 1us). |
43 | mp_hal_delay_us_fast(self->us_delay); |
44 | } |
45 | |
46 | STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) { |
47 | mp_hal_pin_od_low(self->scl); |
48 | } |
49 | |
50 | STATIC int mp_hal_i2c_scl_release(machine_i2c_obj_t *self) { |
51 | uint32_t count = self->us_timeout; |
52 | |
53 | mp_hal_pin_od_high(self->scl); |
54 | mp_hal_i2c_delay(self); |
55 | // For clock stretching, wait for the SCL pin to be released, with timeout. |
56 | for (; mp_hal_pin_read(self->scl) == 0 && count; --count) { |
57 | mp_hal_delay_us_fast(1); |
58 | } |
59 | if (count == 0) { |
60 | return -MP_ETIMEDOUT; |
61 | } |
62 | return 0; // success |
63 | } |
64 | |
65 | STATIC void mp_hal_i2c_sda_low(machine_i2c_obj_t *self) { |
66 | mp_hal_pin_od_low(self->sda); |
67 | } |
68 | |
69 | STATIC void mp_hal_i2c_sda_release(machine_i2c_obj_t *self) { |
70 | mp_hal_pin_od_high(self->sda); |
71 | } |
72 | |
73 | STATIC int mp_hal_i2c_sda_read(machine_i2c_obj_t *self) { |
74 | return mp_hal_pin_read(self->sda); |
75 | } |
76 | |
77 | STATIC int mp_hal_i2c_start(machine_i2c_obj_t *self) { |
78 | mp_hal_i2c_sda_release(self); |
79 | mp_hal_i2c_delay(self); |
80 | int ret = mp_hal_i2c_scl_release(self); |
81 | if (ret != 0) { |
82 | return ret; |
83 | } |
84 | mp_hal_i2c_sda_low(self); |
85 | mp_hal_i2c_delay(self); |
86 | return 0; // success |
87 | } |
88 | |
89 | STATIC int mp_hal_i2c_stop(machine_i2c_obj_t *self) { |
90 | mp_hal_i2c_delay(self); |
91 | mp_hal_i2c_sda_low(self); |
92 | mp_hal_i2c_delay(self); |
93 | int ret = mp_hal_i2c_scl_release(self); |
94 | mp_hal_i2c_sda_release(self); |
95 | mp_hal_i2c_delay(self); |
96 | return ret; |
97 | } |
98 | |
99 | STATIC void mp_hal_i2c_init(machine_i2c_obj_t *self, uint32_t freq) { |
100 | self->us_delay = 500000 / freq; |
101 | if (self->us_delay == 0) { |
102 | self->us_delay = 1; |
103 | } |
104 | mp_hal_pin_open_drain(self->scl); |
105 | mp_hal_pin_open_drain(self->sda); |
106 | mp_hal_i2c_stop(self); // ignore error |
107 | } |
108 | |
109 | // return value: |
110 | // 0 - byte written and ack received |
111 | // 1 - byte written and nack received |
112 | // <0 - error, with errno being the negative of the return value |
113 | STATIC int mp_hal_i2c_write_byte(machine_i2c_obj_t *self, uint8_t val) { |
114 | mp_hal_i2c_delay(self); |
115 | mp_hal_i2c_scl_low(self); |
116 | |
117 | for (int i = 7; i >= 0; i--) { |
118 | if ((val >> i) & 1) { |
119 | mp_hal_i2c_sda_release(self); |
120 | } else { |
121 | mp_hal_i2c_sda_low(self); |
122 | } |
123 | mp_hal_i2c_delay(self); |
124 | int ret = mp_hal_i2c_scl_release(self); |
125 | if (ret != 0) { |
126 | mp_hal_i2c_sda_release(self); |
127 | return ret; |
128 | } |
129 | mp_hal_i2c_scl_low(self); |
130 | } |
131 | |
132 | mp_hal_i2c_sda_release(self); |
133 | mp_hal_i2c_delay(self); |
134 | int ret = mp_hal_i2c_scl_release(self); |
135 | if (ret != 0) { |
136 | return ret; |
137 | } |
138 | |
139 | int ack = mp_hal_i2c_sda_read(self); |
140 | mp_hal_i2c_delay(self); |
141 | mp_hal_i2c_scl_low(self); |
142 | |
143 | return ack; |
144 | } |
145 | |
146 | // return value: |
147 | // 0 - success |
148 | // <0 - error, with errno being the negative of the return value |
149 | STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack) { |
150 | mp_hal_i2c_delay(self); |
151 | mp_hal_i2c_scl_low(self); |
152 | mp_hal_i2c_delay(self); |
153 | |
154 | uint8_t data = 0; |
155 | for (int i = 7; i >= 0; i--) { |
156 | int ret = mp_hal_i2c_scl_release(self); |
157 | if (ret != 0) { |
158 | return ret; |
159 | } |
160 | data = (data << 1) | mp_hal_i2c_sda_read(self); |
161 | mp_hal_i2c_scl_low(self); |
162 | mp_hal_i2c_delay(self); |
163 | } |
164 | *val = data; |
165 | |
166 | // send ack/nack bit |
167 | if (!nack) { |
168 | mp_hal_i2c_sda_low(self); |
169 | } |
170 | mp_hal_i2c_delay(self); |
171 | int ret = mp_hal_i2c_scl_release(self); |
172 | if (ret != 0) { |
173 | mp_hal_i2c_sda_release(self); |
174 | return ret; |
175 | } |
176 | mp_hal_i2c_scl_low(self); |
177 | mp_hal_i2c_sda_release(self); |
178 | |
179 | return 0; // success |
180 | } |
181 | |
182 | // return value: |
183 | // >=0 - success; for read it's 0, for write it's number of acks received |
184 | // <0 - error, with errno being the negative of the return value |
185 | int mp_machine_soft_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { |
186 | machine_i2c_obj_t *self = (machine_i2c_obj_t *)self_in; |
187 | |
188 | // start the I2C transaction |
189 | int ret = mp_hal_i2c_start(self); |
190 | if (ret != 0) { |
191 | return ret; |
192 | } |
193 | |
194 | // write the slave address |
195 | ret = mp_hal_i2c_write_byte(self, (addr << 1) | (flags & MP_MACHINE_I2C_FLAG_READ)); |
196 | if (ret < 0) { |
197 | return ret; |
198 | } else if (ret != 0) { |
199 | // nack received, release the bus cleanly |
200 | mp_hal_i2c_stop(self); |
201 | return -MP_ENODEV; |
202 | } |
203 | |
204 | int transfer_ret = 0; |
205 | for (; n--; ++bufs) { |
206 | size_t len = bufs->len; |
207 | uint8_t *buf = bufs->buf; |
208 | if (flags & MP_MACHINE_I2C_FLAG_READ) { |
209 | // read bytes from the slave into the given buffer(s) |
210 | while (len--) { |
211 | ret = mp_hal_i2c_read_byte(self, buf++, (n | len) == 0); |
212 | if (ret != 0) { |
213 | return ret; |
214 | } |
215 | } |
216 | } else { |
217 | // write bytes from the given buffer(s) to the slave |
218 | while (len--) { |
219 | ret = mp_hal_i2c_write_byte(self, *buf++); |
220 | if (ret < 0) { |
221 | return ret; |
222 | } else if (ret != 0) { |
223 | // nack received, stop sending |
224 | n = 0; |
225 | break; |
226 | } |
227 | ++transfer_ret; // count the number of acks |
228 | } |
229 | } |
230 | } |
231 | |
232 | // finish the I2C transaction |
233 | if (flags & MP_MACHINE_I2C_FLAG_STOP) { |
234 | ret = mp_hal_i2c_stop(self); |
235 | if (ret != 0) { |
236 | return ret; |
237 | } |
238 | } |
239 | |
240 | return transfer_ret; |
241 | } |
242 | |
243 | /******************************************************************************/ |
244 | // Generic helper functions |
245 | |
246 | // For use by ports that require a single buffer of data for a read/write transfer |
247 | int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) { |
248 | size_t len; |
249 | uint8_t *buf; |
250 | if (n == 1) { |
251 | // Use given single buffer |
252 | len = bufs[0].len; |
253 | buf = bufs[0].buf; |
254 | } else { |
255 | // Combine buffers into a single one |
256 | len = 0; |
257 | for (size_t i = 0; i < n; ++i) { |
258 | len += bufs[i].len; |
259 | } |
260 | buf = m_new(uint8_t, len); |
261 | if (!(flags & MP_MACHINE_I2C_FLAG_READ)) { |
262 | len = 0; |
263 | for (size_t i = 0; i < n; ++i) { |
264 | memcpy(buf + len, bufs[i].buf, bufs[i].len); |
265 | len += bufs[i].len; |
266 | } |
267 | } |
268 | } |
269 | |
270 | mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; |
271 | int ret = i2c_p->transfer_single(self, addr, len, buf, flags); |
272 | |
273 | if (n > 1) { |
274 | if (flags & MP_MACHINE_I2C_FLAG_READ) { |
275 | // Copy data from single buffer to individual ones |
276 | len = 0; |
277 | for (size_t i = 0; i < n; ++i) { |
278 | memcpy(bufs[i].buf, buf + len, bufs[i].len); |
279 | len += bufs[i].len; |
280 | } |
281 | } |
282 | m_del(uint8_t, buf, len); |
283 | } |
284 | |
285 | return ret; |
286 | } |
287 | |
288 | STATIC int mp_machine_i2c_readfrom(mp_obj_base_t *self, uint16_t addr, uint8_t *dest, size_t len, bool stop) { |
289 | mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; |
290 | mp_machine_i2c_buf_t buf = {.len = len, .buf = dest}; |
291 | unsigned int flags = MP_MACHINE_I2C_FLAG_READ | (stop ? MP_MACHINE_I2C_FLAG_STOP : 0); |
292 | return i2c_p->transfer(self, addr, 1, &buf, flags); |
293 | } |
294 | |
295 | STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self, uint16_t addr, const uint8_t *src, size_t len, bool stop) { |
296 | mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; |
297 | mp_machine_i2c_buf_t buf = {.len = len, .buf = (uint8_t *)src}; |
298 | unsigned int flags = stop ? MP_MACHINE_I2C_FLAG_STOP : 0; |
299 | return i2c_p->transfer(self, addr, 1, &buf, flags); |
300 | } |
301 | |
302 | /******************************************************************************/ |
303 | // MicroPython bindings for generic machine.I2C |
304 | |
305 | STATIC mp_obj_t machine_i2c_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { |
306 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); |
307 | mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; |
308 | if (i2c_p->init == NULL) { |
309 | mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported" )); |
310 | } |
311 | i2c_p->init(self, n_args - 1, args + 1, kw_args); |
312 | return mp_const_none; |
313 | } |
314 | MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_init_obj, 1, machine_i2c_init); |
315 | |
316 | STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { |
317 | mp_obj_base_t *self = MP_OBJ_TO_PTR(self_in); |
318 | mp_obj_t list = mp_obj_new_list(0, NULL); |
319 | // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved |
320 | for (int addr = 0x08; addr < 0x78; ++addr) { |
321 | int ret = mp_machine_i2c_writeto(self, addr, NULL, 0, true); |
322 | if (ret == 0) { |
323 | mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); |
324 | } |
325 | } |
326 | return list; |
327 | } |
328 | MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan); |
329 | |
330 | STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) { |
331 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); |
332 | mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; |
333 | if (i2c_p->start == NULL) { |
334 | mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported" )); |
335 | } |
336 | int ret = i2c_p->start(self); |
337 | if (ret != 0) { |
338 | mp_raise_OSError(-ret); |
339 | } |
340 | return mp_const_none; |
341 | } |
342 | MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start); |
343 | |
344 | STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) { |
345 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); |
346 | mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; |
347 | if (i2c_p->stop == NULL) { |
348 | mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported" )); |
349 | } |
350 | int ret = i2c_p->stop(self); |
351 | if (ret != 0) { |
352 | mp_raise_OSError(-ret); |
353 | } |
354 | return mp_const_none; |
355 | } |
356 | MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop); |
357 | |
358 | STATIC mp_obj_t machine_i2c_readinto(size_t n_args, const mp_obj_t *args) { |
359 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); |
360 | mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; |
361 | if (i2c_p->read == NULL) { |
362 | mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported" )); |
363 | } |
364 | |
365 | // get the buffer to read into |
366 | mp_buffer_info_t bufinfo; |
367 | mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); |
368 | |
369 | // work out if we want to send a nack at the end |
370 | bool nack = (n_args == 2) ? true : mp_obj_is_true(args[2]); |
371 | |
372 | // do the read |
373 | int ret = i2c_p->read(self, bufinfo.buf, bufinfo.len, nack); |
374 | if (ret != 0) { |
375 | mp_raise_OSError(-ret); |
376 | } |
377 | |
378 | return mp_const_none; |
379 | } |
380 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readinto_obj, 2, 3, machine_i2c_readinto); |
381 | |
382 | STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) { |
383 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); |
384 | mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; |
385 | if (i2c_p->write == NULL) { |
386 | mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported" )); |
387 | } |
388 | |
389 | // get the buffer to write from |
390 | mp_buffer_info_t bufinfo; |
391 | mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); |
392 | |
393 | // do the write |
394 | int ret = i2c_p->write(self, bufinfo.buf, bufinfo.len); |
395 | if (ret < 0) { |
396 | mp_raise_OSError(-ret); |
397 | } |
398 | |
399 | // return number of acks received |
400 | return MP_OBJ_NEW_SMALL_INT(ret); |
401 | } |
402 | MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write); |
403 | |
404 | STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) { |
405 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); |
406 | mp_int_t addr = mp_obj_get_int(args[1]); |
407 | vstr_t vstr; |
408 | vstr_init_len(&vstr, mp_obj_get_int(args[2])); |
409 | bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); |
410 | int ret = mp_machine_i2c_readfrom(self, addr, (uint8_t *)vstr.buf, vstr.len, stop); |
411 | if (ret < 0) { |
412 | mp_raise_OSError(-ret); |
413 | } |
414 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); |
415 | } |
416 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom); |
417 | |
418 | STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) { |
419 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); |
420 | mp_int_t addr = mp_obj_get_int(args[1]); |
421 | mp_buffer_info_t bufinfo; |
422 | mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); |
423 | bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); |
424 | int ret = mp_machine_i2c_readfrom(self, addr, bufinfo.buf, bufinfo.len, stop); |
425 | if (ret < 0) { |
426 | mp_raise_OSError(-ret); |
427 | } |
428 | return mp_const_none; |
429 | } |
430 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine_i2c_readfrom_into); |
431 | |
432 | STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) { |
433 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); |
434 | mp_int_t addr = mp_obj_get_int(args[1]); |
435 | mp_buffer_info_t bufinfo; |
436 | mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); |
437 | bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); |
438 | int ret = mp_machine_i2c_writeto(self, addr, bufinfo.buf, bufinfo.len, stop); |
439 | if (ret < 0) { |
440 | mp_raise_OSError(-ret); |
441 | } |
442 | // return number of acks received |
443 | return MP_OBJ_NEW_SMALL_INT(ret); |
444 | } |
445 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto); |
446 | |
447 | STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) { |
448 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]); |
449 | mp_int_t addr = mp_obj_get_int(args[1]); |
450 | |
451 | // Get the list of data buffer(s) to write |
452 | size_t nitems; |
453 | const mp_obj_t *items; |
454 | mp_obj_get_array(args[2], &nitems, (mp_obj_t **)&items); |
455 | |
456 | // Get the stop argument |
457 | bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]); |
458 | |
459 | // Extract all buffer data, skipping zero-length buffers |
460 | size_t alloc = nitems == 0 ? 1 : nitems; |
461 | size_t nbufs = 0; |
462 | mp_machine_i2c_buf_t *bufs = mp_local_alloc(alloc * sizeof(mp_machine_i2c_buf_t)); |
463 | for (; nitems--; ++items) { |
464 | mp_buffer_info_t bufinfo; |
465 | mp_get_buffer_raise(*items, &bufinfo, MP_BUFFER_READ); |
466 | if (bufinfo.len > 0) { |
467 | bufs[nbufs].len = bufinfo.len; |
468 | bufs[nbufs++].buf = bufinfo.buf; |
469 | } |
470 | } |
471 | |
472 | // Make sure there is at least one buffer, empty if needed |
473 | if (nbufs == 0) { |
474 | bufs[0].len = 0; |
475 | bufs[0].buf = NULL; |
476 | nbufs = 1; |
477 | } |
478 | |
479 | // Do the I2C transfer |
480 | mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; |
481 | int ret = i2c_p->transfer(self, addr, nbufs, bufs, stop ? MP_MACHINE_I2C_FLAG_STOP : 0); |
482 | mp_local_free(bufs); |
483 | |
484 | if (ret < 0) { |
485 | mp_raise_OSError(-ret); |
486 | } |
487 | |
488 | // Return number of acks received |
489 | return MP_OBJ_NEW_SMALL_INT(ret); |
490 | } |
491 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writevto_obj, 3, 4, machine_i2c_writevto); |
492 | |
493 | STATIC size_t fill_memaddr_buf(uint8_t *memaddr_buf, uint32_t memaddr, uint8_t addrsize) { |
494 | size_t memaddr_len = 0; |
495 | if ((addrsize & 7) != 0 || addrsize > 32) { |
496 | mp_raise_ValueError(MP_ERROR_TEXT("invalid addrsize" )); |
497 | } |
498 | for (int16_t i = addrsize - 8; i >= 0; i -= 8) { |
499 | memaddr_buf[memaddr_len++] = memaddr >> i; |
500 | } |
501 | return memaddr_len; |
502 | } |
503 | |
504 | STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) { |
505 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); |
506 | |
507 | // Create buffer with memory address |
508 | uint8_t memaddr_buf[4]; |
509 | size_t memaddr_len = fill_memaddr_buf(&memaddr_buf[0], memaddr, addrsize); |
510 | |
511 | int ret = mp_machine_i2c_writeto(self, addr, memaddr_buf, memaddr_len, false); |
512 | if (ret != memaddr_len) { |
513 | // must generate STOP |
514 | mp_machine_i2c_writeto(self, addr, NULL, 0, true); |
515 | return ret; |
516 | } |
517 | return mp_machine_i2c_readfrom(self, addr, buf, len, true); |
518 | } |
519 | |
520 | STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) { |
521 | mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in); |
522 | |
523 | // Create buffer with memory address |
524 | uint8_t memaddr_buf[4]; |
525 | size_t memaddr_len = fill_memaddr_buf(&memaddr_buf[0], memaddr, addrsize); |
526 | |
527 | // Create partial write buffers |
528 | mp_machine_i2c_buf_t bufs[2] = { |
529 | {.len = memaddr_len, .buf = memaddr_buf}, |
530 | {.len = len, .buf = (uint8_t *)buf}, |
531 | }; |
532 | |
533 | // Do I2C transfer |
534 | mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol; |
535 | return i2c_p->transfer(self, addr, 2, bufs, MP_MACHINE_I2C_FLAG_STOP); |
536 | } |
537 | |
538 | STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = { |
539 | { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, |
540 | { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, |
541 | { MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, |
542 | { MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, |
543 | }; |
544 | |
545 | STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { |
546 | enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize }; |
547 | mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; |
548 | mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, |
549 | MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); |
550 | |
551 | // create the buffer to store data into |
552 | vstr_t vstr; |
553 | vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj)); |
554 | |
555 | // do the transfer |
556 | int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int, |
557 | args[ARG_addrsize].u_int, (uint8_t *)vstr.buf, vstr.len); |
558 | if (ret < 0) { |
559 | mp_raise_OSError(-ret); |
560 | } |
561 | |
562 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); |
563 | } |
564 | MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem); |
565 | |
566 | |
567 | STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { |
568 | enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; |
569 | mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; |
570 | mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, |
571 | MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); |
572 | |
573 | // get the buffer to store data into |
574 | mp_buffer_info_t bufinfo; |
575 | mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE); |
576 | |
577 | // do the transfer |
578 | int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int, |
579 | args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len); |
580 | if (ret < 0) { |
581 | mp_raise_OSError(-ret); |
582 | } |
583 | return mp_const_none; |
584 | } |
585 | MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into); |
586 | |
587 | STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { |
588 | enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; |
589 | mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)]; |
590 | mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, |
591 | MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args); |
592 | |
593 | // get the buffer to write the data from |
594 | mp_buffer_info_t bufinfo; |
595 | mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ); |
596 | |
597 | // do the transfer |
598 | int ret = write_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int, |
599 | args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len); |
600 | if (ret < 0) { |
601 | mp_raise_OSError(-ret); |
602 | } |
603 | |
604 | return mp_const_none; |
605 | } |
606 | STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem); |
607 | |
608 | STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = { |
609 | { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2c_init_obj) }, |
610 | { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) }, |
611 | |
612 | // primitive I2C operations |
613 | { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_i2c_start_obj) }, |
614 | { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_i2c_stop_obj) }, |
615 | { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&machine_i2c_readinto_obj) }, |
616 | { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_write_obj) }, |
617 | |
618 | // standard bus operations |
619 | { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) }, |
620 | { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) }, |
621 | { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) }, |
622 | { MP_ROM_QSTR(MP_QSTR_writevto), MP_ROM_PTR(&machine_i2c_writevto_obj) }, |
623 | |
624 | // memory operations |
625 | { MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) }, |
626 | { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) }, |
627 | { MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) }, |
628 | }; |
629 | MP_DEFINE_CONST_DICT(mp_machine_i2c_locals_dict, machine_i2c_locals_dict_table); |
630 | |
631 | /******************************************************************************/ |
632 | // Implementation of soft I2C |
633 | |
634 | STATIC void mp_machine_soft_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { |
635 | mp_machine_soft_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); |
636 | mp_printf(print, "SoftI2C(scl=" MP_HAL_PIN_FMT ", sda=" MP_HAL_PIN_FMT ", freq=%u)" , |
637 | mp_hal_pin_name(self->scl), mp_hal_pin_name(self->sda), 500000 / self->us_delay); |
638 | } |
639 | |
640 | STATIC void mp_machine_soft_i2c_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { |
641 | enum { ARG_scl, ARG_sda, ARG_freq, ARG_timeout }; |
642 | static const mp_arg_t allowed_args[] = { |
643 | { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, |
644 | { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, |
645 | { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, |
646 | { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} }, |
647 | }; |
648 | |
649 | mp_machine_soft_i2c_obj_t *self = (mp_machine_soft_i2c_obj_t *)self_in; |
650 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; |
651 | mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); |
652 | |
653 | self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj); |
654 | self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj); |
655 | self->us_timeout = args[ARG_timeout].u_int; |
656 | mp_hal_i2c_init(self, args[ARG_freq].u_int); |
657 | } |
658 | |
659 | STATIC mp_obj_t mp_machine_soft_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { |
660 | // create new soft I2C object |
661 | machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t); |
662 | self->base.type = &mp_machine_soft_i2c_type; |
663 | mp_map_t kw_args; |
664 | mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); |
665 | mp_machine_soft_i2c_init(&self->base, n_args, args, &kw_args); |
666 | return MP_OBJ_FROM_PTR(self); |
667 | } |
668 | |
669 | int mp_machine_soft_i2c_read(mp_obj_base_t *self_in, uint8_t *dest, size_t len, bool nack) { |
670 | machine_i2c_obj_t *self = (machine_i2c_obj_t *)self_in; |
671 | while (len--) { |
672 | int ret = mp_hal_i2c_read_byte(self, dest++, nack && (len == 0)); |
673 | if (ret != 0) { |
674 | return ret; |
675 | } |
676 | } |
677 | return 0; // success |
678 | } |
679 | |
680 | int mp_machine_soft_i2c_write(mp_obj_base_t *self_in, const uint8_t *src, size_t len) { |
681 | machine_i2c_obj_t *self = (machine_i2c_obj_t *)self_in; |
682 | int num_acks = 0; |
683 | while (len--) { |
684 | int ret = mp_hal_i2c_write_byte(self, *src++); |
685 | if (ret < 0) { |
686 | return ret; |
687 | } else if (ret != 0) { |
688 | // nack received, stop sending |
689 | break; |
690 | } |
691 | ++num_acks; |
692 | } |
693 | return num_acks; |
694 | } |
695 | |
696 | STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = { |
697 | .init = mp_machine_soft_i2c_init, |
698 | .start = (int (*)(mp_obj_base_t *))mp_hal_i2c_start, |
699 | .stop = (int (*)(mp_obj_base_t *))mp_hal_i2c_stop, |
700 | .read = mp_machine_soft_i2c_read, |
701 | .write = mp_machine_soft_i2c_write, |
702 | .transfer = mp_machine_soft_i2c_transfer, |
703 | }; |
704 | |
705 | const mp_obj_type_t mp_machine_soft_i2c_type = { |
706 | { &mp_type_type }, |
707 | .name = MP_QSTR_SoftI2C, |
708 | .print = mp_machine_soft_i2c_print, |
709 | .make_new = mp_machine_soft_i2c_make_new, |
710 | .protocol = &mp_machine_soft_i2c_p, |
711 | .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict, |
712 | }; |
713 | |
714 | #endif // MICROPY_PY_MACHINE_I2C |
715 | |