@@ -152,19 +152,23 @@ MP_DEFINE_CONST_OBJ_TYPE(operation_type,
152152static mp_obj_t write_then_read (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
153153 PB_PARSE_ARGS_METHOD (n_args , pos_args , kw_args ,
154154 device_obj_t , self ,
155- PB_ARG_DEFAULT_NONE (write_data ),
156- PB_ARG_DEFAULT_INT ( read_size , 0 )
155+ PB_ARG_REQUIRED (write_data ),
156+ PB_ARG_REQUIRED ( read_length )
157157 );
158158
159159 uint8_t * write_data = (uint8_t * )mp_obj_str_get_data (write_data_in , & self -> write_len );
160160
161161 self -> state = 0 ;
162162
163163 // Pre-allocate the return value so we have something to write the result to.
164- self -> read_result = mp_obj_malloc (mp_obj_str_t , & mp_type_bytes );
165- self -> read_result -> len = mp_obj_get_int (read_size_in );
166- self -> read_result -> hash = 0 ;
167- self -> read_result -> data = m_new (byte , self -> read_result -> len );
164+ size_t len = pb_obj_get_positive_int (read_length_in );
165+ if (len ) {
166+ self -> read_result = mp_obj_new_bytes (NULL , len );
167+ self -> read_result -> hash = 0 ;
168+ self -> read_result -> data = m_new (byte , self -> read_result -> len );
169+ } else {
170+ self -> read_result = (mp_obj_str_t * )& mp_const_empty_bytes_obj ;
171+ }
168172
169173 // Kick off the operation. This will immediately raise if a transaction is
170174 // in progress.
@@ -195,11 +199,79 @@ static mp_obj_t write_then_read(size_t n_args, const mp_obj_t *pos_args, mp_map_
195199
196200 return operation_get_result_obj (self );
197201}
198- // See also experimental_globals_table below. This function object is added there to make it importable.
199202static MP_DEFINE_CONST_FUN_OBJ_KW (write_then_read_obj , 0 , write_then_read ) ;
200203
204+ // pybricks.iodevices.I2CDevice.read
205+ static mp_obj_t read (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
206+ PB_PARSE_ARGS_METHOD (n_args , pos_args , kw_args ,
207+ device_obj_t , self ,
208+ PB_ARG_DEFAULT_NONE (reg ),
209+ PB_ARG_DEFAULT_INT (length , 1 )
210+ );
211+
212+ // Write payload is one byte representing the register we want to read,
213+ // or no write for reg=None.
214+ const mp_obj_str_t * write_data = reg_in == mp_const_none ?
215+ & mp_const_empty_bytes_obj :
216+ & (mp_obj_str_t ) {
217+ .base = {
218+ .type = & mp_type_bytes ,
219+ },
220+ .hash = 0 ,
221+ .len = 1 ,
222+ .data = & (const byte ) {
223+ mp_obj_get_int (reg_in ),
224+ },
225+ };
226+
227+ // Call write_then_read with parsed arguments.
228+ const mp_obj_t write_then_read_args [] = {
229+ MP_OBJ_FROM_PTR (self ),
230+ MP_OBJ_FROM_PTR (write_data ),
231+ length_in ,
232+ };
233+ return write_then_read (MP_ARRAY_SIZE (write_then_read_args ), write_then_read_args , (mp_map_t * )& mp_const_empty_map );
234+ }
235+ static MP_DEFINE_CONST_FUN_OBJ_KW (read_obj , 0 , read ) ;
236+
237+ // pybricks.iodevices.I2CDevice.write
238+ static mp_obj_t write (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
239+ PB_PARSE_ARGS_METHOD (n_args , pos_args , kw_args ,
240+ device_obj_t , self ,
241+ PB_ARG_DEFAULT_NONE (reg ),
242+ PB_ARG_DEFAULT_NONE (data )
243+ );
244+
245+ // Treat none as empty bytes, needed for common operation.
246+ if (data_in == mp_const_none ) {
247+ data_in = mp_const_empty_bytes ;
248+ }
249+
250+ // If a register is provided, we need to concatenate it with write data.
251+ if (reg_in != mp_const_none ) {
252+ size_t original_len ;
253+ const char * original_data = mp_obj_str_get_data (data_in , & original_len );
254+ mp_obj_str_t * reg_and_data = mp_obj_new_bytes (NULL , original_len + 1 );
255+ byte * bytes = m_new (byte , reg_and_data -> len );
256+ bytes [0 ] = pb_obj_get_positive_int (reg_in );
257+ memcpy (& reg_and_data [1 ], original_data , original_len );
258+ data_in = MP_OBJ_FROM_PTR (reg_and_data );
259+ }
260+
261+ // Call write_then_read with parsed arguments.
262+ const mp_obj_t write_then_read_args [] = {
263+ MP_OBJ_FROM_PTR (self ),
264+ data_in ,
265+ MP_OBJ_NEW_SMALL_INT (0 ),
266+ };
267+ return write_then_read (MP_ARRAY_SIZE (write_then_read_args ), write_then_read_args , (mp_map_t * )& mp_const_empty_map );
268+ }
269+ static MP_DEFINE_CONST_FUN_OBJ_KW (write_obj , 0 , write ) ;
270+
201271// dir(pybricks.iodevices.I2CDevice)
202272static const mp_rom_map_elem_t locals_dict_table [] = {
273+ { MP_ROM_QSTR (MP_QSTR_read ), MP_ROM_PTR (& read_obj ) },
274+ { MP_ROM_QSTR (MP_QSTR_write ), MP_ROM_PTR (& write_obj ) },
203275 { MP_ROM_QSTR (MP_QSTR_write_then_read ), MP_ROM_PTR (& write_then_read_obj ) },
204276};
205277static MP_DEFINE_CONST_DICT (locals_dict , locals_dict_table ) ;
0 commit comments