3232#include "shared/runtime/mpirq.h"
3333
3434enum {
35- I2C_TARGET_IRQ_ADDR_MATCH = 1 << 0 ,
36- I2C_TARGET_IRQ_READ_REQ = 1 << 1 ,
37- I2C_TARGET_IRQ_WRITE_REQ = 1 << 2 ,
38- I2C_TARGET_IRQ_END = 1 << 3 ,
39- I2C_TARGET_IRQ_STOP = 1 << 4 , // should be able to support this on all targets (rp2 needs custom code though), but maybe can't support addr_match?
40-
41- I2C_TARGET_IRQ_MEM_ADDR_MATCH = 1 << 5 , // needed?
42- I2C_TARGET_IRQ_READ_START = 1 << 6 , // needed?
43- I2C_TARGET_IRQ_WRITE_START = 1 << 7 , // needed?
44- I2C_TARGET_IRQ_READ_END = 1 << 8 , // needed?
45- I2C_TARGET_IRQ_WRITE_END = 1 << 9 , // needed?
35+ // Events exposed to Python.
36+ I2C_TARGET_IRQ_ADDR_MATCH_READ = 1 << 0 ,
37+ I2C_TARGET_IRQ_ADDR_MATCH_WRITE = 1 << 1 ,
38+ I2C_TARGET_IRQ_READ_REQ = 1 << 2 ,
39+ I2C_TARGET_IRQ_WRITE_REQ = 1 << 3 ,
40+ I2C_TARGET_IRQ_END_READ = 1 << 4 ,
41+ I2C_TARGET_IRQ_END_WRITE = 1 << 5 ,
42+
43+ // Internal events, not exposed to Python.
44+ I2C_TARGET_IRQ_STOP = 1 << 6 ,
45+ I2C_TARGET_IRQ_MEM_ADDR_MATCH = 1 << 7 ,
46+ I2C_TARGET_IRQ_READ_START = 1 << 8 ,
47+ I2C_TARGET_IRQ_WRITE_START = 1 << 9 ,
4648};
4749
48- /*
49- mp_machine_i2c_target_event_addr_match(*, read_write)
50- mp_machine_i2c_target_event_read_req(*)
51- mp_machine_i2c_target_event_write_req(*)
52- mp_machine_i2c_target_event_stop(*)
53- */
50+ // Define the IRQs that require a hard interrupt.
51+ #define I2C_TARGET_IRQ_ALL_HARD ( \
52+ I2C_TARGET_IRQ_ADDR_MATCH_READ \
53+ | I2C_TARGET_IRQ_ADDR_MATCH_WRITE \
54+ | I2C_TARGET_IRQ_READ_REQ \
55+ | I2C_TARGET_IRQ_WRITE_REQ \
56+ )
5457
5558enum {
5659 STATE_IDLE ,
60+ STATE_ADDR_MATCH_READ ,
61+ STATE_ADDR_MATCH_WRITE ,
5762 STATE_MEM_ADDR_SELECT ,
5863 STATE_READING ,
5964 STATE_WRITING ,
@@ -63,6 +68,7 @@ typedef struct _machine_i2c_target_data_t {
6368 uint8_t state ;
6469 uint8_t mem_addr_count ;
6570 uint8_t mem_addrsize ;
71+ uint32_t mem_addr_last ;
6672 uint32_t mem_addr ;
6773 uint32_t mem_len ;
6874 uint8_t * mem_buf ;
@@ -96,23 +102,26 @@ static void mp_machine_i2c_target_deinit(machine_i2c_target_obj_t *self);
96102
97103static const mp_irq_methods_t machine_i2c_target_irq_methods ;
98104
99- #define I2C_TARGET_NUM_IRQ (4)
105+ static machine_i2c_target_data_t machine_i2c_target_data [ MICROPY_PY_MACHINE_I2C_TARGET_MAX ];
100106
101107// Needed to retain a root pointer to the memory object.
102- MP_REGISTER_ROOT_POINTER (mp_obj_t i2c_target_mem_obj [ I2C_TARGET_NUM_IRQ ]);
108+ MP_REGISTER_ROOT_POINTER (mp_obj_t machine_i2c_target_mem_obj [ MICROPY_PY_MACHINE_I2C_TARGET_MAX ]);
103109
104- MP_REGISTER_ROOT_POINTER (void * machine_i2c_target_irq_obj [I2C_TARGET_NUM_IRQ ]);
110+ MP_REGISTER_ROOT_POINTER (void * machine_i2c_target_irq_obj [MICROPY_PY_MACHINE_I2C_TARGET_MAX ]);
105111
106112void mp_machine_i2c_target_deinit_all (void ) {
107- for (size_t i = 0 ; i < I2C_TARGET_NUM_IRQ ; ++ i ) {
108- MP_STATE_PORT (i2c_target_mem_obj [i ]) = MP_OBJ_NULL ;
113+ for (size_t i = 0 ; i < MICROPY_PY_MACHINE_I2C_TARGET_MAX ; ++ i ) {
114+ MP_STATE_PORT (machine_i2c_target_mem_obj [i ]) = MP_OBJ_NULL ;
109115 MP_STATE_PORT (machine_i2c_target_irq_obj [i ]) = NULL ;
110116 }
111117 mp_machine_i2c_target_deinit_all_port ();
112118}
113119
114- static bool event (machine_i2c_target_data_t * data , unsigned int trigger , size_t arg0 , size_t arg1 ) {
115- unsigned int id = 0 ; // TODO
120+ static bool handle_event (machine_i2c_target_data_t * data , unsigned int trigger ) {
121+ unsigned int id = data - & machine_i2c_target_data [0 ];
122+ if (trigger & I2C_TARGET_IRQ_MEM_ADDR_MATCH ) {
123+ data -> mem_addr_last = data -> mem_addr ;
124+ }
116125 machine_i2c_target_irq_obj_t * irq = MP_STATE_PORT (machine_i2c_target_irq_obj [id ]);
117126 if (irq != NULL && (trigger & irq -> trigger )) {
118127 irq -> flags = trigger & irq -> trigger ;
@@ -126,6 +135,7 @@ static void machine_i2c_target_data_init(machine_i2c_target_data_t *data, mp_obj
126135 data -> state = STATE_IDLE ;
127136 data -> mem_addr_count = 0 ;
128137 data -> mem_addrsize = 0 ;
138+ data -> mem_addr_last = 0 ;
129139 data -> mem_addr = 0 ;
130140 data -> mem_len = 0 ;
131141 data -> mem_buf = NULL ;
@@ -143,24 +153,30 @@ static void machine_i2c_target_data_init(machine_i2c_target_data_t *data, mp_obj
143153}
144154
145155static void machine_i2c_target_data_reset_helper (machine_i2c_target_data_t * data ) {
146- size_t len = 0 ; // TODO
147156 if (data -> state == STATE_READING ) {
148- event (data , I2C_TARGET_IRQ_READ_END , data -> mem_addr , len );
149- } else if (data -> state == STATE_WRITING ) {
150- event (data , I2C_TARGET_IRQ_WRITE_END , data -> mem_addr , len );
157+ handle_event (data , I2C_TARGET_IRQ_END_READ );
158+ } else if (data -> state == STATE_ADDR_MATCH_WRITE || data -> state == STATE_WRITING ) {
159+ handle_event (data , I2C_TARGET_IRQ_END_WRITE );
151160 }
152161 data -> state = STATE_IDLE ;
153162}
154163
155164static void machine_i2c_target_data_addr_match (machine_i2c_target_data_t * data , bool read ) {
156- event (data , I2C_TARGET_IRQ_ADDR_MATCH , read , 0 );
157165 machine_i2c_target_data_reset_helper (data );
166+ if (read ) {
167+ handle_event (data , I2C_TARGET_IRQ_ADDR_MATCH_READ );
168+ data -> state = STATE_ADDR_MATCH_READ ;
169+ } else {
170+ handle_event (data , I2C_TARGET_IRQ_ADDR_MATCH_WRITE );
171+ data -> state = STATE_ADDR_MATCH_WRITE ;
172+ }
158173}
159174
160175static void machine_i2c_target_data_read_request (machine_i2c_target_obj_t * self , machine_i2c_target_data_t * data ) {
161176 // Let the user handle the read request.
162- bool event_handled = event (data , I2C_TARGET_IRQ_READ_REQ , 0 , 0 );
177+ bool event_handled = handle_event (data , I2C_TARGET_IRQ_READ_REQ );
163178 if (data -> mem_buf == NULL ) {
179+ data -> state = STATE_READING ;
164180 if (!event_handled ) {
165181 // No data source, just write out a zero.
166182 uint8_t val = 0 ;
@@ -171,11 +187,11 @@ static void machine_i2c_target_data_read_request(machine_i2c_target_obj_t *self,
171187 if (data -> state == STATE_MEM_ADDR_SELECT ) {
172188 // Got a short memory address.
173189 data -> mem_addr %= data -> mem_len ;
174- event (data , I2C_TARGET_IRQ_MEM_ADDR_MATCH , data -> mem_addr , 0 );
190+ handle_event (data , I2C_TARGET_IRQ_MEM_ADDR_MATCH );
175191 }
176192 if (data -> state != STATE_READING ) {
177193 data -> state = STATE_READING ;
178- event (data , I2C_TARGET_IRQ_READ_START , data -> mem_addr , 0 );
194+ handle_event (data , I2C_TARGET_IRQ_READ_START );
179195 }
180196 uint8_t val = data -> mem_buf [data -> mem_addr ++ ];
181197 if (data -> mem_addr >= data -> mem_len ) {
@@ -187,21 +203,21 @@ static void machine_i2c_target_data_read_request(machine_i2c_target_obj_t *self,
187203
188204static void machine_i2c_target_data_write_request (machine_i2c_target_obj_t * self , machine_i2c_target_data_t * data ) {
189205 // Let the user handle the write request.
190- bool event_handled = event (data , I2C_TARGET_IRQ_WRITE_REQ , 0 , 0 );
206+ bool event_handled = handle_event (data , I2C_TARGET_IRQ_WRITE_REQ );
191207 if (data -> mem_buf == NULL ) {
208+ data -> state = STATE_WRITING ;
192209 if (!event_handled ) {
193210 // No data sink, just read and discard the incoming byte.
194211 uint8_t buf = 0 ;
195212 mp_machine_i2c_target_read_bytes (self , 1 , & buf );
196213 }
197214 } else {
198215 // Have a buffer.
199- // TODO test read-write behaviour
200216 uint8_t buf [4 ] = {0 };
201217 size_t n = mp_machine_i2c_target_read_bytes (self , sizeof (buf ), & buf [0 ]);
202218 for (size_t i = 0 ; i < n ; ++ i ) {
203219 uint8_t val = buf [i ];
204- if (data -> state == STATE_IDLE ) {
220+ if (data -> state == STATE_ADDR_MATCH_WRITE ) {
205221 data -> state = STATE_MEM_ADDR_SELECT ;
206222 data -> mem_addr = 0 ;
207223 data -> mem_addr_count = data -> mem_addrsize ;
@@ -211,12 +227,12 @@ static void machine_i2c_target_data_write_request(machine_i2c_target_obj_t *self
211227 -- data -> mem_addr_count ;
212228 if (data -> mem_addr_count == 0 ) {
213229 data -> mem_addr %= data -> mem_len ;
214- event (data , I2C_TARGET_IRQ_MEM_ADDR_MATCH , data -> mem_addr , 0 );
230+ handle_event (data , I2C_TARGET_IRQ_MEM_ADDR_MATCH );
215231 }
216232 } else {
217233 if (data -> state == STATE_MEM_ADDR_SELECT ) {
218234 data -> state = STATE_WRITING ;
219- event (data , I2C_TARGET_IRQ_WRITE_START , data -> mem_addr , 0 );
235+ handle_event (data , I2C_TARGET_IRQ_WRITE_START );
220236 }
221237 data -> mem_buf [data -> mem_addr ++ ] = val ;
222238 if (data -> mem_addr >= data -> mem_len ) {
@@ -229,12 +245,11 @@ static void machine_i2c_target_data_write_request(machine_i2c_target_obj_t *self
229245
230246static inline void machine_i2c_target_data_restart_or_stop (machine_i2c_target_data_t * data ) {
231247 machine_i2c_target_data_reset_helper (data );
232- event (data , I2C_TARGET_IRQ_END , 0 , 0 );
233248}
234249
235250static inline void machine_i2c_target_data_stop (machine_i2c_target_data_t * data ) {
236251 machine_i2c_target_data_reset_helper (data );
237- event (data , I2C_TARGET_IRQ_END | I2C_TARGET_IRQ_STOP , 0 , 0 );
252+ handle_event (data , I2C_TARGET_IRQ_STOP );
238253}
239254
240255// The port provides implementations of its bindings in this file.
@@ -266,9 +281,19 @@ static mp_obj_t machine_i2c_target_write(mp_obj_t self_in, mp_obj_t data_in) {
266281}
267282static MP_DEFINE_CONST_FUN_OBJ_2 (machine_i2c_target_write_obj , machine_i2c_target_write ) ;
268283
284+ // I2CTarget.memaddr()
285+ static mp_obj_t machine_i2c_target_memaddr (mp_obj_t self_in ) {
286+ machine_i2c_target_obj_t * self = MP_OBJ_TO_PTR (self_in );
287+ size_t index = mp_machine_i2c_target_get_index (self );
288+ machine_i2c_target_data_t * data = & machine_i2c_target_data [index ];
289+ return mp_obj_new_int (data -> mem_addr_last );
290+ }
291+ static MP_DEFINE_CONST_FUN_OBJ_1 (machine_i2c_target_memaddr_obj , machine_i2c_target_memaddr ) ;
292+
269293static machine_i2c_target_irq_obj_t * machine_i2c_target_get_irq (machine_i2c_target_obj_t * self ) {
270294 // Get the IRQ object.
271- machine_i2c_target_irq_obj_t * irq = MP_STATE_PORT (machine_i2c_target_irq_obj [0 ]);
295+ size_t index = mp_machine_i2c_target_get_index (self );
296+ machine_i2c_target_irq_obj_t * irq = MP_STATE_PORT (machine_i2c_target_irq_obj [index ]);
272297
273298 // Allocate the IRQ object if it doesn't already exist.
274299 if (irq == NULL ) {
@@ -278,17 +303,17 @@ static machine_i2c_target_irq_obj_t *machine_i2c_target_get_irq(machine_i2c_targ
278303 irq -> base .parent = MP_OBJ_FROM_PTR (self );
279304 irq -> base .handler = mp_const_none ;
280305 irq -> base .ishard = false;
281- MP_STATE_PORT (machine_i2c_target_irq_obj [0 ]) = irq ;
306+ MP_STATE_PORT (machine_i2c_target_irq_obj [index ]) = irq ;
282307 }
283308 return irq ;
284309}
285310
286- // I2CTarget.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING , hard=False)
311+ // I2CTarget.irq(handler=None, trigger=IRQ_END_READ|IRQ_END_WRITE , hard=False)
287312static mp_obj_t machine_i2c_target_irq (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
288313 enum { ARG_handler , ARG_trigger , ARG_hard };
289314 static const mp_arg_t allowed_args [] = {
290315 { MP_QSTR_handler , MP_ARG_OBJ , {.u_rom_obj = MP_ROM_NONE } },
291- { MP_QSTR_trigger , MP_ARG_INT , {.u_int = 0 } },
316+ { MP_QSTR_trigger , MP_ARG_INT , {.u_int = I2C_TARGET_IRQ_END_READ | I2C_TARGET_IRQ_END_WRITE } },
292317 { MP_QSTR_hard , MP_ARG_BOOL , {.u_bool = false} },
293318 };
294319 machine_i2c_target_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
@@ -304,9 +329,15 @@ static mp_obj_t machine_i2c_target_irq(size_t n_args, const mp_obj_t *pos_args,
304329 mp_uint_t trigger = args [ARG_trigger ].u_int ;
305330 bool hard = args [ARG_hard ].u_bool ;
306331
307- if (!hard ) {
332+ #if MICROPY_PY_MACHINE_I2C_TARGET_HARD_IRQ
333+ if ((trigger & I2C_TARGET_IRQ_ALL_HARD ) && !hard ) {
308334 mp_raise_ValueError (MP_ERROR_TEXT ("hard IRQ required" ));
309335 }
336+ #else
337+ if (hard ) {
338+ mp_raise_ValueError (MP_ERROR_TEXT ("hard IRQ unsupported" ));
339+ }
340+ #endif
310341
311342 // Disable all IRQs while data is updated.
312343 mp_machine_i2c_target_irq_config (self , 0 );
@@ -330,13 +361,17 @@ static const mp_rom_map_elem_t machine_i2c_target_locals_dict_table[] = {
330361 { MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& machine_i2c_target_deinit_obj ) },
331362 { MP_ROM_QSTR (MP_QSTR_readinto ), MP_ROM_PTR (& machine_i2c_target_readinto_obj ) },
332363 { MP_ROM_QSTR (MP_QSTR_write ), MP_ROM_PTR (& machine_i2c_target_write_obj ) },
364+ { MP_ROM_QSTR (MP_QSTR_memaddr ), MP_ROM_PTR (& machine_i2c_target_memaddr_obj ) },
333365 { MP_ROM_QSTR (MP_QSTR_irq ), MP_ROM_PTR (& machine_i2c_target_irq_obj ) },
334366
335- { MP_ROM_QSTR (MP_QSTR_IRQ_ADDR_MATCH ), MP_ROM_INT (I2C_TARGET_IRQ_ADDR_MATCH ) },
367+ #if MICROPY_PY_MACHINE_I2C_TARGET_HARD_IRQ
368+ { MP_ROM_QSTR (MP_QSTR_IRQ_ADDR_MATCH_READ ), MP_ROM_INT (I2C_TARGET_IRQ_ADDR_MATCH_READ ) },
369+ { MP_ROM_QSTR (MP_QSTR_IRQ_ADDR_MATCH_WRITE ), MP_ROM_INT (I2C_TARGET_IRQ_ADDR_MATCH_WRITE ) },
336370 { MP_ROM_QSTR (MP_QSTR_IRQ_READ_REQ ), MP_ROM_INT (I2C_TARGET_IRQ_READ_REQ ) },
337371 { MP_ROM_QSTR (MP_QSTR_IRQ_WRITE_REQ ), MP_ROM_INT (I2C_TARGET_IRQ_WRITE_REQ ) },
338- { MP_ROM_QSTR (MP_QSTR_IRQ_END ), MP_ROM_INT (I2C_TARGET_IRQ_END ) },
339- { MP_ROM_QSTR (MP_QSTR_IRQ_STOP ), MP_ROM_INT (I2C_TARGET_IRQ_STOP ) },
372+ #endif
373+ { MP_ROM_QSTR (MP_QSTR_IRQ_END_READ ), MP_ROM_INT (I2C_TARGET_IRQ_END_READ ) },
374+ { MP_ROM_QSTR (MP_QSTR_IRQ_END_WRITE ), MP_ROM_INT (I2C_TARGET_IRQ_END_WRITE ) },
340375};
341376static MP_DEFINE_CONST_DICT (machine_i2c_target_locals_dict , machine_i2c_target_locals_dict_table ) ;
342377
@@ -351,7 +386,8 @@ MP_DEFINE_CONST_OBJ_TYPE(
351386
352387static mp_uint_t machine_i2c_target_irq_trigger (mp_obj_t self_in , mp_uint_t new_trigger ) {
353388 machine_i2c_target_obj_t * self = MP_OBJ_TO_PTR (self_in );
354- machine_i2c_target_irq_obj_t * irq = MP_STATE_PORT (machine_i2c_target_irq_obj [0 ]);
389+ size_t index = mp_machine_i2c_target_get_index (self );
390+ machine_i2c_target_irq_obj_t * irq = MP_STATE_PORT (machine_i2c_target_irq_obj [index ]);
355391 mp_machine_i2c_target_irq_config (self , 0 );
356392 irq -> flags = 0 ;
357393 irq -> trigger = new_trigger ;
@@ -360,8 +396,9 @@ static mp_uint_t machine_i2c_target_irq_trigger(mp_obj_t self_in, mp_uint_t new_
360396}
361397
362398static mp_uint_t machine_i2c_target_irq_info (mp_obj_t self_in , mp_uint_t info_type ) {
363- // machine_i2c_target_obj_t *self = MP_OBJ_TO_PTR(self_in);
364- machine_i2c_target_irq_obj_t * irq = MP_STATE_PORT (machine_i2c_target_irq_obj [0 ]);
399+ machine_i2c_target_obj_t * self = MP_OBJ_TO_PTR (self_in );
400+ size_t index = mp_machine_i2c_target_get_index (self );
401+ machine_i2c_target_irq_obj_t * irq = MP_STATE_PORT (machine_i2c_target_irq_obj [index ]);
365402 if (info_type == MP_IRQ_INFO_FLAGS ) {
366403 return irq -> flags ;
367404 } else if (info_type == MP_IRQ_INFO_TRIGGERS ) {
0 commit comments