From 096e5f6948c7fe8b63d8666b45c06ade58f8f9f3 Mon Sep 17 00:00:00 2001 From: whowechina Date: Fri, 5 Apr 2024 20:55:27 +0800 Subject: [PATCH] Touch remap working. --- Production/firmware/mai_pico.uf2 | Bin 120320 -> 143360 bytes firmware/src/board_defs.h | 2 +- firmware/src/commands.c | 83 ++++++++++++++++++++++++++++++- firmware/src/config.h | 2 +- firmware/src/touch.c | 63 ++++++++++++++++++++--- firmware/src/touch.h | 8 ++- 6 files changed, 145 insertions(+), 13 deletions(-) diff --git a/Production/firmware/mai_pico.uf2 b/Production/firmware/mai_pico.uf2 index fcaaf034acb488f2cc173898613f9f44dec7f7ae..b7961b3145b70c58df82cf11ece9de71590f7b5b 100644 GIT binary patch delta 36593 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 COY8ao diff --git a/firmware/src/board_defs.h b/firmware/src/board_defs.h index 0d498c2..aa365f2 100644 --- a/firmware/src/board_defs.h +++ b/firmware/src/board_defs.h @@ -24,7 +24,7 @@ #define TOUCH_MAP { E3, A2, B2, D2, E2, A1, B1, D1, E1, C2, A8, B8, \ D8, E8, A7, B7, D7, E7, A6, B6, D6, E6, A5, B5, \ - D5, E5, C1, A4, B4, D4, E4, A3, B3, D3 } + D5, E5, C1, A4, B4, D4, E4, A3, B3, D3, XX, XX } #else #endif diff --git a/firmware/src/commands.c b/firmware/src/commands.c index 4242557..1750a4e 100644 --- a/firmware/src/commands.c +++ b/firmware/src/commands.c @@ -9,6 +9,7 @@ #include "tusb.h" +#include "mpr121.h" #include "touch.h" #include "button.h" #include "config.h" @@ -16,6 +17,7 @@ #include "cli.h" #include "aime.h" +#include "nfc.h" #define SENSE_LIMIT_MAX 9 #define SENSE_LIMIT_MIN -9 @@ -66,6 +68,7 @@ static void disp_hid() static void disp_aime() { printf("[AIME]\n"); + printf(" NFC Module: %s\n", nfc_module_name()); printf(" Virtual AIC: %s\n", mai_cfg->aime.virtual_aic ? "ON" : "OFF"); } @@ -81,6 +84,21 @@ static void disp_gpio() button_real_gpio(10), button_real_gpio(11)); } +static void disp_touch() +{ + printf("[Touch]\n"); + printf(" ADDR|_0|_1|_2|_3|_4|_5|_6|_7|_8|_9|10|11|\n"); + + for (int m = 0; m < 3; m++) { + printf(" %d: 0x%02x|", m, MPR121_BASE_ADDR + m); + for (int chn = 0; chn < 12; chn++) { + int key = touch_key_from_channel(m * 12 + chn); + printf("%2s|", touch_key_name(key)); + } + printf("\n"); + } +} + void handle_display(int argc, char *argv[]) { const char *usage = "Usage: display [rgb|sense|hid|gpio|aime]\n"; @@ -94,12 +112,13 @@ void handle_display(int argc, char *argv[]) disp_sense(); disp_hid(); disp_gpio(); + disp_touch(); disp_aime(); return; } - const char *choices[] = {"rgb", "sense", "hid", "gpio", "aime"}; - switch (cli_match_prefix(choices, 5, argv[0])) { + const char *choices[] = {"rgb", "sense", "hid", "gpio", "touch", "aime"}; + switch (cli_match_prefix(choices, 6, argv[0])) { case 0: disp_rgb(); break; @@ -113,6 +132,9 @@ void handle_display(int argc, char *argv[]) disp_gpio(); break; case 4: + disp_touch(); + break; + case 5: disp_aime(); break; default: @@ -456,6 +478,62 @@ static void handle_gpio(int argc, char *argv[]) disp_gpio(); } +static void detect_touch() +{ + bool touched = false; + for (int i = 0; i < 34; i++) { + if (touch_touched(i)) { + touched = true; + printf("Touched: %s", touch_key_name(i)); + uint8_t pad = touch_key_channel(i); + if (pad >= 0) { + printf(" (Sensor %d, Electrode %d)\n", pad / 12, pad % 12 + 1); + } else { + printf(" (nil)\n"); + } + } + } + if (!touched) { + printf("No touch detected.\n"); + } +} + +static bool set_touch_map(int argc, char *argv[]) +{ + if (argc != 3) { + return false; + } + if (strlen(argv[2]) != 2) { + return false; + } + int sensor = cli_extract_non_neg_int(argv[0], 0); + int channel = cli_extract_non_neg_int(argv[1], 0); + int key = touch_key_by_name(argv[2]); + + if ((sensor < 0) || (sensor > 2) || + (channel < 0) || (channel > 11) || + (key < 0)) { + return false; + } + touch_set_map(sensor * 12 + channel, key); + return true; +} + +static void handle_touch(int argc, char *argv[]) +{ + const char *usage = "Usage: touch [ ]\n" + " sensor: 0..2\n" + " channel: 0..11\n" + " key: A1, C2, E5, etc. XX means Not Connected.)\n"; + if (argc == 0) { + detect_touch(); + } else if (set_touch_map(argc, argv)) { + disp_touch(); + } else { + printf(usage); + } +} + static void handle_virtual(int argc, char *argv[]) { const char *usage = "Usage: virtual \n"; @@ -491,6 +569,7 @@ void commands_init() cli_register("whoami", handle_whoami, "Identify each com port."); cli_register("save", handle_save, "Save config to flash."); cli_register("gpio", handle_gpio, "Set GPIO pins for buttons."); + cli_register("touch", handle_touch, "Custimze touch mapping."); cli_register("factory", config_factory_reset, "Reset everything to default."); cli_register("virtual", handle_virtual, "Virtual AIC card on AIME."); } diff --git a/firmware/src/config.h b/firmware/src/config.h index 7a65cb9..7f0e7f0 100644 --- a/firmware/src/config.h +++ b/firmware/src/config.h @@ -34,7 +34,7 @@ typedef struct __attribute__((packed)) { } rgb; struct { uint8_t buttons[12]; - uint8_t touch[34]; + uint8_t touch[36]; } alt; struct { bool virtual_aic; diff --git a/firmware/src/touch.c b/firmware/src/touch.c index 43dd772..39ccc2a 100644 --- a/firmware/src/touch.c +++ b/firmware/src/touch.c @@ -9,6 +9,7 @@ #include #include +#include #include #include "bsp/board.h" @@ -40,21 +41,69 @@ void touch_init() memcpy(touch_map, mai_cfg->alt.touch, sizeof(touch_map)); } -const char *touch_pad_name(unsigned i) +const char *touch_key_name(unsigned key) { static char name[3] = { 0 }; - if (i < 18) { - name[0] = "ABC"[i / 8]; - name[1] = '1' + i % 8; - } else if (i < 34) { - name[0] = "DE"[(i - 18) / 8]; - name[1] = '1' + (i - 18) % 8; + if (key < 18) { + name[0] = "ABC"[key / 8]; + name[1] = '1' + key % 8; + } else if (key < 34) { + name[0] = "DE"[(key - 18) / 8]; + name[1] = '1' + (key - 18) % 8; } else { return "XX"; } return name; } +int touch_key_by_name(const char *name) +{ + if (strlen(name) != 2) { + return -1; + } + if (strcasecmp(name, "XX") == 0) { + return 255; + } + + int zone = toupper(name[0]) - 'A'; + int id = name[1] - '1'; + if ((zone < 0) || (zone > 4) || (id < 0) || (id > 7)) { + return -1; + } + if ((zone == 2) && (id > 1)) { + return -1; // C1 and C2 only + } + const int offsets[] = { 0, 8, 16, 18, 26 }; + return offsets[zone] + id; +} + +int touch_key_channel(unsigned key) +{ + for (int i = 0; i < 36; i++) { + if (touch_map[i] == key) { + return i; + } + } + return -1; +} + +unsigned touch_key_from_channel(unsigned channel) +{ + if (channel < 36) { + return touch_map[channel]; + } + return 0xff; +} + +void touch_set_map(unsigned sensor, unsigned key) +{ + if (sensor < 36) { + touch_map[sensor] = key; + memcpy(mai_cfg->alt.touch, touch_map, sizeof(mai_cfg->alt.touch)); + config_changed(); + } +} + static uint64_t touch_reading; static void remap_reading() diff --git a/firmware/src/touch.h b/firmware/src/touch.h index 879d831..c8c2605 100644 --- a/firmware/src/touch.h +++ b/firmware/src/touch.h @@ -9,7 +9,7 @@ #include #include -enum touch_pads { +enum touch_keys { A1 = 0, A2, A3, A4, A5, A6, A7, A8, B1, B2, B3, B4, B5, B6, B7, B8, C1, C2, D1, D2, D3, D4, D5, D6, D7, D8, @@ -17,12 +17,16 @@ enum touch_pads { XX = 255 }; -const char *touch_pad_name(unsigned i); +const char *touch_key_name(unsigned key); +int touch_key_by_name(const char *name); +int touch_key_channel(unsigned key); +unsigned touch_key_from_channel(unsigned channel); void touch_init(); void touch_update(); bool touch_touched(unsigned key); uint64_t touch_touchmap(); +void touch_set_map(unsigned sensor, unsigned key); const uint16_t *touch_raw(); bool touch_sensor_ok(unsigned i);