Skip to content

Commit 83e6e66

Browse files
committed
wip; works on espressif
1 parent 3fb5023 commit 83e6e66

File tree

5 files changed

+107
-94
lines changed

5 files changed

+107
-94
lines changed

locale/circuitpython.pot

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ msgstr ""
9999
msgid "%q length must be %d-%d"
100100
msgstr ""
101101

102-
#: shared-bindings/usb_hid/Device.c
102+
#: shared-bindings/busio/I2C.c shared-bindings/usb_hid/Device.c
103103
msgid "%q length must be >= 1"
104104
msgstr ""
105105

@@ -631,7 +631,7 @@ msgstr ""
631631
msgid "Buffer must be a multiple of 512 bytes"
632632
msgstr ""
633633

634-
#: shared-bindings/bitbangio/I2C.c shared-bindings/busio/I2C.c
634+
#: shared-bindings/bitbangio/I2C.c
635635
msgid "Buffer must be at least length 1"
636636
msgstr ""
637637

ports/espressif/common-hal/busio/I2C.c

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,19 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
136136
self->scl_pin = NULL;
137137
}
138138

139-
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
139+
static esp_err_t i2c_zero_length_write(busio_i2c_obj_t *self, uint8_t addr, TickType_t timeout) {
140+
// i2c_master_write_to_device() won't do zero-length writes, so we do it by hand.
140141
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
141142
i2c_master_start(cmd);
142143
i2c_master_write_byte(cmd, addr << 1, true);
143144
i2c_master_stop(cmd);
144-
esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, 10);
145+
esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, timeout);
145146
i2c_cmd_link_delete(cmd);
147+
return result;
148+
}
149+
150+
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
151+
esp_err_t result = i2c_zero_length_write(self, addr, 1);
146152
return result == ESP_OK;
147153
}
148154

@@ -163,45 +169,36 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
163169
self->has_lock = false;
164170
}
165171

166-
uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
167-
const uint8_t *data, size_t len, bool transmit_stop_bit) {
168-
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
169-
i2c_master_start(cmd);
170-
i2c_master_write_byte(cmd, addr << 1, true);
171-
i2c_master_write(cmd, (uint8_t *)data, len, true);
172-
if (transmit_stop_bit) {
173-
i2c_master_stop(cmd);
172+
static uint8_t convert_esp_err(esp_err_t result) {
173+
switch (result) {
174+
case ESP_OK:
175+
return 0;
176+
case ESP_FAIL:
177+
return MP_ENODEV;
178+
case ESP_ERR_TIMEOUT:
179+
return MP_ETIMEDOUT;
180+
default:
181+
return MP_EIO;
174182
}
175-
esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, 100 /* wait in ticks */);
176-
i2c_cmd_link_delete(cmd);
183+
}
177184

178-
if (result == ESP_OK) {
179-
return 0;
180-
} else if (result == ESP_FAIL) {
181-
return MP_ENODEV;
182-
}
183-
return MP_EIO;
185+
uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint8_t addr, const uint8_t *data, size_t len) {
186+
return convert_esp_err(len == 0
187+
? i2c_zero_length_write(self, addr, 100)
188+
: i2c_master_write_to_device(self->i2c_num, addr, data, len, 100 /* wait in ticks */)
189+
);
184190
}
185191

186-
uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr,
187-
uint8_t *data, size_t len) {
188-
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
189-
i2c_master_start(cmd);
190-
i2c_master_write_byte(cmd, addr << 1 | 1, true); // | 1 to indicate read
191-
if (len > 1) {
192-
i2c_master_read(cmd, data, len - 1, 0);
193-
}
194-
i2c_master_read_byte(cmd, data + len - 1, 1);
195-
i2c_master_stop(cmd);
196-
esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, 100 /* wait in ticks */);
197-
i2c_cmd_link_delete(cmd);
192+
uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len) {
193+
return convert_esp_err(
194+
i2c_master_read_from_device(self->i2c_num, addr, data, len, 100 /* wait in ticks */));
195+
}
198196

199-
if (result == ESP_OK) {
200-
return 0;
201-
} else if (result == ESP_FAIL) {
202-
return MP_ENODEV;
203-
}
204-
return MP_EIO;
197+
uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint8_t addr,
198+
uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) {
199+
return convert_esp_err(
200+
i2c_master_write_read_device(self->i2c_num, (uint8_t)addr,
201+
out_data, out_len, in_data, in_len, 100 /* wait in ticks */));
205202
}
206203

