1919/* Timeout of each I2C communication */
2020#define I2C_TIMEOUT_MS (10 )
2121
22- #define IO_COUNT (8 )
22+ #define IO_COUNT (12 )
2323
2424/* Register address */
25- #define CH422G_REG_IN (0x26 )
26- #define CH422G_REG_OUT (0x38 )
27-
28- /* Default register value on power-up */
29- #define DIR_REG_DEFAULT_VAL (0xff )
30- #define OUT_REG_DEFAULT_VAL (0xdf )
25+ #define CH422G_REG_WR_SET (0x48 >> 1 )
26+ #define CH422G_REG_WR_OC (0x46 >> 1 )
27+ #define CH422G_REG_WR_IO (0x70 >> 1 )
28+ #define CH422G_REG_RD_IO (0x4D >> 1 )
29+
30+ /* Default register value when reset */
31+ // *INDENT-OFF*
32+ #define REG_WR_SET_DEFAULT_VAL (0x01UL ) // Bit: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
33+ // | --- | --- | --- | --- | ------- | ------- | -------- | ------- |
34+ // Value: | / | / | / | / | [SLEEP] | [OD_EN] | [A_SCAN] | [IO_OE] |
35+ // | --- | --- | --- | --- | ------- | ------- | -------- | ------- |
36+ // Default: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
37+
38+ // *INDENT-OFF*
39+ #define REG_WR_OC_DEFAULT_VAL (0x0FUL )
40+ #define REG_WR_IO_DEFAULT_VAL (0xFFUL )
41+ #define REG_OUT_DEFAULT_VAL ((REG_WR_OC_DEFAULT_VAL << 8 ) | REG_WR_IO_DEFAULT_VAL)
42+ #define REG_DIR_DEFAULT_VAL (0xFFFUL )
43+
44+ #define REG_WR_SET_BIT_IO_OE (1 << 0 )
45+ #define REG_WR_SET_BIT_OD_EN (1 << 2 )
3146
3247/* *
3348 * @brief Device Structure Type
@@ -38,14 +53,22 @@ typedef struct {
3853 i2c_port_t i2c_num;
3954 uint32_t i2c_address;
4055 struct {
41- uint8_t direction;
42- uint8_t output;
56+ uint8_t wr_set;
57+ uint8_t wr_oc;
58+ uint8_t wr_io;
4359 } regs;
4460} esp_io_expander_ch422g_t ;
4561
4662static const char *TAG = " ch422g" ;
4763
4864static esp_err_t esp_io_expander_new_i2c_ch422g (i2c_port_t i2c_num, uint32_t i2c_address, esp_io_expander_handle_t *handle);
65+ static esp_err_t read_input_reg (esp_io_expander_handle_t handle, uint32_t *value);
66+ static esp_err_t write_output_reg (esp_io_expander_handle_t handle, uint32_t value);
67+ static esp_err_t read_output_reg (esp_io_expander_handle_t handle, uint32_t *value);
68+ static esp_err_t write_direction_reg (esp_io_expander_handle_t handle, uint32_t value);
69+ static esp_err_t read_direction_reg (esp_io_expander_handle_t handle, uint32_t *value);
70+ static esp_err_t reset (esp_io_expander_t *handle);
71+ static esp_err_t del (esp_io_expander_t *handle);
4972
5073ESP_IOExpander_CH422G::~ESP_IOExpander_CH422G ()
5174{
@@ -62,13 +85,55 @@ void ESP_IOExpander_CH422G::begin(void)
6285 CHECK_ERROR_RETURN (esp_io_expander_new_i2c_ch422g (i2c_id, i2c_address, &handle));
6386}
6487
65- static esp_err_t read_input_reg (esp_io_expander_handle_t handle, uint32_t *value);
66- static esp_err_t write_output_reg (esp_io_expander_handle_t handle, uint32_t value);
67- static esp_err_t read_output_reg (esp_io_expander_handle_t handle, uint32_t *value);
68- static esp_err_t write_direction_reg (esp_io_expander_handle_t handle, uint32_t value);
69- static esp_err_t read_direction_reg (esp_io_expander_handle_t handle, uint32_t *value);
70- static esp_err_t reset (esp_io_expander_t *handle);
71- static esp_err_t del (esp_io_expander_t *handle);
88+ void ESP_IOExpander_CH422G::enableOC_OpenDrain (void )
89+ {
90+ esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
91+ uint8_t data = (uint8_t )(ch422g->regs .wr_set | REG_WR_SET_BIT_OD_EN);
92+
93+ // WR-SET
94+ CHECK_ERROR_RETURN (
95+ i2c_master_write_to_device (ch422g->i2c_num , CH422G_REG_WR_SET, &data, sizeof (data), pdMS_TO_TICKS (I2C_TIMEOUT_MS))
96+ );
97+ ch422g->regs .wr_set = data;
98+ }
99+
100+ void ESP_IOExpander_CH422G::enableOC_PushPull (void )
101+ {
102+ esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
103+ uint8_t data = (uint8_t )(ch422g->regs .wr_set & ~REG_WR_SET_BIT_OD_EN);
104+
105+ // WR-SET
106+ CHECK_ERROR_RETURN (
107+ i2c_master_write_to_device (ch422g->i2c_num , CH422G_REG_WR_SET, &data, sizeof (data), pdMS_TO_TICKS (I2C_TIMEOUT_MS))
108+ );
109+ ch422g->regs .wr_set = data;
110+ }
111+
112+ void ESP_IOExpander_CH422G::enableAllIO_Input (void )
113+ {
114+ esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
115+ uint8_t data = (uint8_t )(ch422g->regs .wr_set & ~REG_WR_SET_BIT_IO_OE);
116+
117+ // WR-SET
118+ CHECK_ERROR_RETURN (
119+ i2c_master_write_to_device (ch422g->i2c_num , CH422G_REG_WR_SET, &data, sizeof (data), pdMS_TO_TICKS (I2C_TIMEOUT_MS))
120+ );
121+ ch422g->regs .wr_set = data;
122+ // Delay 1ms to wait for the IO expander to switch to input mode
123+ vTaskDelay (pdMS_TO_TICKS (2 ));
124+ }
125+
126+ void ESP_IOExpander_CH422G::enableAllIO_Output (void )
127+ {
128+ esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
129+ uint8_t data = (uint8_t )(ch422g->regs .wr_set | REG_WR_SET_BIT_IO_OE);
130+
131+ // WR-SET
132+ CHECK_ERROR_RETURN (
133+ i2c_master_write_to_device (ch422g->i2c_num , CH422G_REG_WR_SET, &data, sizeof (data), pdMS_TO_TICKS (I2C_TIMEOUT_MS))
134+ );
135+ ch422g->regs .wr_set = data;
136+ }
72137
73138static esp_err_t esp_io_expander_new_i2c_ch422g (i2c_port_t i2c_num, uint32_t i2c_address, esp_io_expander_handle_t *handle)
74139{
@@ -79,10 +144,11 @@ static esp_err_t esp_io_expander_new_i2c_ch422g(i2c_port_t i2c_num, uint32_t i2c
79144 ESP_RETURN_ON_FALSE (ch422g, ESP_ERR_NO_MEM, TAG, " Malloc failed" );
80145
81146 ch422g->base .config .io_count = IO_COUNT;
82- ch422g->base .config .flags .dir_out_bit_zero = 1 ;
83147 ch422g->i2c_num = i2c_num;
84148 ch422g->i2c_address = i2c_address;
85- ch422g->regs .output = OUT_REG_DEFAULT_VAL;
149+ ch422g->regs .wr_set = REG_WR_SET_DEFAULT_VAL;
150+ ch422g->regs .wr_oc = REG_WR_OC_DEFAULT_VAL;
151+ ch422g->regs .wr_io = REG_WR_IO_DEFAULT_VAL;
86152 ch422g->base .read_input_reg = read_input_reg;
87153 ch422g->base .write_output_reg = write_output_reg;
88154 ch422g->base .read_output_reg = read_output_reg;
@@ -105,67 +171,93 @@ static esp_err_t esp_io_expander_new_i2c_ch422g(i2c_port_t i2c_num, uint32_t i2c
105171static esp_err_t read_input_reg (esp_io_expander_handle_t handle, uint32_t *value)
106172{
107173 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
108-
109174 uint8_t temp = 0 ;
110175
111176 ESP_RETURN_ON_ERROR (
112- i2c_master_read_from_device (ch422g->i2c_num , ch422g->i2c_address , &temp, 1 , pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
113- TAG, " Read input reg failed" );
114-
115- // *INDENT-OFF*
116- ESP_RETURN_ON_ERROR (
117- i2c_master_read_from_device (ch422g->i2c_num , CH422G_REG_IN, &temp, 1 , pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
118- TAG, " Read input reg failed" );
119- // *INDENT-ON*
177+ i2c_master_read_from_device (ch422g->i2c_num , CH422G_REG_RD_IO, &temp, 1 , pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
178+ TAG, " Read RD-IO reg failed"
179+ );
120180 *value = temp;
181+
121182 return ESP_OK;
122183}
123184
124185static esp_err_t write_output_reg (esp_io_expander_handle_t handle, uint32_t value)
125186{
126187 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
127- value &= 0xff ;
128188
129- uint8_t out_temp = 0x01 ;
130- ESP_RETURN_ON_ERROR (
131- i2c_master_write_to_device (ch422g->i2c_num , ch422g->i2c_address , &out_temp, 1 , pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
132- TAG, " Write output reg failed" );
189+ uint8_t wr_oc_data = (value & 0xF00 ) >> 8 ;
190+ uint8_t wr_io_data = value & 0xFF ;
191+
192+ // WR-OC
193+ if (wr_oc_data) {
194+ ESP_RETURN_ON_ERROR (
195+ i2c_master_write_to_device (ch422g->i2c_num , CH422G_REG_WR_OC, &wr_oc_data, sizeof (wr_oc_data), pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
196+ TAG, " Write WR-OC reg failed"
197+ );
198+ ch422g->regs .wr_oc = wr_oc_data;
199+ }
200+
201+ // WR-IO
202+ if (wr_io_data) {
203+ ESP_RETURN_ON_ERROR (
204+ i2c_master_write_to_device (ch422g->i2c_num , CH422G_REG_WR_IO, &wr_io_data, sizeof (wr_io_data), pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
205+ TAG, " Write WR-IO reg failed"
206+ );
207+ ch422g->regs .wr_io = wr_io_data;
208+ }
133209
134- uint8_t data = (uint8_t )value;
135- ESP_RETURN_ON_ERROR (
136- i2c_master_write_to_device (ch422g->i2c_num , CH422G_REG_OUT, &data, 1 , pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
137- TAG, " Write output reg failed" );
138- ch422g->regs .output = value;
139210 return ESP_OK;
140211}
141212
142213static esp_err_t read_output_reg (esp_io_expander_handle_t handle, uint32_t *value)
143214{
144215 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
145216
146- *value = ch422g->regs .output ;
217+ *value = ch422g->regs .wr_io | (((uint32_t )ch422g->regs .wr_oc ) << 8 );
218+
147219 return ESP_OK;
148220}
149221
150222static esp_err_t write_direction_reg (esp_io_expander_handle_t handle, uint32_t value)
151223{
152224 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
153- value &= 0xff ;
154- ch422g->regs .direction = value;
225+ uint8_t data = ch422g->regs .wr_set ;
226+
227+ value &= 0xFF ;
228+ if (value != 0 ) {
229+ data |= REG_WR_SET_BIT_IO_OE;
230+ } else {
231+ data &= ~REG_WR_SET_BIT_IO_OE;
232+ }
233+
234+ // WR-SET
235+ ESP_RETURN_ON_ERROR (
236+ i2c_master_write_to_device (ch422g->i2c_num , CH422G_REG_WR_SET, &data, sizeof (data), pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
237+ TAG, " Write WR_SET reg failed"
238+ );
239+ ch422g->regs .wr_set = data;
240+
155241 return ESP_OK;
156242}
157243
244+ #define DIR_OUT_VALUE (0xFFF )
245+ #define DIR_IN_VALUE (0xF00 )
246+
158247static esp_err_t read_direction_reg (esp_io_expander_handle_t handle, uint32_t *value)
159248{
160249 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
161250
162- *value = ch422g->regs .direction ;
251+ *value = (ch422g->regs .wr_set & REG_WR_SET_BIT_IO_OE) ? DIR_OUT_VALUE : DIR_IN_VALUE;
252+
163253 return ESP_OK;
164254}
165255
166256static esp_err_t reset (esp_io_expander_t *handle)
167257{
168- ESP_RETURN_ON_ERROR (write_output_reg (handle, OUT_REG_DEFAULT_VAL), TAG, " Write output reg failed" );
258+ ESP_RETURN_ON_ERROR (write_direction_reg (handle, REG_DIR_DEFAULT_VAL), TAG, " Write direction reg (WR_SET) failed" );
259+ ESP_RETURN_ON_ERROR (write_output_reg (handle, REG_OUT_DEFAULT_VAL), TAG, " Write output reg (WR_OC & WR_IO) failed" );
260+
169261 return ESP_OK;
170262}
171263
@@ -174,5 +266,6 @@ static esp_err_t del(esp_io_expander_t *handle)
174266 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
175267
176268 free (ch422g);
269+
177270 return ESP_OK;
178271}
0 commit comments