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
mp_hal_i2c_delay(machine_i2c_obj_t * self)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
mp_hal_i2c_scl_low(machine_i2c_obj_t * self)46 STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) {
47 mp_hal_pin_od_low(self->scl);
48 }
49
mp_hal_i2c_scl_release(machine_i2c_obj_t * self)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
mp_hal_i2c_sda_low(machine_i2c_obj_t * self)65 STATIC void mp_hal_i2c_sda_low(machine_i2c_obj_t *self) {
66 mp_hal_pin_od_low(self->sda);
67 }
68
mp_hal_i2c_sda_release(machine_i2c_obj_t * self)69 STATIC void mp_hal_i2c_sda_release(machine_i2c_obj_t *self) {
70 mp_hal_pin_od_high(self->sda);
71 }
72
mp_hal_i2c_sda_read(machine_i2c_obj_t * self)73 STATIC int mp_hal_i2c_sda_read(machine_i2c_obj_t *self) {
74 return mp_hal_pin_read(self->sda);
75 }
76
mp_hal_i2c_start(machine_i2c_obj_t * self)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
mp_hal_i2c_stop(machine_i2c_obj_t * self)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
mp_hal_i2c_init(machine_i2c_obj_t * self,uint32_t freq)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
mp_hal_i2c_write_byte(machine_i2c_obj_t * self,uint8_t val)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
mp_hal_i2c_read_byte(machine_i2c_obj_t * self,uint8_t * val,int nack)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
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)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
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)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
mp_machine_i2c_readfrom(mp_obj_base_t * self,uint16_t addr,uint8_t * dest,size_t len,bool stop)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
mp_machine_i2c_writeto(mp_obj_base_t * self,uint16_t addr,const uint8_t * src,size_t len,bool stop)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
machine_i2c_init(size_t n_args,const mp_obj_t * args,mp_map_t * kw_args)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
machine_i2c_deinit(size_t n_args,const mp_obj_t * args,mp_map_t * kw_args)316 STATIC mp_obj_t machine_i2c_deinit(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args)
317 {
318 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
319 mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
320 if (i2c_p->deinit != NULL) {
321 i2c_p->deinit(self);
322 }
323 return mp_const_none;
324 }
325 MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_deinit_obj, 1, machine_i2c_deinit);
326
machine_i2c_scan(mp_obj_t self_in)327 STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
328 mp_obj_base_t *self = MP_OBJ_TO_PTR(self_in);
329 mp_obj_t list = mp_obj_new_list(0, NULL);
330 // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
331 for (int addr = 0x08; addr < 0x78; ++addr) {
332 int ret = mp_machine_i2c_writeto(self, addr, NULL, 0, true);
333 if (ret == 0) {
334 mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
335 }
336 }
337 return list;
338 }
339 MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
340
machine_i2c_start(mp_obj_t self_in)341 STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) {
342 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
343 mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
344 if (i2c_p->start == NULL) {
345 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
346 }
347 int ret = i2c_p->start(self);
348 if (ret != 0) {
349 mp_raise_OSError(-ret);
350 }
351 return mp_const_none;
352 }
353 MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start);
354
machine_i2c_stop(mp_obj_t self_in)355 STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) {
356 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
357 mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
358 if (i2c_p->stop == NULL) {
359 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
360 }
361 int ret = i2c_p->stop(self);
362 if (ret != 0) {
363 mp_raise_OSError(-ret);
364 }
365 return mp_const_none;
366 }
367 MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop);
368
machine_i2c_readinto(size_t n_args,const mp_obj_t * args)369 STATIC mp_obj_t machine_i2c_readinto(size_t n_args, const mp_obj_t *args) {
370 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
371 mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
372 if (i2c_p->read == NULL) {
373 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
374 }
375
376 // get the buffer to read into
377 mp_buffer_info_t bufinfo;
378 mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
379
380 // work out if we want to send a nack at the end
381 bool nack = (n_args == 2) ? true : mp_obj_is_true(args[2]);
382
383 // do the read
384 int ret = i2c_p->read(self, bufinfo.buf, bufinfo.len, nack);
385 if (ret != 0) {
386 mp_raise_OSError(-ret);
387 }
388
389 return mp_const_none;
390 }
391 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readinto_obj, 2, 3, machine_i2c_readinto);
392
machine_i2c_write(mp_obj_t self_in,mp_obj_t buf_in)393 STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) {
394 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
395 mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
396 if (i2c_p->write == NULL) {
397 mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
398 }
399
400 // get the buffer to write from
401 mp_buffer_info_t bufinfo;
402 mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
403
404 // do the write
405 int ret = i2c_p->write(self, bufinfo.buf, bufinfo.len);
406 if (ret < 0) {
407 mp_raise_OSError(-ret);
408 }
409
410 // return number of acks received
411 return MP_OBJ_NEW_SMALL_INT(ret);
412 }
413 MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write);
414
machine_i2c_readfrom(size_t n_args,const mp_obj_t * args)415 STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) {
416 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
417 mp_int_t addr = mp_obj_get_int(args[1]);
418 vstr_t vstr;
419 vstr_init_len(&vstr, mp_obj_get_int(args[2]));
420 bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
421 int ret = mp_machine_i2c_readfrom(self, addr, (uint8_t *)vstr.buf, vstr.len, stop);
422 if (ret < 0) {
423 mp_raise_OSError(-ret);
424 }
425 return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
426 }
427 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom);
428
machine_i2c_readfrom_into(size_t n_args,const mp_obj_t * args)429 STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) {
430 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
431 mp_int_t addr = mp_obj_get_int(args[1]);
432 mp_buffer_info_t bufinfo;
433 mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE);
434 bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
435 int ret = mp_machine_i2c_readfrom(self, addr, bufinfo.buf, bufinfo.len, stop);
436 if (ret < 0) {
437 mp_raise_OSError(-ret);
438 }
439 return mp_const_none;
440 }
441 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine_i2c_readfrom_into);
442
machine_i2c_writeto(size_t n_args,const mp_obj_t * args)443 STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) {
444 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
445 mp_int_t addr = mp_obj_get_int(args[1]);
446 mp_buffer_info_t bufinfo;
447 mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
448 bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
449 int ret = mp_machine_i2c_writeto(self, addr, bufinfo.buf, bufinfo.len, stop);
450 if (ret < 0) {
451 mp_raise_OSError(-ret);
452 }
453 // return number of acks received
454 return MP_OBJ_NEW_SMALL_INT(ret);
455 }
456 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto);
457
machine_i2c_writevto(size_t n_args,const mp_obj_t * args)458 STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) {
459 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
460 mp_int_t addr = mp_obj_get_int(args[1]);
461
462 // Get the list of data buffer(s) to write
463 size_t nitems;
464 const mp_obj_t *items;
465 mp_obj_get_array(args[2], &nitems, (mp_obj_t **)&items);
466
467 // Get the stop argument
468 bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
469
470 // Extract all buffer data, skipping zero-length buffers
471 size_t alloc = nitems == 0 ? 1 : nitems;
472 size_t nbufs = 0;
473 mp_machine_i2c_buf_t *bufs = mp_local_alloc(alloc * sizeof(mp_machine_i2c_buf_t));
474 for (; nitems--; ++items) {
475 mp_buffer_info_t bufinfo;
476 mp_get_buffer_raise(*items, &bufinfo, MP_BUFFER_READ);
477 if (bufinfo.len > 0) {
478 bufs[nbufs].len = bufinfo.len;
479 bufs[nbufs++].buf = bufinfo.buf;
480 }
481 }
482
483 // Make sure there is at least one buffer, empty if needed
484 if (nbufs == 0) {
485 bufs[0].len = 0;
486 bufs[0].buf = NULL;
487 nbufs = 1;
488 }
489
490 // Do the I2C transfer
491 mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
492 int ret = i2c_p->transfer(self, addr, nbufs, bufs, stop ? MP_MACHINE_I2C_FLAG_STOP : 0);
493 mp_local_free(bufs);
494
495 if (ret < 0) {
496 mp_raise_OSError(-ret);
497 }
498
499 // Return number of acks received
500 return MP_OBJ_NEW_SMALL_INT(ret);
501 }
502 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writevto_obj, 3, 4, machine_i2c_writevto);
503
fill_memaddr_buf(uint8_t * memaddr_buf,uint32_t memaddr,uint8_t addrsize)504 STATIC size_t fill_memaddr_buf(uint8_t *memaddr_buf, uint32_t memaddr, uint8_t addrsize) {
505 size_t memaddr_len = 0;
506 if ((addrsize & 7) != 0 || addrsize > 32) {
507 mp_raise_ValueError(MP_ERROR_TEXT("invalid addrsize"));
508 }
509 for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
510 memaddr_buf[memaddr_len++] = memaddr >> i;
511 }
512 return memaddr_len;
513 }
514
read_mem(mp_obj_t self_in,uint16_t addr,uint32_t memaddr,uint8_t addrsize,uint8_t * buf,size_t len)515 STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) {
516 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
517
518 // Create buffer with memory address
519 uint8_t memaddr_buf[4];
520 size_t memaddr_len = fill_memaddr_buf(&memaddr_buf[0], memaddr, addrsize);
521
522 int ret = mp_machine_i2c_writeto(self, addr, memaddr_buf, memaddr_len, false);
523 if (ret != memaddr_len) {
524 // must generate STOP
525 mp_machine_i2c_writeto(self, addr, NULL, 0, true);
526 return ret;
527 }
528 return mp_machine_i2c_readfrom(self, addr, buf, len, true);
529 }
530
write_mem(mp_obj_t self_in,uint16_t addr,uint32_t memaddr,uint8_t addrsize,const uint8_t * buf,size_t len)531 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) {
532 mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
533
534 // Create buffer with memory address
535 uint8_t memaddr_buf[4];
536 size_t memaddr_len = fill_memaddr_buf(&memaddr_buf[0], memaddr, addrsize);
537
538 // Create partial write buffers
539 mp_machine_i2c_buf_t bufs[2] = {
540 {.len = memaddr_len, .buf = memaddr_buf},
541 {.len = len, .buf = (uint8_t *)buf},
542 };
543
544 // Do I2C transfer
545 mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
546 return i2c_p->transfer(self, addr, 2, bufs, MP_MACHINE_I2C_FLAG_STOP);
547 }
548
549 STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = {
550 { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
551 { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
552 { MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
553 { MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
554 };
555
machine_i2c_readfrom_mem(size_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)556 STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
557 enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize };
558 mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
559 mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
560 MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
561
562 // create the buffer to store data into
563 vstr_t vstr;
564 vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj));
565
566 // do the transfer
567 int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
568 args[ARG_addrsize].u_int, (uint8_t *)vstr.buf, vstr.len);
569 if (ret < 0) {
570 mp_raise_OSError(-ret);
571 }
572
573 return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
574 }
575 MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
576
577
machine_i2c_readfrom_mem_into(size_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)578 STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
579 enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
580 mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
581 mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
582 MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
583
584 // get the buffer to store data into
585 mp_buffer_info_t bufinfo;
586 mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE);
587
588 // do the transfer
589 int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
590 args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
591 if (ret < 0) {
592 mp_raise_OSError(-ret);
593 }
594 return mp_const_none;
595 }
596 MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into);
597
machine_i2c_writeto_mem(size_t n_args,const mp_obj_t * pos_args,mp_map_t * kw_args)598 STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
599 enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
600 mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
601 mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
602 MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
603
604 // get the buffer to write the data from
605 mp_buffer_info_t bufinfo;
606 mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
607
608 // do the transfer
609 int ret = write_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
610 args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
611 if (ret < 0) {
612 mp_raise_OSError(-ret);
613 }
614
615 return mp_const_none;
616 }
617 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem);
618
619 STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
620 { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2c_init_obj) },
621 { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2c_deinit_obj) },
622 { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) },
623
624 // primitive I2C operations
625 { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_i2c_start_obj) },
626 { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_i2c_stop_obj) },
627 { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&machine_i2c_readinto_obj) },
628 { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_write_obj) },
629
630 // standard bus operations
631 { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) },
632 { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) },
633 { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) },
634 { MP_ROM_QSTR(MP_QSTR_writevto), MP_ROM_PTR(&machine_i2c_writevto_obj) },
635
636 // memory operations
637 { MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) },
638 { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) },
639 { MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) },
640 };
641 MP_DEFINE_CONST_DICT(mp_machine_i2c_locals_dict, machine_i2c_locals_dict_table);
642
643 /******************************************************************************/
644 // Implementation of soft I2C
645
mp_machine_soft_i2c_print(const mp_print_t * print,mp_obj_t self_in,mp_print_kind_t kind)646 STATIC void mp_machine_soft_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
647 mp_machine_soft_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
648 mp_printf(print, "SoftI2C(scl=" MP_HAL_PIN_FMT ", sda=" MP_HAL_PIN_FMT ", freq=%u)",
649 mp_hal_pin_name(self->scl), mp_hal_pin_name(self->sda), 500000 / self->us_delay);
650 }
651
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)652 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) {
653 enum { ARG_scl, ARG_sda, ARG_freq, ARG_timeout };
654 static const mp_arg_t allowed_args[] = {
655 { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
656 { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
657 { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
658 { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 255} },
659 };
660
661 mp_machine_soft_i2c_obj_t *self = (mp_machine_soft_i2c_obj_t *)self_in;
662 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
663 mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
664
665 self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj);
666 self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj);
667 self->us_timeout = args[ARG_timeout].u_int;
668 mp_hal_i2c_init(self, args[ARG_freq].u_int);
669 }
670
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)671 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) {
672 // create new soft I2C object
673 machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t);
674 self->base.type = &mp_machine_soft_i2c_type;
675 mp_map_t kw_args;
676 mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
677 mp_machine_soft_i2c_init(&self->base, n_args, args, &kw_args);
678 return MP_OBJ_FROM_PTR(self);
679 }
680
mp_machine_soft_i2c_read(mp_obj_base_t * self_in,uint8_t * dest,size_t len,bool nack)681 int mp_machine_soft_i2c_read(mp_obj_base_t *self_in, uint8_t *dest, size_t len, bool nack) {
682 machine_i2c_obj_t *self = (machine_i2c_obj_t *)self_in;
683 while (len--) {
684 int ret = mp_hal_i2c_read_byte(self, dest++, nack && (len == 0));
685 if (ret != 0) {
686 return ret;
687 }
688 }
689 return 0; // success
690 }
691
mp_machine_soft_i2c_write(mp_obj_base_t * self_in,const uint8_t * src,size_t len)692 int mp_machine_soft_i2c_write(mp_obj_base_t *self_in, const uint8_t *src, size_t len) {
693 machine_i2c_obj_t *self = (machine_i2c_obj_t *)self_in;
694 int num_acks = 0;
695 while (len--) {
696 int ret = mp_hal_i2c_write_byte(self, *src++);
697 if (ret < 0) {
698 return ret;
699 } else if (ret != 0) {
700 // nack received, stop sending
701 break;
702 }
703 ++num_acks;
704 }
705 return num_acks;
706 }
707
708 STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = {
709 .init = mp_machine_soft_i2c_init,
710 .start = (int (*)(mp_obj_base_t *))mp_hal_i2c_start,
711 .stop = (int (*)(mp_obj_base_t *))mp_hal_i2c_stop,
712 .read = mp_machine_soft_i2c_read,
713 .write = mp_machine_soft_i2c_write,
714 .transfer = mp_machine_soft_i2c_transfer,
715 };
716
717 const mp_obj_type_t mp_machine_soft_i2c_type = {
718 { &mp_type_type },
719 .name = MP_QSTR_SoftI2C,
720 .print = mp_machine_soft_i2c_print,
721 .make_new = mp_machine_soft_i2c_make_new,
722 .protocol = &mp_machine_soft_i2c_p,
723 .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict,
724 };
725
726 #endif // MICROPY_PY_MACHINE_I2C
727