207204
void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {

shared-bindings/busio/I2C.c

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,6 @@
5858
//| :param int frequency: The clock frequency in Hertz
5959
//| :param int timeout: The maximum clock stretching timeut - (used only for
6060
//| :class:`bitbangio.I2C`; ignored for :class:`busio.I2C`)
61-
//|
62-
//| .. note:: On the nRF52840, only one I2C object may be created,
63-
//| except on the Circuit Playground Bluefruit, which allows two,
64-
//| one for the onboard accelerometer, and one for offboard use."""
6561
//| ...
6662
//|
6763
STATIC mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
@@ -191,23 +187,6 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock);
191187
//| :param int end: end of buffer slice; if not specified, use ``len(buffer)``"""
192188
//| ...
193189
//|
194-
// Shared arg parsing for readfrom_into and writeto_then_readfrom.
195-
STATIC void readfrom(busio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end) {
196-
mp_buffer_info_t bufinfo;
197-
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE);
198-
199-
size_t length = bufinfo.len;
200-
normalize_buffer_bounds(&start, end, &length);
201-
if (length == 0) {
202-
mp_raise_ValueError(translate("Buffer must be at least length 1"));
203-
}
204-
205-
uint8_t status = common_hal_busio_i2c_read(self, address, ((uint8_t *)bufinfo.buf) + start, length);
206-
if (status != 0) {
207-
mp_raise_OSError(status);
208-
}
209-
}
210-
211190
STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
212191
enum { ARG_address, ARG_buffer, ARG_start, ARG_end };
213192
static const mp_arg_t allowed_args[] = {
@@ -219,11 +198,27 @@ STATIC mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args,
219198
busio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
220199
check_for_deinit(self);
221200
check_lock(self);
201+
222202
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
223203
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
224204

225-
readfrom(self, args[ARG_address].u_int, args[ARG_buffer].u_obj, args[ARG_start].u_int,
226-
args[ARG_end].u_int);
205+
mp_buffer_info_t bufinfo;
206+
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);
207+
208+
size_t length = bufinfo.len;
209+
int32_t start = args[ARG_start].u_int;
210+
const int32_t end = args[ARG_end].u_int;
211+
normalize_buffer_bounds(&start, end, &length);
212+
if (length == 0) {
213+
mp_raise_ValueError_varg(translate("%q length must be >= 1"), MP_QSTR_buffer);
214+
}
215+
216+
uint8_t status =
217+
common_hal_busio_i2c_read(self, args[ARG_address].u_int, ((uint8_t *)bufinfo.buf) + start, length);
218+
if (status != 0) {
219+
mp_raise_OSError(status);
220+
}
221+
227222
return mp_const_none;
228223
}
229224
MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 1, busio_i2c_readfrom_into);
@@ -247,23 +242,6 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 1, busio_i2c_readfrom_in
247242
//| """
248243
//| ...
249244
//|
250-
// Shared arg parsing for writeto and writeto_then_readfrom.
251-
STATIC void writeto(busio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end, bool stop) {
252-
// get the buffer to write the data from
253-
mp_buffer_info_t bufinfo;
254-
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ);
255-
256-
size_t length = bufinfo.len;
257-
normalize_buffer_bounds(&start, end, &length);
258-
259-
// do the transfer
260-
uint8_t status = common_hal_busio_i2c_write(self, address, ((uint8_t *)bufinfo.buf) + start,
261-
length, stop);
262-
if (status != 0) {
263-
mp_raise_OSError(status);
264-
}
265-
}
266-
267245
STATIC mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
268246
enum { ARG_address, ARG_buffer, ARG_start, ARG_end };
269247
static const mp_arg_t allowed_args[] = {
@@ -278,8 +256,23 @@ STATIC mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_ma
278256
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
279257
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
280258

281-
writeto(self, args[ARG_address].u_int, args[ARG_buffer].u_obj, args[ARG_start].u_int,
282-
args[ARG_end].u_int, true);
259+
// get the buffer to write the data from
260+
mp_buffer_info_t bufinfo;
261+
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
262+
263+
size_t length = bufinfo.len;
264+
int32_t start = args[ARG_start].u_int;
265+
const int32_t end = args[ARG_end].u_int;
266+
normalize_buffer_bounds(&start, end, &length);
267+
268+
// do the transfer
269+
uint8_t status =
270+
common_hal_busio_i2c_write(self, args[ARG_address].u_int, ((uint8_t *)bufinfo.buf) + start, length);
271+
272+
if (status != 0) {
273+
mp_raise_OSError(status);
274+
}
275+
283276
return mp_const_none;
284277
}
285278
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_obj, 1, busio_i2c_writeto);
@@ -314,21 +307,41 @@ STATIC mp_obj_t busio_i2c_writeto_then_readfrom(size_t n_args, const mp_obj_t *p
314307
{ MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
315308
{ MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
316309
{ MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
317-
{ MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
318-
{ MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
319-
{ MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
320-
{ MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
310+
{ MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
311+
{ MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
312+
{ MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
313+
{ MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
321314
};
322315
busio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
323316
check_for_deinit(self);
324317
check_lock(self);
325318
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
326319
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
327320

328-
writeto(self, args[ARG_address].u_int, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int,
329-
args[ARG_out_end].u_int, false);
330-
readfrom(self, args[ARG_address].u_int, args[ARG_in_buffer].u_obj, args[ARG_in_start].u_int,
331-
args[ARG_in_end].u_int);
321+
mp_buffer_info_t out_bufinfo;
322+
mp_get_buffer_raise(args[ARG_out_buffer].u_obj, &out_bufinfo, MP_BUFFER_READ);
323+
324+
size_t out_length = out_bufinfo.len;
325+
int32_t out_start = args[ARG_out_start].u_int;
326+
const int32_t out_end = args[ARG_out_end].u_int;
327+
normalize_buffer_bounds(&out_start, out_end, &out_length);
328+
329+
mp_buffer_info_t in_bufinfo;
330+
mp_get_buffer_raise(args[ARG_in_buffer].u_obj, &in_bufinfo, MP_BUFFER_WRITE);
331+
332+
size_t in_length = in_bufinfo.len;
333+
int32_t in_start = args[ARG_in_start].u_int;
334+
const int32_t in_end = args[ARG_in_end].u_int;
335+
normalize_buffer_bounds(&in_start, in_end, &in_length);
336+
if (in_length == 0) {
337+
mp_raise_ValueError_varg(translate("%q length must be >= 1"), MP_QSTR_out_buffer);
338+
}
339+
340+
uint8_t status = common_hal_busio_i2c_write_read(self, args[ARG_address].u_int,
341+
((uint8_t *)out_bufinfo.buf) + out_start, out_length,((uint8_t *)in_bufinfo.buf) + in_start, in_length);
342+
if (status != 0) {
343+
mp_raise_OSError(status);
344+
}
332345

333346
return mp_const_none;
334347
}

shared-bindings/busio/I2C.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,18 @@ extern void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self);
6060
extern bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr);
6161

6262
// Write to the device and return 0 on success or an appropriate error code from mperrno.h
63-
extern uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t address,
64-
const uint8_t *data, size_t len,
65-
bool stop);
63+
extern uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint8_t address,
64+
const uint8_t *data, size_t len);
6665

6766
// Reads memory of the i2c device picking up where it left off and return 0 on
6867
// success or an appropriate error code from mperrno.h
69-
extern uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t address,
68+
extern uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint8_t address,
7069
uint8_t *data, size_t len);
7170

71+
// Do a write and then a read in the same I2C transaction.
72+
uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint8_t address,
73+
uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len);
74+
7275
// This is used by the supervisor to claim I2C devices indefinitely.
7376
extern void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self);
7477

shared-module/displayio/I2CDisplay.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,12 @@ void common_hal_displayio_i2cdisplay_send(mp_obj_t obj, display_byte_type_t data
112112
command_bytes[2 * i] = 0x80;
113113
command_bytes[2 * i + 1] = data[i];
114114
}
115-
common_hal_busio_i2c_write(self->bus, self->address, command_bytes, 2 * data_length, true);
115+
common_hal_busio_i2c_write(self->bus, self->address, command_bytes, 2 * data_length);
116116
} else {
117117
uint8_t data_bytes[data_length + 1];
118118
data_bytes[0] = 0x40;
119119
memcpy(data_bytes + 1, data, data_length);
120-
common_hal_busio_i2c_write(self->bus, self->address, data_bytes, data_length + 1, true);
120+
common_hal_busio_i2c_write(self->bus, self->address, data_bytes, data_length + 1);
121121
}
122122
}
123123

0 commit comments

Comments
 (0)