diff --git a/examples/TBeamFactory/LoRaBoards.cpp b/examples/TBeamFactory/LoRaBoards.cpp new file mode 100644 index 0000000..53ff16e --- /dev/null +++ b/examples/TBeamFactory/LoRaBoards.cpp @@ -0,0 +1,855 @@ +/** + * @file boards.cpp + * @author Lewis He (lewishe@outlook.com) + * @license MIT + * @copyright Copyright (c) 2024 ShenZhen XinYuan Electronic Technology Co., Ltd + * @date 2024-04-24 + * @last-update 2024-08-07 + * + */ + +#include "LoRaBoards.h" + +#if defined(HAS_SDCARD) +SPIClass SDCardSPI(HSPI); +#endif + + +#if defined(ARDUINO_ARCH_STM32) +HardwareSerial SerialGPS(GPS_RX_PIN, GPS_TX_PIN); +#endif + +#if defined(ARDUINO_ARCH_ESP32) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0) +#include "hal/gpio_hal.h" +#endif +#include "driver/gpio.h" +#endif //ARDUINO_ARCH_ESP32 + + +DISPLAY_MODEL *u8g2 = NULL; +static DevInfo_t devInfo; + +#ifdef HAS_GPS +static bool find_gps = false; +#endif + + + +#ifdef HAS_PMU +XPowersLibInterface *PMU = NULL; +bool pmuInterrupt; + +static void setPmuFlag() +{ + pmuInterrupt = true; +} +#endif + +bool beginPower() +{ +#ifdef HAS_PMU + if (!PMU) { + PMU = new XPowersAXP2101(PMU_WIRE_PORT); + if (!PMU->init()) { + Serial.println("Warning: Failed to find AXP2101 power management"); + delete PMU; + PMU = NULL; + } else { + Serial.println("AXP2101 PMU init succeeded, using AXP2101 PMU"); + } + } + + if (!PMU) { + PMU = new XPowersAXP192(PMU_WIRE_PORT); + if (!PMU->init()) { + Serial.println("Warning: Failed to find AXP192 power management"); + delete PMU; + PMU = NULL; + } else { + Serial.println("AXP192 PMU init succeeded, using AXP192 PMU"); + } + } + + if (!PMU) { + return false; + } + + PMU->setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG); + + pinMode(PMU_IRQ, INPUT_PULLUP); + attachInterrupt(PMU_IRQ, setPmuFlag, FALLING); + + if (PMU->getChipModel() == XPOWERS_AXP192) { + + PMU->setProtectedChannel(XPOWERS_DCDC3); + + // lora + PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300); + // gps + PMU->setPowerChannelVoltage(XPOWERS_LDO3, 3300); + // oled + PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300); + + PMU->enablePowerOutput(XPOWERS_LDO2); + PMU->enablePowerOutput(XPOWERS_LDO3); + + //protected oled power source + PMU->setProtectedChannel(XPOWERS_DCDC1); + //protected esp32 power source + PMU->setProtectedChannel(XPOWERS_DCDC3); + // enable oled power + PMU->enablePowerOutput(XPOWERS_DCDC1); + + //disable not use channel + PMU->disablePowerOutput(XPOWERS_DCDC2); + + PMU->disableIRQ(XPOWERS_AXP192_ALL_IRQ); + + PMU->enableIRQ(XPOWERS_AXP192_VBUS_REMOVE_IRQ | + XPOWERS_AXP192_VBUS_INSERT_IRQ | + XPOWERS_AXP192_BAT_CHG_DONE_IRQ | + XPOWERS_AXP192_BAT_CHG_START_IRQ | + XPOWERS_AXP192_BAT_REMOVE_IRQ | + XPOWERS_AXP192_BAT_INSERT_IRQ | + XPOWERS_AXP192_PKEY_SHORT_IRQ + ); + + } else if (PMU->getChipModel() == XPOWERS_AXP2101) { + +#if defined(CONFIG_IDF_TARGET_ESP32) + //Unuse power channel + PMU->disablePowerOutput(XPOWERS_DCDC2); + PMU->disablePowerOutput(XPOWERS_DCDC3); + PMU->disablePowerOutput(XPOWERS_DCDC4); + PMU->disablePowerOutput(XPOWERS_DCDC5); + PMU->disablePowerOutput(XPOWERS_ALDO1); + PMU->disablePowerOutput(XPOWERS_ALDO4); + PMU->disablePowerOutput(XPOWERS_BLDO1); + PMU->disablePowerOutput(XPOWERS_BLDO2); + PMU->disablePowerOutput(XPOWERS_DLDO1); + PMU->disablePowerOutput(XPOWERS_DLDO2); + + // GNSS RTC PowerVDD 3300mV + PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300); + PMU->enablePowerOutput(XPOWERS_VBACKUP); + + //ESP32 VDD 3300mV + // ! No need to set, automatically open , Don't close it + // PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300); + // PMU->setProtectedChannel(XPOWERS_DCDC1); + PMU->setProtectedChannel(XPOWERS_DCDC1); + + // LoRa VDD 3300mV + PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO2); + + //GNSS VDD 3300mV + PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO3); + +#endif /*CONFIG_IDF_TARGET_ESP32*/ + + +#if defined(T_BEAM_S3_SUPREME) + + //t-beam m.2 inface + //gps + PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO4); + + // lora + PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO3); + + // In order to avoid bus occupation, during initialization, the SD card and QMC sensor are powered off and restarted + if (ESP_SLEEP_WAKEUP_UNDEFINED == esp_sleep_get_wakeup_cause()) { + Serial.println("Power off and restart ALDO BLDO.."); + PMU->disablePowerOutput(XPOWERS_ALDO1); + PMU->disablePowerOutput(XPOWERS_ALDO2); + PMU->disablePowerOutput(XPOWERS_BLDO1); + delay(250); + } + + // Sensor + PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO1); + + PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO2); + + //Sdcard + + PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); + PMU->enablePowerOutput(XPOWERS_BLDO1); + + PMU->setPowerChannelVoltage(XPOWERS_BLDO2, 3300); + PMU->enablePowerOutput(XPOWERS_BLDO2); + + //face m.2 + PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300); + PMU->enablePowerOutput(XPOWERS_DCDC3); + + PMU->setPowerChannelVoltage(XPOWERS_DCDC4, XPOWERS_AXP2101_DCDC4_VOL2_MAX); + PMU->enablePowerOutput(XPOWERS_DCDC4); + + PMU->setPowerChannelVoltage(XPOWERS_DCDC5, 3300); + PMU->enablePowerOutput(XPOWERS_DCDC5); + + + //not use channel + PMU->disablePowerOutput(XPOWERS_DCDC2); + // PMU->disablePowerOutput(XPOWERS_DCDC4); + // PMU->disablePowerOutput(XPOWERS_DCDC5); + PMU->disablePowerOutput(XPOWERS_DLDO1); + PMU->disablePowerOutput(XPOWERS_DLDO2); + PMU->disablePowerOutput(XPOWERS_VBACKUP); + + +#elif defined(T_BEAM_S3_BPF) + + //gps + PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO4); + + //Sdcard + PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO2); + + // Extern Power source + PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300); + PMU->enablePowerOutput(XPOWERS_DCDC3); + + PMU->setPowerChannelVoltage(XPOWERS_DCDC5, 3300); + PMU->enablePowerOutput(XPOWERS_DCDC5); + + PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300); + PMU->enablePowerOutput(XPOWERS_ALDO1); + + //not use channel + PMU->disablePowerOutput(XPOWERS_BLDO1); + PMU->disablePowerOutput(XPOWERS_BLDO2); + PMU->disablePowerOutput(XPOWERS_DCDC4); + PMU->disablePowerOutput(XPOWERS_DCDC2); + PMU->disablePowerOutput(XPOWERS_DCDC4); + PMU->disablePowerOutput(XPOWERS_DCDC5); + PMU->disablePowerOutput(XPOWERS_DLDO1); + PMU->disablePowerOutput(XPOWERS_DLDO2); + PMU->disablePowerOutput(XPOWERS_VBACKUP); + + +#endif + + // Set constant current charge current limit + PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA); + + // Set charge cut-off voltage + PMU->setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2); + + // Disable all interrupts + PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); + // Clear all interrupt flags + PMU->clearIrqStatus(); + // Enable the required interrupt function + PMU->enableIRQ( + XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | //BATTERY + XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | //VBUS + XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | //POWER KEY + XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ //CHARGE + // XPOWERS_AXP2101_PKEY_NEGATIVE_IRQ | XPOWERS_AXP2101_PKEY_POSITIVE_IRQ | //POWER KEY + ); + + } + + PMU->enableSystemVoltageMeasure(); + PMU->enableVbusVoltageMeasure(); + PMU->enableBattVoltageMeasure(); + + Serial.printf("=========================================\n"); + if (PMU->isChannelAvailable(XPOWERS_DCDC1)) { + Serial.printf("DC1 : %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC1)); + } + if (PMU->isChannelAvailable(XPOWERS_DCDC2)) { + Serial.printf("DC2 : %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC2)); + } + if (PMU->isChannelAvailable(XPOWERS_DCDC3)) { + Serial.printf("DC3 : %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC3)); + } + if (PMU->isChannelAvailable(XPOWERS_DCDC4)) { + Serial.printf("DC4 : %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC4)); + } + if (PMU->isChannelAvailable(XPOWERS_DCDC5)) { + Serial.printf("DC5 : %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC5) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC5)); + } + if (PMU->isChannelAvailable(XPOWERS_LDO2)) { + Serial.printf("LDO2 : %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO2)); + } + if (PMU->isChannelAvailable(XPOWERS_LDO3)) { + Serial.printf("LDO3 : %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO3)); + } + if (PMU->isChannelAvailable(XPOWERS_ALDO1)) { + Serial.printf("ALDO1: %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO1)); + } + if (PMU->isChannelAvailable(XPOWERS_ALDO2)) { + Serial.printf("ALDO2: %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO2)); + } + if (PMU->isChannelAvailable(XPOWERS_ALDO3)) { + Serial.printf("ALDO3: %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO3)); + } + if (PMU->isChannelAvailable(XPOWERS_ALDO4)) { + Serial.printf("ALDO4: %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO4)); + } + if (PMU->isChannelAvailable(XPOWERS_BLDO1)) { + Serial.printf("BLDO1: %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO1)); + } + if (PMU->isChannelAvailable(XPOWERS_BLDO2)) { + Serial.printf("BLDO2: %s Voltage: %04u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO2)); + } + Serial.printf("=========================================\n"); + + + // Set the time of pressing the button to turn off + PMU->setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S); + uint8_t opt = PMU->getPowerKeyPressOffTime(); + Serial.print("PowerKeyPressOffTime:"); + switch (opt) { + case XPOWERS_POWEROFF_4S: Serial.println("4 Second"); + break; + case XPOWERS_POWEROFF_6S: Serial.println("6 Second"); + break; + case XPOWERS_POWEROFF_8S: Serial.println("8 Second"); + break; + case XPOWERS_POWEROFF_10S: Serial.println("10 Second"); + break; + default: + break; + } +#endif + return true; +} + +void disablePeripherals() +{ + +#ifdef HAS_PMU + if (!PMU)return; +#if defined(T_BEAM_S3_BPF) + PMU->disablePowerOutput(XPOWERS_ALDO4); //gps + PMU->disablePowerOutput(XPOWERS_ALDO2); //Sdcard + PMU->disablePowerOutput(XPOWERS_DCDC3); // Extern Power source + PMU->disablePowerOutput(XPOWERS_DCDC5); + PMU->disablePowerOutput(XPOWERS_ALDO1); +#else + // LoRa VDD + PMU->disablePowerOutput(XPOWERS_ALDO2); + //GNSS VDD + PMU->disablePowerOutput(XPOWERS_ALDO3); +#endif +#endif + + +} + +void loopPMU() +{ +#ifdef HAS_PMU + if (!PMU) { + return; + } + if (!pmuInterrupt) { + return; + } + + pmuInterrupt = false; + // Get PMU Interrupt Status Register + uint32_t status = PMU->getIrqStatus(); + Serial.print("STATUS => HEX:"); + Serial.print(status, HEX); + Serial.print(" BIN:"); + Serial.println(status, BIN); + + if (PMU->isVbusInsertIrq()) { + Serial.println("isVbusInsert"); + } + if (PMU->isVbusRemoveIrq()) { + Serial.println("isVbusRemove"); + } + if (PMU->isBatInsertIrq()) { + Serial.println("isBatInsert"); + } + if (PMU->isBatRemoveIrq()) { + Serial.println("isBatRemove"); + } + if (PMU->isPekeyShortPressIrq()) { + Serial.println("isPekeyShortPress"); + } + if (PMU->isPekeyLongPressIrq()) { + Serial.println("isPekeyLongPress"); + } + if (PMU->isBatChargeDoneIrq()) { + Serial.println("isBatChargeDone"); + } + if (PMU->isBatChargeStartIrq()) { + Serial.println("isBatChagerStart"); + } + // Clear PMU Interrupt Status Register + PMU->clearIrqStatus(); +#endif +} + +bool beginDisplay() +{ + Wire.beginTransmission(DISPLAY_ADDR); + if (Wire.endTransmission() == 0) { + Serial.printf("Find Display model at 0x%X address\n", DISPLAY_ADDR); + u8g2 = new DISPLAY_MODEL(U8G2_R0, U8X8_PIN_NONE); + u8g2->begin(); + u8g2->clearBuffer(); + u8g2->setFont(u8g2_font_inb19_mr); + u8g2->drawStr(0, 30, "LilyGo"); + u8g2->drawHLine(2, 35, 47); + u8g2->drawHLine(3, 36, 47); + u8g2->drawVLine(45, 32, 12); + u8g2->drawVLine(46, 33, 12); + u8g2->setFont(u8g2_font_inb19_mf); + u8g2->drawStr(58, 60, "LoRa"); + u8g2->sendBuffer(); + u8g2->setFont(u8g2_font_fur11_tf); + delay(3000); + return true; + } + + Serial.printf("Warning: Failed to find Display at 0x%0X address\n", DISPLAY_ADDR); + return false; +} + + +bool beginSDCard() +{ +#ifdef SDCARD_CS + if (SD.begin(SDCARD_CS, SDCardSPI)) { + uint32_t cardSize = SD.cardSize() / (1024 * 1024); + Serial.print("Sd Card init succeeded, The current available capacity is "); + Serial.print(cardSize / 1024.0); + Serial.println(" GB"); + return true; + } else { + Serial.println("Warning: Failed to init Sd Card"); + } +#endif + return false; +} + +void beginWiFi() +{ + if (!WiFi.softAP(BOARD_VARIANT_NAME)) { + log_e("Soft AP creation failed."); + } + IPAddress myIP = WiFi.softAPIP(); + Serial.print("AP IP address: "); + Serial.println(myIP); +} + + +void printWakeupReason() +{ +#ifdef ESP32 + Serial.print("Reset reason:"); + esp_sleep_wakeup_cause_t wakeup_reason; + wakeup_reason = esp_sleep_get_wakeup_cause(); + switch (wakeup_reason) { + case ESP_SLEEP_WAKEUP_UNDEFINED: + Serial.println(" In case of deep sleep, reset was not caused by exit from deep sleep"); + break; + case ESP_SLEEP_WAKEUP_ALL : + break; + case ESP_SLEEP_WAKEUP_EXT0 : + Serial.println("Wakeup caused by external signal using RTC_IO"); + break; + case ESP_SLEEP_WAKEUP_EXT1 : + Serial.println("Wakeup caused by external signal using RTC_CNTL"); + break; + case ESP_SLEEP_WAKEUP_TIMER : + Serial.println("Wakeup caused by timer"); + break; + case ESP_SLEEP_WAKEUP_TOUCHPAD : + Serial.println("Wakeup caused by touchpad"); + break; + case ESP_SLEEP_WAKEUP_ULP : + Serial.println("Wakeup caused by ULP program"); + break; + default : + Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason); + break; + } +#endif +} + + +void getChipInfo() +{ +#if defined(ARDUINO_ARCH_ESP32) + + Serial.println("-----------------------------------"); + + printWakeupReason(); + +#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3) + + if (psramFound()) { + uint32_t psram = ESP.getPsramSize(); + devInfo.psramSize = psram / 1024.0 / 1024.0; + Serial.printf("PSRAM is enable! PSRAM: %.2fMB\n", devInfo.psramSize); + } else { + Serial.println("PSRAM is disable!"); + devInfo.psramSize = 0; + } + +#endif + + Serial.print("Flash:"); + devInfo.flashSize = ESP.getFlashChipSize() / 1024.0 / 1024.0; + devInfo.flashSpeed = ESP.getFlashChipSpeed() / 1000 / 1000; + devInfo.chipModel = ESP.getChipModel(); + devInfo.chipModelRev = ESP.getChipRevision(); + devInfo.chipFreq = ESP.getCpuFreqMHz(); + + Serial.print(devInfo.flashSize); + Serial.println(" MB"); + Serial.print("Flash speed:"); + Serial.print(devInfo.flashSpeed); + Serial.println(" M"); + Serial.print("Model:"); + + Serial.println(devInfo.chipModel); + Serial.print("Chip Revision:"); + Serial.println(devInfo.chipModelRev); + Serial.print("Freq:"); + Serial.print(devInfo.chipFreq); + Serial.println(" MHZ"); + Serial.print("SDK Ver:"); + Serial.println(ESP.getSdkVersion()); + Serial.print("DATE:"); + Serial.println(__DATE__); + Serial.print("TIME:"); + Serial.println(__TIME__); + + Serial.print("EFUSE MAC: "); + Serial.print( ESP.getEfuseMac(), HEX); + Serial.println(); + + Serial.println("-----------------------------------"); + +#elif defined(ARDUINO_ARCH_STM32) + uint32_t uid[3]; + + uid[0] = HAL_GetUIDw0(); + uid[1] = HAL_GetUIDw1(); + uid[2] = HAL_GetUIDw2(); + Serial.print("STM UID: 0X"); + Serial.print( uid[0], HEX); + Serial.print( uid[1], HEX); + Serial.print( uid[2], HEX); + Serial.println(); +#endif +} + + + +void setupBoards(bool disable_u8g2 ) +{ + Serial.begin(115200); + + // while (!Serial); + + Serial.println("setupBoards"); + + getChipInfo(); + +#if defined(ARDUINO_ARCH_ESP32) + SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN); +#elif defined(ARDUINO_ARCH_STM32) + SPI.setMISO(RADIO_MISO_PIN); + SPI.setMOSI(RADIO_MOSI_PIN); + SPI.setSCLK(RADIO_SCLK_PIN); + SPI.begin(); +#endif + +#ifdef HAS_SDCARD + SDCardSPI.begin(SDCARD_SCLK, SDCARD_MISO, SDCARD_MOSI); +#endif + +#ifdef I2C_SDA + Wire.begin(I2C_SDA, I2C_SCL); + scanDevices(&Wire); +#endif + +#ifdef I2C1_SDA + Wire1.begin(I2C1_SDA, I2C1_SCL); +#endif + +#ifdef HAS_GPS +#if defined(ARDUINO_ARCH_ESP32) + SerialGPS.begin(GPS_BAUD_RATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN); +#elif defined(ARDUINO_ARCH_STM32) + SerialGPS.setRx(GPS_RX_PIN); + SerialGPS.setTx(GPS_TX_PIN); + SerialGPS.begin(GPS_BAUD_RATE); +#endif // ARDUINO_ARCH_ +#endif // HAS_GPS + +#if OLED_RST + pinMode(OLED_RST, OUTPUT); + digitalWrite(OLED_RST, HIGH); delay(20); + digitalWrite(OLED_RST, LOW); delay(20); + digitalWrite(OLED_RST, HIGH); delay(20); +#endif + +#ifdef BOARD_LED + /* + * T-Beam LED defaults to low level as turn on, + * so it needs to be forced to pull up + * * * * */ +#if LED_ON == LOW +#if defined(ARDUINO_ARCH_ESP32) + gpio_hold_dis((gpio_num_t)BOARD_LED); +#endif //ARDUINO_ARCH_ESP32 +#endif + + pinMode(BOARD_LED, OUTPUT); + digitalWrite(BOARD_LED, LED_ON); +#endif + +#ifdef GPS_EN_PIN + pinMode(GPS_EN_PIN, OUTPUT); + digitalWrite(GPS_EN_PIN, HIGH); +#endif + +#ifdef GPS_RST_PIN + pinMode(GPS_RST_PIN, OUTPUT); + digitalWrite(GPS_RST_PIN, HIGH); +#endif + + +#if defined(ARDUINO_ARCH_STM32) + SerialGPS.println("@GSR"); delay(300); + SerialGPS.println("@GSR"); delay(300); + SerialGPS.println("@GSR"); delay(300); + SerialGPS.println("@GSR"); delay(300); + SerialGPS.println("@GSR"); delay(300); +#endif + + +#ifdef RADIO_LDO_EN + pinMode(RADIO_LDO_EN, OUTPUT); + digitalWrite(RADIO_LDO_EN, HIGH); +#endif + + beginPower(); + + beginSDCard(); + + if (!disable_u8g2) { + beginDisplay(); + } + + // beginWiFi(); + +#ifdef HAS_GPS +#ifdef T_BEAM_S3_BPF + find_gps = beginGPS(); +#endif +#endif + + Serial.println("init done . "); +} + + +void printResult(bool radio_online) +{ + Serial.print("Radio : "); + Serial.println((radio_online) ? "+" : "-"); + +#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3) + + Serial.print("PSRAM : "); + Serial.println((psramFound()) ? "+" : "-"); + + Serial.print("Display : "); + Serial.println(( u8g2) ? "+" : "-"); + +#ifdef HAS_SDCARD + Serial.print("Sd Card : "); + Serial.println((SD.cardSize() != 0) ? "+" : "-"); +#endif + +#ifdef HAS_PMU + Serial.print("Power : "); + Serial.println(( PMU ) ? "+" : "-"); +#endif + +#ifdef HAS_GPS +#ifdef T_BEAM_S3_BPF + Serial.print("GPS : "); + Serial.println(( find_gps ) ? "+" : "-"); +#endif +#endif + + if (u8g2) { + + u8g2->clearBuffer(); + u8g2->setFont(u8g2_font_NokiaLargeBold_tf ); + uint16_t str_w = u8g2->getStrWidth(BOARD_VARIANT_NAME); + u8g2->drawStr((u8g2->getWidth() - str_w) / 2, 16, BOARD_VARIANT_NAME); + u8g2->drawHLine(5, 21, u8g2->getWidth() - 5); + + u8g2->drawStr( 0, 38, "Disp:"); u8g2->drawStr( 45, 38, ( u8g2) ? "+" : "-"); + +#ifdef HAS_SDCARD + u8g2->drawStr( 0, 54, "SD :"); u8g2->drawStr( 45, 54, (SD.cardSize() != 0) ? "+" : "-"); +#endif + + u8g2->drawStr( 62, 38, "Radio:"); u8g2->drawStr( 120, 38, ( radio_online ) ? "+" : "-"); + +#ifdef HAS_PMU + u8g2->drawStr( 62, 54, "Power:"); u8g2->drawStr( 120, 54, ( PMU ) ? "+" : "-"); +#endif + + u8g2->sendBuffer(); + + delay(2000); + } +#endif +} + + + +static uint8_t ledState = LOW; +static const uint32_t debounceDelay = 50; +static uint32_t lastDebounceTime = 0; + +void flashLed() +{ +#ifdef BOARD_LED + if ((millis() - lastDebounceTime) > debounceDelay) { + ledState = !ledState; + if (ledState) { + digitalWrite(BOARD_LED, LED_ON); + } else { + digitalWrite(BOARD_LED, !LED_ON); + } + lastDebounceTime = millis(); + } +#endif +} + + +void scanDevices(TwoWire *w) +{ + uint8_t err, addr; + int nDevices = 0; + uint32_t start = 0; + + Serial.println("I2C Devices scanning"); + for (addr = 1; addr < 127; addr++) { + start = millis(); + w->beginTransmission(addr); delay(2); + err = w->endTransmission(); + if (err == 0) { + nDevices++; + switch (addr) { + case 0x77: + case 0x76: + Serial.println("\tFind BMX280 Sensor!"); + break; + case 0x34: + Serial.println("\tFind AXP192/AXP2101 PMU!"); + break; + case 0x3C: + Serial.println("\tFind SSD1306/SH1106 dispaly!"); + break; + case 0x51: + Serial.println("\tFind PCF8563 RTC!"); + break; + case 0x1C: + Serial.println("\tFind QMC6310 MAG Sensor!"); + break; + default: + Serial.print("\tI2C device found at address 0x"); + if (addr < 16) { + Serial.print("0"); + } + Serial.print(addr, HEX); + Serial.println(" !"); + break; + } + + } else if (err == 4) { + Serial.print("Unknow error at address 0x"); + if (addr < 16) { + Serial.print("0"); + } + Serial.println(addr, HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found\n"); + + Serial.println("Scan devices done."); + Serial.println("\n"); +} + + +#ifdef HAS_GPS +bool beginGPS() +{ + SerialGPS.begin(GPS_BAUD_RATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN); + bool result = false; + uint32_t startTimeout ; + for (int i = 0; i < 3; ++i) { + SerialGPS.write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n"); + delay(5); + // Get version information + startTimeout = millis() + 3000; + Serial.print("Try to init L76K . Wait stop ."); + while (SerialGPS.available()) { + Serial.print("."); + SerialGPS.readString(); + if (millis() > startTimeout) { + Serial.println("Wait L76K stop NMEA timeout!"); + return false; + } + }; + Serial.println(); + SerialGPS.flush(); + delay(200); + + SerialGPS.write("$PCAS06,0*1B\r\n"); + startTimeout = millis() + 500; + String ver = ""; + while (!SerialGPS.available()) { + if (millis() > startTimeout) { + Serial.println("Get L76K timeout!"); + return false; + } + } + SerialGPS.setTimeout(10); + ver = SerialGPS.readStringUntil('\n'); + if (ver.startsWith("$GPTXT,01,01,02")) { + Serial.println("L76K GNSS init succeeded, using L76K GNSS Module\n"); + result = true; + break; + } + delay(500); + } + // Initialize the L76K Chip, use GPS + GLONASS + SerialGPS.write("$PCAS04,5*1C\r\n"); + delay(250); + // only ask for RMC and GGA + SerialGPS.write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n"); + delay(250); + // Switch to Vehicle Mode, since SoftRF enables Aviation < 2g + SerialGPS.write("$PCAS11,3*1E\r\n"); + return result; +} +#endif \ No newline at end of file diff --git a/examples/TBeamFactory/LoRaBoards.h b/examples/TBeamFactory/LoRaBoards.h new file mode 100644 index 0000000..1bceb83 --- /dev/null +++ b/examples/TBeamFactory/LoRaBoards.h @@ -0,0 +1,102 @@ +/** + * @file boards.h + * @author Lewis He (lewishe@outlook.com) + * @license MIT + * @copyright Copyright (c) 2024 ShenZhen XinYuan Electronic Technology Co., Ltd + * @date 2024-04-25 + * @last-update 2024-08-07 + */ + +#pragma once + + +#include "utilities.h" + +#ifdef HAS_SDCARD +#include +#endif + +#if defined(ARDUINO_ARCH_ESP32) +#include +#include +#endif + +#include +#include +#include +#include +#include + +#ifndef DISPLAY_MODEL +#define DISPLAY_MODEL U8G2_SSD1306_128X64_NONAME_F_HW_I2C +#endif + +#ifndef OLED_WIRE_PORT +#define OLED_WIRE_PORT Wire +#endif + +#ifndef PMU_WIRE_PORT +#define PMU_WIRE_PORT Wire +#endif + +#ifndef DISPLAY_ADDR +#define DISPLAY_ADDR 0x3C +#endif + +#ifndef LORA_FREQ_CONFIG +#define LORA_FREQ_CONFIG 915.0 +#endif + + + + +typedef struct { + String chipModel; + float psramSize; + uint8_t chipModelRev; + uint8_t chipFreq; + uint8_t flashSize; + uint8_t flashSpeed; +} DevInfo_t; + + +void setupBoards(bool disable_u8g2 = false); + +bool beginSDCard(); + +bool beginDisplay(); + +void disablePeripherals(); + +bool beginPower(); + +void printResult(bool radio_online); + +void flashLed(); + +void scanDevices(TwoWire *w); + +bool beginGPS(); + +void loopPMU(); + +#ifdef HAS_PMU +extern XPowersLibInterface *PMU; +extern bool pmuInterrupt; +#endif +extern DISPLAY_MODEL *u8g2; + +#define U8G2_HOR_ALIGN_CENTER(t) ((u8g2->getDisplayWidth() - (u8g2->getUTF8Width(t))) / 2) +#define U8G2_HOR_ALIGN_RIGHT(t) ( u8g2->getDisplayWidth() - u8g2->getUTF8Width(t)) + + +#if defined(ARDUINO_ARCH_ESP32) + +#if defined(HAS_SDCARD) +extern SPIClass SDCardSPI; +#endif + +#define SerialGPS Serial1 +#elif defined(ARDUINO_ARCH_STM32) +extern HardwareSerial SerialGPS; +#endif diff --git a/examples/TBeamFactory/TBeamFactory.ino b/examples/TBeamFactory/TBeamFactory.ino new file mode 100644 index 0000000..d590bc2 --- /dev/null +++ b/examples/TBeamFactory/TBeamFactory.ino @@ -0,0 +1,569 @@ +/** + * @file TBeamFactory.ino + * @author Lewis He (lewishe@outlook.com) + * @license MIT + * @copyright Copyright (c) 2024 Shenzhen Xin Yuan Electronic Technology Co., Ltd + * @date 2024-11-18 + * + */ + +#include +#include +#include +#include +#include +#include +#include "OLEDDisplayUi.h" +#include +#include "utilities.h" +#include +#include "LoRaBoards.h" + +using namespace ace_button; + +void radioTx(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); +void radioRx(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); +void hwInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); + +#if defined(USING_SX1276) +#define CONFIG_RADIO_FREQ 868.0 +#define CONFIG_RADIO_OUTPUT_POWER 17 +#define CONFIG_RADIO_BW 125.0 +SX1276 radio = new Module(RADIO_CS_PIN, RADIO_DIO0_PIN, RADIO_RST_PIN, RADIO_DIO1_PIN); + +#elif defined(USING_SX1278) +#define CONFIG_RADIO_FREQ 433.0 +#define CONFIG_RADIO_OUTPUT_POWER 17 +#define CONFIG_RADIO_BW 125.0 +SX1278 radio = new Module(RADIO_CS_PIN, RADIO_DIO0_PIN, RADIO_RST_PIN, RADIO_DIO1_PIN); + +#elif defined(USING_SX1262) +#define CONFIG_RADIO_FREQ 850.0 +#define CONFIG_RADIO_OUTPUT_POWER 22 +#define CONFIG_RADIO_BW 125.0 + +SX1262 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN); + +#elif defined(USING_SX1280) +#define CONFIG_RADIO_FREQ 2400.0 +#define CONFIG_RADIO_OUTPUT_POWER 13 +#define CONFIG_RADIO_BW 203.125 +SX1280 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN); + +#elif defined(USING_SX1280PA) +#define CONFIG_RADIO_FREQ 2400.0 +#define CONFIG_RADIO_OUTPUT_POWER 3 // PA Version power range : -18 ~ 3dBm +#define CONFIG_RADIO_BW 203.125 +SX1280 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN); + +#elif defined(USING_LR1121) + +// The maximum power of LR1121 2.4G band can only be set to 13 dBm +#define CONFIG_RADIO_FREQ 2450.0 +#define CONFIG_RADIO_OUTPUT_POWER 13 +#define CONFIG_RADIO_BW 125.0 + +// The maximum power of LR1121 Sub 1G band can only be set to 22 dBm +// #define CONFIG_RADIO_FREQ 868.0 +// #define CONFIG_RADIO_OUTPUT_POWER 22 +// #define CONFIG_RADIO_BW 125.0 + +LR1121 radio = new Module(RADIO_CS_PIN, RADIO_DIO9_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN); +#endif + + +// save transmission state between loops +int transmissionState = RADIOLIB_ERR_NONE; +bool transmittedFlag = false; +uint32_t transmissionCounter = 0; +uint32_t recvCounter = 0; +float radioRSSI = 0; + +bool isRadioOnline = false; +bool isSdCardOnline = false; +bool rxStatus = true; +uint32_t radioRunInterval = 0; +uint32_t batteryRunInterval = 0; + +SSD1306Wire display(0x3c, I2C_SDA, I2C_SCL); +OLEDDisplayUi ui( &display ); +FrameCallback frames[] = { hwInfo, radioTx, radioRx}; +SPIClass SDSPI(HSPI); +AceButton button; + + +void setFlag(void) +{ + // we got a packet, set the flag + transmittedFlag = true; +} + + +void handleEvent(AceButton *button, uint8_t eventType, uint8_t buttonState) +{ + int state ; + static uint8_t frameCounter = 1; + switch (eventType) { + case AceButton::kEventClicked: + Serial.printf("frameCounter : %d\n", frameCounter); + switch (frameCounter) { + case 0: + break; + case 1: + Serial.println("Start transmit"); + state = radio.transmit((uint8_t *)&transmissionCounter, 4); + if (state != RADIOLIB_ERR_NONE) { + Serial.println(F("[Radio] transmit packet failed!")); + } + break; + case 2: + Serial.println("Start receive"); + state = radio.startReceive(); + if (state != RADIOLIB_ERR_NONE) { + Serial.println(F("[Radio] Received packet failed!")); + } + break; + default: + break; + } + frameCounter++; + ui.nextFrame(); + frameCounter %= 3; + break; + case AceButton::kEventLongPressed: + Serial.println("Long pressed!"); + + display.clear(); + + digitalWrite(RADIO_RST_PIN, HIGH); + gpio_hold_en((gpio_num_t) RADIO_RST_PIN); + gpio_deep_sleep_hold_en(); + + radio.sleep(); + + display.drawString(60, 28, "Sleep"); + display.display(); + delay(2000); + display.displayOff(); + +#ifdef BOARD_LED + digitalWrite(BOARD_LED, LOW); +#endif + +#ifdef RADIO_TCXO_ENABLE + digitalWrite(RADIO_TCXO_ENABLE, LOW); +#endif + +#ifdef BUTTON_PIN + while (digitalRead(BUTTON_PIN) == LOW) + delay(1); +#endif + + disablePeripherals(); + + SPI.end(); + + Wire.end(); + + Serial.flush(); + + Serial.end(); + + pinMode(RADIO_CS_PIN, INPUT); + pinMode(RADIO_RST_PIN, INPUT); + +#ifdef RADIO_DIO0_PIN + pinMode(RADIO_DIO0_PIN, INPUT); +#endif +#ifdef RADIO_DIO1_PIN + pinMode(RADIO_DIO1_PIN, INPUT); +#endif +#ifdef RADIO_DIO9_PIN + pinMode(RADIO_DIO9_PIN, INPUT); +#endif +#ifdef RADIO_BUSY_PIN + pinMode(RADIO_BUSY_PIN, INPUT); +#endif + pinMode(RADIO_CS_PIN, INPUT); + pinMode(I2C_SDA, INPUT); + pinMode(I2C_SCL, INPUT); +#ifdef OLED_RST + pinMode(OLED_RST, INPUT); +#endif + + pinMode(RADIO_SCLK_PIN, INPUT); + pinMode(RADIO_MISO_PIN, INPUT); + pinMode(RADIO_MOSI_PIN, INPUT); + +#ifdef SDCARD_MOSI + pinMode(SDCARD_MOSI, INPUT); + pinMode(SDCARD_MISO, INPUT); + pinMode(SDCARD_SCLK, INPUT); + pinMode(SDCARD_CS, INPUT); +#endif + + pinMode(BOARD_LED, INPUT); + +#ifdef ADC_PIN + pinMode(ADC_PIN, INPUT); +#endif + + // esp_sleep_enable_ext0_wakeup(GPIO_NUM_0, 0); + + // TBeam-v1.2 ext1 sleep ~607uA , + // See sleep_current.jpg + esp_sleep_enable_ext1_wakeup(_BV(BUTTON_PIN), ESP_EXT1_WAKEUP_ALL_LOW); + + // esp_sleep_enable_timer_wakeup(30 * 1000 * 1000); + + esp_deep_sleep_start(); + + Serial.println("Never print()"); + break; + } +} + +void setup() +{ + if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_ALL) { + gpio_deep_sleep_hold_dis(); + gpio_hold_dis((gpio_num_t) RADIO_RST_PIN); + } + + setupBoards(); + + delay(1000); + +#ifdef RADIO_TCXO_ENABLE + pinMode(RADIO_TCXO_ENABLE, OUTPUT); + digitalWrite(RADIO_TCXO_ENABLE, HIGH); +#endif + + pinMode(BUTTON_PIN, INPUT_PULLUP); + button.init(BUTTON_PIN); + ButtonConfig *buttonConfig = button.getButtonConfig(); + buttonConfig->setEventHandler(handleEvent); + buttonConfig->setFeature(ButtonConfig::kFeatureClick); + buttonConfig->setFeature(ButtonConfig::kFeatureLongPress); + + // Initialising the UI will init the display too. + ui.setTargetFPS(60); + + // You can change this to + // TOP, LEFT, BOTTOM, RIGHT + ui.setIndicatorPosition(BOTTOM); + + // Defines where the first frame is located in the bar. + ui.setIndicatorDirection(LEFT_RIGHT); + + // You can change the transition that is used + // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_UP, SLIDE_DOWN + ui.setFrameAnimation(SLIDE_LEFT); + + // Add frames + ui.setFrames(frames, sizeof(frames) / sizeof(frames[0])); + + ui.disableAutoTransition(); + + // Initialising the UI will init the display too. + ui.init(); + + display.flipScreenVertically(); + + Serial.print(F("[Radio] Initializing ... ")); + int state = radio.begin(); + if ( state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.println(F("failed!")); + } + isRadioOnline = state == RADIOLIB_ERR_NONE; + +#if defined(RADIO_RX_PIN) && defined(RADIO_TX_PIN) + //The SX1280 version needs to set RX, TX antenna switching pins + radio.setRfSwitchPins(RADIO_RX_PIN, RADIO_TX_PIN); +#endif + + /* + * Sets carrier frequency. + * SX1278/SX1276 : Allowed values range from 137.0 MHz to 525.0 MHz. + * SX1268/SX1262 : Allowed values are in range from 150.0 to 960.0 MHz. + * SX1280 : Allowed values are in range from 2400.0 to 2500.0 MHz. + * LR1121 : Allowed values are in range from 150.0 to 960.0 MHz, 1900 - 2200 MHz and 2400 - 2500 MHz. Will also perform calibrations. + * * * */ + + if (radio.setFrequency(CONFIG_RADIO_FREQ) == RADIOLIB_ERR_INVALID_FREQUENCY) { + Serial.println(F("Selected frequency is invalid for this module!")); + while (true); + } + + /* + * Sets LoRa link bandwidth. + * SX1278/SX1276 : Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz. Only available in %LoRa mode. + * SX1268/SX1262 : Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0, 250.0 and 500.0 kHz. + * SX1280 : Allowed values are 203.125, 406.25, 812.5 and 1625.0 kHz. + * LR1121 : Allowed values are 62.5, 125.0, 250.0 and 500.0 kHz. + * * * */ + if (radio.setBandwidth(CONFIG_RADIO_BW) == RADIOLIB_ERR_INVALID_BANDWIDTH) { + Serial.println(F("Selected bandwidth is invalid for this module!")); + while (true); + } + + + /* + * Sets LoRa link spreading factor. + * SX1278/SX1276 : Allowed values range from 6 to 12. Only available in LoRa mode. + * SX1262 : Allowed values range from 5 to 12. + * SX1280 : Allowed values range from 5 to 12. + * LR1121 : Allowed values range from 5 to 12. + * * * */ + if (radio.setSpreadingFactor(10) == RADIOLIB_ERR_INVALID_SPREADING_FACTOR) { + Serial.println(F("Selected spreading factor is invalid for this module!")); + while (true); + } + + /* + * Sets LoRa coding rate denominator. + * SX1278/SX1276/SX1268/SX1262 : Allowed values range from 5 to 8. Only available in LoRa mode. + * SX1280 : Allowed values range from 5 to 8. + * LR1121 : Allowed values range from 5 to 8. + * * * */ + if (radio.setCodingRate(6) == RADIOLIB_ERR_INVALID_CODING_RATE) { + Serial.println(F("Selected coding rate is invalid for this module!")); + while (true); + } + + /* + * Sets LoRa sync word. + * SX1278/SX1276/SX1268/SX1262/SX1280 : Sets LoRa sync word. Only available in LoRa mode. + * * */ + if (radio.setSyncWord(0xAB) != RADIOLIB_ERR_NONE) { + Serial.println(F("Unable to set sync word!")); + while (true); + } + + /* + * Sets transmission output power. + * SX1278/SX1276 : Allowed values range from -3 to 15 dBm (RFO pin) or +2 to +17 dBm (PA_BOOST pin). High power +20 dBm operation is also supported, on the PA_BOOST pin. Defaults to PA_BOOST. + * SX1262 : Allowed values are in range from -9 to 22 dBm. This method is virtual to allow override from the SX1261 class. + * SX1268 : Allowed values are in range from -9 to 22 dBm. + * SX1280 : Allowed values are in range from -18 to 13 dBm. PA Version range : -18 ~ 3dBm + * LR1121 : Allowed values are in range from -17 to 22 dBm (high-power PA) or -18 to 13 dBm (High-frequency PA) + * * * */ + if (radio.setOutputPower(CONFIG_RADIO_OUTPUT_POWER) == RADIOLIB_ERR_INVALID_OUTPUT_POWER) { + Serial.println(F("Selected output power is invalid for this module!")); + while (true); + } + +#if !defined(USING_SX1280) && !defined(USING_LR1121) && !defined(USING_SX1280PA) + /* + * Sets current limit for over current protection at transmitter amplifier. + * SX1278/SX1276 : Allowed values range from 45 to 120 mA in 5 mA steps and 120 to 240 mA in 10 mA steps. + * SX1262/SX1268 : Allowed values range from 45 to 120 mA in 2.5 mA steps and 120 to 240 mA in 10 mA steps. + * NOTE: set value to 0 to disable overcurrent protection + * * * */ + if (radio.setCurrentLimit(140) == RADIOLIB_ERR_INVALID_CURRENT_LIMIT) { + Serial.println(F("Selected current limit is invalid for this module!")); + while (true); + } +#endif + + /* + * Sets preamble length for LoRa or FSK modem. + * SX1278/SX1276 : Allowed values range from 6 to 65535 in %LoRa mode or 0 to 65535 in FSK mode. + * SX1262/SX1268 : Allowed values range from 1 to 65535. + * SX1280 : Allowed values range from 1 to 65535. + * LR1121 : Allowed values range from 1 to 65535. + * * */ + if (radio.setPreambleLength(15) == RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH) { + Serial.println(F("Selected preamble length is invalid for this module!")); + while (true); + } + + // Enables or disables CRC check of received packets. + if (radio.setCRC(false) == RADIOLIB_ERR_INVALID_CRC_CONFIGURATION) { + Serial.println(F("Selected CRC is invalid for this module!")); + while (true); + } + + +#if defined(USING_LR1121) + // LR1121 + // set RF switch configuration for Wio WM1110 + // Wio WM1110 uses DIO5 and DIO6 for RF switching + static const uint32_t rfswitch_dio_pins[] = { + RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, + RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC + }; + + static const Module::RfSwitchMode_t rfswitch_table[] = { + // mode DIO5 DIO6 + { LR11x0::MODE_STBY, { LOW, LOW } }, + { LR11x0::MODE_RX, { HIGH, LOW } }, + { LR11x0::MODE_TX, { LOW, HIGH } }, + { LR11x0::MODE_TX_HP, { LOW, HIGH } }, + { LR11x0::MODE_TX_HF, { LOW, LOW } }, + { LR11x0::MODE_GNSS, { LOW, LOW } }, + { LR11x0::MODE_WIFI, { LOW, LOW } }, + END_OF_MODE_TABLE, + }; + radio.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table); + + // LR1121 TCXO Voltage 2.85~3.15V + radio.setTCXO(3.0); + +#endif + + // set the function that will be called + // when new packet is received + radio.setPacketReceivedAction(setFlag); + + // start listening for LoRa packets + Serial.print(F("[Radio] Starting to listen ... ")); + state = radio.startReceive(); + if (state != RADIOLIB_ERR_NONE) { + Serial.println(F("[Radio] Received packet failed!")); + } +} + +void loop() +{ + button.check(); + ui.update(); + delay(2); +} + + + + +void radioTx(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +{ + display->setTextAlignment(TEXT_ALIGN_LEFT); + if (millis() - radioRunInterval > 1000) { + + if (transmittedFlag) { + // reset flag + transmittedFlag = false; + if (transmissionState == RADIOLIB_ERR_NONE) { + // packet was successfully sent + Serial.println(F("transmission finished!")); + + // NOTE: when using interrupt-driven transmit method, + // it is not possible to automatically measure + // transmission data rate using getDataRate() + + } else { + Serial.print(F("failed, code ")); + Serial.println(transmissionState); + + } + + // clean up after transmission is finished + // this will ensure transmitter is disabled, + // RF switch is powered down etc. + radio.finishTransmit(); + + // send another one + Serial.print(F("[Radio] Sending another packet ... ")); + + // you can transmit C-string or Arduino string up to + // 256 characters long + // transmissionState = radio.startTransmit("Hello World!"); + radio.transmit((uint8_t *)&transmissionCounter, 4); + transmissionCounter++; + + // you can also transmit byte array up to 256 bytes long + /* + byte byteArr[] = {0x01, 0x23, 0x45, 0x67, + 0x89, 0xAB, 0xCD, 0xEF}; + int state = radio.startTransmit(byteArr, 8); + */ + digitalWrite(BOARD_LED, 1 - digitalRead(BOARD_LED)); + } + + Serial.println("Radio TX done !"); + radioRunInterval = millis(); + + } + + display->drawString(0 + x, 0 + y, "Radio Tx"); + display->drawString(0 + x, 12 + y, "TX :" + String(transmissionCounter)); +} + + +void radioRx(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +{ + display->setFont(ArialMT_Plain_10); + // The coordinates define the left starting point of the text + display->setTextAlignment(TEXT_ALIGN_LEFT); + + // check if the flag is set + if (transmittedFlag) { + Serial.println("Radio RX done !"); + + digitalWrite(BOARD_LED, 1 - digitalRead(BOARD_LED)); + + // reset flag + transmittedFlag = false; + + // you can read received data as an Arduino String + int state = radio.readData((uint8_t *)&recvCounter, 4); + + // you can also read received data as byte array + /* + byte byteArr[8]; + int state = radio.readData(byteArr, 8); + */ + + if (state == RADIOLIB_ERR_NONE) { + // packet was successfully received + Serial.println(F("[Radio] Received packet!")); + radioRSSI = radio.getRSSI(); + + } else if (state == RADIOLIB_ERR_CRC_MISMATCH) { + // packet was received, but is malformed + Serial.println(F("[Radio] CRC error!")); + + } else { + // some other error occurred + Serial.print(F("[Radio] Failed, code ")); + Serial.println(state); + } + + // put module back to listen mode + radio.startReceive(); + + } + + display->drawString(0 + x, 0 + y, "Radio Rx"); + display->drawString(0 + x, 22 + y, "RX :" + String(recvCounter)); + display->drawString(0 + x, 10 + y, "RSSI:" + String(radioRSSI)); + + +} + +void hwInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +{ + static char buffer[64]; +#ifdef ADC_PIN + if (millis() - batteryRunInterval > 1000) { + analogReadResolution(12); + float voltage = (analogReadMilliVolts(ADC_PIN) * 2) / 1000.0; + sprintf(buffer, "%.2fV", voltage > 4.2 ? 4.2 : voltage); + batteryRunInterval = millis(); + } +#endif + + display->setFont(ArialMT_Plain_10); + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->drawString(0 + x, 10 + y, "Radio "); + display->drawString(50 + x, 10 + y, isRadioOnline & 1 ? "+" : "NA"); + display->drawString(0 + x, 20 + y, "SD "); + display->drawString(50 + x, 20 + y, SD.cardSize() != 0 ? "+" : "NA"); + display->drawString(0 + x, 30 + y, "BAT "); + display->drawString(50 + x, 30 + y, buffer); +} + + + + diff --git a/examples/TBeamFactory/sleep_current.jpg b/examples/TBeamFactory/sleep_current.jpg new file mode 100644 index 0000000..321e05d Binary files /dev/null and b/examples/TBeamFactory/sleep_current.jpg differ diff --git a/examples/TBeamFactory/utilities.h b/examples/TBeamFactory/utilities.h new file mode 100644 index 0000000..151bb1f --- /dev/null +++ b/examples/TBeamFactory/utilities.h @@ -0,0 +1,596 @@ +/** + * @file utilities.h + * @author Lewis He (lewishe@outlook.com) + * @license MIT + * @copyright Copyright (c) 2024 ShenZhen XinYuan Electronic Technology Co., Ltd + * @date 2024-05-12 + * @last-update 2024-08-07 + */ +#pragma once + + +// Support board list , Macro definition below, select the board definition to be used + +// #define T3_V1_3_SX1276 +// #define T3_V1_3_SX1278 + +// #define T3_V1_6_SX1276 +// #define T3_V1_6_SX1278 + +// #define T3_V1_6_SX1276_TCXO +// #define T3_V3_0_SX1276_TCXO + +// #define T_BEAM_SX1262 +// #define T_BEAM_SX1276 +// #define T_BEAM_SX1278 + +// #define T_BEAM_S3_SUPREME + +// #define T3_S3_V1_2_SX1262 +// #define T3_S3_V1_2_SX1276 +// #define T3_S3_V1_2_SX1278 +// #define T3_S3_V1_2_SX1280 +// #define T3_S3_V1_2_SX1280_PA +// #define T3_S3_V1_2_LR1121 + +// #define T_MOTION + +// #define T3_C6 + +// #define T_BEAM_S3_BPF + + +#define UNUSED_PIN (0) + +#if defined(T_BEAM_SX1262) || defined(T_BEAM_SX1276) || defined(T_BEAM_SX1278) + + +#if defined(T_BEAM_SX1262) +#ifndef USING_SX1262 +#define USING_SX1262 +#endif +#elif defined(T_BEAM_SX1276) +#ifndef USING_SX1276 +#define USING_SX1276 +#endif +#elif defined(T_BEAM_SX1278) +#ifndef USING_SX1278 +#define USING_SX1278 +#endif +#endif // T_BEAM_SX1262 + + +#define GPS_RX_PIN 34 +#define GPS_TX_PIN 12 +#define BUTTON_PIN 38 +#define BUTTON_PIN_MASK GPIO_SEL_38 +#define I2C_SDA 21 +#define I2C_SCL 22 +#define PMU_IRQ 35 + +#define RADIO_SCLK_PIN 5 +#define RADIO_MISO_PIN 19 +#define RADIO_MOSI_PIN 27 +#define RADIO_CS_PIN 18 +#define RADIO_DIO0_PIN 26 +#define RADIO_RST_PIN 23 +#define RADIO_DIO1_PIN 33 +// SX1276/78 +#define RADIO_DIO2_PIN 32 +// SX1262 +#define RADIO_BUSY_PIN 32 + + +#define BOARD_LED 4 +#define LED_ON LOW +#define LED_OFF HIGH + +#define BUTTON_PIN 38 + +#define GPS_BAUD_RATE 9600 +#define HAS_GPS +#define HAS_DISPLAY //Optional, bring your own board, no OLED !! +#define HAS_PMU + +#define BOARD_VARIANT_NAME "T-Beam" + +#elif defined(T3_V1_3_SX1276) || defined(T3_V1_3_SX1278) + + +#if defined(T3_V1_3_SX1276) + +#ifndef USING_SX1276 +#define USING_SX1276 +#endif + +#elif defined(T3_V1_3_SX1278) + +#ifndef USING_SX1278 +#define USING_SX1278 +#endif + +#endif // T3_V1_3_SX1276 + + + +#define I2C_SDA 21 +#define I2C_SCL 22 +#define OLED_RST UNUSED_PIN + +#define RADIO_SCLK_PIN 5 +#define RADIO_MISO_PIN 19 +#define RADIO_MOSI_PIN 27 +#define RADIO_CS_PIN 18 +#define RADIO_DIO0_PIN 26 +#define RADIO_RST_PIN 14 +#define RADIO_DIO1_PIN 33 + +// SX1276/78 +#define RADIO_DIO2_PIN 32 +// SX1262 +#define RADIO_BUSY_PIN 32 + + +#define ADC_PIN 35 +#define HAS_DISPLAY +#define BOARD_VARIANT_NAME "T3 V1.3" + +#elif defined(T3_V1_6_SX1276) || defined(T3_V1_6_SX1278) + + +#if defined(T3_V1_6_SX1276) +#ifndef USING_SX1276 +#define USING_SX1276 +#endif +#elif defined(T3_V1_6_SX1278) +#ifndef USING_SX1278 +#define USING_SX1278 +#endif +#endif // T3_V1_6_SX1276 + +#define I2C_SDA 21 +#define I2C_SCL 22 +#define OLED_RST UNUSED_PIN + +#define RADIO_SCLK_PIN 5 +#define RADIO_MISO_PIN 19 +#define RADIO_MOSI_PIN 27 +#define RADIO_CS_PIN 18 +#define RADIO_DIO0_PIN 26 +#define RADIO_RST_PIN 23 +#define RADIO_DIO1_PIN 33 +// SX1276/78 +#define RADIO_DIO2_PIN 32 +// SX1262 +#define RADIO_BUSY_PIN 32 + +#define SDCARD_MOSI 15 +#define SDCARD_MISO 2 +#define SDCARD_SCLK 14 +#define SDCARD_CS 13 + +#define BOARD_LED 25 +#define LED_ON HIGH + +#define ADC_PIN 35 + +#define HAS_SDCARD +#define HAS_DISPLAY + +#define BOARD_VARIANT_NAME "T3 V1.6" + + +#elif defined(T3_V1_6_SX1276_TCXO) + +#ifndef USING_SX1276 +#define USING_SX1276 +#endif + +#define I2C_SDA 21 +#define I2C_SCL 22 +#define OLED_RST UNUSED_PIN + +#define RADIO_SCLK_PIN 5 +#define RADIO_MISO_PIN 19 +#define RADIO_MOSI_PIN 27 +#define RADIO_CS_PIN 18 +#define RADIO_DIO0_PIN 26 +#define RADIO_RST_PIN 23 +#define RADIO_DIO1_PIN -1//33 +/* +* In the T3 V1.6.1 TCXO version, Radio DIO1 is connected to Radio’s +* internal temperature-compensated crystal oscillator enable +* */ +// TCXO pin must be set to HIGH before enabling Radio +#define RADIO_TCXO_ENABLE 33 +#define RADIO_BUSY_PIN 32 + +#define SDCARD_MOSI 15 +#define SDCARD_MISO 2 +#define SDCARD_SCLK 14 +#define SDCARD_CS 13 + +#define BOARD_LED 25 +#define LED_ON HIGH + +#define ADC_PIN 35 + +#define HAS_SDCARD +#define HAS_DISPLAY + +#define BOARD_VARIANT_NAME "T3 V1.6 TCXO" + + + +#elif defined(T3_V3_0) + + +#define I2C_SDA 21 +#define I2C_SCL 22 +#define OLED_RST 4 + +#define RADIO_SCLK_PIN 5 +#define RADIO_MISO_PIN 19 +#define RADIO_MOSI_PIN 27 +#define RADIO_CS_PIN 18 +#define RADIO_RST_PIN 23 + +// TCXO pin must be set to HIGH before enabling Radio +#define RADIO_TCXO_ENABLE 12 //only sx1276 tcxo version +#define RADIO_BUSY_PIN 32 + + +#if defined(USING_SX1262) + +#define RADIO_DIO1_PIN 26 +#define RADIO_BUSY_PIN 32 + +#elif defined(USING_SX1276) || defined(USING_SX1278) +//!SX1276/78 module only + +#define RADIO_DIO0_PIN 26 +#define RADIO_DIO1_PIN 32 + +#elif defined(USING_LR1121) + +#define RADIO_DIO9_PIN 26 //LR1121 DIO9 +#define RADIO_BUSY_PIN 32 //LR1121 BUSY + +#endif + +#define SDCARD_MOSI 15 +#define SDCARD_MISO 2 +#define SDCARD_SCLK 14 +#define SDCARD_CS 13 + +#define BOARD_LED 25 +#define LED_ON HIGH + +#define ADC_PIN 35 + +#define HAS_SDCARD +#define HAS_DISPLAY + +#define BOARD_VARIANT_NAME "T3 V3.0" + +#define BUTTON_PIN 0 +#define ADC_PIN 35 + + +#elif defined(T3_S3_V1_2_SX1262) || defined(ARDUINO_LILYGO_T3S3_SX1262) || \ + defined(T3_S3_V1_2_SX1276) || defined(ARDUINO_LILYGO_T3S3_SX1276) || \ + defined(T3_S3_V1_2_SX1278) || defined(ARDUINO_LILYGO_T3S3_SX1278) || \ + defined(T3_S3_V1_2_SX1280) || defined(ARDUINO_LILYGO_T3S3_SX1280) || \ + defined(T3_S3_V1_2_SX1280_PA) || defined(ARDUINO_LILYGO_T3S3_SX1280PA) || \ + defined(T3_S3_V1_2_LR1121) || defined(ARDUINO_LILYGO_T3S3_LR1121) + + +#if defined(T3_S3_V1_2_SX1262) || defined(ARDUINO_LILYGO_T3S3_SX1262) +#ifndef USING_SX1262 +#define USING_SX1262 +#endif +#elif defined(T3_S3_V1_2_SX1276) || defined(ARDUINO_LILYGO_T3S3_SX1276) +#ifndef USING_SX1276 +#define USING_SX1276 +#endif +#elif defined(T3_S3_V1_2_SX1278) || defined(ARDUINO_LILYGO_T3S3_SX1278) +#ifndef USING_SX1278 +#define USING_SX1278 +#endif +#elif defined(T3_S3_V1_2_SX1280) || defined(ARDUINO_LILYGO_T3S3_SX1280) +#ifndef USING_SX1280 +#define USING_SX1280 +#endif +#elif defined(T3_S3_V1_2_SX1280_PA) || defined(ARDUINO_LILYGO_T3S3_SX1280PA) +#ifndef USING_SX1280PA +#define USING_SX1280PA +#endif +#elif defined(T3_S3_V1_2_LR1121) || defined(ARDUINO_LILYGO_T3S3_LR1121) +#ifndef USING_LR1121 +#define USING_LR1121 +#endif + +#endif // T3_S3_V1_2_SX1262 + + +#define I2C_SDA 18 +#define I2C_SCL 17 +#define OLED_RST UNUSED_PIN + +#define RADIO_SCLK_PIN 5 +#define RADIO_MISO_PIN 3 +#define RADIO_MOSI_PIN 6 +#define RADIO_CS_PIN 7 + +#define SDCARD_MOSI 11 +#define SDCARD_MISO 2 +#define SDCARD_SCLK 14 +#define SDCARD_CS 13 + +#define BOARD_LED 37 +#define LED_ON HIGH + +#define BUTTON_PIN 0 +#define ADC_PIN 1 + +#define RADIO_RST_PIN 8 + +#if defined(USING_SX1262) + +#define RADIO_DIO1_PIN 33 +#define RADIO_BUSY_PIN 34 + +#elif defined(USING_SX1276) || defined(USING_SX1278) +//!SX1276/78 module only +#define RADIO_BUSY_PIN 33 //DIO1 + +#define RADIO_DIO0_PIN 9 +#define RADIO_DIO1_PIN 33 +#define RADIO_DIO2_PIN 34 +#define RADIO_DIO3_PIN 21 +#define RADIO_DIO4_PIN 10 +#define RADIO_DIO5_PIN 36 + +#elif defined(USING_SX1280) + +#define RADIO_DIO1_PIN 9 //SX1280 DIO1 = IO9 +#define RADIO_BUSY_PIN 36 //SX1280 BUSY = IO36 + +#elif defined(USING_SX1280PA) + +#define RADIO_DIO1_PIN 9 //SX1280 DIO1 = IO9 +#define RADIO_BUSY_PIN 36 //SX1280 BUSY = IO36 +#define RADIO_RX_PIN 21 +#define RADIO_TX_PIN 10 + + +#elif defined(USING_LR1121) + +#define RADIO_DIO9_PIN 36 //LR1121 DIO9 = IO36 +#define RADIO_BUSY_PIN 34 //LR1121 BUSY = IO34 + +#endif + +#define BUTTON_PIN 0 + +#define HAS_SDCARD +#define HAS_DISPLAY + +#define BOARD_VARIANT_NAME "T3 S3 V1.X" + + +#elif defined(T_BEAM_S3_SUPREME) + + +#ifndef USING_SX1262 +#define USING_SX1262 +#endif + + +#define I2C_SDA 17 +#define I2C_SCL 18 + +#define I2C1_SDA 42 +#define I2C1_SCL 41 +#define PMU_IRQ 40 + +#define GPS_RX_PIN 9 +#define GPS_TX_PIN 8 +#define GPS_WAKEUP_PIN 7 +#define GPS_PPS_PIN 6 + +#define BUTTON_PIN 0 +#define BUTTON_PIN_MASK GPIO_SEL_0 +#define BUTTON_CONUT (1) +#define BUTTON_ARRAY {BUTTON_PIN} + +#define RADIO_SCLK_PIN (12) +#define RADIO_MISO_PIN (13) +#define RADIO_MOSI_PIN (11) +#define RADIO_CS_PIN (10) +#define RADIO_DIO0_PIN (-1) +#define RADIO_RST_PIN (5) +#define RADIO_DIO1_PIN (1) +#define RADIO_BUSY_PIN (4) + +#define SPI_MOSI (35) +#define SPI_SCK (36) +#define SPI_MISO (37) +#define SPI_CS (47) +#define IMU_CS (34) +#define IMU_INT (33) + +#define SDCARD_MOSI SPI_MOSI +#define SDCARD_MISO SPI_MISO +#define SDCARD_SCLK SPI_SCK +#define SDCARD_CS SPI_CS + +#define PIN_NONE (-1) +#define RTC_INT (14) +#define BUTTON_PIN 0 + +#define GPS_BAUD_RATE 9600 + +#define HAS_SDCARD +#define HAS_GPS +#define HAS_DISPLAY +#define HAS_PMU + +#define __HAS_SPI1__ +#define __HAS_SENSOR__ + +#define PMU_WIRE_PORT Wire1 +#define DISPLAY_MODEL U8G2_SH1106_128X64_NONAME_F_HW_I2C +#define BOARD_VARIANT_NAME "T-Beam S3" + +#elif defined(T_MOTION_S76G) + +#ifndef USING_SX1276 +#define USING_SX1276 +#endif + + +#define RADIO_SCLK_PIN PB13 +#define RADIO_MISO_PIN PB14 +#define RADIO_MOSI_PIN PB15 +#define RADIO_CS_PIN PB12 +#define RADIO_RST_PIN PB10 + +#define RADIO_DIO0_PIN PB11 +#define RADIO_DIO1_PIN PC13 +#define RADIO_DIO2_PIN PB9 +#define RADIO_DIO3_PIN PB4 +#define RADIO_DIO4_PIN PB3 +#define RADIO_DIO5_PIN PA15 + +#undef RADIO_BUSY_PIN +#undef RADIO_DIO1_PIN +#define RADIO_BUSY_PIN PC13 //DIO1 +#define RADIO_DIO1_PIN PB11 //DIO0 + +#define RADIO_SWITCH_PIN PA1 //1:Rx, 0:Tx + +#define GPS_EN_PIN PC6 +#define GPS_RST_PIN PB2 +#define GPS_RX_PIN PC11 +#define GPS_TX_PIN PC10 +#define GPS_ENABLE_PIN PC6 +#define GPS_BAUD_RATE 115200 +#define GPS_PPS_PIN PB5 + +#define UART_RX_PIN PA10 +#define UART_TX_PIN PA9 + +#define I2C_SCL PB6 +#define I2C_SDA PB7 + +#define BOARD_VARIANT_NAME "T-Motion S76G" + +#define HAS_GPS + +#elif defined(T3_C6) + + +#ifndef USING_SX1262 +#define USING_SX1262 +#endif + + +#define RADIO_SCLK_PIN 6 +#define RADIO_MISO_PIN 1 +#define RADIO_MOSI_PIN 0 +#define RADIO_CS_PIN 18 +#define RADIO_DIO1_PIN 23 +#define RADIO_BUSY_PIN 22 +#define RADIO_RST_PIN 21 + +#define I2C_SDA 8 +#define I2C_SCL 9 + +#define BOARD_LED 7 +#define LED_ON HIGH +#define RADIO_RX_PIN 15 +#define RADIO_TX_PIN 14 + + +#define BOARD_VARIANT_NAME "T3-C6" + +#define USING_DIO2_AS_RF_SWITCH + + +#elif defined(T_BEAM_S3_BPF) + + +#ifndef USING_SX1278 +#define USING_SX1278 +#endif + +#define I2C_SDA 8 +#define I2C_SCL 9 + +#define PMU_IRQ 4 + +#define GPS_RX_PIN 5 +#define GPS_TX_PIN 6 +#define GPS_PPS_PIN 7 + +#define BUTTON_PIN 0 +#define BUTTON_PIN_MASK GPIO_SEL_0 +#define BUTTON_CONUT (2) +#define BUTTON_ARRAY {BUTTON_PIN,3} + +#define RADIO_SCLK_PIN (41) +#define RADIO_MISO_PIN (42) +#define RADIO_MOSI_PIN (2) +#define RADIO_CS_PIN (1) +#define RADIO_RST_PIN (18) + +#define RADIO_DIO0_PIN (14) +#define RADIO_DIO1_PIN (21) +#define RADIO_DIO2_PIN (15) + +#define RADIO_TCXO_ENABLE (17) +#define RADIO_LDO_EN (16) +#define RADIO_BUSY_PIN (RADIO_DIO1_PIN) + +#define SPI_MOSI (11) +#define SPI_SCK (12) +#define SPI_MISO (13) +#define SPI_CS (10) + +#define SDCARD_MOSI SPI_MOSI +#define SDCARD_MISO SPI_MISO +#define SDCARD_SCLK SPI_SCK +#define SDCARD_CS SPI_CS + +#define PIN_NONE (-1) + +#define GPS_BAUD_RATE 9600 + +#define HAS_SDCARD +#define HAS_GPS +#define HAS_DISPLAY +#define HAS_PMU + +#define __HAS_SPI1__ +#define __HAS_SENSOR__ + +#define PMU_WIRE_PORT Wire +#define DISPLAY_MODEL U8G2_SH1106_128X64_NONAME_F_HW_I2C +#define BOARD_VARIANT_NAME "T-Beam BPF" + + + + +#else +#error "When using it for the first time, please define the board model in " +#endif + + + + + + + + +