@@ -132,21 +132,31 @@ static uint8_t gpio_extender_address = 0x00;
132132
133133#if RG_I2C_GPIO_DRIVER == 1 // AW9523
134134
135- #define AW9523_REG_CHIPID 0x10 ///< Register for hardcode chip ID
136- #define AW9523_REG_SOFTRESET 0x7F ///< Register for soft resetting
137- #define AW9523_REG_INPUT0 0x00 ///< Register for reading input values
138- #define AW9523_REG_OUTPUT0 0x02 ///< Register for writing output values
139- #define AW9523_REG_CONFIG0 0x04 ///< Register for configuring direction
140- #define AW9523_REG_INTENABLE0 0x06 ///< Register for enabling interrupt
141- #define AW9523_REG_GCR 0x11 ///< Register for general configuration
142- #define AW9523_REG_LEDMODE 0x12 ///< Register for configuring const current
135+ static const uint8_t gpio_input_regs [ 2 ] = { 0x00 , 0x01 };
136+ static const uint8_t gpio_output_regs [ 2 ] = { 0x02 , 0x03 };
137+ static const uint8_t gpio_direction_regs [ 2 ] = { 0x04 , 0x05 };
138+ static const uint8_t gpio_init_sequence [][ 2 ] = {
139+ { 0x7F , 0x00 }, // Software reset (is it really necessary?)
140+ { 0x11 , 1 << 4 }, // Push-Pull mode
141+ };
142+ static const uint8_t gpio_deinit_sequence [][ 2 ] = {};
143143
144144#elif RG_I2C_GPIO_DRIVER == 2 // PCF9539
145145
146- #define AW9523_REG_INPUT0 0x00 ///< Register for reading input values
147- #define AW9523_REG_OUTPUT0 0x02 ///< Register for writing output values
148- #define AW9523_REG_POLARITY0 0x04 ///< Register for polarity inversion of inputs
149- #define AW9523_REG_CONFIG0 0x06 ///< Register for configuring direction
146+ static const uint8_t gpio_input_regs [2 ] = {0x00 , 0x01 };
147+ static const uint8_t gpio_output_regs [2 ] = {0x02 , 0x03 };
148+ static const uint8_t gpio_direction_regs [2 ] = {0x06 , 0x07 };
149+ static const uint8_t gpio_init_sequence [][2 ] = {};
150+ static const uint8_t gpio_deinit_sequence [][2 ] = {};
151+
152+ #elif RG_I2C_GPIO_DRIVER == 3 // MCP23017
153+
154+ // Mappings when IOCON.BANK = 0 (which should be default on power-on)
155+ static const uint8_t gpio_input_regs [2 ] = {0x12 , 0x13 };
156+ static const uint8_t gpio_output_regs [2 ] = {0x14 , 0x15 };
157+ static const uint8_t gpio_direction_regs [2 ] = {0x00 , 0x01 };
158+ static const uint8_t gpio_init_sequence [][2 ] = {};
159+ static const uint8_t gpio_deinit_sequence [][2 ] = {};
150160
151161#endif
152162
@@ -159,69 +169,49 @@ bool rg_i2c_gpio_init(void)
159169 if (!i2c_initialized && !rg_i2c_init ())
160170 return false;
161171
162- #if RG_I2C_GPIO_DRIVER == 1 // AW9523
163-
164172 gpio_extender_address = RG_I2C_GPIO_ADDR ;
165- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_SOFTRESET , 0 );
166- rg_usleep (10 * 1000 );
167- uint8_t id = rg_i2c_read_byte (gpio_extender_address , AW9523_REG_CHIPID );
168- if (id != 0x23 )
169- {
170- RG_LOGE ("AW9523 invalid ID 0x%x found" , id );
171- return false;
172- }
173- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_CONFIG0 , 0xFF );
174- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_CONFIG0 + 1 , 0xFF );
175- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_LEDMODE , 0xFF );
176- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_LEDMODE + 1 , 0xFF );
177- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_GCR , 1 << 4 );
178-
179173 gpio_extender_initialized = true;
180- return true;
181174
182- #elif RG_I2C_GPIO_DRIVER == 2 // PCF9539
175+ // Configure extender-specific registers if needed (disable open-drain, interrupts, inversion, etc)
176+ for (size_t i = 0 ; i < RG_COUNT (gpio_init_sequence ); ++ i )
177+ rg_i2c_write_byte (gpio_extender_address , gpio_init_sequence [i ][0 ], gpio_init_sequence [i ][1 ]);
183178
184- gpio_extender_address = RG_I2C_GPIO_ADDR ;
185- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_OUTPUT0 , 0xFF );
186- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_OUTPUT0 + 1 , 0xFF );
187- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_POLARITY0 , 0x00 );
188- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_POLARITY0 + 1 , 0x00 );
189- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_CONFIG0 , 0xFF );
190- rg_i2c_write_byte (gpio_extender_address , AW9523_REG_CONFIG0 + 1 , 0xFF );
179+ // Now set all pins of all ports as inputs and clear output latches
180+ for (size_t i = 0 ; i < RG_COUNT (gpio_direction_regs ); ++ i )
181+ rg_i2c_write_byte (gpio_extender_address , gpio_direction_regs [i ], 0xFF );
182+ for (size_t i = 0 ; i < RG_COUNT (gpio_output_regs ); ++ i )
183+ rg_i2c_write_byte (gpio_extender_address , gpio_output_regs [i ], 0x00 );
191184
192- gpio_extender_initialized = true;
193185 return true;
194-
195- #else
196-
197- RG_LOGE ("Unknown driver type" );
198- return false;
199-
200- #endif
201186}
202187
203188bool rg_i2c_gpio_deinit (void )
204189{
205- gpio_extender_initialized = false;
206- gpio_extender_address = 0 ;
190+ if (gpio_extender_initialized )
191+ {
192+ for (size_t i = 0 ; i < RG_COUNT (gpio_deinit_sequence ); ++ i )
193+ rg_i2c_write_byte (gpio_extender_address , gpio_deinit_sequence [i ][0 ], gpio_deinit_sequence [i ][1 ]);
194+ // Should we reset all pins to be high impedance?
195+ gpio_extender_initialized = false;
196+ }
207197 return true;
208198}
209199
210- bool rg_i2c_gpio_set_direction (int pin , int mode )
200+ bool rg_i2c_gpio_set_direction (int pin , rg_gpio_mode_t mode )
211201{
212- uint8_t reg = AW9523_REG_CONFIG0 + (pin >> 3 ), mask = 1 << (pin & 7 );
202+ uint8_t reg = gpio_direction_regs [ (pin >> 3 ) & 1 ] , mask = 1 << (pin & 7 );
213203 uint8_t val = rg_i2c_read_byte (gpio_extender_address , reg );
214204 return rg_i2c_write_byte (gpio_extender_address , reg , mode ? (val | mask ) : (val & ~mask ));
215205}
216206
217207uint8_t rg_i2c_gpio_read_port (int port )
218208{
219- return rg_i2c_read_byte (gpio_extender_address , AW9523_REG_INPUT0 + port );
209+ return rg_i2c_read_byte (gpio_extender_address , gpio_input_regs [ port & 1 ] );
220210}
221211
222212bool rg_i2c_gpio_write_port (int port , uint8_t value )
223213{
224- return rg_i2c_write_byte (gpio_extender_address , AW9523_REG_OUTPUT0 + port , value );
214+ return rg_i2c_write_byte (gpio_extender_address , gpio_output_regs [ port & 1 ] , value );
225215}
226216
227217int rg_i2c_gpio_get_level (int pin )
@@ -231,7 +221,7 @@ int rg_i2c_gpio_get_level(int pin)
231221
232222bool rg_i2c_gpio_set_level (int pin , int level )
233223{
234- uint8_t reg = AW9523_REG_OUTPUT0 + (pin >> 3 ), mask = 1 << (pin & 7 );
224+ uint8_t reg = gpio_output_regs [ (pin >> 3 ) & 1 ] , mask = 1 << (pin & 7 );
235225 uint8_t val = rg_i2c_read_byte (gpio_extender_address , reg );
236226 return rg_i2c_write_byte (gpio_extender_address , reg , level ? (val | mask ) : (val & ~mask ));
237227}
0 commit comments