Skip to content

Commit 07681d1

Browse files
committed
Changing to duck-typing
1 parent 9993814 commit 07681d1

File tree

4 files changed

+89
-65
lines changed

4 files changed

+89
-65
lines changed

shared-bindings/adafruit_bus_device/I2CDevice.c

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "shared-bindings/adafruit_bus_device/I2CDevice.h"
3232
#include "shared-bindings/util.h"
3333
#include "shared-module/adafruit_bus_device/I2CDevice.h"
34+
#include "shared-bindings/busio/I2C.h"
3435

3536
#include "lib/utils/buffer_helper.h"
3637
#include "lib/utils/context_manager_helpers.h"
@@ -76,7 +77,7 @@ STATIC mp_obj_t adafruit_bus_device_i2cdevice_make_new(const mp_obj_type_t *type
7677
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
7778
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
7879

79-
busio_i2c_obj_t* i2c = args[ARG_i2c].u_obj;
80+
mp_obj_t* i2c = args[ARG_i2c].u_obj;
8081

8182
common_hal_adafruit_bus_device_i2cdevice_construct(MP_OBJ_TO_PTR(self), i2c, args[ARG_device_address].u_int);
8283
if (args[ARG_probe].u_bool == true) {
@@ -107,7 +108,7 @@ STATIC mp_obj_t adafruit_bus_device_i2cdevice_obj___exit__(size_t n_args, const
107108
}
108109
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(adafruit_bus_device_i2cdevice___exit___obj, 4, 4, adafruit_bus_device_i2cdevice_obj___exit__);
109110

110-
//| def readinto(self, buf: WriteableBuffer, *, start: int = 0, end: int = 0) -> None:
111+
//| def readinto(self, buf: WriteableBuffer, *, start: int = 0, end: Optional[int] = None) -> None:
111112
//| """Read into ``buf`` from the device. The number of bytes read will be the
112113
//| length of ``buf``.
113114
//| If ``start`` or ``end`` is provided, then the buffer will be sliced
@@ -118,22 +119,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(adafruit_bus_device_i2cdevice___exit_
118119
//| :param int end: Index to write up to but not include; if None, use ``len(buf)``"""
119120
//| ...
120121
//|
121-
STATIC void readinto(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end) {
122-
mp_buffer_info_t bufinfo;
123-
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE);
124-
125-
size_t length = bufinfo.len;
126-
normalize_buffer_bounds(&start, end, &length);
127-
if (length == 0) {
128-
mp_raise_ValueError(translate("Buffer must be at least length 1"));
129-
}
130-
131-
uint8_t status = common_hal_adafruit_bus_device_i2cdevice_readinto(MP_OBJ_TO_PTR(self), ((uint8_t*)bufinfo.buf) + start, length);
132-
if (status != 0) {
133-
mp_raise_OSError(status);
134-
}
135-
}
136-
137122
STATIC mp_obj_t adafruit_bus_device_i2cdevice_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
138123
enum { ARG_buffer, ARG_start, ARG_end };
139124
static const mp_arg_t allowed_args[] = {
@@ -147,12 +132,21 @@ STATIC mp_obj_t adafruit_bus_device_i2cdevice_readinto(size_t n_args, const mp_o
147132
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
148133
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
149134

150-
readinto(self, args[ARG_buffer].u_obj, args[ARG_start].u_int, args[ARG_end].u_int);
135+
mp_obj_t dest[8];
136+
mp_load_method(self->i2c, MP_QSTR_readfrom_into, dest);
137+
dest[2] = mp_obj_new_int_from_ull(self->device_address);
138+
dest[3] = args[ARG_buffer].u_obj;
139+
dest[4] = mp_obj_new_str("start", 5);
140+
dest[5] = mp_obj_new_int(args[ARG_start].u_int);
141+
dest[6] = mp_obj_new_str("end", 3);
142+
dest[7] = mp_obj_new_int(args[ARG_end].u_int);
143+
mp_call_method_n_kw(2, 2, dest);
144+
151145
return mp_const_none;
152146
}
153147
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_readinto_obj, 2, adafruit_bus_device_i2cdevice_readinto);
154148

155-
//| def write(self, buf: ReadableBuffer, *, start: int = 0, end: int = 0) -> None:
149+
//| def write(self, buf: ReadableBuffer, *, start: int = 0, end: Optional[int] = None) -> None:
156150
//| """Write the bytes from ``buffer`` to the device, then transmit a stop bit.
157151
//| If ``start`` or ``end`` is provided, then the buffer will be sliced
158152
//| as if ``buffer[start:end]``. This will not cause an allocation like
@@ -163,22 +157,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_readinto_obj, 2,
163157
//| """
164158
//| ...
165159
//|
166-
STATIC void write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end, bool transmit_stop_bit) {
167-
mp_buffer_info_t bufinfo;
168-
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ);
169-
170-
size_t length = bufinfo.len;
171-
normalize_buffer_bounds(&start, end, &length);
172-
if (length == 0) {
173-
mp_raise_ValueError(translate("Buffer must be at least length 1"));
174-
}
175-
176-
uint8_t status = common_hal_adafruit_bus_device_i2cdevice_write(MP_OBJ_TO_PTR(self), ((uint8_t*)bufinfo.buf) + start, length, transmit_stop_bit);
177-
if (status != 0) {
178-
mp_raise_OSError(status);
179-
}
180-
}
181-
182160
STATIC mp_obj_t adafruit_bus_device_i2cdevice_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
183161
enum { ARG_buffer, ARG_start, ARG_end };
184162
static const mp_arg_t allowed_args[] = {
@@ -191,13 +169,22 @@ STATIC mp_obj_t adafruit_bus_device_i2cdevice_write(size_t n_args, const mp_obj_
191169
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
192170
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
193171

194-
write(self, args[ARG_buffer].u_obj, args[ARG_start].u_int, args[ARG_end].u_int, true);
172+
mp_obj_t dest[8];
173+
mp_load_method(self->i2c, MP_QSTR_writeto, dest);
174+
dest[2] = mp_obj_new_int_from_ull(self->device_address);
175+
dest[3] = args[ARG_buffer].u_obj;
176+
dest[4] = mp_obj_new_str("start", 5);
177+
dest[5] = mp_obj_new_int(args[ARG_start].u_int);
178+
dest[6] = mp_obj_new_str("end", 3);
179+
dest[7] = mp_obj_new_int(args[ARG_end].u_int);
180+
mp_call_method_n_kw(2, 2, dest);
181+
195182
return mp_const_none;
196183
}
197184
MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_write_obj, 2, adafruit_bus_device_i2cdevice_write);
198185

