diff --git a/.gitmodules b/.gitmodules index 7c54ad5139..964204476d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,9 @@ [submodule "protobufs"] path = protobufs url = https://github.com/meshtastic/protobufs.git +[submodule "lib/device-ui"] + path = lib/device-ui + url = https://github.com/meshtastic/device-ui.git [submodule "meshtestic"] path = meshtestic url = https://github.com/meshtastic/meshTestic diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini index 1af68198bf..4e3093c558 100644 --- a/arch/nrf52/nrf52.ini +++ b/arch/nrf52/nrf52.ini @@ -24,4 +24,4 @@ lib_deps= lib_ignore = BluetoothOTA - lvgl + lvgl \ No newline at end of file diff --git a/arch/rp2xx0/rp2040.ini b/arch/rp2xx0/rp2040.ini index c004a3becb..62b4ac30c8 100644 --- a/arch/rp2xx0/rp2040.ini +++ b/arch/rp2xx0/rp2040.ini @@ -18,6 +18,7 @@ build_src_filter = lib_ignore = BluetoothOTA + lvgl lib_deps = ${arduino_base.lib_deps} diff --git a/boards/mesh-tab.json b/boards/mesh-tab.json new file mode 100644 index 0000000000..75ac1b5a21 --- /dev/null +++ b/boards/mesh-tab.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MODE=0", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [["0x303A", "0x1001"]], + "mcu": "esp32s3", + "variant": "mesh-tab" + }, + "connectivity": ["wifi", "bluetooth", "lora"], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": ["esp-builtin"], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": ["arduino", "espidf"], + "name": "ESP32-S3 WROOM-1 N16R2 (16 MB FLASH, 2 MB PSRAM)", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://github.com/valzzu/Mesh-Tab", + "vendor": "Espressif" +} diff --git a/boards/seeed-sensecap-indicator.json b/boards/seeed-sensecap-indicator.json index 3fc57126f9..6ce8d36adc 100644 --- a/boards/seeed-sensecap-indicator.json +++ b/boards/seeed-sensecap-indicator.json @@ -15,10 +15,12 @@ ], "f_cpu": "240000000L", "f_flash": "80000000L", + "f_boot": "120000000L", + "boot": "qio", "flash_mode": "qio", "hwids": [["0x1A86", "0x7523"]], "mcu": "esp32s3", - "variant": "esp32s3r8" + "variant": "esp32s3" }, "connectivity": ["wifi", "bluetooth", "lora"], "debug": { diff --git a/boards/t-deck.json b/boards/t-deck.json index d62ec48e65..b112921b9b 100644 --- a/boards/t-deck.json +++ b/boards/t-deck.json @@ -10,7 +10,7 @@ "-DARDUINO_USB_CDC_ON_BOOT=1", "-DARDUINO_USB_MODE=0", "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=0" + "-DARDUINO_EVENT_RUNNING_CORE=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/lib/device-ui b/lib/device-ui new file mode 160000 index 0000000000..6b760f5373 --- /dev/null +++ b/lib/device-ui @@ -0,0 +1 @@ +Subproject commit 6b760f5373b91de1d8234922a446f7232d5247d0 diff --git a/src/configuration.h b/src/configuration.h index cb2326470c..74b68e44f7 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -246,6 +246,9 @@ along with this program. If not, see . #ifndef HAS_SCREEN #define HAS_SCREEN 0 #endif +#ifndef HAS_TFT +#define HAS_TFT 0 +#endif #ifndef HAS_WIRE #define HAS_WIRE 0 #endif diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index d39c9899c5..19b32a1aab 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -490,4 +490,4 @@ size_t ScanI2CTwoWire::countDevices() const { return foundDevices.size(); } -#endif \ No newline at end of file +#endif diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index efa3ec78fe..f78549a2a6 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1709,7 +1709,7 @@ void Screen::setup() #endif serialSinceMsec = millis(); -#if ARCH_PORTDUINO +#if ARCH_PORTDUINO && !HAS_TFT if (settingsMap[touchscreenModule]) { touchScreenImpl1 = new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast(dispdev)->getTouch); diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 3ba847c236..986d081bdf 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -347,12 +347,12 @@ static LGFX *tft = nullptr; #include // Graphics and font library for ILI9342 driver chip static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h -#elif ARCH_PORTDUINO && HAS_SCREEN != 0 +#elif ARCH_PORTDUINO && HAS_SCREEN != 0 && !HAS_TFT #include // Graphics and font library for ST7735 driver chip class LGFX : public lgfx::LGFX_Device { - lgfx::Panel_LCD *_panel_instance; + lgfx::Panel_Device *_panel_instance; lgfx::Bus_SPI _bus_instance; lgfx::ITouch *_touch_instance; @@ -366,10 +366,21 @@ class LGFX : public lgfx::LGFX_Device _panel_instance = new lgfx::Panel_ST7735; else if (settingsMap[displayPanel] == st7735s) _panel_instance = new lgfx::Panel_ST7735S; + else if (settingsMap[displayPanel] == st7796) + _panel_instance = new lgfx::Panel_ST7796; else if (settingsMap[displayPanel] == ili9341) _panel_instance = new lgfx::Panel_ILI9341; else if (settingsMap[displayPanel] == ili9342) _panel_instance = new lgfx::Panel_ILI9342; + else if (settingsMap[displayPanel] == ili9488) + _panel_instance = new lgfx::Panel_ILI9488; + else if (settingsMap[displayPanel] == hx8357d) + _panel_instance = new lgfx::Panel_HX8357D; + else { + _panel_instance = new lgfx::Panel_NULL; + LOG_ERROR("Unknown display panel configured!"); + } + auto buscfg = _bus_instance.config(); buscfg.spi_mode = 0; buscfg.spi_host = settingsMap[displayspidev]; @@ -383,12 +394,12 @@ class LGFX : public lgfx::LGFX_Device LOG_DEBUG("Height: %d, Width: %d ", settingsMap[displayHeight], settingsMap[displayWidth]); cfg.pin_cs = settingsMap[displayCS]; // Pin number where CS is connected (-1 = disable) cfg.pin_rst = settingsMap[displayReset]; - cfg.panel_width = settingsMap[displayWidth]; // actual displayable width - cfg.panel_height = settingsMap[displayHeight]; // actual displayable height - cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction - cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction - cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is mirrored) - cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed + cfg.panel_width = settingsMap[displayWidth]; // actual displayable width + cfg.panel_height = settingsMap[displayHeight]; // actual displayable height + cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction + cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction + cfg.offset_rotation = settingsMap[displayOffsetRotate]; // Rotation direction value offset 0~7 (4~7 is mirrored) + cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed _panel_instance->config(cfg); @@ -410,7 +421,7 @@ class LGFX : public lgfx::LGFX_Device touch_cfg.y_max = settingsMap[displayWidth] - 1; touch_cfg.pin_int = settingsMap[touchscreenIRQ]; touch_cfg.bus_shared = true; - touch_cfg.offset_rotation = 1; + touch_cfg.offset_rotation = settingsMap[touchscreenRotate]; if (settingsMap[touchscreenI2CAddr] != -1) { touch_cfg.i2c_addr = settingsMap[touchscreenI2CAddr]; } else { diff --git a/src/main.cpp b/src/main.cpp index 0ce6b3bae6..db1b205ad4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,6 +41,7 @@ #include #ifdef ARCH_ESP32 +#include "freertosinc.h" #if !MESHTASTIC_EXCLUDE_WEBSERVER #include "mesh/http/WebServer.h" #endif @@ -113,6 +114,18 @@ AccelerometerThread *accelerometerThread = nullptr; AudioThread *audioThread = nullptr; #endif +#if HAS_TFT +#include "DeviceScreen.h" +#include "DisplayDriverConfig.h" +#include "PacketClient.h" +#include "PacketServer.h" +#include "api/PacketAPI.h" + +void tft_task_handler(void *); + +DeviceScreen *deviceScreen = nullptr; +#endif + #if defined(TCXO_OPTIONAL) float tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE; // if TCXO is optional, put this here so it can be changed further down. #endif @@ -177,6 +190,8 @@ std::pair nodeTelemetrySensorsMap[_meshtastic_TelemetrySenso Router *router = NULL; // Users of router don't care what sort of subclass implements that API +const char *firmware_version = optstr(APP_VERSION_SHORT); + const char *getDeviceName() { uint8_t dmac[6]; @@ -279,6 +294,7 @@ void setup() #endif powerMonInit(); + serialSinceMsec = millis(); LOG_INFO("\n\n//\\ E S H T /\\ S T / C\n"); @@ -414,13 +430,13 @@ void setup() digitalWrite(AQ_SET_PIN, HIGH); #endif -#ifdef T_DECK +#if defined(T_DECK) // enable keyboard pinMode(KB_POWERON, OUTPUT); digitalWrite(KB_POWERON, HIGH); // There needs to be a delay after power on, give LILYGO-KEYBOARD some startup time // otherwise keyboard and touch screen will not work - delay(800); + delay(200); #endif // Currently only the tbeam has a PMU @@ -594,7 +610,6 @@ void setup() SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221) SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048) SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808) SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31) SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHTC3, meshtastic_TelemetrySensorType_SHTC3) SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::LPS22HB, meshtastic_TelemetrySensorType_LPS22) @@ -733,11 +748,92 @@ void setup() SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); LOG_DEBUG("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); SPI.setFrequency(4000000); +#endif +#if HAS_TFT +#ifdef PORTDUINO + if (settingsMap[displayPanel] != no_screen) { + DisplayDriverConfig displayConfig; + static char *panels[] = {"NOSCREEN", "X11", "ST7789", "ST7735", "ST7735S", "ST7796", + "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"}; + static char *touch[] = {"NOTOUCH", "XPT2046", "STMPE610", "GT911", "FT5x06"}; +#ifdef USE_X11 + if (settingsMap[displayPanel] == x11) { + if (settingsMap[displayWidth] && settingsMap[displayHeight]) + displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::X11, (uint16_t)settingsMap[displayWidth], + (uint16_t)settingsMap[displayHeight]); + else + displayConfig.device(DisplayDriverConfig::device_t::X11); + } else +#endif + { + displayConfig.device(DisplayDriverConfig::device_t::CUSTOM_TFT) + .panel(DisplayDriverConfig::panel_config_t{.type = panels[settingsMap[displayPanel]], + .panel_width = (uint16_t)settingsMap[displayWidth], + .panel_height = (uint16_t)settingsMap[displayHeight], + .rotation = (bool)settingsMap[displayRotate], + .pin_cs = (int16_t)settingsMap[displayCS], + .pin_rst = (int16_t)settingsMap[displayReset], + .offset_x = (uint16_t)settingsMap[displayOffsetX], + .offset_y = (uint16_t)settingsMap[displayOffsetY], + .offset_rotation = (uint8_t)settingsMap[displayOffsetRotate], + .invert = settingsMap[displayInvert] ? true : false, + .rgb_order = (bool)settingsMap[displayRGBOrder], + .dlen_16bit = settingsMap[displayPanel] == ili9486 || + settingsMap[displayPanel] == ili9488}) + .bus(DisplayDriverConfig::bus_config_t{.freq_write = (uint32_t)settingsMap[displayBusFrequency], + .freq_read = 16000000, + .spi{.pin_dc = (int8_t)settingsMap[displayDC], + .use_lock = true, + .spi_host = (uint16_t)settingsMap[displayspidev]}}) + .input(DisplayDriverConfig::input_config_t{.keyboardDevice = settingsStrings[keyboardDevice], + .pointerDevice = settingsStrings[pointerDevice]}) + .light(DisplayDriverConfig::light_config_t{.pin_bl = (int16_t)settingsMap[displayBacklight], + .pwm_channel = (int8_t)settingsMap[displayBacklightPWMChannel], + .invert = (bool)settingsMap[displayBacklightInvert]}); + if (settingsMap[touchscreenI2CAddr] == -1) { + displayConfig.touch( + DisplayDriverConfig::touch_config_t{.type = touch[settingsMap[touchscreenModule]], + .freq = (uint32_t)settingsMap[touchscreenBusFrequency], + .pin_int = (int16_t)settingsMap[touchscreenIRQ], + .offset_rotation = (uint8_t)settingsMap[touchscreenRotate], + .spi{ + .spi_host = (int8_t)settingsMap[touchscreenspidev], + }, + .pin_cs = (int16_t)settingsMap[touchscreenCS]}); + } else { + displayConfig.touch(DisplayDriverConfig::touch_config_t{ + .type = touch[settingsMap[touchscreenModule]], + .freq = (uint32_t)settingsMap[touchscreenBusFrequency], + .x_min = 0, + .x_max = + (int16_t)((settingsMap[touchscreenRotate] & 1 ? settingsMap[displayWidth] : settingsMap[displayHeight]) - + 1), + .y_min = 0, + .y_max = + (int16_t)((settingsMap[touchscreenRotate] & 1 ? settingsMap[displayHeight] : settingsMap[displayWidth]) - + 1), + .pin_int = (int16_t)settingsMap[touchscreenIRQ], + .offset_rotation = (uint8_t)settingsMap[touchscreenRotate], + .i2c{.i2c_addr = (uint8_t)settingsMap[touchscreenI2CAddr]}}); + } + } + deviceScreen = &DeviceScreen::create(&displayConfig); + PacketAPI::create(PacketServer::init()); + deviceScreen->init(new PacketClient); + } else { + LOG_INFO("Running without TFT display!"); + } +#else + deviceScreen = &DeviceScreen::create(); + PacketAPI::create(PacketServer::init()); + deviceScreen->init(new PacketClient); +#endif #endif // Initialize the screen first so we can show the logo while we start up everything else. +#if HAS_SCREEN screen = new graphics::Screen(screen_found, screen_model, screen_geometry); - +#endif // setup TZ prior to time actions. #if !MESHTASTIC_EXCLUDE_TZ LOG_DEBUG("Using compiled/slipstreamed %s", slipstreamTZString); // important, removing this clobbers our magic string @@ -1137,7 +1233,19 @@ void setup() // This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values PowerFSM_setup(); // we will transition to ON in a couple of seconds, FIXME, only do this for cold boots, not waking from SDS powerFSMthread = new PowerFSMThread(); + +#if HAS_TFT +#ifdef HAS_FREE_RTOS + xTaskCreatePinnedToCore(tft_task_handler, "tft", 8192, NULL, 1, NULL, 0); +#endif +#else setCPUFast(false); // 80MHz is fine for our slow peripherals +#endif + +#ifdef ARDUINO_ARCH_ESP32 + LOG_DEBUG("Free heap : %7d bytes", ESP.getFreeHeap()); + LOG_DEBUG("Free PSRAM : %7d bytes", ESP.getFreePsram()); +#endif } #endif uint32_t rebootAtMsec; // If not zero we will reboot at this time (used to reboot shortly after the update completes) @@ -1165,6 +1273,7 @@ extern meshtastic_DeviceMetadata getDeviceMetadata() #endif return deviceMetadata; } + #ifndef PIO_UNIT_TESTING void loop() { @@ -1196,3 +1305,22 @@ void loop() } } #endif + +#if HAS_TFT +void tft_task_handler(void *param = nullptr) +{ + while (true) { + if (deviceScreen) { + spiLock->lock(); + deviceScreen->task_handler(); + spiLock->unlock(); + } +#ifdef HAS_FREE_RTOS + vTaskDelay(5 / portTICK_PERIOD_MS); +#else + delay(5); +#endif + } +} + +#endif \ No newline at end of file diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 6b29919587..2bed40f008 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -58,6 +58,7 @@ NodeDB *nodeDB = nullptr; EXT_RAM_BSS_ATTR meshtastic_DeviceState devicestate; meshtastic_MyNodeInfo &myNodeInfo = devicestate.my_node; meshtastic_LocalConfig config; +meshtastic_DeviceUIConfig uiconfig{.screen_brightness = 153, .screen_timeout = 30}; meshtastic_LocalModuleConfig moduleConfig; meshtastic_ChannelFile channelFile; @@ -298,6 +299,13 @@ bool NodeDB::resetRadioConfig(bool factory_reset) rebootAtMsec = millis() + (5 * 1000); } +#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3)) && defined(HAS_TFT) + // as long as PhoneAPI shares BT and TFT app switch BT off + config.bluetooth.enabled = false; + if (moduleConfig.external_notification.nag_timeout == 60) + moduleConfig.external_notification.nag_timeout = 0; +#endif + return didFactoryReset; } @@ -748,6 +756,7 @@ void NodeDB::pickNewNodeNum() static const char *prefFileName = "/prefs/db.proto"; static const char *configFileName = "/prefs/config.proto"; +static const char *uiconfigFileName = "/prefs/uiconfig.proto"; static const char *moduleConfigFileName = "/prefs/module.proto"; static const char *channelFileName = "/prefs/channels.proto"; @@ -850,6 +859,12 @@ void NodeDB::loadFromDisk() } } + state = loadProto(uiconfigFileName, meshtastic_DeviceUIConfig_size, sizeof(meshtastic_DeviceUIConfig), + &meshtastic_DeviceUIConfig_msg, &uiconfig); + if (state == LoadFileResult::LOAD_SUCCESS) { + LOG_INFO("Loaded UIConfig"); + } + // 2.4.X - configuration migration to update new default intervals if (moduleConfig.version < 23) { LOG_DEBUG("ModuleConfig version %d is stale, upgrading to new default intervals", moduleConfig.version); diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index eb33a2f6d4..095e75500f 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -29,6 +29,7 @@ extern meshtastic_DeviceState devicestate; extern meshtastic_ChannelFile channelFile; extern meshtastic_MyNodeInfo &myNodeInfo; extern meshtastic_LocalConfig config; +extern meshtastic_DeviceUIConfig uiconfig; extern meshtastic_LocalModuleConfig moduleConfig; extern meshtastic_User &owner; extern meshtastic_Position localPosition; diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 98db38c47b..8a8838af1a 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -165,6 +165,7 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength) * * Our sending states progress in the following sequence (the client apps ASSUME THIS SEQUENCE, DO NOT CHANGE IT): STATE_SEND_MY_INFO, // send our my info record + STATE_SEND_UIDATA, STATE_SEND_OWN_NODEINFO, STATE_SEND_METADATA, STATE_SEND_CHANNELS @@ -190,18 +191,24 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) case STATE_SEND_NOTHING: LOG_INFO("getFromRadio=STATE_SEND_NOTHING"); break; - case STATE_SEND_MY_INFO: LOG_INFO("getFromRadio=STATE_SEND_MY_INFO"); // If the user has specified they don't want our node to share its location, make sure to tell the phone // app not to send locations on our behalf. fromRadioScratch.which_payload_variant = meshtastic_FromRadio_my_info_tag; fromRadioScratch.my_info = myNodeInfo; - state = STATE_SEND_OWN_NODEINFO; + state = STATE_SEND_UIDATA; service->refreshLocalMeshNode(); // Update my NodeInfo because the client will be asking for it soon. break; + case STATE_SEND_UIDATA: + LOG_INFO("getFromRadio=STATE_SEND_UIDATA"); + fromRadioScratch.which_payload_variant = meshtastic_FromRadio_deviceuiConfig_tag; + fromRadioScratch.deviceuiConfig = uiconfig; + state = STATE_SEND_OWN_NODEINFO; + break; + case STATE_SEND_OWN_NODEINFO: { LOG_INFO("getFromRadio=STATE_SEND_OWN_NODEINFO"); auto us = nodeDB->readNextMeshNode(readIndex); @@ -274,9 +281,12 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) fromRadioScratch.config.which_payload_variant = meshtastic_Config_security_tag; fromRadioScratch.config.payload_variant.security = config.security; break; - case meshtastic_Config_sessionkey_tag: + case meshtastic_Config_sessionkey_tag: // NOOP! fromRadioScratch.config.which_payload_variant = meshtastic_Config_sessionkey_tag; break; + case meshtastic_Config_device_ui_tag: // NOOP! + fromRadioScratch.config.which_payload_variant = meshtastic_Config_device_ui_tag; + break; default: LOG_ERROR("Unknown config type %d", config_state); } @@ -500,6 +510,7 @@ bool PhoneAPI::available() case STATE_SEND_NOTHING: return false; case STATE_SEND_MY_INFO: + case STATE_SEND_UIDATA: case STATE_SEND_CHANNELS: case STATE_SEND_CONFIG: case STATE_SEND_MODULECONFIG: diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index 3247fee5c3..5b92d45d1b 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -34,6 +34,7 @@ class PhoneAPI { enum State { STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config + STATE_SEND_UIDATA, // send stored data for device-ui STATE_SEND_MY_INFO, // send our my info record STATE_SEND_OWN_NODEINFO, STATE_SEND_METADATA, @@ -148,6 +149,9 @@ class PhoneAPI */ virtual void onNowHasData(uint32_t fromRadioNum) {} + /// begin a new connection + void handleStartConfig(); + private: void releasePhonePacket(); @@ -157,9 +161,6 @@ class PhoneAPI void releaseClientNotification(); - /// begin a new connection - void handleStartConfig(); - bool wasSeenRecently(uint32_t packetId); /** diff --git a/src/mesh/api/PacketAPI.cpp b/src/mesh/api/PacketAPI.cpp new file mode 100644 index 0000000000..6c3604efd9 --- /dev/null +++ b/src/mesh/api/PacketAPI.cpp @@ -0,0 +1,100 @@ +#ifdef USE_PACKET_API + +#include "api/PacketAPI.h" +#include "MeshService.h" +#include "PowerFSM.h" +#include "RadioInterface.h" +#include "modules/NodeInfoModule.h" + +PacketAPI *packetAPI = nullptr; + +PacketAPI *PacketAPI::create(PacketServer *_server) +{ + if (!packetAPI) { + packetAPI = new PacketAPI(_server); + } + return packetAPI; +} + +PacketAPI::PacketAPI(PacketServer *_server) : concurrency::OSThread("PacketAPI"), isConnected(false), server(_server) {} + +int32_t PacketAPI::runOnce() +{ + bool success = sendPacket(); + success |= receivePacket(); + return success ? 10 : 50; +} + +bool PacketAPI::receivePacket(void) +{ + bool data_received = false; + while (server->hasData()) { + isConnected = true; + data_received = true; + + powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); + lastContactMsec = millis(); + + meshtastic_ToRadio *mr; + auto p = server->receivePacket()->move(); + int id = p->getPacketId(); + LOG_DEBUG("Received packet id=%u", id); + mr = (meshtastic_ToRadio *)&static_cast *>(p.get())->getData(); + + switch (mr->which_payload_variant) { + case meshtastic_ToRadio_packet_tag: { + meshtastic_MeshPacket *mp = &mr->packet; + printPacket("PACKET FROM QUEUE", mp); + service->handleToRadio(*mp); + break; + } + case meshtastic_ToRadio_want_config_id_tag: { + uint32_t config_nonce = mr->want_config_id; + LOG_INFO("Screen wants config, nonce=%u", config_nonce); + handleStartConfig(); + break; + } + case meshtastic_ToRadio_heartbeat_tag: + if (mr->heartbeat.dummy_field == 1) { + if (nodeInfoModule) { + LOG_INFO("Broadcasting nodeinfo ping"); + nodeInfoModule->sendOurNodeInfo(NODENUM_BROADCAST, true, 0, true); + } + } else { + LOG_DEBUG("Got client heartbeat"); + } + break; + default: + LOG_ERROR("Error: unhandled meshtastic_ToRadio variant: %d", mr->which_payload_variant); + break; + } + } + return data_received; +} + +bool PacketAPI::sendPacket(void) +{ + // fill dummy buffer; we don't use it, we directly send the fromRadio structure + uint32_t len = getFromRadio(txBuf); + if (len != 0) { + static uint32_t id = 0; + fromRadioScratch.id = ++id; + // TODO: think about redesign or drop class MeshPacketServer + // if (typeid(*server) == typeid(MeshPacketServer)) + // return dynamic_cast(server)->sendPacket(fromRadioScratch); + // else + return server->sendPacket(DataPacket(id, fromRadioScratch)); + } else + return false; +} + +/** + * return true if we got (once!) contact from our client and the server send queue is not full + */ +bool PacketAPI::checkIsConnected() +{ + isConnected |= server->hasData(); + return isConnected && server->available(); +} + +#endif \ No newline at end of file diff --git a/src/mesh/api/PacketAPI.h b/src/mesh/api/PacketAPI.h new file mode 100644 index 0000000000..f9ae0812a6 --- /dev/null +++ b/src/mesh/api/PacketAPI.h @@ -0,0 +1,36 @@ +#pragma once + +#include "PacketServer.h" +#include "PhoneAPI.h" +#include "concurrency/OSThread.h" + +/** + * A version of the phone API used for inter task communication based on protobuf packets, e.g. + * between two tasks running on CPU0 and CPU1, respectively. + * + */ +class PacketAPI : public PhoneAPI, public concurrency::OSThread +{ + public: + static PacketAPI *create(PacketServer *_server); + virtual ~PacketAPI(){}; + virtual int32_t runOnce(); + + protected: + PacketAPI(PacketServer *_server); + // Check the current underlying physical queue to see if the client is fetching packets + bool checkIsConnected() override; + + void onNowHasData(uint32_t fromRadioNum) override {} + void onConnectionChanged(bool connected) override {} + + private: + bool receivePacket(void); + bool sendPacket(void); + + bool isConnected; + PacketServer *server; + uint8_t txBuf[MAX_TO_FROM_RADIO_SIZE] = {0}; // dummy buf to obey PhoneAPI +}; + +extern PacketAPI *packetAPI; \ No newline at end of file diff --git a/src/mesh/http/ContentHelper.h b/src/mesh/http/ContentHelper.h index a80c39f47f..e5d3a2f571 100644 --- a/src/mesh/http/ContentHelper.h +++ b/src/mesh/http/ContentHelper.h @@ -1,5 +1,6 @@ #include #include +#include #define BoolToString(x) ((x) ? "true" : "false") diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 90722f5472..fe7a0514d2 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -175,6 +175,12 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta LOG_INFO("Client is setting ham mode"); handleSetHamMode(r->set_ham_mode); break; + case meshtastic_AdminMessage_get_ui_config_request_tag: { + LOG_INFO("Client is getting device-ui config"); + handleGetDeviceUIConfig(mp); + handled = true; + break; + } /** * Other @@ -234,6 +240,12 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta reboot(DEFAULT_REBOOT_SECONDS); break; } + case meshtastic_AdminMessage_store_ui_config_tag: { + LOG_INFO("Storing device-ui config"); + handleStoreDeviceUIConfig(r->store_ui_config); + handled = true; + break; + } case meshtastic_AdminMessage_begin_edit_settings_tag: { LOG_INFO("Beginning transaction for editing settings"); hasOpenEditTransaction = true; @@ -594,6 +606,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) requiresReboot = false; break; + case meshtastic_Config_device_ui_tag: + // NOOP! This is handled by handleStoreDeviceUIConfig + break; } if (requiresReboot && !hasOpenEditTransaction) { disableBluetooth(); @@ -756,6 +771,10 @@ void AdminModule::handleGetConfig(const meshtastic_MeshPacket &req, const uint32 LOG_INFO("Getting config: Sessionkey"); res.get_config_response.which_payload_variant = meshtastic_Config_sessionkey_tag; break; + case meshtastic_AdminMessage_ConfigType_DEVICEUI_CONFIG: + // NOOP! This is handled by handleGetDeviceUIConfig + res.get_config_response.which_payload_variant = meshtastic_Config_device_ui_tag; + break; } // NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior. // So even if we internally use 0 to represent 'use default' we still need to send the value we are @@ -968,6 +987,14 @@ void AdminModule::handleGetChannel(const meshtastic_MeshPacket &req, uint32_t ch } } +void AdminModule::handleGetDeviceUIConfig(const meshtastic_MeshPacket &req) +{ + meshtastic_AdminMessage r = meshtastic_AdminMessage_init_default; + r.which_payload_variant = meshtastic_AdminMessage_get_ui_config_response_tag; + r.get_ui_config_response = uiconfig; + myReply = allocDataProtobuf(r); +} + void AdminModule::reboot(int32_t seconds) { LOG_INFO("Rebooting in %d seconds", seconds); @@ -988,6 +1015,11 @@ void AdminModule::saveChanges(int saveWhat, bool shouldReboot) } } +void AdminModule::handleStoreDeviceUIConfig(const meshtastic_DeviceUIConfig &uicfg) +{ + nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uicfg); +} + void AdminModule::handleSetHamMode(const meshtastic_HamParameters &p) { // Set call sign and override lora limitations for licensed use @@ -1054,7 +1086,8 @@ bool AdminModule::messageIsResponse(const meshtastic_AdminMessage *r) r->which_payload_variant == meshtastic_AdminMessage_get_ringtone_response_tag || r->which_payload_variant == meshtastic_AdminMessage_get_device_connection_status_response_tag || r->which_payload_variant == meshtastic_AdminMessage_get_node_remote_hardware_pins_response_tag || - r->which_payload_variant == meshtastic_NodeRemoteHardwarePinsResponse_node_remote_hardware_pins_tag) + r->which_payload_variant == meshtastic_NodeRemoteHardwarePinsResponse_node_remote_hardware_pins_tag || + r->which_payload_variant == meshtastic_AdminMessage_get_ui_config_response_tag) return true; else return false; @@ -1070,7 +1103,8 @@ bool AdminModule::messageIsRequest(const meshtastic_AdminMessage *r) r->which_payload_variant == meshtastic_AdminMessage_get_device_metadata_request_tag || r->which_payload_variant == meshtastic_AdminMessage_get_ringtone_request_tag || r->which_payload_variant == meshtastic_AdminMessage_get_device_connection_status_request_tag || - r->which_payload_variant == meshtastic_AdminMessage_get_node_remote_hardware_pins_request_tag) + r->which_payload_variant == meshtastic_AdminMessage_get_node_remote_hardware_pins_request_tag || + r->which_payload_variant == meshtastic_AdminMessage_get_ui_config_request_tag) return true; else return false; diff --git a/src/modules/AdminModule.h b/src/modules/AdminModule.h index e54b89af1c..766b2930c7 100644 --- a/src/modules/AdminModule.h +++ b/src/modules/AdminModule.h @@ -41,6 +41,7 @@ class AdminModule : public ProtobufModule, public Obser void handleGetDeviceMetadata(const meshtastic_MeshPacket &req); void handleGetDeviceConnectionStatus(const meshtastic_MeshPacket &req); void handleGetNodeRemoteHardwarePins(const meshtastic_MeshPacket &req); + void handleGetDeviceUIConfig(const meshtastic_MeshPacket &req); /** * Setters */ @@ -50,6 +51,7 @@ class AdminModule : public ProtobufModule, public Obser void handleSetModuleConfig(const meshtastic_ModuleConfig &c); void handleSetChannel(); void handleSetHamMode(const meshtastic_HamParameters &req); + void handleStoreDeviceUIConfig(const meshtastic_DeviceUIConfig &uicfg); void reboot(int32_t seconds); void setPassKey(meshtastic_AdminMessage *res); diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 90c8c0f2cc..5a406d966b 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -971,6 +971,7 @@ bool CannedMessageModule::interceptingKeyboardInput() } } +#if !HAS_TFT void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { char buffer[50]; @@ -1129,6 +1130,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st } } } +#endif ProcessMessage CannedMessageModule::handleReceived(const meshtastic_MeshPacket &mp) { diff --git a/src/modules/CannedMessageModule.h b/src/modules/CannedMessageModule.h index e9dc2bda0a..5504af117e 100644 --- a/src/modules/CannedMessageModule.h +++ b/src/modules/CannedMessageModule.h @@ -113,8 +113,10 @@ class CannedMessageModule : public SinglePortModule, public ObservableshouldDraw(); } virtual Observable *getUIFrameObservable() override { return this; } - virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) override; virtual bool interceptingKeyboardInput() override; +#if !HAS_TFT + virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) override; +#endif virtual AdminMessageHandleResult handleAdminMessageForModule(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request, meshtastic_AdminMessage *response) override; diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index ad3f0ace45..809a8d87b0 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -74,7 +74,7 @@ #include "modules/StoreForwardModule.h" #endif #endif -#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) +#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO) #if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION #include "modules/ExternalNotificationModule.h" #endif @@ -173,7 +173,7 @@ void setupModules() aSerialKeyboardImpl->init(); #endif // INPUTBROKER_MATRIX_TYPE #endif // HAS_BUTTON -#if ARCH_PORTDUINO +#if ARCH_PORTDUINO && !HAS_TFT aLinuxInputImpl = new LinuxInputImpl(); aLinuxInputImpl->init(); #endif @@ -223,7 +223,7 @@ void setupModules() storeForwardModule = new StoreForwardModule(); #endif #endif -#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) +#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO) #if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION externalNotificationModule = new ExternalNotificationModule(); #endif diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 78562e47a7..ca663085c5 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -96,6 +96,7 @@ void portduinoSetup() std::string gpioChipName = "gpiochip"; settingsStrings[i2cdev] = ""; settingsStrings[keyboardDevice] = ""; + settingsStrings[pointerDevice] = ""; settingsStrings[webserverrootpath] = ""; settingsStrings[spidev] = ""; settingsStrings[displayspidev] = ""; @@ -333,6 +334,8 @@ bool loadConfig(const char *configPath) settingsMap[displayPanel] = ili9341; else if (yamlConfig["Display"]["Panel"].as("") == "ILI9342") settingsMap[displayPanel] = ili9342; + else if (yamlConfig["Display"]["Panel"].as("") == "ILI9486") + settingsMap[displayPanel] = ili9486; else if (yamlConfig["Display"]["Panel"].as("") == "ILI9488") settingsMap[displayPanel] = ili9488; else if (yamlConfig["Display"]["Panel"].as("") == "HX8357D") @@ -393,6 +396,7 @@ bool loadConfig(const char *configPath) } if (yamlConfig["Input"]) { settingsStrings[keyboardDevice] = (yamlConfig["Input"]["KeyboardDevice"]).as(""); + settingsStrings[pointerDevice] = (yamlConfig["Input"]["PointerDevice"]).as(""); } if (yamlConfig["Webserver"]) { diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 95d82c1a21..d1a7f96471 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -48,6 +48,7 @@ enum configNames { displayOffsetY, displayInvert, keyboardDevice, + pointerDevice, logoutputlevel, traceFilename, webserver, @@ -58,7 +59,7 @@ enum configNames { ascii_logs, config_directory }; -enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9488, hx8357d }; +enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d }; enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 }; enum { level_error, level_warn, level_info, level_debug, level_trace }; diff --git a/src/sleep.cpp b/src/sleep.cpp index 3bc1042bb5..5b029b7181 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -58,7 +58,7 @@ RTC_DATA_ATTR int bootCount = 0; */ void setCPUFast(bool on) { -#if defined(ARCH_ESP32) && HAS_WIFI +#if defined(ARCH_ESP32) && HAS_WIFI && !HAS_TFT if (isWifiAvailable()) { /* @@ -376,6 +376,9 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r gpio_wakeup_enable(pin, GPIO_INTR_LOW_LEVEL); esp_sleep_enable_gpio_wakeup(); #endif +#ifdef INPUTDRIVER_ENCODER_BTN + gpio_wakeup_enable((gpio_num_t)INPUTDRIVER_ENCODER_BTN, GPIO_INTR_LOW_LEVEL); +#endif #ifdef T_WATCH_S3 gpio_wakeup_enable((gpio_num_t)SCREEN_TOUCH_INT, GPIO_INTR_LOW_LEVEL); #endif diff --git a/variants/picomputer-s3/platformio.ini b/variants/picomputer-s3/platformio.ini index 202cd05e70..8bffdcaa78 100644 --- a/variants/picomputer-s3/platformio.ini +++ b/variants/picomputer-s3/platformio.ini @@ -1,4 +1,4 @@ -[env:picomputer-s3] +[env:picomputer-s3-oled] extends = esp32s3_base board = bpi_picow_esp32_s3 @@ -15,3 +15,47 @@ build_flags = lib_deps = ${esp32s3_base.lib_deps} lovyan03/LovyanGFX@^1.1.8 + + +[env:picomputer-s3] +extends = esp32s3_base +board = bpi_picow_esp32_s3 +board_build.partitions = default_8MB.csv ; just for test +board_check = true +upload_protocol = esptool +build_flags = ${esp32_base.build_flags} + -D PICOMPUTER_S3 + -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -D MESHTASTIC_EXCLUDE_INPUTBROKER=1 + -D MESHTASTIC_EXCLUDE_BLUETOOTH=1 + -D INPUTDRIVER_MATRIX_TYPE=1 + -D USE_PIN_BUZZER=PIN_BUZZER + -D USE_SX127x + -D MAX_NUM_NODES=200 + -D HAS_SCREEN=0 + -D HAS_TFT=1 + -D RAM_SIZE=1024 + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE + -D LV_USE_SYSMON=0 + -D LV_USE_PROFILER=0 + -D LV_USE_PERF_MONITOR=0 + -D LV_USE_MEM_MONITOR=0 + -D LV_USE_LOG=0 + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" + -D LGFX_DRIVER=LGFX_PICOMPUTER_S3 + -D VIEW_320x240 +; -D USE_DOUBLE_BUFFER + -D USE_PACKET_API + -I lib/device-ui/generated/ui_320x240 + -I variants/picomputer-s3 +build_src_filter = ${esp32_base.build_src_filter} + +<../lib/device-ui/generated/ui_320x240> + +<../lib/device-ui/resources> + +<../lib/device-ui/locale> + +<../lib/device-ui/source> +lib_deps = + ${esp32_base.lib_deps} + lovyan03/LovyanGFX@^1.1.16 diff --git a/variants/portduino/platformio.ini b/variants/portduino/platformio.ini index 46417e388e..fa4731ec86 100644 --- a/variants/portduino/platformio.ini +++ b/variants/portduino/platformio.ini @@ -8,3 +8,87 @@ build_flags = ${portduino_base.build_flags} -O0 -I variants/portduino -I /usr/in board = cross_platform lib_deps = ${portduino_base.lib_deps} build_src_filter = ${portduino_base.build_src_filter} + +[env:native-tft-debug] +extends = portduino_base +build_type = debug +build_flags = ${portduino_base.build_flags} -O0 -fsanitize=address -lX11 -linput -lxkbcommon + -D ARCH_PORTDUINO + -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -I variants/portduino + -I /usr/include + -D DEBUG_HEAP + -D RAM_SIZE=16384 + -D USE_X11=1 ; enables usage of X11 + -D HAS_TFT=1 + -D HAS_SCREEN=0 +; -D CALIBRATE_TOUCH=0 + -D LV_BUILD_TEST=0 + -D LV_USE_LOG=1 + -D LV_USE_SYSMON=1 + -D LV_USE_PERF_MONITOR=1 + -D LV_USE_MEM_MONITOR=0 + -D LV_USE_PROFILER=0 + -D LV_USE_LIBINPUT=1 + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" + -D USE_PACKET_API + -I lib/device-ui/generated/ui_320x240 +; The pkg-config commands below optionally add link flags. +; the || : is just a "or run the null command" to avoid returning an error code + !pkg-config --libs libulfius --silence-errors || : + !pkg-config --libs openssl --silence-errors || : +board = cross_platform +build_src_filter = ${portduino_base.build_src_filter} + - + +<../lib/device-ui/generated/ui_320x240> + +<../lib/device-ui/generated/ui_320x240/fonts> + +<../lib/device-ui/resources> + +<../lib/device-ui/portduino> + +<../lib/device-ui/locale> + +<../lib/device-ui/source> + + +[env:native-tft-release] +extends = portduino_base +build_type = release +build_flags = ${portduino_base.build_flags} -Os -lX11 -linput -lxkbcommon -ffunction-sections -fdata-sections -Wl,--gc-sections + -D ARCH_PORTDUINO + -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -I variants/portduino + -I /usr/include + -D RAM_SIZE=16384 + -D USE_X11=1 ; enables usage of X11 + -D HAS_TFT=1 + -D HAS_SCREEN=0 + -D LV_BUILD_TEST=0 +; -D CALIBRATE_TOUCH=0 + -D LV_USE_LOG=0 + -D LV_USE_SYSMON=0 + -D LV_USE_PROFILER=0 + -D LV_USE_PERF_MONITOR=0 + -D LV_USE_MEM_MONITOR=0 + -D LV_USE_LIBINPUT=1 + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" + -D USE_PACKET_API + -I lib/device-ui/generated/ui_320x240 +; The pkg-config commands below optionally add link flags. +; the || : is just a "or run the null command" to avoid returning an error code + !pkg-config --libs libulfius --silence-errors || : + !pkg-config --libs openssl --silence-errors || : +board = cross_platform +build_src_filter = ${portduino_base.build_src_filter} + - + +<../lib/device-ui/generated/ui_320x240> + +<../lib/device-ui/generated/ui_320x240/fonts> + +<../lib/device-ui/resources> + +<../lib/device-ui/portduino> + +<../lib/device-ui/locale> + +<../lib/device-ui/source> \ No newline at end of file diff --git a/variants/portduino/variant.h b/variants/portduino/variant.h index b7b39d6e84..ce7dbd865c 100644 --- a/variants/portduino/variant.h +++ b/variants/portduino/variant.h @@ -1,4 +1,6 @@ +#ifndef HAS_SCREEN #define HAS_SCREEN 1 +#endif #define CANNED_MESSAGE_MODULE_ENABLE 1 #define HAS_GPS 1 #define MAX_RX_TOPHONE settingsMap[maxtophone] diff --git a/variants/rak2560/RAK9154Sensor.cpp b/variants/rak2560/RAK9154Sensor.cpp index 9f660947e8..5fb09c1307 100644 --- a/variants/rak2560/RAK9154Sensor.cpp +++ b/variants/rak2560/RAK9154Sensor.cpp @@ -37,11 +37,11 @@ static void onewire_evt(const uint8_t pid, const uint8_t sid, const SNHUBAPI_EVT break; case SNHUBAPI_EVT_ADD_SID: - // LOG_INFO("+ADD:SID:[%02x]\r\n", msg[0]); + // LOG_INFO("+ADD:SID:[%02x]", msg[0]); break; case SNHUBAPI_EVT_ADD_PID: - // LOG_INFO("+ADD:PID:[%02x]\r\n", msg[0]); + // LOG_INFO("+ADD:PID:[%02x]", msg[0]); #ifdef BOOT_DATA_REQ provision = msg[0]; #endif @@ -55,12 +55,12 @@ static void onewire_evt(const uint8_t pid, const uint8_t sid, const SNHUBAPI_EVT case SNHUBAPI_EVT_SDATA_REQ: - // LOG_INFO("+EVT:PID[%02x],IPSO[%02x]\r\n",pid,msg[0]); + // LOG_INFO("+EVT:PID[%02x],IPSO[%02x]",pid,msg[0]); // for( uint16_t i=1; i + +<../lib/device-ui/resources> + +<../lib/device-ui/locale> + +<../lib/device-ui/source> +lib_deps = ${esp32s3_base.lib_deps} + https://github.com/mverch67/LovyanGFX#develop +; file:///home/manuel/Documents/PlatformIO/Projects/LovyanGFX + bitbank2/bb_captouch@1.2.2 ; alternative touch library supporting FT6x36 + earlephilhower/ESP8266Audio@^1.9.7 + earlephilhower/ESP8266SAM@^1.0.1 diff --git a/variants/seeed-sensecap-indicator/variant.h b/variants/seeed-sensecap-indicator/variant.h index d7ed329eb9..fe07c34b42 100644 --- a/variants/seeed-sensecap-indicator/variant.h +++ b/variants/seeed-sensecap-indicator/variant.h @@ -19,8 +19,7 @@ #define ST7701_BL 45 #define ST7701_SPI_HOST SPI2_HOST #define ST7701_BACKLIGHT_EN 45 -#define SPI_FREQUENCY 20000000 -#define SPI_READ_FREQUENCY 16000000 +#define SPI_FREQUENCY 12000000 #define TFT_HEIGHT 480 #define TFT_WIDTH 480 #define TFT_OFFSET_X 0 diff --git a/variants/t-deck/platformio.ini b/variants/t-deck/platformio.ini index a63ff57a75..a459cd0164 100644 --- a/variants/t-deck/platformio.ini +++ b/variants/t-deck/platformio.ini @@ -2,18 +2,60 @@ [env:t-deck] extends = esp32s3_base board = t-deck +board_level = extra +board_build.partitions = default_16MB.csv ; just for test board_check = true upload_protocol = esptool -#upload_port = COM29 - -build_flags = ${esp32_base.build_flags} - -DT_DECK - -DBOARD_HAS_PSRAM - -DMAX_THREADS=40 - -DGPS_POWER_TOGGLE - -Ivariants/t-deck - -lib_deps = ${esp32s3_base.lib_deps} - lovyan03/LovyanGFX@^1.1.9 +build_flags = ${esp32_base.build_flags} + -D T_DECK + -D CONFIG_DISABLE_HAL_LOCKS=1 ; "feels" to be a bit more stable without locks + -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -D MESHTASTIC_EXCLUDE_INPUTBROKER=1 + -D MESHTASTIC_EXCLUDE_BLUETOOTH=1 + -D MESHTASTIC_EXCLUDE_WEBSERVER=1 + -D INPUTDRIVER_I2C_KBD_TYPE=0x55 + -D INPUTDRIVER_ENCODER_TYPE=3 + -D INPUTDRIVER_ENCODER_LEFT=1 + -D INPUTDRIVER_ENCODER_RIGHT=2 + -D INPUTDRIVER_ENCODER_UP=3 + -D INPUTDRIVER_ENCODER_DOWN=15 + -D INPUTDRIVER_ENCODER_BTN=0 + -D MAX_NUM_NODES=250 + -D MAX_THREADS=40 + -D HAS_SCREEN=0 + -D HAS_TFT=1 + -D USE_I2S_BUZZER + -D RAM_SIZE=1024 + -D GPS_POWER_TOGGLE + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE + -D LV_USE_SYSMON=0 + -D LV_USE_PROFILER=0 + -D LV_USE_PERF_MONITOR=0 + -D LV_USE_MEM_MONITOR=0 + -D LV_USE_LOG=0 + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" + -D RADIOLIB_SPI_PARANOID=0 + -D CUSTOM_TOUCH_DRIVER + -D CALIBRATE_TOUCH=0 + -D LGFX_DRIVER=LGFX_TDECK +; -D LVGL_DRIVER=LVGL_TDECK +; -D LV_USE_ST7789=1 + -D VIEW_320x240 +; -D USE_DOUBLE_BUFFER + -D USE_PACKET_API + -I lib/device-ui/generated/ui_320x240 + -I variants/t-deck +build_src_filter = ${esp32_base.build_src_filter} + +<../lib/device-ui/generated/ui_320x240> + +<../lib/device-ui/resources> + +<../lib/device-ui/locale> + +<../lib/device-ui/source> +lib_deps = + ${esp32_base.lib_deps} + lovyan03/LovyanGFX@^1.1.16 + bitbank2/bb_captouch@1.2.2 ; alternative touch library supporting GT911 earlephilhower/ESP8266Audio@^1.9.7 earlephilhower/ESP8266SAM@^1.0.1 \ No newline at end of file diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h index 9860d608f8..53bb706244 100644 --- a/variants/t-deck/variant.h +++ b/variants/t-deck/variant.h @@ -1,5 +1,5 @@ // ST7789 TFT LCD -#define ST7789_CS 12 +// #define ST7789_CS 12 #define ST7789_RS 11 // DC #define ST7789_SDA 41 // MOSI #define ST7789_SCK 40 @@ -27,8 +27,10 @@ #define SLEEP_TIME 120 +#ifndef HAS_TFT #define BUTTON_PIN 0 // #define BUTTON_NEED_PULLUP +#endif #define GPS_RX_PIN 44 #define GPS_TX_PIN 43 @@ -60,7 +62,7 @@ #define TB_DOWN 15 #define TB_LEFT 1 #define TB_RIGHT 2 -#define TB_PRESS BUTTON_PIN +#define TB_PRESS 0 // BUTTON_PIN // microphone #define ES7210_SCK 47 diff --git a/variants/tlora_t3s3_v1/platformio.ini b/variants/tlora_t3s3_v1/platformio.ini index 0a57972803..c062dbd7b0 100644 --- a/variants/tlora_t3s3_v1/platformio.ini +++ b/variants/tlora_t3s3_v1/platformio.ini @@ -6,4 +6,73 @@ upload_protocol = esptool build_flags = ${esp32_base.build_flags} -D TLORA_T3S3_V1 -I variants/tlora_t3s3_v1 - -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. \ No newline at end of file + -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. + + +[env:tlora-t3s3-tft] +extends = esp32s3_base +board = tlora-t3s3-v1 +;board_check = true +upload_protocol = esp-builtin + +build_flags = ${esp32_base.build_flags} + -D TLORA_T3S3_V1 + -D MESHTASTIC_EXCLUDE_SCREEN=1 + -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -D MESHTASTIC_EXCLUDE_INPUTBROKER=1 + -D MESHTASTIC_EXCLUDE_PAXCOUNTER=1 + -D MESHTASTIC_EXCLUDE_WEBSERVER=1 + -D MESHTASTIC_EXCLUDE_GPS=1 + -D MESHTASTIC_EXCLUDE_AUDIO=1 + -D MESHTASTIC_EXCLUDE_POWER_TELEMETRY=1 + -D MESHTASTIC_EXCLUDE_ATAK=1 + -D MESHTASTIC_EXCLUDE_REMOTEHARDWARE=1 + -D MAX_NUM_NODES=250 + -D HAS_SCREEN=0 + -D HAS_TFT=1 + -D RAM_SIZE=1024 + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE + -D LV_USE_SYSMON=0 + -D LV_USE_PROFILER=0 + -D LV_USE_PERF_MONITOR=0 + -D LV_USE_MEM_MONITOR=0 + -D LV_USE_LOG=0 + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" +; -D CALIBRATE_TOUCH=0 + -D LGFX_DRIVER_TEMPLATE + -D LGFX_DRIVER=LGFX_GENERIC + -D LGFX_PANEL=ST7789 + -D LGFX_OFFSET_ROTATION=1 + -D LGFX_TOUCH=XPT2046 + -D LGFX_PIN_SCK=12 + -D LGFX_PIN_MOSI=15 + -D LGFX_PIN_MISO=16 + -D LGFX_PIN_DC=47 + -D LGFX_PIN_CS=48 + -D LGFX_PIN_RST=34 + -D LGFX_PIN_BL=35 + -D LGFX_TOUCH_INT=38 + -D LGFX_TOUCH_CS=39 + -D LGFX_TOUCH_CLK=12 + -D LGFX_TOUCH_DO=15 + -D LGFX_TOUCH_DIN=16 + -D LGFX_TOUCH_X_MIN=300 + -D LGFX_TOUCH_X_MAX=3900 + -D LGFX_TOUCH_Y_MIN=400 + -D LGFX_TOUCH_Y_MAX=3900 + -D VIEW_320x240 +; -D USE_DOUBLE_BUFFER + -D USE_PACKET_API + -I variants/tlora_t3s3_v1 + -I lib/device-ui/generated/ui_320x240 +build_src_filter = ${esp32_base.build_src_filter} + +<../lib/device-ui/generated/ui_320x240> + +<../lib/device-ui/resources> + +<../lib/device-ui/locale> + +<../lib/device-ui/source> +lib_deps = + ${esp32_base.lib_deps} + lovyan03/LovyanGFX@^1.1.16 diff --git a/variants/unphone/pins_arduino.h b/variants/unphone/pins_arduino.h index c4e9add1c3..74067359fc 100644 --- a/variants/unphone/pins_arduino.h +++ b/variants/unphone/pins_arduino.h @@ -6,14 +6,6 @@ #define USB_VID 0x16D0 #define USB_PID 0x1178 -#define EXTERNAL_NUM_INTERRUPTS 46 -#define NUM_DIGITAL_PINS 48 -#define NUM_ANALOG_INPUTS 20 - -#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1) -#define digitalPinToInterrupt(p) (((p) < 48) ? (p) : -1) -#define digitalPinHasPWM(p) (p < 46) - #define LED_BUILTIN 13 #define BUILTIN_LED LED_BUILTIN // backward compatibility diff --git a/variants/unphone/platformio.ini b/variants/unphone/platformio.ini index 489c70f998..b41848e134 100644 --- a/variants/unphone/platformio.ini +++ b/variants/unphone/platformio.ini @@ -26,7 +26,7 @@ build_flags = ${esp32_base.build_flags} build_src_filter = ${esp32_base.build_src_filter} +<../variants/unphone> lib_deps = ${esp32s3_base.lib_deps} - lovyan03/LovyanGFX@ 1.1.12 + lovyan03/LovyanGFX@ 1.1.16 https://gitlab.com/hamishcunningham/unphonelibrary#meshtastic@9.0.0 adafruit/Adafruit NeoPixel @ ^1.12.0 @@ -46,19 +46,29 @@ build_flags = ${esp32_base.build_flags} -D UNPHONE_UI0=0 -D UNPHONE_LORA=0 -D UNPHONE_FACTORY_MODE=0 + -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -D MESHTASTIC_EXCLUDE_INPUTBROKER=1 + -D MESHTASTIC_EXCLUDE_BLUETOOTH=1 + -D MESHTASTIC_EXCLUDE_WEBSERVER=1 + -D USE_SX127x + -D MAX_NUM_NODES=200 -D MAX_THREADS=40 -D HAS_SCREEN=0 -D HAS_TFT=1 - -D RAM_SIZE=512 + -D DISPLAY_SET_RESOLUTION + -D RAM_SIZE=1024 -D LV_LVGL_H_INCLUDE_SIMPLE -D LV_CONF_INCLUDE_SIMPLE -D LV_COMP_CONF_INCLUDE_SIMPLE -D LV_BUILD_TEST=0 + -D LV_USE_SYSMON=0 + -D LV_USE_PROFILER=0 -D LV_USE_PERF_MONITOR=0 -D LV_USE_MEM_MONITOR=0 + -D LV_USE_LOG=0 -D USE_LOG_DEBUG -D LOG_DEBUG_INC=\"DebugConfiguration.h\" -; -D CALIBRATE_TOUCH=0 + -D CALIBRATE_TOUCH=0 -D LGFX_DRIVER=LGFX_UNPHONE_V9 -D VIEW_320x240 ; -D USE_DOUBLE_BUFFER @@ -69,9 +79,10 @@ build_flags = ${esp32_base.build_flags} build_src_filter = ${esp32_base.build_src_filter} +<../variants/unphone> +<../lib/device-ui/generated/ui_320x240> +<../lib/device-ui/resources> + +<../lib/device-ui/locale> +<../lib/device-ui/source> lib_deps = ${esp32s3_base.lib_deps} - lovyan03/LovyanGFX@^1.1.12 + lovyan03/LovyanGFX@^1.1.16 https://gitlab.com/hamishcunningham/unphonelibrary#meshtastic@9.0.0 adafruit/Adafruit NeoPixel@1.12.0 \ No newline at end of file