Files
ESP32Marauder/esp32_marauder/Display.cpp
2026-04-21 17:22:31 -04:00

620 lines
19 KiB
C++

#include "Display.h"
#include "lang_var.h"
#ifdef HAS_SCREEN
Display::Display()
#ifdef HAS_CYD_TOUCH
: touchscreenSPI(VSPI),
touchscreen(XPT2046_CS, XPT2046_IRQ)
#endif
{
}
int8_t Display::menuButton(uint16_t *x, uint16_t *y, bool pressed, bool check_hold) {
#ifdef HAS_ILI9341
for (uint8_t b = BUTTON_ARRAY_LEN; b < BUTTON_ARRAY_LEN + 3; b++) {
if (pressed && this->key[b].contains(*x, *y)) {
this->key[b].press(true); // tell the button it is pressed
} else {
this->key[b].press(false); // tell the button it is NOT pressed
}
}
for (uint8_t b = BUTTON_ARRAY_LEN; b < BUTTON_ARRAY_LEN + 3; b++) {
if (!check_hold) {
if ((this->key[b].justReleased()) && (!pressed)) {
return b - BUTTON_ARRAY_LEN;
}
}
else {
if ((this->key[b].isPressed())) {
return b - BUTTON_ARRAY_LEN;
}
}
}
#endif
return -1;
}
uint8_t Display::updateTouch(uint16_t *x, uint16_t *y, uint16_t threshold) {
#ifdef HAS_ILI9341
if (!this->headless_mode)
#ifndef HAS_CYD_TOUCH
return this->tft.getTouch(x, y, threshold);
#else
if (this->touchscreen.tirqTouched() && this->touchscreen.touched()) {
TS_Point p = this->touchscreen.getPoint();
//*x = map(p.x, 200, 3700, 1, TFT_WIDTH);
//*y = map(p.y, 240, 3800, 1, TFT_HEIGHT);
uint8_t rot = this->tft.getRotation();
//#ifdef HAS_CYD_PORTRAIT
// rot = 0;
//#endif
switch (rot) {
case 0: // Standard Protrait
*x = map(p.x, 200, 3700, 1, TFT_WIDTH);
*y = map(p.y, 240, 3800, 1, TFT_HEIGHT);
break;
case 1:
*x = map(p.y, 143, 3715, 0, TFT_HEIGHT); // Horizontal (Y axis in touch, X on screen)
*y = map(p.x, 3786, 216, 0, TFT_WIDTH); // Vertical (X axis in touch, Y on screen)
break;
case 2:
*x = map(p.x, 3700, 200, 1, TFT_WIDTH);
*y = map(p.y, 3800, 240, 1, TFT_HEIGHT);
break;
case 3:
*x = map(p.y, 3800, 240, 1, TFT_WIDTH);
*y = map(p.x, 200, 3700, 1, TFT_HEIGHT);
break;
}
return 1;
}
else
return 0;
#endif
else
return !this->headless_mode;
#endif
return 0;
}
bool Display::isTouchHeld(uint16_t threshold) {
static unsigned long touchStartTime = 0;
static bool touchHeld = false;
uint16_t x, y;
if (this->updateTouch(&x, &y, threshold)) {
// Touch detected
if (touchStartTime == 0) {
touchStartTime = millis(); // First touch timestamp
} else if (!touchHeld && millis() - touchStartTime >= 1000) {
touchHeld = true; // Held for at least 1000ms
return true;
}
} else {
// Touch released
touchStartTime = 0;
touchHeld = false;
}
return false;
}
void Display::init() {
tft.init();
#if defined(HAS_DUAL_BAND) && !defined(MARAUDER_MINI_V3)
digitalWrite(TFT_BL, HIGH);
#endif
}
void Display::setCalData(bool landscape) {
#ifndef HAS_CYD_TOUCH
if (!landscape) {
#ifdef TFT_SHIELD
uint16_t calData[5] = { 275, 3494, 361, 3528, 4 }; // tft.setRotation(0); // Portrait with TFT Shield
#elif defined(MARAUDER_CYD_3_5_INCH)
uint16_t calData[5] = { 239, 3560, 262, 3643, 4 };
#elif defined(MARAUDER_V8)
//uint16_t calData[5] = { 351, 3279, 214, 3394, 2 };
uint16_t calData[5] = { 312, 3431, 191, 3456, 2 };
#elif defined(TFT_DIY)
uint16_t calData[5] = { 339, 3470, 237, 3438, 2 }; // tft.setRotation(0); // Portrait with DIY TFT
#endif
#ifdef HAS_ILI9341
tft.setTouch(calData);
#endif
}
else {
#ifdef TFT_SHIELD
uint16_t calData[5] = { 391, 3491, 266, 3505, 7 }; // Landscape TFT Shield
#elif defined(MARAUDER_CYD_3_5_INCH)
uint16_t calData[5] = { 272, 3648, 234, 3565, 7 };
#elif defined(MARAUDER_V8)
uint16_t calData[5] = { 213, 3396, 350, 3275, 1 };
#else if defined(TFT_DIY)
uint16_t calData[5] = { 213, 3469, 320, 3446, 1 }; // Landscape TFT DIY
#endif
#ifdef HAS_ILI9341
tft.setTouch(calData);
#endif
}
#endif
}
// Function to prepare the display and the menus
void Display::RunSetup() {
run_setup = false;
// Need to declare new
display_buffer = new LinkedList<String>();
#ifdef SCREEN_BUFFER
screen_buffer = new LinkedList<String>();
#endif
#ifdef HAS_CYD_TOUCH
this->touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
this->touchscreen.begin(touchscreenSPI);
this->touchscreen.setRotation(0);
#endif
tft.init();
tft.setRotation(SCREEN_ORIENTATION);
tft.setCursor(0, 0);
#ifdef HAS_ILI9341
#ifndef HAS_CYD_TOUCH
this->setCalData();
#endif
#endif
clearScreen();
#ifdef KIT
pinMode(KIT_LED_BUILTIN, OUTPUT);
#endif
#ifdef MARAUDER_REV_FEATHER
pinMode(7, OUTPUT);
delay(10);
digitalWrite(7, HIGH);
#endif
}
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.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
}
void Display::tftDrawEapolColorKey(bool filter)
{
//Display color key
tft.setTextSize(1); tft.setTextColor(TFT_WHITE);
tft.fillRect(14, 0, 15, 8, TFT_CYAN); tft.setCursor(30, 0); tft.println(" - EAPOL");
if (filter) {
uint16_t y = tft.getCursorY();
tft.setCursor(14, y);
tft.println("Filter Active");
}
}
void Display::tftDrawColorKey()
{
//Display color key
tft.setTextSize(1); tft.setTextColor(TFT_WHITE);
tft.fillRect(14, 0, 15, 8, TFT_GREEN); tft.setCursor(30, 0); tft.print(" - Beacons");
tft.fillRect(14, 8, 15, 8, TFT_RED); tft.setCursor(30, 8); tft.print(" - Deauths");
tft.fillRect(14, 16, 15, 8, TFT_BLUE); tft.setCursor(30, 16); tft.print(" - Probes");
}
void Display::tftDrawXScaleButtons(byte x_scale) {
tft.drawFastVLine(234, 0, 20, TFT_WHITE);
tft.setCursor(208, 21); tft.setTextColor(TFT_WHITE); tft.setTextSize(1); tft.print("X Scale:"); tft.print(x_scale);
key[X_MINUS_INDEX].initButton(&tft, // x - box
220,
10, // x, y, w, h, outline, fill, text
20,
20,
TFT_BLACK, // Outline
TFT_CYAN, // Fill
TFT_BLACK, // Text
"-",
2);
key[X_PLUS_INDEX].initButton(&tft, // x + box
249,
10, // x, y, w, h, outline, fill, text
20,
20,
TFT_BLACK, // Outline
TFT_CYAN, // Fill
TFT_BLACK, // Text
"+",
2);
key[X_PLUS_INDEX].setLabelDatum(1, 5, MC_DATUM);
key[X_MINUS_INDEX].setLabelDatum(1, 5, MC_DATUM);
key[X_PLUS_INDEX].drawButton();
key[X_MINUS_INDEX].drawButton();
}
void Display::tftDrawYScaleButtons(byte y_scale)
{
tft.drawFastVLine(290, 0, 20, TFT_WHITE);
tft.setCursor(265, 21); tft.setTextColor(TFT_WHITE); tft.setTextSize(1); tft.print("Y Scale:"); tft.print(y_scale);
key[Y_MINUS_INDEX].initButton(&tft, // y - box
276,
10, // x, y, w, h, outline, fill, text
20,
20,
TFT_BLACK, // Outline
TFT_MAGENTA, // Fill
TFT_BLACK, // Text
"-",
2);
key[Y_PLUS_INDEX].initButton(&tft, // y + box
305,
10, // x, y, w, h, outline, fill, text
20,
20,
TFT_BLACK, // Outline
TFT_MAGENTA, // Fill
TFT_BLACK, // Text
"+",
2);
key[Y_MINUS_INDEX].setLabelDatum(1, 5, MC_DATUM);
key[Y_PLUS_INDEX].setLabelDatum(1, 5, MC_DATUM);
key[Y_MINUS_INDEX].drawButton();
key[Y_PLUS_INDEX].drawButton();
}
void Display::tftDrawChannelScaleButtons(int set_channel, bool lnd_an) {
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);
key[CHAN_MINUS_INDEX].initButton(&tft, // channel - box
164,
10, // x, y, w, h, outline, fill, text
EXT_BUTTON_WIDTH - (EXT_BUTTON_WIDTH * 0.33),
EXT_BUTTON_WIDTH - (EXT_BUTTON_WIDTH * 0.33),
TFT_BLACK, // Outline
TFT_BLUE, // Fill
TFT_BLACK, // Text
"-",
2);
key[CHAN_PLUS_INDEX].initButton(&tft, // channel + box
193,
10, // x, y, w, h, outline, fill, text
EXT_BUTTON_WIDTH - (EXT_BUTTON_WIDTH * 0.33),
EXT_BUTTON_WIDTH - (EXT_BUTTON_WIDTH * 0.33),
TFT_BLACK, // Outline
TFT_BLUE, // Fill
TFT_BLACK, // Text
"+",
2);
}
else {
key[CHAN_MINUS_INDEX].initButton(&tft, // channel - box
(EXT_BUTTON_WIDTH / 2) * 6,
(STATUS_BAR_WIDTH * 2) + (EXT_BUTTON_WIDTH / 2), // x, y, w, h, outline, fill, text
EXT_BUTTON_WIDTH,
EXT_BUTTON_WIDTH,
TFT_BLACK, // Outline
TFT_BLUE, // Fill
TFT_BLACK, // Text
"-",
1);
key[CHAN_PLUS_INDEX].initButton(&tft, // channel + box
(EXT_BUTTON_WIDTH / 2) * 10,
(STATUS_BAR_WIDTH * 2) + (EXT_BUTTON_WIDTH / 2), // x, y, w, h, outline, fill, text
EXT_BUTTON_WIDTH,
EXT_BUTTON_WIDTH,
TFT_BLACK, // Outline
TFT_BLUE, // Fill
TFT_BLACK, // Text
"+",
1);
}
key[CHAN_MINUS_INDEX].setLabelDatum(1, 5, MC_DATUM);
key[CHAN_PLUS_INDEX].setLabelDatum(1, 5, MC_DATUM);
key[CHAN_MINUS_INDEX].drawButton();
key[CHAN_PLUS_INDEX].drawButton();
}
void Display::tftDrawChanHopButton(bool lnd_an, bool en) {
if (lnd_an) {
if (!en) {
key[CHAN_HOP_INDEX].initButton(&tft, // Exit box
137,
10, // x, y, w, h, outline, fill, text
EXT_BUTTON_WIDTH,
EXT_BUTTON_WIDTH,
TFT_ORANGE, // Outline
TFT_RED, // Fill
TFT_BLACK, // Text
"X",
2);
} else {
key[CHAN_HOP_INDEX].initButton(&tft, // Exit box
137,
10, // x, y, w, h, outline, fill, text
EXT_BUTTON_WIDTH,
EXT_BUTTON_WIDTH,
TFT_WHITE, // Outline
TFT_GREEN, // Fill
TFT_BLACK, // Text
"O",
2);
}
}
else {
if (!en) {
key[CHAN_HOP_INDEX].initButton(&tft, // Exit box
(EXT_BUTTON_WIDTH / 2) * 14,
(STATUS_BAR_WIDTH * 2) + (EXT_BUTTON_WIDTH / 2), // x, y, w, h, outline, fill, text
EXT_BUTTON_WIDTH,
EXT_BUTTON_WIDTH,
TFT_ORANGE, // Outline
TFT_RED, // Fill
TFT_BLACK, // Text
"HOP",
1);
} else {
key[CHAN_HOP_INDEX].initButton(&tft, // Exit box
(EXT_BUTTON_WIDTH / 2) * 14,
(STATUS_BAR_WIDTH * 2) + (EXT_BUTTON_WIDTH / 2), // x, y, w, h, outline, fill, text
EXT_BUTTON_WIDTH,
EXT_BUTTON_WIDTH,
TFT_WHITE, // Outline
TFT_GREEN, // Fill
TFT_BLACK, // Text
"HOP",
1);
}
}
key[CHAN_HOP_INDEX].setLabelDatum(1, 5, MC_DATUM);
key[CHAN_HOP_INDEX].drawButton();
}
void Display::tftDrawExitScaleButtons(bool lnd_an) {
//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);
if (lnd_an) {
key[EXIT_BUTTON_INDEX].initButton(&tft, // Exit box
137,
10, // x, y, w, h, outline, fill, text
EXT_BUTTON_WIDTH - (EXT_BUTTON_WIDTH * 0.33),
EXT_BUTTON_WIDTH - (EXT_BUTTON_WIDTH * 0.33),
TFT_ORANGE, // Outline
TFT_RED, // Fill
TFT_BLACK, // Text
"X",
2);
}
else {
key[EXIT_BUTTON_INDEX].initButton(&tft, // Exit box
EXT_BUTTON_WIDTH,
(STATUS_BAR_WIDTH * 2) + (EXT_BUTTON_WIDTH / 2), // x, y, w, h, outline, fill, text
EXT_BUTTON_WIDTH,
EXT_BUTTON_WIDTH,
TFT_ORANGE, // Outline
TFT_RED, // Fill
TFT_BLACK, // Text
"X",
1);
}
key[EXIT_BUTTON_INDEX].setLabelDatum(1, 5, MC_DATUM);
key[EXIT_BUTTON_INDEX].drawButton();
}
void Display::twoPartDisplay(String center_text)
{
tft.setTextColor(TFT_BLACK, TFT_YELLOW);
tft.fillRect(0,16,HEIGHT_1,144, TFT_YELLOW);
//tft.drawCentreString(center_text,120,82,1);
tft.setTextWrap(true);
tft.setFreeFont(NULL);
//showCenterText(center_text, 82);
//tft.drawCentreString(center_text,120,82,1);
tft.setCursor(0, 82);
tft.println(center_text);
tft.setFreeFont(MENU_FONT);
tft.setTextWrap(false);
}
void Display::touchToExit()
{
tft.setTextColor(TFT_BLACK, TFT_LIGHTGREY);
tft.fillRect(0,32,HEIGHT_1,16, TFT_LIGHTGREY);
tft.drawCentreString(text11,TFT_WIDTH / 2,32,2);
}
// Function to just draw the screen black
void Display::clearScreen()
{
//Serial.println(F("clearScreen()"));
#ifndef MARAUDER_V7
tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0);
#elif defined(MARAUDER_MINI) || defined(MARAUDER_MINI_V3)
tft.fillRect(0, 0, TFT_WIDTH, TFT_HEIGHT, TFT_BLACK);
tft.setCursor(0, 0);
#else
tft.fillRect(0, 0, TFT_WIDTH, TFT_HEIGHT, TFT_BLACK);
tft.setCursor(0, 0);
#endif
}
#ifdef SCREEN_BUFFER
void Display::scrollScreenBuffer(bool down) {
// Scroll screen normal direction (Up)
if (!down) {
this->screen_buffer->shift();
}
}
#endif
void Display::processAndPrintString(TFT_eSPI& tft, const String& originalString) {
// Define colors
uint16_t text_color = TFT_GREEN; // Default text color
uint16_t background_color = TFT_BLACK; // Default background color
String new_string = originalString;
// Check for color macros at the start of the string
if (new_string.startsWith(";")) {
if (new_string.startsWith(RED_KEY)) {
text_color = TFT_RED;
new_string.remove(0, strlen(RED_KEY)); // Remove the macro
} else if (new_string.startsWith(GREEN_KEY)) {
text_color = TFT_GREEN;
new_string.remove(0, strlen(GREEN_KEY)); // Remove the macro
} else if (new_string.startsWith(CYAN_KEY)) {
text_color = TFT_CYAN;
new_string.remove(0, strlen(CYAN_KEY)); // Remove the macro
} else if (new_string.startsWith(WHITE_KEY)) {
text_color = TFT_WHITE;
new_string.remove(0, strlen(WHITE_KEY)); // Remove the macro
} else if (new_string.startsWith(MAGENTA_KEY)) {
text_color = TFT_MAGENTA;
new_string.remove(0, strlen(MAGENTA_KEY)); // Remove the macro
}
}
String spaces = String(' ', TFT_WIDTH / CHAR_WIDTH);
// Set text color and print the string
tft.setTextColor(text_color, background_color);
tft.print(new_string + spaces);
}
void Display::displayBuffer(bool do_clear)
{
if (this->display_buffer->size() > 0)
{
int print_count = 2;
while ((display_buffer->size() > 0) && (print_count > 0))
{
// Freeze adding to display buffer
if (display_buffer->size() > DISPLAY_BUFFER_LIMIT)
this->printing = true;
/*#ifndef SCREEN_BUFFER
xPos = 0;
if ((display_buffer->size() > 0) && (!loading))
{
//printing = true;
delay(print_delay_1);
yDraw = scroll_line(TFT_RED);
tft.setCursor(xPos, yDraw);
tft.setTextColor(TFT_GREEN, TFT_BLACK);
tft.print(display_buffer->shift());
//printing = false;
delay(print_delay_2);
}
if (!tteBar)
blank[(18+(yStart - TOP_FIXED_AREA) / TEXT_HEIGHT)%19] = xPos;
else
blank[(18+(yStart - TOP_FIXED_AREA_2) / TEXT_HEIGHT)%19] = xPos;
#else*/
xPos = 0;
if (this->screen_buffer->size() >= MAX_SCREEN_BUFFER)
this->scrollScreenBuffer();
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
this->processAndPrintString(tft, this->screen_buffer->get(i));
}
//#endif
print_count--;
}
this->printing = false;
}
}
void Display::showCenterText(String text, int y, bool small_pp)
{
if (!small_pp)
tft.setCursor((SCREEN_WIDTH - (text.length() * (6 * BANNER_TEXT_SIZE))) / 2, y);
else
tft.setCursor((SCREEN_WIDTH - (text.length() * (6))) / 2, y);
tft.println(text);
}
void Display::updateBanner(String msg)
{
this->buildBanner(msg, current_banner_pos);
}
void Display::buildBanner(String msg, int xpos)
{
int h = TEXT_HEIGHT;
#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, banner_y);
}
#endif