Newer
Older
//#include <stdio.h>
//#include <string.h>
#include "esp_log.h"
#include "driver/i2c.h"
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
static const char *TAG = "captouch";
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define AD7147_BASE_ADDR 0x2C
#define AD7147_REG_PWR_CONTROL 0x00
#define AD7147_REG_STAGE_CAL_EN 0x01
#define AD7147_REG_STAGE_HIGH_INT_ENABLE 0x06
#define AD7147_REG_DEVICE_ID 0x17
#define TIMEOUT_MS 1000
struct ad714x_chip {
uint8_t addr;
uint8_t gpio;
int afe_offsets[13];
int stages;
};
static const struct ad714x_chip chip_top = {.addr = AD7147_BASE_ADDR + 1, .gpio = 48, .afe_offsets = {24, 12, 16, 33, 30, 28, 31, 27, 22, 24, 18, 19, }, .stages=12};
static const struct ad714x_chip chip_bot = {.addr = AD7147_BASE_ADDR, .gpio = 3, .afe_offsets = {3, 2, 1, 1 ,1, 1, 1, 1, 2, 3}, .stages=10};
static esp_err_t ad714x_i2c_write(const struct ad714x_chip *chip, const uint16_t reg, const uint16_t data)
{
const uint8_t tx[] = {reg >> 8, reg & 0xFF, data >> 8, data & 0xFF};
ESP_LOGI(TAG, "AD7147 write reg %X-> %X", reg, data);
return i2c_master_write_to_device(I2C_MASTER_NUM, chip->addr, tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS);
}
static esp_err_t ad714x_i2c_read(const struct ad714x_chip *chip, const uint16_t reg, uint16_t *data, const size_t len)
{
const uint8_t tx[] = {reg >> 8, reg & 0xFF};
uint8_t rx[len * 2];
esp_err_t ret = i2c_master_write_read_device(I2C_MASTER_NUM, chip->addr, tx, sizeof(tx), rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS);
for(int i = 0; i < len; i++) {
data[i] = (rx[i * 2] << 8) | rx[i * 2 + 1];
}
return ret;
}
struct ad7147_stage_config {
unsigned int cinX_connection_setup[13];
unsigned int se_connection_setup:2;
unsigned int neg_afe_offset_disable:1;
unsigned int pos_afe_offset_disable:1;
unsigned int neg_afe_offset:6;
unsigned int neg_afe_offset_swap:1;
unsigned int pos_afe_offset:6;
unsigned int pos_afe_offset_swap:1;
unsigned int neg_threshold_sensitivity:4;
unsigned int neg_peak_detect:3;
unsigned int pos_threshold_sensitivity:4;
unsigned int pos_peak_detect:3;
};
#define CIN CDC_NONE 0
#define CIN_CDC_NEG 1
#define CIN_CDC_POS 2
#define CIN_BIAS 3
static const uint16_t bank2 = 0x80;
static void ad714x_set_stage_config(const struct ad714x_chip *chip, const uint8_t stage, const struct ad7147_stage_config * config)
{
const uint16_t connection_6_0 = (config->cinX_connection_setup[6] << 12) | (config->cinX_connection_setup[5] << 10) | (config->cinX_connection_setup[4] << 8) | (config->cinX_connection_setup[3] << 6) | (config->cinX_connection_setup[2] << 4) | (config->cinX_connection_setup[1] << 2) | (config->cinX_connection_setup[0] << 0);
const uint16_t connection_12_7 = (config->pos_afe_offset_disable << 15) | (config->neg_afe_offset_disable << 14) | (config->se_connection_setup << 12) | (config->cinX_connection_setup[12] << 10) | (config->cinX_connection_setup[11] << 8) | (config->cinX_connection_setup[10] << 6) | (config->cinX_connection_setup[9] << 4) | (config->cinX_connection_setup[8] << 2) | (config->cinX_connection_setup[7] << 0);
const uint16_t afe_offset = (config->pos_afe_offset_swap << 15) | (config->pos_afe_offset << 8) | (config->neg_afe_offset_swap << 7) | (config->neg_afe_offset << 0);
const uint16_t sensitivity = (config->pos_peak_detect << 12) | (config->pos_threshold_sensitivity << 8) | (config->neg_peak_detect << 4) | (config->neg_threshold_sensitivity << 0);
//ESP_LOGI(TAG, "Stage %d config-> %X %X %X %X", stage, connection_6_0, connection_12_7, afe_offset, sensitivity);
//ESP_LOGI(TAG, "Config: %X %X %X %X %X %X %X %X %X", config->pos_afe_offset_disable, config->pos_afe_offset_disable, config->se_connection_setup, config->cinX_connection_setup[12], config->cinX_connection_setup[11], config->cinX_connection_setup[10], config->cinX_connection_setup[9], config->cinX_connection_setup[8], config->cinX_connection_setup[7]);
ad714x_i2c_write(chip, bank2 + stage * 8, connection_6_0);
ad714x_i2c_write(chip, bank2 + stage * 8 + 1, connection_12_7);
ad714x_i2c_write(chip, bank2 + stage * 8 + 2, afe_offset);
ad714x_i2c_write(chip, bank2 + stage * 8 + 3, sensitivity);
}
struct ad7147_device_config {
unsigned int power_mode:2;
unsigned int lp_conv_delay:2;
unsigned int sequence_stage_num:4;
unsigned int decimation:2;
unsigned int sw_reset:1;
unsigned int int_pol:1;
unsigned int ext_source:1;
unsigned int cdc_bias:2;
unsigned int stage0_cal_en:1;
unsigned int stage1_cal_en:1;
unsigned int stage2_cal_en:1;
unsigned int stage3_cal_en:1;
unsigned int stage4_cal_en:1;
unsigned int stage5_cal_en:1;
unsigned int stage6_cal_en:1;
unsigned int stage7_cal_en:1;
unsigned int stage8_cal_en:1;
unsigned int stage9_cal_en:1;
unsigned int stage10_cal_en:1;
unsigned int stage11_cal_en:1;
unsigned int avg_fp_skip:2;
unsigned int avg_lp_skip:2;
unsigned int stage0_high_int_enable:1;
unsigned int stage1_high_int_enable:1;
unsigned int stage2_high_int_enable:1;
unsigned int stage3_high_int_enable:1;
unsigned int stage4_high_int_enable:1;
unsigned int stage5_high_int_enable:1;
unsigned int stage6_high_int_enable:1;
unsigned int stage7_high_int_enable:1;
unsigned int stage8_high_int_enable:1;
unsigned int stage9_high_int_enable:1;
unsigned int stage10_high_int_enable:1;
unsigned int stage11_high_int_enable:1;
};
static void ad714x_set_device_config(const struct ad714x_chip *chip, const struct ad7147_device_config * config)
{
const uint16_t pwr_control = (config->cdc_bias << 14) | (config->ext_source << 12) | (config->int_pol << 11) | (config->sw_reset << 10) | (config->decimation << 8) | (config->sequence_stage_num << 4) | (config->lp_conv_delay << 2) | (config->power_mode << 0);
const uint16_t stage_cal_en = (config->avg_lp_skip << 14) | (config->avg_fp_skip << 12) | (config->stage11_cal_en << 11) | (config->stage10_cal_en << 10) | (config->stage9_cal_en << 9) | (config->stage8_cal_en << 8) | (config->stage7_cal_en << 7) | (config->stage6_cal_en << 6) | (config->stage5_cal_en << 5) | (config->stage4_cal_en << 4) | (config->stage3_cal_en << 3) | (config->stage2_cal_en << 2) | (config->stage1_cal_en << 1) | (config->stage0_cal_en << 0);
const uint16_t stage_high_int_enable = (config->stage11_high_int_enable << 11) | (config->stage10_high_int_enable << 10) | (config->stage9_high_int_enable << 9) | (config->stage8_high_int_enable << 8) | (config->stage7_high_int_enable << 7) | (config->stage6_high_int_enable << 6) | (config->stage5_high_int_enable << 5) | (config->stage4_high_int_enable << 4) | (config->stage3_high_int_enable << 3) | (config->stage2_high_int_enable << 2) | (config->stage1_high_int_enable << 1) | (config->stage0_high_int_enable << 0);
ad714x_i2c_write(chip, AD7147_REG_PWR_CONTROL, pwr_control);
ad714x_i2c_write(chip, AD7147_REG_STAGE_CAL_EN, stage_cal_en);
ad714x_i2c_write(chip, AD7147_REG_STAGE_HIGH_INT_ENABLE, stage_high_int_enable);
}
static struct ad7147_stage_config ad714x_default_config(void)
{
return (struct ad7147_stage_config) {
.cinX_connection_setup={CIN_BIAS, CIN_BIAS, CIN_BIAS, CIN_BIAS, CIN_BIAS, CIN_BIAS, CIN_BIAS, CIN_BIAS, CIN_BIAS, CIN_BIAS, CIN_BIAS, CIN_BIAS},
.se_connection_setup=0b01,
.pos_afe_offset=0,
};
}
#define ESP_INTR_FLAG_DEFAULT 0
static QueueHandle_t gpio_evt_queue = NULL;
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
struct ad714x_chip* chip = (struct ad714x_chip *) arg;
xQueueSendFromISR(gpio_evt_queue, &chip, NULL);
}
void manual_captouch_readout(uint8_t top)
{
struct ad714x_chip* chip = top ? (&chip_top) : (&chip_bot);
static uint16_t pressed_top, pressed_bot;
void gpio_event_handler(void* arg)
{
static unsigned long counter = 0;
struct ad714x_chip* chip;
uint16_t pressed;
while(true) {
if(xQueueReceive(gpio_evt_queue, &chip, portMAX_DELAY)) {
ad714x_i2c_read(chip, 9, &pressed, 1);
ESP_LOGI(TAG, "Addr %x, High interrupt %X", chip->addr, pressed);
pressed &= ((1 << chip->stages) - 1);
if(chip == &chip_top) pressed_top = pressed;
if(chip == &chip_bot) pressed_bot = pressed;
}
}
}
static uint8_t top_map[] = {2, 2, 2, 0, 0, 8, 8, 8, 6, 6, 4, 4};
static uint8_t bot_map[] = {1, 1, 3, 3, 5, 5, 7, 7, 9, 9};
uint16_t read_captouch(){
uint16_t petals = 0;
uint16_t top = pressed_top;
uint16_t bot = pressed_bot;
petals |= (1<<top_map[i]);
}
}
for(int i=0; i<10; i++) {
petals |= (1<<bot_map[i]);
}
}
return petals;
}
void captouch_force_calibration(){
ad714x_i2c_write(&chip_top, 2, (1 << 14));
ad714x_i2c_write(&chip_bot, 2, (1 << 14));
}
static void captouch_init_chip(const struct ad714x_chip* chip, const struct ad7147_device_config device_config)
{
uint16_t data;
ad714x_i2c_read(chip, AD7147_REG_DEVICE_ID, &data, 1);
ESP_LOGI(TAG, "DEVICE ID = %X", data);
ad714x_set_device_config(chip, &device_config);
for(int i=0; i<chip->stages; i++) {
struct ad7147_stage_config stage_config;
stage_config = ad714x_default_config();
stage_config.cinX_connection_setup[i] = CIN_CDC_POS;
stage_config.pos_afe_offset=chip->afe_offsets[i];
ad714x_set_stage_config(chip, i, &stage_config);
}
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_NEGEDGE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << chip->gpio);
io_conf.pull_up_en = 1;
io_conf.pull_down_en = 0;
gpio_config(&io_conf);
// gpio_isr_handler_add(chip->gpio, gpio_isr_handler, (void *)chip);
}
void captouch_init(void)
{
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
captouch_init_chip(&chip_top, (struct ad7147_device_config){.sequence_stage_num = 11,
.decimation = 1,
.stage0_cal_en = 1,
.stage1_cal_en = 1,
.stage2_cal_en = 1,
.stage3_cal_en = 1,
.stage4_cal_en = 1,
.stage5_cal_en = 1,
.stage6_cal_en = 1,
.stage7_cal_en = 1,
.stage8_cal_en = 1,
.stage9_cal_en = 1,
.stage10_cal_en = 1,
.stage11_cal_en = 1,
.stage0_high_int_enable = 1,
.stage1_high_int_enable = 1,
.stage2_high_int_enable = 1,
.stage3_high_int_enable = 1,
.stage4_high_int_enable = 1,
.stage5_high_int_enable = 1,
.stage6_high_int_enable = 1,
.stage7_high_int_enable = 1,
.stage8_high_int_enable = 1,
.stage9_high_int_enable = 1,
.stage10_high_int_enable = 1,
.stage11_high_int_enable = 1,
});
captouch_init_chip(&chip_bot, (struct ad7147_device_config){.sequence_stage_num = 11,
.decimation = 1,
.stage0_cal_en = 1,
.stage1_cal_en = 1,
.stage2_cal_en = 1,
.stage3_cal_en = 1,
.stage4_cal_en = 1,
.stage5_cal_en = 1,
.stage6_cal_en = 1,
.stage7_cal_en = 1,
.stage8_cal_en = 1,
.stage9_cal_en = 1,
.stage0_high_int_enable = 1,
.stage1_high_int_enable = 1,
.stage2_high_int_enable = 1,
.stage3_high_int_enable = 1,
.stage4_high_int_enable = 1,
.stage5_high_int_enable = 1,
.stage6_high_int_enable = 1,
.stage7_high_int_enable = 1,
.stage8_high_int_enable = 1,
.stage9_high_int_enable = 1,
});
gpio_evt_queue = xQueueCreate(10, sizeof(const struct ad714x_chip*));
xTaskCreate(gpio_event_handler, "gpio_event_handler", 2048 * 2, NULL, configMAX_PRIORITIES - 2, NULL);
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
}
static void captouch_print_debug_info_chip(const struct ad714x_chip* chip)
{
uint16_t data[12] = {0,};
uint16_t ambient[12] = {0,};
const int stages = chip->stages;
#if 1
for(int stage=0; stage<stages; stage++) {
ad714x_i2c_read(chip, 0x0FA + stage * (0x104 - 0xE0), data, 1);
ESP_LOGI(TAG, "stage %d threshold: %X", stage, data[0]);
}
ad714x_i2c_read(chip, 0xB, data, stages);
ESP_LOGI(TAG, "CDC results: %X %X %X %X %X %X %X %X %X %X %X %X", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11]);
for(int stage=0; stage<stages; stage++) {
ad714x_i2c_read(chip, 0x0F1 + stage * (0x104 - 0xE0), &ambient[stage], 1);
ESP_LOGI(TAG, "stage %d ambient: %X diff: %d", stage, ambient[stage], data[stage] - ambient[stage]);
}
#endif
#if 1
ad714x_i2c_read(chip, 8, data, 1);
ESP_LOGI(TAG, "Low interrupt %X", data[0]);
ad714x_i2c_read(chip, 9, data, 1);
ESP_LOGI(TAG, "High interrupt %X", data[0]);
ad714x_i2c_read(chip, 0x42, data, 1);
ESP_LOGI(TAG, "Proximity %X", data[0]);
//ESP_LOGI(TAG, "CDC result = %X", data[0]);
//if(data[0] > 0xa000) {
//ESP_LOGI(TAG, "Touch! %X", data[0]);
//}
#endif
}
void captouch_print_debug_info(void)
{
captouch_print_debug_info_chip(&chip_top);
captouch_print_debug_info_chip(&chip_bot);
}
void captouch_get_cross(int paddle, int *x, int *y)
{
uint16_t data[12] = {0,};
uint16_t ambient[12] = {0,};
int result[2] = {0, 0};
float total = 0;
#if 0
if(paddle == 2) {
ad714x_i2c_read(&chip_top, 0xB, data, 3);
//ESP_LOGI(TAG, "CDC results: %X %X %X %X %X %X %X %X %X %X %X %X", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11]);
for(int stage=0; stage<3; stage++) {
ad714x_i2c_read(&chip_top, 0x0F1 + stage * (0x104 - 0xE0), &ambient[stage], 1);
//ESP_LOGI(TAG, "stage %d ambient: %X diff: %d", stage, ambient[stage], data[stage] - ambient[stage]);
}
int vectors[][2] = {{0, 0}, {0,240}, {240, 120}};
total = (data[0] - ambient[0]) + (data[1] - ambient[1]) + (data[2] - ambient[2]);
result[0] = vectors[0][0] * (data[0] - ambient[0]) + vectors[1][0] * (data[1] - ambient[1]) + vectors[2][0] * (data[2] - ambient[2]);
result[1] = vectors[0][1] * (data[0] - ambient[0]) + vectors[1][1] * (data[1] - ambient[1]) + vectors[2][1] * (data[2] - ambient[2]);
}
if(paddle == 8) {
ad714x_i2c_read(&chip_top, 0xB + 5, data + 5, 3);
//ESP_LOGI(TAG, "CDC results: %X %X %X %X %X %X %X %X %X %X %X %X", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11]);
for(int stage=5; stage<8; stage++) {
ad714x_i2c_read(&chip_top, 0x0F1 + stage * (0x104 - 0xE0), &ambient[stage], 1);
//ESP_LOGI(TAG, "stage %d ambient: %X diff: %d", stage, ambient[stage], data[stage] - ambient[stage]);
}
int vectors[][2] = {{240, 240}, {240, 0}, {0, 120}};
total = (data[5] - ambient[5]) + (data[6] - ambient[6]) + (data[7] - ambient[7]);
result[0] = vectors[0][0] * (data[5] - ambient[5]) + vectors[1][0] * (data[6] - ambient[6]) + vectors[2][0] * (data[7] - ambient[7]);
result[1] = vectors[0][1] * (data[5] - ambient[5]) + vectors[1][1] * (data[6] - ambient[6]) + vectors[2][1] * (data[7] - ambient[7]);
}
*x = result[0] / total;
*y = result[1] / total;
//ESP_LOGI(TAG, "x=%d y=%d\n", *x, *y);
#endif
const int paddle_info_1[] = {
4,
0,
1,
2,
11,
4,
9,
7,
6,
9,
};
const int paddle_info_2[] = {
3,
1,
0,
3,
10,
5,
8,
6,
5,
8,
};
struct ad714x_chip* chip;
if (paddle % 2 == 0) {
chip = &chip_top;
} else {
chip = &chip_bot;
}
ad714x_i2c_read(chip, 0xB, data, 12);
//ESP_LOGI(TAG, "CDC results: %X %X %X %X %X %X %X %X %X %X %X %X", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11]);
for(int stage=0; stage<12; stage++) {
ad714x_i2c_read(chip, 0x0F1 + stage * (0x104 - 0xE0), &ambient[stage], 1);
//ESP_LOGI(TAG, "stage %d ambient: %X diff: %d", stage, ambient[stage], data[stage] - ambient[stage]);
}
int diff1 = data[paddle_info_1[paddle]] - ambient[paddle_info_1[paddle]];
int diff2 = data[paddle_info_2[paddle]] - ambient[paddle_info_2[paddle]];
ESP_LOGI(TAG, "%10d %10d", diff1, diff2);
int vectors[][2] = {{240, 240}, {240, 0}, {0, 120}};
total = ((diff1) + (diff2));
result[0] = vectors[0][0] * (diff1) + vectors[1][0] * (diff2);
result[1] = vectors[0][1] * (diff1) + vectors[1][1] * (diff2);
*x = result[0] / total;
*y = result[1] / total;
}