@@ -54,13 +54,15 @@ mp_machine_i2c_target_event_stop(*)
5454
5555enum {
5656 STATE_IDLE ,
57- STATE_MEM_ADDR_SELECTED ,
57+ STATE_MEM_ADDR_SELECT ,
5858 STATE_READING ,
5959 STATE_WRITING ,
6060};
6161
6262typedef 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
8991static 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
123125static 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