Remove LVGL completely

This commit is contained in:
Just Call Me Koko
2025-11-27 03:08:04 -05:00
parent ba67c63010
commit 84416970e7
7 changed files with 468 additions and 348 deletions

View File

@@ -1045,9 +1045,9 @@ void Display::buildBanner(String msg, int xpos)
void Display::main(uint8_t scan_mode)
{
if ((scan_mode == LV_JOIN_WIFI) ||
/*if ((scan_mode == LV_JOIN_WIFI) ||
(scan_mode == LV_ADD_SSID))
lv_task_handler();
lv_task_handler();*/
return;
}
// End SPIFFS_functions

View File

@@ -12,7 +12,7 @@
//#include <JPEGDecoder.h>
#include <LinkedList.h>
#include <SPI.h>
#include <lvgl.h>
//#include <lvgl.h>
#include <Ticker.h>
#include "SPIFFS.h"
#include "Assets.h"

View File

@@ -5,10 +5,10 @@
#ifdef HAS_SCREEN
extern const unsigned char menu_icons[][66];
PROGMEM lv_obj_t * slider_label;
PROGMEM lv_obj_t * ta1;
PROGMEM lv_obj_t * ta2;
PROGMEM lv_obj_t * save_name;
//PROGMEM lv_obj_t * slider_label;
//PROGMEM lv_obj_t * ta1;
//PROGMEM lv_obj_t * ta2;
//PROGMEM lv_obj_t * save_name;
MenuFunctions::MenuFunctions()
{
@@ -18,12 +18,11 @@ MenuFunctions::MenuFunctions()
/* Interrupt driven periodic handler */
#ifdef HAS_ILI9341
void MenuFunctions::lv_tick_handler()
/*void MenuFunctions::lv_tick_handler()
{
lv_tick_inc(LVGL_TICK_PERIOD);
}
/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
extern Display display_obj;
@@ -103,11 +102,11 @@ MenuFunctions::MenuFunctions()
void MenuFunctions::deinitLVGL() {
Serial.println(F("Deinit LVGL"));
//lv_deinit();
}
}*/
// Event handler for settings drop down menus
void setting_dropdown_cb(lv_obj_t * obj, lv_event_t event) {
/*void setting_dropdown_cb(lv_obj_t * obj, lv_event_t event) {
}
@@ -273,17 +272,17 @@ MenuFunctions::MenuFunctions()
if (wifi_scan_obj.connected_network != "")
wifi_scan_obj.currentScanMode = WIFI_CONNECTED;
}
}
}*/
void ta_event_cb(lv_obj_t * ta, lv_event_t event)
/*void ta_event_cb(lv_obj_t * ta, lv_event_t event)
{
if(event == LV_EVENT_CLICKED) {
if(kb != NULL)
lv_keyboard_set_textarea(kb, ta);
}
}
}*/
#endif
//// END LV_ARDUINO STUFF
@@ -1610,9 +1609,9 @@ void MenuFunctions::RunSetup()
this->disable_touch = false;
#ifdef HAS_ILI9341
this->initLVGL();
#endif
//#ifdef HAS_ILI9341
// this->initLVGL();
//#endif
#ifdef MARAUDER_CARDPUTER
M5CardputerKeyboard.begin();
@@ -2240,16 +2239,33 @@ void MenuFunctions::RunSetup()
clearSSIDsMenu.parentMenu = &wifiGeneralMenu;
#ifdef HAS_ILI9341
this->addNodes(&wifiGeneralMenu, text_table1[1], TFTNAVY, NULL, KEYBOARD_ICO, [this](){
/*this->addNodes(&wifiGeneralMenu, text_table1[1], TFTNAVY, NULL, KEYBOARD_ICO, [this](){
display_obj.clearScreen();
wifi_scan_obj.StartScan(LV_ADD_SSID, TFT_YELLOW);
addSSIDGFX();
});*/
this->addNodes(&wifiGeneralMenu, text_table1[1], TFTNAVY, NULL, KEYBOARD_ICO, [this](){
char ssidBuf[64] = {0};
bool keep_going = true;
while (keep_going) {
display_obj.clearScreen();
if (keyboardInput(ssidBuf, sizeof(ssidBuf), "Enter SSID")) {
if (ssidBuf[0] != 0)
wifi_scan_obj.addSSID(String(ssidBuf));
for (int i = 0; i < 64; i++)
ssidBuf[i] = NULL;
}
else
keep_going = false;
}
this->changeMenu(current_menu);
});
#endif
#if (!defined(HAS_ILI9341) && defined(HAS_BUTTONS))
this->addNodes(&wifiGeneralMenu, text_table1[1], TFTNAVY, NULL, KEYBOARD_ICO, [this](){
this->changeMenu(&miniKbMenu, true);
#ifndef HAS_MINI_KB
#ifdef HAS_MINI_KB
this->miniKeyboard(&miniKbMenu);
#endif
});
@@ -2473,9 +2489,17 @@ void MenuFunctions::RunSetup()
// Join WiFi using touch screen keyboard
#ifdef HAS_TOUCH
wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
char passwordBuf[64] = {0}; // or prefill with existing SSID
if (keyboardInput(passwordBuf, sizeof(passwordBuf), "Enter Password")) {
//wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
//wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
wifi_scan_obj.joinWiFi(access_points->get(i).essid, String(passwordBuf), true);
}
this->changeMenu(&wifiGeneralMenu, false);
/*wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
joinWiFiGFX(access_points->get(i).essid);
joinWiFiGFX(access_points->get(i).essid);*/
#endif
});
}
@@ -2516,9 +2540,17 @@ void MenuFunctions::RunSetup()
// Join WiFi using touch screen keyboard
#ifdef HAS_TOUCH
wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
char passwordBuf[64] = {0}; // or prefill with existing SSID
if (keyboardInput(passwordBuf, sizeof(passwordBuf), "Enter Password")) {
//wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
//wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
wifi_scan_obj.joinWiFi(access_points->get(i).essid, String(passwordBuf), true);
}
this->changeMenu(&wifiGeneralMenu, false);
/*wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
joinWiFiGFX(access_points->get(i).essid);
joinWiFiGFX(access_points->get(i).essid);*/
#endif
});
}
@@ -2554,73 +2586,31 @@ void MenuFunctions::RunSetup()
// Join WiFi using touch screen keyboard
#ifdef HAS_TOUCH
wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
/*wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
joinWiFiGFX(ssids->get(i).essid, true);
joinWiFiGFX(ssids->get(i).essid, true);*/
char passwordBuf[64] = {0}; // or prefill with existing SSID
if (keyboardInput(passwordBuf, sizeof(passwordBuf), "Enter Password")) {
//wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
//wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
Serial.println("Using SSID: " + (String)ssids->get(i).essid + " Password: " + String(passwordBuf));
wifi_scan_obj.startWiFi(ssids->get(i).essid, String(passwordBuf));
}
this->changeMenu(&wifiGeneralMenu, false);
/*wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
joinWiFiGFX(access_points->get(i).essid);*/
#endif
});
}
this->changeMenu(&ssidsMenu, true);
});
/*this->addNodes(&wifiGeneralMenu, "Start Saved AP", TFTWHITE, NULL, KEYBOARD_ICO, [this](){
String ssid = settings_obj.loadSetting<String>("APSSID");
String pw = settings_obj.loadSetting<String>("APPW");
if ((ssid != "") && (pw != "")) {
wifi_scan_obj.startWiFi(ssid, pw, false);
this->changeMenu(&wifiGeneralMenu);
}
else {
// Add the back button
wifiAPMenu.list->clear();
this->addNodes(&wifiAPMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() {
this->changeMenu(wifiAPMenu.parentMenu);
});
// Populate the menu with buttons
for (int i = 0; i < ssids->size(); i++) {
// This is the menu node
this->addNodes(&wifiAPMenu, ssids->get(i).essid, TFTCYAN, NULL, 255, [this, i](){
// Join WiFi using mini keyboard
#ifdef HAS_MINI_KB
this->changeMenu(&miniKbMenu);
String password = this->miniKeyboard(&miniKbMenu, true);
if (password != "") {
Serial.println("Using SSID: " + (String)ssids->get(i).essid + " Password: " + (String)password);
wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
wifi_scan_obj.startWiFi(ssids->get(i).essid, password);
this->changeMenu(current_menu);
}
#endif
// Join WiFi using touch screen keyboard
#ifdef HAS_TOUCH
wifi_scan_obj.currentScanMode = LV_JOIN_WIFI;
wifi_scan_obj.StartScan(LV_JOIN_WIFI, TFT_YELLOW);
joinWiFiGFX(ssids->get(i).essid, true);
#endif
});
}
this->changeMenu(&wifiAPMenu);
}
});*/
wifiStationMenu.parentMenu = &ssidsMenu;
this->addNodes(&wifiStationMenu, text09, TFTLIGHTGREY, NULL, 0, [this]() {
this->changeMenu(wifiStationMenu.parentMenu, true);
});
//#endif
//#ifdef HAS_ILI9341
// this->addNodes(&wifiGeneralMenu, "View AP Info", TFTLIGHTGREY, NULL, 0, [this]() {
// display_obj.clearScreen();
// wifi_scan_obj.currentScanMode = LV_ADD_SSID;
// wifi_scan_obj.StartScan(LV_ADD_SSID, TFT_WHITE);
// addAPGFX("AP Info");
// });
//#endif
this->addNodes(&wifiGeneralMenu, "Set MACs", TFTLIGHTGREY, NULL, 0, [this]() {
this->changeMenu(&setMacMenu, true);

View File

@@ -99,21 +99,21 @@ extern Settings settings_obj;
#define FUNNY_BEACON 40
#define FLOCK 41
PROGMEM void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
PROGMEM bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data);
//PROGMEM void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
//PROGMEM bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data);
PROGMEM static lv_disp_buf_t disp_buf;
PROGMEM static lv_color_t buf[LV_HOR_RES_MAX * 10];
//PROGMEM static lv_disp_buf_t disp_buf;
//PROGMEM static lv_color_t buf[LV_HOR_RES_MAX * 10];
PROGMEM static void ta_event_cb(lv_obj_t * ta, lv_event_t event);
PROGMEM static void join_wifi_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event);
PROGMEM static void start_ap_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event);
PROGMEM static void add_ssid_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event);
PROGMEM static void setting_dropdown_cb(lv_obj_t * btn, lv_event_t event);
//PROGMEM static void ta_event_cb(lv_obj_t * ta, lv_event_t event);
//PROGMEM static void join_wifi_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event);
//PROGMEM static void start_ap_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event);
//PROGMEM static void add_ssid_keyboard_event_cb(lv_obj_t * keyboard, lv_event_t event);
//PROGMEM static void setting_dropdown_cb(lv_obj_t * btn, lv_event_t event);
// lvgl stuff
PROGMEM static lv_obj_t *kb;
PROGMEM static lv_obj_t * save_as_kb;
//PROGMEM static lv_obj_t *kb;
//PROGMEM static lv_obj_t * save_as_kb;
struct Menu;
@@ -287,8 +287,8 @@ class MenuFunctions
void joinWiFiGFX(String essid, bool start_ap = false);
void setGraphScale(float scale);
void initLVGL();
void deinitLVGL();
//void initLVGL();
//void deinitLVGL();
void updateStatusBar();
void addSSIDGFX();
void buildButtons(Menu* menu, int starting_index = 0, String button_name = "");

