3030#include "shared-bindings/microcontroller/__init__.h"
3131#include "shared-bindings/microcontroller/Pin.h"
3232
33- static bool in_used = false;
33+ #include "max32_port.h"
34+
35+ #define I2C_PRIORITY 1
36+
37+ typedef enum {
38+ I2C_FREE = 0 ,
39+ I2C_BUSY ,
40+ I2C_NEVER_RESET ,
41+ } i2c_status_t ;
42+
43+ // Set each bit to indicate an active UART
44+ // will be checked by ISR Handler for which ones to call
45+ static uint8_t i2c_active = 0 ;
46+ static i2c_status_t i2c_status [NUM_I2C ];
47+ static volatile int i2c_err ;
48+
49+ // I2C Interrupt Handler
50+ void i2c_isr (void ) {
51+ for (int i = 0 ; i < NUM_I2C ; i ++ ) {
52+ if (i2c_active & (1 << i )) {
53+ // NOTE: I2C_GET_TMR actually returns the I2C registers
54+ MXC_I2C_AsyncHandler (MXC_I2C_GET_I2C (i ));
55+ }
56+ }
57+ }
58+
59+ // Callback gets called when AsyncRequest is COMPLETE
60+ // (e.g. txLen == txCnt)
61+ // static volatile void i2cCallback(mxc_i2c_req_t *req, int error) {
62+ // i2c_status[MXC_I2C_GET_IDX(req->i2c)] = I2C_FREE;
63+ // i2c_err = error;
64+ // }
3465
3566// Construct I2C protocol, this function init i2c peripheral
3667void common_hal_busio_i2c_construct (busio_i2c_obj_t * self ,
3768 const mcu_pin_obj_t * scl ,
3869 const mcu_pin_obj_t * sda ,
3970 uint32_t frequency , uint32_t timeout ) {
4071
41-
72+ int temp , err = 0 ;
73+
74+ // Check for NULL Pointers && valid I2C settings
75+ assert (self );
76+
77+ // Assign I2C ID based on pins
78+ temp = pinsToI2c (sda , scl );
79+ if (temp == -1 ) {
80+ // Error will be indicated by pinsToUart(tx, rx) function
81+ return ;
82+ } else {
83+ self -> i2c_id = temp ;
84+ self -> i2c_regs = MXC_I2C_GET_I2C (temp );
85+ }
86+
87+ assert ((self -> i2c_id >= 0 ) && (self -> i2c_id < NUM_I2C ));
88+
89+ // Init I2C as main / controller node (0x00 is ignored)
90+ if ((scl != NULL ) && (sda != NULL )) {
91+ err = MXC_I2C_Init (self -> i2c_regs , 1 , 0x00 );
92+ if (err ) {
93+ mp_raise_RuntimeError (MP_ERROR_TEXT ("Failed to init I2C.\n" ));
94+ }
95+ err = MXC_I2C_SetFrequency (self -> i2c_regs , frequency );
96+ if (err < 0 ) {
97+ mp_raise_RuntimeError (MP_ERROR_TEXT ("Failed to set I2C frequency\n" ));
98+ }
99+ } else if (scl != NULL ) {
100+ mp_raise_NotImplementedError (MP_ERROR_TEXT ("I2C needs SDA & SCL" ));
101+ } else if (sda != NULL ) {
102+ mp_raise_NotImplementedError (MP_ERROR_TEXT ("I2C needs SDA & SCL" ));
103+ } else {
104+ // Should not get here, as shared-bindings API should not call this way
105+ }
106+
107+ // Attach I2C pins
108+ self -> sda = sda ;
109+ self -> scl = scl ;
110+ common_hal_mcu_pin_claim (self -> sda );
111+ common_hal_mcu_pin_claim (self -> scl );
112+
113+ // Indicate to this module that the I2C is active
114+ i2c_active |= (1 << self -> i2c_id );
115+
116+ // Set the timeout to a default value
117+ if (((timeout < 0.0 ) || (timeout > 100.0 ))) {
118+ self -> timeout = 1.0 ;
119+ } else {
120+ self -> timeout = timeout ;
121+ }
122+
123+ /* Setup I2C interrupt */
124+ NVIC_ClearPendingIRQ (MXC_I2C_GET_IRQ (self -> i2c_id ));
125+ NVIC_DisableIRQ (MXC_I2C_GET_IRQ (self -> i2c_id ));
126+ NVIC_SetPriority (MXC_I2C_GET_IRQ (self -> i2c_id ), I2C_PRIORITY );
127+ NVIC_SetVector (MXC_I2C_GET_IRQ (self -> i2c_id ), (uint32_t )i2c_isr );
128+
129+ return ;
42130}
43131
44132// Never reset I2C obj when reload
@@ -54,7 +142,13 @@ bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
54142
55143// Deinit i2c obj, reset I2C pin
56144void common_hal_busio_i2c_deinit (busio_i2c_obj_t * self ) {
57- // FIXME: Implement
145+ MXC_I2C_Shutdown (self -> i2c_regs );
146+
147+ common_hal_reset_pin (self -> sda );
148+ common_hal_reset_pin (self -> scl );
149+
150+ self -> sda = NULL ;
151+ self -> scl = NULL ;
58152}
59153
60154void common_hal_busio_i2c_mark_deinit (busio_i2c_obj_t * self ) {
@@ -63,17 +157,36 @@ void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) {
63157
64158// Probe device in I2C bus
65159bool common_hal_busio_i2c_probe (busio_i2c_obj_t * self , uint8_t addr ) {
66- // FIXME: Implement
67-
68- return true;
160+ int nack = 0 ;
161+
162+ mxc_i2c_req_t addr_req = {
163+ .addr = addr ,
164+ .i2c = self -> i2c_regs ,
165+ .tx_len = 0 ,
166+ .tx_buf = NULL ,
167+ .rx_len = 0 ,
168+ .rx_buf = NULL ,
169+ .callback = NULL
170+ };
171+
172+ // Probe the address
173+ nack = MXC_I2C_MasterTransaction (& addr_req );
174+ if (nack ) {
175+ return false;
176+ } else {
177+ return true;
178+ }
69179}
70180
71181// Lock I2C bus
72182bool common_hal_busio_i2c_try_lock (busio_i2c_obj_t * self ) {
73183
74- // FIXME: Implement
75-
76- return false;
184+ if (self -> i2c_regs -> status & MXC_F_I2C_STATUS_BUSY ) {
185+ return false;
186+ } else {
187+ self -> has_lock = true;
188+ return true;
189+ }
77190}
78191
79192// Check I2C lock status
0 commit comments