diff --git a/boards/Seeed_Solar_Node.json b/boards/Seeed_Solar_Node.json new file mode 100644 index 000000000..e1b502cfa --- /dev/null +++ b/boards/Seeed_Solar_Node.json @@ -0,0 +1,54 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v7.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DARDUINO_MDBT50Q_RX -DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [["0x2886", "0x0059"]], + "usb_product": "XIAO-BOOT", + "mcu": "nrf52840", + "variant": "Seeed_Solar_Node", + "bsp": { + "name": "adafruit" + }, + "softdevice": { + "sd_flags": "-DS140", + "sd_name": "s140", + "sd_version": "7.3.0", + "sd_fwid": "0x0123" + }, + "bootloader": { + "settings_addr": "0xFF000" + } + }, + "connectivity": ["bluetooth"], + "debug": { + "jlink_device": "nRF52840_xxAA", + "svd_path": "nrf52840.svd", + "openocd_target": "nrf52840-mdk-rs" + }, + "frameworks": ["arduino"], + "name": "Seeed_Solar_Node", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "speed": 115200, + "protocol": "nrfutil", + "protocols": [ + "jlink", + "nrfjprog", + "nrfutil", + "stlink", + "cmsis-dap", + "blackmagic" + ], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + }, + "url": "https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html", + "vendor": "Seeed Studio" +} diff --git a/boards/crowpanel.json b/boards/crowpanel.json new file mode 100644 index 000000000..570961ed7 --- /dev/null +++ b/boards/crowpanel.json @@ -0,0 +1,43 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_16MB.csv" + }, + "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=0" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [["0x303A", "0x1001"]], + "mcu": "esp32s3", + "variant": "ESP32-S3-WROOM-1-N16R8" + }, + "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-N16R8 (16 MB Flash, 8 MB PSRAM)", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 524288, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "monitor": { + "speed": 115200 + }, + "url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf", + "vendor": "Espressif" +} diff --git a/protobufs b/protobufs index b982b36df..27fac3914 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit b982b36dfab2e96b8f8be90af891c68ebf8790c2 +Subproject commit 27fac39141d99fe727a0a1824c5397409b1aea75 diff --git a/src/FSCommon.cpp b/src/FSCommon.cpp index 88f0764b5..f215be80f 100644 --- a/src/FSCommon.cpp +++ b/src/FSCommon.cpp @@ -12,13 +12,14 @@ #include "SPILock.h" #include "configuration.h" -#ifdef HAS_SDCARD +// Software SPI is used by MUI so disable SD card here until it's also implemented +#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI) #include #include #ifdef SDCARD_USE_SPI1 -SPIClass SPI1(HSPI); -#define SDHandler SPI1 +SPIClass SPI_HSPI(HSPI); +#define SDHandler SPI_HSPI #else #define SDHandler SPI #endif @@ -306,7 +307,7 @@ void fsInit() */ void setupSDCard() { -#ifdef HAS_SDCARD +#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI) concurrency::LockGuard g(spiLock); SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI); if (!SD.begin(SDCARD_CS, SDHandler, SD_SPI_FREQUENCY)) { diff --git a/src/Power.cpp b/src/Power.cpp index f11f8eac3..ed1bd20ef 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -450,6 +450,8 @@ class AnalogBatteryLevel : public HasBatteryLevel return isBatteryConnect() && isVbusIn(); #endif #endif + // by default, we check the battery voltage only + return isVbusIn(); } private: diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 4c4d203c2..dbe4796cf 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -19,7 +19,7 @@ #include "sleep.h" #include "target_specific.h" -#if HAS_WIFI && !defined(ARCH_PORTDUINO) +#if HAS_WIFI && !defined(ARCH_PORTDUINO) || defined(MESHTASTIC_EXCLUDE_WIFI) #include "mesh/wifi/WiFiAPClient.h" #endif @@ -269,9 +269,6 @@ Fsm powerFSM(&stateBOOT); void PowerFSM_setup() { bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0); - bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER || - config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER || - config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR; bool hasPower = isPowered(); LOG_INFO("PowerFSM init, USB power=%d", hasPower ? 1 : 0); @@ -383,6 +380,12 @@ void PowerFSM_setup() // See: https://github.com/meshtastic/firmware/issues/1071 // Don't add power saving transitions if we are a power saving tracker or sensor or have Wifi enabled. Sleep will be initiated // through the modules + +#if HAS_WIFI || !defined(MESHTASTIC_EXCLUDE_WIFI) + bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER || + config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER || + config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR; + if ((isRouter || config.power.is_power_saving) && !isWifiAvailable() && !isTrackerOrSensor) { powerFSM.add_timed_transition(&stateNB, &stateLS, Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, @@ -400,7 +403,9 @@ void PowerFSM_setup() Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, "Screen-on timeout"); } -#else +#endif // HAS_WIFI || !defined(MESHTASTIC_EXCLUDE_WIFI) + +#else // (not) ARCH_ESP32 // If not ESP32, light-sleep not used. Check periodically if config has drifted out of stateDark powerFSM.add_timed_transition(&stateDARK, &stateDARK, Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, @@ -409,4 +414,4 @@ void PowerFSM_setup() powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state } -#endif \ No newline at end of file +#endif diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 85fe2bed9..9e4555e53 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1552,7 +1552,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O dispdev = new SSD1306Wire(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); #elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7789_CS) || \ - defined(RAK14014) || defined(HX8357_CS) + defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) dispdev = new TFTDisplay(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); #elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY) @@ -1786,7 +1786,7 @@ void Screen::setup() // flip it. If you have a headache now, you're welcome. if (!config.display.flip_screen) { #if defined(ST7701_CS) || defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || \ - defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS) + defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) static_cast(dispdev)->flipScreenVertically(); #elif defined(USE_ST7789) static_cast(dispdev)->flipScreenVertically(); diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index c5187cffc..14787baff 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -120,6 +120,303 @@ static void rak14014_tpIntHandle(void) _rak14014_touch_int = true; } +#elif defined(ST72xx_DE) +#include +#include +#include +#include +TCA9534 ioex; + +class LGFX : public lgfx::LGFX_Device +{ + lgfx::Bus_RGB _bus_instance; + lgfx::Panel_RGB _panel_instance; + lgfx::Touch_GT911 _touch_instance; + + public: + const uint16_t screenWidth = TFT_WIDTH; + const uint16_t screenHeight = TFT_HEIGHT; + + bool init_impl(bool use_reset, bool use_clear) override + { + ioex.attach(Wire); + ioex.setDeviceAddress(0x18); + ioex.config(1, TCA9534::Config::OUT); + ioex.config(2, TCA9534::Config::OUT); + ioex.config(3, TCA9534::Config::OUT); + ioex.config(4, TCA9534::Config::OUT); + + ioex.output(1, TCA9534::Level::H); + ioex.output(3, TCA9534::Level::L); + ioex.output(4, TCA9534::Level::H); + + pinMode(1, OUTPUT); + digitalWrite(1, LOW); + ioex.output(2, TCA9534::Level::L); + delay(20); + ioex.output(2, TCA9534::Level::H); + delay(100); + pinMode(1, INPUT); + + return LGFX_Device::init_impl(use_reset, use_clear); + } + + LGFX(void) + { + { + auto cfg = _panel_instance.config(); + + cfg.memory_width = screenWidth; + cfg.memory_height = screenHeight; + cfg.panel_width = screenWidth; + cfg.panel_height = screenHeight; + cfg.offset_x = 0; + cfg.offset_y = 0; + cfg.offset_rotation = 0; + _panel_instance.config(cfg); + } + + { + auto cfg = _panel_instance.config_detail(); + cfg.use_psram = 0; + _panel_instance.config_detail(cfg); + } + + { + auto cfg = _bus_instance.config(); + cfg.panel = &_panel_instance; + cfg.pin_d0 = ST72xx_B0; // B0 + cfg.pin_d1 = ST72xx_B1; // B1 + cfg.pin_d2 = ST72xx_B2; // B2 + cfg.pin_d3 = ST72xx_B3; // B3 + cfg.pin_d4 = ST72xx_B4; // B4 + cfg.pin_d5 = ST72xx_G0; // G0 + cfg.pin_d6 = ST72xx_G1; // G1 + cfg.pin_d7 = ST72xx_G2; // G2 + cfg.pin_d8 = ST72xx_G3; // G3 + cfg.pin_d9 = ST72xx_G4; // G4 + cfg.pin_d10 = ST72xx_G5; // G5 + cfg.pin_d11 = ST72xx_R0; // R0 + cfg.pin_d12 = ST72xx_R1; // R1 + cfg.pin_d13 = ST72xx_R2; // R2 + cfg.pin_d14 = ST72xx_R3; // R3 + cfg.pin_d15 = ST72xx_R4; // R4 + + cfg.pin_henable = ST72xx_DE; + cfg.pin_vsync = ST72xx_VSYNC; + cfg.pin_hsync = ST72xx_HSYNC; + cfg.pin_pclk = ST72xx_PCLK; + cfg.freq_write = 13000000; + +#ifdef ST7265_HSYNC_POLARITY + cfg.hsync_polarity = ST7265_HSYNC_POLARITY; + cfg.hsync_front_porch = ST7265_HSYNC_FRONT_PORCH; // 8; + cfg.hsync_pulse_width = ST7265_HSYNC_PULSE_WIDTH; // 4; + cfg.hsync_back_porch = ST7265_HSYNC_BACK_PORCH; // 8; + + cfg.vsync_polarity = ST7265_VSYNC_POLARITY; // 0; + cfg.vsync_front_porch = ST7265_VSYNC_FRONT_PORCH; // 8; + cfg.vsync_pulse_width = ST7265_VSYNC_PULSE_WIDTH; // 4; + cfg.vsync_back_porch = ST7265_VSYNC_BACK_PORCH; // 8; + + cfg.pclk_idle_high = 1; + cfg.pclk_active_neg = ST7265_PCLK_ACTIVE_NEG; // 0; + // cfg.pclk_idle_high = 0; + // cfg.de_idle_high = 1; +#endif + +#ifdef ST7262_HSYNC_POLARITY + cfg.hsync_polarity = ST7262_HSYNC_POLARITY; + cfg.hsync_front_porch = ST7262_HSYNC_FRONT_PORCH; // 8; + cfg.hsync_pulse_width = ST7262_HSYNC_PULSE_WIDTH; // 4; + cfg.hsync_back_porch = ST7262_HSYNC_BACK_PORCH; // 8; + + cfg.vsync_polarity = ST7262_VSYNC_POLARITY; // 0; + cfg.vsync_front_porch = ST7262_VSYNC_FRONT_PORCH; // 8; + cfg.vsync_pulse_width = ST7262_VSYNC_PULSE_WIDTH; // 4; + cfg.vsync_back_porch = ST7262_VSYNC_BACK_PORCH; // 8; + + cfg.pclk_idle_high = 1; + cfg.pclk_active_neg = ST7262_PCLK_ACTIVE_NEG; // 0; + // cfg.pclk_idle_high = 0; + // cfg.de_idle_high = 1; +#endif + +#ifdef SC7277_HSYNC_POLARITY + cfg.hsync_polarity = SC7277_HSYNC_POLARITY; + cfg.hsync_front_porch = SC7277_HSYNC_FRONT_PORCH; // 8; + cfg.hsync_pulse_width = SC7277_HSYNC_PULSE_WIDTH; // 4; + cfg.hsync_back_porch = SC7277_HSYNC_BACK_PORCH; // 8; + + cfg.vsync_polarity = SC7277_VSYNC_POLARITY; // 0; + cfg.vsync_front_porch = SC7277_VSYNC_FRONT_PORCH; // 8; + cfg.vsync_pulse_width = SC7277_VSYNC_PULSE_WIDTH; // 4; + cfg.vsync_back_porch = SC7277_VSYNC_BACK_PORCH; // 8; + + cfg.pclk_idle_high = 1; + cfg.pclk_active_neg = SC7277_PCLK_ACTIVE_NEG; // 0; + // cfg.pclk_idle_high = 0; + // cfg.de_idle_high = 1; +#endif + + _bus_instance.config(cfg); + } + _panel_instance.setBus(&_bus_instance); + + { + auto cfg = _touch_instance.config(); + cfg.x_min = 0; + cfg.x_max = TFT_WIDTH; + cfg.y_min = 0; + cfg.y_max = TFT_HEIGHT; + cfg.pin_int = -1; + cfg.pin_rst = -1; + cfg.bus_shared = true; + cfg.offset_rotation = 0; + + cfg.i2c_port = 0; + cfg.i2c_addr = 0x5D; + cfg.pin_sda = I2C_SDA; + cfg.pin_scl = I2C_SCL; + cfg.freq = 400000; + _touch_instance.config(cfg); + _panel_instance.setTouch(&_touch_instance); + } + + setPanel(&_panel_instance); + } +}; + +static LGFX *tft = nullptr; + +#elif defined(ILI9488_CS) +#include // Graphics and font library for ILI9488 driver chip + +class LGFX : public lgfx::LGFX_Device +{ + lgfx::Panel_ILI9488 _panel_instance; + lgfx::Bus_SPI _bus_instance; + lgfx::Light_PWM _light_instance; + lgfx::Touch_GT911 _touch_instance; + + public: + LGFX(void) + { + { + auto cfg = _bus_instance.config(); + + // configure SPI + cfg.spi_host = ILI9488_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST + cfg.spi_mode = 0; + cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing + // 80MHz by an integer) + cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving + cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin + cfg.use_lock = true; // Set to true to use transaction locking + cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch / + // SPI_DMA_CH_AUTO=auto setting) + cfg.pin_sclk = ILI9488_SCK; // Set SPI SCLK pin number + cfg.pin_mosi = ILI9488_SDA; // Set SPI MOSI pin number + cfg.pin_miso = ILI9488_MISO; // Set SPI MISO pin number (-1 = disable) + cfg.pin_dc = ILI9488_RS; // Set SPI DC pin number (-1 = disable) + + _bus_instance.config(cfg); // applies the set value to the bus. + _panel_instance.setBus(&_bus_instance); // set the bus on the panel. + } + + { // Set the display panel control. + auto cfg = _panel_instance.config(); // Gets a structure for display panel settings. + + cfg.pin_cs = ILI9488_CS; // Pin number where CS is connected (-1 = disable) + cfg.pin_rst = -1; // Pin number where RST is connected (-1 = disable) + cfg.pin_busy = -1; // Pin number where BUSY is connected (-1 = disable) + + // The following setting values ​​are general initial values ​​for each panel, so please comment out any + // unknown items and try them. + + cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC + cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC + cfg.panel_width = TFT_WIDTH; // actual displayable width + cfg.panel_height = TFT_HEIGHT; // actual displayable height + cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction + cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction + cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored) +#ifdef TFT_DUMMY_READ_PIXELS + cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout +#else + cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout +#endif + cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read + cfg.readable = true; // Set to true if data can be read + cfg.invert = true; // Set to true if the light/darkness of the panel is reversed + cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped + cfg.dlen_16bit = + false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI + cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.) + + // Set the following only when the display is shifted with a driver with a variable number of pixels, such as the + // ST7735 or ILI9163. + // cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC + // cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC + _panel_instance.config(cfg); + } + +#ifdef ILI9488_BL + // Set the backlight control + { + auto cfg = _light_instance.config(); // Gets a structure for backlight settings. + + cfg.pin_bl = ILI9488_BL; // Pin number to which the backlight is connected + cfg.invert = false; // true to invert the brightness of the backlight + // cfg.freq = 44100; // PWM frequency of backlight + // cfg.pwm_channel = 1; // PWM channel number to use + + _light_instance.config(cfg); + _panel_instance.setLight(&_light_instance); // Set the backlight on the panel. + } +#endif + +#if HAS_TOUCHSCREEN + // Configure settings for touch screen control. + { + auto cfg = _touch_instance.config(); + + cfg.pin_cs = -1; + cfg.x_min = 0; + cfg.x_max = TFT_HEIGHT - 1; + cfg.y_min = 0; + cfg.y_max = TFT_WIDTH - 1; + cfg.pin_int = SCREEN_TOUCH_INT; +#ifdef SCREEN_TOUCH_RST + cfg.pin_rst = SCREEN_TOUCH_RST; +#endif + cfg.bus_shared = true; + cfg.offset_rotation = TFT_OFFSET_ROTATION; + // cfg.freq = 2500000; + + // I2C + cfg.i2c_port = TOUCH_I2C_PORT; + cfg.i2c_addr = TOUCH_SLAVE_ADDRESS; +#ifdef SCREEN_TOUCH_USE_I2C1 + cfg.pin_sda = I2C_SDA1; + cfg.pin_scl = I2C_SCL1; +#else + cfg.pin_sda = I2C_SDA; + cfg.pin_scl = I2C_SCL; +#endif + // cfg.freq = 400000; + + _touch_instance.config(cfg); + _panel_instance.setTouch(&_touch_instance); + } +#endif + + setPanel(&_panel_instance); + } +}; + +static LGFX *tft = nullptr; + #elif defined(ST7789_CS) #include // Graphics and font library for ST7735 driver chip @@ -129,7 +426,7 @@ class LGFX : public lgfx::LGFX_Device lgfx::Bus_SPI _bus_instance; lgfx::Light_PWM _light_instance; #if HAS_TOUCHSCREEN -#ifdef T_WATCH_S3 +#if defined(T_WATCH_S3) || defined(ELECROW) lgfx::Touch_FT5x06 _touch_instance; #else lgfx::Touch_GT911 _touch_instance; @@ -171,16 +468,22 @@ class LGFX : public lgfx::LGFX_Device // The following setting values ​​are general initial values ​​for each panel, so please comment out any // unknown items and try them. - cfg.panel_width = TFT_WIDTH; // actual displayable width - cfg.panel_height = TFT_HEIGHT; // actual displayable height - cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction - cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction - cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored) - cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout - cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read - cfg.readable = true; // Set to true if data can be read - cfg.invert = true; // Set to true if the light/darkness of the panel is reversed - cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped + cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC + cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC + cfg.panel_width = TFT_WIDTH; // actual displayable width + cfg.panel_height = TFT_HEIGHT; // actual displayable height + cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction + cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction + cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored) +#ifdef TFT_DUMMY_READ_PIXELS + cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout +#else + cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout +#endif + cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read + cfg.readable = true; // Set to true if data can be read + cfg.invert = true; // Set to true if the light/darkness of the panel is reversed + cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped cfg.dlen_16bit = false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.) @@ -217,6 +520,9 @@ class LGFX : public lgfx::LGFX_Device cfg.y_min = 0; cfg.y_max = TFT_WIDTH - 1; cfg.pin_int = SCREEN_TOUCH_INT; +#ifdef SCREEN_TOUCH_RST + cfg.pin_rst = SCREEN_TOUCH_RST; +#endif cfg.bus_shared = true; cfg.offset_rotation = TFT_OFFSET_ROTATION; // cfg.freq = 2500000; @@ -640,7 +946,7 @@ static LGFX *tft = nullptr; #endif #if defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \ - defined(RAK14014) || defined(HX8357_CS) || (ARCH_PORTDUINO && HAS_SCREEN != 0) + defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST72xx_DE) || (ARCH_PORTDUINO && HAS_SCREEN != 0) #include "SPILock.h" #include "TFTDisplay.h" #include diff --git a/src/graphics/images.h b/src/graphics/images.h index f34b51c9b..9409b795e 100644 --- a/src/graphics/images.h +++ b/src/graphics/images.h @@ -22,8 +22,7 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03 #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ defined(ST7789_CS) || defined(USE_ST7789) || defined(USE_ST7796) || defined(HX8357_CS) || defined(ILI9488_CS) || \ - ARCH_PORTDUINO) && \ - !defined(DISPLAY_FORCE_SMALL_FONTS) + ARCH_PORTDUINO) && !defined(DISPLAY_FORCE_SMALL_FONTS) const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff}; const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f}; const uint8_t imgInfoL1[] PROGMEM = {0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff}; diff --git a/src/main.cpp b/src/main.cpp index ebab1da9a..f7a163915 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,6 +115,10 @@ AccelerometerThread *accelerometerThread = nullptr; AudioThread *audioThread = nullptr; #endif +#ifdef USE_PCA9557 +PCA9557 IOEXP; +#endif + #if HAS_TFT extern void tftSetup(void); #endif @@ -133,6 +137,10 @@ void setupNicheGraphics(); #include "nicheGraphics.h" #endif +#if defined(HW_SPI1_DEVICE) && defined(ARCH_ESP32) +SPIClass SPI1(HSPI); +#endif + using namespace concurrency; volatile static const char slipstreamTZString[] = {USERPREFS_TZ_STRING}; @@ -364,9 +372,11 @@ void setup() SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0); #endif +#if !HAS_TFT meshtastic_Config_DisplayConfig_OledType screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO; OLEDDISPLAY_GEOMETRY screen_geometry = GEOMETRY_128_64; +#endif #ifdef USE_SEGGER auto mode = false ? SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL : SEGGER_RTT_MODE_NO_BLOCK_TRIM; @@ -595,6 +605,7 @@ void setup() } #endif +#if !HAS_TFT auto screenInfo = i2cScanner->firstScreen(); screen_found = screenInfo.type != ScanI2C::DeviceType::NONE ? screenInfo.address : ScanI2C::ADDRESS_NONE; @@ -612,6 +623,7 @@ void setup() screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO; } } +#endif #define UPDATE_FROM_SCANNER(FIND_FN) @@ -779,9 +791,11 @@ void setup() else playStartMelody(); +#if !HAS_TFT // fixed screen override? if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO) screen_model = config.display.oled; +#endif #if defined(USE_SH1107) screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128 @@ -837,10 +851,16 @@ void setup() #elif !defined(ARCH_ESP32) // ARCH_RP2040 SPI.begin(); #else - // ESP32 + // ESP32 +#if defined(HW_SPI1_DEVICE) + SPI1.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); + LOG_DEBUG("SPI1.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); + SPI1.setFrequency(4000000); +#else 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 #endif // Initialize the screen first so we can show the logo while we start up everything else. diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index d8f958098..72d54c837 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -584,7 +584,8 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) resetRadioConfig(true); // This also triggers NodeInfo/Position requests since we're fresh strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32); -#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR)) && \ +#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR) || \ + defined(ELECROW)) && \ HAS_TFT // switch BT off by default; use TFT programming mode or hotkey to enable config.bluetooth.enabled = false; @@ -689,7 +690,7 @@ void NodeDB::initConfigIntervals() config.display.screen_on_secs = default_screen_on_secs; -#if defined(T_WATCH_S3) || defined(T_DECK) || defined(UNPHONE) || defined(MESH_TAB) || defined(RAK14014) +#if defined(T_WATCH_S3) || defined(T_DECK) || defined(UNPHONE) || defined(MESH_TAB) || defined(RAK14014) || defined(ELECROW) config.power.is_power_saving = true; config.display.screen_on_secs = 30; config.power.wait_bluetooth_secs = 30; diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 36bded9b2..6fa0b60b0 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -243,6 +243,10 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_HELTEC_MESH_POCKET = 94, /* Seeed Solar Node */ meshtastic_HardwareModel_SEEED_SOLAR_NODE = 95, + /* NomadStar Meteor Pro https://nomadstar.ch/ */ + meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO = 96, + /* Elecrow CrowPanel Advance models, ESP32-S3 and TFT with SX1262 radio plugin */ + meshtastic_HardwareModel_CROWPANEL = 97, /* ------------------------------------------------------------------------------------------------------------------------------------------ Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. ------------------------------------------------------------------------------------------------------------------------------------------ */ diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 0af6d4d04..68d06c6d7 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -182,6 +182,8 @@ #define HW_VENDOR meshtastic_HardwareModel_T_ETH_ELITE #elif defined(HELTEC_SENSOR_HUB) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_SENSOR_HUB +#elif defined(ELECROW_PANEL) +#define HW_VENDOR meshtastic_HardwareModel_CROWPANEL #endif // ----------------------------------------------------------------------------- diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index 21296c3fc..9d1d48f1c 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -81,6 +81,8 @@ #define HW_VENDOR meshtastic_HardwareModel_MESHLINK #elif defined(SEEED_XIAO_NRF52840_KIT) #define HW_VENDOR meshtastic_HardwareModel_XIAO_NRF52_KIT +#elif defined(SEEED_SOLAR_NODE) +#define HW_VENDOR meshtastic_HardwareModel_SEEED_SOLAR_NODE #elif defined(HELTEC_MESH_POCKET) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_POCKET #else @@ -135,4 +137,4 @@ #if !defined(PIN_SERIAL_RX) && !defined(NRF52840_XXAA) // No serial ports on this board - ONLY use segger in memory console #define USE_SEGGER -#endif +#endif \ No newline at end of file diff --git a/src/sleep.cpp b/src/sleep.cpp index 02fa8d871..2985db0c2 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -400,7 +400,7 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r #ifdef INPUTDRIVER_ENCODER_BTN gpio_wakeup_enable((gpio_num_t)INPUTDRIVER_ENCODER_BTN, GPIO_INTR_LOW_LEVEL); #endif -#ifdef T_WATCH_S3 +#if defined(T_WATCH_S3) || defined(ELECROW) gpio_wakeup_enable((gpio_num_t)SCREEN_TOUCH_INT, GPIO_INTR_LOW_LEVEL); #endif enableLoraInterrupt(); @@ -434,7 +434,7 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r gpio_wakeup_disable(pin); #endif -#ifdef T_WATCH_S3 +#if defined(T_WATCH_S3) || defined(ELECROW) gpio_wakeup_disable((gpio_num_t)SCREEN_TOUCH_INT); #endif diff --git a/variants/Seeed_Solar_Node/platformio.ini b/variants/Seeed_Solar_Node/platformio.ini new file mode 100644 index 000000000..9651d3a77 --- /dev/null +++ b/variants/Seeed_Solar_Node/platformio.ini @@ -0,0 +1,14 @@ +[env:Seeed_Solar_Node] +board = Seeed_Solar_Node +extends = nrf52840_base +;board_level = extra +build_flags = ${nrf52840_base.build_flags} + -I $PROJECT_DIR/variants/Seeed_Solar_Node + -D SEEED_SOLAR_NODE + -Isrc/platform/nrf52/softdevice -Isrc/platform/nrf52/softdevice/nrf52 + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" +board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/Seeed_Solar_Node> +lib_deps = + ${nrf52840_base.lib_deps} +debug_tool = jlink diff --git a/variants/Seeed_Solar_Node/variant.cpp b/variants/Seeed_Solar_Node/variant.cpp new file mode 100644 index 000000000..994e97ff9 --- /dev/null +++ b/variants/Seeed_Solar_Node/variant.cpp @@ -0,0 +1,108 @@ +/* + * variant.cpp - Digital pin mapping for nRF52-based development board + * + * This file defines the pin mapping array that maps logical digital pins (D0-D17) + * to physical GPIO ports/pins on the Nordic nRF52 series microcontroller. + * + * Board: [Seeed Studio XIAO nRF52840 Sense (Seeed Solar Node)] + * Hardware Features: + * - LoRa module (CS/SCK/MISO/MOSI control pins) + * - GNSS module (TX/RX/Reset/Wakeup) + * - User LEDs (D11-D12) + * - User button (D13) + * - Grove/NFC interface (D14-D15) + * - Battery voltage monitoring (D16) + * + * Created [20250225] + * By [Dylan] + * Version 1.0 + * License: [MIT] + */ + +#include "variant.h" +#include "nrf.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +/** + * @brief Digital pin to GPIO port/pin mapping table + * + * Format: Logical Pin (Dx) -> nRF Port.Pin (Px.xx) + * + * Pin Groupings: + * [D0-D10] - Peripheral control (LoRa, GNSS) + * [D11-D12] - LED outputs + * [D13] - User button + * [D14-D15] - Grove/NFC interface + * [D16] - Battery voltage ADC input + * [D17] - GNSS module reset + */ + +extern "C" { +const uint32_t g_ADigitalPinMap[] = { + // D0 .. D10 - Peripheral control pins + 2, // D0 P0.02 (A0) GNSS_WAKEUP + 3, // D1 P0.03 (A1) LORA_DIO1 + 28, // D2 P0.28 (A2) LORA_RESET + 29, // D3 P0.29 (A3) LORA_BUSY + 4, // D4 P0.04 (A4/SDA) LORA_CS + 5, // D5 P0.05 (A5/SCL) LORA_SW + 43, // D6 P1.11 (UART_TX) GNSS_TX + 44, // D7 P1.12 (UART_RX) GNSS_RX + 45, // D8 P1.13 (SPI_SCK) LORA_SCK + 46, // D9 P1.14 (SPI_MISO) LORA_MISO + 47, // D10 P1.15 (SPI_MOSI) LORA_MOSI + + // D11-D12 - LED outputs + 15, // D11 P0.15 User LED + 19, // D12 P0.19 Breathing LED + + // D13 - User input + 33, // D13 P1.01 User Button + + // D14-D15 - Grove/NFC interface + 9, // D14 P0.09 NFC1/GROVE_D1 + 10, // D15 P0.10 NFC2/GROVE_D0 + + // D16 - Power management + // 31, // D16 P0.31 VBAT_ADC (Battery voltage) + 31, // D16 P0.31 VBAT_ADC (Battery voltage) + // D17 - GNSS control + 35, // D17 P1.03 GNSS_RESET + + 37, // D18 P1.05 GNSS_ENABLE + 14, // D19 P0.14 BAT_READ + 39, // D20 P1.07 USER_BUTTON + + // + 21, // D21 P0.21 (QSPI_SCK) + 25, // D22 P0.25 (QSPI_CSN) + 20, // D23 P0.20 (QSPI_SIO_0 DI) + 24, // D24 P0.24 (QSPI_SIO_1 DO) + 22, // D25 P0.22 (QSPI_SIO_2 WP) + 23, // D26 P0.23 (QSPI_SIO_3 HOLD) +}; +} + +void initVariant() +{ + pinMode(PIN_QSPI_CS, OUTPUT); + digitalWrite(PIN_QSPI_CS, HIGH); + // This setup is crucial for ensuring low power consumption and proper initialization of the hardware components. + pinMode(GPS_EN, OUTPUT); + digitalWrite(GPS_EN, LOW); + + // VBAT_ENABLE + pinMode(BAT_READ, OUTPUT); + digitalWrite(BAT_READ, LOW); + + pinMode(PIN_LED1, OUTPUT); + digitalWrite(PIN_LED1, LOW); + pinMode(PIN_LED2, OUTPUT); + digitalWrite(PIN_LED2, LOW); + pinMode(PIN_LED2, OUTPUT); + // digitalWrite(LED_PIN, LOW); + + pinMode(GPS_EN, OUTPUT); + digitalWrite(GPS_EN, HIGH); +} \ No newline at end of file diff --git a/variants/Seeed_Solar_Node/variant.h b/variants/Seeed_Solar_Node/variant.h new file mode 100644 index 000000000..86682302b --- /dev/null +++ b/variants/Seeed_Solar_Node/variant.h @@ -0,0 +1,157 @@ +#ifndef _SEEED_SOLAR_NODE_H_ +#define _SEEED_SOLAR_NODE_H_ +#include "WVariant.h" +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Clock Configuration +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define VARIANT_MCK (64000000ul) // Master clock frequency +#define USE_LFXO // 32.768kHz crystal for LFCLK + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Pin Capacity Definitions +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define PINS_COUNT (33u) // Total GPIO pins +#define NUM_DIGITAL_PINS (33u) // Digital I/O pins +#define NUM_ANALOG_INPUTS (8u) // Analog inputs (A0-A5 + VBAT + AREF) +#define NUM_ANALOG_OUTPUTS (0u) + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// LED Configuration +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// LEDs +// LEDs +#define PIN_LED1 (11) // LED P1.15 +#define PIN_LED2 (12) // + +#define LED_BUILTIN PIN_LED1 +#define LED_CONN PIN_LED2 + +#define LED_GREEN PIN_LED1 +#define LED_BLUE PIN_LED2 +// #define LED_PIN PIN_LED2 +#define LED_STATE_ON 1 // State when LED is litted +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Button Configuration +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define BUTTON_PIN D13 // This is the Program Button +// #define BUTTON_NEED_PULLUP 1 +#define BUTTON_ACTIVE_LOW true +#define BUTTON_ACTIVE_PULLUP false + +#define BUTTON_PIN_TOUCH 20 // Touch button +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Digital Pin Mapping (D0-D10) +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define D0 0 // P0.02 GNSS_WAKEUP/IO0 +#define D1 1 // P0.03 LORA_DIO1 +#define D2 2 // P0.28 LORA_RESET +#define D3 3 // P0.29 LORA_BUSY +#define D4 4 // P0.04 LORA_CS/I2C_SDA +#define D5 5 // P0.05 LORA_SW/I2C_SCL +#define D6 6 // P1.11 GNSS_TX +#define D7 7 // P1.12 GNSS_RX +#define D8 8 // P1.13 SPI_SCK +#define D9 9 // P1.14 SPI_MISO +#define D10 10 // P1.15 SPI_MOSI +#define D13 13 // P1.01 User Button +#define D14 14 // P0.09 NFC1/GROVE_D1 +#define D15 15 // P0.10 NFC2/GROVE_D0 +#define D16 16 // P0.31 VBAT_ADC (Battery voltage) +#define D17 17 // P1.03 GNSS_RESET +#define D18 18 // P1.05 GNSS_ENABLE +#define D19 19 // P0.14 BAT_READ +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Analog Pin Definitions +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define PIN_A0 0 // P0.02 Analog Input 0 +#define PIN_A1 1 // P0.03 Analog Input 1 +#define PIN_A2 2 // P0.28 Analog Input 2 +#define PIN_A3 3 // P0.29 Analog Input 3 +#define PIN_A4 4 // P0.04 Analog Input 4 +#define PIN_A5 5 // P0.05 Analog Input 5 +#define PIN_VBAT D16 // P0.31 Battery voltage sense +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Communication Interfaces +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// I2C Configuration +#define HAS_WIRE 1 +#define PIN_WIRE_SDA D14 // P0.09 +#define PIN_WIRE_SCL D15 // P0.10 +#define WIRE_INTERFACES_COUNT 1 +#define I2C_NO_RESCAN + +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; +// SPI Configuration (SX1262) + +#define SPI_INTERFACES_COUNT 1 +#define PIN_SPI_MISO 9 // P1.14 (D9) +#define PIN_SPI_MOSI 10 // P1.15 (D10) +#define PIN_SPI_SCK 8 // P1.13 (D8) + +// SX1262 LoRa Module Pins +#define USE_SX1262 +#define SX126X_CS D4 // Chip select +#define SX126X_DIO1 D1 // Digital IO 1 (Interrupt) +#define SX126X_BUSY D3 // Busy status +#define SX126X_RESET D2 // Reset control +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 // TCXO supply voltage +#define SX126X_RXEN D5 // RX enable control +#define SX126X_TXEN RADIOLIB_NC +#define SX126X_DIO2_AS_RF_SWITCH // This Line is really necessary for SX1262 to work with RF switch or will loss TX power +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Power Management +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +#define BAT_READ \ + D19 // P0_14 = 14 Reads battery voltage from divider on signal board. (PIN_VBAT is reading voltage divider on XIAO and is + // program pin 32 / or P0.31) +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#define ADC_MULTIPLIER 3.3 +#define BATTERY_PIN PIN_VBAT // PIN_A7 +#define AREF_VOLTAGE 3.3 +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// GPS L76KB +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#define GPS_L76K +#ifdef GPS_L76K +#define PIN_GPS_RX D6 // 44 +#define PIN_GPS_TX D7 // 43 +#define HAS_GPS 1 +#define GPS_BAUDRATE 9600 +#define GPS_THREAD_INTERVAL 50 +#define PIN_SERIAL1_RX PIN_GPS_TX +#define PIN_SERIAL1_TX PIN_GPS_RX +#define PIN_GPS_STANDBY D0 +#define GPS_EN D18 // P1.05 +#endif + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// On-board QSPI Flash +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// On-board QSPI Flash +#define PIN_QSPI_SCK (21) +#define PIN_QSPI_CS (22) +#define PIN_QSPI_IO0 (23) +#define PIN_QSPI_IO1 (24) +#define PIN_QSPI_IO2 (25) +#define PIN_QSPI_IO3 (26) + +#define EXTERNAL_FLASH_DEVICES P25Q16H +#define EXTERNAL_FLASH_USE_QSPI + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Compatibility Definitions +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +#ifdef __cplusplus +extern "C" { +#endif +// Serial port placeholders + +#define PIN_SERIAL2_RX (-1) +#define PIN_SERIAL2_TX (-1) +#ifdef __cplusplus +} +#endif + +#endif // _SEEED_SOLAR_NODE_H_ \ No newline at end of file diff --git a/variants/elecrow_panel/pins_arduino.h b/variants/elecrow_panel/pins_arduino.h new file mode 100644 index 000000000..b98530378 --- /dev/null +++ b/variants/elecrow_panel/pins_arduino.h @@ -0,0 +1,64 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +// static const uint8_t LED_BUILTIN = -1; + +// static const uint8_t TX = 43; +// static const uint8_t RX = 44; + +static const uint8_t SDA = 39; +static const uint8_t SCL = 40; + +// Default SPI will be mapped to Radio +static const uint8_t SS = -1; +static const uint8_t MOSI = 48; +static const uint8_t MISO = 47; +static const uint8_t SCK = 41; + +#ifndef CROW_SELECT +static const uint8_t SPI_MOSI = 6; +static const uint8_t SPI_SCK = 5; +static const uint8_t SPI_MISO = 4; +static const uint8_t SPI_CS = 7; // SD does not support -1 +static const uint8_t SDCARD_CS = SPI_CS; +#endif + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +#endif /* Pins_Arduino_h */ \ No newline at end of file diff --git a/variants/elecrow_panel/platformio.ini b/variants/elecrow_panel/platformio.ini new file mode 100644 index 000000000..66dc35c3b --- /dev/null +++ b/variants/elecrow_panel/platformio.ini @@ -0,0 +1,123 @@ +[crowpanel_base] +extends = esp32s3_base +board = crowpanel +board_check = true +upload_protocol = esptool +board_build.partitions = default_16MB.csv ; must be here for some reason, board.json is not enough !? + +build_flags = ${esp32s3_base.build_flags} -Os + -I variants/elecrow_panel + -D ELECROW + -D ELECROW_PANEL + -D CONFIG_ARDUHAL_LOG_COLORS + -D RADIOLIB_DEBUG_SPI=0 + -D RADIOLIB_DEBUG_PROTOCOL=0 + -D RADIOLIB_DEBUG_BASIC=0 + -D RADIOLIB_VERBOSE_ASSERT=0 + -D RADIOLIB_SPI_PARANOID=0 + -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -D MESHTASTIC_EXCLUDE_INPUTBROKER=1 + -D MESHTASTIC_EXCLUDE_WEBSERVER=1 + -D MESHTASTIC_EXCLUDE_SERIAL=1 + -D MESHTASTIC_EXCLUDE_SOCKETAPI=1 + -D MESHTASTIC_EXCLUDE_SCREEN=1 + -D MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1 +; -D INPUTDRIVER_BUTTON_TYPE=0 + -D HAS_TELEMETRY=0 + -D CONFIG_DISABLE_HAL_LOCKS=1 + -D HAS_SCREEN=0 + -D HAS_TFT=1 + -D RAM_SIZE=6144 + -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 LV_BUILD_TEST=0 + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" + -D USE_PACKET_API + +lib_deps = ${esp32s3_base.lib_deps} + ${device-ui_base.lib_deps} + earlephilhower/ESP8266Audio@^1.9.9 + earlephilhower/ESP8266SAM@^1.0.1 + lovyan03/LovyanGFX@^1.2.0 + hideakitai/TCA9534@^0.1.1 + +[env:elecrow-24-28-tft] +extends = crowpanel_base + +build_flags = + ${crowpanel_base.build_flags} + -D TFT_HEIGHT=320 ; needed in variant.h + -D HAS_SDCARD + -D SDCARD_USE_SOFT_SPI + -D SPI_DRIVER_SELECT=2 + -D USE_PIN_BUZZER +; -D INPUTDRIVER_BUTTON_TYPE=0 ; no button as this pin is assigned to LoRa cs! + -D SCREEN_TOUCH_INT=47 ; used to wake up the MCU by touch + -D LGFX_DRIVER_TEMPLATE + -D LGFX_DRIVER=LGFX_GENERIC + -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_GENERIC.h\" + -D SPI_FREQUENCY=80000000 + -D LGFX_SCREEN_WIDTH=240 + -D LGFX_SCREEN_HEIGHT=320 + -D LGFX_PANEL=ST7789 + -D LGFX_ROTATION=1 + -D LGFX_CFG_HOST=SPI2_HOST + -D LGFX_PIN_SCK=42 + -D LGFX_PIN_MOSI=39 + -D LGFX_PIN_DC=41 + -D LGFX_PIN_CS=40 + -D LGFX_PIN_BL=38 + -D LGFX_TOUCH=FT5x06 + -D LGFX_TOUCH_I2C_ADDR=0x38 + -D LGFX_TOUCH_I2C_SDA=15 + -D LGFX_TOUCH_I2C_SCL=16 + -D LGFX_TOUCH_INT=47 + -D LGFX_TOUCH_RST=48 + -D LGFX_TOUCH_ROTATION=0 + -D VIEW_320x240 + -D MAP_FULL_REDRAW + +[env:elecrow-35-tft] +extends = crowpanel_base + +build_flags = + ${crowpanel_base.build_flags} + -D TFT_HEIGHT=480 ; needed in variant.h + -D HAS_SDCARD + -D SDCARD_USE_SOFT_SPI + -D SPI_DRIVER_SELECT=2 + -D USE_PIN_BUZZER +; -D INPUTDRIVER_BUTTON_TYPE=0 ; no button as this pin is assigned to LoRa cs! + -D SCREEN_TOUCH_INT=47 ; used to wake up the MCU by touch + -D LV_CACHE_DEF_SIZE=2097152 + -D LGFX_DRIVER_TEMPLATE + -D LGFX_DRIVER=LGFX_GENERIC + -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_GENERIC.h\" + -D SPI_FREQUENCY=60000000 + -D LGFX_SCREEN_WIDTH=320 + -D LGFX_SCREEN_HEIGHT=480 + -D LGFX_PANEL=ILI9488 + -D LGFX_ROTATION=0 + -D LGFX_CFG_HOST=SPI2_HOST + -D LGFX_PIN_SCK=42 + -D LGFX_PIN_MOSI=39 + -D LGFX_PIN_DC=41 + -D LGFX_PIN_CS=40 + -D LGFX_PIN_BL=38 + -D LGFX_TOUCH=GT911 + -D LGFX_TOUCH_I2C_ADDR=0x5D + -D LGFX_TOUCH_I2C_SDA=15 + -D LGFX_TOUCH_I2C_SCL=16 + -D LGFX_TOUCH_INT=47 + -D LGFX_TOUCH_RST=48 + -D LGFX_TOUCH_ROTATION=0 + -D DISPLAY_SET_RESOLUTION + -D VIEW_320x240 + -D MAP_FULL_REDRAW diff --git a/variants/elecrow_panel/variant.h b/variants/elecrow_panel/variant.h new file mode 100644 index 000000000..b1035ed31 --- /dev/null +++ b/variants/elecrow_panel/variant.h @@ -0,0 +1,195 @@ +#define I2C_SDA 15 +#define I2C_SCL 16 + +#if TFT_HEIGHT == 320 && not defined(HAS_TFT) // 2.4 and 2.8 TFT +// ST7789 TFT LCD +#define ST7789_CS 40 +#define ST7789_RS 41 // DC +#define ST7789_SDA 39 // MOSI +#define ST7789_SCK 42 +#define ST7789_RESET -1 +#define ST7789_MISO 38 +#define ST7789_BUSY -1 +#define ST7789_BL 38 +#define ST7789_SPI_HOST SPI2_HOST +#define TFT_BL 38 +#define SPI_FREQUENCY 60000000 +#define SPI_READ_FREQUENCY 16000000 +#define TFT_OFFSET_ROTATION 0 +#define SCREEN_ROTATE +#define TFT_DUMMY_READ_PIXELS 8 +#define SCREEN_TRANSITION_FRAMERATE 5 +#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness + +#define HAS_TOUCHSCREEN 1 +#define SCREEN_TOUCH_INT 47 +#define SCREEN_TOUCH_RST 48 +#define TOUCH_I2C_PORT 0 +#define TOUCH_SLAVE_ADDRESS 0x38 // FT5x06 +#endif + +#if TFT_HEIGHT == 480 && not defined(HAS_TFT) // 3.5 TFT +// ILI9488 TFT LCD +#define ILI9488_CS 40 +#define ILI9488_RS 41 // DC +#define ILI9488_SDA 39 // MOSI +#define ILI9488_SCK 42 +#define ILI9488_RESET -1 +#define ILI9488_MISO 38 +#define ILI9488_BUSY -1 +#define ILI9488_BL 38 +#define ILI9488_SPI_HOST SPI2_HOST +#define TFT_BL 38 +#define SPI_FREQUENCY 40000000 +#define SPI_READ_FREQUENCY 16000000 +#define TFT_OFFSET_ROTATION 0 +#define SCREEN_ROTATE +#define TFT_DUMMY_READ_PIXELS 8 +#define SCREEN_TRANSITION_FRAMERATE 5 +#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness + +#define HAS_TOUCHSCREEN 1 +#define SCREEN_TOUCH_INT 47 +#define SCREEN_TOUCH_RST 48 +#define TOUCH_I2C_PORT 0 +#define TOUCH_SLAVE_ADDRESS 0x5D // GT911 +#endif + +#ifdef CROW_SELECT +#define ST72xx_DE 42 +#define ST72xx_VSYNC 41 +#define ST72xx_HSYNC 40 +#define ST72xx_PCLK 39 +#define ST72xx_R0 7 +#define ST72xx_R1 17 +#define ST72xx_R2 18 +#define ST72xx_R3 3 +#define ST72xx_R4 46 +#define ST72xx_G0 9 +#define ST72xx_G1 10 +#define ST72xx_G2 11 +#define ST72xx_G3 12 +#define ST72xx_G4 13 +#define ST72xx_G5 14 +#define ST72xx_B0 21 +#define ST72xx_B1 47 +#define ST72xx_B2 48 +#define ST72xx_B3 45 +#define ST72xx_B4 38 + +#define HAS_TOUCHSCREEN 1 +#define TOUCH_I2C_PORT 0 +#define TOUCH_SLAVE_ADDRESS 0x5D // GT911 +#endif + +#if defined(CROW_SELECT) && CROW_SELECT == 1 // 4.3 TFT 800x480 +#define ST7265_HSYNC_POLARITY 0 +#define ST7265_HSYNC_FRONT_PORCH 24 +#define ST7265_HSYNC_PULSE_WIDTH 8 +#define ST7265_HSYNC_BACK_PORCH 24 +#define ST7265_VSYNC_POLARITY 1 +#define ST7265_VSYNC_FRONT_PORCH 24 +#define ST7265_VSYNC_PULSE_WIDTH 8 +#define ST7265_VSYNC_BACK_PORCH 24 +#define ST7265_PCLK_ACTIVE_NEG 1 +#endif + +#if defined(CROW_SELECT) && CROW_SELECT == 2 // 5.0 TFT 800x480 +#define ST7262_HSYNC_POLARITY 0 +#define ST7262_HSYNC_FRONT_PORCH 8 +#define ST7262_HSYNC_PULSE_WIDTH 4 +#define ST7262_HSYNC_BACK_PORCH 8 +#define ST7262_VSYNC_POLARITY 0 +#define ST7262_VSYNC_FRONT_PORCH 8 +#define ST7262_VSYNC_PULSE_WIDTH 4 +#define ST7262_VSYNC_BACK_PORCH 8 +#define ST7262_PCLK_ACTIVE_NEG 0 +#endif + +#if defined(CROW_SELECT) && CROW_SELECT == 3 // 7.0 TFT 800x480 +#define SC7277_HSYNC_POLARITY 0 +#define SC7277_HSYNC_FRONT_PORCH 8 +#define SC7277_HSYNC_PULSE_WIDTH 4 +#define SC7277_HSYNC_BACK_PORCH 8 +#define SC7277_VSYNC_POLARITY 0 +#define SC7277_VSYNC_FRONT_PORCH 8 +#define SC7277_VSYNC_PULSE_WIDTH 4 +#define SC7277_VSYNC_BACK_PORCH 8 +#define SC7277_PCLK_ACTIVE_NEG 0 +#endif + +#if TFT_HEIGHT == 320 // 2.4-2.8 have I2S audio +// dac / amp +// #define HAS_I2S // didn't get I2S sound working +#define PIN_BUZZER 8 // using pwm buzzer instead (nobody will notice, lol) +#define DAC_I2S_BCK 13 +#define DAC_I2S_WS 11 +#define DAC_I2S_DOUT 12 +#define DAC_I2S_MCLK 8 // don't use GPIO0 because it's assigned to LoRa or button +#else +#define PIN_BUZZER 8 +#endif + +// GPS via UART1 connector +#define HAS_GPS 1 +#define GPS_DEFAULT_NOT_PRESENT 1 +#define GPS_RX_PIN 18 +#define GPS_TX_PIN 17 + +// Extension Slot Layout, viewed from above (2.4-3.5) +// DIO1/IO1 o o IO2/NRESET +// SCK/IO10 o o IO16/NC +// MISO/IO9 o o IO15/NC +// MOSI/IO3 o o NC/DIO2 +// 3V3 o o IO46/BUSY +// GND o o IO0/NSS +// 5V/NC o o NC/DIO3 +// J9 J8 + +// Extension Slot Layout, viewed from above (4.3-7.0) +// !! DIO1/IO20 o o IO19/NRESET !! +// !! SCK/IO5 o o IO16/NC +// !! MISO/IO4 o o IO15/NC +// !! MOSI/IO6 o o NC/DIO2 +// 3V3 o o IO2/BUSY !! +// GND o o IO0/NSS +// 5V/NC o o NC/DIO3 +// J9 J8 + +// LoRa +#define USE_SX1262 +#define LORA_CS 0 // GND + +#if TFT_HEIGHT == 320 || TFT_HEIGHT == 480 // 2.4 - 3.5 TFT +#define LORA_SCK 10 +#define LORA_MISO 9 +#define LORA_MOSI 3 + +#define LORA_RESET 2 +#define LORA_DIO1 1 // SX1262 IRQ +#define LORA_DIO2 46 // SX1262 BUSY + +// need to pull IO45 low to enable LORA and disable Microphone on 24 28 35 +#define SENSOR_POWER_CTRL_PIN 45 +#define SENSOR_POWER_ON LOW +#else +#define LORA_SCK 5 +#define LORA_MISO 4 +#define LORA_MOSI 6 + +#define LORA_RESET 19 +#define LORA_DIO1 20 // SX1262 IRQ +#define LORA_DIO2 2 // SX1262 BUSY +#endif + +#define HW_SPI1_DEVICE +#define SX126X_CS LORA_CS +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_DIO2 +#define SX126X_RESET LORA_RESET +#define SX126X_DIO2_AS_RF_SWITCH + +#define SX126X_DIO3_TCXO_VOLTAGE 3.3 + +#define USE_VIRTUAL_KEYBOARD 1 +#define DISPLAY_CLOCK_FRAME 1 \ No newline at end of file