diff --git a/software/firmware/source/SoftRF/src/driver/EPD.cpp b/software/firmware/source/SoftRF/src/driver/EPD.cpp index c522c6eef..3f3901ca6 100644 --- a/software/firmware/source/SoftRF/src/driver/EPD.cpp +++ b/software/firmware/source/SoftRF/src/driver/EPD.cpp @@ -93,7 +93,8 @@ bool EPD_setup(bool splash_screen) display->fillScreen(GxEPD_WHITE); - if (hw_info.model == SOFTRF_MODEL_BADGE) { + if (hw_info.model == SOFTRF_MODEL_BADGE || + hw_info.model == SOFTRF_MODEL_INK) { x = (display->width() - tbw1) / 2; y = (display->height() + tbh1) / 2 - tbh3; diff --git a/software/firmware/source/SoftRF/src/driver/LED.h b/software/firmware/source/SoftRF/src/driver/LED.h index a231f3b78..be503bf74 100644 --- a/software/firmware/source/SoftRF/src/driver/LED.h +++ b/software/firmware/source/SoftRF/src/driver/LED.h @@ -72,6 +72,7 @@ enum DISPLAY_TFT_PORTAPACK, DISPLAY_EPD_2_7, DISPLAY_EPD_1_54, + DISPLAY_EPD_2_13, }; void LED_setup(); diff --git a/software/firmware/source/SoftRF/src/driver/OLED.cpp b/software/firmware/source/SoftRF/src/driver/OLED.cpp index 65fee7298..470d29444 100644 --- a/software/firmware/source/SoftRF/src/driver/OLED.cpp +++ b/software/firmware/source/SoftRF/src/driver/OLED.cpp @@ -426,7 +426,7 @@ static void OLED_other() static int OLED_current = 1; -const char *Aircraft_Type[] = { +const char *OLED_Aircraft_Type[] = { [AIRCRAFT_TYPE_UNKNOWN] = "Unknown ", [AIRCRAFT_TYPE_GLIDER] = " Glider ", [AIRCRAFT_TYPE_TOWPLANE] = "Towplane", @@ -596,7 +596,7 @@ static void OLED_text() uint8_t acft_type = traffic_by_dist[OLED_current - 1].fop->aircraft_type; acft_type = acft_type > AIRCRAFT_TYPE_STATIC ? AIRCRAFT_TYPE_UNKNOWN : acft_type; if (acft_type != prev_type) { - strncpy(acft_id_text, Aircraft_Type[acft_type], sizeof(acft_id_text)); + strncpy(acft_id_text, OLED_Aircraft_Type[acft_type], sizeof(acft_id_text)); u8x8->draw2x2String(0, 6, acft_id_text); prev_type = acft_type; } diff --git a/software/firmware/source/SoftRF/src/driver/OLED.h b/software/firmware/source/SoftRF/src/driver/OLED.h index 465f55c88..b4e389267 100644 --- a/software/firmware/source/SoftRF/src/driver/OLED.h +++ b/software/firmware/source/SoftRF/src/driver/OLED.h @@ -19,7 +19,9 @@ #ifndef OLEDHELPER_H #define OLEDHELPER_H +#if defined(USE_OLED) #include +#endif /* USE_OLED */ #define SSD1306_OLED_I2C_ADDR 0x3C #define SH1106_OLED_I2C_ADDR 0x3C @@ -36,7 +38,10 @@ void OLED_info3(int, char *, char *, char *); void OLED_Next_Page(void); void OLED_Up(void); +#if defined(USE_OLED) extern U8X8 *u8x8; +#endif /* USE_OLED */ + extern uint8_t OLED_flip; extern bool OLED_display_titles; extern bool OLED_busy; diff --git a/software/firmware/source/SoftRF/src/platform/ESP32.cpp b/software/firmware/source/SoftRF/src/platform/ESP32.cpp index 5bd4edfb9..2bc5827ba 100644 --- a/software/firmware/source/SoftRF/src/platform/ESP32.cpp +++ b/software/firmware/source/SoftRF/src/platform/ESP32.cpp @@ -137,6 +137,24 @@ void TFT_backlight_on() } #endif /* USE_TFT */ +#if defined(USE_EPAPER) +#include "../driver/EPD.h" + +GxEPD2_BW epd_bn (GxEPD2_213_BN( + SOC_GPIO_PIN_T3S3_EPD_SS, + SOC_GPIO_PIN_T3S3_EPD_DC, + SOC_GPIO_PIN_T3S3_EPD_RST, + SOC_GPIO_PIN_T3S3_EPD_BUSY)); +GxEPD2_GFX *display; + +const char *Hardware_Rev[] = { + [0] = "TBD", + [1] = "TBD", + [2] = "TBD", + [3] = "Unknown" +}; +#endif /* USE_EPAPER */ + AXP20X_Class axp_xxx; XPowersPMU axp_2xxx; @@ -1322,6 +1340,20 @@ static void ESP32_setup() #if defined(USE_RADIOLIB) lmic_pins.dio[0] = SOC_GPIO_PIN_T3S3_DIO1; #endif /* USE_RADIOLIB */ + + int uSD_SS_pin = SOC_GPIO_PIN_T3S3_SD_SS; + + /* uSD-SPI init */ + uSD_SPI.begin(SOC_GPIO_PIN_T3S3_SD_SCK, + SOC_GPIO_PIN_T3S3_SD_MISO, + SOC_GPIO_PIN_T3S3_SD_MOSI, + uSD_SS_pin); + + pinMode(uSD_SS_pin, OUTPUT); + digitalWrite(uSD_SS_pin, HIGH); + + uSD_is_attached = uSD.cardBegin(SD_CONFIG); + #endif /* CONFIG_IDF_TARGET_ESP32S3 */ #if defined(CONFIG_IDF_TARGET_ESP32C2) @@ -1906,6 +1938,68 @@ static void ESP32_post_init() break; #endif /* USE_OLED */ + +#if defined(USE_EPAPER) + case DISPLAY_EPD_1_54: + case DISPLAY_EPD_2_13: + if (hw_info.model == SOFTRF_MODEL_INK) { + + EPD_info1(); + + char key[8]; + char out[64]; + uint8_t tokens[3] = { 0 }; + cdbResult rt; + int c, i = 0, token_cnt = 0; + + int acfts; + char *reg, *mam, *cn; + reg = mam = cn = NULL; + + if (ADB_is_open) { + acfts = ucdb.recordsNumber(); + + snprintf(key, sizeof(key),"%06X", ThisAircraft.addr); + + rt = ucdb.findKey(key, strlen(key)); + + switch (rt) { + case KEY_FOUND: + while ((c = ucdb.readValue()) != -1 && i < (sizeof(out) - 1)) { + if (c == '|') { + if (token_cnt < (sizeof(tokens) - 1)) { + token_cnt++; + tokens[token_cnt] = i+1; + } + c = 0; + } + out[i++] = (char) c; + } + out[i] = 0; + + reg = out + tokens[1]; + mam = out + tokens[0]; + cn = out + tokens[2]; + + break; + + case KEY_NOT_FOUND: + default: + break; + } + + reg = (reg != NULL) && strlen(reg) ? reg : (char *) "REG: N/A"; + mam = (mam != NULL) && strlen(mam) ? mam : (char *) "M&M: N/A"; + cn = (cn != NULL) && strlen(cn) ? cn : (char *) "N/A"; + + } else { + acfts = -1; + } + + EPD_info2(acfts, reg, mam, cn); + } +#endif /* USE_EPAPER */ + break; case DISPLAY_NONE: default: break; @@ -3228,9 +3322,10 @@ static byte ESP32_Display_setup() { byte rval = DISPLAY_NONE; - if (esp32_board != ESP32_TTGO_T_WATCH && - esp32_board != ESP32_S2_T8_V1_1 && - esp32_board != ESP32_HELTEC_TRACKER) { + if (esp32_board != ESP32_TTGO_T_WATCH && + esp32_board != ESP32_S2_T8_V1_1 && + esp32_board != ESP32_HELTEC_TRACKER && + esp32_board != ESP32_LILYGO_T3S3_EPD) { #if defined(USE_OLED) bool has_oled = false; @@ -3375,6 +3470,27 @@ static byte ESP32_Display_setup() SoC->ADB_ops && SoC->ADB_ops->setup(); #endif /* USE_OLED */ + } else if (esp32_board == ESP32_LILYGO_T3S3_EPD) { +#if defined(USE_EPAPER) + display = &epd_bn; + display->epd2.selectSPI(uSD_SPI, SPISettings(4000000, MSBFIRST, SPI_MODE0)); + + if (EPD_setup(true)) { + +#if defined(USE_EPD_TASK) + Display_Semaphore = xSemaphoreCreateBinary(); + + if( Display_Semaphore != NULL ) { + xSemaphoreGive( Display_Semaphore ); + } + + xTaskCreate(EPD_Task, "EPD", EPD_STACK_SZ, NULL, /* TASK_PRIO_HIGH */ TASK_PRIO_LOW , &EPD_Task_Handle); + + TaskInfoTime = millis(); +#endif + rval = DISPLAY_EPD_1_54; + } +#endif /* USE_EPAPER */ } else { #if defined(USE_TFT) @@ -3784,6 +3900,13 @@ static void ESP32_Display_loop() break; #endif /* USE_OLED */ +#if defined(USE_EPAPER) + case DISPLAY_EPD_1_54: + case DISPLAY_EPD_2_13: + EPD_loop(); + break; +#endif /* USE_EPAPER */ + case DISPLAY_NONE: default: break; @@ -4296,6 +4419,11 @@ void handleMainEvent(AceButton* button, uint8_t eventType, OLED_Next_Page(); } #endif /* USE_OLED */ +#if defined(USE_EPAPER) + if (button == &button_1 && esp32_board == ESP32_LILYGO_T3S3_EPD) { + EPD_Mode(); + } +#endif /* USE_EPAPER */ #if defined(USE_SA8X8) if (button == &button_ptt && hw_info.rf == RF_IC_SA8X8 && @@ -4354,11 +4482,13 @@ static void ESP32_Button_setup() esp32_board == ESP32_S2_T8_V1_1 || esp32_board == ESP32_LILYGO_T_TWR2 || esp32_board == ESP32_HELTEC_TRACKER || + esp32_board == ESP32_LILYGO_T3S3_EPD || esp32_board == ESP32_S3_DEVKIT) { - button_pin = esp32_board == ESP32_S2_T8_V1_1 ? SOC_GPIO_PIN_T8_S2_BUTTON : - esp32_board == ESP32_S3_DEVKIT ? SOC_GPIO_PIN_S3_BUTTON : - esp32_board == ESP32_HELTEC_TRACKER ? SOC_GPIO_PIN_S3_BUTTON : - esp32_board == ESP32_LILYGO_T_TWR2 ? + button_pin = esp32_board == ESP32_S2_T8_V1_1 ? SOC_GPIO_PIN_T8_S2_BUTTON : + esp32_board == ESP32_S3_DEVKIT ? SOC_GPIO_PIN_S3_BUTTON : + esp32_board == ESP32_HELTEC_TRACKER ? SOC_GPIO_PIN_S3_BUTTON : + esp32_board == ESP32_LILYGO_T3S3_EPD ? SOC_GPIO_PIN_S3_BUTTON : + esp32_board == ESP32_LILYGO_T_TWR2 ? SOC_GPIO_PIN_TWR2_ENC_BUTTON : SOC_GPIO_PIN_TBEAM_V05_BUTTON; // Button(s) uses external pull up resistor. @@ -4417,6 +4547,7 @@ static void ESP32_Button_loop() esp32_board == ESP32_S2_T8_V1_1 || esp32_board == ESP32_LILYGO_T_TWR2 || esp32_board == ESP32_HELTEC_TRACKER || + esp32_board == ESP32_LILYGO_T3S3_EPD || esp32_board == ESP32_S3_DEVKIT) { button_1.check(); #if defined(USE_SA8X8) @@ -4432,6 +4563,7 @@ static void ESP32_Button_fini() if (esp32_board == ESP32_S2_T8_V1_1 || esp32_board == ESP32_LILYGO_T_TWR2 || esp32_board == ESP32_HELTEC_TRACKER || + esp32_board == ESP32_LILYGO_T3S3_EPD || esp32_board == ESP32_S3_DEVKIT) { int button_pin = esp32_board == ESP32_S2_T8_V1_1 ? SOC_GPIO_PIN_T8_S2_BUTTON : esp32_board == ESP32_LILYGO_T_TWR2 ? diff --git a/software/firmware/source/SoftRF/src/platform/ESP32.h b/software/firmware/source/SoftRF/src/platform/ESP32.h index 02def2bf5..00bba7013 100644 --- a/software/firmware/source/SoftRF/src/platform/ESP32.h +++ b/software/firmware/source/SoftRF/src/platform/ESP32.h @@ -279,6 +279,13 @@ enum esp32_board_id { ESP32_LILYGO_T3S3_EPD, }; +enum ep_model_id { + EP_UNKNOWN, + EP_GDEW027W3, + EP_GDEY027T91, + EP_DEPG0213BN, +}; + /* https://github.com/espressif/usb-pids/blob/main/allocated-pids.txt#L313 */ enum softrf_usb_pid { SOFTRF_USB_PID_WEBTOP = 0x8131, @@ -434,6 +441,7 @@ extern const USB_Device_List_t supported_USB_devices[]; /* Experimental */ #define ENABLE_REMOTE_ID //#define EXCLUDE_VOICE_MESSAGE +//#define USE_EPAPER #endif /* S3 */ #if defined(CONFIG_IDF_TARGET_ESP32S2) @@ -460,6 +468,12 @@ extern const USB_Device_List_t supported_USB_devices[]; #endif /* CONFIG_IDF_TARGET_ESP32S3 */ #endif /* USE_OLED */ +#if defined(USE_EPAPER) +typedef void EPD_Task_t; + +extern const char *Hardware_Rev[]; +#endif /* USE_EPAPER */ + #endif /* PLATFORM_ESP32_H */ #endif /* ESP32 */ diff --git a/software/firmware/source/SoftRF/src/ui/Text_EPD.cpp b/software/firmware/source/SoftRF/src/ui/Text_EPD.cpp index e65334162..562472528 100644 --- a/software/firmware/source/SoftRF/src/ui/Text_EPD.cpp +++ b/software/firmware/source/SoftRF/src/ui/Text_EPD.cpp @@ -36,7 +36,7 @@ #include -const char *Aircraft_Type[] = { +const char *EPD_Aircraft_Type[] = { [AIRCRAFT_TYPE_UNKNOWN] = "Unknown", [AIRCRAFT_TYPE_GLIDER] = "Glider", [AIRCRAFT_TYPE_TOWPLANE] = "Towplane", @@ -143,7 +143,7 @@ static void EPD_Draw_Text() if (ui->idpref == ID_TYPE) { uint8_t acft_type = traffic_by_dist[EPD_current - 1].fop->aircraft_type; acft_type = acft_type > AIRCRAFT_TYPE_STATIC ? AIRCRAFT_TYPE_UNKNOWN : acft_type; - strncpy(id_text, Aircraft_Type[acft_type], sizeof(id_text)); + strncpy(id_text, EPD_Aircraft_Type[acft_type], sizeof(id_text)); } else { uint32_t id = traffic_by_dist[EPD_current - 1].fop->addr; diff --git a/software/firmware/source/libraries/U8g2_for_Adafruit_GFX/src/u8g2_fonts.c b/software/firmware/source/libraries/U8g2_for_Adafruit_GFX/src/u8g2_fonts.c index cf56c49ec..bbfe46ad0 100644 --- a/software/firmware/source/libraries/U8g2_for_Adafruit_GFX/src/u8g2_fonts.c +++ b/software/firmware/source/libraries/U8g2_for_Adafruit_GFX/src/u8g2_fonts.c @@ -1,8 +1,12 @@ +#if defined(ESP32) +#include "sdkconfig.h" +#endif /* ESP32 */ + /* u8g2_fonts.c */ #include "u8g2_fonts.h" - +#if !defined(CONFIG_IDF_TARGET_ESP32S3) /* Fontname: u8glib_4 Copyright: public domain @@ -298,6 +302,8 @@ const uint8_t u8g2_font_emoticons21_tr[1156] U8G2_FONT_SECTION("u8g2_font_emotic "\220$\42\212\304\6\262L\36\220\312&r\331\244N<\30\344\0\70\5\0l\3\71\5\0l\3:\5" "\0l\3;\5\0l\3<\5\0l\3=\5\0l\3>\5\0l\3\77\5\0l\3\0\0\0\4" "\377\377\0"; +#endif /* CONFIG_IDF_TARGET_ESP32S3 */ + /* Fontname: battery19 Copyright: Created with Fony 1.4.7 @@ -311,6 +317,8 @@ const uint8_t u8g2_font_battery19_tn[167] U8G2_FONT_SECTION("u8g2_font_battery19 "\35\304\272P$\24\261\204\42\241\210%\24\11E,\241H(\342\203\0\65\37\70\317\42\35\304\22\212\204" "\42\226P$\24\261\204\42\241\210%\24\11E,\241H(\342\203\0\66\5\0\316\0\67\5\0\316\0\0" "\0\0\4\377\377\0"; + +#if !defined(CONFIG_IDF_TARGET_ESP32S3) /* Fontname: -FreeType-FreeDooM-Bold-R-Normal--34-340-72-72-P-170-ISO8859-1 Copyright: FreeUniveral (c) Stephen Wilson 2009 Original Font Sil-Sophia Copyright (c) SIL International, 1994-2008. @@ -343730,3 +343738,5 @@ const uint8_t u8g2_font_px437wyse700b_mn[330] U8G2_FONT_SECTION("u8g2_font_px437 "\357\36%\0\70\32\260\3\327\335\324\320\334\314\334\320\324\334\335\324\320\334\314\334\320\324\334=\62\0\71\26" "\260\3\327\335\324\320\334\314\334\320\330\330\301\364\306c\7\361\310\0:\16\260\3\77\302\351y<\231\236\307" "\24\0\0\0\0\4\377\377\0"; + +#endif /* CONFIG_IDF_TARGET_ESP32S3 */