From c315419e949d7624824bd7588686f6ca61c5c752 Mon Sep 17 00:00:00 2001 From: H4W9 Date: Mon, 29 Jun 2026 13:19:19 -0500 Subject: [PATCH 1/2] Adds the Pancake C5 board (ESP32-C5, ST7796 320x480, FT6336 capacitive touch) This Pancake C5 Hardware Is already supported by other firmware... -Ghost ESP (Release v2.0) -Launcher(Beta Release) I left the CI build step commented out like the V8 build until... you are ready. - configs.h: MARAUDER_PANCAKE board defines, pins, battery (MAX17048), cap-touch I2C, and screen geometry. Status-bar icon x-positions and packet-monitor geometry generalized to SB_*/PKT_* macros so the wider 320px panel lays out correctly (identical results on existing 240px boards). - Display.cpp/.h: FT6336 capacitive touch path (rotation-aware, edge exclusion) gated on HAS_CAP_TOUCH; ft6336.h driver added. - MenuFunctions.cpp / WiFiScan.cpp: hardcoded status-bar and oscilloscope pixel coords replaced with the new screen-size macros. - User_Setup_marauder_pancake.h + User_Setup_Select.h entry. - build_parallel.yml: Pancake matrix entry added but commented out --- .github/workflows/build_parallel.yml | 5 +- User_Setup_Select.h | 1 + User_Setup_marauder_pancake.h | 55 +++++++++ esp32_marauder/Display.cpp | 93 ++++++++++++--- esp32_marauder/Display.h | 4 + esp32_marauder/MenuFunctions.cpp | 66 +++++------ esp32_marauder/WiFiScan.cpp | 30 ++--- esp32_marauder/configs.h | 168 +++++++++++++++++++++++++++ esp32_marauder/ft6336.h | 72 ++++++++++++ 9 files changed, 430 insertions(+), 64 deletions(-) create mode 100644 User_Setup_marauder_pancake.h create mode 100644 esp32_marauder/ft6336.h diff --git a/.github/workflows/build_parallel.yml b/.github/workflows/build_parallel.yml index 14e5455..2667499 100644 --- a/.github/workflows/build_parallel.yml +++ b/.github/workflows/build_parallel.yml @@ -38,6 +38,9 @@ jobs: - { 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" } - { name: "M5NanoC6", flag: "MARAUDER_M5_NANO_C6", fbqn: "esp32:esp32:esp32c6:CDCOnBoot=cdc,PartitionScheme=min_spiffs", file_name: "m5nanoc6", tft: false, tft_file: "", build_dir: "esp32c6", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } + # Marauder Pancake (ESP32-C5) — disabled until the custom TFT_eSPI-ESP32-C5 library + # is added to the repo and a "Use custom TFT_eSPI for ESP32-C5" copy step is restored. + #- { name: "Marauder Pancake", flag: "MARAUDER_PANCAKE", fbqn: "esp32:esp32:esp32c5:FlashSize=8M,PartitionScheme=default_8MB,PSRAM=enabled", file_name: "pancake", tft: true, tft_file: "User_Setup_marauder_pancake.h", build_dir: "esp32c5", addr: "0x2000", idf_ver: "3.3.4", nimble_ver: "2.3.8", esp_async: "bigbrodude6119/ESPAsyncWebServer", esp_async_ver: "master" } steps: - name: Checkout Code @@ -111,7 +114,7 @@ jobs: repository: Bodmer/TFT_eSPI ref: V2.5.34 path: CustomTFT_eSPI - + - name: Install XPT2046_Touchscreen uses: actions/checkout@v2 with: diff --git a/User_Setup_Select.h b/User_Setup_Select.h index 06b89de..e5ff9ca 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -37,6 +37,7 @@ //#include //#include //#include +//#include //#include // Setup file configured for my ILI9341 //#include // Setup file configured for my ST7735 diff --git a/User_Setup_marauder_pancake.h b/User_Setup_marauder_pancake.h new file mode 100644 index 0000000..a707910 --- /dev/null +++ b/User_Setup_marauder_pancake.h @@ -0,0 +1,55 @@ +// USER DEFINED SETTINGS +// TFT_eSPI setup for Marauder Pancake (ESP32-C5-DevKitC-1 + ILI9341 3.5") + +// ################################################################################## +// Section 1. Driver +// ################################################################################## + +//#define ILI9341_DRIVER +#define ST7796_DRIVER + +// 3.5-inch portrait panel native resolution +#define TFT_WIDTH 320 +#define TFT_HEIGHT 480 + + +// 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 + +// ################################################################################## +// Section 2. Pin assignments (Pancake hardware) +// ################################################################################## + +#define TFT_MISO 4 +#define TFT_MOSI 24 +#define TFT_SCLK 23 +#define TFT_CS 5 // TFT chip select +#define TFT_DC 3 // Data/command +#define TFT_RST 2 // Reset +#define TFT_BL 26 // Backlight + +#define TOUCH_CS -1 // No resistive touch chip; FT6336 is I2C-only + +// ################################################################################## +// Section 3. Fonts +// ################################################################################## + +#define LOAD_GLCD +#define LOAD_FONT2 +#define LOAD_FONT4 +// #define LOAD_FONT6 +// #define LOAD_FONT7 +// #define LOAD_FONT8 +#define LOAD_GFXFF +#define SMOOTH_FONT + +// ################################################################################## +// Section 4. SPI speed +// ################################################################################## + +#define SPI_FREQUENCY 27000000 +#define SPI_READ_FREQUENCY 20000000 +#define SPI_TOUCH_FREQUENCY 2500000 diff --git a/esp32_marauder/Display.cpp b/esp32_marauder/Display.cpp index cb18eb4..10d76ba 100644 --- a/esp32_marauder/Display.cpp +++ b/esp32_marauder/Display.cpp @@ -41,8 +41,47 @@ int8_t Display::menuButton(uint16_t *x, uint16_t *y, bool pressed, bool check_ho uint8_t Display::updateTouch(uint16_t *x, uint16_t *y, uint16_t threshold) { #ifdef HAS_ILI9341 - if (!this->headless_mode) - #ifndef HAS_CYD_TOUCH + if (!this->headless_mode) { + #ifdef HAS_CAP_TOUCH + // FT6336 capacitive touch: rotation-aware + edge exclusion + { + uint16_t raw_x, raw_y; + if (!ft6336_read_raw(&raw_x, &raw_y)) return 0; + + // Discard touches within PANCAKE_TOUCH_MARGIN pixels of any panel edge + #define PANCAKE_PANEL_W TFT_WIDTH + #define PANCAKE_PANEL_H TFT_HEIGHT + #define PANCAKE_TOUCH_MARGIN 5 + if (raw_x < PANCAKE_TOUCH_MARGIN || raw_x >= (PANCAKE_PANEL_W - PANCAKE_TOUCH_MARGIN)) return 0; + if (raw_y < PANCAKE_TOUCH_MARGIN || raw_y >= (PANCAKE_PANEL_H - PANCAKE_TOUCH_MARGIN)) return 0; + + // Transform panel-native portrait coords to screen coords per rotation + uint8_t rot = this->tft.getRotation(); + switch (rot) { + case 0: // Portrait + *x = raw_x; + *y = raw_y; + break; + case 1: // Landscape 90 CW + *x = raw_y; + *y = (PANCAKE_PANEL_W - 1) - raw_x; + break; + case 2: // Portrait 180 + *x = (PANCAKE_PANEL_W - 1) - raw_x; + *y = (PANCAKE_PANEL_H - 1) - raw_y; + break; + case 3: // Landscape 270 CW + *x = (PANCAKE_PANEL_H - 1) - raw_y; + *y = raw_x; + break; + default: + *x = raw_x; + *y = raw_y; + break; + } + return 1; + } + #elif !defined(HAS_CYD_TOUCH) return this->tft.getTouch(x, y, threshold); #else if (this->touchscreen.tirqTouched() && this->touchscreen.touched()) { @@ -80,8 +119,9 @@ uint8_t Display::updateTouch(uint16_t *x, uint16_t *y, uint16_t threshold) { else return 0; #endif - else + } else { return !this->headless_mode; + } #endif return 0; @@ -118,7 +158,7 @@ void Display::init() { } void Display::setCalData(bool landscape) { - #ifndef HAS_CYD_TOUCH + #if !defined(HAS_CYD_TOUCH) && !defined(HAS_CAP_TOUCH) if (!landscape) { #ifdef TFT_SHIELD uint16_t calData[5] = { 275, 3494, 361, 3528, 4 }; // tft.setRotation(0); // Portrait with TFT Shield @@ -167,6 +207,10 @@ void Display::RunSetup() { this->touchscreen.begin(touchscreenSPI); this->touchscreen.setRotation(0); #endif + + #ifdef HAS_CAP_TOUCH + ft6336_init(); + #endif tft.init(); @@ -176,7 +220,7 @@ void Display::RunSetup() { #ifdef HAS_ILI9341 - #ifndef HAS_CYD_TOUCH + #if !defined(HAS_CYD_TOUCH) && !defined(HAS_CAP_TOUCH) this->setCalData(); #endif @@ -200,14 +244,13 @@ void Display::RunSetup() { void Display::tftDrawGraphObjects(byte x_scale) { //draw the graph objects - tft.fillRect(11, 5, x_scale+1, 120, TFT_BLACK); // positive start point - tft.fillRect(11, 121, x_scale+1, 119, TFT_BLACK); // negative start point - tft.drawFastVLine(10, 5, 230, TFT_WHITE); // y axis - tft.drawFastHLine(10, HEIGHT_1 - 1, 310, TFT_WHITE); // x axis + tft.fillRect(11, 5, x_scale+1, PKT_HALF, TFT_BLACK); // positive start point + tft.fillRect(11, PKT_HALF + 1, x_scale+1, PKT_HALF - 1, TFT_BLACK); // negative start point + tft.drawFastVLine(10, 5, PKT_HALF * 2 - 10, TFT_WHITE); // y axis + tft.drawFastHLine(10, HEIGHT_1 - 1, PKT_AXIS_W, TFT_WHITE); // x axis tft.setTextColor(TFT_YELLOW); tft.setTextSize(1); // set parameters for y axis labels - //tft.setCursor(3, 116); tft.print(midway); // "0" at center of ya axis - tft.setCursor(3, 6); tft.print("+"); // "+' at top of y axis - tft.setCursor(3, 228); tft.print("0"); // "-" at bottom of y axis + tft.setCursor(3, 6); tft.print("+"); // '+' at top of y axis + tft.setCursor(3, PKT_HALF * 2 - 12); tft.print("0"); // "0" near baseline } void Display::tftDrawEapolColorKey(bool filter) @@ -297,6 +340,9 @@ void Display::tftDrawYScaleButtons(byte y_scale) } void Display::tftDrawChannelScaleButtons(int set_channel, bool lnd_an) { + #ifdef MARAUDER_PANCAKE + TOP_FIXED_AREA_2 = lnd_an ? 48 : 64; + #endif if (lnd_an) { tft.drawFastVLine(178, 0, 20, TFT_WHITE); tft.setCursor(145, 21); tft.setTextColor(TFT_WHITE); tft.setTextSize(1); tft.print(text10); tft.print(set_channel); @@ -354,6 +400,9 @@ void Display::tftDrawChannelScaleButtons(int set_channel, bool lnd_an) { } void Display::tftDrawChanHopButton(bool lnd_an, bool en) { + #ifdef MARAUDER_PANCAKE + TOP_FIXED_AREA_2 = lnd_an ? 48 : 64; + #endif if (lnd_an) { if (!en) { key[CHAN_HOP_INDEX].initButton(&tft, // Exit box @@ -412,6 +461,9 @@ void Display::tftDrawChanHopButton(bool lnd_an, bool en) { } void Display::tftDrawExitScaleButtons(bool lnd_an) { + #ifdef MARAUDER_PANCAKE + TOP_FIXED_AREA_2 = lnd_an ? 48 : 64; + #endif //tft.drawFastVLine(178, 0, 20, TFT_WHITE); //tft.setCursor(145, 21); tft.setTextColor(TFT_WHITE); tft.setTextSize(1); tft.print("Channel:"); tft.print(set_channel); @@ -473,6 +525,9 @@ void Display::touchToExit() // Function to just draw the screen black void Display::clearScreen() { + #ifdef MARAUDER_PANCAKE + TOP_FIXED_AREA_2 = 48; + #endif //Serial.println(F("clearScreen()")); #ifndef MARAUDER_V7 tft.fillScreen(TFT_BLACK); @@ -573,11 +628,15 @@ void Display::displayBuffer(bool do_clear) screen_buffer->add(display_buffer->shift()); for (int i = 0; i < this->screen_buffer->size(); i++) { - #ifdef HAS_TOUCH - tft.setCursor(xPos, (i * 12) + ((TFT_HEIGHT / 6) * 1.3)); - #else - tft.setCursor(xPos, (i * 12) + (TFT_HEIGHT / 6)); - #endif + #ifdef MARAUDER_PANCAKE + tft.setCursor(xPos, (i * TEXT_HEIGHT) + TOP_FIXED_AREA_2); + #else + #ifdef HAS_TOUCH + tft.setCursor(xPos, (i * 12) + ((TFT_HEIGHT / 6) * 1.3)); + #else + tft.setCursor(xPos, (i * 12) + (TFT_HEIGHT / 6)); + #endif + #endif this->processAndPrintString(tft, this->screen_buffer->get(i)); } diff --git a/esp32_marauder/Display.h b/esp32_marauder/Display.h index c017fd7..2fbd437 100644 --- a/esp32_marauder/Display.h +++ b/esp32_marauder/Display.h @@ -20,6 +20,10 @@ #include #endif +#ifdef HAS_CAP_TOUCH + #include "ft6336.h" +#endif + // WiFi stuff #define OTA_UPDATE 100 #define SHOW_INFO 101 diff --git a/esp32_marauder/MenuFunctions.cpp b/esp32_marauder/MenuFunctions.cpp index ab4c5c1..785e284 100644 --- a/esp32_marauder/MenuFunctions.cpp +++ b/esp32_marauder/MenuFunctions.cpp @@ -259,10 +259,10 @@ void MenuFunctions::main(uint32_t currentTime) if (pressed && (wifi_scan_obj.currentScanMode == WIFI_SCAN_WAR_DRIVE || wifi_scan_obj.currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE)) { - if (t_y >= 270) { + if (t_y >= (SCREEN_HEIGHT - 50)) { wifi_scan_obj.tagPOI(nullptr); // Brief green flash - display_obj.tft.fillRect(0, 270, 240, 50, TFT_GREEN); + display_obj.tft.fillRect(0, SCREEN_HEIGHT - 50, SCREEN_WIDTH, 50, TFT_GREEN); display_obj.tft.setTextSize(2); #ifdef HAS_GPS if (gps_obj.getFixStatus()) @@ -272,7 +272,7 @@ void MenuFunctions::main(uint32_t currentTime) display_obj.tft.setTextColor(TFT_BLACK, TFT_RED); String poiFlash = "POI (" + String(wifi_scan_obj.poiCount) + ")"; int16_t flashWidth = poiFlash.length() * 12; - display_obj.tft.setCursor((240 - flashWidth) / 2, 287); + display_obj.tft.setCursor((SCREEN_WIDTH - flashWidth) / 2, SCREEN_HEIGHT - 33); display_obj.tft.print(poiFlash); delay(200); x = -1; @@ -961,15 +961,15 @@ void MenuFunctions::battery2(bool initial) else the_color = TFT_GREEN; display_obj.tft.setTextColor(the_color, STATUSBAR_COLOR); - display_obj.tft.fillRect(186, 0, 50, STATUS_BAR_WIDTH, STATUSBAR_COLOR); - display_obj.tft.drawXBitmap(186, + display_obj.tft.fillRect(SB_TOUCH_X, 0, 50, STATUS_BAR_WIDTH, STATUSBAR_COLOR); + display_obj.tft.drawXBitmap(SB_TOUCH_X, 0, menu_icons[STATUS_BAT], 16, 16, STATUSBAR_COLOR, the_color); - display_obj.tft.drawString((String) battery_analog + "%", 204, 0, 2); + display_obj.tft.drawString((String) battery_analog + "%", SB_BAT_X, 0, 2); } #else void MenuFunctions::battery(bool initial) @@ -991,7 +991,7 @@ void MenuFunctions::battery(bool initial) display_obj.tft.setCursor(0, 1); /*if (!this->disable_touch) { - display_obj.tft.drawXBitmap(186, + display_obj.tft.drawXBitmap(SB_TOUCH_X, 0, menu_icons[STATUS_BAT], 16, @@ -1000,9 +1000,9 @@ void MenuFunctions::battery(bool initial) the_color); }*/ #if defined(MARAUDER_CARDPUTER) || defined(MARAUDER_CARDPUTER_ADV) - display_obj.tft.drawString((String)battery_obj.battery_level + "%", 204, 0, 1); + display_obj.tft.drawString((String)battery_obj.battery_level + "%", SB_BAT_X, 0, 1); #else - display_obj.tft.drawString((String)battery_obj.battery_level + "%", 204, 0, 2); + display_obj.tft.drawString((String)battery_obj.battery_level + "%", SB_BAT_X, 0, 2); #endif } #endif @@ -1093,13 +1093,13 @@ void MenuFunctions::updateStatusBar() wifi_scan_obj.free_ram = String(esp_get_free_heap_size()); if ((wifi_scan_obj.free_ram != wifi_scan_obj.old_free_ram) || (status_changed)) { wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram; - //display_obj.tft.fillRect(100, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR); + //display_obj.tft.fillRect(SB_MEM_X, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR); #ifdef HAS_FULL_SCREEN #ifndef HAS_PSRAM - display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", 100, 0, 2); + display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 2); #else - display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", 100, 0, 1); - display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", 100, 8, 1); + display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 1); + display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", SB_MEM_X, 8, 1); #endif #endif @@ -1110,14 +1110,14 @@ void MenuFunctions::updateStatusBar() // Draw battery info MenuFunctions::battery(false); - display_obj.tft.fillRect(186, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR); + display_obj.tft.fillRect(SB_TOUCH_X, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR); // Disable touch stuff #ifdef HAS_ILI9341 #ifdef HAS_BUTTONS if (this->disable_touch) { display_obj.tft.setCursor(0, 1); - display_obj.tft.drawXBitmap(186, + display_obj.tft.drawXBitmap(SB_TOUCH_X, 0, menu_icons[DISABLE_TOUCH], 16, @@ -1127,7 +1127,7 @@ void MenuFunctions::updateStatusBar() } else { display_obj.tft.setCursor(0, 1); - display_obj.tft.drawXBitmap(186, + display_obj.tft.drawXBitmap(SB_TOUCH_X, 0, menu_icons[DISABLE_TOUCH], 16, @@ -1146,7 +1146,7 @@ void MenuFunctions::updateStatusBar() the_color = TFT_RED; #ifdef HAS_FULL_SCREEN - display_obj.tft.drawXBitmap(170, + display_obj.tft.drawXBitmap(SB_SD_X, 0, menu_icons[STATUS_SD], 16, @@ -1164,7 +1164,7 @@ void MenuFunctions::updateStatusBar() // WiFi connection status stuff if (wifi_scan_obj.wifi_connected) { #ifdef HAS_FULL_SCREEN - display_obj.tft.drawXBitmap(170 - 16, + display_obj.tft.drawXBitmap(SB_WIFI_X, 0, menu_icons[JOINED], 16, @@ -1174,7 +1174,7 @@ void MenuFunctions::updateStatusBar() #endif } else { #ifdef HAS_FULL_SCREEN - display_obj.tft.drawXBitmap(170 - 16, + display_obj.tft.drawXBitmap(SB_WIFI_X, 0, menu_icons[JOINED], 16, @@ -1187,7 +1187,7 @@ void MenuFunctions::updateStatusBar() // Force PMKID stuff if ((wifi_scan_obj.force_pmkid) || (wifi_scan_obj.ep_deauth)) { #ifdef HAS_FULL_SCREEN - display_obj.tft.drawXBitmap(170 - (16 * 2), + display_obj.tft.drawXBitmap(SB_FORCE_X, 0, menu_icons[FORCE], 16, @@ -1197,7 +1197,7 @@ void MenuFunctions::updateStatusBar() #endif } else { #ifdef HAS_FULL_SCREEN - display_obj.tft.drawXBitmap(170 - (16 * 2), + display_obj.tft.drawXBitmap(SB_FORCE_X, 0, menu_icons[FORCE], 16, @@ -1271,13 +1271,13 @@ void MenuFunctions::drawStatusBar() // RAM Stuff wifi_scan_obj.free_ram = String(esp_get_free_heap_size()); wifi_scan_obj.old_free_ram = wifi_scan_obj.free_ram; - display_obj.tft.fillRect(100, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR); + display_obj.tft.fillRect(SB_MEM_X, 0, 60, STATUS_BAR_WIDTH, STATUSBAR_COLOR); #ifdef HAS_FULL_SCREEN #ifndef HAS_PSRAM - display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", 100, 0, 2); + display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 2); #else - display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", 100, 0, 1); - display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", 100, 8, 1); + display_obj.tft.drawString("D:" + String(getDRAMUsagePercent()) + "%", SB_MEM_X, 0, 1); + display_obj.tft.drawString("P:" + String(getPSRAMUsagePercent()) + "%", SB_MEM_X, 8, 1); #endif #endif @@ -1287,7 +1287,7 @@ void MenuFunctions::drawStatusBar() MenuFunctions::battery(true); - display_obj.tft.fillRect(186, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR); + display_obj.tft.fillRect(SB_TOUCH_X, 0, 16, STATUS_BAR_WIDTH, STATUSBAR_COLOR); // Disable touch stuff @@ -1295,7 +1295,7 @@ void MenuFunctions::drawStatusBar() #ifdef HAS_BUTTONS if (this->disable_touch) { display_obj.tft.setCursor(0, 1); - display_obj.tft.drawXBitmap(186, + display_obj.tft.drawXBitmap(SB_TOUCH_X, 0, menu_icons[DISABLE_TOUCH], 16, @@ -1305,7 +1305,7 @@ void MenuFunctions::drawStatusBar() } else { display_obj.tft.setCursor(0, 1); - display_obj.tft.drawXBitmap(186, + display_obj.tft.drawXBitmap(SB_TOUCH_X, 0, menu_icons[DISABLE_TOUCH], 16, @@ -1325,7 +1325,7 @@ void MenuFunctions::drawStatusBar() #ifdef HAS_FULL_SCREEN - display_obj.tft.drawXBitmap(170, + display_obj.tft.drawXBitmap(SB_SD_X, 0, menu_icons[STATUS_SD], 16, @@ -1343,7 +1343,7 @@ void MenuFunctions::drawStatusBar() // WiFi connection status stuff if (wifi_scan_obj.wifi_connected) { #ifdef HAS_FULL_SCREEN - display_obj.tft.drawXBitmap(170 - 16, + display_obj.tft.drawXBitmap(SB_WIFI_X, 0, menu_icons[JOINED], 16, @@ -1353,7 +1353,7 @@ void MenuFunctions::drawStatusBar() #endif } else { #ifdef HAS_FULL_SCREEN - display_obj.tft.drawXBitmap(170 - 16, + display_obj.tft.drawXBitmap(SB_WIFI_X, 0, menu_icons[JOINED], 16, @@ -1366,7 +1366,7 @@ void MenuFunctions::drawStatusBar() // Force PMKID stuff if ((wifi_scan_obj.force_pmkid) || (wifi_scan_obj.ep_deauth)) { #ifdef HAS_FULL_SCREEN - display_obj.tft.drawXBitmap(170 - (16 * 2), + display_obj.tft.drawXBitmap(SB_FORCE_X, 0, menu_icons[FORCE], 16, @@ -1376,7 +1376,7 @@ void MenuFunctions::drawStatusBar() #endif } else { #ifdef HAS_FULL_SCREEN - display_obj.tft.drawXBitmap(170 - (16 * 2), + display_obj.tft.drawXBitmap(SB_FORCE_X, 0, menu_icons[FORCE], 16, diff --git a/esp32_marauder/WiFiScan.cpp b/esp32_marauder/WiFiScan.cpp index 1055367..018f2d7 100644 --- a/esp32_marauder/WiFiScan.cpp +++ b/esp32_marauder/WiFiScan.cpp @@ -4102,7 +4102,11 @@ void WiFiScan::RunPacketMonitor(uint8_t scan_mode, uint16_t color) { (scan_mode != WIFI_SCAN_CHAN_ACT)) { #ifdef HAS_SCREEN display_obj.init(); - display_obj.tft.setRotation(1); + #ifdef HAS_CAP_TOUCH + display_obj.tft.setRotation(3); // Pancake: landscape-3 + #else + display_obj.tft.setRotation(1); + #endif display_obj.tft.fillScreen(TFT_BLACK); #endif @@ -4116,7 +4120,7 @@ void WiFiScan::RunPacketMonitor(uint8_t scan_mode, uint16_t color) { //display_obj.tft.setFreeFont(1); display_obj.tft.setFreeFont(NULL); display_obj.tft.setTextSize(1); - display_obj.tft.fillRect(127, 0, 193, 28, TFT_BLACK); // Buttons + display_obj.tft.fillRect(127, 0, WIDTH_1 - 127, 28, TFT_BLACK); // Buttons display_obj.tft.fillRect(12, 0, 90, 32, TFT_BLACK); // color key delay(10); @@ -5125,12 +5129,12 @@ void WiFiScan::displayWardriveStats() { #endif // POI button — full width bottom bar - display_obj.tft.drawRect(0, 270, 240, 50, TFT_MAGENTA); + display_obj.tft.drawRect(0, SCREEN_HEIGHT - 50, SCREEN_WIDTH, 50, TFT_MAGENTA); display_obj.tft.setTextSize(2); display_obj.tft.setTextColor(TFT_MAGENTA, TFT_BLACK); String poiText = "POI (" + String(this->poiCount) + ")"; int16_t poiTextWidth = poiText.length() * 12; // 12px per char at size 2 - display_obj.tft.setCursor((240 - poiTextWidth) / 2, 287); + display_obj.tft.setCursor((SCREEN_WIDTH - poiTextWidth) / 2, SCREEN_HEIGHT - 33); display_obj.tft.print(poiText); #endif @@ -8901,7 +8905,7 @@ bool WiFiScan::filterActive() { void WiFiScan::packetMonitorMain(uint32_t currentTime) { - for (x_pos = (11 + x_scale); x_pos <= 320; x_pos = x_pos) + for (x_pos = (11 + x_scale); x_pos <= WIDTH_1; x_pos = x_pos) { currentTime = millis(); do_break = false; @@ -9038,19 +9042,19 @@ bool WiFiScan::filterActive() { display_obj.tft.drawLine(x_pos - x_scale, y_pos_y_old, x_pos, y_pos_y, TFT_RED); //Draw preceding black 'boxes' to erase old plot lines, !!!WEIRD CODE TO COMPENSATE FOR BUTTONS AND COLOR KEY SO 'ERASER' DOESN'T ERASE BUTTONS AND COLOR KEY!!! - if ((x_pos <= 90) || ((x_pos >= 117) && (x_pos <= 320))) //above x axis - display_obj.tft.fillRect(x_pos+1, 28, 10, 93, TFT_BLACK); //compensate for buttons! + if ((x_pos <= 90) || ((x_pos >= 117) && (x_pos <= WIDTH_1))) //above x axis + display_obj.tft.fillRect(x_pos+1, 28, 10, PKT_HALF - 27, TFT_BLACK); //compensate for buttons! else - display_obj.tft.fillRect(x_pos+1, 0, 10, 121, TFT_BLACK); //don't compensate for buttons! + display_obj.tft.fillRect(x_pos+1, 0, 10, PKT_HALF + 1, TFT_BLACK); //don't compensate for buttons! if (x_pos < 0) // below x axis - display_obj.tft.fillRect(x_pos+1, 121, 10, 88, TFT_CYAN); + display_obj.tft.fillRect(x_pos+1, PKT_HALF + 1, 10, PKT_HALF - 32, TFT_CYAN); else - display_obj.tft.fillRect(x_pos+1, 121, 10, 118, TFT_BLACK); + display_obj.tft.fillRect(x_pos+1, PKT_HALF + 1, 10, PKT_HALF - 2, TFT_BLACK); - if ( (y_pos_x == 120) || (y_pos_y == 120) || (y_pos_z == 120) ) - display_obj.tft.drawFastHLine(10, 120, 310, TFT_WHITE); // x axis + if ( (y_pos_x == PKT_HALF) || (y_pos_y == PKT_HALF) || (y_pos_z == PKT_HALF) ) + display_obj.tft.drawFastHLine(10, PKT_HALF, PKT_AXIS_W, TFT_WHITE); // x axis y_pos_x_old = y_pos_x; //set old y pos values to current y pos values y_pos_y_old = y_pos_y; @@ -9061,7 +9065,7 @@ bool WiFiScan::filterActive() { } - display_obj.tft.fillRect(127, 0, 193, 28, TFT_BLACK); //erase XY buttons and any lines behind them + display_obj.tft.fillRect(127, 0, WIDTH_1 - 127, 28, TFT_BLACK); //erase XY buttons and any lines behind them display_obj.tft.fillRect(12, 0, 90, 32, TFT_BLACK); // key display_obj.tftDrawXScaleButtons(x_scale); //re-draw stuff diff --git a/esp32_marauder/configs.h b/esp32_marauder/configs.h index 2a64bc1..74650ea 100644 --- a/esp32_marauder/configs.h +++ b/esp32_marauder/configs.h @@ -33,6 +33,7 @@ //#define MARAUDER_CARDPUTER //#define MARAUDER_CARDPUTER_ADV //#define MARAUDER_V8 + //#define MARAUDER_PANCAKE //#define MARAUDER_MINI_V3 //#define MARAUDER_M5_NANO_C6 //#define DUAL_MINI_C5 @@ -103,6 +104,8 @@ #define HARDWARE_NAME "ESP32-C5 DevKit" #elif defined(MARAUDER_V8) #define HARDWARE_NAME "Marauder v8" + #elif defined(MARAUDER_PANCAKE) + #define HARDWARE_NAME "Pancake Marauder V8" #elif defined(MARAUDER_MINI_V3) #define HARDWARE_NAME "Marauder Mini v3" #elif defined(DUAL_MINI_C5) @@ -516,6 +519,29 @@ #define HAS_ACT_LED #endif + #ifdef MARAUDER_PANCAKE + #define HAS_TOUCH + #define HAS_CAP_TOUCH + //#define HAS_FLIPPER_LED + //#define FLIPPER_ZERO_HAT + #define HAS_BATTERY + #define HAS_BT + //#define HAS_BUTTONS + #define HAS_NEOPIXEL_LED + //#define HAS_PWR_MGMT + #define HAS_SCREEN + #define HAS_FULL_SCREEN + #define HAS_GPS + #define HAS_C5_SD + #define HAS_SD + #define USE_SD + #define HAS_DUAL_BAND + #define HAS_PSRAM + //#define HAS_TEMP_SENSOR + #define HAS_NIMBLE_2 + #define HAS_IDF_3 + #endif + #ifdef MARAUDER_MINI_V3 //#define HAS_TOUCH //#define HAS_FLIPPER_LED @@ -1299,6 +1325,75 @@ #define KIT_LED_BUILTIN 13 #endif + #if defined(MARAUDER_PANCAKE) + #define CHAN_PER_PAGE 7 + + #define SCREEN_CHAR_WIDTH 40 + #define HAS_ILI9341 + + #define BANNER_TEXT_SIZE 2 + + #ifndef TFT_WIDTH + #define TFT_WIDTH 320 + #endif + + #ifndef TFT_HEIGHT + #define TFT_HEIGHT 480 + #endif + + #define GRAPH_VERT_LIM TFT_HEIGHT/2 - 1 + + #define EXT_BUTTON_WIDTH 30 + + #define SCREEN_BUFFER + + #define MAX_SCREEN_BUFFER 26 + + #define SCREEN_ORIENTATION 0 + + #define CHAR_WIDTH 12 + #define SCREEN_WIDTH TFT_WIDTH + #define SCREEN_HEIGHT TFT_HEIGHT + #define HEIGHT_1 TFT_WIDTH + #define WIDTH_1 TFT_HEIGHT + #define STANDARD_FONT_CHAR_LIMIT (TFT_WIDTH/6) + #define TEXT_HEIGHT 16 + #define BOT_FIXED_AREA 0 + #define TOP_FIXED_AREA 48 + #define YMAX 480 + #define minimum(a,b) (((a) < (b)) ? (a) : (b)) + //#define MENU_FONT NULL + #define MENU_FONT &FreeMono9pt7b // Winner + //#define MENU_FONT &FreeMonoBold9pt7b + //#define MENU_FONT &FreeSans9pt7b + //#define MENU_FONT &FreeSansBold9pt7b + #define BUTTON_SCREEN_LIMIT 18 + #define BUTTON_ARRAY_LEN BUTTON_SCREEN_LIMIT + #define STATUS_BAR_WIDTH 16 + #define LVGL_TICK_PERIOD 6 + + #define FRAME_X 100 + #define FRAME_Y 64 + #define FRAME_W TFT_WIDTH / 2 + #define FRAME_H 50 + + // Red zone size + #define REDBUTTON_X FRAME_X + #define REDBUTTON_Y FRAME_Y + #define REDBUTTON_W (FRAME_W/2) + #define REDBUTTON_H FRAME_H + + // Green zone size + #define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W) + #define GREENBUTTON_Y FRAME_Y + #define GREENBUTTON_W (FRAME_W/2) + #define GREENBUTTON_H FRAME_H + + #define STATUSBAR_COLOR 0x4A49 + + #define KIT_LED_BUILTIN 13 + #endif + #if defined(MARAUDER_CYD_MICRO) #define CHAN_PER_PAGE 7 @@ -2062,6 +2157,24 @@ //#define BUTTON_ARRAY_LEN 5 #endif + // Status bar right-side icon x-positions (SCREEN_WIDTH-relative) + // V8 (240px): SD=170 WiFi=154 Force=138 Touch=186 Bat=204 + // Pancake (320px): SD=250 WiFi=234 Force=218 Touch=266 Bat=284 + #define SB_MEM_X (SCREEN_WIDTH / 2 - 20) // D%/P% text: 120 on V8, 160 on Pancake + #define SB_SD_X (SCREEN_WIDTH - 70) + #define SB_WIFI_X (SCREEN_WIDTH - 86) + #define SB_FORCE_X (SCREEN_WIDTH - 102) + #define SB_TOUCH_X (SCREEN_WIDTH - 54) + #define SB_BAT_X (SCREEN_WIDTH - 36) + + // Packet monitor oscilloscope geometry + // PKT_HALF = landscape height midpoint (zero-line y) + // PKT_AXIS_W = x-axis draw width + // HEIGHT_1 = TFT_WIDTH (landscape height): V8=240 Pancake=320 + // WIDTH_1 = TFT_HEIGHT (landscape width): V8=320 Pancake=480 + #define PKT_HALF (HEIGHT_1 / 2) + #define PKT_AXIS_W (WIDTH_1 - 10) + #if defined(MARAUDER_V8) #define BANNER_TIME 100 @@ -2081,6 +2194,25 @@ //#define BUTTON_ARRAY_LEN 5 #endif + #if defined(MARAUDER_PANCAKE) + #define BANNER_TIME 100 + + #define COMMAND_PREFIX "!" + + // Keypad start position, key sizes and spacing + #define KEY_X 160 // Centre of key + #define KEY_Y 59 + #define KEY_W 320 // Width and height + #define KEY_H 22 + #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 22 + //#define BUTTON_ARRAY_LEN 5 + #endif + #if defined(MARAUDER_CYD_MICRO) #define BANNER_TIME 100 @@ -2396,6 +2528,10 @@ #define SD_CS 10 #endif + #ifdef MARAUDER_PANCAKE + #define SD_CS 7 + #endif + #ifdef MARAUDER_MINI_V3 #define SD_CS 10 #endif @@ -2504,6 +2640,8 @@ #define MEM_LOWER_LIM 10000 #elif defined(MARAUDER_V8) #define MEM_LOWER_LIM 10000 + #elif defined(MARAUDER_PANCAKE) + #define MEM_LOWER_LIM 10000 #elif defined(MARAUDER_MINI_V3) #define MEM_LOWER_LIM 10000 #else @@ -2530,6 +2668,8 @@ #define PIN 27 #elif defined(MARAUDER_V8) #define PIN 27 + #elif defined(MARAUDER_PANCAKE) + #define PIN 27 #elif defined(MARAUDER_CARDPUTER_ADV) #define PIN 21 #elif defined(MARAUDER_M5_NANO_C6) @@ -2637,6 +2777,10 @@ #define GPS_SERIAL_INDEX 1 #define GPS_TX 14 #define GPS_RX 13 + #elif defined(MARAUDER_PANCAKE) + #define GPS_SERIAL_INDEX 1 + #define GPS_TX 14 + #define GPS_RX 13 #elif defined(MARAUDER_MINI_V3) #define GPS_SERIAL_INDEX 1 #define GPS_TX 14 @@ -2699,8 +2843,18 @@ #define HAS_MAX1704X #undef HAS_AXP2101 #undef HAS_IP5306 + + #elif defined(MARAUDER_PANCAKE) + #define I2C_SDA 9 + #define I2C_SCL 10 + #define HAS_MAX1704X + // FT6336 cap touch - shares I2C bus with MAX17048 + #define CTP_RST 8 + #define CTP_SDA I2C_SDA + #define CTP_SCL I2C_SCL #endif + // If we know what we have, we can delete what we're not using #ifdef BATTERY_ADC_PIN #undef HAS_AXP2101 @@ -2729,6 +2883,11 @@ #undef HAS_IP5306 #undef HAS_MAX1704X + #elif defined(HAS_MAX1704X) + #undef HAS_AXP2101 + #undef HAS_IP5306 + #undef HAS_AXP192 + #else // punt // #define HAS_AXP2101 @@ -2739,6 +2898,7 @@ #endif // HAS_BATTERY + //// MARAUDER TITLE STUFF #ifdef MARAUDER_V4 #define MARAUDER_TITLE_BYTES 13578 @@ -2766,6 +2926,8 @@ #define MARAUDER_TITLE_BYTES 13578 #elif defined(MARAUDER_V8) #define MARAUDER_TITLE_BYTES 13578 + #elif defined(MARAUDER_PANCAKE) + #define MARAUDER_TITLE_BYTES 13578 #elif defined(MARAUDER_MINI_V3) #define MARAUDER_TITLE_BYTES 13578 #else @@ -2832,6 +2994,12 @@ #define SD_SCK TFT_SCLK #endif + #ifdef MARAUDER_PANCAKE + #define SD_MISO TFT_MISO + #define SD_MOSI TFT_MOSI + #define SD_SCK TFT_SCLK + #endif + #ifdef MARAUDER_V4 #define SD_MISO TFT_MISO #define SD_MOSI TFT_MOSI diff --git a/esp32_marauder/ft6336.h b/esp32_marauder/ft6336.h new file mode 100644 index 0000000..29b7dba --- /dev/null +++ b/esp32_marauder/ft6336.h @@ -0,0 +1,72 @@ +#pragma once +#ifndef ft6336_h +#define ft6336_h + +#ifdef HAS_CAP_TOUCH + +#include + +#define FT6336_ADDR 0x38 +#define FT6336_TD_STATUS 0x02 +#define FT6336_T1_XH 0x03 + +static bool _ft6336_read(uint8_t reg, uint8_t *buf, uint8_t len) { + Wire.beginTransmission(FT6336_ADDR); + Wire.write(reg); + if (Wire.endTransmission(false) != 0) return false; + Wire.requestFrom((int)FT6336_ADDR, (int)len); + for (uint8_t i = 0; i < len; i++) + buf[i] = Wire.available() ? Wire.read() : 0; + return true; +} + +static void ft6336_init() { + pinMode(CTP_RST, OUTPUT); + digitalWrite(CTP_RST, LOW); + delay(10); + digitalWrite(CTP_RST, HIGH); + delay(300); + Wire.begin(CTP_SDA, CTP_SCL, 400000U); + + uint8_t chipId = 0; + Wire.beginTransmission(FT6336_ADDR); + Wire.write(0xA3); + if (Wire.endTransmission(false) == 0) { + Wire.requestFrom((int)FT6336_ADDR, 1); + if (Wire.available()) chipId = Wire.read(); + } + Serial.printf("[Touch] FT6336U ID: 0x%02X%s\n", + chipId, chipId == 0x64 ? " (OK)" : " (unexpected)"); + + // Raise touch threshold to reduce phantom touches. + // Register 0x80 = IDTHRESHOLD, default 22. Higher = less sensitive. + // Range 0–255; 40 is a good balance for panel-in-case use. + Wire.beginTransmission(FT6336_ADDR); + Wire.write(0x80); + Wire.write(40); + Wire.endTransmission(); +} + +// Reads raw panel coordinates (panel native portrait space: 0..319 × 0..479). +// Call this when you need to apply a rotation-specific transform. +static uint8_t ft6336_read_raw(uint16_t *raw_x, uint16_t *raw_y) { + uint8_t data[7]; + if (!_ft6336_read(FT6336_TD_STATUS, data, 7)) return 0; + if ((data[0] & 0x0F) == 0) return 0; + *raw_x = ((uint16_t)(data[1] & 0x0F) << 8) | data[2]; + *raw_y = ((uint16_t)(data[3] & 0x0F) << 8) | data[4]; + return 1; +} + +// Portrait-only convenience wrapper (rotation 0). +// For rotation-aware transforms, use ft6336_read_raw() via Display::updateTouch(). +static uint8_t ft6336_update(uint16_t *x, uint16_t *y) { + uint16_t raw_x, raw_y; + if (!ft6336_read_raw(&raw_x, &raw_y)) return 0; + *x = (raw_x < SCREEN_WIDTH) ? raw_x : (uint16_t)(SCREEN_WIDTH - 1); + *y = (raw_y < SCREEN_HEIGHT) ? raw_y : (uint16_t)(SCREEN_HEIGHT - 1); + return 1; +} + +#endif // HAS_CAP_TOUCH +#endif // ft6336_h From 5914e06bbc0480a69b95a45833bad0a94dde101a Mon Sep 17 00:00:00 2001 From: Just Call Me Koko Date: Wed, 1 Jul 2026 17:17:07 -0400 Subject: [PATCH 2/2] Fix buttons for raw sniff --- esp32_marauder/WiFiScan.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/esp32_marauder/WiFiScan.cpp b/esp32_marauder/WiFiScan.cpp index 612ffd1..e33d9c0 100644 --- a/esp32_marauder/WiFiScan.cpp +++ b/esp32_marauder/WiFiScan.cpp @@ -5244,10 +5244,11 @@ void WiFiScan::RunRawScan(uint8_t scan_mode, uint16_t color) { display_obj.tft.setFreeFont(NULL); display_obj.tft.setTextSize(1); display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK); - //display_obj.tftDrawChannelScaleButtons(set_channel, false); - //display_obj.tftDrawExitScaleButtons(false); - //if (scan_mode == WIFI_SCAN_RAW_CAPTURE) - //display_obj.tftDrawChanHopButton(false, settings_obj.loadSetting("ChanHop")); + if (scan_mode == WIFI_SCAN_RAW_CAPTURE) { + display_obj.tftDrawChannelScaleButtons(set_channel, false); + display_obj.tftDrawExitScaleButtons(false); + display_obj.tftDrawChanHopButton(false, settings_obj.loadSetting("ChanHop")); + } } #endif #endif