View File

@@ -1,277 +1,402 @@
#include "TouchKeyboard.h"
#include <string.h> // for strlen, memset
#include <string.h>
#include <Arduino.h>
#ifdef HAS_TOUCH
// display_obj is created in your main .ino
extern Display display_obj;
// ---- Layout config ----
// Keyboard will occupy the bottom half of the screen.
static inline int16_t kbHeight() { return TFT_HEIGHT / 2; }
static inline int16_t kbYStart() { return TFT_HEIGHT - kbHeight(); }
static inline int16_t kbWidth() { return TFT_WIDTH; }
static inline int16_t kbXStart() { return 0; }
// Well do 4 rows of “normal” keys and 1 special row = 5 rows total
static const int KEY_ROWS = 5;
// Character rows (top to bottom of the keyboard area)
static const char ROW0[] = "1234567890";
static const char ROW1[] = "QWERTYUIOP";
static const char ROW2[] = "ASDFGHJKL";
static const char ROW3[] = "ZXCVBNM.-_";
static const char ROW0_ALPHA[] = "1234567890";
static const char ROW1_ALPHA[] = "qwertyuiop";
static const char ROW2_ALPHA[] = "asdfghjkl";
static const char ROW3_ALPHA[] = "zxcvbnm.";
// Special row: [SPACE] [BKSP] [OK] handled separately
static const char ROW0_SYM[] = "!@#$%^&*()";
static const char ROW1_SYM[] = "`~-_=+[]{}";
static const char ROW2_SYM[] = "\\|;:'\"";
static const char ROW3_SYM[] = ",.<>/?";
// Touch threshold (adjust if needed)
static const uint16_t TOUCH_THRESHOLD = 600;
// --- Helper: draw text area (top half) ---
enum KeyboardLayout {
LAYOUT_ALPHA = 0,
LAYOUT_SYMBOLS
};
static void drawTextArea(const char *title, const char *buffer)
{
int16_t areaHeight = TFT_HEIGHT - kbHeight();
static void drawTextArea(const char *title, const char *buffer) {
int16_t areaHeight = TFT_HEIGHT - kbHeight();
// Clear text area
display_obj.tft.fillRect(0, 0, TFT_WIDTH, areaHeight, TFT_BLACK);
// Clear text area
display_obj.tft.fillRect(0, 0, TFT_WIDTH, areaHeight, TFT_BLACK);
int16_t cursorY = 2;
int16_t cursorY = 2;
// Optional title
if (title && title[0] != '\0') {
display_obj.tft.setCursor(2, cursorY);
display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
display_obj.tft.print(title);
cursorY += 16;
}
// Draw current text
// Optional title
if (title && title[0] != '\0') {
display_obj.tft.setCursor(2, cursorY);
display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK);
display_obj.tft.print(buffer ? buffer : "");
display_obj.tft.setTextColor(TFT_GREEN, TFT_BLACK);
display_obj.tft.print(title);
cursorY += 16;
}
// Draw current text
display_obj.tft.setCursor(2, cursorY);
display_obj.tft.setTextColor(TFT_WHITE, TFT_BLACK);
display_obj.tft.print(buffer ? buffer : "");
}
// --- Helper: draw entire keyboard ---
static void drawKeyboard(KeyboardLayout layout, bool caps) {
const int16_t kY = kbYStart();
const int16_t kH = kbHeight();
const int16_t kX = kbXStart();
const int16_t kW = kbWidth();
static void drawKeyboard()
{
const int16_t kY = kbYStart();
const int16_t kH = kbHeight();
const int16_t kX = kbXStart();
const int16_t kW = kbWidth();
const int maxCols = 10;
const int rows = KEY_ROWS;
const int maxCols = 10; // base grid is 10 columns
const int rows = KEY_ROWS; // 4 char rows + 1 special row
const int16_t cellW = kW / maxCols;
const int16_t cellH = kH / rows;
const int16_t cellW = kW / maxCols;
const int16_t cellH = kH / rows;
display_obj.tft.fillRect(kX, kY, kW, kH, TFT_DARKGREY);
display_obj.tft.setTextColor(TFT_BLACK, TFT_DARKGREY);
display_obj.tft.fillRect(kX, kY, kW, kH, TFT_DARKGREY);
// Choose row strings based on layout
const char *rowStringsAlpha[4] = {
ROW0_ALPHA, ROW1_ALPHA, ROW2_ALPHA, ROW3_ALPHA
};
const char *rowStringsSym[4] = {
ROW0_SYM, ROW1_SYM, ROW2_SYM, ROW3_SYM
};
display_obj.tft.setTextColor(TFT_BLACK, TFT_DARKGREY);
const char **rowsPtr = (layout == LAYOUT_ALPHA)
? (const char **)rowStringsAlpha
: (const char **)rowStringsSym;
// Draw normal character rows (03)
const char *rowStrings[4] = { ROW0, ROW1, ROW2, ROW3 };
// Draw normal character rows (03)
for (int r = 0; r < 4; ++r) {
const char *row = rowsPtr[r];
for (int r = 0; r < 4; ++r) {
const char *row = rowStrings[r];
int rowLen = strlen(row);
// For alpha layout row 3, we will also draw CAPS on the rightmost 2 columns.
// The textual row only covers the first part.
int rowLen = strlen(row);
int16_t rowY = kY + r * cellH;
int16_t xOffset = (maxCols - rowLen);
if (xOffset < 0) xOffset = 0;
xOffset = (xOffset * cellW) / 2; // center row
for (int i = 0; i < rowLen; ++i) {
int16_t keyX = kX + xOffset + i * cellW;
int16_t keyY = rowY;
// Key border
display_obj.tft.drawRect(keyX, keyY, cellW, cellH, TFT_BLACK);
// Label
display_obj.tft.setCursor(keyX + cellW / 2 - 3, keyY + cellH / 2 - 4);
char c[2] = { row[i], '\0' };
display_obj.tft.print(c);
}
}
// Special row (row index 4): SPACE | BKSP | OK
int r = 4;
int16_t rowY = kY + r * cellH;
// Well divide width into 3 segments
int16_t spaceW = kW / 2; // left half for SPACE
int16_t bkspW = kW / 4; // next quarter for BKSP
int16_t okW = kW - spaceW - bkspW; // remaining for OK
// For alpha row 3, we want row chars towards the left, leaving space for CAPS.
int16_t xOffset;
if (layout == LAYOUT_ALPHA && r == 3) {
// Use columns 0..7 for characters, 8..9 for CAPS
xOffset = 0;
} else {
int maxColsRow = maxCols;
xOffset = (maxColsRow - rowLen);
if (xOffset < 0) xOffset = 0;
xOffset = (xOffset * cellW) / 2; // center row
}
int16_t keyX = kX;
// SPACE
display_obj.tft.drawRect(keyX, rowY, spaceW, cellH, TFT_BLACK);
display_obj.tft.setCursor(keyX + 4, rowY + cellH / 2 - 4);
display_obj.tft.print("SPACE");
for (int i = 0; i < rowLen; ++i) {
int16_t keyX = kX + xOffset + i * cellW;
int16_t keyY = rowY;
keyX += spaceW;
// BKSP
display_obj.tft.drawRect(keyX, rowY, bkspW, cellH, TFT_BLACK);
display_obj.tft.setCursor(keyX + 4, rowY + cellH / 2 - 4);
display_obj.tft.print("BKSP");
// Key border
display_obj.tft.drawRect(keyX, keyY, cellW, cellH, TFT_BLACK);
keyX += bkspW;
// OK
display_obj.tft.drawRect(keyX, rowY, okW, cellH, TFT_BLACK);
display_obj.tft.setCursor(keyX + okW / 2 - 6, rowY + cellH / 2 - 4);
display_obj.tft.print("OK");
// Label
display_obj.tft.setCursor(keyX + cellW / 2 - 3, keyY + cellH / 2 - 4);
char c = row[i];
// Apply CAPS on alpha letters
if (layout == LAYOUT_ALPHA && r > 0) {
if (c >= 'a' && c <= 'z') {
if (caps) {
c = (char)(c - 'a' + 'A');
}
}
}
char s[2] = { c, '\0' };
display_obj.tft.print(s);
}
// Draw CAPS key for alpha layout on row 3 (rightmost two columns)
if (layout == LAYOUT_ALPHA && r == 3) {
int16_t capsX = kX + 8 * cellW;
int16_t capsW = 2 * cellW;
display_obj.tft.drawRect(capsX, rowY, capsW, cellH, TFT_BLACK);
display_obj.tft.setCursor(capsX + 4, rowY + cellH / 2 - 4);
// Show different label based on state
if (caps) {
display_obj.tft.print("caps");
} else {
display_obj.tft.print("CAPS");
}
}
}
// Special row (row index 4): CANCEL | SYMB/ABC | SPACE | BKSP | OK
int r = 4;
int16_t rowY = kY + r * cellH;
// Divide width into 6 segments:
// [CANCEL][SYMB][SPACE (2 segments)][BKSP][OK]
int16_t segW = kW / 6;
int16_t x0 = kX;
int16_t x1 = x0 + segW; // end CANCEL
int16_t x2 = x1 + segW; // end SYMB
int16_t x3 = x2 + 2 * segW; // end SPACE
int16_t x4 = x3 + segW; // end BKSP
int16_t x5 = x4 + segW; // end OK
// CANCEL
display_obj.tft.drawRect(x0, rowY, segW, cellH, TFT_BLACK);
display_obj.tft.setCursor(x0 + 4, rowY + cellH / 2 - 4);
display_obj.tft.print("CANCEL");
// SYMB / ABC
display_obj.tft.drawRect(x1, rowY, segW, cellH, TFT_BLACK);
display_obj.tft.setCursor(x1 + 4, rowY + cellH / 2 - 4);
if (layout == LAYOUT_ALPHA) {
display_obj.tft.print("SYMB");
} else {
display_obj.tft.print("ABC");
}
display_obj.tft.drawRect(x2, rowY, (x3 - x2), cellH, TFT_BLACK);
display_obj.tft.setCursor(x2 + 4, rowY + cellH / 2 - 4);
display_obj.tft.print("SPACE");
display_obj.tft.drawRect(x3, rowY, (x4 - x3), cellH, TFT_BLACK);
display_obj.tft.setCursor(x3 + 4, rowY + cellH / 2 - 4);
display_obj.tft.print("BKSP");
display_obj.tft.drawRect(x4, rowY, (x5 - x4), cellH, TFT_BLACK);
display_obj.tft.setCursor(x4 + 4, rowY + cellH / 2 - 4);
display_obj.tft.print("OK");
}
// --- Helper: process a touch and update buffer ---
static bool appendChar(char *buffer, size_t bufLen, char c) {
size_t len = strlen(buffer);
if (len + 1 < bufLen) {
buffer[len] = c;
buffer[len + 1] = '\0';
return true;
}
return false;
}
static KeyboardResult handleKeyboardTouch(uint16_t tx, uint16_t ty,
char *buffer, size_t bufLen)
{
if (!buffer || bufLen < 2) return KB_NONE;
char *buffer, size_t bufLen,
KeyboardLayout layout,
bool caps) {
if (!buffer || bufLen < 2) return KB_NONE;
const int16_t kY = kbYStart();
const int16_t kH = kbHeight();
const int16_t kX = kbXStart();
const int16_t kW = kbWidth();
if (ty < kY || ty >= (kY + kH)) {
// Touch is outside keyboard area
return KB_NONE;
}
const int maxCols = 10;
const int rows = KEY_ROWS;
const int16_t cellW = kW / maxCols;
const int16_t cellH = kH / rows;
int rowIndex = (ty - kY) / cellH;
// Normal rows (0..3)
if (rowIndex >= 0 && rowIndex <= 3) {
const char *rowStrings[4] = { ROW0, ROW1, ROW2, ROW3 };
const char *row = rowStrings[rowIndex];
int rowLen = strlen(row);
int16_t rowY = kY + rowIndex * cellH;
int16_t xOffset = (maxCols - rowLen);
if (xOffset < 0) xOffset = 0;
xOffset = (xOffset * cellW) / 2;
// Determine which key in this row
if (tx < kX + xOffset || tx >= kX + xOffset + rowLen * cellW) {
return KB_NONE;
}
int colIndex = (tx - (kX + xOffset)) / cellW;
if (colIndex < 0 || colIndex >= rowLen) return KB_NONE;
char c = row[colIndex];
// Append char if space
size_t len = strlen(buffer);
if (len + 1 < bufLen) {
buffer[len] = c;
buffer[len + 1] = '\0';
return KB_CHANGED;
}
return KB_NONE;
}
// Special row (rowIndex == 4): SPACE | BKSP | OK
if (rowIndex == 4) {
int16_t rowY = kY + rowIndex * cellH;
int16_t spaceW = kW / 2;
int16_t bkspW = kW / 4;
int16_t okW = kW - spaceW - bkspW;
int16_t x0 = kX;
int16_t x1 = x0 + spaceW;
int16_t x2 = x1 + bkspW;
int16_t x3 = x2 + okW;
// SPACE
if (tx >= x0 && tx < x1) {
size_t len = strlen(buffer);
if (len + 1 < bufLen) {
buffer[len] = ' ';
buffer[len + 1] = '\0';
return KB_CHANGED;
}
return KB_NONE;
}
// BKSP
if (tx >= x1 && tx < x2) {
size_t len = strlen(buffer);
if (len > 0) {
buffer[len - 1] = '\0';
return KB_CHANGED;
}
return KB_NONE;
}
// OK
if (tx >= x2 && tx < x3) {
return KB_DONE;
}
}
const int16_t kY = kbYStart();
const int16_t kH = kbHeight();
const int16_t kX = kbXStart();
const int16_t kW = kbWidth();
if (ty < kY || ty >= (kY + kH)) {
// Touch is outside keyboard area
return KB_NONE;
}
const int maxCols = 10;
const int rows = KEY_ROWS;
const int16_t cellW = kW / maxCols;
const int16_t cellH = kH / rows;
int rowIndex = (ty - kY) / cellH;
// Choose row strings based on layout
const char *rowStringsAlpha[4] = {
ROW0_ALPHA, ROW1_ALPHA, ROW2_ALPHA, ROW3_ALPHA
};
const char *rowStringsSym[4] = {
ROW0_SYM, ROW1_SYM, ROW2_SYM, ROW3_SYM
};
const char **rowsPtr = (layout == LAYOUT_ALPHA)
? (const char **)rowStringsAlpha
: (const char **)rowStringsSym;
// Normal rows (0..3)
if (rowIndex >= 0 && rowIndex <= 3) {
const char *row = rowsPtr[rowIndex];
int rowLen = strlen(row);
int16_t rowY = kY + rowIndex * cellH;
// Alpha row 3: characters on columns 0..7, CAPS on columns 8..9
if (layout == LAYOUT_ALPHA && rowIndex == 3) {
int16_t capsXStart = kX + 8 * cellW;
int16_t capsXEnd = capsXStart + 2 * cellW;
// Check CAPS region
if (tx >= capsXStart && tx < capsXEnd) {
return KB_TOGGLE_CAPS;
}
// Characters only in the columns before CAPS
int16_t xOffset = 0;
if (tx < kX || tx >= (kX + 8 * cellW)) {
return KB_NONE;
}
int colIndex = (tx - (kX + xOffset)) / cellW;
if (colIndex < 0 || colIndex >= rowLen) return KB_NONE;
char c = row[colIndex];
// Apply caps mapping
if (c >= 'a' && c <= 'z' && caps) {
c = (char)(c - 'a' + 'A');
}
if (appendChar(buffer, bufLen, c)) {
return KB_CHANGED;
}
return KB_NONE;
}
// All other rows
int16_t xOffset = (maxCols - rowLen);
if (xOffset < 0) xOffset = 0;
xOffset = (xOffset * cellW) / 2;
if (tx < kX + xOffset || tx >= kX + xOffset + rowLen * cellW) {
return KB_NONE;
}
int colIndex = (tx - (kX + xOffset)) / cellW;
if (colIndex < 0 || colIndex >= rowLen) return KB_NONE;
char c = row[colIndex];
// Apply caps on alpha letters (rows 1 and 2)
if (layout == LAYOUT_ALPHA && rowIndex > 0) {
if (c >= 'a' && c <= 'z' && caps) {
c = (char)(c - 'a' + 'A');
}
}
if (appendChar(buffer, bufLen, c)) {
return KB_CHANGED;
}
return KB_NONE;
}
// Special row (rowIndex == 4): CANCEL | SYMB/ABC | SPACE | BKSP | OK
if (rowIndex == 4) {
int16_t rowY = kY + rowIndex * cellH;
int16_t segW = kW / 6;
int16_t x0 = kX;
int16_t x1 = x0 + segW; // end CANCEL
int16_t x2 = x1 + segW; // end SYMB
int16_t x3 = x2 + 2 * segW; // end SPACE
int16_t x4 = x3 + segW; // end BKSP
int16_t x5 = x4 + segW; // end OK
// CANCEL
if (tx >= x0 && tx < x1) {
return KB_CANCEL;
}
// SYMB / ABC toggle
if (tx >= x1 && tx < x2) {
return KB_TOGGLE_LAYOUT;
}
// SPACE (x2..x3)
if (tx >= x2 && tx < x3) {
if (appendChar(buffer, bufLen, ' ')) {
return KB_CHANGED;
}
return KB_NONE;
}
// BKSP (x3..x4)
if (tx >= x3 && tx < x4) {
size_t len = strlen(buffer);
if (len > 0) {
buffer[len - 1] = '\0';
return KB_CHANGED;
}
return KB_NONE;
}
// OK (x4..x5)
if (tx >= x4 && tx < x5) {
return KB_DONE;
}
}
return KB_NONE;
}
// --- Public API: blocking keyboard input ---
bool keyboardInput(char *buffer, size_t bufLen, const char *title)
{
if (!buffer || bufLen < 2) {
bool keyboardInput(char *buffer, size_t bufLen, const char *title) {
if (!buffer || bufLen < 2) {
return false;
}
// To force clear, uncomment this:
// buffer[0] = '\0';
KeyboardLayout layout = LAYOUT_ALPHA;
bool caps = false;
drawTextArea(title, buffer);
drawKeyboard(layout, caps);
uint32_t lastTouchTime = 0;
const uint32_t debounceMs = 120;
while (true) {
uint16_t x = 0, y = 0;
uint8_t touched = display_obj.updateTouch(&x, &y, TOUCH_THRESHOLD);
if (touched) {
uint32_t now = millis();
if (now - lastTouchTime < debounceMs) {
// "debounce"
continue;
}
lastTouchTime = now;
KeyboardResult r = handleKeyboardTouch(x, y, buffer, bufLen, layout, caps);
if (r == KB_CHANGED) {
drawTextArea(title, buffer);
} else if (r == KB_DONE) {
drawTextArea(title, buffer);
return true;
} else if (r == KB_CANCEL) {
// Optional: buffer[0] = '\0';
drawTextArea(title, buffer);
return false;
} else if (r == KB_TOGGLE_LAYOUT) {
layout = (layout == LAYOUT_ALPHA) ? LAYOUT_SYMBOLS : LAYOUT_ALPHA;
drawKeyboard(layout, caps);
} else if (r == KB_TOGGLE_CAPS) {
caps = !caps;
drawKeyboard(layout, caps);
}
}
// Preserve existing buffer content (caller may prefill) or clear:
// buffer[0] = '\0';
delay(5);
yield();
}
drawTextArea(title, buffer);
drawKeyboard();
uint32_t lastTouchTime = 0;
const uint32_t debounceMs = 120;
while (true) {
uint16_t x = 0, y = 0;
uint8_t touched = display_obj.updateTouch(&x, &y, TOUCH_THRESHOLD);
if (touched) {
uint32_t now = millis();
if (now - lastTouchTime < debounceMs) {
// crude debounce
continue;
}
lastTouchTime = now;
KeyboardResult r = handleKeyboardTouch(x, y, buffer, bufLen);
if (r == KB_CHANGED) {
drawTextArea(title, buffer);
} else if (r == KB_DONE) {
// Redraw once more to ensure final text shown (optional)
drawTextArea(title, buffer);
return true;
}
}
// Allow other tasks / WiFi / BLE to run
delay(5);
yield();
}
// Unreachable
// return false;
return false;
}
#endif

View File

@@ -9,9 +9,12 @@
#include <stdint.h>
enum KeyboardResult {
KB_NONE = 0,
KB_CHANGED,
KB_DONE
KB_NONE = 0,
KB_CHANGED,
KB_DONE,
KB_CANCEL,
KB_TOGGLE_LAYOUT,
KB_TOGGLE_CAPS
};
/**
@@ -21,8 +24,7 @@ enum KeyboardResult {
* @param bufLen Total size of the buffer (including space for '\0').
* @param title Optional title displayed above the text box (can be nullptr).
*
* @return true if user pressed OK, false if aborted (currently: youd have to
* add your own external abort condition e.g. button press).
* @return true if user pressed OK, false if user pressed CANCEL (or if buffer invalid).
*/
bool keyboardInput(char *buffer, size_t bufLen, const char *title = nullptr);

View File

@@ -630,6 +630,7 @@ extern "C" {
#ifdef HAS_SCREEN
String display_string = "";
display_string.concat(CYAN_KEY);
display_string.concat(String(rssi));
display_string.concat(" ");
if (serial.length()) {
@@ -1349,6 +1350,7 @@ extern "C" {
#ifdef HAS_SCREEN
String display_string = "";
display_string.concat(CYAN_KEY);
display_string.concat(String(rssi));
display_string.concat(" ");
if (serial.length()) {
@@ -1879,7 +1881,7 @@ bool WiFiScan::joinWiFi(String ssid, String password, bool gui)
int count = 0;
if ((WiFi.status() == WL_CONNECTED) && (ssid == connected_network) && (ssid != "")) {
#ifdef HAS_TOUCH
/*#ifdef HAS_TOUCH
if (gui) {
lv_obj_t * mbox1 = lv_msgbox_create(lv_scr_act(), NULL);
lv_msgbox_set_text(mbox1, text_table4[2]);
@@ -1887,7 +1889,7 @@ bool WiFiScan::joinWiFi(String ssid, String password, bool gui)
lv_obj_set_width(mbox1, 200);
lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0); //Align to the corner
}
#endif
#endif*/
this->wifi_initialized = true;
this->currentScanMode = WIFI_CONNECTED;
return true;
@@ -1908,7 +1910,7 @@ bool WiFiScan::joinWiFi(String ssid, String password, bool gui)
WiFi.begin(ssid.c_str(), password.c_str());
#ifdef HAS_SCREEN
#ifdef HAS_MINI_KB
//#ifdef HAS_MINI_KB
if (gui) {
display_obj.clearScreen();
display_obj.tft.setCursor(0, TFT_HEIGHT / 2);
@@ -1916,7 +1918,7 @@ bool WiFiScan::joinWiFi(String ssid, String password, bool gui)
display_obj.tft.print("Connecting");
display_obj.tft.setTextWrap(true, false);
}
#endif
//#endif
#endif
Serial.print(F("Connecting to WiFi"));
@@ -1924,25 +1926,25 @@ bool WiFiScan::joinWiFi(String ssid, String password, bool gui)
delay(500);
Serial.print(".");
#ifdef HAS_SCREEN
#ifdef HAS_MINI_KB
//#ifdef HAS_MINI_KB
if (gui) {
display_obj.tft.print(".");
}
#endif
//#endif
#endif
count++;
if (count == 20)
{
Serial.println(F("\nCould not connect to WiFi network"));
#ifdef HAS_SCREEN
#ifdef HAS_MINI_KB
//#ifdef HAS_MINI_KB
if (gui) {
display_obj.tft.println("\nFailed to connect");
delay(1000);
}
#endif
//#endif
#endif
#ifdef HAS_TOUCH
/*#ifdef HAS_TOUCH
if (gui) {
lv_obj_t * mbox1 = lv_msgbox_create(lv_scr_act(), NULL);
lv_msgbox_set_text(mbox1, text_table4[3]);
@@ -1951,7 +1953,7 @@ bool WiFiScan::joinWiFi(String ssid, String password, bool gui)
//lv_obj_set_event_cb(mbox1, event_handler);
lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0); //Align to the corner
}
#endif
#endif*/
this->wifi_initialized = true;
this->StartScan(WIFI_SCAN_OFF, TFT_BLACK);
#ifdef HAS_SCREEN
@@ -1961,19 +1963,19 @@ bool WiFiScan::joinWiFi(String ssid, String password, bool gui)
}
}
#ifdef HAS_TOUCH
/*#ifdef HAS_TOUCH
lv_obj_t * mbox1 = lv_msgbox_create(lv_scr_act(), NULL);
lv_msgbox_set_text(mbox1, text_table4[4]);
lv_msgbox_add_btns(mbox1, btns);
lv_obj_set_width(mbox1, 200);
lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0); //Align to the corner
#endif
#endif*/
this->connected_network = ssid;
this->setNetworkInfo();
this->showNetworkInfo();
#ifdef HAS_SCREEN
#ifdef HAS_MINI_KB
//#ifdef HAS_MINI_KB
display_obj.tft.println("\nConnected!");
display_obj.tft.print("IP address: ");
display_obj.tft.println(this->ip_addr);
@@ -1985,7 +1987,7 @@ bool WiFiScan::joinWiFi(String ssid, String password, bool gui)
display_obj.tft.println(WiFi.macAddress());
display_obj.tft.println("Returning...");
delay(2000);
#endif
//#endif
#endif
this->wifi_initialized = true;
#ifndef HAS_TOUCH
@@ -2007,7 +2009,7 @@ bool WiFiScan::startWiFi(String ssid, String password, bool gui)
int count = 0;
if ((WiFi.status() == WL_CONNECTED) && (ssid == connected_network) && (ssid != "")) {
#ifdef HAS_TOUCH
/*#ifdef HAS_TOUCH
if (gui) {
lv_obj_t * mbox1 = lv_msgbox_create(lv_scr_act(), NULL);
lv_msgbox_set_text(mbox1, text_table4[2]);
@@ -2015,7 +2017,7 @@ bool WiFiScan::startWiFi(String ssid, String password, bool gui)
lv_obj_set_width(mbox1, 200);
lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0); //Align to the corner
}
#endif
#endif*/
this->wifi_initialized = true;
this->currentScanMode = WIFI_CONNECTED;
return true;
@@ -2039,7 +2041,7 @@ bool WiFiScan::startWiFi(String ssid, String password, bool gui)
WiFi.softAP(ssid.c_str());
#ifdef HAS_SCREEN
#ifdef HAS_MINI_KB
//#ifdef HAS_MINI_KB
if (gui) {
display_obj.clearScreen();
display_obj.tft.setCursor(0, TFT_HEIGHT / 2);
@@ -2047,25 +2049,25 @@ bool WiFiScan::startWiFi(String ssid, String password, bool gui)
display_obj.tft.print("Starting");
display_obj.tft.setTextWrap(true, false);
}
#endif
//#endif
#endif
Serial.print(F("Started WiFi"));
#ifdef HAS_TOUCH
/*#ifdef HAS_TOUCH
lv_obj_t * mbox1 = lv_msgbox_create(lv_scr_act(), NULL);
lv_msgbox_set_text(mbox1, text_table4[4]);
lv_msgbox_add_btns(mbox1, btns);
lv_obj_set_width(mbox1, 200);
lv_obj_align(mbox1, NULL, LV_ALIGN_CENTER, 0, 0); //Align to the corner
#endif
#endif*/
this->connected_network = ssid;
this->setNetworkInfo();
this->showNetworkInfo();
#ifdef HAS_SCREEN
#ifdef HAS_MINI_KB
//#ifdef HAS_MINI_KB
display_obj.tft.println(F("\nStarted AP"));
display_obj.tft.print(F("IP address: "));
display_obj.tft.println(this->ip_addr);
@@ -2077,15 +2079,15 @@ bool WiFiScan::startWiFi(String ssid, String password, bool gui)
display_obj.tft.println(WiFi.macAddress());
display_obj.tft.println(F("Returning..."));
delay(2000);
#endif
//#endif
#endif
this->wifi_initialized = true;
#ifndef HAS_TOUCH
//#ifndef HAS_TOUCH
this->currentScanMode = WIFI_CONNECTED;
#ifdef HAS_SCREEN
display_obj.tft.setTextWrap(false, false);
#endif
#endif
//#endif
//settings_obj.saveSetting<bool>("APSSID", ssid);
//settings_obj.saveSetting<bool>("APPW", password);
@@ -3364,7 +3366,7 @@ void WiFiScan::RunAPScan(uint8_t scan_mode, uint16_t color)
#ifdef HAS_SCREEN
void WiFiScan::RunLvJoinWiFi(uint8_t scan_mode, uint16_t color) {
#ifdef HAS_TOUCH
/*#ifdef HAS_TOUCH
display_obj.init();
display_obj.tft.setRotation(1);
#endif
@@ -3378,7 +3380,7 @@ void WiFiScan::RunAPScan(uint8_t scan_mode, uint16_t color)
#ifdef HAS_TOUCH
lv_obj_t * scr = lv_cont_create(NULL, NULL);
lv_disp_load_scr(scr);
#endif
#endif*/
}
#endif
@@ -7160,7 +7162,7 @@ void WiFiScan::beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type
getMAC(addr, snifferPacket->payload, 10);
display_string.concat(MAGENTA_KEY);
display_string.concat((String)snifferPacket->rx_ctrl.rssi);
display_string.concat("PRBE ");
display_string.concat(" ");
display_string.concat(addr);
display_string.concat(" -> ");
display_string.concat(probe_req_essid);
@@ -7198,7 +7200,7 @@ void WiFiScan::beaconSnifferCallback(void* buf, wifi_promiscuous_pkt_type_t type
getMAC(addr, snifferPacket->payload, 10);
display_string.concat(GREEN_KEY);
display_string.concat((String)snifferPacket->rx_ctrl.rssi);
display_string.concat("BECN ");
display_string.concat(" ");
display_string.concat(addr);
display_string.concat(" -> ");
display_string.concat(essid);
@@ -10120,7 +10122,8 @@ void WiFiScan::main(uint32_t currentTime)
(currentScanMode == WIFI_SCAN_MULTISSID) ||
(currentScanMode == WIFI_SCAN_DEAUTH) ||
(currentScanMode == WIFI_SCAN_STATION_WAR_DRIVE) ||
(currentScanMode == WIFI_SCAN_ALL))
(currentScanMode == WIFI_SCAN_ALL) ||
(currentScanMode == BT_SCAN_FLOCK))
{
if (currentTime - initTime >= this->channel_hop_delay * HOP_DELAY)
{