199186

200-
//| def write_then_readinto(self, out_buffer: WriteableBuffer, in_buffer: ReadableBuffer, *, out_start: int = 0, out_end: int = 0, in_start: int = 0, in_end: int = 0) -> None:
187+
//| def write_then_readinto(self, out_buffer: WriteableBuffer, in_buffer: ReadableBuffer, *, out_start: int = 0, out_end: Optional[int] = None, in_start: int = 0, in_end: Optional[int] = None) -> None:
201188
//| """Write the bytes from ``out_buffer`` to the device, then immediately
202189
//| reads into ``in_buffer`` from the device. The number of bytes read
203190
//| will be the length of ``in_buffer``.
@@ -233,9 +220,21 @@ STATIC mp_obj_t adafruit_bus_device_i2cdevice_write_then_readinto(size_t n_args,
233220
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
234221
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
235222

236-
write(self, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int, args[ARG_out_end].u_int, false);
237-
238-
readinto(self, args[ARG_in_buffer].u_obj, args[ARG_in_start].u_int, args[ARG_in_end].u_int);
223+
mp_obj_t dest[13];
224+
mp_load_method(self->i2c, MP_QSTR_writeto_then_readfrom, dest);
225+
dest[2] = mp_obj_new_int_from_ull(self->device_address);
226+
dest[3] = args[ARG_out_buffer].u_obj;
227+
dest[4] = args[ARG_in_buffer].u_obj;
228+
dest[5] = mp_obj_new_str("out_start", 9);
229+
dest[6] = mp_obj_new_int(args[ARG_out_start].u_int);
230+
dest[7] = mp_obj_new_str("out_end", 7);
231+
dest[8] = mp_obj_new_int(args[ARG_out_end].u_int);
232+
dest[9] = mp_obj_new_str("in_start", 8);
233+
dest[10] = mp_obj_new_int(args[ARG_in_start].u_int);
234+
dest[11] = mp_obj_new_str("in_end", 6);
235+
dest[12] = mp_obj_new_int(args[ARG_in_end].u_int);
236+
237+
mp_call_method_n_kw(3, 4, dest);
239238

240239
return mp_const_none;
241240
}

shared-bindings/adafruit_bus_device/I2CDevice.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@
4343
extern const mp_obj_type_t adafruit_bus_device_i2cdevice_type;
4444

4545
// Initializes the hardware peripheral.
46-
extern void common_hal_adafruit_bus_device_i2cdevice_construct(adafruit_bus_device_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address);
47-
extern uint8_t common_hal_adafruit_bus_device_i2cdevice_readinto(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length);
48-
extern uint8_t common_hal_adafruit_bus_device_i2cdevice_write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length, bool transmit_stop_bit);
46+
extern void common_hal_adafruit_bus_device_i2cdevice_construct(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t *i2c, uint8_t device_address);
4947
extern void common_hal_adafruit_bus_device_i2cdevice_lock(adafruit_bus_device_i2cdevice_obj_t *self);
5048
extern void common_hal_adafruit_bus_device_i2cdevice_unlock(adafruit_bus_device_i2cdevice_obj_t *self);
5149
extern void common_hal_adafruit_bus_device_i2cdevice_probe_for_device(adafruit_bus_device_i2cdevice_obj_t *self);

shared-module/adafruit_bus_device/I2CDevice.c

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,48 +31,75 @@
3131
#include "py/runtime.h"
3232
#include "lib/utils/interrupt_char.h"
3333

