19
19
/* Timeout of each I2C communication */
20
20
#define I2C_TIMEOUT_MS (10 )
21
21
22
- #define IO_COUNT (8 )
22
+ #define IO_COUNT (12 )
23
23
24
24
/* 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 )
31
46
32
47
/* *
33
48
* @brief Device Structure Type
@@ -38,14 +53,22 @@ typedef struct {
38
53
i2c_port_t i2c_num;
39
54
uint32_t i2c_address;
40
55
struct {
41
- uint8_t direction;
42
- uint8_t output;
56
+ uint8_t wr_set;
57
+ uint8_t wr_oc;
58
+ uint8_t wr_io;
43
59
} regs;
44
60
} esp_io_expander_ch422g_t ;
45
61
46
62
static const char *TAG = " ch422g" ;
47
63
48
64
static 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);
49
72
50
73
ESP_IOExpander_CH422G::~ESP_IOExpander_CH422G ()
51
74
{
@@ -62,13 +85,55 @@ void ESP_IOExpander_CH422G::begin(void)
62
85
CHECK_ERROR_RETURN (esp_io_expander_new_i2c_ch422g (i2c_id, i2c_address, &handle));
63
86
}
64
87
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
+ }
72
137
73
138
static esp_err_t esp_io_expander_new_i2c_ch422g (i2c_port_t i2c_num, uint32_t i2c_address, esp_io_expander_handle_t *handle)
74
139
{
@@ -79,10 +144,11 @@ static esp_err_t esp_io_expander_new_i2c_ch422g(i2c_port_t i2c_num, uint32_t i2c
79
144
ESP_RETURN_ON_FALSE (ch422g, ESP_ERR_NO_MEM, TAG, " Malloc failed" );
80
145
81
146
ch422g->base .config .io_count = IO_COUNT;
82
- ch422g->base .config .flags .dir_out_bit_zero = 1 ;
83
147
ch422g->i2c_num = i2c_num;
84
148
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;
86
152
ch422g->base .read_input_reg = read_input_reg;
87
153
ch422g->base .write_output_reg = write_output_reg;
88
154
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
105
171
static esp_err_t read_input_reg (esp_io_expander_handle_t handle, uint32_t *value)
106
172
{
107
173
esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
108
-
109
174
uint8_t temp = 0 ;
110
175
111
176
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
+ );
120
180
*value = temp;
181
+
121
182
return ESP_OK;
122
183
}
123
184
124
185
static esp_err_t write_output_reg (esp_io_expander_handle_t handle, uint32_t value)
125
186
{
126
187
esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
127
- value &= 0xff ;
128
188
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
+ }
133
209
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;
139
210
return ESP_OK;
140
211
}
141
212
142
213
static esp_err_t read_output_reg (esp_io_expander_handle_t handle, uint32_t *value)
143
214
{
144
215
esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
145
216
146
- *value = ch422g->regs .output ;
217
+ *value = ch422g->regs .wr_io | (((uint32_t )ch422g->regs .wr_oc ) << 8 );
218
+
147
219
return ESP_OK;
148
220
}
149
221
150
222
static esp_err_t write_direction_reg (esp_io_expander_handle_t handle, uint32_t value)
151
223
{
152
224
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
+
155
241
return ESP_OK;
156
242
}
157
243
244
+ #define DIR_OUT_VALUE (0xFFF )
245
+ #define DIR_IN_VALUE (0xF00 )
246
+
158
247
static esp_err_t read_direction_reg (esp_io_expander_handle_t handle, uint32_t *value)
159
248
{
160
249
esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
161
250
162
- *value = ch422g->regs .direction ;
251
+ *value = (ch422g->regs .wr_set & REG_WR_SET_BIT_IO_OE) ? DIR_OUT_VALUE : DIR_IN_VALUE;
252
+
163
253
return ESP_OK;
164
254
}
165
255
166
256
static esp_err_t reset (esp_io_expander_t *handle)
167
257
{
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
+
169
261
return ESP_OK;
170
262
}
171
263
@@ -174,5 +266,6 @@ static esp_err_t del(esp_io_expander_t *handle)
174
266
esp_io_expander_ch422g_t *ch422g = (esp_io_expander_ch422g_t *)__containerof (handle, esp_io_expander_ch422g_t , base);
175
267
176
268
free (ch422g);
269
+
177
270
return ESP_OK;
178
271
}
0 commit comments