Skip to content

Commit c2f5779

Browse files
committed
extmod/machine_i2c_target: Improve mem mode.
Signed-off-by: Damien George <[email protected]>
1 parent 199e16c commit c2f5779

File tree

1 file changed

+42
-20
lines changed

1 file changed

+42
-20
lines changed

extmod/machine_i2c_target.c

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,15 @@ mp_machine_i2c_target_event_stop(*)
5454

5555
enum {
5656
STATE_IDLE,
57-
STATE_MEM_ADDR_SELECTED,
57+
STATE_MEM_ADDR_SELECT,
5858
STATE_READING,
5959
STATE_WRITING,
6060
};
6161

6262
typedef struct _machine_i2c_target_data_t {
6363
uint8_t state;
64+
uint8_t mem_addr_count;
65+
uint8_t mem_addrsize;
6466
uint32_t mem_addr;
6567
uint32_t mem_len;
6668
uint8_t *mem_buf;
@@ -80,11 +82,11 @@ static void mp_machine_i2c_target_event_callback(machine_i2c_target_irq_obj_t *i
8082

8183
// read up to N bytes
8284
// return the number of bytes read
83-
static mp_int_t mp_machine_i2c_target_read_bytes(machine_i2c_target_obj_t *self, size_t len, uint8_t *buf);
85+
static size_t mp_machine_i2c_target_read_bytes(machine_i2c_target_obj_t *self, size_t len, uint8_t *buf);
8486

8587
// write/buffer N bytes
8688
// return the number of bytes written/buffered
87-
static mp_int_t mp_machine_i2c_target_write_bytes(machine_i2c_target_obj_t *self, size_t len, const uint8_t *buf);
89+
static size_t mp_machine_i2c_target_write_bytes(machine_i2c_target_obj_t *self, size_t len, const uint8_t *buf);
8890

8991
static void mp_machine_i2c_target_irq_config(machine_i2c_target_obj_t *self, unsigned int trigger);
9092

@@ -122,15 +124,19 @@ static bool event(machine_i2c_target_data_t *data, unsigned int trigger, size_t
122124

123125
static void machine_i2c_target_data_init(machine_i2c_target_data_t *data, mp_obj_t mem_obj, mp_int_t mem_addrsize) {
124126
data->state = STATE_IDLE;
127+
data->mem_addr_count = 0;
128+
data->mem_addrsize = 0;
125129
data->mem_addr = 0;
126130
data->mem_len = 0;
127131
data->mem_buf = NULL;
128132
if (mem_obj != mp_const_none) {
133+
// maybe allow MP_BUFFER_READ, in which case writes will be discarded?
129134
mp_buffer_info_t bufinfo;
130135
mp_get_buffer_raise(mem_obj, &bufinfo, MP_BUFFER_RW);
131-
if (mem_addrsize < 8 || mem_addrsize > 32 || mem_addrsize % 8 != 0) {
132-
mp_raise_ValueError(MP_ERROR_TEXT("mem_addrsize must be 8, 16, 24 or 32"));
136+
if (mem_addrsize < 0 || mem_addrsize > 32 || mem_addrsize % 8 != 0) {
137+
mp_raise_ValueError(MP_ERROR_TEXT("mem_addrsize must be 0, 8, 16, 24 or 32"));
133138
}
139+
data->mem_addrsize = mem_addrsize / 8;
134140
data->mem_len = bufinfo.len;
135141
data->mem_buf = bufinfo.buf;
136142
}
@@ -162,7 +168,12 @@ static void machine_i2c_target_data_read_request(machine_i2c_target_obj_t *self,
162168
}
163169
} else {
164170
// Have a buffer.
165-
if (data->state == STATE_MEM_ADDR_SELECTED) {
171+
if (data->state == STATE_MEM_ADDR_SELECT) {
172+
// Got a short memory address.
173+
data->mem_addr %= data->mem_len;
174+
event(data, I2C_TARGET_IRQ_MEM_ADDR_MATCH, data->mem_addr, 0);
175+
}
176+
if (data->state != STATE_READING) {
166177
data->state = STATE_READING;
167178
event(data, I2C_TARGET_IRQ_READ_START, data->mem_addr, 0);
168179
}
@@ -185,21 +196,32 @@ static void machine_i2c_target_data_write_request(machine_i2c_target_obj_t *self
185196
}
186197
} else {
187198
// Have a buffer.
188-
uint8_t val = 0;
189-
mp_machine_i2c_target_read_bytes(self, 1, &val);
190-
if (data->state == STATE_IDLE) {
191-
// TODO allow N bytes for address, with N=0 allowed
192-
data->state = STATE_MEM_ADDR_SELECTED;
193-
data->mem_addr = val % data->mem_len;
194-
event(data, I2C_TARGET_IRQ_MEM_ADDR_MATCH, data->mem_addr, 0);
195-
} else {
196-
if (data->state == STATE_MEM_ADDR_SELECTED) {
197-
data->state = STATE_WRITING;
198-
event(data, I2C_TARGET_IRQ_WRITE_START, data->mem_addr, 0);
199-
}
200-
data->mem_buf[data->mem_addr++] = val;
201-
if (data->mem_addr >= data->mem_len) {
199+
// TODO test read-write behaviour
200+
uint8_t buf[4] = {0};
201+
size_t n = mp_machine_i2c_target_read_bytes(self, sizeof(buf), &buf[0]);
202+
for (size_t i = 0; i < n; ++i) {
203+
uint8_t val = buf[i];
204+
if (data->state == STATE_IDLE) {
205+
data->state = STATE_MEM_ADDR_SELECT;
202206
data->mem_addr = 0;
207+
data->mem_addr_count = data->mem_addrsize;
208+
}
209+
if (data->state == STATE_MEM_ADDR_SELECT && data->mem_addr_count > 0) {
210+
data->mem_addr = data->mem_addr << 8 | val;
211+
--data->mem_addr_count;
212+
if (data->mem_addr_count == 0) {
213+
data->mem_addr %= data->mem_len;
214+
event(data, I2C_TARGET_IRQ_MEM_ADDR_MATCH, data->mem_addr, 0);
215+
}
216+
} else {
217+
if (data->state == STATE_MEM_ADDR_SELECT) {
218+
data->state = STATE_WRITING;
219+
event(data, I2C_TARGET_IRQ_WRITE_START, data->mem_addr, 0);
220+
}
221+
data->mem_buf[data->mem_addr++] = val;
222+
if (data->mem_addr >= data->mem_len) {
223+
data->mem_addr = 0;
224+
}
203225
}
204226
}
205227
}

0 commit comments

Comments
 (0)