From 01af8484b1c99cd0d806641554d70d70b4de19c3 Mon Sep 17 00:00:00 2001 From: Adam Benhassen Date: Sat, 7 Mar 2026 21:46:17 +0100 Subject: [PATCH] feat: add M5Stack Cardputer ADV board support Add support for the M5Stack Cardputer ADV hardware variant, which replaces the original GPIO matrix keyboard with a TCA8418 I2C keypad controller. Changes: - Vendor Adafruit_TCA8418 library for I2C keyboard communication - Add MARAUDER_CARDPUTER_ADV board target with feature flags in configs.h - Implement TCA8418 keyboard driver with interrupt-driven FIFO scanning, coordinate remapping (verified against M5Cardputer-UserDemo-ADV), and persistent key state tracking for compatibility with menu polling - Extend all MARAUDER_CARDPUTER preprocessor guards to include ADV variant - Add TFT_eSPI display configuration (same display as original Cardputer) - Add CI build matrix entries for both parallel and nightly workflows --- .github/workflows/build_parallel.yml | 9 +- .github/workflows/nightly_build.yml | 9 +- User_Setup_Select.h | 1 + User_Setup_marauder_m5cardputer_adv.h | 328 +++++++++++++++ esp32_marauder/Keyboard.cpp | 85 ++++ esp32_marauder/Keyboard.h | 18 +- esp32_marauder/Keyboard_def.h | 2 +- esp32_marauder/MenuFunctions.cpp | 42 +- esp32_marauder/MenuFunctions.h | 4 +- esp32_marauder/SDInterface.cpp | 6 +- esp32_marauder/SDInterface.h | 2 +- esp32_marauder/configs.h | 17 +- esp32_marauder/esp32_marauder.ino | 2 +- .../Adafruit_TCA8418/Adafruit_TCA8418.cpp | 392 ++++++++++++++++++ libraries/Adafruit_TCA8418/Adafruit_TCA8418.h | 104 +++++ .../Adafruit_TCA8418_registers.h | 94 +++++ 16 files changed, 1074 insertions(+), 41 deletions(-) create mode 100644 User_Setup_marauder_m5cardputer_adv.h create mode 100644 libraries/Adafruit_TCA8418/Adafruit_TCA8418.cpp create mode 100644 libraries/Adafruit_TCA8418/Adafruit_TCA8418.h create mode 100644 libraries/Adafruit_TCA8418/Adafruit_TCA8418_registers.h diff --git a/.github/workflows/build_parallel.yml b/.github/workflows/build_parallel.yml index b939ec2..db440e6 100644 --- a/.github/workflows/build_parallel.yml +++ b/.github/workflows/build_parallel.yml @@ -34,7 +34,8 @@ jobs: - { name: "Marauder CYD 2432S024 GUITION", flag: "MARAUDER_CYD_GUITION", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_2432S024_guition", tft: true, tft_file: "User_Setup_cyd_guition.h", build_dir: "d32", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder CYD 2432S028 2 USB", flag: "MARAUDER_CYD_2USB", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_2432S028_2usb", tft: true, tft_file: "User_Setup_cyd_2usb.h", build_dir: "d32", addr: "0x1000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder CYD 3.5inch", flag: "MARAUDER_CYD_3_5_INCH", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_3_5_inch", tft: true, tft_file: "User_Setup_cyd_3_5_inch.h", build_dir: "d32", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - - { name: "M5Cardputer", flag: "MARAUDER_CARDPUTER", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer", tft: true, tft_file: "User_Setup_marauder_m5cardputer.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } + - { name: "M5Cardputer", flag: "MARAUDER_CARDPUTER", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer", tft: true, tft_file: "User_Setup_marauder_m5cardputer.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } + - { name: "M5Cardputer ADV", flag: "MARAUDER_CARDPUTER_ADV", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer_adv", tft: true, tft_file: "User_Setup_marauder_m5cardputer_adv.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "ESP32-C5-DevKitC-1", flag: "MARAUDER_C5", fbqn: "esp32:esp32:esp32c5:FlashSize=8M,PartitionScheme=min_spiffs,PSRAM=enabled", file_name: "esp32c5devkitc1", tft: false, tft_file: "", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } steps: @@ -179,7 +180,10 @@ jobs: repository: adafruit/Adafruit_MAX1704X ref: 1.0.2 path: CustomAdafruit_MAX1704X - + + - name: Install Adafruit_TCA8418 + run: cp -r libraries/Adafruit_TCA8418 CustomAdafruit_TCA8418 + - name: Show Libraries run: | find /home/runner/ -name "Custom*" @@ -323,6 +327,7 @@ jobs: | RL Phantom | `_cyd_2432S024_guition.bin` | | CYD 2432S028 2 USB | `_cyd_2432S028_2usb.bin` | | M5 Cardputer | `_m5cardputer.bin` (Available on M5 Burner) | + | M5 Cardputer ADV | `_m5cardputer_adv.bin` | | ESP32-C5 DevKit | [`_esp32c5_devkit.bin`](https://github.com/justcallmekoko/ESP32Marauder/wiki/ESP32%E2%80%90C5%E2%80%90DevKitC%E2%80%901) | | AWOK V2/V3 screen (white usb) | `_v6_1.bin` | | AWOK V2 flipper (orange usb) | `_flipper.bin` | diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml index bbb41d9..fb050a0 100644 --- a/.github/workflows/nightly_build.yml +++ b/.github/workflows/nightly_build.yml @@ -97,7 +97,8 @@ jobs: - { name: "Marauder CYD 2432S024 GUITION", flag: "MARAUDER_CYD_GUITION", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_2432S024_guition", tft: true, tft_file: "User_Setup_cyd_guition.h", build_dir: "d32", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder CYD 2432S028 2 USB", flag: "MARAUDER_CYD_2USB", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_2432S028_2usb", tft: true, tft_file: "User_Setup_cyd_2usb.h", build_dir: "d32", addr: "0x1000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "Marauder CYD 3.5inch", flag: "MARAUDER_CYD_3_5_INCH", fbqn: "esp32:esp32:d32:PartitionScheme=min_spiffs", file_name: "cyd_3_5_inch", tft: true, tft_file: "User_Setup_cyd_3_5_inch.h", build_dir: "d32", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - - { name: "M5Cardputer", flag: "MARAUDER_CARDPUTER", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer", tft: true, tft_file: "User_Setup_marauder_m5cardputer.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } + - { name: "M5Cardputer", flag: "MARAUDER_CARDPUTER", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer", tft: true, tft_file: "User_Setup_marauder_m5cardputer.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } + - { name: "M5Cardputer ADV", flag: "MARAUDER_CARDPUTER_ADV", fbqn: "esp32:esp32:esp32s3:PartitionScheme=min_spiffs,FlashSize=8M,PSRAM=disabled", file_name: "m5cardputer_adv", tft: true, tft_file: "User_Setup_marauder_m5cardputer_adv.h", build_dir: "esp32s3", addr: "0x1000", idf_ver: "2.0.11", nimble_ver: "1.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } - { name: "ESP32-C5-DevKitC-1", flag: "MARAUDER_C5", fbqn: "esp32:esp32:esp32c5:FlashSize=8M,PartitionScheme=min_spiffs,PSRAM=enabled", file_name: "esp32c5devkitc1", tft: false, tft_file: "", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "master", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } steps: @@ -233,7 +234,10 @@ jobs: repository: adafruit/Adafruit_MAX1704X ref: 1.0.2 path: CustomAdafruit_MAX1704X - + + - name: Install Adafruit_TCA8418 + run: cp -r libraries/Adafruit_TCA8418 CustomAdafruit_TCA8418 + - name: Show Libraries run: | find /home/runner/ -name "Custom*" @@ -415,6 +419,7 @@ jobs: | RL Phantom | `_cyd_2432S024_guition.bin` | | CYD 2432S028 2 USB | `_cyd_2432S028_2usb.bin` | | M5 Cardputer | `_m5cardputer.bin` (Available on M5 Burner) | + | M5 Cardputer ADV | `_m5cardputer_adv.bin` | | ESP32-C5 DevKit | [`_esp32c5_devkit.bin`](https://github.com/justcallmekoko/ESP32Marauder/wiki/ESP32%E2%80%90C5%E2%80%90DevKitC%E2%80%901) | | AWOK V2/V3 screen (white usb) | `_v6_1.bin` | | AWOK V2 flipper (orange usb) | `_flipper.bin` | diff --git a/User_Setup_Select.h b/User_Setup_Select.h index 8eefd12..06b89de 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -35,6 +35,7 @@ //#include //#include //#include +//#include //#include //#include // Setup file configured for my ILI9341 diff --git a/User_Setup_marauder_m5cardputer_adv.h b/User_Setup_marauder_m5cardputer_adv.h new file mode 100644 index 0000000..4427beb --- /dev/null +++ b/User_Setup_marauder_m5cardputer_adv.h @@ -0,0 +1,328 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded, pins used and SPI control method etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! +// Note that some sketches are designed for a particular TFT pixel width/height + + +// ################################################################################## +// +// Section 1. Call up the right driver file and any options for it +// +// ################################################################################## + +// Display type - only define if RPi display +//#define RPI_DRIVER + +#define CGRAM_OFFSET + +// Only define one driver, the other ones must be commented out +//#define ILI9341_DRIVER // OG Marauder +//#define ST7735_DRIVER // Marauder Mini // Define additional parameters below for this display +//#define ILI9163_DRIVER // Define additional parameters below for this display +//#define S6D02A1_DRIVER +//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI +//#define HX8357D_DRIVER +//#define ILI9481_DRIVER +//#define ILI9486_DRIVER +//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high) +//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display +#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display +//#define R61581_DRIVER +//#define RM68140_DRIVER +//#define ST7796_DRIVER + +// Some displays support SPI reads via the MISO pin, other displays have a single +// bi-directional SDA pin and the library will try to read this via the MOSI line. +// To use the SDA line for reading data from the TFT uncomment the following line: + +// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 display only + +// For ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display +// Try ONE option at a time to find the correct colour order for your display + + #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + +// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below + +// #define M5STACK + +// For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +// #define TFT_WIDTH 80 + #define TFT_WIDTH 135 // Marauder Mini +// #define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320 +// #define TFT_HEIGHT 160 + #define TFT_HEIGHT 240 // Marauder Mini +// #define TFT_HEIGHT 240 // ST7789 240 x 240 +// #define TFT_HEIGHT 320 // ST7789 240 x 320 + +// For ST7735 ONLY, define the type of display, originally this was based on the +// colour of the tab on the screen protector film but this is not always true, so try +// out the different options below if the screen does not display graphics correctly, +// e.g. colours wrong, mirror images, or tray pixels at the edges. +// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this +// this User_Setup file, then rebuild and upload the sketch to the board again: + +// #define ST7735_INITB +// #define ST7735_GREENTAB +// #define ST7735_GREENTAB2 +// #define ST7735_GREENTAB3 +// #define ST7735_GREENTAB128 // For 128 x 128 display +// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) +// #define ST7735_REDTAB +// #define ST7735_BLACKTAB +// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset + +// If colours are inverted (white shows as black) then uncomment one of the next +// 2 lines try both options, one of the options should correct the inversion. + +// #define TFT_INVERSION_ON +// #define TFT_INVERSION_OFF + +// If a backlight control signal is available then define the TFT_BL pin in Section 2 +// below. The backlight will be turned ON when tft.begin() is called, but the library +// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be +// driven with a PWM signal or turned OFF/ON then this must be handled by the user +// sketch. e.g. with digitalWrite(TFT_BL, LOW); + + #define TFT_BACKLIGHT_ON HIGH // HIGH or LOW are options + +// ################################################################################## +// +// Section 2. Define the pins that are used to interface with the display here +// +// ################################################################################## + +// We must use hardware SPI, a minimum of 3 GPIO pins is needed. +// Typical setup for ESP8266 NodeMCU ESP-12 is : +// +// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) +// Display LED to NodeMCU pin VIN (or 5V, see below) +// Display SCK to NodeMCU pin D5 +// Display SDI/MOSI to NodeMCU pin D7 +// Display DC (RS/AO)to NodeMCU pin D3 +// Display RESET to NodeMCU pin D4 (or RST, see below) +// Display CS to NodeMCU pin D8 (or GND, see below) +// Display GND to NodeMCU pin GND (0V) +// Display VCC to NodeMCU 5V or 3.3V +// +// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin +// +// The DC (Data Command) pin may be labeled AO or RS (Register Select) +// +// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more +// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS +// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin +// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. +// +// The NodeMCU D0 pin can be used for RST +// +// +// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin +// If 5V is not available at a pin you can use 3.3V but backlight brightness +// will be lower. + + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +//#define TFT_CS PIN_D8 // Chip select control pin D8 +//#define TFT_DC PIN_D3 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) + +//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. It is best not to connect MISO as some displays +// do not tristate that line wjen chip select is high! +// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode +// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK +// In ESP8266 overlap mode the following must be defined + +//#define TFT_SPI_OVERLAP + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +// M5 Cardputer ADV +#define TFT_BL 38 +#define TFT_RST 33 // Reset pin (could connect to NodeMCU RST, see next line) +#define TFT_DC 34 // Data Command control pin +#define TFT_MOSI 35 +#define TFT_SCLK 36 +#define TFT_CS 37 // Chip select control pin D8 +#define TOUCH_CS -1 +// #define TFT_MISO -1 + +// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) +// Display LED to NodeMCU pin VIN (or 5V, see below) +// Display SCK to NodeMCU pin D5 +// Display SDI/MOSI to NodeMCU pin D7 +// Display DC (RS/AO)to NodeMCU pin D3 +// Display RESET to NodeMCU pin D4 (or RST, see below) +// Display CS to NodeMCU pin D8 (or GND, see below) +// Display GND to NodeMCU pin GND (0V) +// Display VCC to NodeMCU 5V or 3.3V + +/* +// ESP32 Marauder +#define TFT_MISO 19 +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 17 // Chip select control pin +#define TFT_DC 16 // Data Command control pin +#define TFT_RST 5 // Reset pin (could connect to RST pin) +//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + +#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) + +#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen +*/ +///////////////////////////// + +// ESP32 Centauri +/* +#define TFT_MISO 19 +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 27 // Chip select control pin +#define TFT_DC 26 // Data Command control pin +#define TFT_RST 5 // Reset pin (could connect to RST pin) +//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + +#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) + +#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen +*/ +///////////////////////////// + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light (required for M5Stack) + +// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### + +// The library supports 8 bit parallel TFTs with the ESP32, the pin +// selection below is compatible with ESP32 boards in UNO format. +// Wemos D32 boards need to be modified, see diagram in Tools folder. +// Only ILI9481 and ILI9341 based displays have been tested! + +// Parallel bus is only supported on ESP32 +// Uncomment line below to use ESP32 Parallel interface instead of SPI + +//#define ESP32_PARALLEL + +// The ESP32 and TFT the pins used for testing are: +//#define TFT_CS 33 // Chip select control pin (library pulls permanently low +//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 +//#define TFT_RST 32 // Reset pin, toggles on startup + +//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 +//#define TFT_RD 2 // Read strobe control pin + +//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus +//#define TFT_D1 13 // so a single register write sets/clears all bits. +//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect +//#define TFT_D3 25 // TFT screen update performance. +//#define TFT_D4 17 +//#define TFT_D5 16 +//#define TFT_D6 27 +//#define TFT_D7 14 + + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + + +// ################################################################################## +// +// Section 4. Other options +// +// ################################################################################## + +// Define the SPI clock frequency, this affects the graphics rendering speed. Too +// fast and the TFT driver will not keep up and display corruption appears. +// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails +// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) +// With an ILI9163 display 27 MHz works OK. + +// #define SPI_FREQUENCY 1000000 +//#define SPI_FREQUENCY 5000000 +// #define SPI_FREQUENCY 10000000 + #define SPI_FREQUENCY 20000000 +//#define SPI_FREQUENCY 27000000 // Marauder // Actually sets it to 26.67MHz = 80/3 +// #define SPI_FREQUENCY 40000000 +// #define SPI_FREQUENCY 80000000 + +// Optional reduced SPI frequency for reading TFT +#define SPI_READ_FREQUENCY 20000000 + +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + +// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default. +// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam) +// then uncomment the following line: +//#define USE_HSPI_PORT + +// Comment out the following #define if "SPI Transactions" do not need to be +// supported. When commented out the code size will be smaller and sketches will +// run slightly faster, so leave it commented out unless you need it! + +// Transaction support is needed to work with SD library but not needed with TFT_SdFat +// Transaction support is required if other SPI devices are connected. + +// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) +// so changing it here has no effect + +// #define SUPPORT_TRANSACTIONS \ No newline at end of file diff --git a/esp32_marauder/Keyboard.cpp b/esp32_marauder/Keyboard.cpp index 5d47a9e..a8e1bfe 100644 --- a/esp32_marauder/Keyboard.cpp +++ b/esp32_marauder/Keyboard.cpp @@ -1,5 +1,7 @@ #include "Keyboard.h" +#if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) + #ifdef MARAUDER_CARDPUTER #include #include @@ -31,9 +33,19 @@ uint8_t Keyboard_Class::_get_input(const std::vector &pinList) return buffer; } +#endif + +#ifdef MARAUDER_CARDPUTER_ADV +volatile bool Keyboard_Class::_tca_interrupt = false; + +void IRAM_ATTR Keyboard_Class::_tca_isr() { + _tca_interrupt = true; +} +#endif void Keyboard_Class::begin() { +#ifdef MARAUDER_CARDPUTER for (auto i : output_list) { gpio_reset_pin((gpio_num_t)i); @@ -50,6 +62,20 @@ void Keyboard_Class::begin() } _set_output(output_list, 0); +#elif defined(MARAUDER_CARDPUTER_ADV) + Wire.begin(8, 9); // SDA=GPIO8, SCL=GPIO9 + _tca_initialized = _tca8418.begin(TCA8418_DEFAULT_ADDR, &Wire); + if (_tca_initialized) { + _tca8418.matrix(7, 8); // 7 rows x 8 cols + _tca8418.flush(); + _tca8418.enableInterrupts(); + pinMode(11, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(11), _tca_isr, FALLING); + _tca_interrupt = true; // Force initial scan + } else { + Serial.println("[ERROR] TCA8418 keyboard not found on I2C (addr 0x34)"); + } +#endif } uint8_t Keyboard_Class::getKey(Point2D_t keyCoor) @@ -76,6 +102,8 @@ void Keyboard_Class::updateKeyList() { _key_list_buffer.clear(); Point2D_t coor; + +#ifdef MARAUDER_CARDPUTER uint8_t input_value = 0; for (int i = 0; i < 8; i++) @@ -106,6 +134,63 @@ void Keyboard_Class::updateKeyList() } } } +#elif defined(MARAUDER_CARDPUTER_ADV) + if (!_tca_initialized) return; + + // Drain TCA8418 FIFO when interrupt signals new events + if (_tca_interrupt) { + _tca_interrupt = false; + + int evt; + while ((evt = _tca8418.getEvent()) != 0) { + // Bit 7 = 1 means key press per TCA8418 datasheet (SCPS162). + // Note: the vendored Adafruit library comments have this backwards. + bool pressed = (evt & 0x80) != 0; + int key = (evt & 0x7F) - 1; // Convert from 1-indexed key code to 0-indexed + if (key < 0 || key >= 70) continue; + // TCA8418 uses 10-column stride internally + int row = key / 10; + int col = key % 10; + if (row >= 7 || col >= 8) continue; + + // Remap to match _key_value_map[4][14] coordinate system + coor.x = (row * 2) + (col > 3 ? 1 : 0); + coor.y = col % 4; + + if (coor.x >= 14 || coor.y >= 4) continue; + + if (pressed) { + // Prevent duplicate tracking (e.g. on missed release event) + bool already = false; + for (auto &k : _tca_pressed_keys) { + if (k.x == coor.x && k.y == coor.y) { already = true; break; } + } + if (!already) _tca_pressed_keys.push_back(coor); + } else { + // Remove released key from tracked state + for (auto it = _tca_pressed_keys.begin(); it != _tca_pressed_keys.end(); ++it) { + if (it->x == coor.x && it->y == coor.y) { + _tca_pressed_keys.erase(it); + break; + } + } + } + } + // Check for FIFO overflow (bit 3) and recover + uint8_t int_stat = _tca8418.readRegister(TCA8418_REG_INT_STAT); + if (int_stat & 0x08) { + _tca8418.flush(); + _tca_pressed_keys.clear(); + } + // Clear all INT_STAT bits so the INT pin deasserts and can fire again + _tca8418.writeRegister(TCA8418_REG_INT_STAT, 0x0F); + } + + // Always populate buffer from currently-held keys + for (auto &k : _tca_pressed_keys) { + _key_list_buffer.push_back(k); + } +#endif } uint8_t Keyboard_Class::isPressed() diff --git a/esp32_marauder/Keyboard.h b/esp32_marauder/Keyboard.h index ea983f0..7ae991c 100644 --- a/esp32_marauder/Keyboard.h +++ b/esp32_marauder/Keyboard.h @@ -5,7 +5,7 @@ #include "configs.h" -#ifdef MARAUDER_CARDPUTER +#if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) /** * @file keyboard.h @@ -23,6 +23,11 @@ #include "Keyboard_def.h" #include "configs.h" +#ifdef MARAUDER_CARDPUTER_ADV +#include +#include "Adafruit_TCA8418.h" +#endif + struct Chart_t { uint8_t value; @@ -36,10 +41,12 @@ struct Point2D_t int y; }; +#ifdef MARAUDER_CARDPUTER const std::vector output_list = {8, 9, 11}; const std::vector input_list = {13, 15, 3, 4, 5, 6, 7}; const Chart_t X_map_chart[7] = {{1, 0, 1}, {2, 2, 3}, {4, 4, 5}, {8, 6, 7}, {16, 8, 9}, {32, 10, 11}, {64, 12, 13}}; +#endif struct KeyValue_t { @@ -152,8 +159,17 @@ private: bool _is_caps_locked; uint8_t _last_key_size; +#ifdef MARAUDER_CARDPUTER void _set_output(const std::vector &pinList, uint8_t output); uint8_t _get_input(const std::vector &pinList); +#endif +#ifdef MARAUDER_CARDPUTER_ADV + Adafruit_TCA8418 _tca8418; + bool _tca_initialized = false; + static volatile bool _tca_interrupt; + static void IRAM_ATTR _tca_isr(); + std::vector _tca_pressed_keys; // Currently held keys +#endif public: const char _ascii_list[95] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p', diff --git a/esp32_marauder/Keyboard_def.h b/esp32_marauder/Keyboard_def.h index e1da6d8..06d505c 100644 --- a/esp32_marauder/Keyboard_def.h +++ b/esp32_marauder/Keyboard_def.h @@ -3,7 +3,7 @@ #include "configs.h" -#ifdef MARAUDER_CARDPUTER +#if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) #define SHIFT 0x80 diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp index 7fe777a..3963314 100644 --- a/esp32_marauder/MenuFunctions.cpp +++ b/esp32_marauder/MenuFunctions.cpp @@ -307,9 +307,9 @@ void MenuFunctions::main(uint32_t currentTime) #ifdef HAS_BUTTONS - #if (C_BTN >= 0) && !defined(MARAUDER_CARDPUTER) + #if (C_BTN >= 0) && !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV) bool c_btn_press = c_btn.justPressed(); - #elif defined(MARAUDER_CARDPUTER) + #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) bool c_btn_press = this->isKeyPressed('('); #endif @@ -651,10 +651,10 @@ void MenuFunctions::main(uint32_t currentTime) // Don't do this for touch screens #if !(defined(MARAUDER_V6) || defined(MARAUDER_V6_1) || defined(MARAUDER_CYD_MICRO) || defined(MARAUDER_CYD_GUITION) || defined(MARAUDER_CYD_2USB) || defined(MARAUDER_CYD_3_5_INCH)) #if !defined(MARAUDER_M5STICKC) || defined(MARAUDER_M5STICKCP2) - #if (U_BTN >= 0 || defined(MARAUDER_CARDPUTER)) + #if (U_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)) #if (U_BTN >= 0) if (u_btn.justPressed()) { - #elif defined(MARAUDER_CARDPUTER) + #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) if (this->isKeyPressed(';')) { #endif if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) || @@ -722,10 +722,10 @@ void MenuFunctions::main(uint32_t currentTime) #endif #endif - #if (D_BTN >= 0 || defined(MARAUDER_CARDPUTER)) + #if (D_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)) #if (D_BTN >= 0) if (d_btn.justPressed()){ - #elif defined(MARAUDER_CARDPUTER) + #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) if (this->isKeyPressed('.')){ #endif if ((wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) || @@ -797,10 +797,10 @@ void MenuFunctions::main(uint32_t currentTime) } #endif - #if (R_BTN >= 0 || defined(MARAUDER_CARDPUTER)) + #if (R_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)) #if (R_BTN >= 0) if (r_btn.justPressed()) { - #elif defined(MARAUDER_CARDPUTER) + #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) if (this->isKeyPressed('/')) { #endif if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) { @@ -821,10 +821,10 @@ void MenuFunctions::main(uint32_t currentTime) } #endif - #if (L_BTN >= 0 || defined(MARAUDER_CARDPUTER)) + #if (L_BTN >= 0 || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)) #if (L_BTN >= 0) if (l_btn.justPressed()) { - #elif defined(MARAUDER_CARDPUTER) + #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) if (this->isKeyPressed(',')) { #endif if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) { @@ -964,10 +964,10 @@ void MenuFunctions::updateStatusBar() bool status_changed = false; - #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_MINI_V3) + #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(MARAUDER_MINI_V3) display_obj.tft.setFreeFont(NULL); #endif - + uint16_t the_color; #ifdef HAS_GPS @@ -1018,7 +1018,7 @@ void MenuFunctions::updateStatusBar() if ((current_channel != wifi_scan_obj.old_channel) || (status_changed)) { wifi_scan_obj.old_channel = current_channel; - #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_MINI_V3) + #if defined(MARAUDER_MINI) || defined(MARAUDER_M5STICKC) || defined(MARAUDER_REV_FEATHER) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(MARAUDER_MINI_V3) display_obj.tft.fillRect(TFT_WIDTH/4, 0, CHAR_WIDTH * 6, STATUS_BAR_WIDTH, STATUSBAR_COLOR); #elif defined(HAS_DUAL_BAND) display_obj.tft.fillRect(50, 0, (CHAR_WIDTH / 2) * 8, STATUS_BAR_WIDTH, STATUSBAR_COLOR); @@ -1415,7 +1415,7 @@ void MenuFunctions::displaySetting(String key, Menu* menu, int index) { } -#ifdef MARAUDER_CARDPUTER +#if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) bool MenuFunctions::isKeyPressed(char c) { M5CardputerKeyboard.updateKeyList(); @@ -1441,7 +1441,7 @@ void MenuFunctions::RunSetup() this->disable_touch = false; - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) M5CardputerKeyboard.begin(); #endif @@ -2120,7 +2120,7 @@ void MenuFunctions::RunSetup() //#if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS)) miniKbMenu.parentMenu = &wifiGeneralMenu; - #ifndef MARAUDER_CARDPUTER + #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV) this->addNodes(&miniKbMenu, "a", TFTCYAN, NULL, 0, [this]() { this->changeMenu(miniKbMenu.parentMenu, true); }); @@ -3071,7 +3071,7 @@ void MenuFunctions::RunSetup() #endif // Add SSID - #ifdef HAS_C && !defined(MARAUDER_CARDPUTER) + #if defined(HAS_C) && !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV) if (c_btn.justPressed()) { while (!c_btn.justReleased()) { c_btn.justPressed(); // Need to continue updating button hold status. My shitty library. @@ -3097,7 +3097,7 @@ void MenuFunctions::RunSetup() #endif #endif - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) for (int i = 0; i < 95; i++) { if ((M5CardputerKeyboard._ascii_list[i] != '(') && (M5CardputerKeyboard._ascii_list[i] != '`')) { @@ -3285,12 +3285,12 @@ void MenuFunctions::RunSetup() display_obj.tft.setTextColor(TFT_ORANGE, TFT_BLACK); #ifdef HAS_MINI_KB - #ifndef MARAUDER_CARDPUTER + #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV) display_obj.tft.println("U/D - Rem/Add Char"); display_obj.tft.println("L/R - Prev/Nxt Char"); #endif if (!do_pass) { - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) display_obj.tft.println("Enter - Save"); display_obj.tft.println("Esc - Exit"); #else @@ -3299,7 +3299,7 @@ void MenuFunctions::RunSetup() #endif } else { - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) display_obj.tft.println("Enter - Enter"); #else display_obj.tft.println("C(Hold) - Enter"); diff --git a/esp32_marauder/MenuFunctions.h b/esp32_marauder/MenuFunctions.h index 121bf1c..8a74002 100644 --- a/esp32_marauder/MenuFunctions.h +++ b/esp32_marauder/MenuFunctions.h @@ -5,7 +5,7 @@ #include "configs.h" -#ifdef MARAUDER_CARDPUTER +#if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) #include "Keyboard.h" #endif @@ -230,7 +230,7 @@ class MenuFunctions #endif //#endif - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) Keyboard_Class M5CardputerKeyboard = Keyboard_Class(); bool isKeyPressed(char c); #endif diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp index e40bbbd..822c181 100644 --- a/esp32_marauder/SDInterface.cpp +++ b/esp32_marauder/SDInterface.cpp @@ -21,7 +21,7 @@ bool SDInterface::initSD() { pinMode(SD_CS, OUTPUT); delay(10); - #if (defined(MARAUDER_M5STICKC)) || (defined(HAS_CYD_TOUCH)) || (defined(MARAUDER_CARDPUTER)) + #if (defined(MARAUDER_M5STICKC)) || (defined(HAS_CYD_TOUCH)) || (defined(MARAUDER_CARDPUTER)) || (defined(MARAUDER_CARDPUTER_ADV)) /* Set up SPI SD Card using external pin header StickCPlus Header - SPI SD Card Reader 3v3 - 3v3 @@ -33,12 +33,12 @@ bool SDInterface::initSD() { */ #if defined(MARAUDER_M5STICKC) enum { SPI_SCK = 0, SPI_MISO = 36, SPI_MOSI = 26 }; - #elif defined(HAS_CYD_TOUCH) || defined(MARAUDER_CARDPUTER) || defined(HAS_SEPARATE_SD) + #elif defined(HAS_CYD_TOUCH) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) || defined(HAS_SEPARATE_SD) enum { SPI_SCK = SD_SCK, SPI_MISO = SD_MISO, SPI_MOSI = SD_MOSI }; #else enum { SPI_SCK = 0, SPI_MISO = 36, SPI_MOSI = 26 }; #endif - #ifndef MARAUDER_CARDPUTER + #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV) this->spiExt = new SPIClass(); #else this->spiExt = new SPIClass(FSPI); diff --git a/esp32_marauder/SDInterface.h b/esp32_marauder/SDInterface.h index cc9047d..efbaefb 100644 --- a/esp32_marauder/SDInterface.h +++ b/esp32_marauder/SDInterface.h @@ -36,7 +36,7 @@ extern Settings settings_obj; class SDInterface { private: - #if (defined(MARAUDER_M5STICKC) || defined(HAS_CYD_TOUCH) || defined(MARAUDER_CARDPUTER)) + #if (defined(MARAUDER_M5STICKC) || defined(HAS_CYD_TOUCH) || defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV)) SPIClass *spiExt; #elif defined(HAS_C5_SD) SPIClass* _spi; diff --git a/esp32_marauder/configs.h b/esp32_marauder/configs.h index 5bb0e5a..95e5f2d 100644 --- a/esp32_marauder/configs.h +++ b/esp32_marauder/configs.h @@ -31,6 +31,7 @@ //#define MARAUDER_CYD_3_5_INCH //#define MARAUDER_C5 //#define MARAUDER_CARDPUTER + //#define MARAUDER_CARDPUTER_ADV //#define MARAUDER_V8 //#define MARAUDER_MINI_V3 //#define DUAL_MINI_C5 @@ -61,6 +62,8 @@ #define HARDWARE_NAME "M5Stick-C Plus2" #elif defined(MARAUDER_CARDPUTER) #define HARDWARE_NAME "M5 Cardputer" + #elif defined(MARAUDER_CARDPUTER_ADV) + #define HARDWARE_NAME "M5 Cardputer ADV" #elif defined(MARAUDER_MINI) #define HARDWARE_NAME "Marauder Mini" #elif defined(MARAUDER_V7) @@ -130,7 +133,7 @@ #define HAS_GPS #endif - #if defined(MARAUDER_CARDPUTER) + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) //#define FLIPPER_ZERO_HAT #define HAS_MINI_KB //#define HAS_BATTERY @@ -643,7 +646,7 @@ #define D_PULL true #endif - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) #define L_BTN -1 #define C_BTN 0 #define U_BTN -1 @@ -969,7 +972,7 @@ #endif - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) #define CHAN_PER_PAGE 7 #define SCREEN_CHAR_WIDTH 40 @@ -2230,7 +2233,7 @@ #define BUTTON_PADDING 60 #endif - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) #define BANNER_TIME 50 #define COMMAND_PREFIX "!" @@ -2322,7 +2325,7 @@ #define SD_CS -1 #endif - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) //#define SS 12 #define SD_CS 12 #define SD_SCK 40 @@ -2423,7 +2426,7 @@ // These values are in bytes #ifdef MARAUDER_M5STICKC #define MEM_LOWER_LIM 10000 - #elif defined(MARAUDER_CARDPUTER) + #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) #define MEM_LOWER_LIM 10000 #elif defined(MARAUDER_MINI) #define MEM_LOWER_LIM 10000 @@ -2570,7 +2573,7 @@ #define GPS_SERIAL_INDEX 1 #define GPS_TX 33 #define GPS_RX 32 - #elif defined(MARAUDER_CARDPUTER) + #elif defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) #define GPS_SERIAL_INDEX 1 #define GPS_TX 1 #define GPS_RX 2 diff --git a/esp32_marauder/esp32_marauder.ino b/esp32_marauder/esp32_marauder.ino index 51bbbe2..3437006 100644 --- a/esp32_marauder/esp32_marauder.ino +++ b/esp32_marauder/esp32_marauder.ino @@ -314,7 +314,7 @@ void setup() #endif #ifdef HAS_SCREEN - #ifndef MARAUDER_CARDPUTER + #if !defined(MARAUDER_CARDPUTER) && !defined(MARAUDER_CARDPUTER_ADV) display_obj.tft.drawCentreString("ESP32 Marauder", TFT_WIDTH/2, TFT_HEIGHT * 0.33, 1); display_obj.tft.drawCentreString("JustCallMeKoko", TFT_WIDTH/2, TFT_HEIGHT * 0.5, 1); display_obj.tft.drawCentreString(display_obj.version_number, TFT_WIDTH/2, TFT_HEIGHT * 0.66, 1); diff --git a/libraries/Adafruit_TCA8418/Adafruit_TCA8418.cpp b/libraries/Adafruit_TCA8418/Adafruit_TCA8418.cpp new file mode 100644 index 0000000..8ab315f --- /dev/null +++ b/libraries/Adafruit_TCA8418/Adafruit_TCA8418.cpp @@ -0,0 +1,392 @@ +/** + * @file Adafruit_TCA8418.cpp + * + * @mainpage I2C Driver for the Adafruit TCA8418 Keypad Matrix / GPIO Expander + * Breakout + * + * @section intro_sec Introduction + * + * I2C Driver for the Adafruit TCA8418 Keypad Matrix / GPIO Expander + * Breakout + * + * This is a library for the Adafruit TCA8418 breakout: + * https://www.adafruit.com/product/XXXX + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing products from + * Adafruit! + * + * @section dependencies Dependencies + * This library depends on the Adafruit BusIO library + * + * @section author Author + * + * Limor Fried (Adafruit Industries) + * + * @section license License + * + * BSD (see license.txt) + * + * @section HISTORY + * + * v1.0 - First release + */ + +#include "Arduino.h" + +#include "Adafruit_TCA8418.h" + +/** + * @brief Instantiates a new TCA8418 class + */ +Adafruit_TCA8418::Adafruit_TCA8418(void) {} + +/** + * @brief destructor + */ +Adafruit_TCA8418::~Adafruit_TCA8418(void) {} + +/** + * @brief Sets up the hardware and initializes I2C + * @param address The I2C address for the expander + * @param wire The TwoWire object to be used for I2C connections. + * @return True if initialization was successful, otherwise false. + */ +bool Adafruit_TCA8418::begin(uint8_t address, TwoWire *wire) { + if (i2c_dev) { + delete i2c_dev; // remove old interface + } + + i2c_dev = new Adafruit_I2CDevice(address, wire); + + if (!i2c_dev->begin()) { + return false; + } + + // GPIO + // set default all GIO pins to INPUT + writeRegister(TCA8418_REG_GPIO_DIR_1, 0x00); + writeRegister(TCA8418_REG_GPIO_DIR_2, 0x00); + writeRegister(TCA8418_REG_GPIO_DIR_3, 0x00); + + // add all pins to key events + writeRegister(TCA8418_REG_GPI_EM_1, 0xFF); + writeRegister(TCA8418_REG_GPI_EM_2, 0xFF); + writeRegister(TCA8418_REG_GPI_EM_3, 0xFF); + + // set all pins to FALLING interrupts + writeRegister(TCA8418_REG_GPIO_INT_LVL_1, 0x00); + writeRegister(TCA8418_REG_GPIO_INT_LVL_2, 0x00); + writeRegister(TCA8418_REG_GPIO_INT_LVL_3, 0x00); + + // add all pins to interrupts + writeRegister(TCA8418_REG_GPIO_INT_EN_1, 0xFF); + writeRegister(TCA8418_REG_GPIO_INT_EN_2, 0xFF); + writeRegister(TCA8418_REG_GPIO_INT_EN_3, 0xFF); + + return true; +} + +/** + * @brief configures the size of the keypad matrix. + * + * @param [in] rows number of rows, should be <= 8 + * @param [in] columns number of columns, should be <= 10 + * @return true is rows and columns have valid values. + * + * @details will always use the lowest pins for rows and columns. + * 0..rows-1 and 0..columns-1 + */ +bool Adafruit_TCA8418::matrix(uint8_t rows, uint8_t columns) { + if ((rows > 8) || (columns > 10)) + return false; + + // MATRIX + // skip zero size matrix + if ((rows != 0) && (columns != 0)) { + // setup the keypad matrix. + uint8_t mask = 0x00; + for (int r = 0; r < rows; r++) { + mask <<= 1; + mask |= 1; + } + writeRegister(TCA8418_REG_KP_GPIO_1, mask); + + mask = 0x00; + for (int c = 0; c < columns && c < 8; c++) { + mask <<= 1; + mask |= 1; + } + writeRegister(TCA8418_REG_KP_GPIO_2, mask); + + if (columns > 8) { + if (columns == 9) + mask = 0x01; + else + mask = 0x03; + writeRegister(TCA8418_REG_KP_GPIO_3, mask); + } + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////// +// +// KEY EVENTS +// + +/** + * @brief checks if key events are available in the internal buffer + * + * @return number of key events in the buffer + */ +uint8_t Adafruit_TCA8418::available() { + uint8_t eventCount = readRegister(TCA8418_REG_KEY_LCK_EC); + eventCount &= 0x0F; // lower 4 bits only + return eventCount; +} + +/** + * @brief gets first event from the internal buffer + * + * @return key event or 0 if none available + * + * @details + * key event 0x00 no event + * 0x01..0x50 key press + * 0x81..0xD0 key release + * 0x5B..0x72 GPIO press + * 0xDB..0xF2 GPIO release + */ +uint8_t Adafruit_TCA8418::getEvent() { + uint8_t event = readRegister(TCA8418_REG_KEY_EVENT_A); + return event; +} + +/** + * @brief flushes the internal buffer of key events + * and cleans the GPIO status registers. + * + * @return number of keys flushed. + */ +uint8_t Adafruit_TCA8418::flush() { + // flush key events + uint8_t count = 0; + while (getEvent() != 0) + count++; + // flush gpio events + readRegister(TCA8418_REG_GPIO_INT_STAT_1); + readRegister(TCA8418_REG_GPIO_INT_STAT_2); + readRegister(TCA8418_REG_GPIO_INT_STAT_3); + // clear INT_STAT register + writeRegister(TCA8418_REG_INT_STAT, 3); + return count; +} + +///////////////////////////////////////////////////////////////////////////// +// +// GPIO +// + +/** + * @brief read GPIO + * + * @param [in] pinnum Pin name between TCA8418_ROW0 and TCA8418_COL9 0..17 + * @return 0 = LOW, 1 = HIGH, 0xFF = pinnum out of range + */ +uint8_t Adafruit_TCA8418::digitalRead(uint8_t pinnum) { + if (pinnum > TCA8418_COL9) + return 0xFF; + + uint8_t reg = TCA8418_REG_GPIO_DAT_STAT_1 + pinnum / 8; + uint8_t mask = (1 << (pinnum % 8)); + + // LEVEL 0 = LOW other = HIGH + uint8_t value = readRegister(reg); + if (value & mask) + return HIGH; + return LOW; +} + +/** + * @brief set GPIO pin to LOW or HIGH + * + * @param [in] pinnum Pin name between TCA8418_ROW0 and TCA8418_COL9 0..17 + * @param [in] level 0 = LOW, all other are HIGH + * @return true if successful + */ +bool Adafruit_TCA8418::digitalWrite(uint8_t pinnum, uint8_t level) { + if (pinnum > TCA8418_COL9) + return false; + + uint8_t reg = TCA8418_REG_GPIO_DAT_OUT_1 + pinnum / 8; + uint8_t mask = (1 << (pinnum % 8)); + + // LEVEL 0 = LOW other = HIGH + uint8_t value = readRegister(reg); + if (level == LOW) + value &= ~mask; + else + value |= mask; + writeRegister(reg, value); + return true; +} + +/** + * @brief set mode of GPIO pin to INPUT, INPUT_PULLUP or OUTPUT + * + * @param [in] pinnum Pin name between TCA8418_ROW0 and TCA8418_COL9 0..17 + * @param [in] mode INPUT, INPUT_PULLUP or OUTPUT + * @return false if failed. + */ +bool Adafruit_TCA8418::pinMode(uint8_t pinnum, uint8_t mode) { + if (pinnum > TCA8418_COL9) + return false; + // if (mode > INPUT_PULLUP) return false; ?s + + uint8_t idx = pinnum / 8; + uint8_t reg = TCA8418_REG_GPIO_DIR_1 + idx; + uint8_t mask = (1 << (pinnum % 8)); + + // MODE 0 = INPUT 1 = OUTPUT + uint8_t value = readRegister(reg); + if (mode == OUTPUT) + value |= mask; + else + value &= ~mask; + writeRegister(reg, value); + + // PULLUP 0 = enabled 1 = disabled + reg = TCA8418_REG_GPIO_PULL_1 + idx; + value = readRegister(reg); + if (mode == INPUT_PULLUP) + value &= ~mask; + else + value |= mask; + writeRegister(reg, value); + + return true; +} + +/** + * @brief set IRQ mode of GPIO pin to FALLING RISING + * + * @param [in] pinnum Pin name between TCA8418_ROW0 and TCA8418_COL9 0..17 + * @param [in] mode IRQ mode FALLING RISING + * @return false if failed. + */ +bool Adafruit_TCA8418::pinIRQMode(uint8_t pinnum, uint8_t mode) { + if (pinnum > TCA8418_COL9) + return false; + if ((mode != RISING) && (mode != FALLING)) + return false; + + // MODE 0 = FALLING 1 = RISING + uint8_t idx = pinnum / 8; + uint8_t reg = TCA8418_REG_GPIO_INT_LVL_1 + idx; + uint8_t mask = (1 << (pinnum % 8)); + + uint8_t value = readRegister(reg); + if (mode == RISING) + value |= mask; + else + value &= ~mask; + writeRegister(reg, value); + + // ENABLE INTERRUPT + reg = TCA8418_REG_GPIO_INT_EN_1 + idx; + value = readRegister(reg); + value |= mask; + writeRegister(reg, value); + + return true; +} + +///////////////////////////////////////////////////////////////////////////// +// +// CONFIGURATION +// + +/** + * @brief enables key event + GPIO interrupts. + */ +void Adafruit_TCA8418::enableInterrupts() { + uint8_t value = readRegister(TCA8418_REG_CFG); + value |= (TCA8418_REG_CFG_GPI_IEN | TCA8418_REG_CFG_KE_IEN); + writeRegister(TCA8418_REG_CFG, value); +}; + +/** + * @brief disables key events + GPIO interrupts. + */ +void Adafruit_TCA8418::disableInterrupts() { + uint8_t value = readRegister(TCA8418_REG_CFG); + value &= ~(TCA8418_REG_CFG_GPI_IEN | TCA8418_REG_CFG_KE_IEN); + writeRegister(TCA8418_REG_CFG, value); +}; + +/** + * @brief enables matrix overflow interrupt. + */ +void Adafruit_TCA8418::enableMatrixOverflow() { + uint8_t value = readRegister(TCA8418_REG_CFG); + value |= TCA8418_REG_CFG_OVR_FLOW_M; + writeRegister(TCA8418_REG_CFG, value); +}; + +/** + * @brief disables matrix overflow interrupt. + */ +void Adafruit_TCA8418::disableMatrixOverflow() { + uint8_t value = readRegister(TCA8418_REG_CFG); + value &= ~TCA8418_REG_CFG_OVR_FLOW_M; + writeRegister(TCA8418_REG_CFG, value); +}; + +/** + * @brief enables key debounce. + */ +void Adafruit_TCA8418::enableDebounce() { + writeRegister(TCA8418_REG_DEBOUNCE_DIS_1, 0x00); + writeRegister(TCA8418_REG_DEBOUNCE_DIS_2, 0x00); + writeRegister(TCA8418_REG_DEBOUNCE_DIS_3, 0x00); +} + +/** + * @brief disables key debounce. + */ +void Adafruit_TCA8418::disableDebounce() { + writeRegister(TCA8418_REG_DEBOUNCE_DIS_1, 0xFF); + writeRegister(TCA8418_REG_DEBOUNCE_DIS_2, 0xFF); + writeRegister(TCA8418_REG_DEBOUNCE_DIS_3, 0xFF); +} + +///////////////////////////////////////////////////////////////////////////// +// +// LOW LEVEL +// + +/** + * @brief reads byte value from register + * + * @param [in] reg register address + * @return value from register + */ +uint8_t Adafruit_TCA8418::readRegister(uint8_t reg) { + Adafruit_I2CRegister i2cReg = Adafruit_I2CRegister(i2c_dev, reg); + uint8_t buffer[1] = {0}; + i2cReg.read(buffer, 1); + return buffer[0]; +} + +/** + * @brief write byte value to register + * + * @param [in] reg register address + * @param [in] value + */ +void Adafruit_TCA8418::writeRegister(uint8_t reg, uint8_t value) { + Adafruit_I2CRegister i2cReg = Adafruit_I2CRegister(i2c_dev, reg); + i2cReg.write(value); +} diff --git a/libraries/Adafruit_TCA8418/Adafruit_TCA8418.h b/libraries/Adafruit_TCA8418/Adafruit_TCA8418.h new file mode 100644 index 0000000..61fd1e2 --- /dev/null +++ b/libraries/Adafruit_TCA8418/Adafruit_TCA8418.h @@ -0,0 +1,104 @@ +/*! + * @file Adafruit_TCA8418.h + * + * I2C Driver for the Adafruit TCA8418 Keypad Matrix / GPIO Expander + *Breakout + * + * This is a library for the Adafruit TCA8418 breakout: + * https://www.adafruit.com/products/4918 + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing products from + * Adafruit! + * + * + * BSD license (see license.txt) + */ + +#ifndef _ADAFRUIT_TCA8418_H +#define _ADAFRUIT_TCA8418_H + +#include "Arduino.h" +#include +#include +#include + +#define TCA8418_DEFAULT_ADDR 0x34 ///< The default I2C address for our breakout + +/** Pin IDs for matrix rows/columns */ +enum { + TCA8418_ROW0, // Pin ID for row 0 + TCA8418_ROW1, // Pin ID for row 1 + TCA8418_ROW2, // Pin ID for row 2 + TCA8418_ROW3, // Pin ID for row 3 + TCA8418_ROW4, // Pin ID for row 4 + TCA8418_ROW5, // Pin ID for row 5 + TCA8418_ROW6, // Pin ID for row 6 + TCA8418_ROW7, // Pin ID for row 7 + TCA8418_COL0, // Pin ID for column 0 + TCA8418_COL1, // Pin ID for column 1 + TCA8418_COL2, // Pin ID for column 2 + TCA8418_COL3, // Pin ID for column 3 + TCA8418_COL4, // Pin ID for column 4 + TCA8418_COL5, // Pin ID for column 5 + TCA8418_COL6, // Pin ID for column 6 + TCA8418_COL7, // Pin ID for column 7 + TCA8418_COL8, // Pin ID for column 8 + TCA8418_COL9 // Pin ID for column 9 +}; + +/*! + * @brief Class that stores state and functions for interacting with + * the TCA8418 I2C GPIO expander + */ +class Adafruit_TCA8418 { +public: + Adafruit_TCA8418(); + ~Adafruit_TCA8418(); + + // initialize the TCA8418 + bool begin(uint8_t address = TCA8418_DEFAULT_ADDR, TwoWire *wire = &Wire); + + // KEY EVENTS + // configure the size of the keypad. + // all other rows and columns are set as inputs. + bool matrix(uint8_t rows, uint8_t columns); + + // key events available in the internal FIFO buffer + uint8_t available(); + + // get one event from the FIFO buffer + // bit 7 indicates press = 0 or release == 1 (mask 0x80) + uint8_t getEvent(); + + // flush all events in the FIFO buffer + GPIO events + uint8_t flush(); + + // GPIO + uint8_t digitalRead(uint8_t pinnum); + bool digitalWrite(uint8_t pinnum, uint8_t level); + bool pinMode(uint8_t pinnum, uint8_t mode); + bool pinIRQMode(uint8_t pinnum, uint8_t mode); // MODE FALLING or RISING + + // CONFIGURATION + // enable / disable interrupts for matrix and GPI pins + void enableInterrupts(); + void disableInterrupts(); + + // ignore key events when FIFO buffer is full or not. + void enableMatrixOverflow(); + void disableMatrixOverflow(); + + // debounce keys. + void enableDebounce(); + void disableDebounce(); + + // for expert mode + uint8_t readRegister(uint8_t reg); + void writeRegister(uint8_t reg, uint8_t value); + +protected: + Adafruit_I2CDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface +}; + +#endif diff --git a/libraries/Adafruit_TCA8418/Adafruit_TCA8418_registers.h b/libraries/Adafruit_TCA8418/Adafruit_TCA8418_registers.h new file mode 100644 index 0000000..855170e --- /dev/null +++ b/libraries/Adafruit_TCA8418/Adafruit_TCA8418_registers.h @@ -0,0 +1,94 @@ +#pragma once +/** + * @file Adafruit_TCA8418_registers.h + * + * I2C Driver for the Adafruit TCA8418 Keypad Matrix / GPIO Expander + *Breakout + * + * This is a library for the Adafruit TCA8418 breakout: + * https://www.adafruit.com/products/4918 + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing products from + * Adafruit! + * + * + * BSD license (see license.txt) + */ + +// REGISTERS + +// #define TCA8418_REG_RESERVED 0x00 +#define TCA8418_REG_CFG 0x01 ///< Configuration register +#define TCA8418_REG_INT_STAT 0x02 ///< Interrupt status +#define TCA8418_REG_KEY_LCK_EC 0x03 ///< Key lock and event counter +#define TCA8418_REG_KEY_EVENT_A 0x04 ///< Key event register A +#define TCA8418_REG_KEY_EVENT_B 0x05 ///< Key event register B +#define TCA8418_REG_KEY_EVENT_C 0x06 ///< Key event register C +#define TCA8418_REG_KEY_EVENT_D 0x07 ///< Key event register D +#define TCA8418_REG_KEY_EVENT_E 0x08 ///< Key event register E +#define TCA8418_REG_KEY_EVENT_F 0x09 ///< Key event register F +#define TCA8418_REG_KEY_EVENT_G 0x0A ///< Key event register G +#define TCA8418_REG_KEY_EVENT_H 0x0B ///< Key event register H +#define TCA8418_REG_KEY_EVENT_I 0x0C ///< Key event register I +#define TCA8418_REG_KEY_EVENT_J 0x0D ///< Key event register J +#define TCA8418_REG_KP_LCK_TIMER 0x0E ///< Keypad lock1 to lock2 timer +#define TCA8418_REG_UNLOCK_1 0x0F ///< Unlock register 1 +#define TCA8418_REG_UNLOCK_2 0x10 ///< Unlock register 2 +#define TCA8418_REG_GPIO_INT_STAT_1 0x11 ///< GPIO interrupt status 1 +#define TCA8418_REG_GPIO_INT_STAT_2 0x12 ///< GPIO interrupt status 2 +#define TCA8418_REG_GPIO_INT_STAT_3 0x13 ///< GPIO interrupt status 3 +#define TCA8418_REG_GPIO_DAT_STAT_1 0x14 ///< GPIO data status 1 +#define TCA8418_REG_GPIO_DAT_STAT_2 0x15 ///< GPIO data status 2 +#define TCA8418_REG_GPIO_DAT_STAT_3 0x16 ///< GPIO data status 3 +#define TCA8418_REG_GPIO_DAT_OUT_1 0x17 ///< GPIO data out 1 +#define TCA8418_REG_GPIO_DAT_OUT_2 0x18 ///< GPIO data out 2 +#define TCA8418_REG_GPIO_DAT_OUT_3 0x19 ///< GPIO data out 3 +#define TCA8418_REG_GPIO_INT_EN_1 0x1A ///< GPIO interrupt enable 1 +#define TCA8418_REG_GPIO_INT_EN_2 0x1B ///< GPIO interrupt enable 2 +#define TCA8418_REG_GPIO_INT_EN_3 0x1C ///< GPIO interrupt enable 3 +#define TCA8418_REG_KP_GPIO_1 0x1D ///< Keypad/GPIO select 1 +#define TCA8418_REG_KP_GPIO_2 0x1E ///< Keypad/GPIO select 2 +#define TCA8418_REG_KP_GPIO_3 0x1F ///< Keypad/GPIO select 3 +#define TCA8418_REG_GPI_EM_1 0x20 ///< GPI event mode 1 +#define TCA8418_REG_GPI_EM_2 0x21 ///< GPI event mode 2 +#define TCA8418_REG_GPI_EM_3 0x22 ///< GPI event mode 3 +#define TCA8418_REG_GPIO_DIR_1 0x23 ///< GPIO data direction 1 +#define TCA8418_REG_GPIO_DIR_2 0x24 ///< GPIO data direction 2 +#define TCA8418_REG_GPIO_DIR_3 0x25 ///< GPIO data direction 3 +#define TCA8418_REG_GPIO_INT_LVL_1 0x26 ///< GPIO edge/level detect 1 +#define TCA8418_REG_GPIO_INT_LVL_2 0x27 ///< GPIO edge/level detect 2 +#define TCA8418_REG_GPIO_INT_LVL_3 0x28 ///< GPIO edge/level detect 3 +#define TCA8418_REG_DEBOUNCE_DIS_1 0x29 ///< Debounce disable 1 +#define TCA8418_REG_DEBOUNCE_DIS_2 0x2A ///< Debounce disable 2 +#define TCA8418_REG_DEBOUNCE_DIS_3 0x2B ///< Debounce disable 3 +#define TCA8418_REG_GPIO_PULL_1 0x2C ///< GPIO pull-up disable 1 +#define TCA8418_REG_GPIO_PULL_2 0x2D ///< GPIO pull-up disable 2 +#define TCA8418_REG_GPIO_PULL_3 0x2E ///< GPIO pull-up disable 3 +// #define TCA8418_REG_RESERVED 0x2F + +// FIELDS CONFIG REGISTER 1 +#define TCA8418_REG_CFG_AI 0x80 ///< Auto-increment for read/write +#define TCA8418_REG_CFG_GPI_E_CGF 0x40 ///< Event mode config +#define TCA8418_REG_CFG_OVR_FLOW_M 0x20 ///< Overflow mode enable +#define TCA8418_REG_CFG_INT_CFG 0x10 ///< Interrupt config +#define TCA8418_REG_CFG_OVR_FLOW_IEN 0x08 ///< Overflow interrupt enable +#define TCA8418_REG_CFG_K_LCK_IEN 0x04 ///< Keypad lock interrupt enable +#define TCA8418_REG_CFG_GPI_IEN 0x02 ///< GPI interrupt enable +#define TCA8418_REG_CFG_KE_IEN 0x01 ///< Key events interrupt enable + +// FIELDS INT_STAT REGISTER 2 +#define TCA8418_REG_STAT_CAD_INT 0x10 ///< Ctrl-alt-del seq status +#define TCA8418_REG_STAT_OVR_FLOW_INT 0x08 ///< Overflow interrupt status +#define TCA8418_REG_STAT_K_LCK_INT 0x04 ///< Key lock interrupt status +#define TCA8418_REG_STAT_GPI_INT 0x02 ///< GPI interrupt status +#define TCA8418_REG_STAT_K_INT 0x01 ///< Key events interrupt status + +// FIELDS KEY_LCK_EC REGISTER 3 +#define TCA8418_REG_LCK_EC_K_LCK_EN 0x40 ///< Key lock enable +#define TCA8418_REG_LCK_EC_LCK_2 0x20 ///< Keypad lock status 2 +#define TCA8418_REG_LCK_EC_LCK_1 0x10 ///< Keypad lock status 1 +#define TCA8418_REG_LCK_EC_KLEC_3 0x08 ///< Key event count bit 3 +#define TCA8418_REG_LCK_EC_KLEC_2 0x04 ///< Key event count bit 2 +#define TCA8418_REG_LCK_EC_KLEC_1 0x02 ///< Key event count bit 1 +#define TCA8418_REG_LCK_EC_KLEC_0 0x01 ///< Key event count bit 0