3636
3737STATIC const mp_obj_type_t machine_hard_i2c_type ;
3838
39+ STATIC const mp_arg_t machine_i2c_mem_allowed_args [] = {
40+ { MP_QSTR_addr , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 0 } },
41+ { MP_QSTR_memaddr , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 0 } },
42+ { MP_QSTR_arg , MP_ARG_REQUIRED | MP_ARG_OBJ , {.u_obj = MP_OBJ_NULL } },
43+ { MP_QSTR_addrsize , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 8 } },
44+ };
45+
3946typedef struct _machine_hard_i2c_obj_t {
4047 mp_obj_base_t base ;
4148 struct rt_i2c_bus_device * i2c_bus ;
@@ -53,12 +60,66 @@ STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp
5360 return ;
5461}
5562
56- int machine_hard_i2c_readfrom (mp_obj_base_t * self_in , uint16_t addr , uint8_t * dest , size_t len , bool stop ) {
63+ 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 ) {
64+ machine_hard_i2c_obj_t * self = (machine_hard_i2c_obj_t * )MP_OBJ_TO_PTR (self_in );
65+
66+ // Create buffer with memory address
67+ size_t memaddr_len = 0 ;
68+ uint8_t memaddr_buf [4 ];
69+ for (int16_t i = addrsize - 8 ; i >= 0 ; i -= 8 ) {
70+ memaddr_buf [memaddr_len ++ ] = memaddr >> i ;
71+ }
72+
73+ struct rt_i2c_msg msg [2 ];
74+
75+ msg [0 ].buf = memaddr_buf ;
76+ msg [0 ].len = (addrsize + 7 )/8 ;
77+ msg [0 ].flags = RT_I2C_WR ;
78+ msg [0 ].addr = addr ;
79+
80+ msg [1 ].buf = (rt_uint8_t * )buf ;
81+ msg [1 ].len = len ;
82+ msg [1 ].flags = RT_I2C_WR ;
83+ msg [1 ].addr = addr ;
84+
85+ if (rt_i2c_transfer (self -> i2c_bus , msg , 2 ) != 2 )
86+ return - MP_EIO ;
87+
88+ return len ;
89+ }
90+
91+ STATIC int read_mem (mp_obj_t self_in , uint16_t addr , uint32_t memaddr , uint8_t addrsize , uint8_t * buf , size_t len ) {
92+ machine_hard_i2c_obj_t * self = (machine_hard_i2c_obj_t * )MP_OBJ_TO_PTR (self_in );
93+ uint8_t memaddr_buf [4 ];
94+ size_t memaddr_len = 0 ;
95+ for (int16_t i = addrsize - 8 ; i >= 0 ; i -= 8 ) {
96+ memaddr_buf [memaddr_len ++ ] = memaddr >> i ;
97+ }
98+
99+ struct rt_i2c_msg msg [2 ];
100+
101+ msg [0 ].buf = memaddr_buf ;
102+ msg [0 ].len = (addrsize + 7 )/8 ;
103+ msg [0 ].flags = RT_I2C_WR ;
104+ msg [0 ].addr = addr ;
105+
106+ msg [1 ].buf = buf ;
107+ msg [1 ].len = len ;
108+ msg [1 ].flags = RT_I2C_RD ;
109+ msg [1 ].addr = addr ;
110+
111+ if (rt_i2c_transfer (self -> i2c_bus , msg , 2 ) != 2 )
112+ return - MP_EIO ;
113+
114+ return len ;
115+ }
116+
117+ STATIC int mp_machine_i2c_readfrom (mp_obj_base_t * self_in , uint16_t addr , uint8_t * dest , size_t len , bool stop ) {
57118 machine_hard_i2c_obj_t * self = MP_OBJ_TO_PTR (self_in );
58119 return rt_i2c_master_recv (self -> i2c_bus , addr , 0 , dest , len );
59120}
60121
61- int machine_hard_i2c_writeto (mp_obj_base_t * self_in , uint16_t addr , const uint8_t * src , size_t len , bool stop ) {
122+ STATIC int mp_machine_i2c_writeto (mp_obj_base_t * self_in , uint16_t addr , const uint8_t * src , size_t len , bool stop ) {
62123 uint8_t buf [1 ] = {0 };
63124 machine_hard_i2c_obj_t * self = MP_OBJ_TO_PTR (self_in );
64125 if (len == 0 ){
@@ -73,6 +134,188 @@ int machine_hard_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_
73134 return rt_i2c_master_send (self -> i2c_bus , addr , 0 , src , len );
74135}
75136
137+ STATIC mp_obj_t machine_i2c_scan (mp_obj_t self_in ) {
138+ mp_obj_base_t * self = MP_OBJ_TO_PTR (self_in );
139+ mp_obj_t list = mp_obj_new_list (0 , NULL );
140+ // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
141+ for (int addr = 0x08 ; addr < 0x78 ; ++ addr ) {
142+ int ret = mp_machine_i2c_writeto (self , addr , NULL , 0 , true);
143+ if (ret == 0 ) {
144+ mp_obj_list_append (list , MP_OBJ_NEW_SMALL_INT (addr ));
145+ }
146+ }
147+ return list ;
148+ }
149+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (machine_i2c_scan_obj , machine_i2c_scan );
150+
151+ STATIC mp_obj_t machine_i2c_readfrom (size_t n_args , const mp_obj_t * args ) {
152+ mp_obj_base_t * self = (mp_obj_base_t * )MP_OBJ_TO_PTR (args [0 ]);
153+ mp_int_t addr = mp_obj_get_int (args [1 ]);
154+ vstr_t vstr ;
155+ vstr_init_len (& vstr , mp_obj_get_int (args [2 ]));
156+ bool stop = (n_args == 3 ) ? true : mp_obj_is_true (args [3 ]);
157+ int ret = mp_machine_i2c_readfrom (self , addr , (uint8_t * )vstr .buf , vstr .len , stop );
158+ if (ret < 0 ) {
159+ mp_raise_OSError (- ret );
160+ }
161+ return mp_obj_new_str_from_vstr (& mp_type_bytes , & vstr );
162+ }
163+ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (machine_i2c_readfrom_obj , 3 , 4 , machine_i2c_readfrom );
164+
165+ STATIC mp_obj_t machine_i2c_readfrom_into (size_t n_args , const mp_obj_t * args ) {
166+ mp_obj_base_t * self = (mp_obj_base_t * )MP_OBJ_TO_PTR (args [0 ]);
167+ mp_int_t addr = mp_obj_get_int (args [1 ]);
168+ mp_buffer_info_t bufinfo ;
169+ mp_get_buffer_raise (args [2 ], & bufinfo , MP_BUFFER_WRITE );
170+ bool stop = (n_args == 3 ) ? true : mp_obj_is_true (args [3 ]);
171+ int ret = mp_machine_i2c_readfrom (self , addr , bufinfo .buf , bufinfo .len , stop );
172+ if (ret < 0 ) {
173+ mp_raise_OSError (- ret );
174+ }
175+ return mp_const_none ;
176+ }
177+ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (machine_i2c_readfrom_into_obj , 3 , 4 , machine_i2c_readfrom_into );
178+
179+ STATIC mp_obj_t machine_i2c_writeto (size_t n_args , const mp_obj_t * args ) {
180+ mp_obj_base_t * self = (mp_obj_base_t * )MP_OBJ_TO_PTR (args [0 ]);
181+ mp_int_t addr = mp_obj_get_int (args [1 ]);
182+ mp_buffer_info_t bufinfo ;
183+ mp_get_buffer_raise (args [2 ], & bufinfo , MP_BUFFER_READ );
184+ bool stop = (n_args == 3 ) ? true : mp_obj_is_true (args [3 ]);
185+ int ret = mp_machine_i2c_writeto (self , addr , bufinfo .buf , bufinfo .len , stop );
186+ if (ret < 0 ) {
187+ mp_raise_OSError (- ret );
188+ }
189+ // return number of acks received
190+ return MP_OBJ_NEW_SMALL_INT (ret );
191+ }
192+ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (machine_i2c_writeto_obj , 3 , 4 , machine_i2c_writeto );
193+
194+ STATIC mp_obj_t machine_i2c_writevto (size_t n_args , const mp_obj_t * args ) {
195+ mp_obj_base_t * self = (mp_obj_base_t * )MP_OBJ_TO_PTR (args [0 ]);
196+ mp_int_t addr = mp_obj_get_int (args [1 ]);
197+
198+ // Get the list of data buffer(s) to write
199+ size_t nitems ;
200+ const mp_obj_t * items ;
201+ mp_obj_get_array (args [2 ], & nitems , (mp_obj_t * * )& items );
202+
203+ // Get the stop argument
204+ bool stop = (n_args == 3 ) ? true : mp_obj_is_true (args [3 ]);
205+
206+ // Extract all buffer data, skipping zero-length buffers
207+ size_t alloc = nitems == 0 ? 1 : nitems ;
208+ size_t nbufs = 0 ;
209+ struct rt_i2c_msg * bufs = mp_local_alloc (alloc * sizeof (struct rt_i2c_msg ));
210+ for (; nitems -- ; ++ items ) {
211+ mp_buffer_info_t bufinfo ;
212+ mp_get_buffer_raise (* items , & bufinfo , MP_BUFFER_READ );
213+ if (bufinfo .len > 0 ) {
214+ bufs [nbufs ].addr = addr ;
215+ bufs [nbufs ].flags = RT_I2C_WR ;
216+ bufs [nbufs ].len = bufinfo .len ;
217+ bufs [nbufs ++ ].buf = bufinfo .buf ;
218+ }
219+ }
220+
221+ // Make sure there is at least one buffer, empty if needed
222+ if (nbufs == 0 ) {
223+ bufs [0 ].len = 0 ;
224+ bufs [0 ].buf = NULL ;
225+ nbufs = 1 ;
226+ }
227+
228+ // Do the I2C transfer
229+ machine_hard_i2c_obj_t * i2c_p = (machine_hard_i2c_obj_t * )self ;
230+ int ret = rt_i2c_transfer (i2c_p -> i2c_bus , bufs , nbufs );
231+ mp_local_free (bufs );
232+
233+ if (ret < 0 ) {
234+ mp_raise_OSError (- ret );
235+ }
236+
237+ // Return number of acks received
238+ return MP_OBJ_NEW_SMALL_INT (ret );
239+ }
240+ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (machine_i2c_writevto_obj , 3 , 4 , machine_i2c_writevto );
241+
242+ STATIC mp_obj_t machine_i2c_readfrom_mem (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
243+ enum { ARG_addr , ARG_memaddr , ARG_n , ARG_addrsize };
244+ mp_arg_val_t args [MP_ARRAY_SIZE (machine_i2c_mem_allowed_args )];
245+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args ,
246+ MP_ARRAY_SIZE (machine_i2c_mem_allowed_args ), machine_i2c_mem_allowed_args , args );
247+
248+ // create the buffer to store data into
249+ vstr_t vstr ;
250+ vstr_init_len (& vstr , mp_obj_get_int (args [ARG_n ].u_obj ));
251+
252+ // do the transfer
253+ int ret = read_mem (pos_args [0 ], args [ARG_addr ].u_int , args [ARG_memaddr ].u_int ,
254+ args [ARG_addrsize ].u_int , (uint8_t * )vstr .buf , vstr .len );
255+ if (ret < 0 ) {
256+ mp_raise_OSError (- ret );
257+ }
258+
259+ return mp_obj_new_str_from_vstr (& mp_type_bytes , & vstr );
260+ }
261+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (machine_i2c_readfrom_mem_obj , 1 , machine_i2c_readfrom_mem );
262+
263+ STATIC mp_obj_t machine_i2c_readfrom_mem_into (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
264+ enum { ARG_addr , ARG_memaddr , ARG_buf , ARG_addrsize };
265+ mp_arg_val_t args [MP_ARRAY_SIZE (machine_i2c_mem_allowed_args )];
266+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args ,
267+ MP_ARRAY_SIZE (machine_i2c_mem_allowed_args ), machine_i2c_mem_allowed_args , args );
268+
269+ // get the buffer to store data into
270+ mp_buffer_info_t bufinfo ;
271+ mp_get_buffer_raise (args [ARG_buf ].u_obj , & bufinfo , MP_BUFFER_WRITE );
272+
273+ // do the transfer
274+ int ret = read_mem (pos_args [0 ], args [ARG_addr ].u_int , args [ARG_memaddr ].u_int ,
275+ args [ARG_addrsize ].u_int , bufinfo .buf , bufinfo .len );
276+ if (ret < 0 ) {
277+ mp_raise_OSError (- ret );
278+ }
279+ return mp_const_none ;
280+ }
281+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (machine_i2c_readfrom_mem_into_obj , 1 , machine_i2c_readfrom_mem_into );
282+
283+ STATIC mp_obj_t machine_i2c_writeto_mem (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
284+ enum { ARG_addr , ARG_memaddr , ARG_buf , ARG_addrsize };
285+ mp_arg_val_t args [MP_ARRAY_SIZE (machine_i2c_mem_allowed_args )];
286+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args ,
287+ MP_ARRAY_SIZE (machine_i2c_mem_allowed_args ), machine_i2c_mem_allowed_args , args );
288+
289+ // get the buffer to write the data from
290+ mp_buffer_info_t bufinfo ;
291+ mp_get_buffer_raise (args [ARG_buf ].u_obj , & bufinfo , MP_BUFFER_READ );
292+
293+ // do the transfer
294+ int ret = write_mem (pos_args [0 ], args [ARG_addr ].u_int , args [ARG_memaddr ].u_int ,
295+ args [ARG_addrsize ].u_int , bufinfo .buf , bufinfo .len );
296+ if (ret < 0 ) {
297+ mp_raise_OSError (- ret );
298+ }
299+
300+ return mp_const_none ;
301+ }
302+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (machine_i2c_writeto_mem_obj , 1 , machine_i2c_writeto_mem );
303+
304+ STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table [] = {
305+ { MP_ROM_QSTR (MP_QSTR_scan ), MP_ROM_PTR (& machine_i2c_scan_obj ) },
306+
307+ // standard bus operations
308+ { MP_ROM_QSTR (MP_QSTR_readfrom ), MP_ROM_PTR (& machine_i2c_readfrom_obj ) },
309+ { MP_ROM_QSTR (MP_QSTR_readfrom_into ), MP_ROM_PTR (& machine_i2c_readfrom_into_obj ) },
310+ { MP_ROM_QSTR (MP_QSTR_writeto ), MP_ROM_PTR (& machine_i2c_writeto_obj ) },
311+ { MP_ROM_QSTR (MP_QSTR_writevto ), MP_ROM_PTR (& machine_i2c_writevto_obj ) },
312+
313+ // memory operations
314+ { MP_ROM_QSTR (MP_QSTR_readfrom_mem ), MP_ROM_PTR (& machine_i2c_readfrom_mem_obj ) },
315+ { MP_ROM_QSTR (MP_QSTR_readfrom_mem_into ), MP_ROM_PTR (& machine_i2c_readfrom_mem_into_obj ) },
316+ { MP_ROM_QSTR (MP_QSTR_writeto_mem ), MP_ROM_PTR (& machine_i2c_writeto_mem_obj ) },
317+ };
318+
76319/******************************************************************************/
77320/* MicroPython bindings for machine API */
78321
@@ -94,6 +337,8 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz
94337 return (mp_obj_t ) self ;
95338}
96339
340+ MP_DEFINE_CONST_DICT (mp_machine_hard_i2c_locals_dict , machine_i2c_locals_dict_table );
341+
97342STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = {
98343 .start = NULL ,
99344 .stop = NULL ,
@@ -109,7 +354,7 @@ STATIC const mp_obj_type_t machine_hard_i2c_type = {
109354 .print = machine_hard_i2c_print ,
110355 .make_new = machine_hard_i2c_make_new ,
111356 .protocol = & machine_hard_i2c_p ,
112- .locals_dict = (mp_obj_dict_t * )& mp_machine_soft_i2c_locals_dict ,
357+ .locals_dict = (mp_obj_dict_t * )& mp_machine_hard_i2c_locals_dict ,
113358};
114359
115360#endif // MICROPYTHON_USING_MACHINE_I2C
0 commit comments