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 )
25+ #define CH422G_REG_WR_SET (0x48 )
26+ #define CH422G_REG_WR_OC (0x46 )
27+ #define CH422G_REG_WR_IO (0x70 )
28+ #define CH422G_REG_RD_IO (0x4D )
2729
2830/* Default register value on power-up */
29- #define DIR_REG_DEFAULT_VAL (0xff )
30- #define OUT_REG_DEFAULT_VAL (0xdf )
31+ // *INDENT-OFF*
32+ #define REG_WR_SET_DEFAULT_VAL (0x00UL ) // Bit: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
33+ // |---------|---|---|---------|---|----------|---|---------|
34+ // Value: | [SLEEP] | 0 | 0 | [OD_EN] | 0 | [A_SCAN] | 0 | [IO_OE] |
35+ // |---------|---|---|---------|---|----------|---|---------|
36+ // Default: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
37+ // *INDENT-OFF*
38+ #define REG_WR_OC_DEFAULT_VAL (0x00UL )
39+ #define REG_WR_IO_DEFAULT_VAL (0x00UL )
40+ #define REG_OUT_DEFAULT_VAL (REG_WR_OC_DEFAULT_VAL << 8 | REG_WR_IO_DEFAULT_VAL)
41+
42+ #define REG_WR_SET_BIT_IO_OE (1 << 0 )
43+ #define REG_WR_SET_BIT_OD_EN (1 << 4 )
3144
3245/* *
3346 * @brief Device Structure Type
@@ -38,8 +51,9 @@ typedef struct {
3851 i2c_port_t i2c_num;
3952 uint32_t i2c_address;
4053 struct {
41- uint8_t direction;
42- uint8_t output;
54+ uint8_t wr_set;
55+ uint8_t wr_oc;
56+ uint8_t wr_io;
4357 } regs;
4458} esp_io_expander_ch422g_t ;
4559
@@ -62,6 +76,32 @@ void ESP_IOExpander_CH422G::begin(void)
6276 CHECK_ERROR_RETURN (esp_io_expander_new_i2c_ch422g (i2c_id, i2c_address, &handle));
6377}
6478
79+ void ESP_IOExpander_CH422G::enableOC_OpenDrain (void )
80+ {
81+ esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
82+
83+ uint8_t data[2 ] = {CH422G_REG_WR_SET, (uint8_t )(ch422g->regs .wr_set | REG_WR_SET_BIT_OD_EN)};
84+
85+ // WR-SET
86+ CHECK_ERROR_RETURN (
87+ i2c_master_write_to_device (ch422g->i2c_num , ch422g->i2c_address , data, sizeof (data), pdMS_TO_TICKS (I2C_TIMEOUT_MS))
88+ );
89+ ch422g->regs .wr_set = data[1 ];
90+ }
91+
92+ void ESP_IOExpander_CH422G::enableOC_PushPull (void )
93+ {
94+ esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
95+
96+ uint8_t data[2 ] = {CH422G_REG_WR_SET, (uint8_t )(ch422g->regs .wr_set & ~REG_WR_SET_BIT_OD_EN)};
97+
98+ // WR-SET
99+ CHECK_ERROR_RETURN (
100+ i2c_master_write_to_device (ch422g->i2c_num , ch422g->i2c_address , data, sizeof (data), pdMS_TO_TICKS (I2C_TIMEOUT_MS))
101+ );
102+ ch422g->regs .wr_set = data[1 ];
103+ }
104+
65105static esp_err_t read_input_reg (esp_io_expander_handle_t handle, uint32_t *value);
66106static esp_err_t write_output_reg (esp_io_expander_handle_t handle, uint32_t value);
67107static esp_err_t read_output_reg (esp_io_expander_handle_t handle, uint32_t *value);
@@ -82,7 +122,9 @@ static esp_err_t esp_io_expander_new_i2c_ch422g(i2c_port_t i2c_num, uint32_t i2c
82122 ch422g->base .config .flags .dir_out_bit_zero = 1 ;
83123 ch422g->i2c_num = i2c_num;
84124 ch422g->i2c_address = i2c_address;
85- ch422g->regs .output = OUT_REG_DEFAULT_VAL;
125+ ch422g->regs .wr_set = REG_WR_SET_DEFAULT_VAL;
126+ ch422g->regs .wr_oc = REG_WR_OC_DEFAULT_VAL;
127+ ch422g->regs .wr_io = REG_WR_IO_DEFAULT_VAL;
86128 ch422g->base .read_input_reg = read_input_reg;
87129 ch422g->base .write_output_reg = write_output_reg;
88130 ch422g->base .read_output_reg = read_output_reg;
@@ -107,65 +149,99 @@ static esp_err_t read_input_reg(esp_io_expander_handle_t handle, uint32_t *value
107149 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
108150
109151 uint8_t temp = 0 ;
152+ uint8_t reg = CH422G_REG_RD_IO;
110153
111154 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*
155+ i2c_master_write_read_device (ch422g->i2c_num , ch422g->i2c_address , ®, 1 , &temp, 1 , pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
156+ TAG, " Read RD-IO reg failed"
157+ );
120158 *value = temp;
159+
121160 return ESP_OK;
122161}
123162
124163static esp_err_t write_output_reg (esp_io_expander_handle_t handle, uint32_t value)
125164{
126165 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
127- value &= 0xff ;
128166
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" );
167+ uint8_t wr_oc_data = (value & 0xf00 ) >> 8 ;
168+ uint8_t wr_io_data = value & 0xff ;
169+ uint8_t data[2 ] = {};
170+
171+ // WR-OC
172+ if (wr_oc_data) {
173+ data[0 ] = CH422G_REG_WR_OC;
174+ data[1 ] = wr_oc_data;
175+ ESP_RETURN_ON_ERROR (
176+ i2c_master_write_to_device (ch422g->i2c_num , ch422g->i2c_address , data, sizeof (data), pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
177+ TAG, " Write WR-OC reg failed"
178+ );
179+ ch422g->regs .wr_oc = wr_oc_data;
180+ }
181+
182+ // WR-IO
183+ if (wr_io_data) {
184+ data[0 ] = CH422G_REG_WR_IO;
185+ data[1 ] = wr_io_data;
186+ ESP_RETURN_ON_ERROR (
187+ i2c_master_write_to_device (ch422g->i2c_num , ch422g->i2c_address , data, sizeof (data), pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
188+ TAG, " Write WR-IO reg failed"
189+ );
190+ ch422g->regs .wr_io = wr_io_data;
191+ }
133192
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;
139193 return ESP_OK;
140194}
141195
142196static esp_err_t read_output_reg (esp_io_expander_handle_t handle, uint32_t *value)
143197{
144198 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
145199
146- *value = ch422g->regs .output ;
200+ *value = ch422g->regs .wr_io | (((uint32_t )ch422g->regs .wr_oc ) << 8 );
201+
147202 return ESP_OK;
148203}
149204
150205static esp_err_t write_direction_reg (esp_io_expander_handle_t handle, uint32_t value)
151206{
152207 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
153208 value &= 0xff ;
154- ch422g->regs .direction = value;
209+
210+ uint8_t data[2 ] = {CH422G_REG_WR_SET, ch422g->regs .wr_set };
211+
212+ if (value > 0 ) {
213+ data[1 ] |= REG_WR_SET_BIT_IO_OE;
214+ } else {
215+ data[1 ] &= ~REG_WR_SET_BIT_IO_OE;
216+ }
217+
218+ // WR-SET
219+ ESP_RETURN_ON_ERROR (
220+ i2c_master_write_to_device (ch422g->i2c_num , ch422g->i2c_address , data, sizeof (data), pdMS_TO_TICKS (I2C_TIMEOUT_MS)),
221+ TAG, " Write WR_SET reg failed"
222+ );
223+ ch422g->regs .wr_set = data[1 ];
224+
155225 return ESP_OK;
156226}
157227
228+ #define DIR_OUT_VALUE (0xFFF )
229+ #define DIR_IN_VALUE (0xF00 )
230+
158231static esp_err_t read_direction_reg (esp_io_expander_handle_t handle, uint32_t *value)
159232{
160233 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
161234
162- *value = ch422g->regs .direction ;
235+ *value = (ch422g->regs .wr_set & REG_WR_SET_BIT_IO_OE) ? DIR_OUT_VALUE : DIR_IN_VALUE;
236+
163237 return ESP_OK;
164238}
165239
166240static esp_err_t reset (esp_io_expander_t *handle)
167241{
168- ESP_RETURN_ON_ERROR (write_output_reg (handle, OUT_REG_DEFAULT_VAL), TAG, " Write output reg failed" );
242+ ESP_RETURN_ON_ERROR (write_direction_reg (handle, REG_WR_SET_DEFAULT_VAL), TAG, " Write direction reg (WR_SET) failed" );
243+ ESP_RETURN_ON_ERROR (write_output_reg (handle, REG_OUT_DEFAULT_VAL), TAG, " Write output reg (WR_OC & WR_IO) failed" );
244+
169245 return ESP_OK;
170246}
171247
@@ -174,5 +250,6 @@ static esp_err_t del(esp_io_expander_t *handle)
174250 esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
175251
176252 free (ch422g);
253+
177254 return ESP_OK;
178255}
0 commit comments