Skip to content

Commit 6412d47

Browse files
committed
pybricks.iodevices.I2CDevice: Implement legacy read and write.
These are wrappers around write_then_read for backwards compatibility.
1 parent f8e62bc commit 6412d47

File tree

1 file changed

+79
-7
lines changed

1 file changed

+79
-7
lines changed

pybricks/iodevices/pb_type_iodevices_i2cdevice.c

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,19 +152,23 @@ MP_DEFINE_CONST_OBJ_TYPE(operation_type,
152152
static 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.
199202
static 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)
202272
static 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
};
205277
static MP_DEFINE_CONST_DICT(locals_dict, locals_dict_table);

0 commit comments

Comments
 (0)