34-
void common_hal_adafruit_bus_device_i2cdevice_construct(adafruit_bus_device_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address) {
34+
void common_hal_adafruit_bus_device_i2cdevice_construct(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t *i2c, uint8_t device_address) {
3535
self->i2c = i2c;
3636
self->device_address = device_address;
3737
}
3838

3939
void common_hal_adafruit_bus_device_i2cdevice_lock(adafruit_bus_device_i2cdevice_obj_t *self) {
40-
bool success = common_hal_busio_i2c_try_lock(self->i2c);
40+
mp_obj_t dest[2];
41+
mp_load_method(self->i2c, MP_QSTR_try_lock, dest);
4142

42-
while (!success) {
43+
mp_obj_t success = mp_call_method_n_kw(0, 0, dest);
44+
45+
while (!mp_obj_is_true(success)) {
4346
RUN_BACKGROUND_TASKS;
4447
if (mp_hal_is_interrupted()) {
4548
break;
4649
}
4750

48-
success = common_hal_busio_i2c_try_lock(self->i2c);
51+
success = mp_call_method_n_kw(0, 0, dest);
4952
}
5053
}
5154

5255
void common_hal_adafruit_bus_device_i2cdevice_unlock(adafruit_bus_device_i2cdevice_obj_t *self) {
53-
common_hal_busio_i2c_unlock(self->i2c);
54-
}
55-
56-
uint8_t common_hal_adafruit_bus_device_i2cdevice_readinto(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) {
57-
return common_hal_busio_i2c_read(self->i2c, self->device_address, buffer, length);
58-
}
59-
60-
uint8_t common_hal_adafruit_bus_device_i2cdevice_write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length, bool transmit_stop_bit) {
61-
return common_hal_busio_i2c_write(self->i2c, self->device_address, buffer, length, transmit_stop_bit);
56+
mp_obj_t dest[2];
57+
mp_load_method(self->i2c, MP_QSTR_unlock, dest);
58+
mp_call_method_n_kw(0, 0, dest);
6259
}
6360

6461
void common_hal_adafruit_bus_device_i2cdevice_probe_for_device(adafruit_bus_device_i2cdevice_obj_t *self) {
6562
common_hal_adafruit_bus_device_i2cdevice_lock(self);
6663

67-
mp_buffer_info_t bufinfo;
68-
mp_obj_t buffer = mp_obj_new_bytearray_of_zeros(1);
64+
mp_buffer_info_t write_bufinfo;
65+
mp_obj_t write_buffer = mp_obj_new_bytearray_of_zeros(0);
66+
mp_get_buffer_raise(write_buffer, &write_bufinfo, MP_BUFFER_READ);
67+
68+
mp_obj_t dest[4];
6969

70-
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE);
70+
/* catch exceptions that may be thrown while probing for the device */
71+
nlr_buf_t write_nlr;
72+
if (nlr_push(&write_nlr) == 0) {
73+
mp_load_method(self->i2c, MP_QSTR_writeto, dest);
74+
dest[2] = mp_obj_new_int_from_ull(self->device_address);
75+
dest[3] = write_buffer;
76+
mp_call_method_n_kw(2, 0, dest);
77+
nlr_pop();
78+
} else {
79+
/* some OS's don't like writing an empty bytestring... retry by reading a byte */
80+
mp_buffer_info_t read_bufinfo;
81+
mp_obj_t read_buffer = mp_obj_new_bytearray_of_zeros(1);
82+
mp_get_buffer_raise(read_buffer, &read_bufinfo, MP_BUFFER_WRITE);
7183

72-
uint8_t status = common_hal_adafruit_bus_device_i2cdevice_readinto(self, (uint8_t*)bufinfo.buf, 1);
73-
if (status != 0) {
74-
common_hal_adafruit_bus_device_i2cdevice_unlock(self);
75-
mp_raise_ValueError_varg(translate("No I2C device at address: %x"), self->device_address);
84+
mp_load_method(self->i2c, MP_QSTR_readfrom_into, dest);
85+
dest[2] = mp_obj_new_int_from_ull(self->device_address);
86+
dest[3] = read_buffer;
87+
88+
nlr_buf_t read_nlr;
89+
if (nlr_push(&read_nlr) == 0) {
90+
mp_call_method_n_kw(2, 0, dest);
91+
nlr_pop();
92+
} else {
93+
/* At this point we tried two methods and only got exceptions */
94+
if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)read_nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_OSError))) {
95+
common_hal_adafruit_bus_device_i2cdevice_unlock(self);
96+
mp_raise_ValueError_varg(translate("No I2C device at address: %x"), self->device_address);
97+
}
98+
else {
99+
/* In case we receive an unrelated exception pass it up */
100+
nlr_raise(MP_OBJ_FROM_PTR(read_nlr.ret_val));
101+
}
102+
}
76103
}
77104

78105
common_hal_adafruit_bus_device_i2cdevice_unlock(self);

shared-module/adafruit_bus_device/I2CDevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
typedef struct {
3434
mp_obj_base_t base;
35-
busio_i2c_obj_t *i2c;
35+
mp_obj_t *i2c;
3636
uint8_t device_address;
3737
} adafruit_bus_device_i2cdevice_obj_t;
3838

0 commit comments

Comments
 (0)