From 26fe314153807d5f01024a172b3d1a788ca2e4c3 Mon Sep 17 00:00:00 2001 From: fukuen Date: Fri, 28 Nov 2025 22:34:14 +0900 Subject: [PATCH 1/2] Arduino Nesso N1 support --- src/detect/ScanI2CTwoWire.cpp | 2 +- src/graphics/TFTDisplay.cpp | 9 +- src/input/i2cButton.cpp | 4 +- src/input/i2cButton.h | 2 +- src/main.cpp | 2 +- src/modules/Modules.cpp | 2 +- .../esp32c6/arduino_nesso_n1/GpioExtLogic.cpp | 12 ++ .../esp32c6/arduino_nesso_n1/GpioExtLogic.h | 14 ++ .../esp32c6/arduino_nesso_n1/pins_arduino.h | 22 +++ .../esp32c6/arduino_nesso_n1/platformio.ini | 36 +++++ variants/esp32c6/arduino_nesso_n1/variant.cpp | 127 ++++++++++++++++++ variants/esp32c6/arduino_nesso_n1/variant.h | 83 ++++++++++++ 12 files changed, 308 insertions(+), 7 deletions(-) create mode 100644 variants/esp32c6/arduino_nesso_n1/GpioExtLogic.cpp create mode 100644 variants/esp32c6/arduino_nesso_n1/GpioExtLogic.h create mode 100644 variants/esp32c6/arduino_nesso_n1/pins_arduino.h create mode 100644 variants/esp32c6/arduino_nesso_n1/platformio.ini create mode 100644 variants/esp32c6/arduino_nesso_n1/variant.cpp create mode 100644 variants/esp32c6/arduino_nesso_n1/variant.h diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index db269ac641..b15d0a2e90 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -298,7 +298,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) type = AHT10; break; #endif -#if !defined(M5STACK_UNITC6L) +#if !defined(M5STACK_UNITC6L) && !defined(ARDUINO_NESSO_N1) case INA_ADDR: case INA_ADDR_ALTERNATE: case INA_ADDR_WAVESHARE_UPS: diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 87593b0d41..caf8b1cada 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -15,6 +15,10 @@ extern SX1509 gpioExtender; #endif +#ifdef TFT_BL_EXT +#include "GpioExtLogic.h" +#endif + #ifdef TFT_MESH_OVERRIDE uint16_t TFT_MESH = TFT_MESH_OVERRIDE; #else @@ -479,7 +483,7 @@ class LGFX : public lgfx::LGFX_Device lgfx::Bus_SPI _bus_instance; lgfx::Light_PWM _light_instance; #if HAS_TOUCHSCREEN -#if defined(T_WATCH_S3) || defined(ELECROW) +#if defined(T_WATCH_S3) || defined(ELECROW) || defined(ARDUINO_NESSO_N1) lgfx::Touch_FT5x06 _touch_instance; #elif defined(HELTEC_V4_TFT) lgfx::TOUCH_CHSC6X _touch_instance; @@ -1160,6 +1164,9 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY g virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio p = virtPin; } +#elif defined(TFT_BL_EXT) + #include "GpioExtLogic.h" + GpioPin *p = new GpioExtPin(TFT_BL_EXT); #else GpioPin *p = new GpioVirtPin(); // Just simulate a pin #endif diff --git a/src/input/i2cButton.cpp b/src/input/i2cButton.cpp index d874146cde..ef49421d68 100644 --- a/src/input/i2cButton.cpp +++ b/src/input/i2cButton.cpp @@ -2,7 +2,7 @@ #include "meshUtils.h" #include "configuration.h" -#if defined(M5STACK_UNITC6L) +#if defined(M5STACK_UNITC6L) || defined(ARDUINO_NESSO_N1) #include "MeshService.h" #include "RadioLibInterface.h" @@ -92,4 +92,4 @@ int32_t i2cButtonThread::runOnce() } return 50; } -#endif \ No newline at end of file +#endif diff --git a/src/input/i2cButton.h b/src/input/i2cButton.h index 1ad9086061..992efd5c43 100644 --- a/src/input/i2cButton.h +++ b/src/input/i2cButton.h @@ -4,7 +4,7 @@ #include "OneButton.h" #include "concurrency/OSThread.h" #include "configuration.h" -#if defined(M5STACK_UNITC6L) +#if defined(M5STACK_UNITC6L) || defined(ARDUINO_NESSO_N1) class i2cButtonThread : public Observable, public concurrency::OSThread { diff --git a/src/main.cpp b/src/main.cpp index da2e396044..46343f6819 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -563,7 +563,7 @@ void setup() #endif #endif -#if defined(M5STACK_UNITC6L) +#if defined(M5STACK_UNITC6L) || defined(ARDUINO_NESSO_N1) pinMode(LORA_CS, OUTPUT); digitalWrite(LORA_CS, 1); c6l_init(); diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index 827524fc3a..23f9f227eb 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -203,7 +203,7 @@ void setupModules() #endif cardKbI2cImpl = new CardKbI2cImpl(); cardKbI2cImpl->init(); -#if defined(M5STACK_UNITC6L) +#if defined(M5STACK_UNITC6L) || defined(ARDUINO_NESSO_N1) i2cButton = new i2cButtonThread("i2cButtonThread"); #endif #ifdef INPUTBROKER_MATRIX_TYPE diff --git a/variants/esp32c6/arduino_nesso_n1/GpioExtLogic.cpp b/variants/esp32c6/arduino_nesso_n1/GpioExtLogic.cpp new file mode 100644 index 0000000000..b09dded537 --- /dev/null +++ b/variants/esp32c6/arduino_nesso_n1/GpioExtLogic.cpp @@ -0,0 +1,12 @@ +#include "GpioExtLogic.h" +#include + +void GpioExtPin::set(bool value) +{ + gpio_ext_set(this->address, this->pin, value); +} + +uint8_t GpioExtPin::get() +{ + return gpio_ext_get(this->address, this->pin); +} diff --git a/variants/esp32c6/arduino_nesso_n1/GpioExtLogic.h b/variants/esp32c6/arduino_nesso_n1/GpioExtLogic.h new file mode 100644 index 0000000000..85236cbb86 --- /dev/null +++ b/variants/esp32c6/arduino_nesso_n1/GpioExtLogic.h @@ -0,0 +1,14 @@ +#include "GpioLogic.h" + +class GpioExtPin : public GpioPin +{ + uint32_t num; + + public: + GpioExtPin(uint16_t _pin) : pin(_pin & 0x3F), address(_pin & 0x100 ? 0x44 : 0x43){}; + uint8_t pin; + uint8_t address; + + void set(bool value); + uint8_t get(); +}; diff --git a/variants/esp32c6/arduino_nesso_n1/pins_arduino.h b/variants/esp32c6/arduino_nesso_n1/pins_arduino.h new file mode 100644 index 0000000000..9cb528913d --- /dev/null +++ b/variants/esp32c6/arduino_nesso_n1/pins_arduino.h @@ -0,0 +1,22 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303A +#define USB_PID 0x1001 + +static const uint8_t TX = -1; +static const uint8_t RX = -1; + +static const uint8_t SDA = 10; +static const uint8_t SCL = 8; + +// Default SPI will be mapped to Radio +static const uint8_t MOSI = 21; +static const uint8_t MISO = 22; +static const uint8_t SCK = 20; +static const uint8_t SS = 23; + +#endif /* Pins_Arduino_h */ + diff --git a/variants/esp32c6/arduino_nesso_n1/platformio.ini b/variants/esp32c6/arduino_nesso_n1/platformio.ini new file mode 100644 index 0000000000..5ff93a90c0 --- /dev/null +++ b/variants/esp32c6/arduino_nesso_n1/platformio.ini @@ -0,0 +1,36 @@ +[env:arduino-nesso-n1] +extends = esp32c6_base +board = esp32-c6-devkitc-1 +upload_protocol = esptool +build_unflags = + -D HAS_BLUETOOTH + -D MESHTASTIC_EXCLUDE_BLUETOOTH + -D HAS_WIFI +lib_deps = + ${esp32c6_base.lib_deps} + h2zero/NimBLE-Arduino@^2.3.6 + lovyan03/LovyanGFX@^1.2.0 + https://github.com/mverch67/BQ27220/archive/07d92be846abd8a0258a50c23198dac0858b22ed.zip +build_flags = + ${esp32c6_base.build_flags} + -D PRIVATE_HW + -D ARDUINO_NESSO_N1 + -I variants/esp32c6/arduino_nesso_n1 + -DMESHTASTIC_EXCLUDE_PAXCOUNTER=1 + -DSOC_USB_OTG_SUPPORTED=1 + -DARDUINO_USB_CDC_ON_BOOT=1 + -DARDUINO_USB_MODE=1 + -D HAS_BLUETOOTH=1 + -D MESHTASTIC_EXCLUDE_WEBSERVER + -D MESHTASTIC_EXCLUDE_MQTT + -DCONFIG_BT_NIMBLE_EXT_ADV=1 + -DCONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2 + -D NIMBLE_TWO + -D CORE_DEBUG_LEVEL=5 + -D _ESP_LOGLEVEL_=5 +monitor_speed=115200 +lib_ignore = + NonBlockingRTTTL + libpax +build_src_filter = + ${esp32c6_base.build_src_filter} +<../variants/esp32c6/arduino_nesso_n1> diff --git a/variants/esp32c6/arduino_nesso_n1/variant.cpp b/variants/esp32c6/arduino_nesso_n1/variant.cpp new file mode 100644 index 0000000000..7b486b3185 --- /dev/null +++ b/variants/esp32c6/arduino_nesso_n1/variant.cpp @@ -0,0 +1,127 @@ +#include "driver/gpio.h" +#include +#include +// I2C device addr +#define PI4IO_M_ADDR 0x43 +#define PI4IO_M_ADDR2 0x44 + +// PI4IO registers +#define PI4IO_REG_CHIP_RESET 0x01 +#define PI4IO_REG_IO_DIR 0x03 +#define PI4IO_REG_OUT_SET 0x05 +#define PI4IO_REG_OUT_H_IM 0x07 +#define PI4IO_REG_IN_DEF_STA 0x09 +#define PI4IO_REG_PULL_EN 0x0B +#define PI4IO_REG_PULL_SEL 0x0D +#define PI4IO_REG_IN_STA 0x0F +#define PI4IO_REG_INT_MASK 0x11 +#define PI4IO_REG_IRQ_STA 0x13 +// PI4IO + +#define setbit(x, y) x |= (0x01 << y) +#define clrbit(x, y) x &= ~(0x01 << y) +#define reversebit(x, y) x ^= (0x01 << y) +#define getbit(x, y) ((x) >> (y)&0x01) + +void i2c_read_byte(uint8_t addr, uint8_t reg, uint8_t *value) +{ + Wire.beginTransmission(addr); + Wire.write(reg); + Wire.endTransmission(); + Wire.requestFrom(addr, 1); + *value = Wire.read(); +} + +/*******************************************************************/ +void i2c_write_byte(uint8_t addr, uint8_t reg, uint8_t value) +{ + Wire.beginTransmission(addr); + Wire.write(reg); + Wire.write(value); + Wire.endTransmission(); +} +/*******************************************************************/ +void c6l_init() +{ + // P7 LoRa Reset + // P6 RF Switch + // P5 LNA Enable + // P1 KEY2 + // P0 KEY1 + // P107 LED_BUILTIN + // P106 LCD_BACKLIGHT + // P105 VIN_DETECT + // P102 GROVE_POWER_EN + // P101 LCD_RESET + // P100 POWEROFF + + printf("pi4io_init\n"); + uint8_t in_data; + i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_CHIP_RESET, 0xFF); + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_read_byte(PI4IO_M_ADDR, PI4IO_REG_CHIP_RESET, &in_data); + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_IO_DIR, 0b11000000); // 0: input 1: output + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_OUT_H_IM, 0b00111100); // Output High-Impedance, 1 high-impedance + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_PULL_SEL, 0b11000011); // pull up/down select, 0 down, 1 up + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_PULL_EN, 0b11000011); // pull up/down enable, 0 disable, 1 enable + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_IN_DEF_STA, 0b00000011); // P0 P1 Default state HIGH, interrupt when pressed + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_INT_MASK, 0b11111100); // P0 P1 Interrupt 0 enable, 1 disable + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_OUT_SET, 0b10000000); // default output to 0 + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_read_byte(PI4IO_M_ADDR, PI4IO_REG_IRQ_STA, &in_data); // Read IRQ_STA clear register + + i2c_read_byte(PI4IO_M_ADDR, PI4IO_REG_OUT_SET, &in_data); + setbit(in_data, 6); // HIGH + i2c_write_byte(PI4IO_M_ADDR, PI4IO_REG_OUT_SET, in_data); + + i2c_write_byte(PI4IO_M_ADDR2, PI4IO_REG_CHIP_RESET, 0xFF); + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_read_byte(PI4IO_M_ADDR2, PI4IO_REG_CHIP_RESET, &in_data); + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR2, PI4IO_REG_IO_DIR, 0b11000110); // 0: input 1: output + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR2, PI4IO_REG_OUT_H_IM, 0b00111000); // Output High-Impedance, 1 high-impedance + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR2, PI4IO_REG_PULL_SEL, 0b11000111); // pull up/down select, 0 down, 1 up + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR2, PI4IO_REG_PULL_EN, 0b11000111); // pull up/down enable, 0 disable, 1 enable + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR2, PI4IO_REG_IN_DEF_STA, 0b00000000); // P0 P1 Default state HIGH, interrupt when pressed + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR2, PI4IO_REG_INT_MASK, 0b11111111); // P0 P1 Interrupt 0 enable, 1 disable + vTaskDelay(10 / portTICK_PERIOD_MS); + i2c_write_byte(PI4IO_M_ADDR2, PI4IO_REG_OUT_SET, 0b11000110); // default output to 0 + + // AW32001E - address 0x49 + // charge current 256mA (default 128mA) + i2c_write_byte(0x49, 0x2, 0x1f); + // charge voltage 4.200(default) + // disable watch dog timer (default: 0x1f) + i2c_write_byte(0x49, 0x5, 0x1a); + // UVLO: 2.580 (default: 2.760), charge enable, disable HIZ (default: 0xac) + i2c_write_byte(0x49, 0x1, 0xa2); + // DPM 4.520 (default) + i2c_write_byte(0x49, 0x0, 0x8f); +} + +void gpio_ext_set(uint8_t address, uint8_t pin, bool value) +{ + uint8_t in_data; + i2c_read_byte(address, PI4IO_REG_OUT_SET, &in_data); + value ? setbit(in_data, pin) : clrbit(in_data, pin); + i2c_write_byte(address, PI4IO_REG_OUT_SET, in_data); +} + +uint8_t gpio_ext_get(uint8_t address, uint8_t pin) +{ + uint8_t in_data; + i2c_read_byte(address, PI4IO_REG_OUT_SET, &in_data); + return getbit(in_data, pin); +} diff --git a/variants/esp32c6/arduino_nesso_n1/variant.h b/variants/esp32c6/arduino_nesso_n1/variant.h new file mode 100644 index 0000000000..3baf68a395 --- /dev/null +++ b/variants/esp32c6/arduino_nesso_n1/variant.h @@ -0,0 +1,83 @@ +void c6l_init(); +void gpio_ext_set(uint8_t address, uint8_t pin, bool value); +uint8_t gpio_ext_get(uint8_t address, uint8_t pin); + +#define HAS_GPS 0 +#define GPS_RX_PIN -1 +#define GPS_TX_PIN -1 + +#define I2C_SDA 10 +#define I2C_SCL 8 + +#define LCD_CS 17 +#define LCD_RS 16 +#define SYS_IRQ 3 + +#define MOSI 21 +#define MISO 22 +#define SCK 20 + +#define PIN_BUZZER 11 + +#define IO_EXPANDER 0x40 +#define LCD_BACKLIGHT 0x106 + +// #define BUTTON_PIN 9 +#define BUTTON_EXTENDER + +#undef LORA_SCK +#undef LORA_MISO +#undef LORA_MOSI +#undef LORA_CS + +// battery charger BQ25896 +//#define HAS_PPM 1 +//#define XPOWERS_CHIP_BQ25896 + +// battery quality management BQ27220 +#define HAS_BQ27220 1 +#define BQ27220_I2C_SDA I2C_SDA +#define BQ27220_I2C_SCL I2C_SCL +#define BQ27220_DESIGN_CAPACITY 250 + +// WaveShare Core1262-868M OK +// https://www.waveshare.com/wiki/Core1262-868M +#define USE_SX1262 + +#define LORA_MISO 22 +#define LORA_SCK 20 +#define LORA_MOSI 21 +#define LORA_CS 23 +#define LORA_RESET RADIOLIB_NC +#define LORA_DIO1 15 +#define LORA_BUSY 19 +#define SX126X_CS LORA_CS +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_BUSY +#define SX126X_RESET LORA_RESET +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 3.0 + +#define ST7789_DRIVER +#define ST7789_CS 17 +#define ST7789_RS 16 +#define ST7789_SDA 21 +#define ST7789_SCK 20 +#define ST7789_RESET -1 +#define ST7789_MISO 22 +#define ST7789_BUSY -1 +#define ST7789_SPI_HOST SPI2_HOST +#define SPI_FREQUENCY 40000000 +#define SPI_READ_FREQUENCY 16000000 +#define TFT_HEIGHT 240 +#define TFT_WIDTH 135 +#define TFT_OFFSET_X 52 +#define TFT_OFFSET_Y 40 +#define TFT_OFFSET_ROTATION 1 +#define SCREEN_TRANSITION_FRAMERATE 10 +#define BRIGHTNESS_DEFAULT 130 +#define HAS_TOUCHSCREEN 1 +#define TOUCH_I2C_PORT 0 +#define TOUCH_SLAVE_ADDRESS 0x38 +#define SCREEN_TOUCH_INT 3 +#define TFT_BL_EXT (LCD_BACKLIGHT | IO_EXPANDER) From 6716f2298dd1f1dcacf1b8f080ac41c48b87d7ca Mon Sep 17 00:00:00 2001 From: fukuen Date: Sat, 29 Nov 2025 00:29:22 +0900 Subject: [PATCH 2/2] fix --- src/graphics/TFTDisplay.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index caf8b1cada..bcbc0de06a 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -1165,7 +1165,6 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY g p = virtPin; } #elif defined(TFT_BL_EXT) - #include "GpioExtLogic.h" GpioPin *p = new GpioExtPin(TFT_BL_EXT); #else GpioPin *p = new GpioVirtPin(); // Just simulate a pin