diff --git a/.github/workflows/build_parallel.yml b/.github/workflows/build_parallel.yml index 17e1f12..97297f5 100644 --- a/.github/workflows/build_parallel.yml +++ b/.github/workflows/build_parallel.yml @@ -35,6 +35,7 @@ jobs: - { 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: "2.3.8", 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 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: "2.3.8", 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 a23537c..80ca23f 100644 --- a/.github/workflows/nightly_build.yml +++ b/.github/workflows/nightly_build.yml @@ -98,6 +98,7 @@ jobs: - { 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: "2.3.8", 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 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: "2.3.8", 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/BatteryInterface.cpp b/esp32_marauder/BatteryInterface.cpp index 7c44118..93c87a7 100644 --- a/esp32_marauder/BatteryInterface.cpp +++ b/esp32_marauder/BatteryInterface.cpp @@ -26,7 +26,13 @@ void BatteryInterface::RunSetup() { #ifdef HAS_BATTERY - #ifndef HAS_AXP2101 + #ifdef BATTERY_ADC_PIN + analogReadResolution(12); + pinMode(BATTERY_ADC_PIN, INPUT); + this->has_adc_battery = true; + this->i2c_supported = true; + Serial.println(F("Battery: ADC mode")); + #elif !defined(HAS_AXP2101) Wire.begin(I2C_SDA, I2C_SCL); Wire.beginTransmission(IP5306_ADDR); @@ -59,13 +65,22 @@ void BatteryInterface::RunSetup() { this->i2c_supported = true; this->has_axp2101 = true; #endif - + this->initTime = millis(); #endif } int8_t BatteryInterface::getBatteryLevel() { + #ifdef BATTERY_ADC_PIN + if (this->has_adc_battery) { + int voltage_mv = analogReadMilliVolts(BATTERY_ADC_PIN) * 2; // voltage divider ratio 2:1 + if (voltage_mv <= 3300) return 0; + if (voltage_mv >= 4150) return 100; + return (int8_t)(((voltage_mv - 3300) * 100) / 850); + } + #endif + if (this->has_ip5306) { Wire.beginTransmission(IP5306_ADDR); Wire.write(0x78); diff --git a/esp32_marauder/BatteryInterface.h b/esp32_marauder/BatteryInterface.h index d5748c9..0d684c2 100644 --- a/esp32_marauder/BatteryInterface.h +++ b/esp32_marauder/BatteryInterface.h @@ -34,6 +34,7 @@ class BatteryInterface { bool has_max17048 = false; bool has_ip5306 = false; bool has_axp2101 = false; + bool has_adc_battery = false; BatteryInterface(); diff --git a/esp32_marauder/Display.cpp b/esp32_marauder/Display.cpp index d5ad8ec..4fca3f8 100644 --- a/esp32_marauder/Display.cpp +++ b/esp32_marauder/Display.cpp @@ -601,11 +601,16 @@ void Display::buildBanner(String msg, int xpos) { int h = TEXT_HEIGHT; - this->tft.fillRect(0, STATUS_BAR_WIDTH, SCREEN_WIDTH, TEXT_HEIGHT, TFT_BLACK); + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) + int banner_y = STATUS_BAR_WIDTH + 8; + #else + int banner_y = STATUS_BAR_WIDTH; + #endif + this->tft.fillRect(0, STATUS_BAR_WIDTH, SCREEN_WIDTH, TEXT_HEIGHT + (banner_y - STATUS_BAR_WIDTH), TFT_BLACK); this->tft.setFreeFont(NULL); // Font 4 selected this->tft.setTextSize(BANNER_TEXT_SIZE); // Font size scaling is x1 this->tft.setTextColor(TFT_WHITE, TFT_BLACK); // Black text, no background colour - this->showCenterText(msg, STATUS_BAR_WIDTH); + this->showCenterText(msg, banner_y); } #endif 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 580fa06..de7f4a1 100644 --- a/esp32_marauder/MenuFunctions.cpp +++ b/esp32_marauder/MenuFunctions.cpp @@ -102,6 +102,10 @@ void MenuFunctions::displayMenuButtons() { // Function to check menu input void MenuFunctions::main(uint32_t currentTime) { + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) + this->updateKeyboard(); + #endif + // Some function exited and we need to go back to normal if (display_obj.exit_draw) { if (wifi_scan_obj.currentScanMode != WIFI_CONNECTED) @@ -334,9 +338,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 @@ -430,12 +434,17 @@ void MenuFunctions::main(uint32_t currentTime) (wifi_scan_obj.currentScanMode == BT_SCAN_ANALYZER)) { wifi_scan_obj.StartScan(WIFI_SCAN_OFF); - - // If we don't do this, the text and button coordinates will be off - display_obj.init(); - + + // Restore display state without full reinit to avoid screen flash + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) + display_obj.tft.setRotation(SCREEN_ORIENTATION); + display_obj.clearScreen(); + #else + display_obj.init(); + #endif + // Take us back to the menu - changeMenu(current_menu); + changeMenu(current_menu, true); } x = -1; @@ -642,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) || @@ -713,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) || @@ -788,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) { @@ -812,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) { @@ -836,6 +845,16 @@ void MenuFunctions::main(uint32_t currentTime) } #endif + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) + if (this->isKeyPressed('`') || this->isKeyPressed(KEY_BACKSPACE)) { + if (wifi_scan_obj.currentScanMode == WIFI_SCAN_OFF) { + if (current_menu->parentMenu != NULL) { + this->changeMenu(current_menu->parentMenu, true); + } + } + } + #endif + if(c_btn_press){ current_menu->list->get(current_menu->selected).callable(); } @@ -930,7 +949,20 @@ void MenuFunctions::battery(bool initial) } display_obj.tft.setCursor(0, 1); - display_obj.tft.drawString((String)battery_obj.battery_level + "%", 204, 0, 2); + /*if (!this->disable_touch) { + display_obj.tft.drawXBitmap(186, + 0, + menu_icons[STATUS_BAT], + 16, + 16, + STATUSBAR_COLOR, + the_color); + }*/ + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) + display_obj.tft.drawString((String)battery_obj.battery_level + "%", 204, 0, 1); + #else + display_obj.tft.drawString((String)battery_obj.battery_level + "%", 204, 0, 2); + #endif } #endif } @@ -946,16 +978,16 @@ 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 if (this->old_gps_sat_count != gps_obj.getNumSats()) { this->old_gps_sat_count = gps_obj.getNumSats(); - display_obj.tft.fillRect(0, 0, TFT_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR); + display_obj.tft.fillRect(0, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR); status_changed = true; } #endif @@ -1000,7 +1032,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); @@ -1145,7 +1177,7 @@ void MenuFunctions::drawStatusBar() #ifdef HAS_MINI_SCREEN display_obj.tft.setFreeFont(NULL); #endif - display_obj.tft.fillRect(0, 0, TFT_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR); + display_obj.tft.fillRect(0, 0, SCREEN_WIDTH, STATUS_BAR_WIDTH, STATUSBAR_COLOR); display_obj.tft.setTextColor(TFT_WHITE, STATUSBAR_COLOR); uint16_t the_color; @@ -1389,11 +1421,15 @@ void MenuFunctions::displaySetting(String key, Menu* menu, int index) { } -#ifdef MARAUDER_CARDPUTER -bool MenuFunctions::isKeyPressed(char c) +#if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) +void MenuFunctions::updateKeyboard() { M5CardputerKeyboard.updateKeyList(); M5CardputerKeyboard.updateKeysState(); +} + +bool MenuFunctions::isKeyPressed(char c) +{ bool pressed = M5CardputerKeyboard.isKeyPressed(c); if (pressed) @@ -1415,7 +1451,7 @@ void MenuFunctions::RunSetup() this->disable_touch = false; - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) M5CardputerKeyboard.begin(); #endif @@ -2094,7 +2130,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); }); @@ -3041,7 +3077,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. @@ -3067,7 +3103,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] != '`')) { @@ -3255,12 +3291,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 @@ -3269,7 +3305,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"); @@ -3441,42 +3477,42 @@ void MenuFunctions::drawGraphSmall(uint8_t *values) { uint8_t maxValue = 0; //(i + (CHAN_PER_PAGE * (this->activity_page - 1))) - int bar_width = TFT_WIDTH / (CHAN_PER_PAGE * 2); - //display_obj.tft.fillRect(0, TFT_HEIGHT / 2 + 1, TFT_WIDTH, (TFT_HEIGHT / 2) + 1, TFT_BLACK); + int bar_width = SCREEN_WIDTH / (CHAN_PER_PAGE * 2); + //display_obj.tft.fillRect(0, TFT_HEIGHT / 2 + 1, SCREEN_WIDTH, (TFT_HEIGHT / 2) + 1, TFT_BLACK); #ifndef HAS_DUAL_BAND for (int i = 1; i < CHAN_PER_PAGE + 1; i++) { int targ_val = i + (CHAN_PER_PAGE * (wifi_scan_obj.activity_page - 1)) - 1; int x_mult = (i * 2) - 1; - int x_coord = (TFT_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1); + int x_coord = (SCREEN_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1); if (values[targ_val] > maxValue) { maxValue = values[targ_val]; } if (values[targ_val] * this->_graph_scale <= GRAPH_VERT_LIM) { - display_obj.tft.fillRect(x_coord, TFT_HEIGHT / 2 + 1, bar_width, TFT_HEIGHT / 2 + 1, TFT_BLACK); - display_obj.tft.fillRect(x_coord, TFT_HEIGHT - (values[targ_val] * this->_graph_scale), bar_width, values[targ_val] * this->_graph_scale, TFT_CYAN); + display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT / 2 + 1, bar_width, SCREEN_HEIGHT / 2 + 1, TFT_BLACK); + display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT - (values[targ_val] * this->_graph_scale), bar_width, values[targ_val] * this->_graph_scale, TFT_CYAN); } - display_obj.tft.drawLine(x_coord - 2, TFT_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), x_coord - 2, TFT_HEIGHT, TFT_WHITE); + display_obj.tft.drawLine(x_coord - 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), x_coord - 2, SCREEN_HEIGHT, TFT_WHITE); } #else for (int i = 1; i < CHAN_PER_PAGE + 1; i++) { int targ_val = i + (CHAN_PER_PAGE * (wifi_scan_obj.activity_page - 1)) - 1; int x_mult = (i * 2) - 1; - int x_coord = (TFT_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1); + int x_coord = (SCREEN_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1); if (values[targ_val] > maxValue) { maxValue = values[targ_val]; } if (values[targ_val] * this->_graph_scale <= GRAPH_VERT_LIM) { - display_obj.tft.fillRect(x_coord, TFT_HEIGHT / 2 + 1, bar_width, TFT_HEIGHT / 2 + 1, TFT_BLACK); - display_obj.tft.fillRect(x_coord, TFT_HEIGHT - (values[targ_val] * this->_graph_scale), bar_width, values[targ_val] * this->_graph_scale, TFT_CYAN); + display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT / 2 + 1, bar_width, SCREEN_HEIGHT / 2 + 1, TFT_BLACK); + display_obj.tft.fillRect(x_coord, SCREEN_HEIGHT - (values[targ_val] * this->_graph_scale), bar_width, values[targ_val] * this->_graph_scale, TFT_CYAN); } - display_obj.tft.drawLine(x_coord - 2, TFT_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), x_coord - 2, TFT_HEIGHT, TFT_WHITE); + display_obj.tft.drawLine(x_coord - 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), x_coord - 2, SCREEN_HEIGHT, TFT_WHITE); } #endif @@ -3513,11 +3549,11 @@ void MenuFunctions::drawGraph(int16_t *values) { void MenuFunctions::renderGraphUI(uint8_t scan_mode) { display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); if (scan_mode == WIFI_SCAN_CHAN_ANALYZER) - display_obj.tft.drawCentreString("Frames/" + (String)BANNER_TIME + "ms", TFT_WIDTH / 2, TFT_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), 1); + display_obj.tft.drawCentreString("Frames/" + (String)BANNER_TIME + "ms", SCREEN_WIDTH / 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), 1); else if (scan_mode == BT_SCAN_ANALYZER) - display_obj.tft.drawCentreString("BLE Beacons/" + (String)BANNER_TIME + "ms", TFT_WIDTH / 2, TFT_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), 1); - display_obj.tft.drawLine(0, TFT_HEIGHT - GRAPH_VERT_LIM - 1, TFT_WIDTH, TFT_HEIGHT - GRAPH_VERT_LIM - 1, TFT_WHITE); - display_obj.tft.setCursor(0, TFT_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 8)); + display_obj.tft.drawCentreString("BLE Beacons/" + (String)BANNER_TIME + "ms", SCREEN_WIDTH / 2, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), 1); + display_obj.tft.drawLine(0, SCREEN_HEIGHT - GRAPH_VERT_LIM - 1, SCREEN_WIDTH, SCREEN_HEIGHT - GRAPH_VERT_LIM - 1, TFT_WHITE); + display_obj.tft.setCursor(0, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 8)); display_obj.tft.setTextSize(1); display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); display_obj.tft.println("Max"); @@ -3621,9 +3657,11 @@ void MenuFunctions::buildButtons(Menu *menu, int starting_index, String button_n buf, KEY_TEXTSIZE); - - display_obj.key[i].setLabelDatum(BUTTON_PADDING - (KEY_W / 2), 2, ML_DATUM); - + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) + display_obj.key[i].setLabelDatum(BUTTON_PADDING - (KEY_W / 2), 4, ML_DATUM); + #else + display_obj.key[i].setLabelDatum(BUTTON_PADDING - (KEY_W / 2), 2, ML_DATUM); + #endif } for (int i = BUTTON_ARRAY_LEN; i < BUTTON_ARRAY_LEN + 3; i++) { diff --git a/esp32_marauder/MenuFunctions.h b/esp32_marauder/MenuFunctions.h index c93e8cb..883eb38 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 @@ -231,8 +231,9 @@ class MenuFunctions #endif //#endif - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) Keyboard_Class M5CardputerKeyboard = Keyboard_Class(); + void updateKeyboard(); bool isKeyPressed(char c); #endif diff --git a/esp32_marauder/SDInterface.cpp b/esp32_marauder/SDInterface.cpp index dc30e30..0287c19 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/WiFiScan.cpp b/esp32_marauder/WiFiScan.cpp index b60372d..d3f13c5 100644 --- a/esp32_marauder/WiFiScan.cpp +++ b/esp32_marauder/WiFiScan.cpp @@ -9239,33 +9239,33 @@ void WiFiScan::signalAnalyzerLoop(uint32_t tick) { void WiFiScan::drawChannelLine() { #ifdef HAS_SCREEN //#ifdef HAS_FULL_SCREEN - display_obj.tft.fillRect(0, TFT_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), TFT_WIDTH, (CHAR_WIDTH * 2) - 1, TFT_BLACK); + display_obj.tft.fillRect(0, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2), SCREEN_WIDTH, (CHAR_WIDTH * 2) - 1, TFT_BLACK); //#else //#endif //Serial.println("Drawing channel line..."); #ifndef HAS_DUAL_BAND for (int i = 1; i < CHAN_PER_PAGE + 1; i++) { int x_mult = (i * 2) - 1; - int x_coord = (TFT_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1); + int x_coord = (SCREEN_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1); #ifdef HAS_FULL_SCREEN display_obj.tft.setTextSize(2); #else display_obj.tft.setTextSize(1); #endif - display_obj.tft.setCursor(x_coord, TFT_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2)); + display_obj.tft.setCursor(x_coord, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2)); display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); display_obj.tft.print((String)(i + (CHAN_PER_PAGE * (this->activity_page - 1)))); } #else for (int i = 1; i < CHAN_PER_PAGE + 1; i++) { int x_mult = (i * 2) - 1; - int x_coord = (TFT_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1); + int x_coord = (SCREEN_WIDTH / (CHAN_PER_PAGE * 2)) * (x_mult - 1); //#ifdef HAS_FULL_SCREEN // display_obj.tft.setTextSize(2); //#else display_obj.tft.setTextSize(1); //#endif - display_obj.tft.setCursor(x_coord, TFT_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2)); + display_obj.tft.setCursor(x_coord, SCREEN_HEIGHT - GRAPH_VERT_LIM - (CHAR_WIDTH * 2)); display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK); display_obj.tft.print((String)this->dual_band_channels[(i + (CHAN_PER_PAGE * (this->activity_page - 1)) - 1)]); } diff --git a/esp32_marauder/configs.h b/esp32_marauder/configs.h index fd679bf..8a06da4 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,20 +133,26 @@ #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 #define HAS_BT #define HAS_BUTTONS //#define HAS_NEOPIXEL_LED //#define HAS_PWR_MGMT + //#define HAS_BATTERY #define HAS_SCREEN #define HAS_MINI_SCREEN #define HAS_SD #define USE_SD #define HAS_TEMP_SENSOR #define HAS_GPS + + #ifdef MARAUDER_CARDPUTER_ADV + #define HAS_BATTERY + #define BATTERY_ADC_PIN 10 + #define HAS_NEOPIXEL_LED + #endif #endif #ifdef MARAUDER_MINI @@ -643,7 +652,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,8 +978,8 @@ #endif - #ifdef MARAUDER_CARDPUTER - #define CHAN_PER_PAGE 7 + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) + #define CHAN_PER_PAGE 14 #define SCREEN_CHAR_WIDTH 40 //#define TFT_MISO -1 @@ -996,15 +1005,14 @@ #define TFT_HEIGHT 240 #endif - #define GRAPH_VERT_LIM TFT_HEIGHT/2 - 1 - #define EXT_BUTTON_WIDTH 0 #define SCREEN_ORIENTATION 1 #define CHAR_WIDTH 6 - #define SCREEN_WIDTH TFT_HEIGHT // Originally 240 - #define SCREEN_HEIGHT TFT_WIDTH // Originally 320 + #define SCREEN_WIDTH TFT_HEIGHT // 240 in landscape + #define SCREEN_HEIGHT TFT_WIDTH // 135 in landscape + #define GRAPH_VERT_LIM SCREEN_HEIGHT/2 - 1 #define HEIGHT_1 TFT_WIDTH #define WIDTH_1 TFT_WIDTH #define STANDARD_FONT_CHAR_LIMIT (TFT_WIDTH/6) // number of characters on a single line with normal font @@ -1020,7 +1028,7 @@ //#define MENU_FONT &FreeSansBold9pt7b #define BUTTON_SCREEN_LIMIT 6 #define BUTTON_ARRAY_LEN 100 - #define STATUS_BAR_WIDTH (TFT_HEIGHT/16) + #define STATUS_BAR_WIDTH (SCREEN_HEIGHT/16) #define LVGL_TICK_PERIOD 6 #define FRAME_X 100 @@ -2230,22 +2238,22 @@ #define BUTTON_PADDING 60 #endif - #ifdef MARAUDER_CARDPUTER + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) #define BANNER_TIME 50 - + #define COMMAND_PREFIX "!" - + // Keypad start position, key sizes and spacing - #define KEY_X (TFT_WIDTH/2) // Centre of key - #define KEY_Y (TFT_HEIGHT/5) - #define KEY_W TFT_HEIGHT // Width and height + #define KEY_X (SCREEN_WIDTH/2) // Centre of key + #define KEY_Y (TFT_HEIGHT/6) + #define KEY_W SCREEN_WIDTH // Width and height #define KEY_H (TFT_HEIGHT/17) #define KEY_SPACING_X 0 // X and Y gap #define KEY_SPACING_Y 1 #define KEY_TEXTSIZE 1 // Font size multiplier #define ICON_W 22 #define ICON_H 22 - #define BUTTON_PADDING 60 + #define BUTTON_PADDING 7 #endif #ifdef MARAUDER_MINI_V3 @@ -2322,7 +2330,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 +2431,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 @@ -2487,6 +2495,8 @@ #define PIN 27 #elif defined(MARAUDER_V8) #define PIN 27 + #elif defined(MARAUDER_CARDPUTER_ADV) + #define PIN 21 #else #define PIN 25 #endif @@ -2574,6 +2584,10 @@ #define GPS_SERIAL_INDEX 1 #define GPS_TX 1 #define GPS_RX 2 + #elif defined(MARAUDER_CARDPUTER_ADV) + #define GPS_SERIAL_INDEX 1 + #define GPS_TX 15 + #define GPS_RX 13 #elif defined(MARAUDER_REV_FEATHER) #define GPS_SERIAL_INDEX 1 #define GPS_TX 6 diff --git a/esp32_marauder/esp32_marauder.ino b/esp32_marauder/esp32_marauder.ino index 5e08cb8..26b0c74 100644 --- a/esp32_marauder/esp32_marauder.ino +++ b/esp32_marauder/esp32_marauder.ino @@ -322,7 +322,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); @@ -402,6 +402,9 @@ void setup() #endif #ifdef HAS_SCREEN + #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) + display_obj.clearScreen(); + #endif menu_function_obj.RunSetup(); #endif 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 diff --git a/mechanical/Antenna Plug 2/Antenna Plug Soft Plastic.stl b/mechanical/Antenna Plug 2/Antenna Plug Soft Plastic.stl new file mode 100644 index 0000000..408e578 Binary files /dev/null and b/mechanical/Antenna Plug 2/Antenna Plug Soft Plastic.stl differ diff --git a/mechanical/Antenna Plug 2/Hard Plastic.stl b/mechanical/Antenna Plug 2/Hard Plastic.stl new file mode 100644 index 0000000..20b13da Binary files /dev/null and b/mechanical/Antenna Plug 2/Hard Plastic.stl differ diff --git a/mechanical/V8/Faceplate.stl b/mechanical/V8/Faceplate.stl new file mode 100644 index 0000000..47d171d Binary files /dev/null and b/mechanical/V8/Faceplate.stl differ diff --git a/mechanical/V8/GPS Antenna Lid.stl b/mechanical/V8/GPS Antenna Lid.stl new file mode 100644 index 0000000..1bb571f Binary files /dev/null and b/mechanical/V8/GPS Antenna Lid.stl differ diff --git a/mechanical/V8/Main Body (Straight Antennas).stl b/mechanical/V8/Main Body (Straight Antennas).stl new file mode 100644 index 0000000..618388b Binary files /dev/null and b/mechanical/V8/Main Body (Straight Antennas).stl differ diff --git a/mechanical/V8/Switch.stl b/mechanical/V8/Switch.stl new file mode 100644 index 0000000..e975364 Binary files /dev/null and b/mechanical/V8/Switch.stl differ