diff --git a/.github/workflows/PR_All_envs.yml b/.github/workflows/PR_All_envs.yml index 7dd47e6a5..337256a29 100644 --- a/.github/workflows/PR_All_envs.yml +++ b/.github/workflows/PR_All_envs.yml @@ -26,6 +26,7 @@ jobs: - { env: "m5stack-core4mb", family: "ESP32",} - { env: "m5stack-cores3", family: "ESP32-S3",} - { env: "esp32-s3-devkitc-1", family: "ESP32-S3",} + - { env: "esp32-c5", family: "ESP32-C5",} - { env: "CYD-2432S028", family: "ESP32",} - { env: "CYD-2USB", family: "ESP32",} - { env: "CYD-2432W328C", family: "ESP32",} diff --git a/.github/workflows/PR_check.yml b/.github/workflows/PR_check.yml index 1626ac001..299af278e 100644 --- a/.github/workflows/PR_check.yml +++ b/.github/workflows/PR_check.yml @@ -47,6 +47,11 @@ jobs: env: "LAUNCHER_CYD-2432S028", partitions: { bootloader_addr: "0x1000" }, } + - { + name: "ESP32-C5", + env: "esp32-c5", + partitions: { bootloader_addr: "0x2000" }, + } steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/buil_parallel.yml b/.github/workflows/buil_parallel.yml index 159c528a8..736ae5ab2 100644 --- a/.github/workflows/buil_parallel.yml +++ b/.github/workflows/buil_parallel.yml @@ -26,6 +26,7 @@ jobs: - { env: "m5stack-core4mb", family: "ESP32",} - { env: "m5stack-cores3", family: "ESP32-S3",} - { env: "esp32-s3-devkitc-1", family: "ESP32-S3",} + - { env: "esp32-c5", family: "ESP32-C5",} - { env: "CYD-2432S028", family: "ESP32",} - { env: "CYD-2USB", family: "ESP32",} - { env: "CYD-2432W328C", family: "ESP32",} diff --git a/.vscode/settings.json b/.vscode/settings.json index 8f25f9f13..2be0b0503 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -70,7 +70,21 @@ "*.tpp": "cpp", "condition_variable": "cpp", "mutex": "cpp", - "thread": "cpp" + "thread": "cpp", + "bit": "cpp", + "charconv": "cpp", + "compare": "cpp", + "concepts": "cpp", + "netfwd": "cpp", + "source_location": "cpp", + "format": "cpp", + "numbers": "cpp", + "semaphore": "cpp", + "span": "cpp", + "stop_token": "cpp", + "text_encoding": "cpp", + "variant": "cpp", + "usb_serial_jtag.h": "c" }, "files.trimTrailingWhitespace": true, "files.insertFinalNewline": true, diff --git a/2.0_road_path.md b/2.0_road_path.md index 9c214607b..589171969 100644 --- a/2.0_road_path.md +++ b/2.0_road_path.md @@ -3,13 +3,12 @@ the objective of 2.0 is changing the Framework to Arduino-ESP32 v3.+, to be able to program to ESP32-C5 chips ## Downsides -- Incompatibility with WireGuard -- Remove OpenHeystack (hard to use and not that usefull) -- Remove DPWO (turn it into a Javascript thing) +- [x] Remove OpenHeystack (hard to use and not that usefull) +- [x] Remove DPWO (turn it into a Javascript thing) ## Enhancements -- Using newer version of C++ -- Availability to program to ESP32-C5 (5ghz wifi chip) +- [x] Using newer version of C++ +- [x] Availability to program to ESP32-C5 (5ghz wifi chip) ## Things to change on 2.0 - [] InputHadler common codes, defined within #defines structures, not programmin functions to each device @@ -20,7 +19,7 @@ the objective of 2.0 is changing the Framework to Arduino-ESP32 v3.+, to be able ## Things to add on 2.0 ### Wifi - - [] Wifi 5Ghz support + - [x] Wifi 5Ghz support ### BLE - [] Session hijacking diff --git a/README.md b/README.md index 12e74ab64..edd5a3962 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,6 @@ Also, [read our FAQ](https://github.com/pr3y/Bruce/wiki/FAQ) - [x] [RAW Sniffer](https://github.com/pr3y/Bruce/wiki/WiFi#raw-sniffer) - [x] [TCP Client](https://github.com/pr3y/Bruce/wiki/WiFi#tcp-client) - [x] [TCP Listener](https://github.com/pr3y/Bruce/wiki/WiFi#tcp-listener) -- [x] [DPWO-ESP32](https://github.com/pr3y/Bruce/wiki/WiFi#dpwo-esp32) - [x] [Evil Portal](https://github.com/pr3y/Bruce/wiki/WiFi#evil-portal) - [x] [Scan Hosts](https://github.com/pr3y/Bruce/wiki/WiFi#evil-portal) - [x] [Wireguard Tunneling](https://github.com/pr3y/Bruce/wiki/WiFi#wireguard-tunneling) @@ -174,7 +173,6 @@ Also, [read our FAQ](https://github.com/pr3y/Bruce/wiki/FAQ) - [x] Megalodon - [x] [BADUsb (New features, LittleFS and SDCard)](https://github.com/pr3y/Bruce/wiki/Others#badusb) - [x] USB Keyboard - Cardputer and T-Deck Only -- [x] [Openhaystack](https://github.com/pr3y/Bruce/wiki/Others#openhaystack) - [x] [iButton](https://github.com/pr3y/Bruce/wiki/Others#ibutton) - [x] [LED Control](https://github.com/pr3y/Bruce/wiki/Others#led-control) @@ -228,7 +226,7 @@ Also, [read our FAQ](https://github.com/pr3y/Bruce/wiki/FAQ) ² CYD have a LITE_VERSION version for Launcher Compatibility ¹ Core, CYD and StickCs Bad-USB: [here](https://github.com/pr3y/Bruce/wiki/Others#badusb) -*LITE_VERSION*: TelNet, SSH, DPWO, WireGuard, ScanHosts, RawSniffer, Brucegotchi, BLEBacon, BLEScan, Interpreter and OpenHaystack are NOT available for M5Launcher Compatibility +*LITE_VERSION*: TelNet, SSH, WireGuard, ScanHosts, RawSniffer, Brucegotchi, BLEBacon, BLEScan and Interpreter are NOT available for M5Launcher Compatibility ## :sparkles: Why and how does it look? diff --git a/boards/CYD-2432S028/CYD-2432S028.ini b/boards/CYD-2432S028/CYD-2432S028.ini index 3fb059661..c22815c7c 100644 --- a/boards/CYD-2432S028/CYD-2432S028.ini +++ b/boards/CYD-2432S028/CYD-2432S028.ini @@ -182,12 +182,12 @@ build_flags = [env:LAUNCHER_CYD-2USB] extends=env:CYD-2432S028 +board_build.partitions = custom_4Mb.csv build_flags = ${env:CYD-2432S028.build_flags} - -DCONFIG_ESP32_JTAG_SUPPORT_DISABLE=1 - -DTFT_INVERSION_ON - -DLITE_VERSION=1 - -DDEVICE_NAME='"LAUNCHER_CYD-2USB"' + ${env_light.build_flags} +lib_deps = + ${env_light.lib_deps} [env:CYD-2432W328C] extends = CYD_base @@ -204,11 +204,12 @@ build_flags = [env:LAUNCHER_CYD-2432S028] extends=env:CYD-2432S028 +board_build.partitions = custom_4Mb.csv build_flags = ${env:CYD-2432S028.build_flags} - -DCONFIG_ESP32_JTAG_SUPPORT_DISABLE=1 - -DLITE_VERSION=1 - -DDEVICE_NAME='"LAUNCHER_CYD-2432S028"' + ${env_light.build_flags} +lib_deps = + ${env_light.lib_deps} [env:CYD-2432W328C_2] # commom to CYD-2432S024 Capacitive board extends = env:CYD-2432W328C @@ -218,11 +219,12 @@ build_unflags = [env:LAUNCHER_CYD-2432W328C] extends=env:CYD-2432W328C +board_build.partitions = custom_4Mb.csv build_flags = ${env:CYD-2432W328C.build_flags} - -DCONFIG_ESP32_JTAG_SUPPORT_DISABLE=1 - -DLITE_VERSION=1 - -DDEVICE_NAME='"LAUNCHER_CYD-2432W328C"' + ${env_light.build_flags} +lib_deps = + ${env_light.lib_deps} [env:CYD-2432W328R-or-S024R] extends = CYD_base @@ -244,9 +246,8 @@ extends = env:CYD-2432W328R-or-S024R board_build.partitions = custom_4Mb.csv build_flags = ${env:CYD-2432W328R-or-S024R.build_flags} - -DCORE_DEBUG_LEVEL=0 - -DCONFIG_ESP32_JTAG_SUPPORT_DISABLE=1 - -DLITE_VERSION=1 - -DDEVICE_NAME='"LAUNCHER_CYD-2432W328R-or-S024R"' + ${env_light.build_flags} +lib_deps = + ${env_light.lib_deps} ################################# END OF CYD MODELS #################################################### diff --git a/boards/CYD-2432S028/interface.cpp b/boards/CYD-2432S028/interface.cpp index 51b5aebfc..d795ca542 100644 --- a/boards/CYD-2432S028/interface.cpp +++ b/boards/CYD-2432S028/interface.cpp @@ -79,8 +79,7 @@ void _post_setup_gpio() { // Brightness control must be initialized after tft in this case @Pirata pinMode(TFT_BL, OUTPUT); - ledcSetup(TFT_BRIGHT_CHANNEL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); // Channel 0, 10khz, 8bits - ledcAttachPin(TFT_BL, TFT_BRIGHT_CHANNEL); + ledcAttach(TFT_BL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); ledcWrite(TFT_BRIGHT_CHANNEL, 255); } diff --git a/boards/ESP-General/interface.cpp b/boards/ESP-General/interface.cpp index 7f6c4f721..1fc6d437a 100644 --- a/boards/ESP-General/interface.cpp +++ b/boards/ESP-General/interface.cpp @@ -6,7 +6,7 @@ ** Location: main.cpp ** Description: initial setup for the device ***************************************************************************************/ -void _setup_gpio() {} +void _setup_gpio() { bruceConfig.startupApp = "WebUI"; } /*************************************************************************************** ** Function name: getBattery() diff --git a/boards/ESP32-C5/ESP32-C5.ini b/boards/ESP32-C5/ESP32-C5.ini new file mode 100644 index 000000000..19dc124e7 --- /dev/null +++ b/boards/ESP32-C5/ESP32-C5.ini @@ -0,0 +1,116 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32-c5] +board = esp32-c5-devkitc-1 +board_build.partitions = custom_8Mb.csv +extra_scripts = + pre:patch-c5.py + pre:pre_build_current_year.py + post:build.py +build_src_filter =${env.build_src_filter} +<../boards/ESP32-C5> +build_flags = + ${env.build_flags} + -Iboards/ESP32-C5 + -DDEVICE_NAME='"ESP32-C5"' + -DARDUINO_USB_CDC_ON_BOOT=1 + -DARDUINO_USB_MODE=1 + -DCORE_DEBUG_LEVEL=1 + -DBAD_RX=4 + -DBAD_TX=5 + ; grove pins + ; defaults from https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h + -DGROVE_SDA=0 ; default RF TX pin + -DGROVE_SCL=1 ; default IR/RF RX pin + ;-DALLOW_ALL_GPIO_FOR_IR_RF=1 ; Set this option to make use of all GPIOs, from 1 to 44 to be chosen, except TFT and SD pins + + ; ir led pin + -DIR_TX_PINS='{{"Grove W", GROVE_SCL}, {"Grove Y", GROVE_SDA}}' + -DIR_RX_PINS='{{"Grove W", GROVE_SCL}, {"Grove Y", GROVE_SDA}}' + -DLED=27 + -DLED_ON=HIGH + -DLED_OFF=LOW + + ;Radio Frequency (one pin modules) pin setting + -DRF_TX_PINS='{{"Grove W", GROVE_SCL}, {"Grove Y", GROVE_SDA}}' + -DRF_RX_PINS='{{"Grove W", GROVE_SCL}, {"Grove Y", GROVE_SDA}}' + + ; sd card pins + ; suggested https://github.com/espressif/esp-idf/tree/master/examples/storage/sd_card/sdmmc + -DSDCARD_CS=-1 + -DSDCARD_SCK=-1 + -DSDCARD_MISO=-1 + -DSDCARD_MOSI=-1 + + ; tft vars + -DROTATION=1 + -DBACKLIGHT=-1 ; tft backlight pin + -DMINBRIGHT=160 ; unused? + -DUSER_SETUP_LOADED=1 ; dont redefine pins + -DILI9341_DRIVER=1 ; example only + -DSMOOTH_FONT=1 + -DTFT_DISPON=0x29 + -DTFT_DISPOFF=0x28 + -DTFT_CS=-1 + -DTFT_DC=-1 + -DTFT_RST=-1 + -DTOUCH_CS=-1 + -DTFT_MOSI=-1 + -DTFT_SCLK=-1 + -DTFT_BL=-1 + ; text sizes + -DFP=1 + -DFM=2 + -DFG=3 + ; ui control buttons + ;-DSEL_BTN=1 + ;-DUP_BTN=2 ; also work as ESC + ;-DDW_BTN=3 ; also work as NEXT + -DBTN_ALIAS='"OK"' + + ;FM Radio + ;-DFM_SI4713=1 ;Uncomment to activate FM Radio using Adafruit Si4713 + ;Microphone + ;-DMIC_SPM1423=1 ; uncomment to enable Applicable for SPM1423 device + ;-DPIN_CLK=-1 + ;-DI2S_SCLK_PIN=-1 + ;-DI2S_DATA_PIN=-1 + ;-DPIN_DATA=-1 + + ;CC1101 SPI connection pins + ; best connection pins for higher speed https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/spi_master.html#gpio-matrix-and-io-mux + -DUSE_CC1101_VIA_SPI + -DCC1101_GDO0_PIN=-1 + -DCC1101_SS_PIN=SPI_SS_PIN + -DCC1101_MOSI_PIN=SPI_MOSI_PIN + -DCC1101_SCK_PIN=SPI_SCK_PIN + -DCC1101_MISO_PIN=SPI_MISO_PIN + ;-DCC1101_GDO2_PIN=14 ; optional + + ; connections are the same as CC1101 + ;-DUSE_NRF24_VIA_SPI + ;-DNRF24_CE_PIN=5 + ;-DNRF24_SS_PIN=SPI_SS_PIN ; chip select + ;-DNRF24_MOSI_PIN=SPI_MOSI_PIN + ;-DNRF24_SCK_PIN=SPI_SCK_PIN + ;-DNRF24_MISO_PIN=SPI_MISO_PIN + + -DSPI_SCK_PIN=-1 + -DSPI_MOSI_PIN=-1 + -DSPI_MISO_PIN=-1 + -DSPI_SS_PIN=-1 + + ; connections are the same as W5500 + ; -DUSE_W5500_VIA_SPI + ; -DW5500_SS_PIN=SPI_SS_PIN + ; -DW5500_MOSI_PIN=SPI_MOSI_PIN + ; -DW5500_SCK_PIN=SPI_SCK_PIN + ; -DW5500_MISO_PIN=SPI_MISO_PIN + ; -DW5500_INT_PIN=5 diff --git a/boards/ESP32-C5/interface.cpp b/boards/ESP32-C5/interface.cpp new file mode 100644 index 000000000..1fc6d437a --- /dev/null +++ b/boards/ESP32-C5/interface.cpp @@ -0,0 +1,49 @@ +#include "core/powerSave.h" +#include + +/*************************************************************************************** +** Function name: _setup_gpio() +** Location: main.cpp +** Description: initial setup for the device +***************************************************************************************/ +void _setup_gpio() { bruceConfig.startupApp = "WebUI"; } + +/*************************************************************************************** +** Function name: getBattery() +** location: display.cpp +** Description: Delivers the battery value from 1-100 +***************************************************************************************/ +int getBattery() { return 0; } + +/*************************************************************************************** +** Function name: isCharging() +** Description: Default implementation that returns false +***************************************************************************************/ +bool isCharging() { return false; } + +/********************************************************************* +** Function: setBrightness +** location: settings.cpp +** set brightness value +**********************************************************************/ +void _setBrightness(uint8_t brightval) {} + +/********************************************************************* +** Function: InputHandler +** Handles the variables PrevPress, NextPress, SelPress, AnyKeyPress and EscPress +**********************************************************************/ +void InputHandler(void) {} + +/********************************************************************* +** Function: powerOff +** location: mykeyboard.cpp +** Turns off the device (or try to) +**********************************************************************/ +void powerOff() {} + +/********************************************************************* +** Function: checkReboot +** location: mykeyboard.cpp +** Btn logic to turnoff the device (name is odd btw) +**********************************************************************/ +void checkReboot() {} diff --git a/boards/ESP32-C5/pins_arduino.h b/boards/ESP32-C5/pins_arduino.h new file mode 100644 index 000000000..c48a6e432 --- /dev/null +++ b/boards/ESP32-C5/pins_arduino.h @@ -0,0 +1,56 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include "soc/soc_caps.h" +#include + +#define PIN_RGB_LED 27 +// BUILTIN_LED can be used in new Arduino API digitalWrite() like in Blink.ino +static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED; +#define BUILTIN_LED LED_BUILTIN // backward compatibility +#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN +// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API rgbLedWrite() +#define RGB_BUILTIN LED_BUILTIN +#define RGB_BRIGHTNESS 64 + +static const uint8_t TX = 11; +static const uint8_t RX = 12; + +// static const uint8_t USB_DM = 13; +// static const uint8_t USB_DP = 14; + +static const uint8_t SDA = 0; +static const uint8_t SCL = 1; + +static const uint8_t SS = 6; +static const uint8_t MOSI = 8; +static const uint8_t MISO = 9; +static const uint8_t SCK = 10; + +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; + +// LP I2C Pins are fixed on ESP32-C5 +static const uint8_t LP_SDA = 2; +static const uint8_t LP_SCL = 3; +#define WIRE1_PIN_DEFINED +#define SDA1 LP_SDA +#define SCL1 LP_SCL + +// LP UART Pins are fixed on ESP32-C5 +static const uint8_t LP_RX = 4; +static const uint8_t LP_TX = 5; + +#define HAS_RGB_LED 1 +#define LED_ORDER GRB +#define LED_TYPE_IS_RGBW 1 +#define LED_COUNT 1 +#define LED_TYPE WS2812 +#define LED_COLOR_STEP 15 +#define RGB_LED 27 + +#endif /* Pins_Arduino_h */ diff --git a/boards/_boards_json/esp32-c5-devkitc-1.json b/boards/_boards_json/esp32-c5-devkitc-1.json new file mode 100644 index 000000000..6f83eb5e5 --- /dev/null +++ b/boards/_boards_json/esp32-c5-devkitc-1.json @@ -0,0 +1,35 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DESP32C5_DEVKITC_1", + "-DESP32C5" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c5", + "variant": "pinouts" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32c5.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-C5-DevKitC-1 8MB no PSRAM", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c5/esp32-c5-devkitc-1/user_guide.html", + "vendor": "Espressif" +} diff --git a/boards/lilygo-t-deck/interface.cpp b/boards/lilygo-t-deck/interface.cpp index 706aa724c..6a255a127 100644 --- a/boards/lilygo-t-deck/interface.cpp +++ b/boards/lilygo-t-deck/interface.cpp @@ -1,14 +1,8 @@ +#include "TouchDrvGT911.hpp" #include "core/powerSave.h" +#include "core/utils.h" #include #include - -#include "core/utils.h" -#include -#include -#include -#include - -#include "TouchDrvGT911.hpp" TouchDrvGT911 touch; struct TouchPointPro { @@ -112,23 +106,8 @@ void _setup_gpio() { ***************************************************************************************/ int getBattery() { int percent = 0; - uint8_t _batAdcCh = ADC1_GPIO4_CHANNEL; - uint8_t _batAdcUnit = 1; - static uint32_t lastVolt = 5000; - static unsigned long lastTime = 0; - adc1_config_width(ADC_WIDTH_BIT_12); - adc1_config_channel_atten((adc1_channel_t)_batAdcCh, ADC_ATTEN_DB_12); - static esp_adc_cal_characteristics_t *adc_chars = nullptr; - static constexpr int BASE_VOLATAGE = 3600; - adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t)); - esp_adc_cal_characterize( - (adc_unit_t)_batAdcUnit, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, BASE_VOLATAGE, adc_chars - ); - int raw; - raw = adc1_get_raw((adc1_channel_t)_batAdcCh); - uint32_t volt = esp_adc_cal_raw_to_voltage(raw, adc_chars); - - float mv = volt * 2; + uint32_t volt = analogReadMilliVolts(GPIO_NUM_4); + float mv = volt; percent = (mv - 3300) * 100 / (float)(4150 - 3350); return (percent < 0) ? 0 : (percent >= 100) ? 100 : percent; @@ -145,8 +124,7 @@ void _post_setup_gpio() { #define TFT_BRIGHT_FREQ 5000 // Brightness control must be initialized after tft in this case @Pirata pinMode(TFT_BL, OUTPUT); - ledcSetup(TFT_BRIGHT_CHANNEL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); // Channel 0, 10khz, 8bits - ledcAttachPin(TFT_BL, TFT_BRIGHT_CHANNEL); + ledcAttach(TFT_BL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); ledcWrite(TFT_BRIGHT_CHANNEL, 255); } /********************************************************************* diff --git a/boards/lilygo-t-deck/lilygo-t-deck.ini b/boards/lilygo-t-deck/lilygo-t-deck.ini index cabd551ad..7b942c637 100644 --- a/boards/lilygo-t-deck/lilygo-t-deck.ini +++ b/boards/lilygo-t-deck/lilygo-t-deck.ini @@ -18,7 +18,7 @@ build_flags = -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw -Os - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 ;Features Enabled # Config to use IRQ and RST pins of PN532, if needed diff --git a/boards/lilygo-t-display-s3-pro/interface.cpp b/boards/lilygo-t-display-s3-pro/interface.cpp index b9dbe3abb..307350a07 100644 --- a/boards/lilygo-t-display-s3-pro/interface.cpp +++ b/boards/lilygo-t-display-s3-pro/interface.cpp @@ -10,8 +10,6 @@ static PowersSY6970 PMU; #include #define LCD_MODULE_CMD_1 -#include - #define BOARD_I2C_SDA 5 #define BOARD_I2C_SCL 6 #define BOARD_SENSOR_IRQ 21 @@ -79,8 +77,7 @@ void _setup_gpio() { ***************************************************************************************/ void _post_setup_gpio() { // PWM backlight setup - ledcSetup(TFT_BRIGHT_CHANNEL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); // Channel 0, 10khz, 8bits - ledcAttachPin(TFT_BL, TFT_BRIGHT_CHANNEL); + ledcAttach(TFT_BL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); ledcWrite(TFT_BRIGHT_CHANNEL, 255); } diff --git a/boards/lilygo-t-display-s3-pro/platformio.ini b/boards/lilygo-t-display-s3-pro/platformio.ini index e3efef871..9db132d8f 100644 --- a/boards/lilygo-t-display-s3-pro/platformio.ini +++ b/boards/lilygo-t-display-s3-pro/platformio.ini @@ -16,7 +16,7 @@ build_src_filter =${env.build_src_filter} +<../boards/lilygo-t-display-s3-pro> build_flags = ${env.build_flags} -Iboards/lilygo-t-display-s3-pro - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 -DBOARD_HAS_PSRAM=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DT_DISPLAY_S3_PRO=1 diff --git a/boards/lilygo-t-display-s3/interface.cpp b/boards/lilygo-t-display-s3/interface.cpp index f01770427..13f44fbff 100644 --- a/boards/lilygo-t-display-s3/interface.cpp +++ b/boards/lilygo-t-display-s3/interface.cpp @@ -32,7 +32,7 @@ Button *btn1; Button *btn2; #if defined(T_DISPLAY_S3) -#include + #endif /*************************************************************************************** @@ -116,11 +116,7 @@ void _setup_gpio() { ***************************************************************************************/ int getBattery() { int percent = 0; - esp_adc_cal_characteristics_t adc_chars; - esp_adc_cal_value_t val_type = - esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, 1100, &adc_chars); - uint32_t raw = analogRead(BAT_PIN); - uint32_t v1 = esp_adc_cal_raw_to_voltage(raw, &adc_chars) * 2; + uint32_t v1 = analogReadMilliVolts(BAT_PIN); if (v1 > 4150) { percent = 0; @@ -152,7 +148,7 @@ void _setBrightness(uint8_t brightval) { void InputHandler(void) { static long tm = 0; static bool btn_pressed = false; - bool selPressed=false; + bool selPressed = false; if (nxtPress || prvPress || ecPress || slPress || selPressed) btn_pressed = true; if (millis() - tm > 200 || LongPress) { @@ -193,7 +189,10 @@ void InputHandler(void) { touchHeatMap(touchPoint); } #endif - if(digitalRead(SEL_BTN) == BTN_ACT) { selPressed=true; btn_pressed=true; } + if (digitalRead(SEL_BTN) == BTN_ACT) { + selPressed = true; + btn_pressed = true; + } if (btn_pressed) { btn_pressed = false; if (!wakeUpScreen()) AnyKeyPress = true; diff --git a/boards/lilygo-t-display-s3/lilygo-t-display-s3.ini b/boards/lilygo-t-display-s3/lilygo-t-display-s3.ini index dcb9b4d72..d6b2066fc 100644 --- a/boards/lilygo-t-display-s3/lilygo-t-display-s3.ini +++ b/boards/lilygo-t-display-s3/lilygo-t-display-s3.ini @@ -6,7 +6,7 @@ build_flags = ${env.build_flags} -Iboards/lilygo-t-display-s3 -Os - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 -DREDRAW_DELAY=1 # Used to improve navigation on menus for this device -DMIC_SPM1423 @@ -14,11 +14,9 @@ build_flags = ;-UARDUINO_USB_CDC_ON_BOOT #Turn off CDC on boot https://github.com/Xinyuan-LilyGO/T-Display-S3 -DDISABLE_ALL_LIBRARY_WARNINGS - -DDEVICE_NAME='"Lilygo T-Display S3"' lib_deps = ${env.lib_deps} - fastled/FastLED @3.9.4 https://github.com/bmorcelli/ESP32_Button https://github.com/mmMicky/TouchLib diff --git a/boards/lilygo-t-display-s3/pins_arduino.h b/boards/lilygo-t-display-s3/pins_arduino.h index 294f65d52..4b20cde2c 100644 --- a/boards/lilygo-t-display-s3/pins_arduino.h +++ b/boards/lilygo-t-display-s3/pins_arduino.h @@ -4,6 +4,9 @@ #include "soc/soc_caps.h" #include +#ifndef DEVICE_NAME +#define DEVICE_NAME '"Lilygo T-Display S3"' +#endif // Lite Version // #define LITE_VERSION 1 diff --git a/boards/lilygo-t-display-ttgo/interface.cpp b/boards/lilygo-t-display-ttgo/interface.cpp index 04690b370..26d936515 100644 --- a/boards/lilygo-t-display-ttgo/interface.cpp +++ b/boards/lilygo-t-display-ttgo/interface.cpp @@ -1,7 +1,7 @@ #include "core/powerSave.h" #include "core/utils.h" #include -#include + #include #include volatile bool nxtPress = false; @@ -79,11 +79,7 @@ void _setup_gpio() { ***************************************************************************************/ int getBattery() { int percent = 0; - esp_adc_cal_characteristics_t adc_chars; - esp_adc_cal_value_t val_type = - esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, 1100, &adc_chars); - uint32_t raw = analogRead(ADC_PIN); - uint32_t v1 = esp_adc_cal_raw_to_voltage(raw, &adc_chars) * 2; + uint32_t v1 = analogReadMilliVolts(ADC_PIN); if (v1 > 4150) { percent = 0; diff --git a/boards/lilygo-t-embed-cc1101/interface.cpp b/boards/lilygo-t-embed-cc1101/interface.cpp index bb159b743..9172bdeaf 100644 --- a/boards/lilygo-t-embed-cc1101/interface.cpp +++ b/boards/lilygo-t-embed-cc1101/interface.cpp @@ -18,10 +18,7 @@ IRAM_ATTR void checkPosition(); #include XPowersPPM PPM; #elif defined(T_EMBED) -#include -#include -#include -#include + #endif #ifdef USE_BQ27220_VIA_I2C @@ -55,6 +52,8 @@ void _setup_gpio() { digitalWrite(TFT_CS, HIGH); pinMode(SDCARD_CS, OUTPUT); digitalWrite(SDCARD_CS, HIGH); + pinMode(44, OUTPUT); // NRF24 on Plus + digitalWrite(44, HIGH); // Power chip pin pinMode(PIN_POWER_ON, OUTPUT); @@ -65,13 +64,13 @@ void _setup_gpio() { if (pmu_ret) { PPM.setSysPowerDownVoltage(3300); PPM.setInputCurrentLimit(3250); - Serial.printf("getInputCurrentLimit: %d mA\n", PPM.getInputCurrentLimit()); + Serial.printf("getInputCurrentLimit: %d mA\n", (int)PPM.getInputCurrentLimit()); PPM.disableCurrentLimitPin(); PPM.setChargeTargetVoltage(4208); PPM.setPrechargeCurr(64); PPM.setChargerConstantCurr(832); PPM.getChargerConstantCurr(); - Serial.printf("getChargerConstantCurr: %d mA\n", PPM.getChargerConstantCurr()); + Serial.printf("getChargerConstantCurr: %d mA\n", (int)PPM.getChargerConstantCurr()); PPM.enableMeasure(PowersBQ25896::CONTINUOUS); PPM.disableOTG(); PPM.enableCharge(); @@ -123,21 +122,8 @@ int getBattery() { #if defined(USE_BQ27220_VIA_I2C) percent = bq.getChargePcnt(); #elif defined(T_EMBED) - uint8_t _batAdcCh = ADC1_GPIO4_CHANNEL; - uint8_t _batAdcUnit = 1; - adc1_config_width(ADC_WIDTH_BIT_12); - adc1_config_channel_atten((adc1_channel_t)_batAdcCh, ADC_ATTEN_DB_12); - static esp_adc_cal_characteristics_t *adc_chars = nullptr; - static constexpr int BASE_VOLATAGE = 3600; - adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t)); - esp_adc_cal_characterize( - (adc_unit_t)_batAdcUnit, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, BASE_VOLATAGE, adc_chars - ); - int raw; - raw = adc1_get_raw((adc1_channel_t)_batAdcCh); - uint32_t volt = esp_adc_cal_raw_to_voltage(raw, adc_chars); - - float mv = volt * 2; + uint32_t volt = analogReadMilliVolts(GPIO_NUM_4); + float mv = volt; percent = (mv - 3300) * 100 / (float)(4150 - 3350); #endif diff --git a/boards/lilygo-t-embed-cc1101/lilygo-t-embed-cc1101.ini b/boards/lilygo-t-embed-cc1101/lilygo-t-embed-cc1101.ini index e1780c720..580e46e9a 100644 --- a/boards/lilygo-t-embed-cc1101/lilygo-t-embed-cc1101.ini +++ b/boards/lilygo-t-embed-cc1101/lilygo-t-embed-cc1101.ini @@ -9,7 +9,7 @@ build_flags = -Iboards/lilygo-t-embed-cc1101 -O2 -DMIC_SPM1423 - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 -DRF_TX_PINS='{{"Pin 43", 43}, {"Pin 44", 44}}' -DRF_RX_PINS='{{"Pin 43", 43}, {"Pin 44", 44}}' @@ -21,4 +21,3 @@ lib_deps = ${env.lib_deps} lewisxhe/XPowersLib @0.2.7 mathertel/RotaryEncoder @1.5.3 - fastled/FastLED @3.9.4 diff --git a/boards/lilygo-t-embed-cc1101/lilygo-t-embed.ini b/boards/lilygo-t-embed-cc1101/lilygo-t-embed.ini index 48d8e7090..3b6267426 100644 --- a/boards/lilygo-t-embed-cc1101/lilygo-t-embed.ini +++ b/boards/lilygo-t-embed-cc1101/lilygo-t-embed.ini @@ -6,7 +6,7 @@ build_flags = ${env.build_flags} -Iboards/lilygo-t-embed-cc1101 -Os - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 -DMIC_SPM1423 ;Infrared Led default pin and state @@ -22,4 +22,3 @@ lib_deps = ${env.lib_deps} lewisxhe/XPowersLib @0.2.6 mathertel/RotaryEncoder @1.5.3 - fastled/FastLED @3.9.4 diff --git a/boards/lilygo-t-embed-cc1101/pins_arduino.h b/boards/lilygo-t-embed-cc1101/pins_arduino.h index 6bf897fd5..a36bd1ad9 100644 --- a/boards/lilygo-t-embed-cc1101/pins_arduino.h +++ b/boards/lilygo-t-embed-cc1101/pins_arduino.h @@ -109,6 +109,12 @@ static const uint8_t RX = SERIAL_RX; // Fuel Gauge #define USE_BQ27220_VIA_I2C #define BQ27220_I2C_ADDRESS 0x55 +#ifdef BQ27220_I2C_SDA +#undef BQ27220_I2C_SDA +#endif +#ifdef BQ27220_I2C_SCL +#undef BQ27220_I2C_SCL +#endif #define BQ27220_I2C_SDA GROVE_SDA #define BQ27220_I2C_SCL GROVE_SCL diff --git a/boards/lilygo-t-hmi/interface.cpp b/boards/lilygo-t-hmi/interface.cpp index a9205209a..fa14c39b8 100644 --- a/boards/lilygo-t-hmi/interface.cpp +++ b/boards/lilygo-t-hmi/interface.cpp @@ -3,11 +3,8 @@ #include "core/utils.h" #include #include -#include -#include #include -#include -#include + CYD28_TouchR touch(320, 240); /*************************************************************************************** @@ -39,8 +36,7 @@ void _post_setup_gpio() { #define TFT_BRIGHT_FREQ 5000 // Brightness control must be initialized after tft in this case @Pirata pinMode(TFT_BL, OUTPUT); - ledcSetup(TFT_BRIGHT_CHANNEL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); // Channel 0, 10khz, 8bits - ledcAttachPin(TFT_BL, TFT_BRIGHT_CHANNEL); + ledcAttach(TFT_BL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); ledcWrite(TFT_BRIGHT_CHANNEL, 255); } @@ -132,22 +128,8 @@ void checkReboot() {} ***************************************************************************************/ int getBattery() { uint8_t percent; - uint8_t _batAdcCh = ADC1_GPIO5_CHANNEL; - uint8_t _batAdcUnit = 1; - - adc1_config_width(ADC_WIDTH_BIT_12); - adc1_config_channel_atten((adc1_channel_t)_batAdcCh, ADC_ATTEN_DB_12); - static esp_adc_cal_characteristics_t *adc_chars = nullptr; - static constexpr int BASE_VOLATAGE = 3600; - adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t)); - esp_adc_cal_characterize( - (adc_unit_t)_batAdcUnit, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, BASE_VOLATAGE, adc_chars - ); - int raw; - raw = adc1_get_raw((adc1_channel_t)_batAdcCh); - uint32_t volt = esp_adc_cal_raw_to_voltage(raw, adc_chars); - - float mv = volt * 2; + uint32_t volt = analogReadMilliVolts(GPIO_NUM_5); + float mv = volt; percent = (mv - 3300) * 100 / (float)(4150 - 3350); return (percent < 0) ? 0 : (percent >= 100) ? 100 : percent; diff --git a/boards/lilygo-t-hmi/lilygo-t-hmi.ini b/boards/lilygo-t-hmi/lilygo-t-hmi.ini index ab3a75ccb..a74d18e25 100644 --- a/boards/lilygo-t-hmi/lilygo-t-hmi.ini +++ b/boards/lilygo-t-hmi/lilygo-t-hmi.ini @@ -6,7 +6,7 @@ build_flags = ${env.build_flags} -Iboards/lilygo-t-hmi -Os - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 -DRF_TX_PINS='{{"Pin 15", 15}, {"Pin 16", 16}, {"Pin 17", 17}, {"Pin 18", 18}, {"Pin 43", 43}, {"Pin 44", 44}}' -DRF_RX_PINS='{{"Pin 15", 15}, {"Pin 16", 16}, {"Pin 17", 17}, {"Pin 18", 18}, {"Pin 43", 43}, {"Pin 44", 44}}' diff --git a/boards/lilygo-t-lora-pager/lilygo-t-lora-pager.ini b/boards/lilygo-t-lora-pager/lilygo-t-lora-pager.ini index c92172270..176d2e725 100644 --- a/boards/lilygo-t-lora-pager/lilygo-t-lora-pager.ini +++ b/boards/lilygo-t-lora-pager/lilygo-t-lora-pager.ini @@ -1,20 +1,20 @@ - -[env:lilygo-t-lora-pager] -board = lilygo-t-lora-pager -board_build.arduino.memory_type = qio_qspi -board_build.partitions = custom_16Mb.csv -build_src_filter =${env.build_src_filter} +<../boards/lilygo-t-lora-pager> -build_flags = - ${env.build_flags} - -Iboards/lilygo-t-lora-pager - -O2 - -DMIC_SPM1423 - -DCGRAM_OFFSET - -DCORE_DEBUG_LEVEL=5 - -lib_deps = - ${env.lib_deps} - lewisxhe/XPowersLib @0.3.0 - lewisxhe/SensorLib - mathertel/RotaryEncoder @1.5.3 - adafruit/Adafruit TCA8418 @ ^1.0.2 + +[env:lilygo-t-lora-pager] +board = lilygo-t-lora-pager +board_build.arduino.memory_type = qio_qspi +board_build.partitions = custom_16Mb.csv +build_src_filter =${env.build_src_filter} +<../boards/lilygo-t-lora-pager> +build_flags = + ${env.build_flags} + -Iboards/lilygo-t-lora-pager + -O2 + -DMIC_SPM1423 + -DCGRAM_OFFSET + -DCORE_DEBUG_LEVEL=1 + +lib_deps = + ${env.lib_deps} + lewisxhe/XPowersLib @0.3.0 + lewisxhe/SensorLib + mathertel/RotaryEncoder @1.5.3 + adafruit/Adafruit TCA8418 @ ^1.0.2 diff --git a/boards/lilygo-t-watch-s3/interface.cpp b/boards/lilygo-t-watch-s3/interface.cpp index b04773629..0d5fae5df 100644 --- a/boards/lilygo-t-watch-s3/interface.cpp +++ b/boards/lilygo-t-watch-s3/interface.cpp @@ -94,8 +94,7 @@ void _setup_gpio() { void _post_setup_gpio() { pinMode(TFT_BL, OUTPUT); digitalWrite(TFT_BL, HIGH); - ledcSetup(TFT_BRIGHT_CHANNEL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); // Channel 0, 10khz, 8bits - ledcAttachPin(TFT_BL, TFT_BRIGHT_CHANNEL); + ledcAttach(TFT_BL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); ledcWrite(TFT_BRIGHT_CHANNEL, 255); } diff --git a/boards/lilygo-t-watch-s3/lilygo-t-watch-s3.ini b/boards/lilygo-t-watch-s3/lilygo-t-watch-s3.ini index 1eec240bc..d9d745b51 100644 --- a/boards/lilygo-t-watch-s3/lilygo-t-watch-s3.ini +++ b/boards/lilygo-t-watch-s3/lilygo-t-watch-s3.ini @@ -18,7 +18,7 @@ build_flags = -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw -Os - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 -DREMOVE_RF_MENU -DREMOVE_RFID_MENU diff --git a/boards/m5stack-cardputer/interface.cpp b/boards/m5stack-cardputer/interface.cpp index 7a8cedfb1..86d2fb847 100644 --- a/boards/m5stack-cardputer/interface.cpp +++ b/boards/m5stack-cardputer/interface.cpp @@ -15,35 +15,17 @@ void _setup_gpio() { pinMode(10, INPUT); // Pin that reads the } -#include -#include -#include -#include /*************************************************************************************** ** Function name: getBattery() ** location: display.cpp ** Description: Delivers the battery value from 1-100 ***************************************************************************************/ int getBattery() { + pinMode(GPIO_NUM_10, INPUT); uint8_t percent; - uint8_t _batAdcCh = ADC1_GPIO10_CHANNEL; - uint8_t _batAdcUnit = 1; - static uint32_t lastVolt = 5000; - static unsigned long lastTime = 0; + uint32_t volt = analogReadMilliVolts(GPIO_NUM_10); - adc1_config_width(ADC_WIDTH_BIT_12); - adc1_config_channel_atten((adc1_channel_t)_batAdcCh, ADC_ATTEN_DB_12); - static esp_adc_cal_characteristics_t *adc_chars = nullptr; - static constexpr int BASE_VOLATAGE = 3600; - adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t)); - esp_adc_cal_characterize( - (adc_unit_t)_batAdcUnit, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, BASE_VOLATAGE, adc_chars - ); - int raw; - raw = adc1_get_raw((adc1_channel_t)_batAdcCh); - uint32_t volt = esp_adc_cal_raw_to_voltage(raw, adc_chars); - - float mv = volt * 2; + float mv = volt; percent = (mv - 3300) * 100 / (float)(4150 - 3350); return (percent < 0) ? 0 : (percent >= 100) ? 100 : percent; diff --git a/boards/m5stack-cardputer/m5stack-cardputer.ini b/boards/m5stack-cardputer/m5stack-cardputer.ini index 9c2339082..30261b60c 100644 --- a/boards/m5stack-cardputer/m5stack-cardputer.ini +++ b/boards/m5stack-cardputer/m5stack-cardputer.ini @@ -15,7 +15,7 @@ build_src_filter =${env.build_src_filter} +<../boards/m5stack-cardputer> build_flags = ${env.build_flags} -Iboards/m5stack-cardputer - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 ;Features Enabled ;-DLITE_VERSION=1 ;limits some features to save space for M5Launcher Compatibility @@ -134,7 +134,3 @@ build_flags = -DSPI_SS_PIN=GROVE_SCL -DDEVICE_NAME='"M5Stack Cardputer"' - -lib_deps = - ${env.lib_deps} - fastled/FastLED @3.9.4 diff --git a/boards/m5stack-core/m5stack-core.ini b/boards/m5stack-core/m5stack-core.ini index 06700df78..71299cc8d 100644 --- a/boards/m5stack-core/m5stack-core.ini +++ b/boards/m5stack-core/m5stack-core.ini @@ -151,10 +151,12 @@ build_flags = lib_deps = ${env.lib_deps} - m5stack/M5Unified @ 0.2.2 + ;m5stack/M5Unified @ ^0.2.8 ; not released + https://github.com/m5stack/M5Unified#develop [env:m5stack-core4mb] extends=m5stack-core_base + build_flags = ${m5stack-core_base.build_flags} -DLITE_VERSION=1 #limits some features to save space for M5Launcher Compatibility diff --git a/boards/m5stack-core2/m5stack-core2.ini b/boards/m5stack-core2/m5stack-core2.ini index 0d410a20b..246844673 100644 --- a/boards/m5stack-core2/m5stack-core2.ini +++ b/boards/m5stack-core2/m5stack-core2.ini @@ -21,7 +21,7 @@ build_src_filter =${env.build_src_filter} +<../boards/m5stack-core2> build_flags = ${env.build_flags} -Iboards/m5stack-core2 - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 ;Features Enabled ;-DLITE_VERSION=1 ;limits some features to save space for M5Launcher Compatibility @@ -151,4 +151,5 @@ build_flags = -DDEVICE_NAME='"M5Stack Core 2"' lib_deps = ${env.lib_deps} - m5stack/M5Unified @ 0.2.2 + ;m5stack/M5Unified @ ^0.2.8 ; not released + https://github.com/m5stack/M5Unified#develop diff --git a/boards/m5stack-cores3/m5stack-cores3.ini b/boards/m5stack-cores3/m5stack-cores3.ini index 140680ca0..d6038ab50 100644 --- a/boards/m5stack-cores3/m5stack-cores3.ini +++ b/boards/m5stack-cores3/m5stack-cores3.ini @@ -44,5 +44,7 @@ build_flags = -DDEVICE_NAME='"M5Stack Core 3"' lib_deps = ${env.lib_deps} - m5stack/M5Unified @ 0.2.2 + ;m5stack/M5Unified @ ^0.2.8 ; not released + https://github.com/m5stack/M5GFX#develop + https://github.com/m5stack/M5Unified#develop diff --git a/boards/m5stack-cplus1_1/m5stack-cplus1_1.ini b/boards/m5stack-cplus1_1/m5stack-cplus1_1.ini index c325f03af..511da1da3 100644 --- a/boards/m5stack-cplus1_1/m5stack-cplus1_1.ini +++ b/boards/m5stack-cplus1_1/m5stack-cplus1_1.ini @@ -145,5 +145,7 @@ extends=env:m5stack-cplus1_1 board_build.partitions = custom_4Mb.csv build_flags = ${env:m5stack-cplus1_1.build_flags} - -DLITE_VERSION=1 ;limits some features to save space for M5Launcher Compatibility + ${env_light.build_flags} +lib_deps = + ${env_light.lib_deps} diff --git a/boards/m5stack-cplus2/interface.cpp b/boards/m5stack-cplus2/interface.cpp index a8735a465..78a690ab2 100644 --- a/boards/m5stack-cplus2/interface.cpp +++ b/boards/m5stack-cplus2/interface.cpp @@ -1,9 +1,5 @@ #include "core/powerSave.h" -#include -#include #include -#include -#include /*************************************************************************************** ** Function name: _setup_gpio() @@ -31,24 +27,8 @@ void _setup_gpio() { ***************************************************************************************/ int getBattery() { uint8_t percent; - uint8_t _batAdcCh = ADC1_GPIO38_CHANNEL; - uint8_t _batAdcUnit = 1; - static uint32_t lastVolt = 5000; - static unsigned long lastTime = 0; - - adc1_config_width(ADC_WIDTH_BIT_12); - adc1_config_channel_atten((adc1_channel_t)_batAdcCh, ADC_ATTEN_DB_12); - static esp_adc_cal_characteristics_t *adc_chars = nullptr; - static constexpr int BASE_VOLATAGE = 3600; - adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t)); - esp_adc_cal_characterize( - (adc_unit_t)_batAdcUnit, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, BASE_VOLATAGE, adc_chars - ); - int raw; - raw = adc1_get_raw((adc1_channel_t)_batAdcCh); - uint32_t volt = esp_adc_cal_raw_to_voltage(raw, adc_chars); - - float mv = volt * 2; + uint32_t volt = analogReadMilliVolts(GPIO_NUM_38); + float mv = volt; percent = (mv - 3300) * 100 / (float)(4150 - 3350); return (percent >= 100) ? 100 : percent; diff --git a/boards/m5stack-cplus2/m5stack-cplus2.ini b/boards/m5stack-cplus2/m5stack-cplus2.ini index 366b8c076..d078c89c0 100644 --- a/boards/m5stack-cplus2/m5stack-cplus2.ini +++ b/boards/m5stack-cplus2/m5stack-cplus2.ini @@ -18,7 +18,7 @@ build_src_filter =${env.build_src_filter} +<../boards/m5stack-cplus2> build_flags = ${env.build_flags} -Iboards/m5stack-cplus2 - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 ;Features Enabled ;-DLITE_VERSION=1 ;limits some features to save space for M5Launcher Compatibility diff --git a/boards/marauder-mini/marauder-mini.ini b/boards/marauder-mini/marauder-mini.ini index eff259228..7362524bb 100644 --- a/boards/marauder-mini/marauder-mini.ini +++ b/boards/marauder-mini/marauder-mini.ini @@ -88,17 +88,15 @@ extends=env:Marauder-Mini board_build.partitions = custom_4Mb.csv build_flags = ${env:Marauder-Mini.build_flags} - -DCORE_DEBUG_LEVEL=0 - -DCONFIG_ESP32_JTAG_SUPPORT_DISABLE=1 - -DLITE_VERSION=1 - -DDEVICE_NAME='"Launcher Marauder mini"' + ${env_light.build_flags} +lib_deps = + ${env_light.lib_deps} [env:LAUNCHER_Marauder-v7] extends=env:Marauder-v7 board_build.partitions = custom_4Mb.csv build_flags = ${env:Marauder-v7.build_flags} - -DCORE_DEBUG_LEVEL=0 - -DCONFIG_ESP32_JTAG_SUPPORT_DISABLE=1 - -DLITE_VERSION=1 - -DDEVICE_NAME='"Launcher Marauder v7"' + ${env_light.build_flags} +lib_deps = + ${env_light.lib_deps} diff --git a/boards/marauder-touch/marauder-touch.ini b/boards/marauder-touch/marauder-touch.ini index 6b98f7139..10606f6e1 100644 --- a/boards/marauder-touch/marauder-touch.ini +++ b/boards/marauder-touch/marauder-touch.ini @@ -50,20 +50,18 @@ extends=env:Marauder-V4-V6 board_build.partitions = custom_4Mb.csv build_flags = ${env:Marauder-V4-V6.build_flags} - -DCORE_DEBUG_LEVEL=0 - -DCONFIG_ESP32_JTAG_SUPPORT_DISABLE=1 - -DLITE_VERSION=1 - -DDEVICE_NAME='"Launcher Marauder v4-v6"' + ${env_light.build_flags} +lib_deps = + ${env_light.lib_deps} [env:LAUNCHER_Marauder-v61] extends=env:Marauder-v61 board_build.partitions = custom_4Mb.csv build_flags = ${env:Marauder-v61.build_flags} - -DCORE_DEBUG_LEVEL=0 - -DCONFIG_ESP32_JTAG_SUPPORT_DISABLE=1 - -DLITE_VERSION=1 - -DDEVICE_NAME='"Launcher Marauder v6.1"' + ${env_light.build_flags} +lib_deps = + ${env_light.lib_deps} diff --git a/boards/phantom/interface.cpp b/boards/phantom/interface.cpp index 409e4eb30..dca544120 100644 --- a/boards/phantom/interface.cpp +++ b/boards/phantom/interface.cpp @@ -14,7 +14,7 @@ SPIClass touchSPI; void _setup_gpio() { pinMode(XPT2046_CS, OUTPUT); digitalWrite(XPT2046_CS, HIGH); - bruceConfig.rotation = 0; // portrait mode for Phantom + bruceConfig.rotation = 0; // portrait mode for Phantom bruceConfig.colorInverted = 0; // color invert for Phantom tft.setRotation(bruceConfig.rotation); uint16_t calData[5] = {275, 3500, 280, 3590, 3}; // 0011 = 3 @@ -35,8 +35,7 @@ void _post_setup_gpio() { // tft.setTouch(calData); // Brightness control must be initialized after tft in this case @Pirata pinMode(TFT_BL, OUTPUT); - ledcSetup(TFT_BRIGHT_CHANNEL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); // Channel 0, 10khz, 8bits - ledcAttachPin(TFT_BL, TFT_BRIGHT_CHANNEL); + ledcAttach(TFT_BL, TFT_BRIGHT_FREQ, TFT_BRIGHT_Bits); ledcWrite(TFT_BRIGHT_CHANNEL, 255); } diff --git a/boards/phantom/phantom.ini b/boards/phantom/phantom.ini index 80e7bffa5..838838523 100644 --- a/boards/phantom/phantom.ini +++ b/boards/phantom/phantom.ini @@ -176,8 +176,10 @@ extends = env:Phantom_S024R board_build.partitions = custom_4Mb.csv build_flags = ${env:Phantom_S024R.build_flags} - -DLITE_VERSION=1 - -DDEVICE_NAME='"Launcher Phantom S024R"' + ${env_light.build_flags} +lib_deps = + ${env_light.lib_deps} + ################################# END OF CYD MODELS #################################################### diff --git a/boards/pinouts/pins_arduino.h b/boards/pinouts/pins_arduino.h index 56dde08a1..91309dce6 100644 --- a/boards/pinouts/pins_arduino.h +++ b/boards/pinouts/pins_arduino.h @@ -38,4 +38,6 @@ #include "../marauder-mini/pins_arduino.h" #elif LILYGO_T_HMI #include "../lilygo-t-hmi/pins_arduino.h" +#elif ESP32C5_DEVKITC_1 +#include "../ESP32-C5/pins_arduino.h" #endif diff --git a/boards/smoochiee-board/interface.cpp b/boards/smoochiee-board/interface.cpp index 0ae9f6482..9a688aa90 100644 --- a/boards/smoochiee-board/interface.cpp +++ b/boards/smoochiee-board/interface.cpp @@ -1,10 +1,5 @@ #include "core/powerSave.h" -#include -#include -#include -#include - /*************************************************************************************** ** Function name: _setup_gpio() ** Location: main.cpp diff --git a/boards/smoochiee-board/pins_arduino.h b/boards/smoochiee-board/pins_arduino.h index 38c6c34ed..f262bbc3c 100644 --- a/boards/smoochiee-board/pins_arduino.h +++ b/boards/smoochiee-board/pins_arduino.h @@ -98,7 +98,7 @@ static const uint8_t SCK = 18; #define LED_TYPE WS2812B #define LED_ORDER GRB #define LED_TYPE_IS_RGBW 0 -#define LED_COUNT 16 +#define LED_COUNT 16 #define LED_COLOR_STEP 15 #define USE_BQ25896 diff --git a/boards/smoochiee-board/smoochiee-board.ini b/boards/smoochiee-board/smoochiee-board.ini index bf0aa8872..2e8de4599 100644 --- a/boards/smoochiee-board/smoochiee-board.ini +++ b/boards/smoochiee-board/smoochiee-board.ini @@ -18,7 +18,7 @@ build_flags = ${env.build_flags} -Iboards/smoochiee-board -Os - -DCORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=1 -DIR_TX_PINS='{{"M5 IR Mod", GROVE_SDA}, {"Grove W", GROVE_SCL}, {"Grove Y", GROVE_SDA}, {"GPIO 5", 5}, {"GPIO 2", 2}}' -DIR_RX_PINS='{{"M5 IR Mod", GROVE_SCL}, {"Grove W", GROVE_SCL}, {"Grove Y", GROVE_SDA}, {"GPIO 4", 4}, {"GPIO 2", 2}}' -DRF_TX_PINS='{{"M5 RF433T", GROVE_SDA}, {"Grove W", GROVE_SCL}, {"Grove Y", GROVE_SDA}, {"GPIO 1", 1}, {"GPIO 2", 2}}' @@ -32,4 +32,4 @@ build_flags = lib_deps = ${env.lib_deps} lewisxhe/XPowersLib @0.2.6 - fastled/FastLED @3.9.4 + diff --git a/build.py b/build.py index 3f536ea35..444913eba 100644 --- a/build.py +++ b/build.py @@ -61,7 +61,7 @@ def q(p): return f"\"{p}\"" cmd = " ".join([ "pio pkg exec -p \"tool-esptoolpy\" -- esptool.py", "--chip", chip_arg, - "merge_bin", + "merge-bin", "--output", q(out_bin), hex(boot_offset), q(boot_bin), hex(PART_TABLE_OFFSET), q(part_bin), diff --git a/include/tftLogger.h b/include/tftLogger.h index 3fa1fb62a..5b4892419 100644 --- a/include/tftLogger.h +++ b/include/tftLogger.h @@ -1,7 +1,6 @@ #ifndef __DISPLAY_LOGER #define __DISPLAY_LOGER #include //need to fetch the device Settings that are not in platformio.ini file -#include #ifdef HAS_SCREEN #include #define BRUCE_TFT_DRIVER TFT_eSPI @@ -49,9 +48,14 @@ class tft_logger : public BRUCE_TFT_DRIVER { tftLog log[MAX_LOG_ENTRIES]; char images[MAX_LOG_IMAGES][MAX_LOG_IMG_PATH]; uint8_t logWriteIndex = 0; + uint8_t logCount = 0; bool logging = false; bool _logging = false; void clearLog(); + bool async_serial = false; + TaskHandle_t asyncSerialTask = NULL; + QueueHandle_t asyncSerialQueue = NULL; + static void asyncSerialTaskFunc(void *pv); public: tft_logger(int16_t w = TFT_WIDTH, int16_t h = TFT_HEIGHT); @@ -64,7 +68,9 @@ class tft_logger : public BRUCE_TFT_DRIVER { void removeOverlappedImages(int x, int y, int center, int ms); void fillScreen(int32_t color); - + void startAsyncSerial(); + void stopAsyncSerial(); + void getTftInfo(); void imageToBin(uint8_t fs, String file, int x, int y, bool center, int Ms); void drawLine(int32_t x, int32_t y, int32_t x1, int32_t y1, int32_t color); @@ -121,8 +127,22 @@ class tft_logger : public BRUCE_TFT_DRIVER { protected: bool isLogEqual(const tftLog &a, const tftLog &b); void pushLogIfUnique(const tftLog &l); - void checkAndLog(tftFuncs f, std::initializer_list values); + // void checkAndLog(tftFuncs f, std::initializer_list values); + template void checkAndLog(tftFuncs f, Args... args) { + if (!logging) return; + + uint8_t buffer[MAX_LOG_SIZE]; + uint8_t pos = 0; + logWriteHeader(buffer, pos, f); + + (writeUint16(buffer, pos, static_cast(args)), ...); + buffer[1] = pos; + tftLog l; + memcpy(l.data, buffer, pos); + pushLogIfUnique(l); + logging = false; + } void restoreLogger(); void addLogEntry(const uint8_t *buffer, uint8_t size); void logWriteHeader(uint8_t *buffer, uint8_t &pos, tftFuncs fn); diff --git a/lib/Bad_Usb_Lib/BleKeyboard.cpp b/lib/Bad_Usb_Lib/BleKeyboard.cpp index d6ffb2869..8a60a2dc2 100644 --- a/lib/Bad_Usb_Lib/BleKeyboard.cpp +++ b/lib/Bad_Usb_Lib/BleKeyboard.cpp @@ -1,21 +1,12 @@ #include "BleKeyboard.h" #include "KeyboardLayout.h" -#if defined(USE_NIMBLE) +#include "HIDTypes.h" +#include "sdkconfig.h" #include #include #include #include -#else -#include "BLE2902.h" -#include "BLEHIDDevice.h" -#include -#include -#include -#endif // USE_NIMBLE -#include "HIDTypes.h" -#include "sdkconfig.h" -#include #if defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" @@ -170,46 +161,38 @@ void BleKeyboard::begin(const uint8_t *layout, uint16_t showAs) { _asciimap = layout; BLEDevice::init(deviceName.c_str()); pServer = BLEDevice::createServer(); - pServer->setCallbacks(this); - + pServer->setCallbacks(new ServerCallbacks(this)); hid = new BLEHIDDevice(pServer); - inputKeyboard = hid->inputReport(KEYBOARD_ID); // <-- input REPORTID from report map - outputKeyboard = hid->outputReport(KEYBOARD_ID); - inputMediaKeys = hid->inputReport(MEDIA_KEYS_ID); - - inputKeyboard->setCallbacks(this); - outputKeyboard->setCallbacks(this); - inputMediaKeys->setCallbacks(this); - - hid->manufacturer()->setValue(deviceManufacturer); + inputKeyboard = hid->getInputReport(KEYBOARD_ID); // <-- input REPORTID from report map + outputKeyboard = hid->getOutputReport(KEYBOARD_ID); + inputMediaKeys = hid->getInputReport(MEDIA_KEYS_ID); - hid->pnp(0x02, vid, pid, version); - hid->hidInfo(0x00, 0x01); + inputKeyboard->setCallbacks(new CharacteristicCallbacks(this)); + outputKeyboard->setCallbacks(new CharacteristicCallbacks(this)); + inputMediaKeys->setCallbacks(new CharacteristicCallbacks(this)); -#if defined(USE_NIMBLE) + hid->setManufacturer("Espressif"); + hid->setPnp(0x02, vid, pid, version); + hid->setHidInfo(0x00, 0x01); BLEDevice::setSecurityAuth(true, true, true); -#else - - BLESecurity *pSecurity = new BLESecurity(); - pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND); - -#endif // USE_NIMBLE - - hid->reportMap((uint8_t *)_hidReportDescriptor, sizeof(_hidReportDescriptor)); + hid->setReportMap((uint8_t *)_hidReportDescriptor, sizeof(_hidReportDescriptor)); hid->startServices(); - - onStarted(pServer); - advertising = pServer->getAdvertising(); advertising->setAppearance(appearance); - if (_randUUID) { // this workaround makes 2 Bruce connect and work on the same Android device + if (_randUUID) { advertising->addServiceUUID(BLEUUID((uint16_t)(ESP.getEfuseMac() & 0xFFFF))); } else { - advertising->addServiceUUID(hid->hidService()->getUUID()); + + advertising->addServiceUUID(hid->getHidService()->getUUID()); + NimBLEAdvertisementData advertisementData = NimBLEAdvertisementData(); + advertisementData.setFlags(0x06); + advertisementData.setName(deviceName.c_str()); + advertising->setAdvertisementData(advertisementData); } - advertising->setScanResponse(false); + + advertising->enableScanResponse(false); advertising->start(); hid->setBatteryLevel(batteryLevel); } @@ -250,8 +233,12 @@ void BleKeyboard::set_product_id(uint16_t pid) { this->pid = pid; } void BleKeyboard::set_version(uint16_t version) { this->version = version; } void BleKeyboard::sendReport(KeyReport *keys) { - // if (this->isConnected()) - if (this->isConnected() && this->inputKeyboard->getSubscribedCount() > 0) { +#ifdef NIMBLE_V2_PLUS + if (this->isConnected() && this->getSubscribedCount() > 0) +#else + if (this->isConnected() && this->inputKeyboard->getSubscribedCount() > 0) +#endif + { this->inputKeyboard->setValue((uint8_t *)keys, sizeof(KeyReport)); this->inputKeyboard->notify(); #if defined(USE_NIMBLE) @@ -262,8 +249,12 @@ void BleKeyboard::sendReport(KeyReport *keys) { } void BleKeyboard::sendReport(MediaKeyReport *keys) { - // if (this->isConnected()) - if (this->isConnected() && this->inputKeyboard->getSubscribedCount() > 0) { +#ifdef NIMBLE_V2_PLUS + if (this->isConnected() && this->getSubscribedCount() > 0) +#else + if (this->isConnected() && this->inputKeyboard->getSubscribedCount() > 0) +#endif + { this->inputMediaKeys->setValue((uint8_t *)keys, sizeof(MediaKeyReport)); this->inputMediaKeys->notify(); #if defined(USE_NIMBLE) @@ -421,38 +412,68 @@ size_t BleKeyboard::write(const uint8_t *buffer, size_t size) { } return n; } +#ifdef NIMBLE_V2_PLUS +void BleKeyboard::ServerCallbacks::onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo) { + // BleKeyboard::connected = true; + Serial.println("BRUCE KEYBOARD: lib connected"); +} +void BleKeyboard::ServerCallbacks::onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) { + // BleKeyboard::connected = true; + Serial.println("BRUCE KEYBOARD: lib disconnected"); +} +void BleKeyboard::ServerCallbacks::onAuthenticationComplete(NimBLEConnInfo &connInfo) { + if (connInfo.isEncrypted()) { + Serial.println("BRUCE KEYBOARD: Paired successfully."); + parent->connected = true; + } else { + Serial.println("BRUCE KEYBOARD: Pairing failed"); + parent->connected = false; + } +} + +void BleKeyboard::CharacteristicCallbacks::onWrite( + NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo +) { + uint8_t *value = (uint8_t *)(pCharacteristic->getValue().c_str()); + (void)value; + ESP_LOGI(LOG_TAG, "special keys: %d", *value); +} +void BleKeyboard::CharacteristicCallbacks::onSubscribe( + NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo, uint16_t subValue +) { + if (subValue == 0) { + Serial.println("BRUCE KEYBOARD: Client unsubscribed from notifications/indications."); + if (parent->m_subCount) parent->m_subCount--; + } else { + parent->m_subCount++; + Serial.println("BRUCE KEYBOARD: Client subscribed to notifications."); + } +} +#else void BleKeyboard::onConnect(BLEServer *pServer) { // this->connected = true; Serial.println("lib connected"); - -#if !defined(USE_NIMBLE) - - BLE2902 *desc = (BLE2902 *)this->inputKeyboard->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); - desc->setNotifications(true); - desc = (BLE2902 *)this->inputMediaKeys->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); - desc->setNotifications(true); - -#endif // !USE_NIMBLE } - void BleKeyboard::onDisconnect(BLEServer *pServer) { this->connected = false; // NimBLEDevice::startAdvertising(); Serial.println("lib disconnected"); - -#if !defined(USE_NIMBLE) - - BLE2902 *desc = (BLE2902 *)this->inputKeyboard->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); - desc->setNotifications(false); - desc = (BLE2902 *)this->inputMediaKeys->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); - desc->setNotifications(false); - - advertising->start(); - -#endif // !USE_NIMBLE } - +void BleKeyboard::onWrite(BLECharacteristic *me) { + uint8_t *value = (uint8_t *)(me->getValue().c_str()); + (void)value; + ESP_LOGI(LOG_TAG, "special keys: %d", *value); +} +void BleKeyboard::onSubscribe( + NimBLECharacteristic *pCharacteristic, ble_gap_conn_desc *desc, uint16_t subValue +) { + if (subValue == 0) { + Serial.println("Client unsubscribed from notifications/indications."); + } else { + Serial.println("Client subscribed to notifications."); + } +} void BleKeyboard::onAuthenticationComplete(ble_gap_conn_desc *desc) { if (desc->sec_state.encrypted) { Serial.println("Paired successfully."); @@ -462,12 +483,7 @@ void BleKeyboard::onAuthenticationComplete(ble_gap_conn_desc *desc) { this->connected = false; } } - -void BleKeyboard::onWrite(BLECharacteristic *me) { - uint8_t *value = (uint8_t *)(me->getValue().c_str()); - (void)value; - ESP_LOGI(LOG_TAG, "special keys: %d", *value); -} +#endif void BleKeyboard::delay_ms(uint64_t ms) { uint64_t m = esp_timer_get_time(); @@ -479,12 +495,3 @@ void BleKeyboard::delay_ms(uint64_t ms) { while (esp_timer_get_time() < e) {} } } -void BleKeyboard::onSubscribe( - NimBLECharacteristic *pCharacteristic, ble_gap_conn_desc *desc, uint16_t subValue -) { - if (subValue == 0) { - Serial.println("Client unsubscribed from notifications/indications."); - } else { - Serial.println("Client subscribed to notifications."); - } -} diff --git a/lib/Bad_Usb_Lib/BleKeyboard.h b/lib/Bad_Usb_Lib/BleKeyboard.h index 1df53f004..e9ba6ba18 100644 --- a/lib/Bad_Usb_Lib/BleKeyboard.h +++ b/lib/Bad_Usb_Lib/BleKeyboard.h @@ -6,11 +6,15 @@ #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #define USE_NIMBLE -#if defined(USE_NIMBLE) - +#if __has_include() +#define NIMBLE_V2_PLUS 1 +#endif #include "NimBLECharacteristic.h" #include "NimBLEHIDDevice.h" - +#ifdef NIMBLE_V2_PLUS +#include "NimBLEAdvertising.h" +#include "NimBLEServer.h" +#endif #define BLEDevice NimBLEDevice #define BLEServerCallbacks NimBLEServerCallbacks #define BLECharacteristicCallbacks NimBLECharacteristicCallbacks @@ -19,13 +23,6 @@ #define BLEAdvertising NimBLEAdvertising #define BLEServer NimBLEServer -#else - -#include "BLECharacteristic.h" -#include "BLEHIDDevice.h" - -#endif // USE_NIMBLE - #include "Bad_Usb_Lib.h" #include "Print.h" #include "keys.h" @@ -96,13 +93,41 @@ class BleKeyboard : public BLEServerCallbacks, public BLECharacteristicCallbacks protected: bool _randUUID = false; - virtual void onStarted(BLEServer *pServer) {}; +#ifndef NIMBLE_V2_PLUS + virtual void onAuthenticationComplete(ble_gap_conn_desc *desc); virtual void onConnect(BLEServer *pServer) override; virtual void onDisconnect(BLEServer *pServer) override; - virtual void onAuthenticationComplete(ble_gap_conn_desc *desc); virtual void onWrite(BLECharacteristic *me) override; virtual void onSubscribe(NimBLECharacteristic *pCharacteristic, ble_gap_conn_desc *desc, uint16_t subValue) override; +#else + + class ServerCallbacks : public NimBLEServerCallbacks { + private: + BleKeyboard *parent; + + public: + ServerCallbacks(BleKeyboard *kb) : parent(kb) {} + void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo) override; + void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) override; + void onAuthenticationComplete(NimBLEConnInfo &connInfo) override; + }; + class CharacteristicCallbacks : public NimBLECharacteristicCallbacks { + private: + BleKeyboard *parent; + + public: + CharacteristicCallbacks(BleKeyboard *kb) : parent(kb) {} + void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) override; + void onSubscribe( + NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo, uint16_t subValue + ) override; + }; + uint8_t getSubscribedCount() { return m_subCount; } + +private: + uint8_t m_subCount{0}; +#endif }; #endif // CONFIG_BT_ENABLED diff --git a/lib/HAL/SD.h b/lib/HAL/SD.h index ff0ffd52f..0b0334bfd 100644 --- a/lib/HAL/SD.h +++ b/lib/HAL/SD.h @@ -23,7 +23,7 @@ #else #include -#include +#include #endif namespace fs { @@ -48,6 +48,7 @@ class SDFS : public FS { static bool sdmmcDetachBus(void *bus_pointer); public: + SDFS(FSImplPtr impl); bool setPins(int clk, int cmd, int d0); bool setPins(int clk, int cmd, int d0, int d1, int d2, int d3); #ifdef SOC_SDMMC_IO_POWER_EXTERNAL @@ -57,20 +58,28 @@ class SDFS : public FS { const char *mountpoint = "/sdcard", bool mode1bit = false, bool format_if_mount_failed = false, int sdmmc_frequency = BOARD_MAX_SDMMC_FREQ, uint8_t maxOpenFiles = 5 ); - + bool begin(int SS) { return begin(); }; +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) + void end(); + sdcard_type_t cardType(); + uint64_t cardSize(); + uint64_t totalBytes(); + uint64_t usedBytes(); + size_t sectorSize(); + size_t numSectors(); + bool readRAW(uint8_t *buffer, uint32_t sector); + bool writeRAW(uint8_t *buffer, uint32_t sector); +#endif #else protected: uint8_t _pdrv; public: + SDFS(FSImplPtr impl); bool begin( uint8_t ssPin = SS, SPIClass &spi = SPI, uint32_t frequency = 4000000, const char *mountpoint = "/sd", uint8_t max_files = 5, bool format_if_empty = false ); -#endif - - SDFS(FSImplPtr impl); - void end(); sdcard_type_t cardType(); uint64_t cardSize(); @@ -80,6 +89,7 @@ class SDFS : public FS { uint64_t usedBytes(); bool readRAW(uint8_t *buffer, uint32_t sector); bool writeRAW(uint8_t *buffer, uint32_t sector); +#endif }; } // namespace fs diff --git a/lib/HAL/sd_card/SD.cpp b/lib/HAL/sd_card/SD.cpp index e6dcf2946..bfca00fe3 100644 --- a/lib/HAL/sd_card/SD.cpp +++ b/lib/HAL/sd_card/SD.cpp @@ -1,5 +1,5 @@ #ifndef USE_SD_MMC -#include "SD.h" +#include "../SD.h" #include "FS.h" #include "ff.h" // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD @@ -16,7 +16,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "sd_diskio.h" +#include "sd_diskio2.h" #include "vfs_api.h" using namespace fs; diff --git a/lib/HAL/sd_card/SD_MMC.cpp b/lib/HAL/sd_card/SD_MMC.cpp index 57b76aef8..aab4b2905 100644 --- a/lib/HAL/sd_card/SD_MMC.cpp +++ b/lib/HAL/sd_card/SD_MMC.cpp @@ -1,7 +1,389 @@ #ifdef USE_SD_MMC +#include +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) #include "../SD.h" -#include "FS.h" +#include "io_pin_remap.h" +#include "pins_arduino.h" +#ifdef SOC_SDMMC_HOST_SUPPORTED +#include "vfs_api.h" + +#include "diskio.h" +#include "diskio_sdmmc.h" +#include "driver/sdmmc_defs.h" +#include "driver/sdmmc_host.h" +#include "esp32-hal-periman.h" +#include "esp_vfs_fat.h" #include "ff.h" +#include "sdmmc_cmd.h" +#include "soc/sdmmc_pins.h" +#include + +#if SOC_SDMMC_IO_POWER_EXTERNAL +#include "sd_pwr_ctrl_by_on_chip_ldo.h" +#endif + +using namespace fs; + +SDFS::SDFS(FSImplPtr impl) : FS(impl), _card(nullptr) { +#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && defined(BOARD_HAS_SDMMC) && !defined(CONFIG_IDF_TARGET_ESP32P4) + _pin_clk = SDMMC_CLK; + _pin_cmd = SDMMC_CMD; + _pin_d0 = SDMMC_D0; +#ifndef BOARD_HAS_1BIT_SDMMC + _pin_d1 = SDMMC_D1; + _pin_d2 = SDMMC_D2; + _pin_d3 = SDMMC_D3; +#endif // BOARD_HAS_1BIT_SDMMC + +#elif defined(SOC_SDMMC_USE_IOMUX) && defined(CONFIG_IDF_TARGET_ESP32) + _pin_clk = SDMMC_SLOT1_IOMUX_PIN_NUM_CLK; + _pin_cmd = SDMMC_SLOT1_IOMUX_PIN_NUM_CMD; + _pin_d0 = SDMMC_SLOT1_IOMUX_PIN_NUM_D0; +#ifndef BOARD_HAS_1BIT_SDMMC + _pin_d1 = SDMMC_SLOT1_IOMUX_PIN_NUM_D1; + _pin_d2 = SDMMC_SLOT1_IOMUX_PIN_NUM_D2; + _pin_d3 = SDMMC_SLOT1_IOMUX_PIN_NUM_D3; +#endif // BOARD_HAS_1BIT_SDMMC + +// ESP32-P4 can use either IOMUX or GPIO matrix +#elif defined(BOARD_HAS_SDMMC) && defined(CONFIG_IDF_TARGET_ESP32P4) +#if defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0) + _pin_clk = SDMMC_SLOT0_IOMUX_PIN_NUM_CLK; + _pin_cmd = SDMMC_SLOT0_IOMUX_PIN_NUM_CMD; + _pin_d0 = SDMMC_SLOT0_IOMUX_PIN_NUM_D0; +#ifndef BOARD_HAS_1BIT_SDMMC + _pin_d1 = SDMMC_SLOT0_IOMUX_PIN_NUM_D1; + _pin_d2 = SDMMC_SLOT0_IOMUX_PIN_NUM_D2; + _pin_d3 = SDMMC_SLOT0_IOMUX_PIN_NUM_D3; +#endif // BOARD_HAS_1BIT_SDMMC +#else + _pin_clk = SDMMC_CLK; + _pin_cmd = SDMMC_CMD; + _pin_d0 = SDMMC_D0; +#ifndef BOARD_HAS_1BIT_SDMMC + _pin_d1 = SDMMC_D1; + _pin_d2 = SDMMC_D2; + _pin_d3 = SDMMC_D3; +#endif // BOARD_HAS_1BIT_SDMMC +#endif // BOARD_SDMMC_SLOT_NO +#endif +#if defined(SOC_SDMMC_IO_POWER_EXTERNAL) && defined(BOARD_SDMMC_POWER_CHANNEL) + _power_channel = BOARD_SDMMC_POWER_CHANNEL; +#endif +} + +bool SDFS::sdmmcDetachBus(void *bus_pointer) { + SDFS *bus = (SDFS *)bus_pointer; + if (bus->_card) { bus->end(); } + return true; +} + +bool SDFS::setPins(int clk, int cmd, int d0) { + return setPins(clk, cmd, d0, GPIO_NUM_NC, GPIO_NUM_NC, GPIO_NUM_NC); +} + +bool SDFS::setPins(int clk, int cmd, int d0, int d1, int d2, int d3) { + if (_card != nullptr) { + log_e("SD_MMC.setPins must be called before SD_MMC.begin"); + return false; + } + + // map logical pins to GPIO numbers + clk = digitalPinToGPIONumber(clk); + cmd = digitalPinToGPIONumber(cmd); + d0 = digitalPinToGPIONumber(d0); + d1 = digitalPinToGPIONumber(d1); + d2 = digitalPinToGPIONumber(d2); + d3 = digitalPinToGPIONumber(d3); + +#if defined(SOC_SDMMC_USE_GPIO_MATRIX) && !defined(CONFIG_IDF_TARGET_ESP32P4) + // SoC supports SDMMC pin configuration via GPIO matrix. Save the pins for later use in SDFS::begin. + _pin_clk = (int8_t)clk; + _pin_cmd = (int8_t)cmd; + _pin_d0 = (int8_t)d0; + _pin_d1 = (int8_t)d1; + _pin_d2 = (int8_t)d2; + _pin_d3 = (int8_t)d3; + return true; +#elif CONFIG_IDF_TARGET_ESP32 + // ESP32 doesn't support SDMMC pin configuration via GPIO matrix. + // Since SDFS::begin hardcodes the usage of slot 1, only check if + // the pins match slot 1 pins. + bool pins_ok = (clk == (int)SDMMC_SLOT1_IOMUX_PIN_NUM_CLK) && + (cmd == (int)SDMMC_SLOT1_IOMUX_PIN_NUM_CMD) && (d0 == (int)SDMMC_SLOT1_IOMUX_PIN_NUM_D0) && + (((d1 == -1) && (d2 == -1) && (d3 == -1)) || + ((d1 == (int)SDMMC_SLOT1_IOMUX_PIN_NUM_D1) && (d2 == (int)SDMMC_SLOT1_IOMUX_PIN_NUM_D2) && + (d3 == (int)SDMMC_SLOT1_IOMUX_PIN_NUM_D3))); + if (!pins_ok) { + log_e("SDFS: specified pins are not supported by this chip."); + return false; + } + return true; +#elif defined(CONFIG_IDF_TARGET_ESP32P4) +#if defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0) + // ESP32-P4 can use either IOMUX or GPIO matrix + bool pins_ok = (clk == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_CLK) && + (cmd == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_CMD) && (d0 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D0) && + (((d1 == -1) && (d2 == -1) && (d3 == -1)) || + ((d1 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D1) && (d2 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D2) && + (d3 == (int)SDMMC_SLOT0_IOMUX_PIN_NUM_D3))); + if (!pins_ok) { + log_e("SDFS: specified pins are not supported when using IOMUX (SDMMC SLOT 0)."); + return false; + } + return true; +#else + _pin_clk = (int8_t)clk; + _pin_cmd = (int8_t)cmd; + _pin_d0 = (int8_t)d0; + _pin_d1 = (int8_t)d1; + _pin_d2 = (int8_t)d2; + _pin_d3 = (int8_t)d3; + return true; +#endif +#else +#error SoC not supported +#endif +} + +#ifdef SOC_SDMMC_IO_POWER_EXTERNAL +bool SDFS::setPowerChannel(int power_channel) { + if (_card != nullptr) { + log_e("SD_MMC.setPowerChannel must be called before SD_MMC.begin"); + return false; + } + _power_channel = power_channel; + return true; +} +#endif + +bool SDFS::begin( + const char *mountpoint, bool mode1bit, bool format_if_mount_failed, int sdmmc_frequency, + uint8_t maxOpenFiles +) { + if (_card) { return true; } + perimanSetBusDeinit(ESP32_BUS_TYPE_SDMMC_CLK, SDFS::sdmmcDetachBus); + perimanSetBusDeinit(ESP32_BUS_TYPE_SDMMC_CMD, SDFS::sdmmcDetachBus); + perimanSetBusDeinit(ESP32_BUS_TYPE_SDMMC_D0, SDFS::sdmmcDetachBus); + if (!mode1bit) { + perimanSetBusDeinit(ESP32_BUS_TYPE_SDMMC_D1, SDFS::sdmmcDetachBus); + perimanSetBusDeinit(ESP32_BUS_TYPE_SDMMC_D2, SDFS::sdmmcDetachBus); + perimanSetBusDeinit(ESP32_BUS_TYPE_SDMMC_D3, SDFS::sdmmcDetachBus); + } + // mount + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); +#if (defined(SOC_SDMMC_USE_GPIO_MATRIX) && !defined(CONFIG_IDF_TARGET_ESP32P4)) || \ + (defined(CONFIG_IDF_TARGET_ESP32P4) && \ + ((defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 1)) || !defined(BOARD_HAS_SDMMC))) + log_d( + "pin_cmd: %d, pin_clk: %d, pin_d0: %d, pin_d1: %d, pin_d2: %d, pin_d3: %d", + _pin_cmd, + _pin_clk, + _pin_d0, + _pin_d1, + _pin_d2, + _pin_d3 + ); + // SoC supports SDMMC pin configuration via GPIO matrix. + // Check that the pins have been set either in the constructor or setPins function. + if (_pin_cmd == -1 || _pin_clk == -1 || _pin_d0 == -1 || + (!mode1bit && (_pin_d1 == -1 || _pin_d2 == -1 || _pin_d3 == -1))) { + log_e("SDFS: some SD pins are not set"); + return false; + } + + slot_config.clk = (gpio_num_t)_pin_clk; + slot_config.cmd = (gpio_num_t)_pin_cmd; + slot_config.d0 = (gpio_num_t)_pin_d0; + slot_config.d1 = (gpio_num_t)_pin_d1; + slot_config.d2 = (gpio_num_t)_pin_d2; + slot_config.d3 = (gpio_num_t)_pin_d3; + slot_config.width = 4; +#endif // SOC_SDMMC_USE_GPIO_MATRIX + + if (!perimanClearPinBus(_pin_cmd)) { return false; } + if (!perimanClearPinBus(_pin_clk)) { return false; } + if (!perimanClearPinBus(_pin_d0)) { return false; } + if (!mode1bit) { + if (!perimanClearPinBus(_pin_d1)) { return false; } + if (!perimanClearPinBus(_pin_d2)) { return false; } + if (!perimanClearPinBus(_pin_d3)) { return false; } + } + + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + host.flags = SDMMC_HOST_FLAG_4BIT; +#if defined(CONFIG_IDF_TARGET_ESP32P4) && defined(BOARD_SDMMC_SLOT) && (BOARD_SDMMC_SLOT == 0) + host.slot = SDMMC_HOST_SLOT_0; + // reconfigure slot_config to remove all pins in order to use IO_MUX + slot_config = { + .cd = SDMMC_SLOT_NO_CD, + .wp = SDMMC_SLOT_NO_WP, + .width = 4, + .flags = 0, + }; +#else + host.slot = SDMMC_HOST_SLOT_1; +#endif + host.max_freq_khz = sdmmc_frequency; +#ifdef BOARD_HAS_1BIT_SDMMC + mode1bit = true; +#endif + if (mode1bit) { + host.flags = SDMMC_HOST_FLAG_1BIT; // use 1-line SD mode + slot_config.width = 1; + } + _mode1bit = mode1bit; + +#ifdef SOC_SDMMC_IO_POWER_EXTERNAL + if (_power_channel == -1) { + log_i("On-chip power channel specified, use external power for SDMMC"); + } else { + sd_pwr_ctrl_ldo_config_t ldo_config = { + .ldo_chan_id = _power_channel, + }; + sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL; + + if (sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle) != ESP_OK) { + log_e("Failed to create a new on-chip LDO power control driver"); + return false; + } + host.pwr_ctrl_handle = pwr_ctrl_handle; + } +#endif + +#if defined(BOARD_SDMMC_POWER_PIN) +#ifndef BOARD_SDMMC_POWER_ON_LEVEL +#error "BOARD_SDMMC_POWER_ON_LEVEL not defined, please define it in pins_arduino.h" +#endif + pinMode(BOARD_SDMMC_POWER_PIN, OUTPUT); + digitalWrite(BOARD_SDMMC_POWER_PIN, !BOARD_SDMMC_POWER_ON_LEVEL); + delay(200); + digitalWrite(BOARD_SDMMC_POWER_PIN, BOARD_SDMMC_POWER_ON_LEVEL); + perimanSetPinBusExtraType(BOARD_SDMMC_POWER_PIN, "SDMMC_POWER"); +#endif + + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = format_if_mount_failed, + .max_files = maxOpenFiles, + .allocation_unit_size = 0, + .disk_status_check_enable = false, + .use_one_fat = false + }; + + esp_err_t ret = esp_vfs_fat_sdmmc_mount(mountpoint, &host, &slot_config, &mount_config, &_card); + if (ret != ESP_OK) { + if (ret == ESP_FAIL) { + log_e( + "Failed to mount filesystem. If you want the card to be formatted, set " + "format_if_mount_failed = true." + ); + } else if (ret == ESP_ERR_INVALID_STATE) { + _impl->mountpoint(mountpoint); + log_w("SD Already mounted"); + return true; + } else { + log_e( + "Failed to initialize the card (0x%x). Make sure SD card lines have pull-up resistors in " + "place.", + ret + ); + } + _card = NULL; + return false; + } + _impl->mountpoint(mountpoint); + _pdrv = ff_diskio_get_pdrv_card(_card); + + if (!perimanSetPinBus(_pin_cmd, ESP32_BUS_TYPE_SDMMC_CMD, (void *)(this), -1, -1)) { goto err; } + if (!perimanSetPinBus(_pin_clk, ESP32_BUS_TYPE_SDMMC_CLK, (void *)(this), -1, -1)) { goto err; } + if (!perimanSetPinBus(_pin_d0, ESP32_BUS_TYPE_SDMMC_D0, (void *)(this), -1, -1)) { goto err; } + if (!mode1bit) { + if (!perimanSetPinBus(_pin_d1, ESP32_BUS_TYPE_SDMMC_D1, (void *)(this), -1, -1)) { goto err; } + if (!perimanSetPinBus(_pin_d2, ESP32_BUS_TYPE_SDMMC_D2, (void *)(this), -1, -1)) { goto err; } + if (!perimanSetPinBus(_pin_d3, ESP32_BUS_TYPE_SDMMC_D3, (void *)(this), -1, -1)) { goto err; } + } + return true; + +err: + log_e("Failed to set all pins bus to SDMMC"); + SDFS::sdmmcDetachBus((void *)(this)); + return false; +} + +void SDFS::end() { + if (_card) { + esp_vfs_fat_sdcard_unmount(_impl->mountpoint(), _card); + _impl->mountpoint(NULL); + _card = NULL; + perimanClearPinBus(_pin_cmd); + perimanClearPinBus(_pin_clk); + perimanClearPinBus(_pin_d0); + if (!_mode1bit) { + perimanClearPinBus(_pin_d1); + perimanClearPinBus(_pin_d2); + perimanClearPinBus(_pin_d3); + } +#if defined(BOARD_SDMMC_POWER_PIN) + perimanClearPinBus(BOARD_SDMMC_POWER_PIN); +#endif + } +} + +sdcard_type_t SDFS::cardType() { + if (!_card) { return CARD_NONE; } + return (_card->ocr & SD_OCR_SDHC_CAP) ? CARD_SDHC : CARD_SD; +} + +uint64_t SDFS::cardSize() { + if (!_card) { return 0; } + return (uint64_t)_card->csd.capacity * _card->csd.sector_size; +} + +uint64_t SDFS::totalBytes() { + FATFS *fsinfo; + DWORD fre_clust; + if (f_getfree("0:", &fre_clust, &fsinfo) != 0) { return 0; } + uint64_t size = ((uint64_t)(fsinfo->csize)) * (fsinfo->n_fatent - 2) +#if _MAX_SS != 512 + * (fsinfo->ssize); +#else + * 512; +#endif + return size; +} + +uint64_t SDFS::usedBytes() { + FATFS *fsinfo; + DWORD fre_clust; + if (f_getfree("0:", &fre_clust, &fsinfo) != 0) { return 0; } + uint64_t size = ((uint64_t)(fsinfo->csize)) * ((fsinfo->n_fatent - 2) - (fsinfo->free_clst)) +#if _MAX_SS != 512 + * (fsinfo->ssize); +#else + * 512; +#endif + return size; +} + +size_t SDFS::sectorSize() { + if (!_card) { return 0; } + return _card->csd.sector_size; +} + +size_t SDFS::numSectors() { + if (!_card) { return 0; } + return (totalBytes() / _card->csd.sector_size); +} + +bool SDFS::readRAW(uint8_t *buffer, uint32_t sector) { return (disk_read(_pdrv, buffer, sector, 1) == 0); } + +bool SDFS::writeRAW(uint8_t *buffer, uint32_t sector) { return (disk_write(_pdrv, buffer, sector, 1) == 0); } + +SDFS SD = SDFS(FSImplPtr(new VFSImpl())); +#endif /* SOC_SDMMC_HOST_SUPPORTED */ +#else + +#include "../SD.h" // Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +398,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "SD_MMC.h" #include "io_pin_remap.h" #include "pins_arduino.h" #ifdef SOC_SDMMC_HOST_SUPPORTED @@ -211,4 +592,5 @@ bool SDFS::writeRAW(uint8_t *buffer, uint32_t sector) { return false; } SDFS SD = SDFS(FSImplPtr(new VFSImpl())); #endif /* SOC_SDMMC_HOST_SUPPORTED */ +#endif /* ESP-IDF Version check */ #endif diff --git a/lib/HAL/sd_card/sd_diskio.cpp b/lib/HAL/sd_card/sd_diskio.cpp new file mode 100644 index 000000000..1330e070d --- /dev/null +++ b/lib/HAL/sd_card/sd_diskio.cpp @@ -0,0 +1,814 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Disable the automatic pin remapping of the API calls in this file +#define ARDUINO_CORE_BUILD + +#include "sd_diskio2.h" +#include "esp_system.h" +#include "esp32-hal-periman.h" + +extern "C" { +#include "ff.h" +#include "diskio.h" +#if ESP_IDF_VERSION_MAJOR > 3 +#include "diskio_impl.h" +#endif +//#include "esp_vfs.h" +#include "esp_vfs_fat.h" +char CRC7(const char *data, int length); +unsigned short CRC16(const char *data, int length); +} + +typedef enum { + GO_IDLE_STATE = 0, + SEND_OP_COND = 1, + SEND_CID = 2, + SEND_RELATIVE_ADDR = 3, + SEND_SWITCH_FUNC = 6, + SEND_IF_COND = 8, + SEND_CSD = 9, + STOP_TRANSMISSION = 12, + SEND_STATUS = 13, + SET_BLOCKLEN = 16, + READ_BLOCK_SINGLE = 17, + READ_BLOCK_MULTIPLE = 18, + SEND_NUM_WR_BLOCKS = 22, + SET_WR_BLK_ERASE_COUNT = 23, + WRITE_BLOCK_SINGLE = 24, + WRITE_BLOCK_MULTIPLE = 25, + APP_OP_COND = 41, + APP_CLR_CARD_DETECT = 42, + APP_CMD = 55, + READ_OCR = 58, + CRC_ON_OFF = 59 +} ardu_sdcard_command_t; + +typedef struct { + uint8_t ssPin; + SPIClass *spi; + int frequency; + char *base_path; + sdcard_type_t type; + unsigned long sectors; + bool supports_crc; + int status; +} ardu_sdcard_t; + +static ardu_sdcard_t *s_cards[FF_VOLUMES] = {NULL}; + +#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR +const char *fferr2str[] = { + "(0) Succeeded", + "(1) A hard error occurred in the low level disk I/O layer", + "(2) Assertion failed", + "(3) The physical drive cannot work", + "(4) Could not find the file", + "(5) Could not find the path", + "(6) The path name format is invalid", + "(7) Access denied due to prohibited access or directory full", + "(8) Access denied due to prohibited access", + "(9) The file/directory object is invalid", + "(10) The physical drive is write protected", + "(11) The logical drive number is invalid", + "(12) The volume has no work area", + "(13) There is no valid FAT volume", + "(14) The f_mkfs() aborted due to any problem", + "(15) Could not get a grant to access the volume within defined period", + "(16) The operation is rejected according to the file sharing policy", + "(17) LFN working buffer could not be allocated", + "(18) Number of open files > FF_FS_LOCK", + "(19) Given parameter is invalid" +}; +#endif + +/* + * SD SPI + * */ + +bool sdWait(uint8_t pdrv, int timeout) { + char resp; + uint32_t start = millis(); + + do { + resp = s_cards[pdrv]->spi->transfer(0xFF); + } while (resp == 0x00 && (millis() - start) < (unsigned int)timeout); + + if (!resp) { + log_w("Wait Failed"); + } + return (resp > 0x00); +} + +void sdStop(uint8_t pdrv) { + s_cards[pdrv]->spi->write(0xFD); +} + +void sdDeselectCard(uint8_t pdrv) { + ardu_sdcard_t *card = s_cards[pdrv]; + digitalWrite(card->ssPin, HIGH); +} + +bool sdSelectCard(uint8_t pdrv) { + ardu_sdcard_t *card = s_cards[pdrv]; + digitalWrite(card->ssPin, LOW); + bool s = sdWait(pdrv, 500); + if (!s) { + log_e("Select Failed"); + digitalWrite(card->ssPin, HIGH); + return false; + } + return true; +} + +char sdCommand(uint8_t pdrv, char cmd, unsigned int arg, unsigned int *resp) { + char token; + ardu_sdcard_t *card = s_cards[pdrv]; + + for (int f = 0; f < 3; f++) { + if (cmd == SEND_NUM_WR_BLOCKS || cmd == SET_WR_BLK_ERASE_COUNT || cmd == APP_OP_COND || cmd == APP_CLR_CARD_DETECT) { + token = sdCommand(pdrv, APP_CMD, 0, NULL); + sdDeselectCard(pdrv); + if (token > 1) { + break; + } + if (!sdSelectCard(pdrv)) { + token = 0xFF; + break; + } + } + + char cmdPacket[7]; + cmdPacket[0] = cmd | 0x40; + cmdPacket[1] = arg >> 24; + cmdPacket[2] = arg >> 16; + cmdPacket[3] = arg >> 8; + cmdPacket[4] = arg; + if (card->supports_crc || cmd == GO_IDLE_STATE || cmd == SEND_IF_COND) { + cmdPacket[5] = (CRC7(cmdPacket, 5) << 1) | 0x01; + } else { + cmdPacket[5] = 0x01; + } + cmdPacket[6] = 0xFF; + + card->spi->writeBytes((uint8_t *)cmdPacket, (cmd == STOP_TRANSMISSION) ? 7 : 6); + + for (int i = 0; i < 9; i++) { + token = card->spi->transfer(0xFF); + if (!(token & 0x80)) { + break; + } + } + + if (token == 0xFF) { + log_w("no token received"); + sdDeselectCard(pdrv); + delay(100); + sdSelectCard(pdrv); + continue; + } else if (token & 0x08) { + log_w("crc error"); + sdDeselectCard(pdrv); + delay(100); + sdSelectCard(pdrv); + continue; + } else if (token > 1) { + log_w("token error [%u] 0x%x", cmd, token); + break; + } + + if (cmd == SEND_STATUS && resp) { + *resp = card->spi->transfer(0xFF); + } else if ((cmd == SEND_IF_COND || cmd == READ_OCR) && resp) { + *resp = card->spi->transfer32(0xFFFFFFFF); + } + + break; + } + if (token == 0xFF) { + log_e("Card Failed! cmd: 0x%02x", cmd); + card->status = STA_NOINIT; + } + return token; +} + +bool sdReadBytes(uint8_t pdrv, char *buffer, int length) { + char token; + unsigned short crc; + ardu_sdcard_t *card = s_cards[pdrv]; + + uint32_t start = millis(); + do { + token = card->spi->transfer(0xFF); + } while (token == 0xFF && (millis() - start) < 500); + + if (token != 0xFE) { + return false; + } + + card->spi->transferBytes(NULL, (uint8_t *)buffer, length); + crc = card->spi->transfer16(0xFFFF); + return (!card->supports_crc || crc == CRC16(buffer, length)); +} + +char sdWriteBytes(uint8_t pdrv, const char *buffer, char token) { + ardu_sdcard_t *card = s_cards[pdrv]; + unsigned short crc = (card->supports_crc) ? CRC16(buffer, 512) : 0xFFFF; + if (!sdWait(pdrv, 500)) { + return 0; + } + + card->spi->write(token); + card->spi->writeBytes((uint8_t *)buffer, 512); + card->spi->write16(crc); + return (card->spi->transfer(0xFF) & 0x1F); +} + +/* + * SPI SDCARD Communication + * */ + +char sdTransaction(uint8_t pdrv, char cmd, unsigned int arg, unsigned int *resp) { + if (!sdSelectCard(pdrv)) { + return 0xFF; + } + char token = sdCommand(pdrv, cmd, arg, resp); + sdDeselectCard(pdrv); + return token; +} + +bool sdReadSector(uint8_t pdrv, char *buffer, unsigned long long sector) { + for (int f = 0; f < 3; f++) { + if (!sdSelectCard(pdrv)) { + return false; + } + if (!sdCommand(pdrv, READ_BLOCK_SINGLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) { + bool success = sdReadBytes(pdrv, buffer, 512); + sdDeselectCard(pdrv); + if (success) { + return true; + } + } else { + break; + } + } + sdDeselectCard(pdrv); + return false; +} + +bool sdReadSectors(uint8_t pdrv, char *buffer, unsigned long long sector, int count) { + for (int f = 0; f < 3;) { + if (!sdSelectCard(pdrv)) { + return false; + } + + if (!sdCommand(pdrv, READ_BLOCK_MULTIPLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) { + do { + if (!sdReadBytes(pdrv, buffer, 512)) { + f++; + break; + } + + sector++; + buffer += 512; + f = 0; + } while (--count); + + if (sdCommand(pdrv, STOP_TRANSMISSION, 0, NULL)) { + log_e("command failed"); + break; + } + + sdDeselectCard(pdrv); + if (count == 0) { + return true; + } + } else { + break; + } + } + sdDeselectCard(pdrv); + return false; +} + +bool sdWriteSector(uint8_t pdrv, const char *buffer, unsigned long long sector) { + for (int f = 0; f < 3; f++) { + if (!sdSelectCard(pdrv)) { + return false; + } + if (!sdCommand(pdrv, WRITE_BLOCK_SINGLE, (s_cards[pdrv]->type == CARD_SDHC) ? sector : sector << 9, NULL)) { + char token = sdWriteBytes(pdrv, buffer, 0xFE); + sdDeselectCard(pdrv); + + if (token == 0x0A) { + continue; + } else if (token == 0x0C) { + return false; + } + + unsigned int resp; + if (sdTransaction(pdrv, SEND_STATUS, 0, &resp) || resp) { + return false; + } + return true; + } else { + break; + } + } + sdDeselectCard(pdrv); + return false; +} + +bool sdWriteSectors(uint8_t pdrv, const char *buffer, unsigned long long sector, int count) { + char token; + const char *currentBuffer = buffer; + unsigned long long currentSector = sector; + int currentCount = count; + ardu_sdcard_t *card = s_cards[pdrv]; + + for (int f = 0; f < 3;) { + if (card->type != CARD_MMC) { + if (sdTransaction(pdrv, SET_WR_BLK_ERASE_COUNT, currentCount, NULL)) { + return false; + } + } + + if (!sdSelectCard(pdrv)) { + return false; + } + + if (!sdCommand(pdrv, WRITE_BLOCK_MULTIPLE, (card->type == CARD_SDHC) ? currentSector : currentSector << 9, NULL)) { + do { + token = sdWriteBytes(pdrv, currentBuffer, 0xFC); + if (token != 0x05) { + f++; + break; + } + currentBuffer += 512; + f = 0; + } while (--currentCount); + + if (!sdWait(pdrv, 500)) { + break; + } + + if (currentCount == 0) { + sdStop(pdrv); + sdDeselectCard(pdrv); + + unsigned int resp; + if (sdTransaction(pdrv, SEND_STATUS, 0, &resp) || resp) { + return false; + } + return true; + } else { + if (sdCommand(pdrv, STOP_TRANSMISSION, 0, NULL)) { + break; + } + + if (token == 0x0A) { + sdDeselectCard(pdrv); + unsigned int writtenBlocks = 0; + if (card->type != CARD_MMC && sdSelectCard(pdrv)) { + if (!sdCommand(pdrv, SEND_NUM_WR_BLOCKS, 0, NULL)) { + char acmdData[4]; + if (sdReadBytes(pdrv, acmdData, 4)) { + writtenBlocks = acmdData[0] << 24; + writtenBlocks |= acmdData[1] << 16; + writtenBlocks |= acmdData[2] << 8; + writtenBlocks |= acmdData[3]; + } + } + sdDeselectCard(pdrv); + } + currentBuffer = buffer + (writtenBlocks << 9); + currentSector = sector + writtenBlocks; + currentCount = count - writtenBlocks; + continue; + } else { + break; + } + } + } else { + break; + } + } + sdDeselectCard(pdrv); + return false; +} + +unsigned long sdGetSectorsCount(uint8_t pdrv) { + for (int f = 0; f < 3; f++) { + if (!sdSelectCard(pdrv)) { + return 0; + } + + if (!sdCommand(pdrv, SEND_CSD, 0, NULL)) { + char csd[16]; + bool success = sdReadBytes(pdrv, csd, 16); + sdDeselectCard(pdrv); + if (success) { + if ((csd[0] >> 6) == 0x01) { + unsigned long size = (((unsigned long)(csd[7] & 0x3F) << 16) | ((unsigned long)csd[8] << 8) | csd[9]) + 1; + return size << 10; + } + unsigned long size = (((unsigned long)(csd[6] & 0x03) << 10) | ((unsigned long)csd[7] << 2) | ((csd[8] & 0xC0) >> 6)) + 1; + size <<= ((((csd[9] & 0x03) << 1) | ((csd[10] & 0x80) >> 7)) + 2); + size <<= (csd[5] & 0x0F); + return size >> 9; + } + } else { + break; + } + } + + sdDeselectCard(pdrv); + return 0; +} + +namespace { + +struct AcquireSPI { + ardu_sdcard_t *card; + explicit AcquireSPI(ardu_sdcard_t *card) : card(card) { + card->spi->beginTransaction(SPISettings(card->frequency, MSBFIRST, SPI_MODE0)); + } + AcquireSPI(ardu_sdcard_t *card, int frequency) : card(card) { + card->spi->beginTransaction(SPISettings(frequency, MSBFIRST, SPI_MODE0)); + } + ~AcquireSPI() { + card->spi->endTransaction(); + } + +private: + AcquireSPI(AcquireSPI const &); + AcquireSPI &operator=(AcquireSPI const &); +}; + +} // namespace + +/* + * FATFS API + * */ + +DSTATUS ff_sd_initialize(uint8_t pdrv) { + char token; + unsigned int resp; + unsigned int start; + ardu_sdcard_t *card = s_cards[pdrv]; + + if (!(card->status & STA_NOINIT)) { + return card->status; + } + + AcquireSPI card_locked(card, 400000); + + digitalWrite(card->ssPin, HIGH); + for (uint8_t i = 0; i < 20; i++) { + card->spi->transfer(0XFF); + } + + // Fix mount issue - sdWait fail ignored before command GO_IDLE_STATE + digitalWrite(card->ssPin, LOW); + if (!sdWait(pdrv, 500)) { + log_w("sdWait fail ignored, card initialize continues"); + } + if (sdCommand(pdrv, GO_IDLE_STATE, 0, NULL) != 1) { + sdDeselectCard(pdrv); + log_w("GO_IDLE_STATE failed"); + goto unknown_card; + } + sdDeselectCard(pdrv); + + token = sdTransaction(pdrv, CRC_ON_OFF, 1, NULL); + if (token == 0x5) { + //old card maybe + card->supports_crc = false; + } else if (token != 1) { + log_w("CRC_ON_OFF failed: %u", token); + goto unknown_card; + } + + if (sdTransaction(pdrv, SEND_IF_COND, 0x1AA, &resp) == 1) { + if ((resp & 0xFFF) != 0x1AA) { + log_w("SEND_IF_COND failed: %03X", resp & 0xFFF); + goto unknown_card; + } + + if (sdTransaction(pdrv, READ_OCR, 0, &resp) != 1 || !(resp & (1 << 20))) { + log_w("READ_OCR failed: %X", resp); + goto unknown_card; + } + + start = millis(); + do { + token = sdTransaction(pdrv, APP_OP_COND, 0x40100000, NULL); + } while (token == 1 && (millis() - start) < 1000); + + if (token) { + log_w("APP_OP_COND failed: %u", token); + goto unknown_card; + } + + if (!sdTransaction(pdrv, READ_OCR, 0, &resp)) { + if (resp & (1 << 30)) { + card->type = CARD_SDHC; + } else { + card->type = CARD_SD; + } + } else { + log_w("READ_OCR failed: %X", resp); + goto unknown_card; + } + } else { + if (sdTransaction(pdrv, READ_OCR, 0, &resp) != 1 || !(resp & (1 << 20))) { + log_w("READ_OCR failed: %X", resp); + goto unknown_card; + } + + start = millis(); + do { + token = sdTransaction(pdrv, APP_OP_COND, 0x100000, NULL); + } while (token == 0x01 && (millis() - start) < 1000); + + if (!token) { + card->type = CARD_SD; + } else { + start = millis(); + do { + token = sdTransaction(pdrv, SEND_OP_COND, 0x100000, NULL); + } while (token != 0x00 && (millis() - start) < 1000); + + if (token == 0x00) { + card->type = CARD_MMC; + } else { + log_w("SEND_OP_COND failed: %u", token); + goto unknown_card; + } + } + } + + if (card->type != CARD_MMC) { + if (sdTransaction(pdrv, APP_CLR_CARD_DETECT, 0, NULL)) { + log_w("APP_CLR_CARD_DETECT failed"); + goto unknown_card; + } + } + + if (card->type != CARD_SDHC) { + if (sdTransaction(pdrv, SET_BLOCKLEN, 512, NULL) != 0x00) { + log_w("SET_BLOCKLEN failed"); + goto unknown_card; + } + } + + card->sectors = sdGetSectorsCount(pdrv); + + if (card->frequency > 25000000) { + card->frequency = 25000000; + } + + card->status &= ~STA_NOINIT; + return card->status; + +unknown_card: + card->type = CARD_UNKNOWN; + return card->status; +} + +DSTATUS ff_sd_status(uint8_t pdrv) { + ardu_sdcard_t *card = s_cards[pdrv]; + AcquireSPI lock(card); + + if (sdTransaction(pdrv, SEND_STATUS, 0, NULL)) { + log_e("Check status failed"); + return STA_NOINIT; + } + return s_cards[pdrv]->status; +} + +DRESULT ff_sd_read(uint8_t pdrv, uint8_t *buffer, DWORD sector, UINT count) { + ardu_sdcard_t *card = s_cards[pdrv]; + if (card->status & STA_NOINIT) { + return RES_NOTRDY; + } + DRESULT res = RES_OK; + + AcquireSPI lock(card); + + if (count > 1) { + res = sdReadSectors(pdrv, (char *)buffer, sector, count) ? RES_OK : RES_ERROR; + } else { + res = sdReadSector(pdrv, (char *)buffer, sector) ? RES_OK : RES_ERROR; + } + return res; +} + +DRESULT ff_sd_write(uint8_t pdrv, const uint8_t *buffer, DWORD sector, UINT count) { + ardu_sdcard_t *card = s_cards[pdrv]; + if (card->status & STA_NOINIT) { + return RES_NOTRDY; + } + + if (card->status & STA_PROTECT) { + return RES_WRPRT; + } + DRESULT res = RES_OK; + + AcquireSPI lock(card); + + if (count > 1) { + res = sdWriteSectors(pdrv, (const char *)buffer, sector, count) ? RES_OK : RES_ERROR; + } else { + res = sdWriteSector(pdrv, (const char *)buffer, sector) ? RES_OK : RES_ERROR; + } + return res; +} + +DRESULT ff_sd_ioctl(uint8_t pdrv, uint8_t cmd, void *buff) { + switch (cmd) { + case CTRL_SYNC: + { + AcquireSPI lock(s_cards[pdrv]); + if (sdSelectCard(pdrv)) { + sdDeselectCard(pdrv); + return RES_OK; + } + } + return RES_ERROR; + case GET_SECTOR_COUNT: *((unsigned long *)buff) = s_cards[pdrv]->sectors; return RES_OK; + case GET_SECTOR_SIZE: *((WORD *)buff) = 512; return RES_OK; + case GET_BLOCK_SIZE: *((uint32_t *)buff) = 1; return RES_OK; + } + return RES_PARERR; +} + +bool sd_read_raw(uint8_t pdrv, uint8_t *buffer, DWORD sector) { + return ff_sd_read(pdrv, buffer, sector, 1) == ESP_OK; +} + +bool sd_write_raw(uint8_t pdrv, uint8_t *buffer, DWORD sector) { + return ff_sd_write(pdrv, buffer, sector, 1) == ESP_OK; +} + +/* + * Public methods + * */ + +uint8_t sdcard_uninit(uint8_t pdrv) { + ardu_sdcard_t *card = s_cards[pdrv]; + if (pdrv >= FF_VOLUMES || card == NULL) { + return 1; + } + { + AcquireSPI lock(card); + sdTransaction(pdrv, GO_IDLE_STATE, 0, NULL); + } // lock is destructed here + ff_diskio_register(pdrv, NULL); + s_cards[pdrv] = NULL; + esp_err_t err = ESP_OK; + if (card->base_path) { + err = esp_vfs_fat_unregister_path(card->base_path); + free(card->base_path); + } + free(card); + return err; +} + +uint8_t sdcard_init(uint8_t cs, SPIClass *spi, int hz) { + + uint8_t pdrv = 0xFF; + if (ff_diskio_get_drive(&pdrv) != ESP_OK || pdrv == 0xFF) { + return pdrv; + } + + ardu_sdcard_t *card = (ardu_sdcard_t *)malloc(sizeof(ardu_sdcard_t)); + if (!card) { + return 0xFF; + } + + card->base_path = NULL; + card->frequency = hz; + card->spi = spi; + card->ssPin = digitalPinToGPIONumber(cs); + + card->supports_crc = true; + card->type = CARD_NONE; + card->status = STA_NOINIT; + + pinMode(card->ssPin, OUTPUT); + digitalWrite(card->ssPin, HIGH); + perimanSetPinBusExtraType(card->ssPin, "SD_SS"); + + s_cards[pdrv] = card; + + static const ff_diskio_impl_t sd_impl = { + .init = &ff_sd_initialize, .status = &ff_sd_status, .read = &ff_sd_read, .write = &ff_sd_write, .ioctl = &ff_sd_ioctl + }; + ff_diskio_register(pdrv, &sd_impl); + + return pdrv; +} + +uint8_t sdcard_unmount(uint8_t pdrv) { + ardu_sdcard_t *card = s_cards[pdrv]; + if (pdrv >= FF_VOLUMES || card == NULL) { + return 1; + } + card->status |= STA_NOINIT; + card->type = CARD_NONE; + + char drv[3] = {(char)('0' + pdrv), ':', 0}; + f_mount(NULL, drv, 0); + return 0; +} + +bool sdcard_mount(uint8_t pdrv, const char *path, uint8_t max_files, bool format_if_empty) { + ardu_sdcard_t *card = s_cards[pdrv]; + if (pdrv >= FF_VOLUMES || card == NULL) { + return false; + } + + if (card->base_path) { + free(card->base_path); + } + card->base_path = strdup(path); + + FATFS *fs; + char drv[3] = {(char)('0' + pdrv), ':', 0}; + esp_err_t err = esp_vfs_fat_register(path, drv, max_files, &fs); + if (err == ESP_ERR_INVALID_STATE) { + log_e("esp_vfs_fat_register failed 0x(%x): SD is registered.", err); + return false; + } else if (err != ESP_OK) { + log_e("esp_vfs_fat_register failed 0x(%x)", err); + return false; + } + + FRESULT res = f_mount(fs, drv, 1); + if (res != FR_OK) { + log_e("f_mount failed: %s", fferr2str[res]); + if (res == 13 && format_if_empty) { + BYTE *work = (BYTE *)malloc(sizeof(BYTE) * FF_MAX_SS); + if (!work) { + log_e("alloc for f_mkfs failed"); + return false; + } + //FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len); + const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, 0}; + res = f_mkfs(drv, &opt, work, sizeof(BYTE) * FF_MAX_SS); + free(work); + if (res != FR_OK) { + log_e("f_mkfs failed: %s", fferr2str[res]); + esp_vfs_fat_unregister_path(path); + return false; + } + res = f_mount(fs, drv, 1); + if (res != FR_OK) { + log_e("f_mount failed: %s", fferr2str[res]); + esp_vfs_fat_unregister_path(path); + return false; + } + } else { + esp_vfs_fat_unregister_path(path); + return false; + } + } + AcquireSPI lock(card); + card->sectors = sdGetSectorsCount(pdrv); + return true; +} + +uint32_t sdcard_num_sectors(uint8_t pdrv) { + ardu_sdcard_t *card = s_cards[pdrv]; + if (pdrv >= FF_VOLUMES || card == NULL) { + return 0; + } + return card->sectors; +} + +uint32_t sdcard_sector_size(uint8_t pdrv) { + if (pdrv >= FF_VOLUMES || s_cards[pdrv] == NULL) { + return 0; + } + return 512; +} + +sdcard_type_t sdcard_type(uint8_t pdrv) { + ardu_sdcard_t *card = s_cards[pdrv]; + if (pdrv >= FF_VOLUMES || card == NULL) { + return CARD_NONE; + } + return card->type; +} diff --git a/lib/HAL/sd_card/sd_diskio_crc.c b/lib/HAL/sd_card/sd_diskio_crc.c new file mode 100644 index 000000000..9c839a583 --- /dev/null +++ b/lib/HAL/sd_card/sd_diskio_crc.c @@ -0,0 +1,61 @@ +/* SD/MMC File System Library + * Copyright (c) 2014 Neil Thiessen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const char m_CRC7Table[] = {0x00, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x3F, 0x48, 0x41, 0x5A, 0x53, 0x6C, 0x65, 0x7E, 0x77, 0x19, 0x10, 0x0B, 0x02, 0x3D, 0x34, + 0x2F, 0x26, 0x51, 0x58, 0x43, 0x4A, 0x75, 0x7C, 0x67, 0x6E, 0x32, 0x3B, 0x20, 0x29, 0x16, 0x1F, 0x04, 0x0D, 0x7A, 0x73, 0x68, 0x61, + 0x5E, 0x57, 0x4C, 0x45, 0x2B, 0x22, 0x39, 0x30, 0x0F, 0x06, 0x1D, 0x14, 0x63, 0x6A, 0x71, 0x78, 0x47, 0x4E, 0x55, 0x5C, 0x64, 0x6D, + 0x76, 0x7F, 0x40, 0x49, 0x52, 0x5B, 0x2C, 0x25, 0x3E, 0x37, 0x08, 0x01, 0x1A, 0x13, 0x7D, 0x74, 0x6F, 0x66, 0x59, 0x50, 0x4B, 0x42, + 0x35, 0x3C, 0x27, 0x2E, 0x11, 0x18, 0x03, 0x0A, 0x56, 0x5F, 0x44, 0x4D, 0x72, 0x7B, 0x60, 0x69, 0x1E, 0x17, 0x0C, 0x05, 0x3A, 0x33, + 0x28, 0x21, 0x4F, 0x46, 0x5D, 0x54, 0x6B, 0x62, 0x79, 0x70, 0x07, 0x0E, 0x15, 0x1C, 0x23, 0x2A, 0x31, 0x38, 0x41, 0x48, 0x53, 0x5A, + 0x65, 0x6C, 0x77, 0x7E, 0x09, 0x00, 0x1B, 0x12, 0x2D, 0x24, 0x3F, 0x36, 0x58, 0x51, 0x4A, 0x43, 0x7C, 0x75, 0x6E, 0x67, 0x10, 0x19, + 0x02, 0x0B, 0x34, 0x3D, 0x26, 0x2F, 0x73, 0x7A, 0x61, 0x68, 0x57, 0x5E, 0x45, 0x4C, 0x3B, 0x32, 0x29, 0x20, 0x1F, 0x16, 0x0D, 0x04, + 0x6A, 0x63, 0x78, 0x71, 0x4E, 0x47, 0x5C, 0x55, 0x22, 0x2B, 0x30, 0x39, 0x06, 0x0F, 0x14, 0x1D, 0x25, 0x2C, 0x37, 0x3E, 0x01, 0x08, + 0x13, 0x1A, 0x6D, 0x64, 0x7F, 0x76, 0x49, 0x40, 0x5B, 0x52, 0x3C, 0x35, 0x2E, 0x27, 0x18, 0x11, 0x0A, 0x03, 0x74, 0x7D, 0x66, 0x6F, + 0x50, 0x59, 0x42, 0x4B, 0x17, 0x1E, 0x05, 0x0C, 0x33, 0x3A, 0x21, 0x28, 0x5F, 0x56, 0x4D, 0x44, 0x7B, 0x72, 0x69, 0x60, 0x0E, 0x07, + 0x1C, 0x15, 0x2A, 0x23, 0x38, 0x31, 0x46, 0x4F, 0x54, 0x5D, 0x62, 0x6B, 0x70, 0x79}; + +char CRC7(const char *data, int length) { + char crc = 0; + for (int i = 0; i < length; i++) { + crc = m_CRC7Table[(crc << 1) ^ data[i]]; + } + return crc; +} + +const unsigned short m_CRC16Table[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, + 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, + 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, + 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, + 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, + 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, + 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, + 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, + 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, + 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, + 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, + 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, + 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; + +unsigned short CRC16(const char *data, int length) { + unsigned short crc = 0; + for (int i = 0; i < length; i++) { + crc = (crc << 8) ^ m_CRC16Table[((crc >> 8) ^ data[i]) & 0x00FF]; + } + return crc; +} diff --git a/lib/HAL/sd_diskio2.h b/lib/HAL/sd_diskio2.h new file mode 100644 index 000000000..762cb6ed1 --- /dev/null +++ b/lib/HAL/sd_diskio2.h @@ -0,0 +1,34 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SD_DISKIO_H_ +#define _SD_DISKIO_H_ + +#include "Arduino.h" +#include "SPI.h" +#include "sd_defines.h" +// #include "diskio.h" + +uint8_t sdcard_init(uint8_t cs, SPIClass *spi, int hz); +uint8_t sdcard_uninit(uint8_t pdrv); + +bool sdcard_mount(uint8_t pdrv, const char *path, uint8_t max_files, bool format_if_empty); +uint8_t sdcard_unmount(uint8_t pdrv); + +sdcard_type_t sdcard_type(uint8_t pdrv); +uint32_t sdcard_num_sectors(uint8_t pdrv); +uint32_t sdcard_sector_size(uint8_t pdrv); +bool sd_read_raw(uint8_t pdrv, uint8_t *buffer, uint32_t sector); +bool sd_write_raw(uint8_t pdrv, uint8_t *buffer, uint32_t sector); + +#endif /* _SD_DISKIO_H_ */ diff --git a/lib/TFT_eSPI/Processors/TFT_eSPI_ESP32.h b/lib/TFT_eSPI/Processors/TFT_eSPI_ESP32.h index ad60e3dd2..ef414afd9 100644 --- a/lib/TFT_eSPI/Processors/TFT_eSPI_ESP32.h +++ b/lib/TFT_eSPI/Processors/TFT_eSPI_ESP32.h @@ -1,6 +1,6 @@ - //////////////////////////////////////////////////// - // TFT_eSPI driver functions for ESP32 processors // - //////////////////////////////////////////////////// +//////////////////////////////////////////////////// +// TFT_eSPI driver functions for ESP32 processors // +//////////////////////////////////////////////////// #ifndef _TFT_eSPI_ESP32H_ #define _TFT_eSPI_ESP32H_ @@ -9,34 +9,38 @@ #define PROCESSOR_ID 0x32 // Include processor specific header -#include "soc/spi_reg.h" #include "driver/spi_master.h" #include "hal/gpio_ll.h" +#include "soc/spi_reg.h" -#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32) - #define CONFIG_IDF_TARGET_ESP32 +#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \ + !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C5) && \ + !defined(CONFIG_IDF_TARGET_ESP32C6) +#define CONFIG_IDF_TARGET_ESP32 #endif // Fix IDF problems with ESP32C3 -#if CONFIG_IDF_TARGET_ESP32C3 - // Fix ESP32C3 IDF bug for missing definition - #ifndef REG_SPI_BASE - #define REG_SPI_BASE(i) (DR_REG_SPI1_BASE + (((i)>1) ? (((i)* 0x1000) + 0x20000) : (((~(i)) & 1)* 0x1000 ))) - #endif +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) +// Fix ESP32C3 IDF bug for missing definition +#ifndef REG_SPI_BASE +#define REG_SPI_BASE(i) \ + (DR_REG_SPI1_BASE + (((i) > 1) ? (((i) * 0x1000) + 0x20000) : (((~(i)) & 1) * 0x1000))) +#endif - // Fix ESP32C3 IDF bug for name change - #ifndef SPI_MOSI_DLEN_REG - #define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x) - #endif +// Fix ESP32C3 IDF bug for name change +#ifndef SPI_MOSI_DLEN_REG +#define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x) +#endif - // Fix ESP32C3 specific register reference - #define out_w1tc out_w1tc.val - #define out_w1ts out_w1ts.val +// Fix ESP32C3 specific register reference +#define out_w1tc out_w1tc.val +#define out_w1ts out_w1ts.val #endif // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled -#if !defined (SUPPORT_TRANSACTIONS) - #define SUPPORT_TRANSACTIONS +#if !defined(SUPPORT_TRANSACTIONS) +#define SUPPORT_TRANSACTIONS #endif /* @@ -63,451 +67,531 @@ SPI3_HOST = 2 // ESP32 specific SPI port selection #ifdef USE_HSPI_PORT - #ifdef CONFIG_IDF_TARGET_ESP32 - #define SPI_PORT HSPI //HSPI is port 2 on ESP32 - #else - #define SPI_PORT 3 //HSPI is port 3 on ESP32 S2 - #endif +#ifdef CONFIG_IDF_TARGET_ESP32 +#define SPI_PORT HSPI // HSPI is port 2 on ESP32 +#else +#define SPI_PORT 3 // HSPI is port 3 on ESP32 S2 +#endif #elif defined(USE_FSPI_PORT) - #define SPI_PORT 2 //FSPI(ESP32 S2) +#define SPI_PORT 2 // FSPI(ESP32 S2) +#else +#ifdef CONFIG_IDF_TARGET_ESP32 +#define SPI_PORT VSPI #else - #ifdef CONFIG_IDF_TARGET_ESP32 - #define SPI_PORT VSPI - #else - #define SPI_PORT 2 //FSPI(ESP32 S2) - #endif +#define SPI_PORT 2 // FSPI(ESP32 S2) +#endif #endif #ifdef RPI_DISPLAY_TYPE - #define CMD_BITS (16-1) +#define CMD_BITS (16 - 1) #else - #define CMD_BITS (8-1) +#define CMD_BITS (8 - 1) #endif // Initialise processor specific SPI functions, used by init() #define INIT_TFT_DATA_BUS // Not used // Define a generic flag for 8-bit parallel -#if defined (ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility - #if !defined (TFT_PARALLEL_8_BIT) - #define TFT_PARALLEL_8_BIT // Generic parallel flag - #endif +#if defined(ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility +#if !defined(TFT_PARALLEL_8_BIT) +#define TFT_PARALLEL_8_BIT // Generic parallel flag +#endif #endif // Ensure ESP32 specific flag is defined for 8-bit parallel -#if defined (TFT_PARALLEL_8_BIT) - #if !defined (ESP32_PARALLEL) - #define ESP32_PARALLEL - #endif +#if defined(TFT_PARALLEL_8_BIT) +#if !defined(ESP32_PARALLEL) +#define ESP32_PARALLEL +#endif #endif // Processor specific code used by SPI bus transaction startWrite and endWrite functions -#if !defined (ESP32_PARALLEL) - #if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2) - #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE - #define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE - #else - #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI - #define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN - #endif +#if !defined(ESP32_PARALLEL) +#if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2) +#define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE +#define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE #else - // Not applicable to parallel bus - #define SET_BUS_WRITE_MODE - #define SET_BUS_READ_MODE +#define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI +#define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN +#endif +#else +// Not applicable to parallel bus +#define SET_BUS_WRITE_MODE +#define SET_BUS_READ_MODE #endif // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions #if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER) - #define ESP32_DMA - // Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions - #define DMA_BUSY_CHECK dmaWait() +#define ESP32_DMA +// Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions +#define DMA_BUSY_CHECK dmaWait() #else - #define DMA_BUSY_CHECK +#define DMA_BUSY_CHECK #endif #if defined(TFT_PARALLEL_8_BIT) - #define SPI_BUSY_CHECK +#define SPI_BUSY_CHECK #else - #define SPI_BUSY_CHECK while (*_spi_cmd&SPI_USR) +#define SPI_BUSY_CHECK while (*_spi_cmd & SPI_USR) #endif // If smooth font is used then it is likely SPIFFS will be needed #ifdef SMOOTH_FONT - // Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts - #define FS_NO_GLOBALS - #include - #include "SPIFFS.h" // ESP32 only - #define FONT_FS_AVAILABLE +// Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts +#define FS_NO_GLOBALS +#include "SPIFFS.h" // ESP32 only +#include +#define FONT_FS_AVAILABLE #endif - //////////////////////////////////////////////////////////////////////////////////////// // Define the DC (TFT Data/Command or Register Select (RS))pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifndef TFT_DC - #define DC_C // No macro allocated so it generates no code - #define DC_D // No macro allocated so it generates no code +#define DC_C // No macro allocated so it generates no code +#define DC_D // No macro allocated so it generates no code #else - #if defined (TFT_PARALLEL_8_BIT) - // TFT_DC, by design, must be in range 0-31 for single register parallel write - #if (TFT_DC >= 0) && (TFT_DC < 32) - #define DC_C GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1ts = (1 << TFT_DC) - #elif (TFT_DC >= 32) - #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC- 32)) - #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC- 32)) - #else - #define DC_C - #define DC_D - #endif - #else - #if (TFT_DC >= 32) - #ifdef RPI_DISPLAY_TYPE // RPi displays need a slower DC change - #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ - GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) - #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ - GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) - #else - #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) - #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) - #endif - #elif (TFT_DC >= 0) - #if defined (RPI_DISPLAY_TYPE) - #if defined (ILI9486_DRIVER) - // RPi ILI9486 display needs a slower DC change - #define DC_C GPIO.out_w1tc = (1 << TFT_DC); \ - GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ - GPIO.out_w1ts = (1 << TFT_DC) - #else - // Other RPi displays need a slower C->D change - #define DC_C GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ - GPIO.out_w1ts = (1 << TFT_DC) - #endif - #else - #define DC_C GPIO.out_w1tc = (1 << TFT_DC)//;GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1ts = (1 << TFT_DC)//;GPIO.out_w1ts = (1 << TFT_DC) - #endif - #else - #define DC_C - #define DC_D - #endif - #endif +#if defined(TFT_PARALLEL_8_BIT) +// TFT_DC, by design, must be in range 0-31 for single register parallel write +#if (TFT_DC >= 0) && (TFT_DC < 32) +#define DC_C GPIO.out_w1tc = (1 << TFT_DC) +#define DC_D GPIO.out_w1ts = (1 << TFT_DC) +#elif (TFT_DC >= 32) +#define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) +#define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) +#else +#define DC_C +#define DC_D +#endif +#else +#if (TFT_DC >= 32) +#ifdef RPI_DISPLAY_TYPE // RPi displays need a slower DC change +#define DC_C \ + GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ + GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) +#define DC_D \ + GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ + GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) +#else +#define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) //;GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) +#define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) //;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) +#endif +#elif (TFT_DC >= 0) +#if defined(RPI_DISPLAY_TYPE) +#if defined(ILI9486_DRIVER) +// RPi ILI9486 display needs a slower DC change +#define DC_C \ + GPIO.out_w1tc = (1 << TFT_DC); \ + GPIO.out_w1tc = (1 << TFT_DC) +#define DC_D \ + GPIO.out_w1tc = (1 << TFT_DC); \ + GPIO.out_w1ts = (1 << TFT_DC) +#else +// Other RPi displays need a slower C->D change +#define DC_C GPIO.out_w1tc = (1 << TFT_DC) +#define DC_D \ + GPIO.out_w1tc = (1 << TFT_DC); \ + GPIO.out_w1ts = (1 << TFT_DC) +#endif +#else +#define DC_C GPIO.out_w1tc = (1 << TFT_DC) //;GPIO.out_w1tc = (1 << TFT_DC) +#define DC_D GPIO.out_w1ts = (1 << TFT_DC) //;GPIO.out_w1ts = (1 << TFT_DC) +#endif +#else +#define DC_C +#define DC_D +#endif +#endif #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the CS (TFT chip select) pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifndef TFT_CS - #define TFT_CS -1 // Keep DMA code happy - #define CS_L // No macro allocated so it generates no code - #define CS_H // No macro allocated so it generates no code +#define TFT_CS -1 // Keep DMA code happy +#define CS_L // No macro allocated so it generates no code +#define CS_H // No macro allocated so it generates no code +#else +#if defined(TFT_PARALLEL_8_BIT) +#if TFT_CS >= 32 +#define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) +#define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) +#elif TFT_CS >= 0 +#define CS_L GPIO.out_w1tc = (1 << TFT_CS) +#define CS_H GPIO.out_w1ts = (1 << TFT_CS) +#else +#define CS_L +#define CS_H +#endif +#else +#if (TFT_CS >= 32) +#ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change +#define CS_L \ + GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ + GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) +#define CS_H \ + GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ + GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) +#else +#define CS_L \ + GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ + GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) +#define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) //;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) +#endif +#elif (TFT_CS >= 0) +#ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change +#define CS_L \ + GPIO.out_w1ts = (1 << TFT_CS); \ + GPIO.out_w1tc = (1 << TFT_CS) +#define CS_H \ + GPIO.out_w1tc = (1 << TFT_CS); \ + GPIO.out_w1ts = (1 << TFT_CS) +#else +#define CS_L \ + GPIO.out_w1tc = (1 << TFT_CS); \ + GPIO.out_w1tc = (1 << TFT_CS) +#define CS_H GPIO.out_w1ts = (1 << TFT_CS) //;GPIO.out_w1ts = (1 << TFT_CS) +#endif #else - #if defined (TFT_PARALLEL_8_BIT) - #if TFT_CS >= 32 - #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) - #elif TFT_CS >= 0 - #define CS_L GPIO.out_w1tc = (1 << TFT_CS) - #define CS_H GPIO.out_w1ts = (1 << TFT_CS) - #else - #define CS_L - #define CS_H - #endif - #else - #if (TFT_CS >= 32) - #ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change - #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ - GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ - GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) - #else - #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) - #endif - #elif (TFT_CS >= 0) - #ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change - #define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) - #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS) - #else - #define CS_L GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) - #define CS_H GPIO.out_w1ts = (1 << TFT_CS)//;GPIO.out_w1ts = (1 << TFT_CS) - #endif - #else - #define CS_L - #define CS_H - #endif - #endif +#define CS_L +#define CS_H +#endif +#endif #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the WR (TFT Write) pin drive code //////////////////////////////////////////////////////////////////////////////////////// -#if defined (TFT_WR) - #if (TFT_WR >= 32) - // Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32 - #define WR_L GPIO.out1_w1tc.val = (1 << (TFT_WR - 32)) - #define WR_H GPIO.out1_w1ts.val = (1 << (TFT_WR - 32)) - #elif (TFT_WR >= 0) - // TFT_WR, for best performance, should be in range 0-31 for single register parallel write - #define WR_L GPIO.out_w1tc = (1 << TFT_WR) - #define WR_H GPIO.out_w1ts = (1 << TFT_WR) - #else - #define WR_L - #define WR_H - #endif +#if defined(TFT_WR) +#if (TFT_WR >= 32) +// Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32 +#define WR_L GPIO.out1_w1tc.val = (1 << (TFT_WR - 32)) +#define WR_H GPIO.out1_w1ts.val = (1 << (TFT_WR - 32)) +#elif (TFT_WR >= 0) +// TFT_WR, for best performance, should be in range 0-31 for single register parallel write +#define WR_L GPIO.out_w1tc = (1 << TFT_WR) +#define WR_H GPIO.out_w1ts = (1 << TFT_WR) #else - #define WR_L - #define WR_H +#define WR_L +#define WR_H +#endif +#else +#define WR_L +#define WR_H #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the touch screen chip select pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifndef TOUCH_CS - #define T_CS_L // No macro allocated so it generates no code - #define T_CS_H // No macro allocated so it generates no code -#else // XPT2046 is slow, so use slower digitalWrite here - #define T_CS_L digitalWrite(TOUCH_CS, LOW) - #define T_CS_H digitalWrite(TOUCH_CS, HIGH) +#define T_CS_L // No macro allocated so it generates no code +#define T_CS_H // No macro allocated so it generates no code +#else // XPT2046 is slow, so use slower digitalWrite here +#define T_CS_L digitalWrite(TOUCH_CS, LOW) +#define T_CS_H digitalWrite(TOUCH_CS, HIGH) #endif //////////////////////////////////////////////////////////////////////////////////////// // Make sure SPI default pins are assigned if not specified by user or set to -1 //////////////////////////////////////////////////////////////////////////////////////// -#if !defined (TFT_PARALLEL_8_BIT) - - #ifdef USE_HSPI_PORT - - #ifndef TFT_MISO - #define TFT_MISO -1 - #endif - - #ifndef TFT_MOSI - #define TFT_MOSI 13 - #endif - #if (TFT_MOSI == -1) - #undef TFT_MOSI - #define TFT_MOSI 13 - #endif - - #ifndef TFT_SCLK - #define TFT_SCLK 14 - #endif - #if (TFT_SCLK == -1) - #undef TFT_SCLK - #define TFT_SCLK 14 - #endif - - #else // VSPI port - - #ifndef TFT_MISO - #define TFT_MISO -1 - #endif - - #ifndef TFT_MOSI - #define TFT_MOSI 23 - #endif - #if (TFT_MOSI == -1) - #undef TFT_MOSI - #define TFT_MOSI 23 - #endif - - #ifndef TFT_SCLK - #define TFT_SCLK 18 - #endif - #if (TFT_SCLK == -1) - #undef TFT_SCLK - #define TFT_SCLK 18 - #endif - - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) - #if (TFT_MISO == -1) - #undef TFT_MISO - #define TFT_MISO TFT_MOSI - #endif - #endif - - #endif +#if !defined(TFT_PARALLEL_8_BIT) + +#ifdef USE_HSPI_PORT + +#ifndef TFT_MISO +#define TFT_MISO -1 +#endif + +#ifndef TFT_MOSI +#define TFT_MOSI 13 +#endif +#if (TFT_MOSI == -1) +#undef TFT_MOSI +#define TFT_MOSI 13 +#endif + +#ifndef TFT_SCLK +#define TFT_SCLK 14 +#endif +#if (TFT_SCLK == -1) +#undef TFT_SCLK +#define TFT_SCLK 14 +#endif + +#else // VSPI port + +#ifndef TFT_MISO +#define TFT_MISO -1 +#endif + +#ifndef TFT_MOSI +#define TFT_MOSI 23 +#endif +#if (TFT_MOSI == -1) +#undef TFT_MOSI +#define TFT_MOSI 23 +#endif + +#ifndef TFT_SCLK +#define TFT_SCLK 18 +#endif +#if (TFT_SCLK == -1) +#undef TFT_SCLK +#define TFT_SCLK 18 +#endif + +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) +#if (TFT_MISO == -1) +#undef TFT_MISO +#define TFT_MISO TFT_MOSI +#endif +#endif + +#endif #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the parallel bus interface chip pin drive code //////////////////////////////////////////////////////////////////////////////////////// -#if defined (TFT_PARALLEL_8_BIT) - - // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically - // can then use e.g. GPIO.out_w1ts = set_mask(0xFF); to set data bus to 0xFF - #define PARALLEL_INIT_TFT_DATA_BUS \ - for (int32_t c = 0; c<256; c++) \ - { \ - xset_mask[c] = 0; \ - if ( c & 0x01 ) xset_mask[c] |= (1 << TFT_D0); \ - if ( c & 0x02 ) xset_mask[c] |= (1 << TFT_D1); \ - if ( c & 0x04 ) xset_mask[c] |= (1 << TFT_D2); \ - if ( c & 0x08 ) xset_mask[c] |= (1 << TFT_D3); \ - if ( c & 0x10 ) xset_mask[c] |= (1 << TFT_D4); \ - if ( c & 0x20 ) xset_mask[c] |= (1 << TFT_D5); \ - if ( c & 0x40 ) xset_mask[c] |= (1 << TFT_D6); \ - if ( c & 0x80 ) xset_mask[c] |= (1 << TFT_D7); \ - } \ - - // Mask for the 8 data bits to set pin directions - #define GPIO_DIR_MASK ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7)) - - #if (TFT_WR >= 32) - // Data bits and the write line are cleared sequentially - #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L - #elif (TFT_WR >= 0) - // Data bits and the write line are cleared to 0 in one step (1.25x faster) - #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR)) - #else - #define GPIO_OUT_CLR_MASK - #endif - - // A lookup table is used to set the different bit patterns, this uses 1kByte of RAM - #define set_mask(C) xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in real time - - // Real-time shifting alternative to above to save 1KByte RAM, 47 fps Sprite rendering test - /*#define set_mask(C) (((C)&0x80)>>7)<>6)<>5)<>4)<>3)<>2)<>1)<>0)<> 8)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x07E0)>> 3)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x001F)<< 3)); WR_H - - // 18-bit color write with swapped bytes - #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) - - #else - - #ifdef PSEUDO_16_BIT - // One write strobe for both bytes - #define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H - #define tft_Write_16S(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H - #else - // Write 16 bits to TFT - #define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H - - // 16-bit write with swapped bytes - #define tft_Write_16S(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H - #endif - - #endif - - // Write 32 bits to TFT - #define tft_Write_32(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 24)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 16)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H - - // Write two concatenated 16-bit values to TFT - #define tft_Write_32C(C,D) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 8)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 0)); WR_H - - // Write 16-bit value twice to TFT - used by drawPixel() - #define tft_Write_32D(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H - - // Read pin - #ifdef TFT_RD - #if (TFT_RD >= 32) - #define RD_L GPIO.out1_w1tc.val = (1 << (TFT_RD - 32)) - #define RD_H GPIO.out1_w1ts.val = (1 << (TFT_RD - 32)) - #elif (TFT_RD >= 0) - #define RD_L GPIO.out_w1tc = (1 << TFT_RD) - //#define RD_L digitalWrite(TFT_WR, LOW) - #define RD_H GPIO.out_w1ts = (1 << TFT_RD) - //#define RD_H digitalWrite(TFT_WR, HIGH) - #else - #define RD_L - #define RD_H - #endif - #else - #define TFT_RD -1 - #define RD_L - #define RD_H - #endif +#if defined(TFT_PARALLEL_8_BIT) + +// Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically +// can then use e.g. GPIO.out_w1ts = set_mask(0xFF); to set data bus to 0xFF +#define PARALLEL_INIT_TFT_DATA_BUS \ + for (int32_t c = 0; c < 256; c++) { \ + xset_mask[c] = 0; \ + if (c & 0x01) xset_mask[c] |= (1 << TFT_D0); \ + if (c & 0x02) xset_mask[c] |= (1 << TFT_D1); \ + if (c & 0x04) xset_mask[c] |= (1 << TFT_D2); \ + if (c & 0x08) xset_mask[c] |= (1 << TFT_D3); \ + if (c & 0x10) xset_mask[c] |= (1 << TFT_D4); \ + if (c & 0x20) xset_mask[c] |= (1 << TFT_D5); \ + if (c & 0x40) xset_mask[c] |= (1 << TFT_D6); \ + if (c & 0x80) xset_mask[c] |= (1 << TFT_D7); \ + } + +// Mask for the 8 data bits to set pin directions +#define GPIO_DIR_MASK \ + ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | \ + (1 << TFT_D6) | (1 << TFT_D7)) + +#if (TFT_WR >= 32) +// Data bits and the write line are cleared sequentially +#define GPIO_OUT_CLR_MASK \ + (GPIO_DIR_MASK); \ + WR_L +#elif (TFT_WR >= 0) +// Data bits and the write line are cleared to 0 in one step (1.25x faster) +#define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR)) +#else +#define GPIO_OUT_CLR_MASK +#endif + +// A lookup table is used to set the different bit patterns, this uses 1kByte of RAM +#define set_mask(C) \ + xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in + // real time + +// Real-time shifting alternative to above to save 1KByte RAM, 47 fps Sprite rendering test +/*#define set_mask(C) (((C)&0x80)>>7)<>6)<>5)<>4)<>3)<>2)<>1)<>0)<> 8)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)(((C) & 0x07E0) >> 3)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)(((C) & 0x001F) << 3)); \ + WR_H + +// 18-bit color write with swapped bytes +#define tft_Write_16S(C) \ + Cswap = ((C) >> 8 | (C) << 8); \ + tft_Write_16(Cswap) + +#else + +#ifdef PSEUDO_16_BIT +// One write strobe for both bytes +#define tft_Write_16(C) \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 0)); \ + WR_H +#define tft_Write_16S(C) \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 8)); \ + WR_H +#else +// Write 16 bits to TFT +#define tft_Write_16(C) \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 8)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 0)); \ + WR_H + +// 16-bit write with swapped bytes +#define tft_Write_16S(C) \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 0)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 8)); \ + WR_H +#endif + +#endif + +// Write 32 bits to TFT +#define tft_Write_32(C) \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 24)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 16)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 8)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 0)); \ + WR_H + +// Write two concatenated 16-bit values to TFT +#define tft_Write_32C(C, D) \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 8)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 0)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((D) >> 8)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((D) >> 0)); \ + WR_H + +// Write 16-bit value twice to TFT - used by drawPixel() +#define tft_Write_32D(C) \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 8)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 0)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 8)); \ + WR_H; \ + GPIO.out_w1tc = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts = set_mask((uint8_t)((C) >> 0)); \ + WR_H + +// Read pin +#ifdef TFT_RD +#if (TFT_RD >= 32) +#define RD_L GPIO.out1_w1tc.val = (1 << (TFT_RD - 32)) +#define RD_H GPIO.out1_w1ts.val = (1 << (TFT_RD - 32)) +#elif (TFT_RD >= 0) +#define RD_L GPIO.out_w1tc = (1 << TFT_RD) +// #define RD_L digitalWrite(TFT_WR, LOW) +#define RD_H GPIO.out_w1ts = (1 << TFT_RD) +// #define RD_H digitalWrite(TFT_WR, HIGH) +#else +#define RD_L +#define RD_H +#endif +#else +#define TFT_RD -1 +#define RD_L +#define RD_H +#endif //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to a SPI ILI948x TFT //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour +#elif defined(SPI_18BIT_DRIVER) // SPI 18-bit colour - // Write 8 bits to TFT - #define tft_Write_8(C) spi.transfer(C) +// Write 8 bits to TFT +#define tft_Write_8(C) spi.transfer(C) - // Convert 16-bit colour to 18-bit and write in 3 bytes - #define tft_Write_16(C) spi.transfer(((C) & 0xF800)>>8); \ - spi.transfer(((C) & 0x07E0)>>3); \ - spi.transfer(((C) & 0x001F)<<3) +// Convert 16-bit colour to 18-bit and write in 3 bytes +#define tft_Write_16(C) \ + spi.transfer(((C) & 0xF800) >> 8); \ + spi.transfer(((C) & 0x07E0) >> 3); \ + spi.transfer(((C) & 0x001F) << 3) - // Future option for transfer without wait - #define tft_Write_16N(C) tft_Write_16(C) +// Future option for transfer without wait +#define tft_Write_16N(C) tft_Write_16(C) - // Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes - #define tft_Write_16S(C) spi.transfer((C) & 0xF8); \ - spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \ - spi.transfer(((C) & 0x1F00)>>5) +// Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes +#define tft_Write_16S(C) \ + spi.transfer((C) & 0xF8); \ + spi.transfer(((C) & 0xE000) >> 11 | ((C) & 0x07) << 5); \ + spi.transfer(((C) & 0x1F00) >> 5) - // Write 32 bits to TFT - #define tft_Write_32(C) spi.write32(C) +// Write 32 bits to TFT +#define tft_Write_32(C) spi.write32(C) - // Write two concatenated 16-bit values to TFT - #define tft_Write_32C(C,D) spi.write32((C)<<16 | (D)) +// Write two concatenated 16-bit values to TFT +#define tft_Write_32C(C, D) spi.write32((C) << 16 | (D)) - // Write 16-bit value twice to TFT - #define tft_Write_32D(C) spi.write32((C)<<16 | (C)) +// Write 16-bit value twice to TFT +#define tft_Write_32D(C) spi.write32((C) << 16 | (C)) //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to an Raspberry Pi TFT //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (RPI_DISPLAY_TYPE) +#elif defined(RPI_DISPLAY_TYPE) - // ESP32 low level SPI writes for 8, 16 and 32-bit values - // to avoid the function call overhead - #define TFT_WRITE_BITS(D, B) \ - WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \ - WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), D); \ - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ - while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); +// ESP32 low level SPI writes for 8, 16 and 32-bit values +// to avoid the function call overhead +#define TFT_WRITE_BITS(D, B) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B - 1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), D); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT)) & SPI_USR); - // Write 8 bits - #define tft_Write_8(C) TFT_WRITE_BITS((C)<<8, 16) +// Write 8 bits +#define tft_Write_8(C) TFT_WRITE_BITS((C) << 8, 16) - // Write 16 bits with corrected endianness for 16-bit colours - #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) +// Write 16 bits with corrected endianness for 16-bit colours +#define tft_Write_16(C) TFT_WRITE_BITS((C) << 8 | (C) >> 8, 16) - // Future option for transfer without wait - #define tft_Write_16N(C) tft_Write_16(C) +// Future option for transfer without wait +#define tft_Write_16N(C) tft_Write_16(C) - // Write 16 bits - #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) +// Write 16 bits +#define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) - // Write 32 bits - #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) +// Write 32 bits +#define tft_Write_32(C) TFT_WRITE_BITS(C, 32) - // Write two address coordinates - #define tft_Write_32C(C,D) TFT_WRITE_BITS((C)<<24 | (C), 32); \ - TFT_WRITE_BITS((D)<<24 | (D), 32) +// Write two address coordinates +#define tft_Write_32C(C, D) \ + TFT_WRITE_BITS((C) << 24 | (C), 32); \ + TFT_WRITE_BITS((D) << 24 | (D), 32) - // Write same value twice - #define tft_Write_32D(C) tft_Write_32C(C,C) +// Write same value twice +#define tft_Write_32D(C) tft_Write_32C(C, C) //////////////////////////////////////////////////////////////////////////////////////// // Macros for all other SPI displays @@ -541,51 +625,55 @@ SPI3_HOST = 2 #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) //*/ //* Replacement slimmer macros - #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1; \ - *_spi_w = D; \ - *_spi_cmd = SPI_USR; \ - while (*_spi_cmd & SPI_USR); +#define TFT_WRITE_BITS(D, B) \ + *_spi_mosi_dlen = B - 1; \ + *_spi_w = D; \ + *_spi_cmd = SPI_USR; \ + while (*_spi_cmd & SPI_USR); - // Write 8 bits - #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) +// Write 8 bits +#define tft_Write_8(C) TFT_WRITE_BITS(C, 8) - // Write 16 bits with corrected endianness for 16-bit colours - #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) +// Write 16 bits with corrected endianness for 16-bit colours +#define tft_Write_16(C) TFT_WRITE_BITS((C) << 8 | (C) >> 8, 16) - // Future option for transfer without wait - #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1; \ - *_spi_w = ((C)<<8 | (C)>>8); \ - *_spi_cmd = SPI_USR; +// Future option for transfer without wait +#define tft_Write_16N(C) \ + *_spi_mosi_dlen = 16 - 1; \ + *_spi_w = ((C) << 8 | (C) >> 8); \ + *_spi_cmd = SPI_USR; - // Write 16 bits - #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) +// Write 16 bits +#define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) - // Write 32 bits - #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) +// Write 32 bits +#define tft_Write_32(C) TFT_WRITE_BITS(C, 32) - // Write two address coordinates - #define tft_Write_32C(C,D) TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) +// Write two address coordinates +#define tft_Write_32C(C, D) \ + TFT_WRITE_BITS((uint16_t)((D) << 8 | (D) >> 8) << 16 | (uint16_t)((C) << 8 | (C) >> 8), 32) - // Write same value twice - #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) +// Write same value twice +#define tft_Write_32D(C) \ + TFT_WRITE_BITS((uint16_t)((C) << 8 | (C) >> 8) << 16 | (uint16_t)((C) << 8 | (C) >> 8), 32) //*/ #endif #ifndef tft_Write_16N - #define tft_Write_16N tft_Write_16 +#define tft_Write_16N tft_Write_16 #endif //////////////////////////////////////////////////////////////////////////////////////// // Macros to read from display using SPI or software SPI //////////////////////////////////////////////////////////////////////////////////////// -#if !defined (TFT_PARALLEL_8_BIT) - // Read from display using SPI or software SPI - // Use a SPI read transfer - #define tft_Read_8() spi.transfer(0) +#if !defined(TFT_PARALLEL_8_BIT) +// Read from display using SPI or software SPI +// Use a SPI read transfer +#define tft_Read_8() spi.transfer(0) #endif // Concatenate a byte sequence A,B,C,D to CDAB, P is a uint8_t pointer -#define DAT8TO32(P) ( (uint32_t)P[0]<<8 | P[1] | P[2]<<24 | P[3]<<16 ) +#define DAT8TO32(P) ((uint32_t)P[0] << 8 | P[1] | P[2] << 24 | P[3] << 16) #endif // Header end diff --git a/lib/TFT_eSPI/Processors/TFT_eSPI_ESP32_C3.h b/lib/TFT_eSPI/Processors/TFT_eSPI_ESP32_C3.h index 6fa185854..86a663f19 100644 --- a/lib/TFT_eSPI/Processors/TFT_eSPI_ESP32_C3.h +++ b/lib/TFT_eSPI/Processors/TFT_eSPI_ESP32_C3.h @@ -1,6 +1,6 @@ - //////////////////////////////////////////////////// - // TFT_eSPI driver functions for ESP32 processors // - //////////////////////////////////////////////////// +//////////////////////////////////////////////////// +// TFT_eSPI driver functions for ESP32 processors // +//////////////////////////////////////////////////// // Temporarily a separate file to TFT_eSPI_ESP32.h until board package low level API stabilises @@ -8,41 +8,44 @@ #define _TFT_eSPI_ESP32H_ #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) - #warning >>>>------>> DMA is not supported on the ESP32 C3 (possible future update) +#warning >>>>------>> DMA is not supported on the ESP32 C3 (possible future update) #endif // Processor ID reported by getSetup() #define PROCESSOR_ID 0x32 // Include processor specific header -#include "soc/spi_reg.h" #include "driver/spi_master.h" #include "hal/gpio_ll.h" +#include "soc/spi_reg.h" -#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32) - #define CONFIG_IDF_TARGET_ESP32 +#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && \ + !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C5) && \ + !defined(CONFIG_IDF_TARGET_ESP32C6) +#define CONFIG_IDF_TARGET_ESP32 #endif #ifndef VSPI - #define VSPI FSPI +#define VSPI FSPI #endif // Fix IDF problems with ESP32C3 -#if CONFIG_IDF_TARGET_ESP32C3 - // Fix ESP32C3 IDF bug for missing definition (VSPI/FSPI only tested at the moment) - #ifndef REG_SPI_BASE - #define REG_SPI_BASE(i) DR_REG_SPI2_BASE - #endif +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) +// Fix ESP32C3 IDF bug for missing definition (VSPI/FSPI only tested at the moment) +#ifndef REG_SPI_BASE +#define REG_SPI_BASE(i) DR_REG_SPI2_BASE +#endif - // Fix ESP32C3 IDF bug for name change - #ifndef SPI_MOSI_DLEN_REG - #define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x) - #endif +// Fix ESP32C3 IDF bug for name change +#ifndef SPI_MOSI_DLEN_REG +#define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x) +#endif #endif // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled -#if !defined (SUPPORT_TRANSACTIONS) - #define SUPPORT_TRANSACTIONS +#if !defined(SUPPORT_TRANSACTIONS) +#define SUPPORT_TRANSACTIONS #endif /* @@ -71,434 +74,515 @@ SPI3_HOST = 2 #define SPI_PORT SPI2_HOST #ifdef RPI_DISPLAY_TYPE - #define CMD_BITS (16-1) +#define CMD_BITS (16 - 1) #else - #define CMD_BITS (8-1) +#define CMD_BITS (8 - 1) #endif // Initialise processor specific SPI functions, used by init() #define INIT_TFT_DATA_BUS // Not used // Define a generic flag for 8-bit parallel -#if defined (ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility - #if !defined (TFT_PARALLEL_8_BIT) - #define TFT_PARALLEL_8_BIT // Generic parallel flag - #endif +#if defined(ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility +#if !defined(TFT_PARALLEL_8_BIT) +#define TFT_PARALLEL_8_BIT // Generic parallel flag +#endif #endif // Ensure ESP32 specific flag is defined for 8-bit parallel -#if defined (TFT_PARALLEL_8_BIT) - #if !defined (ESP32_PARALLEL) - #define ESP32_PARALLEL - #endif +#if defined(TFT_PARALLEL_8_BIT) +#if !defined(ESP32_PARALLEL) +#define ESP32_PARALLEL +#endif #endif // Processor specific code used by SPI bus transaction startWrite and endWrite functions -#if !defined (ESP32_PARALLEL) - #if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2) - #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE - #define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE - #else - #define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI - #define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN - #endif +#if !defined(ESP32_PARALLEL) +#if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2) +#define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE +#define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE #else - // Not applicable to parallel bus - #define SET_BUS_WRITE_MODE - #define SET_BUS_READ_MODE +#define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI +#define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN +#endif +#else +// Not applicable to parallel bus +#define SET_BUS_WRITE_MODE +#define SET_BUS_READ_MODE #endif // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions #if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER) - #define ESP32_DMA - // Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions - #define DMA_BUSY_CHECK dmaWait() +#define ESP32_DMA +// Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions +#define DMA_BUSY_CHECK dmaWait() #else - #define DMA_BUSY_CHECK +#define DMA_BUSY_CHECK #endif #if defined(TFT_PARALLEL_8_BIT) - #define SPI_BUSY_CHECK +#define SPI_BUSY_CHECK #else - #define SPI_BUSY_CHECK while (*_spi_cmd&SPI_USR) +#define SPI_BUSY_CHECK while (*_spi_cmd & SPI_USR) #endif // If smooth font is used then it is likely SPIFFS will be needed #ifdef SMOOTH_FONT - // Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts - #define FS_NO_GLOBALS - #include - #include "SPIFFS.h" // ESP32 only - #define FONT_FS_AVAILABLE +// Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts +#define FS_NO_GLOBALS +#include "SPIFFS.h" // ESP32 only +#include +#define FONT_FS_AVAILABLE #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the DC (TFT Data/Command or Register Select (RS))pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifndef TFT_DC - #define DC_C // No macro allocated so it generates no code - #define DC_D // No macro allocated so it generates no code +#define DC_C // No macro allocated so it generates no code +#define DC_D // No macro allocated so it generates no code +#else +#if defined(TFT_PARALLEL_8_BIT) +// TFT_DC, by design, must be in range 0-31 for single register parallel write +#if (TFT_DC >= 0) && (TFT_DC < 32) +#define DC_C GPIO.out_w1tc.val = (1 << TFT_DC) +#define DC_D GPIO.out_w1ts.val = (1 << TFT_DC) +#elif (TFT_DC >= 32) +#define DC_C GPIO.out_w1tc.val = (1 << (TFT_DC - 32)) +#define DC_D GPIO.out_w1ts.val = (1 << (TFT_DC - 32)) +#else +#define DC_C +#define DC_D +#endif +#else +#if (TFT_DC >= 32) +#ifdef RPI_DISPLAY_TYPE // RPi displays need a slower DC change +#define DC_C \ + GPIO.out_w1ts.val = (1 << (TFT_DC - 32)); \ + GPIO.out_w1tc.val = (1 << (TFT_DC - 32)) +#define DC_D \ + GPIO.out_w1tc.val = (1 << (TFT_DC - 32)); \ + GPIO.out_w1ts.val = (1 << (TFT_DC - 32)) #else - #if defined (TFT_PARALLEL_8_BIT) - // TFT_DC, by design, must be in range 0-31 for single register parallel write - #if (TFT_DC >= 0) && (TFT_DC < 32) - #define DC_C GPIO.out_w1tc.val = (1 << TFT_DC) - #define DC_D GPIO.out_w1ts.val = (1 << TFT_DC) - #elif (TFT_DC >= 32) - #define DC_C GPIO.out_w1tc.val = (1 << (TFT_DC- 32)) - #define DC_D GPIO.out_w1ts.val = (1 << (TFT_DC- 32)) - #else - #define DC_C - #define DC_D - #endif - #else - #if (TFT_DC >= 32) - #ifdef RPI_DISPLAY_TYPE // RPi displays need a slower DC change - #define DC_C GPIO.out_w1ts.val = (1 << (TFT_DC - 32)); \ - GPIO.out_w1tc.val = (1 << (TFT_DC - 32)) - #define DC_D GPIO.out_w1tc.val = (1 << (TFT_DC - 32)); \ - GPIO.out_w1ts.val = (1 << (TFT_DC - 32)) - #else - #define DC_C GPIO.out_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out_w1tc.val = (1 << (TFT_DC - 32)) - #define DC_D GPIO.out_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out_w1ts.val = (1 << (TFT_DC - 32)) - #endif - #elif (TFT_DC >= 0) - #if defined (RPI_DISPLAY_TYPE) - #if defined (ILI9486_DRIVER) - // RPi ILI9486 display needs a slower DC change - #define DC_C GPIO.out_w1tc.val = (1 << TFT_DC); \ - GPIO.out_w1tc.val = (1 << TFT_DC) - #define DC_D GPIO.out_w1tc.val = (1 << TFT_DC); \ - GPIO.out_w1ts.val = (1 << TFT_DC) - #else - // Other RPi displays need a slower C->D change - #define DC_C GPIO.out_w1tc.val = (1 << TFT_DC) - #define DC_D GPIO.out_w1tc.val = (1 << TFT_DC); \ - GPIO.out_w1ts.val = (1 << TFT_DC) - #endif - #else - #define DC_C GPIO.out_w1tc.val = (1 << TFT_DC)//;GPIO.out_w1tc.val = (1 << TFT_DC) - #define DC_D GPIO.out_w1ts.val = (1 << TFT_DC)//;GPIO.out_w1ts.val = (1 << TFT_DC) - #endif - #else - #define DC_C - #define DC_D - #endif - #endif +#define DC_C GPIO.out_w1tc.val = (1 << (TFT_DC - 32)) //;GPIO.out_w1tc.val = (1 << (TFT_DC - 32)) +#define DC_D GPIO.out_w1ts.val = (1 << (TFT_DC - 32)) //;GPIO.out_w1ts.val = (1 << (TFT_DC - 32)) +#endif +#elif (TFT_DC >= 0) +#if defined(RPI_DISPLAY_TYPE) +#if defined(ILI9486_DRIVER) +// RPi ILI9486 display needs a slower DC change +#define DC_C \ + GPIO.out_w1tc.val = (1 << TFT_DC); \ + GPIO.out_w1tc.val = (1 << TFT_DC) +#define DC_D \ + GPIO.out_w1tc.val = (1 << TFT_DC); \ + GPIO.out_w1ts.val = (1 << TFT_DC) +#else +// Other RPi displays need a slower C->D change +#define DC_C GPIO.out_w1tc.val = (1 << TFT_DC) +#define DC_D \ + GPIO.out_w1tc.val = (1 << TFT_DC); \ + GPIO.out_w1ts.val = (1 << TFT_DC) +#endif +#else +#define DC_C GPIO.out_w1tc.val = (1 << TFT_DC) //;GPIO.out_w1tc.val = (1 << TFT_DC) +#define DC_D GPIO.out_w1ts.val = (1 << TFT_DC) //;GPIO.out_w1ts.val = (1 << TFT_DC) +#endif +#else +#define DC_C +#define DC_D +#endif +#endif #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the CS (TFT chip select) pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifndef TFT_CS - #define TFT_CS -1 // Keep DMA code happy - #define CS_L // No macro allocated so it generates no code - #define CS_H // No macro allocated so it generates no code +#define TFT_CS -1 // Keep DMA code happy +#define CS_L // No macro allocated so it generates no code +#define CS_H // No macro allocated so it generates no code +#else +#if defined(TFT_PARALLEL_8_BIT) +#if TFT_CS >= 32 +#define CS_L GPIO.out_w1tc.val = (1 << (TFT_CS - 32)) +#define CS_H GPIO.out_w1ts.val = (1 << (TFT_CS - 32)) +#elif TFT_CS >= 0 +#define CS_L GPIO.out_w1tc.val = (1 << TFT_CS) +#define CS_H GPIO.out_w1ts.val = (1 << TFT_CS) +#else +#define CS_L +#define CS_H +#endif +#else +#if (TFT_CS >= 32) +#ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change +#define CS_L \ + GPIO.out_w1ts.val = (1 << (TFT_CS - 32)); \ + GPIO.out_w1tc.val = (1 << (TFT_CS - 32)) +#define CS_H \ + GPIO.out_w1tc.val = (1 << (TFT_CS - 32)); \ + GPIO.out_w1ts.val = (1 << (TFT_CS - 32)) +#else +#define CS_L \ + GPIO.out_w1tc.val = (1 << (TFT_CS - 32)); \ + GPIO.out_w1tc.val = (1 << (TFT_CS - 32)) +#define CS_H GPIO.out_w1ts.val = (1 << (TFT_CS - 32)) //;GPIO.out_w1ts.val = (1 << (TFT_CS - 32)) +#endif +#elif (TFT_CS >= 0) +#ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change +#define CS_L \ + GPIO.out_w1ts.val = (1 << TFT_CS); \ + GPIO.out_w1tc.val = (1 << TFT_CS) +#define CS_H \ + GPIO.out_w1tc.val = (1 << TFT_CS); \ + GPIO.out_w1ts.val = (1 << TFT_CS) +#else +#define CS_L \ + GPIO.out_w1tc.val = (1 << TFT_CS); \ + GPIO.out_w1tc.val = (1 << TFT_CS) +#define CS_H GPIO.out_w1ts.val = (1 << TFT_CS) //;GPIO.out_w1ts.val = (1 << TFT_CS) +#endif #else - #if defined (TFT_PARALLEL_8_BIT) - #if TFT_CS >= 32 - #define CS_L GPIO.out_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out_w1ts.val = (1 << (TFT_CS - 32)) - #elif TFT_CS >= 0 - #define CS_L GPIO.out_w1tc.val = (1 << TFT_CS) - #define CS_H GPIO.out_w1ts.val = (1 << TFT_CS) - #else - #define CS_L - #define CS_H - #endif - #else - #if (TFT_CS >= 32) - #ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change - #define CS_L GPIO.out_w1ts.val = (1 << (TFT_CS - 32)); \ - GPIO.out_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out_w1tc.val = (1 << (TFT_CS - 32)); \ - GPIO.out_w1ts.val = (1 << (TFT_CS - 32)) - #else - #define CS_L GPIO.out_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out_w1ts.val = (1 << (TFT_CS - 32)) - #endif - #elif (TFT_CS >= 0) - #ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change - #define CS_L GPIO.out_w1ts.val = (1 << TFT_CS); GPIO.out_w1tc.val = (1 << TFT_CS) - #define CS_H GPIO.out_w1tc.val = (1 << TFT_CS); GPIO.out_w1ts.val = (1 << TFT_CS) - #else - #define CS_L GPIO.out_w1tc.val = (1 << TFT_CS); GPIO.out_w1tc.val = (1 << TFT_CS) - #define CS_H GPIO.out_w1ts.val = (1 << TFT_CS)//;GPIO.out_w1ts.val = (1 << TFT_CS) - #endif - #else - #define CS_L - #define CS_H - #endif - #endif +#define CS_L +#define CS_H +#endif +#endif #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the WR (TFT Write) pin drive code //////////////////////////////////////////////////////////////////////////////////////// -#if defined (TFT_WR) - #if (TFT_WR >= 32) - // Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32 - #define WR_L GPIO.out_w1tc.val = (1 << (TFT_WR - 32)) - #define WR_H GPIO.out_w1ts.val = (1 << (TFT_WR - 32)) - #elif (TFT_WR >= 0) - // TFT_WR, for best performance, should be in range 0-31 for single register parallel write - #define WR_L GPIO.out_w1tc.val = (1 << TFT_WR) - #define WR_H GPIO.out_w1ts.val = (1 << TFT_WR) - #else - #define WR_L - #define WR_H - #endif +#if defined(TFT_WR) +#if (TFT_WR >= 32) +// Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32 +#define WR_L GPIO.out_w1tc.val = (1 << (TFT_WR - 32)) +#define WR_H GPIO.out_w1ts.val = (1 << (TFT_WR - 32)) +#elif (TFT_WR >= 0) +// TFT_WR, for best performance, should be in range 0-31 for single register parallel write +#define WR_L GPIO.out_w1tc.val = (1 << TFT_WR) +#define WR_H GPIO.out_w1ts.val = (1 << TFT_WR) +#else +#define WR_L +#define WR_H +#endif #else - #define WR_L - #define WR_H +#define WR_L +#define WR_H #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the touch screen chip select pin drive code //////////////////////////////////////////////////////////////////////////////////////// #ifndef TOUCH_CS - #define T_CS_L // No macro allocated so it generates no code - #define T_CS_H // No macro allocated so it generates no code -#else // XPT2046 is slow, so use slower digitalWrite here - #define T_CS_L digitalWrite(TOUCH_CS, LOW) - #define T_CS_H digitalWrite(TOUCH_CS, HIGH) +#define T_CS_L // No macro allocated so it generates no code +#define T_CS_H // No macro allocated so it generates no code +#else // XPT2046 is slow, so use slower digitalWrite here +#define T_CS_L digitalWrite(TOUCH_CS, LOW) +#define T_CS_H digitalWrite(TOUCH_CS, HIGH) #endif //////////////////////////////////////////////////////////////////////////////////////// // Make sure SPI default pins are assigned if not specified by user or set to -1 //////////////////////////////////////////////////////////////////////////////////////// -#if !defined (TFT_PARALLEL_8_BIT) - - #ifdef USE_HSPI_PORT - - #ifndef TFT_MISO - #define TFT_MISO -1 - #endif - - #ifndef TFT_MOSI - #define TFT_MOSI 13 - #endif - #if (TFT_MOSI == -1) - #undef TFT_MOSI - #define TFT_MOSI 13 - #endif - - #ifndef TFT_SCLK - #define TFT_SCLK 14 - #endif - #if (TFT_SCLK == -1) - #undef TFT_SCLK - #define TFT_SCLK 14 - #endif - - #else // VSPI port - - #ifndef TFT_MISO - #define TFT_MISO -1 - #endif - - #ifndef TFT_MOSI - #define TFT_MOSI 23 - #endif - #if (TFT_MOSI == -1) - #undef TFT_MOSI - #define TFT_MOSI 23 - #endif - - #ifndef TFT_SCLK - #define TFT_SCLK 18 - #endif - #if (TFT_SCLK == -1) - #undef TFT_SCLK - #define TFT_SCLK 18 - #endif - - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) - #if (TFT_MISO == -1) - #undef TFT_MISO - #define TFT_MISO TFT_MOSI - #endif - #endif - - #endif +#if !defined(TFT_PARALLEL_8_BIT) + +#ifdef USE_HSPI_PORT + +#ifndef TFT_MISO +#define TFT_MISO -1 +#endif + +#ifndef TFT_MOSI +#define TFT_MOSI 13 +#endif +#if (TFT_MOSI == -1) +#undef TFT_MOSI +#define TFT_MOSI 13 +#endif + +#ifndef TFT_SCLK +#define TFT_SCLK 14 +#endif +#if (TFT_SCLK == -1) +#undef TFT_SCLK +#define TFT_SCLK 14 +#endif + +#else // VSPI port + +#ifndef TFT_MISO +#define TFT_MISO -1 +#endif + +#ifndef TFT_MOSI +#define TFT_MOSI 23 +#endif +#if (TFT_MOSI == -1) +#undef TFT_MOSI +#define TFT_MOSI 23 +#endif + +#ifndef TFT_SCLK +#define TFT_SCLK 18 +#endif +#if (TFT_SCLK == -1) +#undef TFT_SCLK +#define TFT_SCLK 18 +#endif + +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32C6) +#if (TFT_MISO == -1) +#undef TFT_MISO +#define TFT_MISO TFT_MOSI +#endif +#endif + +#endif #endif //////////////////////////////////////////////////////////////////////////////////////// // Define the parallel bus interface chip pin drive code //////////////////////////////////////////////////////////////////////////////////////// -#if defined (TFT_PARALLEL_8_BIT) - - // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically - // can then use e.g. GPIO.out_w1ts.val = set_mask(0xFF); to set data bus to 0xFF - #define PARALLEL_INIT_TFT_DATA_BUS \ - for (int32_t c = 0; c<256; c++) \ - { \ - xset_mask[c] = 0; \ - if ( c & 0x01 ) xset_mask[c] |= (1 << TFT_D0); \ - if ( c & 0x02 ) xset_mask[c] |= (1 << TFT_D1); \ - if ( c & 0x04 ) xset_mask[c] |= (1 << TFT_D2); \ - if ( c & 0x08 ) xset_mask[c] |= (1 << TFT_D3); \ - if ( c & 0x10 ) xset_mask[c] |= (1 << TFT_D4); \ - if ( c & 0x20 ) xset_mask[c] |= (1 << TFT_D5); \ - if ( c & 0x40 ) xset_mask[c] |= (1 << TFT_D6); \ - if ( c & 0x80 ) xset_mask[c] |= (1 << TFT_D7); \ - } \ - - // Mask for the 8 data bits to set pin directions - #define GPIO_DIR_MASK ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7)) - - #if (TFT_WR >= 32) - // Data bits and the write line are cleared sequentially - #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L - #elif (TFT_WR >= 0) - // Data bits and the write line are cleared to 0 in one step (1.25x faster) - #define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR)) - #else - #define GPIO_OUT_CLR_MASK - #endif - - // A lookup table is used to set the different bit patterns, this uses 1kByte of RAM - #define set_mask(C) xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in real time - - // Real-time shifting alternative to above to save 1KByte RAM, 47 fps Sprite rendering test - /*#define set_mask(C) (((C)&0x80)>>7)<>6)<>5)<>4)<>3)<>2)<>1)<>0)<> 8)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) (((C) & 0x07E0)>> 3)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) (((C) & 0x001F)<< 3)); WR_H - - // 18-bit color write with swapped bytes - #define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap) - - #else - - #ifdef PSEUDO_16_BIT - // One write strobe for both bytes - #define tft_Write_16(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H - #define tft_Write_16S(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H - #else - // Write 16 bits to TFT - #define tft_Write_16(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H - - // 16-bit write with swapped bytes - #define tft_Write_16S(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H - #endif - - #endif - - // Write 32 bits to TFT - #define tft_Write_32(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 24)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 16)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H - - // Write two concatenated 16-bit values to TFT - #define tft_Write_32C(C,D) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((D) >> 8)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((D) >> 0)); WR_H - - // Write 16-bit value twice to TFT - used by drawPixel() - #define tft_Write_32D(C) GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 8)); WR_H; \ - GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; GPIO.out_w1ts.val = set_mask((uint8_t) ((C) >> 0)); WR_H - - // Read pin - #ifdef TFT_RD - #if (TFT_RD >= 32) - #define RD_L GPIO.out_w1tc.val = (1 << (TFT_RD - 32)) - #define RD_H GPIO.out_w1ts.val = (1 << (TFT_RD - 32)) - #elif (TFT_RD >= 0) - #define RD_L GPIO.out_w1tc.val = (1 << TFT_RD) - //#define RD_L digitalWrite(TFT_WR, LOW) - #define RD_H GPIO.out_w1ts.val = (1 << TFT_RD) - //#define RD_H digitalWrite(TFT_WR, HIGH) - #else - #define RD_L - #define RD_H - #endif - #else - #define TFT_RD -1 - #define RD_L - #define RD_H - #endif +#if defined(TFT_PARALLEL_8_BIT) + +// Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically +// can then use e.g. GPIO.out_w1ts.val = set_mask(0xFF); to set data bus to 0xFF +#define PARALLEL_INIT_TFT_DATA_BUS \ + for (int32_t c = 0; c < 256; c++) { \ + xset_mask[c] = 0; \ + if (c & 0x01) xset_mask[c] |= (1 << TFT_D0); \ + if (c & 0x02) xset_mask[c] |= (1 << TFT_D1); \ + if (c & 0x04) xset_mask[c] |= (1 << TFT_D2); \ + if (c & 0x08) xset_mask[c] |= (1 << TFT_D3); \ + if (c & 0x10) xset_mask[c] |= (1 << TFT_D4); \ + if (c & 0x20) xset_mask[c] |= (1 << TFT_D5); \ + if (c & 0x40) xset_mask[c] |= (1 << TFT_D6); \ + if (c & 0x80) xset_mask[c] |= (1 << TFT_D7); \ + } + +// Mask for the 8 data bits to set pin directions +#define GPIO_DIR_MASK \ + ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | \ + (1 << TFT_D6) | (1 << TFT_D7)) + +#if (TFT_WR >= 32) +// Data bits and the write line are cleared sequentially +#define GPIO_OUT_CLR_MASK \ + (GPIO_DIR_MASK); \ + WR_L +#elif (TFT_WR >= 0) +// Data bits and the write line are cleared to 0 in one step (1.25x faster) +#define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR)) +#else +#define GPIO_OUT_CLR_MASK +#endif + +// A lookup table is used to set the different bit patterns, this uses 1kByte of RAM +#define set_mask(C) \ + xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in + // real time + +// Real-time shifting alternative to above to save 1KByte RAM, 47 fps Sprite rendering test +/*#define set_mask(C) (((C)&0x80)>>7)<>6)<>5)<>4)<>3)<>2)<>1)<>0)<> 8)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)(((C) & 0x07E0) >> 3)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)(((C) & 0x001F) << 3)); \ + WR_H + +// 18-bit color write with swapped bytes +#define tft_Write_16S(C) \ + Cswap = ((C) >> 8 | (C) << 8); \ + tft_Write_16(Cswap) + +#else + +#ifdef PSEUDO_16_BIT +// One write strobe for both bytes +#define tft_Write_16(C) \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 0)); \ + WR_H +#define tft_Write_16S(C) \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 8)); \ + WR_H +#else +// Write 16 bits to TFT +#define tft_Write_16(C) \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 8)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 0)); \ + WR_H + +// 16-bit write with swapped bytes +#define tft_Write_16S(C) \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 0)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 8)); \ + WR_H +#endif + +#endif + +// Write 32 bits to TFT +#define tft_Write_32(C) \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 24)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 16)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 8)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 0)); \ + WR_H + +// Write two concatenated 16-bit values to TFT +#define tft_Write_32C(C, D) \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 8)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 0)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((D) >> 8)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((D) >> 0)); \ + WR_H + +// Write 16-bit value twice to TFT - used by drawPixel() +#define tft_Write_32D(C) \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 8)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 0)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 8)); \ + WR_H; \ + GPIO.out_w1tc.val = GPIO_OUT_CLR_MASK; \ + GPIO.out_w1ts.val = set_mask((uint8_t)((C) >> 0)); \ + WR_H + +// Read pin +#ifdef TFT_RD +#if (TFT_RD >= 32) +#define RD_L GPIO.out_w1tc.val = (1 << (TFT_RD - 32)) +#define RD_H GPIO.out_w1ts.val = (1 << (TFT_RD - 32)) +#elif (TFT_RD >= 0) +#define RD_L GPIO.out_w1tc.val = (1 << TFT_RD) +// #define RD_L digitalWrite(TFT_WR, LOW) +#define RD_H GPIO.out_w1ts.val = (1 << TFT_RD) +// #define RD_H digitalWrite(TFT_WR, HIGH) +#else +#define RD_L +#define RD_H +#endif +#else +#define TFT_RD -1 +#define RD_L +#define RD_H +#endif //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to a SPI ILI948x TFT //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour +#elif defined(SPI_18BIT_DRIVER) // SPI 18-bit colour - // Write 8 bits to TFT - #define tft_Write_8(C) spi.transfer(C) +// Write 8 bits to TFT +#define tft_Write_8(C) spi.transfer(C) - // Convert 16-bit colour to 18-bit and write in 3 bytes - #define tft_Write_16(C) spi.transfer(((C) & 0xF800)>>8); \ - spi.transfer(((C) & 0x07E0)>>3); \ - spi.transfer(((C) & 0x001F)<<3) +// Convert 16-bit colour to 18-bit and write in 3 bytes +#define tft_Write_16(C) \ + spi.transfer(((C) & 0xF800) >> 8); \ + spi.transfer(((C) & 0x07E0) >> 3); \ + spi.transfer(((C) & 0x001F) << 3) - // Future option for transfer without wait - #define tft_Write_16N(C) tft_Write_16(C) +// Future option for transfer without wait +#define tft_Write_16N(C) tft_Write_16(C) - // Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes - #define tft_Write_16S(C) spi.transfer((C) & 0xF8); \ - spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \ - spi.transfer(((C) & 0x1F00)>>5) +// Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes +#define tft_Write_16S(C) \ + spi.transfer((C) & 0xF8); \ + spi.transfer(((C) & 0xE000) >> 11 | ((C) & 0x07) << 5); \ + spi.transfer(((C) & 0x1F00) >> 5) - // Write 32 bits to TFT - #define tft_Write_32(C) spi.write32(C) +// Write 32 bits to TFT +#define tft_Write_32(C) spi.write32(C) - // Write two concatenated 16-bit values to TFT - #define tft_Write_32C(C,D) spi.write32((C)<<16 | (D)) +// Write two concatenated 16-bit values to TFT +#define tft_Write_32C(C, D) spi.write32((C) << 16 | (D)) - // Write 16-bit value twice to TFT - #define tft_Write_32D(C) spi.write32((C)<<16 | (C)) +// Write 16-bit value twice to TFT +#define tft_Write_32D(C) spi.write32((C) << 16 | (C)) //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to an Raspberry Pi TFT //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (RPI_DISPLAY_TYPE) +#elif defined(RPI_DISPLAY_TYPE) - // ESP32 low level SPI writes for 8, 16 and 32-bit values - // to avoid the function call overhead - #define TFT_WRITE_BITS(D, B) \ - WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \ - WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), D); \ - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ - while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); +// ESP32 low level SPI writes for 8, 16 and 32-bit values +// to avoid the function call overhead +#define TFT_WRITE_BITS(D, B) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B - 1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), D); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT)) & SPI_USR); - // Write 8 bits - #define tft_Write_8(C) TFT_WRITE_BITS((C)<<8, 16) +// Write 8 bits +#define tft_Write_8(C) TFT_WRITE_BITS((C) << 8, 16) - // Write 16 bits with corrected endianness for 16-bit colours - #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) +// Write 16 bits with corrected endianness for 16-bit colours +#define tft_Write_16(C) TFT_WRITE_BITS((C) << 8 | (C) >> 8, 16) - // Future option for transfer without wait - #define tft_Write_16N(C) tft_Write_16(C) +// Future option for transfer without wait +#define tft_Write_16N(C) tft_Write_16(C) - // Write 16 bits - #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) +// Write 16 bits +#define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) - // Write 32 bits - #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) +// Write 32 bits +#define tft_Write_32(C) TFT_WRITE_BITS(C, 32) - // Write two address coordinates - #define tft_Write_32C(C,D) TFT_WRITE_BITS((C)<<24 | (C), 32); \ - TFT_WRITE_BITS((D)<<24 | (D), 32) +// Write two address coordinates +#define tft_Write_32C(C, D) \ + TFT_WRITE_BITS((C) << 24 | (C), 32); \ + TFT_WRITE_BITS((D) << 24 | (D), 32) - // Write same value twice - #define tft_Write_32D(C) tft_Write_32C(C,C) +// Write same value twice +#define tft_Write_32D(C) tft_Write_32C(C, C) //////////////////////////////////////////////////////////////////////////////////////// // Macros for all other SPI displays @@ -532,67 +616,75 @@ SPI3_HOST = 2 #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) //*/ //* Replacement slimmer macros - #if !defined(CONFIG_IDF_TARGET_ESP32C3) - #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1; \ - *_spi_w = D; \ - *_spi_cmd = SPI_USR; \ - while (*_spi_cmd & SPI_USR); - #else - #define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1; \ - *_spi_w = D; \ - *_spi_cmd = SPI_UPDATE; \ - while (*_spi_cmd & SPI_UPDATE); \ - *_spi_cmd = SPI_USR; \ - while (*_spi_cmd & SPI_USR); - #endif - // Write 8 bits - #define tft_Write_8(C) TFT_WRITE_BITS(C, 8) - - // Write 16 bits with corrected endianness for 16-bit colours - #define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16) +#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && \ + !defined(CONFIG_IDF_TARGET_ESP32C6) +#define TFT_WRITE_BITS(D, B) \ + *_spi_mosi_dlen = B - 1; \ + *_spi_w = D; \ + *_spi_cmd = SPI_USR; \ + while (*_spi_cmd & SPI_USR); +#else +#define TFT_WRITE_BITS(D, B) \ + *_spi_mosi_dlen = B - 1; \ + *_spi_w = D; \ + *_spi_cmd = SPI_UPDATE; \ + while (*_spi_cmd & SPI_UPDATE); \ + *_spi_cmd = SPI_USR; \ + while (*_spi_cmd & SPI_USR); +#endif +// Write 8 bits +#define tft_Write_8(C) TFT_WRITE_BITS(C, 8) + +// Write 16 bits with corrected endianness for 16-bit colours +#define tft_Write_16(C) TFT_WRITE_BITS((C) << 8 | (C) >> 8, 16) + +// Future option for transfer without wait +#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32C5) && \ + !defined(CONFIG_IDF_TARGET_ESP32C6) +#define tft_Write_16N(C) \ + *_spi_mosi_dlen = 16 - 1; \ + *_spi_w = ((C) << 8 | (C) >> 8); \ + *_spi_cmd = SPI_USR; +#else +#define tft_Write_16N(C) \ + *_spi_mosi_dlen = 16 - 1; \ + *_spi_w = ((C) << 8 | (C) >> 8); \ + *_spi_cmd = SPI_UPDATE; \ + while (*_spi_cmd & SPI_UPDATE); \ + *_spi_cmd = SPI_USR; +#endif - // Future option for transfer without wait - #if !defined(CONFIG_IDF_TARGET_ESP32C3) - #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1; \ - *_spi_w = ((C)<<8 | (C)>>8); \ - *_spi_cmd = SPI_USR; - #else - #define tft_Write_16N(C) *_spi_mosi_dlen = 16-1; \ - *_spi_w = ((C)<<8 | (C)>>8); \ - *_spi_cmd = SPI_UPDATE; \ - while (*_spi_cmd & SPI_UPDATE); \ - *_spi_cmd = SPI_USR; - #endif +// Write 16 bits +#define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) - // Write 16 bits - #define tft_Write_16S(C) TFT_WRITE_BITS(C, 16) +// Write 32 bits +#define tft_Write_32(C) TFT_WRITE_BITS(C, 32) - // Write 32 bits - #define tft_Write_32(C) TFT_WRITE_BITS(C, 32) - - // Write two address coordinates - #define tft_Write_32C(C,D) TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) +// Write two address coordinates +#define tft_Write_32C(C, D) \ + TFT_WRITE_BITS((uint16_t)((D) << 8 | (D) >> 8) << 16 | (uint16_t)((C) << 8 | (C) >> 8), 32) - // Write same value twice - #define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32) +// Write same value twice +#define tft_Write_32D(C) \ + TFT_WRITE_BITS((uint16_t)((C) << 8 | (C) >> 8) << 16 | (uint16_t)((C) << 8 | (C) >> 8), 32) //*/ #endif #ifndef tft_Write_16N - #define tft_Write_16N tft_Write_16 +#define tft_Write_16N tft_Write_16 #endif //////////////////////////////////////////////////////////////////////////////////////// // Macros to read from display using SPI or software SPI //////////////////////////////////////////////////////////////////////////////////////// -#if !defined (TFT_PARALLEL_8_BIT) - // Read from display using SPI or software SPI - // Use a SPI read transfer - #define tft_Read_8() spi.transfer(0) +#if !defined(TFT_PARALLEL_8_BIT) +// Read from display using SPI or software SPI +// Use a SPI read transfer +#define tft_Read_8() spi.transfer(0) #endif // Concatenate a byte sequence A,B,C,D to CDAB, P is a uint8_t pointer -#define DAT8TO32(P) ( (uint32_t)P[0]<<8 | P[1] | P[2]<<24 | P[3]<<16 ) +#define DAT8TO32(P) ((uint32_t)P[0] << 8 | P[1] | P[2] << 24 | P[3] << 16) #endif // Header end diff --git a/lib/TFT_eSPI/TFT_eSPI.h b/lib/TFT_eSPI/TFT_eSPI.h index cf3232f26..ee354dbde 100644 --- a/lib/TFT_eSPI/TFT_eSPI.h +++ b/lib/TFT_eSPI/TFT_eSPI.h @@ -26,11 +26,11 @@ ** Section 1: Load required header files ***************************************************************************************/ -//Standard support +// Standard support #include #include -#if !defined (TFT_PARALLEL_8_BIT) && !defined (RP2040_PIO_INTERFACE) - #include +#if !defined(TFT_PARALLEL_8_BIT) && !defined(RP2040_PIO_INTERFACE) +#include #endif /*************************************************************************************** ** Section 2: Load library and processor specific header files @@ -38,122 +38,125 @@ // Include header file that defines the fonts loaded, the TFT drivers // available and the pins to be used, etc. etc. #ifdef CONFIG_TFT_eSPI_ESPIDF - #include "TFT_config.h" +#include "TFT_config.h" #endif // New ESP8266 board package uses ARDUINO_ARCH_ESP8266 // old package defined ESP8266 -#if defined (ESP8266) - #ifndef ARDUINO_ARCH_ESP8266 - #define ARDUINO_ARCH_ESP8266 - #endif +#if defined(ESP8266) +#ifndef ARDUINO_ARCH_ESP8266 +#define ARDUINO_ARCH_ESP8266 +#endif #endif // The following lines allow the user setup to be included in the sketch folder, see // "Sketch_with_tft_setup" generic example. #if !defined __has_include - #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) - #warning Compiler does not support __has_include, so sketches cannot define the setup - #endif +#if !defined(DISABLE_ALL_LIBRARY_WARNINGS) +#warning Compiler does not support __has_include, so sketches cannot define the setup +#endif #else - #if __has_include() - // Include the sketch setup file - #include - #ifndef USER_SETUP_LOADED - // Prevent loading further setups - #define USER_SETUP_LOADED - #endif - #endif +#if __has_include() +// Include the sketch setup file +#include +#ifndef USER_SETUP_LOADED +// Prevent loading further setups +#define USER_SETUP_LOADED +#endif +#endif #endif #include // Handle FLASH based storage e.g. PROGMEM #if defined(ARDUINO_ARCH_RP2040) - #undef pgm_read_byte - #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) - #undef pgm_read_word - #define pgm_read_word(addr) ({ \ - typeof(addr) _addr = (addr); \ - *(const unsigned short *)(_addr); \ - }) - #undef pgm_read_dword - #define pgm_read_dword(addr) ({ \ - typeof(addr) _addr = (addr); \ - *(const unsigned long *)(_addr); \ - }) +#undef pgm_read_byte +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#undef pgm_read_word +#define pgm_read_word(addr) \ + ({ \ + typeof(addr) _addr = (addr); \ + *(const unsigned short *)(_addr); \ + }) +#undef pgm_read_dword +#define pgm_read_dword(addr) \ + ({ \ + typeof(addr) _addr = (addr); \ + *(const unsigned long *)(_addr); \ + }) #elif defined(__AVR__) - #include +#include #elif defined(ARDUINO_ARCH_ESP8266) || defined(ESP32) - #include +#include #else - #ifndef PROGMEM - #define PROGMEM - #endif +#ifndef PROGMEM +#define PROGMEM +#endif #endif // Include the processor specific drivers #if defined(CONFIG_IDF_TARGET_ESP32S3) - #include "Processors/TFT_eSPI_ESP32_S3.h" -#elif defined(CONFIG_IDF_TARGET_ESP32C3) - #include "Processors/TFT_eSPI_ESP32_C3.h" -#elif defined (ESP32) - #include "Processors/TFT_eSPI_ESP32.h" -#elif defined (ARDUINO_ARCH_ESP8266) - #include "Processors/TFT_eSPI_ESP8266.h" -#elif defined (STM32) - #include "Processors/TFT_eSPI_STM32.h" +#include "Processors/TFT_eSPI_ESP32_S3.h" +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) +#include "Processors/TFT_eSPI_ESP32_C3.h" +#elif defined(ESP32) +#include "Processors/TFT_eSPI_ESP32.h" +#elif defined(ARDUINO_ARCH_ESP8266) +#include "Processors/TFT_eSPI_ESP8266.h" +#elif defined(STM32) +#include "Processors/TFT_eSPI_STM32.h" #elif defined(ARDUINO_ARCH_RP2040) - #include "Processors/TFT_eSPI_RP2040.h" +#include "Processors/TFT_eSPI_RP2040.h" #else - #include "Processors/TFT_eSPI_Generic.h" - #define GENERIC_PROCESSOR +#include "Processors/TFT_eSPI_Generic.h" +#define GENERIC_PROCESSOR #endif /*************************************************************************************** ** Section 3: Interface setup ***************************************************************************************/ #ifndef TAB_COLOUR - #define TAB_COLOUR 0 +#define TAB_COLOUR 0 #endif // If the SPI frequency is not defined, set a default #ifndef SPI_FREQUENCY - #define SPI_FREQUENCY 20000000 +#define SPI_FREQUENCY 20000000 #endif // If the SPI read frequency is not defined, set a default #ifndef SPI_READ_FREQUENCY - #define SPI_READ_FREQUENCY 10000000 +#define SPI_READ_FREQUENCY 10000000 #endif // Some ST7789 boards do not work with Mode 0 #ifndef TFT_SPI_MODE - #if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER) - #define TFT_SPI_MODE SPI_MODE3 - #else - #define TFT_SPI_MODE SPI_MODE0 - #endif +#if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER) +#define TFT_SPI_MODE SPI_MODE3 +#else +#define TFT_SPI_MODE SPI_MODE0 +#endif #endif // If the XPT2046 SPI frequency is not defined, set a default #ifndef SPI_TOUCH_FREQUENCY - #define SPI_TOUCH_FREQUENCY 2500000 +#define SPI_TOUCH_FREQUENCY 2500000 #endif #ifndef SPI_BUSY_CHECK - #define SPI_BUSY_CHECK +#define SPI_BUSY_CHECK #endif // If half duplex SDA mode is defined then MISO pin should be -1 #ifdef TFT_SDA_READ - #ifdef TFT_MISO - #if TFT_MISO != -1 - #undef TFT_MISO - #define TFT_MISO -1 - #warning TFT_MISO set to -1 - #endif - #endif +#ifdef TFT_MISO +#if TFT_MISO != -1 +#undef TFT_MISO +#define TFT_MISO -1 +#warning TFT_MISO set to -1 +#endif +#endif #endif /*************************************************************************************** @@ -162,65 +165,65 @@ // Use GLCD font in error case where user requests a smooth font file // that does not exist (this is a temporary fix to stop ESP32 reboot) #ifdef SMOOTH_FONT - #ifndef LOAD_GLCD - #define LOAD_GLCD - #endif +#ifndef LOAD_GLCD +#define LOAD_GLCD +#endif #endif // Only load the fonts defined in User_Setup.h (to save space) // Set flag so RLE rendering code is optionally compiled #ifdef LOAD_GLCD - #include +#include #endif #ifdef LOAD_FONT2 - #include +#include #endif #ifdef LOAD_FONT4 - #include - #define LOAD_RLE +#include +#define LOAD_RLE #endif #ifdef LOAD_FONT6 - #include - #ifndef LOAD_RLE - #define LOAD_RLE - #endif +#include +#ifndef LOAD_RLE +#define LOAD_RLE +#endif #endif #ifdef LOAD_FONT7 - #include - #ifndef LOAD_RLE - #define LOAD_RLE - #endif +#include +#ifndef LOAD_RLE +#define LOAD_RLE +#endif #endif #ifdef LOAD_FONT8 - #include - #ifndef LOAD_RLE - #define LOAD_RLE - #endif +#include +#ifndef LOAD_RLE +#define LOAD_RLE +#endif #elif defined LOAD_FONT8N // Optional narrower version - #define LOAD_FONT8 - #include - #ifndef LOAD_RLE - #define LOAD_RLE - #endif +#define LOAD_FONT8 +#include +#ifndef LOAD_RLE +#define LOAD_RLE +#endif #endif #ifdef LOAD_GFXFF - // We can include all the free fonts and they will only be built into - // the sketch if they are used - #include - // Call up any user custom fonts - #include +// We can include all the free fonts and they will only be built into +// the sketch if they are used +#include +// Call up any user custom fonts +#include #endif // #ifdef LOAD_GFXFF // Create a null default font in case some fonts not used (to prevent crash) -const uint8_t widtbl_null[1] = {0}; +const uint8_t widtbl_null[1] = {0}; PROGMEM const uint8_t chr_null[1] = {0}; -PROGMEM const uint8_t* const chrtbl_null[1] = {chr_null}; +PROGMEM const uint8_t *const chrtbl_null[1] = {chr_null}; // This is a structure to conveniently hold information on the default fonts // Stores pointer to font character image address table, width table and height @@ -229,72 +232,72 @@ typedef struct { const uint8_t *widthtbl; uint8_t height; uint8_t baseline; - } fontinfo; +} fontinfo; // Now fill the structure -const PROGMEM fontinfo fontdata [] = { - #ifdef LOAD_GLCD - { (const uint8_t *)font, widtbl_null, 0, 0 }, - #else - { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, - #endif - // GLCD font (Font 1) does not have all parameters - { (const uint8_t *)chrtbl_null, widtbl_null, 8, 7 }, - - #ifdef LOAD_FONT2 - { (const uint8_t *)chrtbl_f16, widtbl_f16, chr_hgt_f16, baseline_f16}, - #else - { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, - #endif - - // Font 3 current unused - { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, - - #ifdef LOAD_FONT4 - { (const uint8_t *)chrtbl_f32, widtbl_f32, chr_hgt_f32, baseline_f32}, - #else - { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, - #endif - - // Font 5 current unused - { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, - - #ifdef LOAD_FONT6 - { (const uint8_t *)chrtbl_f64, widtbl_f64, chr_hgt_f64, baseline_f64}, - #else - { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, - #endif - - #ifdef LOAD_FONT7 - { (const uint8_t *)chrtbl_f7s, widtbl_f7s, chr_hgt_f7s, baseline_f7s}, - #else - { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, - #endif - - #ifdef LOAD_FONT8 - { (const uint8_t *)chrtbl_f72, widtbl_f72, chr_hgt_f72, baseline_f72} - #else - { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 } - #endif +const PROGMEM fontinfo fontdata[] = { +#ifdef LOAD_GLCD + {(const uint8_t *)font, widtbl_null, 0, 0 }, +#else + {(const uint8_t *)chrtbl_null, widtbl_null, 0, 0}, +#endif + // GLCD font (Font 1) does not have all parameters + {(const uint8_t *)chrtbl_null, widtbl_null, 8, 7 }, + +#ifdef LOAD_FONT2 + {(const uint8_t *)chrtbl_f16, widtbl_f16, chr_hgt_f16, baseline_f16}, +#else + {(const uint8_t *)chrtbl_null, widtbl_null, 0, 0}, +#endif + + // Font 3 current unused + {(const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, + +#ifdef LOAD_FONT4 + {(const uint8_t *)chrtbl_f32, widtbl_f32, chr_hgt_f32, baseline_f32}, +#else + {(const uint8_t *)chrtbl_null, widtbl_null, 0, 0}, +#endif + + // Font 5 current unused + {(const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, + +#ifdef LOAD_FONT6 + {(const uint8_t *)chrtbl_f64, widtbl_f64, chr_hgt_f64, baseline_f64}, +#else + {(const uint8_t *)chrtbl_null, widtbl_null, 0, 0}, +#endif + +#ifdef LOAD_FONT7 + {(const uint8_t *)chrtbl_f7s, widtbl_f7s, chr_hgt_f7s, baseline_f7s}, +#else + {(const uint8_t *)chrtbl_null, widtbl_null, 0, 0}, +#endif + +#ifdef LOAD_FONT8 + {(const uint8_t *)chrtbl_f72, widtbl_f72, chr_hgt_f72, baseline_f72} +#else + {(const uint8_t *)chrtbl_null, widtbl_null, 0, 0} +#endif }; /*************************************************************************************** ** Section 5: Font datum enumeration ***************************************************************************************/ -//These enumerate the text plotting alignment (reference datum point) -#define TL_DATUM 0 // Top left (default) -#define TC_DATUM 1 // Top centre -#define TR_DATUM 2 // Top right -#define ML_DATUM 3 // Middle left -#define CL_DATUM 3 // Centre left, same as above -#define MC_DATUM 4 // Middle centre -#define CC_DATUM 4 // Centre centre, same as above -#define MR_DATUM 5 // Middle right -#define CR_DATUM 5 // Centre right, same as above -#define BL_DATUM 6 // Bottom left -#define BC_DATUM 7 // Bottom centre -#define BR_DATUM 8 // Bottom right -#define L_BASELINE 9 // Left character baseline (Line the 'A' character would sit on) +// These enumerate the text plotting alignment (reference datum point) +#define TL_DATUM 0 // Top left (default) +#define TC_DATUM 1 // Top centre +#define TR_DATUM 2 // Top right +#define ML_DATUM 3 // Middle left +#define CL_DATUM 3 // Centre left, same as above +#define MC_DATUM 4 // Middle centre +#define CC_DATUM 4 // Centre centre, same as above +#define MR_DATUM 5 // Middle right +#define CR_DATUM 5 // Centre right, same as above +#define BL_DATUM 6 // Bottom left +#define BC_DATUM 7 // Bottom centre +#define BR_DATUM 8 // Bottom right +#define L_BASELINE 9 // Left character baseline (Line the 'A' character would sit on) #define C_BASELINE 10 // Centre character baseline #define R_BASELINE 11 // Right character baseline @@ -302,30 +305,30 @@ const PROGMEM fontinfo fontdata [] = { ** Section 6: Colour enumeration ***************************************************************************************/ // Default color definitions -#define TFT_BLACK 0x0000 /* 0, 0, 0 */ -#define TFT_NAVY 0x000F /* 0, 0, 128 */ -#define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */ -#define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */ -#define TFT_MAROON 0x7800 /* 128, 0, 0 */ -#define TFT_PURPLE 0x780F /* 128, 0, 128 */ -#define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */ -#define TFT_LIGHTGREY 0xD69A /* 211, 211, 211 */ -#define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */ -#define TFT_BLUE 0x001F /* 0, 0, 255 */ -#define TFT_GREEN 0x07E0 /* 0, 255, 0 */ -#define TFT_CYAN 0x07FF /* 0, 255, 255 */ -#define TFT_RED 0xF800 /* 255, 0, 0 */ -#define TFT_MAGENTA 0xF81F /* 255, 0, 255 */ -#define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */ -#define TFT_WHITE 0xFFFF /* 255, 255, 255 */ -#define TFT_ORANGE 0xFDA0 /* 255, 180, 0 */ -#define TFT_GREENYELLOW 0xB7E0 /* 180, 255, 0 */ -#define TFT_PINK 0xFE19 /* 255, 192, 203 */ //Lighter pink, was 0xFC9F -#define TFT_BROWN 0x9A60 /* 150, 75, 0 */ -#define TFT_GOLD 0xFEA0 /* 255, 215, 0 */ -#define TFT_SILVER 0xC618 /* 192, 192, 192 */ -#define TFT_SKYBLUE 0x867D /* 135, 206, 235 */ -#define TFT_VIOLET 0x915C /* 180, 46, 226 */ +#define TFT_BLACK 0x0000 /* 0, 0, 0 */ +#define TFT_NAVY 0x000F /* 0, 0, 128 */ +#define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */ +#define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */ +#define TFT_MAROON 0x7800 /* 128, 0, 0 */ +#define TFT_PURPLE 0x780F /* 128, 0, 128 */ +#define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */ +#define TFT_LIGHTGREY 0xD69A /* 211, 211, 211 */ +#define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */ +#define TFT_BLUE 0x001F /* 0, 0, 255 */ +#define TFT_GREEN 0x07E0 /* 0, 255, 0 */ +#define TFT_CYAN 0x07FF /* 0, 255, 255 */ +#define TFT_RED 0xF800 /* 255, 0, 0 */ +#define TFT_MAGENTA 0xF81F /* 255, 0, 255 */ +#define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */ +#define TFT_WHITE 0xFFFF /* 255, 255, 255 */ +#define TFT_ORANGE 0xFDA0 /* 255, 180, 0 */ +#define TFT_GREENYELLOW 0xB7E0 /* 180, 255, 0 */ +#define TFT_PINK 0xFE19 /* 255, 192, 203 */ // Lighter pink, was 0xFC9F +#define TFT_BROWN 0x9A60 /* 150, 75, 0 */ +#define TFT_GOLD 0xFEA0 /* 255, 215, 0 */ +#define TFT_SILVER 0xC618 /* 192, 192, 192 */ +#define TFT_SKYBLUE 0x867D /* 135, 206, 235 */ +#define TFT_VIOLET 0x915C /* 180, 46, 226 */ // Next is a special 16-bit colour value that encodes to 8 bits // and will then decode back to the same 16-bit value. @@ -334,22 +337,22 @@ const PROGMEM fontinfo fontdata [] = { // Default palette for 4-bit colour sprites static const uint16_t default_4bit_palette[] PROGMEM = { - TFT_BLACK, // 0 ^ - TFT_BROWN, // 1 | - TFT_RED, // 2 | - TFT_ORANGE, // 3 | - TFT_YELLOW, // 4 Colours 0-9 follow the resistor colour code! - TFT_GREEN, // 5 | - TFT_BLUE, // 6 | - TFT_PURPLE, // 7 | - TFT_DARKGREY, // 8 | - TFT_WHITE, // 9 v - TFT_CYAN, // 10 Blue+green mix - TFT_MAGENTA, // 11 Blue+red mix - TFT_MAROON, // 12 Darker red colour - TFT_DARKGREEN,// 13 Darker green colour - TFT_NAVY, // 14 Darker blue colour - TFT_PINK // 15 + TFT_BLACK, // 0 ^ + TFT_BROWN, // 1 | + TFT_RED, // 2 | + TFT_ORANGE, // 3 | + TFT_YELLOW, // 4 Colours 0-9 follow the resistor colour code! + TFT_GREEN, // 5 | + TFT_BLUE, // 6 | + TFT_PURPLE, // 7 | + TFT_DARKGREY, // 8 | + TFT_WHITE, // 9 v + TFT_CYAN, // 10 Blue+green mix + TFT_MAGENTA, // 11 Blue+red mix + TFT_MAROON, // 12 Darker red colour + TFT_DARKGREEN, // 13 Darker green colour + TFT_NAVY, // 14 Darker blue colour + TFT_PINK // 15 }; /*************************************************************************************** @@ -360,60 +363,59 @@ static const uint16_t default_4bit_palette[] PROGMEM = { // This structure allows sketches to retrieve the user setup parameters at runtime // by calling getSetup(), zero impact on code size unless used, mainly for diagnostics -typedef struct -{ -String version = TFT_ESPI_VERSION; -String setup_info; // Setup reference name available to use in a user setup -uint32_t setup_id; // ID available to use in a user setup -int32_t esp; // Processor code -uint8_t trans; // SPI transaction support -uint8_t serial; // Serial (SPI) or parallel +typedef struct { + String version = TFT_ESPI_VERSION; + String setup_info; // Setup reference name available to use in a user setup + uint32_t setup_id; // ID available to use in a user setup + int32_t esp; // Processor code + uint8_t trans; // SPI transaction support + uint8_t serial; // Serial (SPI) or parallel #ifndef GENERIC_PROCESSOR -uint8_t port; // SPI port -#endif -uint8_t overlap; // ESP8266 overlap mode -uint8_t interface; // Interface type - -uint16_t tft_driver; // Hexadecimal code -uint16_t tft_width; // Rotation 0 width and height -uint16_t tft_height; - -uint8_t r0_x_offset; // Display offsets, not all used yet -uint8_t r0_y_offset; -uint8_t r1_x_offset; -uint8_t r1_y_offset; -uint8_t r2_x_offset; -uint8_t r2_y_offset; -uint8_t r3_x_offset; -uint8_t r3_y_offset; - -int8_t pin_tft_mosi; // SPI pins -int8_t pin_tft_miso; -int8_t pin_tft_clk; -int8_t pin_tft_cs; - -int8_t pin_tft_dc; // Control pins -int8_t pin_tft_rd; -int8_t pin_tft_wr; -int8_t pin_tft_rst; - -int8_t pin_tft_d0; // Parallel port pins -int8_t pin_tft_d1; -int8_t pin_tft_d2; -int8_t pin_tft_d3; -int8_t pin_tft_d4; -int8_t pin_tft_d5; -int8_t pin_tft_d6; -int8_t pin_tft_d7; - -int8_t pin_tft_led; -int8_t pin_tft_led_on; - -int8_t pin_tch_cs; // Touch chip select pin - -int16_t tft_spi_freq;// TFT write SPI frequency -int16_t tft_rd_freq; // TFT read SPI frequency -int16_t tch_spi_freq;// Touch controller read/write SPI frequency + uint8_t port; // SPI port +#endif + uint8_t overlap; // ESP8266 overlap mode + uint8_t interface; // Interface type + + uint16_t tft_driver; // Hexadecimal code + uint16_t tft_width; // Rotation 0 width and height + uint16_t tft_height; + + uint8_t r0_x_offset; // Display offsets, not all used yet + uint8_t r0_y_offset; + uint8_t r1_x_offset; + uint8_t r1_y_offset; + uint8_t r2_x_offset; + uint8_t r2_y_offset; + uint8_t r3_x_offset; + uint8_t r3_y_offset; + + int8_t pin_tft_mosi; // SPI pins + int8_t pin_tft_miso; + int8_t pin_tft_clk; + int8_t pin_tft_cs; + + int8_t pin_tft_dc; // Control pins + int8_t pin_tft_rd; + int8_t pin_tft_wr; + int8_t pin_tft_rst; + + int8_t pin_tft_d0; // Parallel port pins + int8_t pin_tft_d1; + int8_t pin_tft_d2; + int8_t pin_tft_d3; + int8_t pin_tft_d4; + int8_t pin_tft_d5; + int8_t pin_tft_d6; + int8_t pin_tft_d7; + + int8_t pin_tft_led; + int8_t pin_tft_led_on; + + int8_t pin_tch_cs; // Touch chip select pin + + int16_t tft_spi_freq; // TFT write SPI frequency + int16_t tft_rd_freq; // TFT read SPI frequency + int16_t tch_spi_freq; // Touch controller read/write SPI frequency } setup_t; /*************************************************************************************** @@ -424,541 +426,589 @@ int16_t tch_spi_freq;// Touch controller read/write SPI frequency typedef uint16_t (*getColorCallback)(uint16_t x, uint16_t y); // Class functions and variables -class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has access to protected members - - //--------------------------------------- public ------------------------------------// - public: - - TFT_eSPI(int16_t _W = TFT_WIDTH, int16_t _H = TFT_HEIGHT); - - // init() and begin() are equivalent, begin() included for backwards compatibility - // Sketch defined tab colour option is for ST7735 displays only - void init(uint8_t tc = TAB_COLOUR), begin(uint8_t tc = TAB_COLOUR); - - void sleep(bool value); - - // These are virtual so the TFT_eSprite class can override them with sprite specific functions - virtual void drawPixel(int32_t x, int32_t y, uint32_t color), - drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size), - drawLine(int32_t xs, int32_t ys, int32_t xe, int32_t ye, uint32_t color), - drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), - drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), - fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); - - virtual int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font), - drawChar(uint16_t uniCode, int32_t x, int32_t y), - height(void), - width(void); - - // Read the colour of a pixel at x,y and return value in 565 format - virtual uint16_t readPixel(int32_t x, int32_t y); - - virtual void setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); // Note: start + end coordinates - - // Push (aka write pixel) colours to the set window - virtual void pushColor(uint16_t color); - - // These are non-inlined to enable override - virtual void begin_nin_write(); - virtual void end_nin_write(); - - void setRotation(uint8_t r); // Set the display image orientation to 0, 1, 2 or 3 - uint8_t getRotation(void); // Read the current rotation - - // Change the origin position from the default top left - // Note: setRotation, setViewport and resetViewport will revert origin to top left corner of screen/sprite - void setOrigin(int32_t x, int32_t y); - int32_t getOriginX(void); - int32_t getOriginY(void); - - void invertDisplay(bool i); // Tell TFT to invert all displayed colours - void setDisplayOff(); // Turn off display - void setDisplayOn(); // Turn on display - - - // The TFT_eSprite class inherits the following functions (not all are useful to Sprite class - void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); // Note: start coordinates + width and height - - // Viewport commands, see "Viewport_Demo" sketch - void setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum = true); - bool checkViewport(int32_t x, int32_t y, int32_t w, int32_t h); - int32_t getViewportX(void); - int32_t getViewportY(void); - int32_t getViewportWidth(void); - int32_t getViewportHeight(void); - bool getViewportDatum(void); - void frameViewport(uint16_t color, int32_t w); - void resetViewport(void); - - // Clip input window to viewport bounds, return false if whole area is out of bounds - bool clipAddrWindow(int32_t* x, int32_t* y, int32_t* w, int32_t* h); - // Clip input window area to viewport bounds, return false if whole area is out of bounds - bool clipWindow(int32_t* xs, int32_t* ys, int32_t* xe, int32_t* ye); - - // Push (aka write pixel) colours to the TFT (use setAddrWindow() first) - void pushColor(uint16_t color, uint32_t len), // Deprecated, use pushBlock() - pushColors(uint16_t *data, uint32_t len, bool swap = true), // With byte swap option - pushColors(uint8_t *data, uint32_t len); // Deprecated, use pushPixels() - - // Write a solid block of a single colour - void pushBlock(uint16_t color, uint32_t len); - - // Write a set of pixels stored in memory, use setSwapBytes(true/false) function to correct endianess - void pushPixels(const void * data_in, uint32_t len); - - // Support for half duplex (bi-directional SDA) SPI bus where MOSI must be switched to input - #ifdef TFT_SDA_READ - #if defined (TFT_eSPI_ENABLE_8_BIT_READ) - uint8_t tft_Read_8(void); // Read 8-bit value from TFT command register - #endif - void begin_SDA_Read(void); // Begin a read on a half duplex (bi-directional SDA) SPI bus - sets MOSI to input - void end_SDA_Read(void); // Restore MOSI to output - #endif - - - // Graphics drawing - void fillScreen(uint32_t color), - drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color), - drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color), - fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color); - - void fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2); - void fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2); - - void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color), - drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color), - fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color), - fillCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, int32_t delta, uint32_t color), - - drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color), - fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color), - - // Corner 1 Corner 2 Corner 3 - drawTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color), - fillTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color); - - - // Smooth (anti-aliased) graphics drawing - // Draw a pixel blended with the background pixel colour (bg_color) specified, return blended colour - // If the bg_color is not specified, the background pixel colour will be read from TFT or sprite - uint16_t drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha, uint32_t bg_color = 0x00FFFFFF); - - // Draw an anti-aliased (smooth) arc between start and end angles. Arc ends are anti-aliased. - // By default the arc is drawn with square ends unless the "roundEnds" parameter is included and set true - // Angle = 0 is at 6 o'clock position, 90 at 9 o'clock etc. The angles must be in range 0-360 or they will be clipped to these limits - // The start angle may be larger than the end angle. Arcs are always drawn clockwise from the start angle. - void drawSmoothArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool roundEnds = false); - - // As per "drawSmoothArc" except the ends of the arc are NOT anti-aliased, this facilitates dynamic arc length changes with - // arc segments and ensures clean segment joints. - // The sides of the arc are anti-aliased by default. If smoothArc is false sides will NOT be anti-aliased - void drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, uint32_t fg_color, uint32_t bg_color, bool smoothArc = true); - - // Draw an anti-aliased filled circle at x, y with radius r - // Note: The thickness of line is 3 pixels to reduce the visible "braiding" effect of anti-aliasing narrow lines - // this means the inner anti-alias zone is always at r-1 and the outer zone at r+1 - void drawSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t fg_color, uint32_t bg_color); - - // Draw an anti-aliased filled circle at x, y with radius r - // If bg_color is not included the background pixel colour will be read from TFT or sprite - void fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, uint32_t bg_color = 0x00FFFFFF); - - // Draw a rounded rectangle that has a line thickness of r-ir+1 and bounding box defined by x,y and w,h - // The outer corner radius is r, inner corner radius is ir - // The inside and outside of the border are anti-aliased - void drawSmoothRoundRect(int32_t x, int32_t y, int32_t r, int32_t ir, int32_t w, int32_t h, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF, uint8_t quadrants = 0xF); - - // Draw a filled rounded rectangle , corner radius r and bounding box defined by x,y and w,h - void fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color, uint32_t bg_color = 0x00FFFFFF); - - // Draw a small anti-aliased filled circle at ax,ay with radius r (uses drawWideLine) - // If bg_color is not included the background pixel colour will be read from TFT or sprite - void drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF); - - // Draw an anti-aliased wide line from ax,ay to bx,by width wd with radiused ends (radius is wd/2) - // If bg_color is not included the background pixel colour will be read from TFT or sprite - void drawWideLine(float ax, float ay, float bx, float by, float wd, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF); - - // Draw an anti-aliased wide line from ax,ay to bx,by with different width at each end aw, bw and with radiused ends - // If bg_color is not included the background pixel colour will be read from TFT or sprite - void drawWedgeLine(float ax, float ay, float bx, float by, float aw, float bw, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF); - - - // Image rendering - // Swap the byte order for pushImage() and pushPixels() - corrects endianness - void setSwapBytes(bool swap); - bool getSwapBytes(void); - - // Draw bitmap - void drawBitmap( int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor), - drawBitmap( int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor), - drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor), - drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor), - setBitmapColor(uint16_t fgcolor, uint16_t bgcolor); // Define the 2 colours for 1bpp sprites - - // Set TFT pivot point (use when rendering rotated sprites) - void setPivot(int16_t x, int16_t y); - int16_t getPivotX(void), // Get pivot x - getPivotY(void); // Get pivot y - - // The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to another location - // Read a block of pixels to a data buffer, buffer is 16-bit and the size must be at least w * h - void readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); - // Write a block of pixels to the screen which have been read by readRect() - void pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); - - // These are used to render images or sprites stored in RAM arrays (used by Sprite class for 16bpp Sprites) - void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); - void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transparent); - - // These are used to render images stored in FLASH (PROGMEM) - void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transparent); - void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data); - - // These are used by Sprite class pushSprite() member function for 1, 4 and 8 bits per pixel (bpp) colours - // They are not intended to be used with user sketches (but could be) - // Set bpp8 true for 8bpp sprites, false otherwise. The cmap pointer must be specified for 4bpp - void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8 = true, uint16_t *cmap = nullptr); - void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true, uint16_t *cmap = nullptr); - // FLASH version - void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *data, bool bpp8, uint16_t *cmap = nullptr); - - // Render a 16-bit colour image with a 1bpp mask - void pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *img, uint8_t *mask); - - // This next function has been used successfully to dump the TFT screen to a PC for documentation purposes - // It reads a screen area and returns the 3 RGB 8-bit colour values of each pixel in the buffer - // Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes - void readRectRGB(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data); - - - // Text rendering - value returned is the pixel width of the rendered text - int16_t drawNumber(long intNumber, int32_t x, int32_t y, uint8_t font), // Draw integer using specified font number - drawNumber(long intNumber, int32_t x, int32_t y), // Draw integer using current font - - // Decimal is the number of decimal places to render - // Use with setTextDatum() to position values on TFT, and setTextPadding() to blank old displayed values - drawFloat(float floatNumber, uint8_t decimal, int32_t x, int32_t y, uint8_t font), // Draw float using specified font number - drawFloat(float floatNumber, uint8_t decimal, int32_t x, int32_t y), // Draw float using current font - - // Handle char arrays - // Use with setTextDatum() to position string on TFT, and setTextPadding() to blank old displayed strings - drawString(const char *string, int32_t x, int32_t y, uint8_t font), // Draw string using specified font number - drawString(const char *string, int32_t x, int32_t y), // Draw string using current font - drawString(const String& string, int32_t x, int32_t y, uint8_t font),// Draw string using specified font number - drawString(const String& string, int32_t x, int32_t y), // Draw string using current font - - drawCentreString(const char *string, int32_t x, int32_t y, uint8_t font), // Deprecated, use setTextDatum() and drawString() - drawRightString(const char *string, int32_t x, int32_t y, uint8_t font), // Deprecated, use setTextDatum() and drawString() - drawCentreString(const String& string, int32_t x, int32_t y, uint8_t font),// Deprecated, use setTextDatum() and drawString() - drawRightString(const String& string, int32_t x, int32_t y, uint8_t font); // Deprecated, use setTextDatum() and drawString() +class TFT_eSPI : public Print { + friend class TFT_eSprite; // Sprite class has access to protected members + + //--------------------------------------- public ------------------------------------// +public: + TFT_eSPI(int16_t _W = TFT_WIDTH, int16_t _H = TFT_HEIGHT); + + // init() and begin() are equivalent, begin() included for backwards compatibility + // Sketch defined tab colour option is for ST7735 displays only + void init(uint8_t tc = TAB_COLOUR), begin(uint8_t tc = TAB_COLOUR); + + void sleep(bool value); + + // These are virtual so the TFT_eSprite class can override them with sprite specific functions + virtual void drawPixel(int32_t x, int32_t y, uint32_t color), + drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size), + drawLine(int32_t xs, int32_t ys, int32_t xe, int32_t ye, uint32_t color), + drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), + drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), + fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); + + virtual int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font), + drawChar(uint16_t uniCode, int32_t x, int32_t y), height(void), width(void); + + // Read the colour of a pixel at x,y and return value in 565 format + virtual uint16_t readPixel(int32_t x, int32_t y); + + virtual void setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); // Note: start + end coordinates + + // Push (aka write pixel) colours to the set window + virtual void pushColor(uint16_t color); + + // These are non-inlined to enable override + virtual void begin_nin_write(); + virtual void end_nin_write(); + + void setRotation(uint8_t r); // Set the display image orientation to 0, 1, 2 or 3 + uint8_t getRotation(void); // Read the current rotation + + // Change the origin position from the default top left + // Note: setRotation, setViewport and resetViewport will revert origin to top left corner of screen/sprite + void setOrigin(int32_t x, int32_t y); + int32_t getOriginX(void); + int32_t getOriginY(void); + + void invertDisplay(bool i); // Tell TFT to invert all displayed colours + void setDisplayOff(); // Turn off display + void setDisplayOn(); // Turn on display + + // The TFT_eSprite class inherits the following functions (not all are useful to Sprite class + void + setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); // Note: start coordinates + width and height + + // Viewport commands, see "Viewport_Demo" sketch + void setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum = true); + bool checkViewport(int32_t x, int32_t y, int32_t w, int32_t h); + int32_t getViewportX(void); + int32_t getViewportY(void); + int32_t getViewportWidth(void); + int32_t getViewportHeight(void); + bool getViewportDatum(void); + void frameViewport(uint16_t color, int32_t w); + void resetViewport(void); + + // Clip input window to viewport bounds, return false if whole area is out of bounds + bool clipAddrWindow(int32_t *x, int32_t *y, int32_t *w, int32_t *h); + // Clip input window area to viewport bounds, return false if whole area is out of bounds + bool clipWindow(int32_t *xs, int32_t *ys, int32_t *xe, int32_t *ye); + + // Push (aka write pixel) colours to the TFT (use setAddrWindow() first) + void pushColor(uint16_t color, uint32_t len), // Deprecated, use pushBlock() + pushColors(uint16_t *data, uint32_t len, bool swap = true), // With byte swap option + pushColors(uint8_t *data, uint32_t len); // Deprecated, use pushPixels() + + // Write a solid block of a single colour + void pushBlock(uint16_t color, uint32_t len); + + // Write a set of pixels stored in memory, use setSwapBytes(true/false) function to correct endianess + void pushPixels(const void *data_in, uint32_t len); + +// Support for half duplex (bi-directional SDA) SPI bus where MOSI must be switched to input +#ifdef TFT_SDA_READ +#if defined(TFT_eSPI_ENABLE_8_BIT_READ) + uint8_t tft_Read_8(void); // Read 8-bit value from TFT command register +#endif + void + begin_SDA_Read(void); // Begin a read on a half duplex (bi-directional SDA) SPI bus - sets MOSI to input + void end_SDA_Read(void); // Restore MOSI to output +#endif + // Graphics drawing + void fillScreen(uint32_t color), drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color), + drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color), + fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color); + + void fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2); + void fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color1, uint32_t color2); + + void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color), + drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color), + fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color), + fillCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, int32_t delta, uint32_t color), + + drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color), + fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color), + + // Corner 1 Corner 2 Corner 3 + drawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, uint32_t color), + fillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, uint32_t color); + + // Smooth (anti-aliased) graphics drawing + // Draw a pixel blended with the background pixel colour (bg_color) specified, return blended colour + // If the bg_color is not specified, the background pixel colour will be read from TFT or sprite + uint16_t drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha, uint32_t bg_color = 0x00FFFFFF); + + // Draw an anti-aliased (smooth) arc between start and end angles. Arc ends are anti-aliased. + // By default the arc is drawn with square ends unless the "roundEnds" parameter is included and set true + // Angle = 0 is at 6 o'clock position, 90 at 9 o'clock etc. The angles must be in range 0-360 or they will + // be clipped to these limits The start angle may be larger than the end angle. Arcs are always drawn + // clockwise from the start angle. + void drawSmoothArc( + int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, + uint32_t fg_color, uint32_t bg_color, bool roundEnds = false + ); + + // As per "drawSmoothArc" except the ends of the arc are NOT anti-aliased, this facilitates dynamic arc + // length changes with arc segments and ensures clean segment joints. The sides of the arc are + // anti-aliased by default. If smoothArc is false sides will NOT be anti-aliased + void drawArc( + int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t startAngle, uint32_t endAngle, + uint32_t fg_color, uint32_t bg_color, bool smoothArc = true + ); + + // Draw an anti-aliased filled circle at x, y with radius r + // Note: The thickness of line is 3 pixels to reduce the visible "braiding" effect of anti-aliasing narrow + // lines + // this means the inner anti-alias zone is always at r-1 and the outer zone at r+1 + void drawSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t fg_color, uint32_t bg_color); + + // Draw an anti-aliased filled circle at x, y with radius r + // If bg_color is not included the background pixel colour will be read from TFT or sprite + void fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, uint32_t bg_color = 0x00FFFFFF); + + // Draw a rounded rectangle that has a line thickness of r-ir+1 and bounding box defined by x,y and w,h + // The outer corner radius is r, inner corner radius is ir + // The inside and outside of the border are anti-aliased + void drawSmoothRoundRect( + int32_t x, int32_t y, int32_t r, int32_t ir, int32_t w, int32_t h, uint32_t fg_color, + uint32_t bg_color = 0x00FFFFFF, uint8_t quadrants = 0xF + ); + + // Draw a filled rounded rectangle , corner radius r and bounding box defined by x,y and w,h + void fillSmoothRoundRect( + int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color, + uint32_t bg_color = 0x00FFFFFF + ); + + // Draw a small anti-aliased filled circle at ax,ay with radius r (uses drawWideLine) + // If bg_color is not included the background pixel colour will be read from TFT or sprite + void drawSpot(float ax, float ay, float r, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF); + + // Draw an anti-aliased wide line from ax,ay to bx,by width wd with radiused ends (radius is wd/2) + // If bg_color is not included the background pixel colour will be read from TFT or sprite + void drawWideLine( + float ax, float ay, float bx, float by, float wd, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF + ); + + // Draw an anti-aliased wide line from ax,ay to bx,by with different width at each end aw, bw and with + // radiused ends If bg_color is not included the background pixel colour will be read from TFT or sprite + void drawWedgeLine( + float ax, float ay, float bx, float by, float aw, float bw, uint32_t fg_color, + uint32_t bg_color = 0x00FFFFFF + ); + + // Image rendering + // Swap the byte order for pushImage() and pushPixels() - corrects endianness + void setSwapBytes(bool swap); + bool getSwapBytes(void); + + // Draw bitmap + void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor), + drawBitmap( + int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, + uint16_t bgcolor + ), + drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor), + drawXBitmap( + int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, + uint16_t bgcolor + ), + setBitmapColor(uint16_t fgcolor, uint16_t bgcolor); // Define the 2 colours for 1bpp sprites + + // Set TFT pivot point (use when rendering rotated sprites) + void setPivot(int16_t x, int16_t y); + int16_t getPivotX(void), // Get pivot x + getPivotY(void); // Get pivot y + + // The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to + // another location Read a block of pixels to a data buffer, buffer is 16-bit and the size must be at + // least w * h + void readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); + // Write a block of pixels to the screen which have been read by readRect() + void pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); + + // These are used to render images or sprites stored in RAM arrays (used by Sprite class for 16bpp + // Sprites) + void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); + void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transparent); + + // These are used to render images stored in FLASH (PROGMEM) + void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transparent); + void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data); + + // These are used by Sprite class pushSprite() member function for 1, 4 and 8 bits per pixel (bpp) colours + // They are not intended to be used with user sketches (but could be) + // Set bpp8 true for 8bpp sprites, false otherwise. The cmap pointer must be specified for 4bpp + void pushImage( + int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8 = true, uint16_t *cmap = nullptr + ); + void pushImage( + int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true, + uint16_t *cmap = nullptr + ); + // FLASH version + void pushImage( + int32_t x, int32_t y, int32_t w, int32_t h, const uint8_t *data, bool bpp8, uint16_t *cmap = nullptr + ); + + // Render a 16-bit colour image with a 1bpp mask + void pushMaskedImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *img, uint8_t *mask); + + // This next function has been used successfully to dump the TFT screen to a PC for documentation purposes + // It reads a screen area and returns the 3 RGB 8-bit colour values of each pixel in the buffer + // Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes + void readRectRGB(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data); + + // Text rendering - value returned is the pixel width of the rendered text + int16_t drawNumber( + long intNumber, int32_t x, int32_t y, uint8_t font + ), // Draw integer using specified font number + drawNumber(long intNumber, int32_t x, int32_t y), // Draw integer using current font + + // Decimal is the number of decimal places to render + // Use with setTextDatum() to position values on TFT, and setTextPadding() to blank old displayed + // values + drawFloat( + float floatNumber, uint8_t decimal, int32_t x, int32_t y, uint8_t font + ), // Draw float using specified font number + drawFloat(float floatNumber, uint8_t decimal, int32_t x, int32_t y), // Draw float using current font + + // Handle char arrays + // Use with setTextDatum() to position string on TFT, and setTextPadding() to blank old displayed + // strings + drawString( + const char *string, int32_t x, int32_t y, uint8_t font + ), // Draw string using specified font number + drawString(const char *string, int32_t x, int32_t y), // Draw string using current font + drawString( + const String &string, int32_t x, int32_t y, uint8_t font + ), // Draw string using specified font number + drawString(const String &string, int32_t x, int32_t y), // Draw string using current font + + drawCentreString( + const char *string, int32_t x, int32_t y, uint8_t font + ), // Deprecated, use setTextDatum() and drawString() + drawRightString( + const char *string, int32_t x, int32_t y, uint8_t font + ), // Deprecated, use setTextDatum() and drawString() + drawCentreString( + const String &string, int32_t x, int32_t y, uint8_t font + ), // Deprecated, use setTextDatum() and drawString() + drawRightString( + const String &string, int32_t x, int32_t y, uint8_t font + ); // Deprecated, use setTextDatum() and drawString() + + // Text rendering and font handling support functions + void setCursor(int16_t x, int16_t y), // Set cursor for tft.print() + setCursor(int16_t x, int16_t y, uint8_t font); // Set cursor and font number for tft.print() + + int16_t getCursorX(void), // Read current cursor x position (moves with tft.print()) + getCursorY(void); // Read current cursor y position + + void setTextColor(uint16_t color), // Set character (glyph) color only (background not over-written) + setTextColor( + uint16_t fgcolor, uint16_t bgcolor, bool bgfill = false + ), // Set character (glyph) foreground and background colour, optional background fill for smooth + // fonts + setTextSize(uint8_t size); // Set character size multiplier (this increases pixel size) + + void + setTextWrap(bool wrapX, bool wrapY = false); // Turn on/off wrapping of text in TFT width and/or height + + void setTextDatum(uint8_t datum); // Set text datum position (default is top left), see Section 5 above + uint8_t getTextDatum(void); + + void + setTextPadding(uint16_t x_width); // Set text padding (background blanking/over-write) width in pixels + uint16_t getTextPadding(void); // Get text padding - // Text rendering and font handling support functions - void setCursor(int16_t x, int16_t y), // Set cursor for tft.print() - setCursor(int16_t x, int16_t y, uint8_t font); // Set cursor and font number for tft.print() +#ifdef LOAD_GFXFF + void setFreeFont(const GFXfont *f = NULL), // Select the GFX Free Font + setTextFont(uint8_t font); // Set the font number to use in future +#else + void setFreeFont(uint8_t font), // Not used, historical fix to prevent an error + setTextFont(uint8_t font); // Set the font number to use in future +#endif - int16_t getCursorX(void), // Read current cursor x position (moves with tft.print()) - getCursorY(void); // Read current cursor y position + int16_t textWidth(const char *string, uint8_t font), // Returns pixel width of string in specified font + textWidth(const char *string), // Returns pixel width of string in current font + textWidth(const String &string, uint8_t font), // As above for String types + textWidth(const String &string), + fontHeight(int16_t font), // Returns pixel height of specified font + fontHeight(void); // Returns pixel height of current font - void setTextColor(uint16_t color), // Set character (glyph) color only (background not over-written) - setTextColor(uint16_t fgcolor, uint16_t bgcolor, bool bgfill = false), // Set character (glyph) foreground and background colour, optional background fill for smooth fonts - setTextSize(uint8_t size); // Set character size multiplier (this increases pixel size) + // Used by library and Smooth font class to extract Unicode point codes from a UTF8 encoded string + uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining), decodeUTF8(uint8_t c); - void setTextWrap(bool wrapX, bool wrapY = false); // Turn on/off wrapping of text in TFT width and/or height + // Support function to UTF8 decode and draw characters piped through print stream + size_t write(uint8_t); + // size_t write(const uint8_t *buf, size_t len); - void setTextDatum(uint8_t datum); // Set text datum position (default is top left), see Section 5 above - uint8_t getTextDatum(void); + // Used by Smooth font class to fetch a pixel colour for the anti-aliasing + void setCallback(getColorCallback getCol); - void setTextPadding(uint16_t x_width); // Set text padding (background blanking/over-write) width in pixels - uint16_t getTextPadding(void); // Get text padding + uint16_t fontsLoaded(void); // Each bit in returned value represents a font type that is loaded - used for + // debug/error handling only -#ifdef LOAD_GFXFF - void setFreeFont(const GFXfont *f = NULL), // Select the GFX Free Font - setTextFont(uint8_t font); // Set the font number to use in future + // Low level read/write + void spiwrite(uint8_t); // legacy support only +#ifdef RM68120_DRIVER + void writecommand(uint16_t c); // Send a 16-bit command, function resets DC/RS high ready for data + void writeRegister8(uint16_t c, uint8_t d); // Write 8-bit data data to 16-bit command register + void writeRegister16(uint16_t c, uint16_t d); // Write 16-bit data data to 16-bit command register #else - void setFreeFont(uint8_t font), // Not used, historical fix to prevent an error - setTextFont(uint8_t font); // Set the font number to use in future + void writecommand(uint8_t c); // Send an 8-bit command, function resets DC/RS high ready for data #endif + void writedata(uint8_t d); // Send data with DC/RS set high + + void commandList(const uint8_t *addr); // Send a initialisation sequence to TFT stored in FLASH + + uint8_t readcommand8(uint8_t cmd_function, uint8_t index = 0); // read 8 bits from TFT + uint16_t readcommand16(uint8_t cmd_function, uint8_t index = 0); // read 16 bits from TFT + uint32_t readcommand32(uint8_t cmd_function, uint8_t index = 0); // read 32 bits from TFT + + // Colour conversion + // Convert 8-bit red, green and blue to 16 bits + uint16_t color565(uint8_t red, uint8_t green, uint8_t blue); + + // Convert 8-bit colour to 16 bits + uint16_t color8to16(uint8_t color332); + // Convert 16-bit colour to 8 bits + uint8_t color16to8(uint16_t color565); + + // Convert 16-bit colour to/from 24-bit, R+G+B concatenated into LS 24 bits + uint32_t color16to24(uint16_t color565); + uint32_t color24to16(uint32_t color888); + + // Alpha blend 2 colours, see generic "alphaBlend_Test" example + // alpha = 0 = 100% background colour + // alpha = 255 = 100% foreground colour + uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); + + // 16-bit colour alphaBlend with alpha dither (dither reduces colour banding) + uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither); + // 24-bit colour alphaBlend with optional alpha dither + uint32_t alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither = 0); + + // Direct Memory Access (DMA) support functions + // These can be used for SPI writes when using the ESP32 (original) or STM32 processors. + // DMA also works on a RP2040 processor with PIO based SPI and parallel (8 and 16-bit) interfaces + // Bear in mind DMA will only be of benefit in particular circumstances and can be tricky + // to manage by noobs. The functions have however been designed to be noob friendly and + // avoid a few DMA behaviour "gotchas". + // + // At best you will get a 2x TFT rendering performance improvement when using DMA because + // this library handles the SPI bus so efficiently during normal (non DMA) transfers. The best + // performance improvement scenario is the DMA transfer time is exactly the same as the time it + // takes for the processor to prepare the next image buffer and initiate another DMA transfer. + // + // DMA transfer to the TFT is done while the processor moves on to handle other tasks. Bear + // this in mind and watch out for "gotchas" like the image buffer going out of scope as the + // processor leaves a function or its content being changed while the DMA engine is reading it. + // + // The compiler MAY change the implied scope of a buffer which has been set aside by creating + // an array. For example a buffer defined before a "for-next" loop may get de-allocated when + // the loop ends. To avoid this use, for example, malloc() and free() to take control of when + // the buffer space is available and ensure it is not released until DMA is complete. + // + // Clearly you should not modify a buffer that is being DMA'ed to the TFT until the DMA is over. + // Use the dmaBusy() function to check this. Use tft.startWrite() before invoking DMA so the + // TFT chip select stays low. If you use tft.endWrite() before DMA is complete then the endWrite + // function will wait for the DMA to complete, so this may defeat any DMA performance benefit. + // + + bool initDMA( + bool ctrl_cs = false + ); // Initialise the DMA engine and attach to SPI bus - typically used in setup() + // Parameter "true" enables DMA engine control of TFT chip select (ESP32 only) + // For ESP32 only, TFT reads will not work if parameter is true + void deInitDMA(void); // De-initialise the DMA engine and detach from SPI bus - typically not used + + // Push an image to the TFT using DMA, buffer is optional and grabs (double buffers) a copy of the image + // Use the buffer if the image data will get over-written or destroyed while DMA is in progress + // + // Note 1: If swapping colour bytes is defined, and the double buffer option is NOT used, then the bytes + // in the original image buffer content will be byte swapped by the function before DMA is initiated. + // + // Note 2: If part of the image will be off screen or outside of a set viewport, then the the original + // image buffer content will be altered to a correctly clipped image before DMA is initiated. + // + // The function will wait for the last DMA to complete if it is called while a previous DMA is still + // in progress, this simplifies the sketch and helps avoid "gotchas". + void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t *buffer = nullptr); + +#if defined(ESP32) // ESP32 only at the moment + // For case where pointer is a const and the image data must not be modified (clipped or byte swapped) + void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const *data); +#endif + // Push a block of pixels into a window set up using setAddrWindow() + void pushPixelsDMA(uint16_t *image, uint32_t len); + + // Check if the DMA is complete - use while(tft.dmaBusy); for a blocking wait + bool dmaBusy(void); // returns true if DMA is still in progress + void dmaWait(void); // wait until DMA is complete + + bool DMA_Enabled = false; // Flag for DMA enabled state + uint8_t spiBusyCheck = 0; // Number of ESP32 transfer buffers to check + + // Bare metal functions + void startWrite(void); // Begin SPI transaction + void writeColor(uint16_t color, uint32_t len); // Deprecated, use pushBlock() + void endWrite(void); // End SPI transaction + + // Set/get an arbitrary library configuration attribute or option + // Use to switch ON/OFF capabilities such as UTF8 decoding - each attribute has a unique ID + // id = 0: reserved - may be used in future to reset all attributes to a default state + // id = 1: Turn on (a=true) or off (a=false) GLCD cp437 font character error correction + // id = 2: Turn on (a=true) or off (a=false) UTF8 decoding + // id = 3: Enable or disable use of ESP32 PSRAM (if available) +#define CP437_SWITCH 1 +#define UTF8_SWITCH 2 +#define PSRAM_ENABLE 3 + void setAttribute(uint8_t id = 0, uint8_t a = 0); // Set attribute value + uint8_t getAttribute(uint8_t id = 0); // Get attribute value + + // Used for diagnostic sketch to see library setup adopted by compiler, see Section 7 above + void getSetup(setup_t &tft_settings); // Sketch provides the instance to populate + bool verifySetupID(uint32_t id); + + // Global variables +#if !defined(TFT_PARALLEL_8_BIT) && !defined(RP2040_PIO_INTERFACE) + static SPIClass &getSPIinstance(void); // Get SPI class handle +#endif + uint32_t textcolor, textbgcolor; // Text foreground and background colours - int16_t textWidth(const char *string, uint8_t font), // Returns pixel width of string in specified font - textWidth(const char *string), // Returns pixel width of string in current font - textWidth(const String& string, uint8_t font), // As above for String types - textWidth(const String& string), - fontHeight(int16_t font), // Returns pixel height of specified font - fontHeight(void); // Returns pixel height of current font - - // Used by library and Smooth font class to extract Unicode point codes from a UTF8 encoded string - uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining), - decodeUTF8(uint8_t c); + uint32_t bitmap_fg, bitmap_bg; // Bitmap foreground (bit=1) and background (bit=0) colours - // Support function to UTF8 decode and draw characters piped through print stream - size_t write(uint8_t); - // size_t write(const uint8_t *buf, size_t len); + uint8_t textfont, // Current selected font number + textsize, // Current font size multiplier + textdatum, // Text reference datum + rotation; // Display rotation (0-3) - // Used by Smooth font class to fetch a pixel colour for the anti-aliasing - void setCallback(getColorCallback getCol); + uint8_t decoderState = 0; // UTF8 decoder state - not for user access + uint16_t decoderBuffer; // Unicode code-point buffer - not for user access - uint16_t fontsLoaded(void); // Each bit in returned value represents a font type that is loaded - used for debug/error handling only + // Moved here to Core2 capture it + bool locked, inTransaction, lockTransaction; // SPI transaction and mutex lock flags + int32_t cursor_x, cursor_y, padX; // Text cursor x,y and padding setting + //--------------------------------------- private ------------------------------------// +private: + // Legacy begin and end prototypes - deprecated TODO: delete + void spi_begin(); + void spi_end(); + void spi_begin_read(); + void spi_end_read(); - // Low level read/write - void spiwrite(uint8_t); // legacy support only -#ifdef RM68120_DRIVER - void writecommand(uint16_t c); // Send a 16-bit command, function resets DC/RS high ready for data - void writeRegister8(uint16_t c, uint8_t d); // Write 8-bit data data to 16-bit command register - void writeRegister16(uint16_t c, uint16_t d); // Write 16-bit data data to 16-bit command register -#else - void writecommand(uint8_t c); // Send an 8-bit command, function resets DC/RS high ready for data -#endif - void writedata(uint8_t d); // Send data with DC/RS set high - - void commandList(const uint8_t *addr); // Send a initialisation sequence to TFT stored in FLASH - - uint8_t readcommand8( uint8_t cmd_function, uint8_t index = 0); // read 8 bits from TFT - uint16_t readcommand16(uint8_t cmd_function, uint8_t index = 0); // read 16 bits from TFT - uint32_t readcommand32(uint8_t cmd_function, uint8_t index = 0); // read 32 bits from TFT - - - // Colour conversion - // Convert 8-bit red, green and blue to 16 bits - uint16_t color565(uint8_t red, uint8_t green, uint8_t blue); - - // Convert 8-bit colour to 16 bits - uint16_t color8to16(uint8_t color332); - // Convert 16-bit colour to 8 bits - uint8_t color16to8(uint16_t color565); - - // Convert 16-bit colour to/from 24-bit, R+G+B concatenated into LS 24 bits - uint32_t color16to24(uint16_t color565); - uint32_t color24to16(uint32_t color888); - - // Alpha blend 2 colours, see generic "alphaBlend_Test" example - // alpha = 0 = 100% background colour - // alpha = 255 = 100% foreground colour - uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); - - // 16-bit colour alphaBlend with alpha dither (dither reduces colour banding) - uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither); - // 24-bit colour alphaBlend with optional alpha dither - uint32_t alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither = 0); - - // Direct Memory Access (DMA) support functions - // These can be used for SPI writes when using the ESP32 (original) or STM32 processors. - // DMA also works on a RP2040 processor with PIO based SPI and parallel (8 and 16-bit) interfaces - // Bear in mind DMA will only be of benefit in particular circumstances and can be tricky - // to manage by noobs. The functions have however been designed to be noob friendly and - // avoid a few DMA behaviour "gotchas". - // - // At best you will get a 2x TFT rendering performance improvement when using DMA because - // this library handles the SPI bus so efficiently during normal (non DMA) transfers. The best - // performance improvement scenario is the DMA transfer time is exactly the same as the time it - // takes for the processor to prepare the next image buffer and initiate another DMA transfer. - // - // DMA transfer to the TFT is done while the processor moves on to handle other tasks. Bear - // this in mind and watch out for "gotchas" like the image buffer going out of scope as the - // processor leaves a function or its content being changed while the DMA engine is reading it. - // - // The compiler MAY change the implied scope of a buffer which has been set aside by creating - // an array. For example a buffer defined before a "for-next" loop may get de-allocated when - // the loop ends. To avoid this use, for example, malloc() and free() to take control of when - // the buffer space is available and ensure it is not released until DMA is complete. - // - // Clearly you should not modify a buffer that is being DMA'ed to the TFT until the DMA is over. - // Use the dmaBusy() function to check this. Use tft.startWrite() before invoking DMA so the - // TFT chip select stays low. If you use tft.endWrite() before DMA is complete then the endWrite - // function will wait for the DMA to complete, so this may defeat any DMA performance benefit. - // - - bool initDMA(bool ctrl_cs = false); // Initialise the DMA engine and attach to SPI bus - typically used in setup() - // Parameter "true" enables DMA engine control of TFT chip select (ESP32 only) - // For ESP32 only, TFT reads will not work if parameter is true - void deInitDMA(void); // De-initialise the DMA engine and detach from SPI bus - typically not used - - // Push an image to the TFT using DMA, buffer is optional and grabs (double buffers) a copy of the image - // Use the buffer if the image data will get over-written or destroyed while DMA is in progress - // - // Note 1: If swapping colour bytes is defined, and the double buffer option is NOT used, then the bytes - // in the original image buffer content will be byte swapped by the function before DMA is initiated. - // - // Note 2: If part of the image will be off screen or outside of a set viewport, then the the original - // image buffer content will be altered to a correctly clipped image before DMA is initiated. - // - // The function will wait for the last DMA to complete if it is called while a previous DMA is still - // in progress, this simplifies the sketch and helps avoid "gotchas". - void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* data, uint16_t* buffer = nullptr); - -#if defined (ESP32) // ESP32 only at the moment - // For case where pointer is a const and the image data must not be modified (clipped or byte swapped) - void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const* data); -#endif - // Push a block of pixels into a window set up using setAddrWindow() - void pushPixelsDMA(uint16_t* image, uint32_t len); - - // Check if the DMA is complete - use while(tft.dmaBusy); for a blocking wait - bool dmaBusy(void); // returns true if DMA is still in progress - void dmaWait(void); // wait until DMA is complete - - bool DMA_Enabled = false; // Flag for DMA enabled state - uint8_t spiBusyCheck = 0; // Number of ESP32 transfer buffers to check - - // Bare metal functions - void startWrite(void); // Begin SPI transaction - void writeColor(uint16_t color, uint32_t len); // Deprecated, use pushBlock() - void endWrite(void); // End SPI transaction - - // Set/get an arbitrary library configuration attribute or option - // Use to switch ON/OFF capabilities such as UTF8 decoding - each attribute has a unique ID - // id = 0: reserved - may be used in future to reset all attributes to a default state - // id = 1: Turn on (a=true) or off (a=false) GLCD cp437 font character error correction - // id = 2: Turn on (a=true) or off (a=false) UTF8 decoding - // id = 3: Enable or disable use of ESP32 PSRAM (if available) - #define CP437_SWITCH 1 - #define UTF8_SWITCH 2 - #define PSRAM_ENABLE 3 - void setAttribute(uint8_t id = 0, uint8_t a = 0); // Set attribute value - uint8_t getAttribute(uint8_t id = 0); // Get attribute value - - // Used for diagnostic sketch to see library setup adopted by compiler, see Section 7 above - void getSetup(setup_t& tft_settings); // Sketch provides the instance to populate - bool verifySetupID(uint32_t id); - - // Global variables -#if !defined (TFT_PARALLEL_8_BIT) && !defined (RP2040_PIO_INTERFACE) - static SPIClass& getSPIinstance(void); // Get SPI class handle -#endif - uint32_t textcolor, textbgcolor; // Text foreground and background colours - - uint32_t bitmap_fg, bitmap_bg; // Bitmap foreground (bit=1) and background (bit=0) colours - - uint8_t textfont, // Current selected font number - textsize, // Current font size multiplier - textdatum, // Text reference datum - rotation; // Display rotation (0-3) - - uint8_t decoderState = 0; // UTF8 decoder state - not for user access - uint16_t decoderBuffer; // Unicode code-point buffer - not for user access - - //Moved here to Core2 capture it - bool locked, inTransaction, lockTransaction; // SPI transaction and mutex lock flags - int32_t cursor_x, cursor_y, padX; // Text cursor x,y and padding setting - //--------------------------------------- private ------------------------------------// - private: - // Legacy begin and end prototypes - deprecated TODO: delete - void spi_begin(); - void spi_end(); - - void spi_begin_read(); - void spi_end_read(); - - // New begin and end prototypes - // begin/end a TFT write transaction - // For SPI bus the transmit clock rate is set - inline void begin_tft_write() __attribute__((always_inline)); - inline void end_tft_write() __attribute__((always_inline)); - - // begin/end a TFT read transaction - // For SPI bus: begin lowers SPI clock rate, end reinstates transmit clock rate - inline void begin_tft_read() __attribute__((always_inline)); - inline void end_tft_read() __attribute__((always_inline)); - - // Initialise the data bus GPIO and hardware interfaces - void initBus(void); + // New begin and end prototypes + // begin/end a TFT write transaction + // For SPI bus the transmit clock rate is set + inline void begin_tft_write() __attribute__((always_inline)); + inline void end_tft_write() __attribute__((always_inline)); - // Temporary library development function TODO: remove need for this - void pushSwapBytePixels(const void* data_in, uint32_t len); + // begin/end a TFT read transaction + // For SPI bus: begin lowers SPI clock rate, end reinstates transmit clock rate + inline void begin_tft_read() __attribute__((always_inline)); + inline void end_tft_read() __attribute__((always_inline)); - // Same as setAddrWindow but exits with CGRAM in read mode - void readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); + // Initialise the data bus GPIO and hardware interfaces + void initBus(void); - // Byte read prototype - uint8_t readByte(void); + // Temporary library development function TODO: remove need for this + void pushSwapBytePixels(const void *data_in, uint32_t len); - // GPIO parallel bus input/output direction control - void busDir(uint32_t mask, uint8_t mode); + // Same as setAddrWindow but exits with CGRAM in read mode + void readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); - // Single GPIO input/output direction control - void gpioMode(uint8_t gpio, uint8_t mode); + // Byte read prototype + uint8_t readByte(void); - // Smooth graphics helper - uint8_t sqrt_fraction(uint32_t num); + // GPIO parallel bus input/output direction control + void busDir(uint32_t mask, uint8_t mode); - // Helper function: calculate distance of a point from a finite length line between two points - float wedgeLineDistance(float pax, float pay, float bax, float bay, float dr); + // Single GPIO input/output direction control + void gpioMode(uint8_t gpio, uint8_t mode); - // Display variant settings - uint8_t tabcolor, // ST7735 screen protector "tab" colour (now invalid) - colstart = 0, rowstart = 0; // Screen display area to CGRAM area coordinate offsets + // Smooth graphics helper + uint8_t sqrt_fraction(uint32_t num); - // Port and pin masks for control signals (ESP826 only) - TODO: remove need for this - volatile uint32_t *dcport, *csport; - uint32_t cspinmask, dcpinmask, wrpinmask, sclkpinmask; + // Helper function: calculate distance of a point from a finite length line between two points + float wedgeLineDistance(float pax, float pay, float bax, float bay, float dr); - #if defined(ESP32_PARALLEL) - // Bit masks for ESP32 parallel bus interface - uint32_t xclr_mask, xdir_mask; // Port set/clear and direction control masks + // Display variant settings + uint8_t tabcolor, // ST7735 screen protector "tab" colour (now invalid) + colstart = 0, rowstart = 0; // Screen display area to CGRAM area coordinate offsets - // Lookup table for ESP32 parallel bus interface uses 1kbyte RAM, - uint32_t xset_mask[256]; // Makes Sprite rendering test 33% faster, for slower macro equivalent - // see commented out #define set_mask(C) within TFT_eSPI_ESP32.h - #endif + // Port and pin masks for control signals (ESP826 only) - TODO: remove need for this + volatile uint32_t *dcport, *csport; + uint32_t cspinmask, dcpinmask, wrpinmask, sclkpinmask; - //uint32_t lastColor = 0xFFFF; // Last colour - used to minimise bit shifting overhead +#if defined(ESP32_PARALLEL) + // Bit masks for ESP32 parallel bus interface + uint32_t xclr_mask, xdir_mask; // Port set/clear and direction control masks - getColorCallback getColor = nullptr; // Smooth font callback function pointer + // Lookup table for ESP32 parallel bus interface uses 1kbyte RAM, + uint32_t xset_mask[256]; // Makes Sprite rendering test 33% faster, for slower macro equivalent + // see commented out #define set_mask(C) within TFT_eSPI_ESP32.h +#endif + // uint32_t lastColor = 0xFFFF; // Last colour - used to minimise bit shifting overhead - //-------------------------------------- protected ----------------------------------// - protected: + getColorCallback getColor = nullptr; // Smooth font callback function pointer - //int32_t win_xe, win_ye; // Window end coords - not needed + //-------------------------------------- protected ----------------------------------// +protected: + // int32_t win_xe, win_ye; // Window end coords - not needed - int32_t _init_width, _init_height; // Display w/h as input, used by setRotation() - int32_t _width, _height; // Display w/h as modified by current rotation - int32_t addr_row, addr_col; // Window position - used to minimise window commands + int32_t _init_width, _init_height; // Display w/h as input, used by setRotation() + int32_t _width, _height; // Display w/h as modified by current rotation + int32_t addr_row, addr_col; // Window position - used to minimise window commands - int16_t _xPivot; // TFT x pivot point coordinate for rotated Sprites - int16_t _yPivot; // TFT x pivot point coordinate for rotated Sprites + int16_t _xPivot; // TFT x pivot point coordinate for rotated Sprites + int16_t _yPivot; // TFT x pivot point coordinate for rotated Sprites - // Viewport variables - int32_t _vpX, _vpY, _vpW, _vpH; // Note: x start, y start, x end + 1, y end + 1 - int32_t _xDatum; - int32_t _yDatum; - int32_t _xWidth; - int32_t _yHeight; - bool _vpDatum; - bool _vpOoB; + // Viewport variables + int32_t _vpX, _vpY, _vpW, _vpH; // Note: x start, y start, x end + 1, y end + 1 + int32_t _xDatum; + int32_t _yDatum; + int32_t _xWidth; + int32_t _yHeight; + bool _vpDatum; + bool _vpOoB; - int32_t bg_cursor_x; // Background fill cursor - int32_t last_cursor_x; // Previous text cursor position when fill used + int32_t bg_cursor_x; // Background fill cursor + int32_t last_cursor_x; // Previous text cursor position when fill used - uint32_t fontsloaded; // Bit field of fonts loaded + uint32_t fontsloaded; // Bit field of fonts loaded - uint8_t glyph_ab, // Smooth font glyph delta Y (height) above baseline - glyph_bb; // Smooth font glyph delta Y (height) below baseline + uint8_t glyph_ab, // Smooth font glyph delta Y (height) above baseline + glyph_bb; // Smooth font glyph delta Y (height) below baseline - bool isDigits; // adjust bounding box for numbers to reduce visual jiggling - bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display - bool _swapBytes; // Swap the byte order for TFT pushImage() + bool isDigits; // adjust bounding box for numbers to reduce visual jiggling + bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display + bool _swapBytes; // Swap the byte order for TFT pushImage() - bool _booted; // init() or begin() has already run once + bool _booted; // init() or begin() has already run once - // User sketch manages these via set/getAttribute() - bool _cp437; // If set, use correct CP437 charset (default is OFF) - bool _utf8; // If set, use UTF-8 decoder in print stream 'write()' function (default ON) - bool _psram_enable; // Enable PSRAM use for library functions (TBD) and Sprites + // User sketch manages these via set/getAttribute() + bool _cp437; // If set, use correct CP437 charset (default is OFF) + bool _utf8; // If set, use UTF-8 decoder in print stream 'write()' function (default ON) + bool _psram_enable; // Enable PSRAM use for library functions (TBD) and Sprites - uint32_t _lastColor; // Buffered value of last colour used + uint32_t _lastColor; // Buffered value of last colour used - bool _fillbg; // Fill background flag (just for for smooth fonts at the moment) + bool _fillbg; // Fill background flag (just for for smooth fonts at the moment) -#if defined (SSD1963_DRIVER) - uint16_t Cswap; // Swap buffer for SSD1963 - uint8_t r6, g6, b6; // RGB buffer for SSD1963 +#if defined(SSD1963_DRIVER) + uint16_t Cswap; // Swap buffer for SSD1963 + uint8_t r6, g6, b6; // RGB buffer for SSD1963 #endif #ifdef LOAD_GFXFF - GFXfont *gfxFont; + GFXfont *gfxFont; #endif /*************************************************************************************** @@ -966,42 +1016,43 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac ***************************************************************************************/ // Load the Touch extension #ifdef TOUCH_CS - #if defined (TFT_PARALLEL_8_BIT) || defined (RP2040_PIO_INTERFACE) - #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) - #error >>>>------>> Touch functions not supported in 8/16-bit parallel mode or with RP2040 PIO. - #endif - #else - #include "Extensions/Touch.h" // Loaded if TOUCH_CS is defined by user - #endif +#if defined(TFT_PARALLEL_8_BIT) || defined(RP2040_PIO_INTERFACE) +#if !defined(DISABLE_ALL_LIBRARY_WARNINGS) +#error >>>>------>> Touch functions not supported in 8/16-bit parallel mode or with RP2040 PIO. +#endif #else - #if !defined(DISABLE_ALL_LIBRARY_WARNINGS) - #warning >>>>------>> TOUCH_CS pin not defined, TFT_eSPI touch functions will not be available! - #endif +#include "Extensions/Touch.h" // Loaded if TOUCH_CS is defined by user +#endif +#else +#if !defined(DISABLE_ALL_LIBRARY_WARNINGS) +#warning >>>>------>> TOUCH_CS pin not defined, TFT_eSPI touch functions will not be available! +#endif #endif // Load the Anti-aliased font extension #ifdef SMOOTH_FONT - #include "Extensions/Smooth_font.h" // Loaded if SMOOTH_FONT is defined by user +#include "Extensions/Smooth_font.h" // Loaded if SMOOTH_FONT is defined by user #endif }; // End of class TFT_eSPI // Swap any type -template static inline void -transpose(T& a, T& b) { T t = a; a = b; b = t; } +template static inline void transpose(T &a, T &b) { + T t = a; + a = b; + b = t; +} // Fast alphaBlend -template static inline uint16_t -fastBlend(A alpha, F fgc, B bgc) -{ - // Split out and blend 5-bit red and blue channels - uint32_t rxb = bgc & 0xF81F; - rxb += ((fgc & 0xF81F) - rxb) * (alpha >> 2) >> 6; - // Split out and blend 6-bit green channel - uint32_t xgx = bgc & 0x07E0; - xgx += ((fgc & 0x07E0) - xgx) * alpha >> 8; - // Recombine channels - return (rxb & 0xF81F) | (xgx & 0x07E0); +template static inline uint16_t fastBlend(A alpha, F fgc, B bgc) { + // Split out and blend 5-bit red and blue channels + uint32_t rxb = bgc & 0xF81F; + rxb += ((fgc & 0xF81F) - rxb) * (alpha >> 2) >> 6; + // Split out and blend 6-bit green channel + uint32_t xgx = bgc & 0x07E0; + xgx += ((fgc & 0x07E0) - xgx) * alpha >> 8; + // Recombine channels + return (rxb & 0xF81F) | (xgx & 0x07E0); } /*************************************************************************************** diff --git a/patch-c5.py b/patch-c5.py new file mode 100644 index 000000000..f0e96d3fd --- /dev/null +++ b/patch-c5.py @@ -0,0 +1,171 @@ +import hashlib +from typing import TYPE_CHECKING, Any +import requests + +if TYPE_CHECKING: + Import: Any = None + env: Any = {} + +import glob +import gzip +from os import makedirs, remove, rename +from os.path import basename, dirname, exists, isfile, join + +Import("env") # type: ignore + +FRAMEWORK_DIR = env.PioPlatform().get_package_dir("framework-arduinoespressif32-libs") +board_mcu = env.BoardConfig() +mcu = board_mcu.get("build.mcu", "") +patchflag_path = join(FRAMEWORK_DIR, mcu, "lib", ".patched") + + +# patch file only if we didn't do it befored + +if not isfile(join(FRAMEWORK_DIR, mcu, "lib", ".patched")): + original_file = join(FRAMEWORK_DIR, mcu, "lib", "libnet80211.a") + patched_file = join( + FRAMEWORK_DIR, mcu, "lib", "libnet80211.a.patched" + ) + + env.Execute( + "pio pkg exec -p toolchain-riscv32-esp -- riscv32-esp-elf-objcopy --weaken-symbol=s %s %s" + % (original_file, patched_file) + ) + if isfile("%s.old" % (original_file)): + remove("%s.old" % (original_file)) + rename(original_file, "%s.old" % (original_file)) + env.Execute( + "pio pkg exec -p toolchain-riscv32-esp -- riscv32-esp-elf-objcopy --weaken-symbol=ieee80211_raw_frame_sanity_check %s %s" + % (patched_file, original_file) + ) + + def _touch(path): + with open(path, "w") as fp: + fp.write("") + + env.Execute(lambda *args, **kwargs: _touch(patchflag_path)) + + +def hash_file(file_path): + """Generate SHA-256 hash for a single file.""" + hasher = hashlib.sha256() + with open(file_path, "rb") as f: + # Read the file in chunks to avoid memory issues + for chunk in iter(lambda: f.read(4096), b""): + hasher.update(chunk) + return hasher.hexdigest() + + +def hash_files(file_paths): + """Generate a combined hash for multiple files.""" + combined_hash = hashlib.sha256() + + for file_path in file_paths: + file_hash = hash_file(file_path) + combined_hash.update(file_hash.encode("utf-8")) # Update with the file's hash + + return combined_hash.hexdigest() + + +def save_checksum_file(hash_value, output_file): + """Save the hash value to a specified output file.""" + with open(output_file, "w") as f: + f.write(hash_value) + + +def load_checksum_file(input_file): + """Load the hash value from a specified input file.""" + with open(input_file, "r") as f: + return f.readline().strip() + +def minify_css(c): + minify_req = requests.post("https://www.toptal.com/developers/cssminifier/api/raw", {"input": c.read().decode('utf-8')}) + return c if minify_req is False else minify_req.text.encode('utf-8') + +def minify_js(js): + minify_req = requests.post('https://www.toptal.com/developers/javascript-minifier/api/raw', {'input': js.read().decode('utf-8')}) + return js if minify_req is False else minify_req.text.encode('utf-8') + +def minify_html(html): + minify_req = requests.post('https://www.toptal.com/developers/html-minifier/api/raw', {'input': html.read().decode('utf-8')}) + return html if minify_req is False else minify_req.text.encode('utf-8') + +# gzip web files +def prepare_www_files(): + HEADER_FILE = join(env.get("PROJECT_DIR"), "include", "webFiles.h") + filetypes_to_gzip = ["html", "css", "js"] + data_src_dir = join(env.get("PROJECT_DIR"), "embedded_resources/web_interface") + checksum_file = join(data_src_dir, "checksum.sha256") + checksum = "" + + if not exists(data_src_dir): + print(f'Error: Source directory "{data_src_dir}" does not exist!') + return + + if exists(checksum_file): + checksum = load_checksum_file(checksum_file) + + files_to_gzip = [] + for extension in filetypes_to_gzip: + files_to_gzip.extend(glob.glob(join(data_src_dir, "*." + extension))) + + files_checksum = hash_files(files_to_gzip) + if files_checksum == checksum: + print("[GZIP & EMBED INTO HEADER] - Nothing to process.") + return + + print(f"[GZIP & EMBED INTO HEADER] - Processing {len(files_to_gzip)} files.") + + makedirs(dirname(HEADER_FILE), exist_ok=True) + + with open(HEADER_FILE, "w") as header: + header.write( + "#ifndef WEB_FILES_H\n#define WEB_FILES_H\n\n#include \n\n" + ) + header.write( + "// THIS FILE IS AUTOGENERATED DO NOT MODIFY IT. MODIFY FILES IN /embedded_resources/web_interface\n\n" + ) + + for file in files_to_gzip: + gz_file = file + ".gz" + with open(file, "rb") as src, gzip.open(gz_file, "wb") as dst: + ext = basename(file).rsplit(".", 1)[-1].lower() + if ext == 'html': + minified = minify_html(src) + elif ext == 'css': + minified = minify_css(src) + elif ext == 'js': + minified = minify_js(src) + else: + raise ValueError(f"Unsupported file type: {ext}") + + dst.write(minified) + + with open(gz_file, "rb") as gz: + compressed_data = gz.read() + var_name = basename(file).replace(".", "_") + + header.write(f"const uint8_t {var_name}[] PROGMEM = {{\n") + + # Write hex values, inserting a newline every 15 bytes + for i in range(0, len(compressed_data), 15): + hex_chunk = ", ".join( + f"0x{byte:02X}" for byte in compressed_data[i : i + 15] + ) + header.write(f" {hex_chunk},\n") + + header.write("};\n\n") + header.write( + f"const uint32_t {var_name}_size = {len(compressed_data)};\n\n" + ) + + remove(gz_file) # Clean up temporary gzip file + + header.write("#endif // WEB_FILES_H\n") + + save_checksum_file(files_checksum, checksum_file) + + print(f"[DONE] Gzipped files embedded into {HEADER_FILE}") + + +prepare_www_files() diff --git a/patch.py b/patch.py index 062baacad..fa3536117 100644 --- a/patch.py +++ b/patch.py @@ -13,16 +13,16 @@ Import("env") # type: ignore -FRAMEWORK_DIR = env.PioPlatform().get_package_dir("framework-arduinoespressif32") +FRAMEWORK_DIR = env.PioPlatform().get_package_dir("framework-arduinoespressif32-libs") board_mcu = env.BoardConfig() mcu = board_mcu.get("build.mcu", "") -patchflag_path = join(FRAMEWORK_DIR, "tools", "sdk", mcu, "lib", ".patched") +patchflag_path = join(FRAMEWORK_DIR,mcu, "lib", ".patched") # patch file only if we didn't do it befored -if not isfile(patchflag_path): - original_file = join(FRAMEWORK_DIR, "tools", "sdk", mcu, "lib", "libnet80211.a") +if not isfile(join(FRAMEWORK_DIR,mcu, "lib", ".patched")): + original_file = join(FRAMEWORK_DIR,mcu, "lib", "libnet80211.a") patched_file = join( - FRAMEWORK_DIR, "tools", "sdk", mcu, "lib", "libnet80211.a.patched" + FRAMEWORK_DIR, mcu, "lib", "libnet80211.a.patched" ) env.Execute( diff --git a/platformio.ini b/platformio.ini index 0fed322a5..692d7d9a0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -54,6 +54,8 @@ default_envs = ;LAUNCHER_Marauder-V4-V6 ;LAUNCHER_Marauder-v61 ;Awok-Touch" + ;esp32-c5 + ;uncomment to not use global dirs to avoid possible conflicts ;platforms_dir = .pio/platforms ;packages_dir = .pio/packages @@ -66,9 +68,14 @@ extra_configs = boards/*/*.ini [env] -platform = espressif32 +platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip platform_packages = - framework-arduinoespressif32 @ https://github.com/bmorcelli/arduino-esp32/releases/download/2.0.17e/esp32-2.0.17e.zip + ;framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs-idf-release_v5.5-b66b5448-v1.zip + framework-arduinoespressif32-libs @ https://github.com/bmorcelli/esp32-arduino-lib-builder/releases/download/idf-release_v5.5/esp32-arduino-libs.zip +; Use with framework 2.0.17 +; platform_packages = +; framework-arduinoespressif32 @ https://github.com/bmorcelli/arduino-esp32/releases/download/2.0.17e/esp32-2.0.17e.zip + monitor_filters = esp32_exception_decoder, send_on_enter, colorize framework = arduino board_build.variants_dir = boards @@ -81,6 +88,7 @@ build_src_flags = -Wignored-qualifiers ; -Wmissing-field-initializers ; -Wsign-compare ; commented because it produces too much warnings, some of them are imposible to fix due to external deps + -Woverloaded-virtual=0 -Wtype-limits -Wno-unused-label -Wno-comment @@ -103,6 +111,7 @@ build_flags = ; This setting let RF Spectrum to work with LED interface with FastLED on ESP32-S3 -DCONFIG_ASYNC_TCP_RUNNING_CORE=-1 ; Runs on any core, added to disable the following flag -DCONFIG_ASYNC_TCP_USE_WDT=0 ; Disables the Watchdog timer on Async TCP, to avoid restartings during file uploads + -DAUDIO_USE_IDF5_DRIVER=1 extra_scripts = pre:patch.py @@ -110,19 +119,20 @@ extra_scripts = post:build.py lib_deps = - WireGuard-ESP32 - IRremoteESP8266 + https://github.com/sayacom/WireGuard-ESP32-Arduino#feature/esp-netif + ;WireGuard-ESP32 + https://github.com/BorisKofman/IRremoteESP8266#Espressif-version-3 + ;IRremoteESP8266 Time LibSSH-ESP32 - bakadave/PCA9554 https://github.com/bmorcelli/ESPping Adafruit BusIO=https://github.com/emericklaw/Adafruit-BusIO_Bruce Adafruit PN532=https://github.com/emericklaw/Adafruit-PN532_Bruce https://github.com/rennancockles/Arduino_MFRC522v2.git - https://github.com/rennancockles/ESP-ChameleonUltra - https://github.com/rennancockles/ESP-Amiibolink + https://github.com/bmorcelli/ESP-ChameleonUltra + https://github.com/bmorcelli/ESP-Amiibolink https://github.com/rennancockles/SimpleCLI - https://github.com/whywilson/ESP-PN532BLE + https://github.com/bmorcelli/ESP-PN532BLE https://github.com/whywilson/ESP-PN532-UART@^0.0.2 https://github.com/whywilson/ESP-PN532Killer@^0.0.5 NTPClient @@ -130,24 +140,133 @@ lib_deps = ESP32Time bblanchon/ArduinoJson https://github.com/bmorcelli/rc-switch - ESP8266Audio + https://github.com/bmorcelli/ESP8266Audio#codex/update-library-for-esp-idf-5.x-compatibility FFat earlephilhower/ESP8266SAM@^1.0.1 mikalhart/TinyGPSPlus tinyu-zhao/FFT@^0.0.1 - h2zero/NimBLE-Arduino@^1.4.0 + h2zero/NimBLE-Arduino@^2.3.3 nrf24/RF24 @ 1.4.11 Adafruit Si4713 Library@1.2.3 Bodmer/JPEGDecoder https://github.com/bmorcelli/SmartRC-CC1101-Driver-Lib/ ducktape=https://github.com/bmorcelli/duktape/releases/download/2.7.0-lite/duktape-2.7.0.zip - paulstoffregen/OneWire@^2.3.8 + ;paulstoffregen/OneWire@^2.3.8 + https://github.com/bmorcelli/OneWire#patch-1 ;jackjansen/esp32_idf5_https_server_compat - tobozo/ESP32-PSRamFS + https://github.com/bmorcelli/ESP32-PsRamFS#patch-1 ;chegewara/EspTinyUSB bitbank2/AnimatedGIF bitbank2/PNGdec @ ^1.1.2 ESP32Async/ESPAsyncWebServer - https://github.com/pschatzmann/arduino-audio-driver + https://github.com/bmorcelli/FastLED + +; Use with framework 2.0.17 +; lib_deps = +; WireGuard-ESP32 +; IRremoteESP8266 +; Time +; LibSSH-ESP32 +; bakadave/PCA9554 +; https://github.com/bmorcelli/ESPping +; Adafruit BusIO=https://github.com/emericklaw/Adafruit-BusIO_Bruce +; Adafruit PN532=https://github.com/emericklaw/Adafruit-PN532_Bruce +; https://github.com/rennancockles/Arduino_MFRC522v2.git +; https://github.com/rennancockles/ESP-ChameleonUltra +; https://github.com/rennancockles/ESP-Amiibolink +; https://github.com/rennancockles/SimpleCLI +; https://github.com/whywilson/ESP-PN532BLE +; https://github.com/whywilson/ESP-PN532-UART@^0.0.2 +; https://github.com/whywilson/ESP-PN532Killer@^0.0.4 +; NTPClient +; Timezone +; ESP32Time +; bblanchon/ArduinoJson +; https://github.com/bmorcelli/rc-switch +; ESP8266Audio +; FFat +; earlephilhower/ESP8266SAM@^1.0.1 +; mikalhart/TinyGPSPlus +; tinyu-zhao/FFT@^0.0.1 +; h2zero/NimBLE-Arduino@^1.4.0 +; nrf24/RF24 @ 1.4.11 +; Adafruit Si4713 Library@1.2.3 +; Bodmer/JPEGDecoder +; https://github.com/bmorcelli/SmartRC-CC1101-Driver-Lib/ +; ducktape=https://github.com/bmorcelli/duktape/releases/download/2.7.0-lite/duktape-2.7.0.zip +; paulstoffregen/OneWire@^2.3.8 +; ;jackjansen/esp32_idf5_https_server_compat +; tobozo/ESP32-PSRamFS +; ;chegewara/EspTinyUSB +; bitbank2/AnimatedGIF +; bitbank2/PNGdec @ ^1.1.2 +; ESP32Async/ESPAsyncWebServer monitor_speed = 115200 + + + +[env_light] +extends = env +build_flags = + -Os + -DCORE_DEBUG_LEVEL=0 + -DCONFIG_ESP32_JTAG_SUPPORT_DISABLE=1 + -DLITE_VERSION=1 + -D_IR_ENABLE_DEFAULT_=false + -DDECODE_NEC=true + -DSEND_NEC=true + -DDECODE_SAMSUNG=true + -DSEND_SAMSUNG=true + -DDECODE_RC5=true + -DSEND_RC5=true + -DDECODE_RC6=true + -DSEND_RC6=true + -DDECODE_LG=true + -DSEND_LG=true + -DDECODE_SONY=true + -DSEND_SONY=true + -DSEND_PANASONIC=true + -DDECODE_PANASONIC=true + -DSEND_RAW=true + +lib_deps = + ;https://github.com/sayacom/WireGuard-ESP32-Arduino#feature/esp-netif + ;WireGuard-ESP32 + https://github.com/BorisKofman/IRremoteESP8266#Espressif-version-3 + ;IRremoteESP8266 + Time + ;LibSSH-ESP32 + https://github.com/bmorcelli/ESPping + Adafruit BusIO=https://github.com/emericklaw/Adafruit-BusIO_Bruce + Adafruit PN532=https://github.com/emericklaw/Adafruit-PN532_Bruce + https://github.com/rennancockles/Arduino_MFRC522v2.git + https://github.com/bmorcelli/ESP-ChameleonUltra + ;https://github.com/bmorcelli/ESP-Amiibolink + https://github.com/rennancockles/SimpleCLI + ;https://github.com/bmorcelli/ESP-PN532BLE + ;https://github.com/whywilson/ESP-PN532-UART@^0.0.2 + ;https://github.com/whywilson/ESP-PN532Killer#079790e + NTPClient + Timezone + ESP32Time + bblanchon/ArduinoJson + https://github.com/bmorcelli/rc-switch + ;https://github.com/bmorcelli/ESP8266Audio#codex/update-library-for-esp-idf-5.x-compatibility + FFat + ;earlephilhower/ESP8266SAM@^1.0.1 + mikalhart/TinyGPSPlus + tinyu-zhao/FFT@^0.0.1 + h2zero/NimBLE-Arduino@^2.3.3 + nrf24/RF24 @ 1.4.11 + ;Adafruit Si4713 Library@1.2.3 + Bodmer/JPEGDecoder + https://github.com/bmorcelli/SmartRC-CC1101-Driver-Lib/ + ;ducktape=https://github.com/bmorcelli/duktape/releases/download/2.7.0-lite/duktape-2.7.0.zip + ;paulstoffregen/OneWire@^2.3.8 + ;https://github.com/bmorcelli/OneWire#patch-1 + https://github.com/bmorcelli/ESP32-PsRamFS#patch-1 + ;bitbank2/AnimatedGIF + ;bitbank2/PNGdec @ ^1.1.2 + ESP32Async/ESPAsyncWebServer + ;https://github.com/bmorcelli/FastLED diff --git a/sd_files/esp32_serial_navigator.html b/sd_files/esp32_serial_navigator.html new file mode 100644 index 000000000..47dc5facd --- /dev/null +++ b/sd_files/esp32_serial_navigator.html @@ -0,0 +1,551 @@ + + + + + + + ESP32 Web Serial + Navigator + + + +
+
+ ESP32 Web Serial + Disconnected +
+
+ + + + + +
+
+ +
+
+
+ + + + + + + Tip: Enter to send • Ctrl+K clear +
+
+ + + + + + + diff --git a/src/core/configPins.cpp b/src/core/configPins.cpp index 42064187d..43fdf8a38 100644 --- a/src/core/configPins.cpp +++ b/src/core/configPins.cpp @@ -1,4 +1,5 @@ #include "configPins.h" +#include "esp_mac.h" #include "sd_functions.h" String getMacAddress() { diff --git a/src/core/connect/esp_connection.cpp b/src/core/connect/esp_connection.cpp index dda6ba359..574aebcad 100644 --- a/src/core/connect/esp_connection.cpp +++ b/src/core/connect/esp_connection.cpp @@ -174,7 +174,7 @@ String EspConnection::macToString(const uint8_t *mac) { } void EspConnection::appendPeerToList(const uint8_t *mac) { - peerOptions.push_back({macToString(mac).c_str(), [=]() { setDstAddress(mac); }}); + peerOptions.push_back({macToString(mac).c_str(), [this, mac]() { setDstAddress(mac); }}); } void EspConnection::onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { @@ -201,3 +201,13 @@ void EspConnection::onDataRecv(const uint8_t *mac, const uint8_t *incomingData, recvQueue.push_back(recvMessage); } + +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) +void EspConnection::onDataSentStatic(const wifi_tx_info_t *info, esp_now_send_status_t status) { + if (instance) instance->onDataSent(info->src_addr, status); +} + +void EspConnection::onDataRecvStatic(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len) { + if (instance) instance->onDataRecv(info->src_addr, incomingData, len); +} +#endif diff --git a/src/core/connect/esp_connection.h b/src/core/connect/esp_connection.h index 2c5e257ed..5bc8728d7 100644 --- a/src/core/connect/esp_connection.h +++ b/src/core/connect/esp_connection.h @@ -44,13 +44,17 @@ class EspConnection { static void setInstance(EspConnection *conn) { instance = conn; } +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) + static void onDataSentStatic(const wifi_tx_info_t *info, esp_now_send_status_t status); + static void onDataRecvStatic(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len); +#else static void onDataSentStatic(const uint8_t *mac_addr, esp_now_send_status_t status) { if (instance) instance->onDataSent(mac_addr, status); }; static void onDataRecvStatic(const uint8_t *mac, const uint8_t *incomingData, int len) { if (instance) instance->onDataRecv(mac, incomingData, len); }; - +#endif protected: Status recvStatus; Status sendStatus; diff --git a/src/core/display.cpp b/src/core/display.cpp index 9bfb5368a..42dea3e14 100644 --- a/src/core/display.cpp +++ b/src/core/display.cpp @@ -571,7 +571,7 @@ int loopOptions( forceMenuOption = -1; // reset SerialCommand navigation option Serial.print("Forcely "); } - Serial.println("Selected: " + String(options[index].label)); + Serial.println("Selected: " + String(options[chosen].label)); options[chosen].operation(); break; } @@ -1226,6 +1226,7 @@ bool showJpeg(FS &fs, String filename, int x, int y, bool center) { delete[] data_array; // free heap before leaving return true; } + #if !defined(LITE_VERSION) // #################################################################################################### // Draw a GIF on the TFT @@ -1625,7 +1626,9 @@ bool drawImg(FS &fs, String filename, int x, int y, bool center, int playDuratio if (ext.endsWith("jpg")) return showJpeg(fs, filename, x, y, center); else if (ext.endsWith("bmp")) return drawBmp(fs, filename, x, y, center); else if (ext.endsWith("png")) return drawPNG(fs, filename, x, y, center); + #if !defined(LITE_VERSION) + else if (ext.endsWith("gif")) return showGif(&fs, filename.c_str(), x, y, center, playDurationMs); #endif else log_e("Image not supported"); @@ -1722,5 +1725,6 @@ bool drawPNG(FS &fs, String filename, int x, int y, bool center) { #else bool drawPNG(FS &fs, String filename, int x, int y, bool center) { log_w("PNG: Not supported in this version"); + return false; } #endif diff --git a/src/core/display.h b/src/core/display.h index 516c7d3e1..b68b45c52 100644 --- a/src/core/display.h +++ b/src/core/display.h @@ -25,7 +25,9 @@ struct Opt_Coord { uint16_t bgcolor = bruceConfig.bgColor; }; void displayScrollingText(const String &text, Opt_Coord &coord); + #if !defined(LITE_VERSION) + #include struct GifPosition { diff --git a/src/core/led_control.cpp b/src/core/led_control.cpp index 3177d9c60..99aa4d054 100644 --- a/src/core/led_control.cpp +++ b/src/core/led_control.cpp @@ -1,13 +1,17 @@ #include "led_control.h" -#ifdef HAS_RGB_LED + #include "core/display.h" #include "core/utils.h" #include - -#define FASTLED_RMT_BUILTIN_DRIVER 1 // Use the ESP32 RMT built-in driver -#define FASTLED_RMT_MAX_CHANNELS 1 // Maximum number of RMT channels -#define FASTLED_ESP32_RMT_CHANNEL_0 0 // Use RMT channel 0 for FastLED -#include "driver/rmt.h" +#ifdef HAS_RGB_LED +#define FASTLED_RMT_BUILTIN_DRIVER 1 // Use the ESP32 RMT built-in driver +#define FASTLED_RMT_MAX_CHANNELS 1 // Maximum number of RMT channels +#define FASTLED_ESP32_RMT_CHANNEL_0 0 // Use RMT channel 0 for FastLED +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) // RMT +#include +#else +#include #include #include @@ -281,7 +285,7 @@ void setLedBrightness(int value) { FastLED.show(); } -const CRGB BrucePurple = 0x960064; // Custom purple color for Bruce +#define BrucePurple 9830500 // Custom purple color for Bruce // TODO: 3852441 -> 3849837 void setLedColorConfig() { ledPreviewMode(true); diff --git a/src/core/main_menu.cpp b/src/core/main_menu.cpp index d53b241c1..4fe3d8947 100644 --- a/src/core/main_menu.cpp +++ b/src/core/main_menu.cpp @@ -17,7 +17,7 @@ MainMenu::MainMenu() { &rfidMenu, #endif &irMenu, -#if defined(FM_SI4713) +#if defined(FM_SI4713) && !defined(LITE_VERSION) &fmMenu, #endif &fileMenu, @@ -30,7 +30,9 @@ MainMenu::MainMenu() { #endif &othersMenu, &clockMenu, +#if !defined(LITE_VERSION) &connectMenu, +#endif &configMenu, }; @@ -50,7 +52,7 @@ void MainMenu::begin(void) { options.push_back( {// selected lambda _menuItems[i]->getName(), - [=]() { _menuItems[i]->optionsMenu(); }, + [this, i]() { _menuItems[i]->optionsMenu(); }, false, // selected = false [](void *menuItem, bool shouldRender) { // render lambda if (!shouldRender) return false; @@ -86,7 +88,7 @@ void MainMenu::hideAppsMenu() { String label = item->getName(); std::vector l = bruceConfig.disabledMenus; bool enabled = find(l.begin(), l.end(), label) == l.end(); - options.push_back({label, [=]() { bruceConfig.addDisabledMenu(label); }, enabled}); + options.push_back({label, [this, label]() { bruceConfig.addDisabledMenu(label); }, enabled}); } options.push_back({"Show All", [=]() { bruceConfig.disabledMenus.clear(); }, true}); addOptionToMainMenu(); diff --git a/src/core/massStorage.cpp b/src/core/massStorage.cpp index 939ee2f1b..0724635ef 100644 --- a/src/core/massStorage.cpp +++ b/src/core/massStorage.cpp @@ -1,9 +1,9 @@ -#if defined(ARDUINO_USB_MODE) && !defined(USE_SD_MMC) + #include "massStorage.h" #include "core/display.h" #include - +#if defined(SOC_USB_OTG_SUPPORTED) && !defined(USE_SD_MMC) bool MassStorage::shouldStop = false; int32_t MassStorage::status = -1; @@ -182,4 +182,4 @@ void drawUSBStickIcon(bool plugged) { tft.fillRoundRect(ledX, ledY, ledW, ledH, radius, plugged ? TFT_GREEN : TFT_RED); } -#endif // ARDUINO_USB_MODE +#endif // SOC_USB_OTG_SUPPORTED diff --git a/src/core/massStorage.h b/src/core/massStorage.h index 36e22a43a..25609405b 100644 --- a/src/core/massStorage.h +++ b/src/core/massStorage.h @@ -1,10 +1,9 @@ -#ifdef ARDUINO_USB_MODE - #ifndef __MASS_STORAGE_H__ #define __MASS_STORAGE_H__ -#include #include +#if defined(SOC_USB_OTG_SUPPORTED) +#include class MassStorage { public: @@ -51,4 +50,4 @@ bool usbStartStopCallback(uint8_t power_condition, bool start, bool load_eject); void drawUSBStickIcon(bool plugged); #endif // MASS_STORAGE_H -#endif // ARDUINO_USB_MODE +#endif // SOC_USB_OTG_SUPPORTED diff --git a/src/core/menu_items/BleMenu.cpp b/src/core/menu_items/BleMenu.cpp index f47ae2894..e8b8c79e1 100644 --- a/src/core/menu_items/BleMenu.cpp +++ b/src/core/menu_items/BleMenu.cpp @@ -34,7 +34,9 @@ void BleMenu::optionsMenu() { options.push_back({"Android Spam", lambdaHelper(aj_adv, 4)}); options.push_back({"Spam All", lambdaHelper(aj_adv, 5)}); options.push_back({"Spam Custom", lambdaHelper(aj_adv, 6)}); +#if !defined(LITE_VERSION) options.push_back({"Ninebot", [=]() { BLENinebot(); }}); +#endif addOptionToMainMenu(); loopOptions(options, MENU_TYPE_SUBMENU, "Bluetooth"); diff --git a/src/core/menu_items/ConnectMenu.cpp b/src/core/menu_items/ConnectMenu.cpp index cb97c5222..cfad01ba3 100644 --- a/src/core/menu_items/ConnectMenu.cpp +++ b/src/core/menu_items/ConnectMenu.cpp @@ -9,10 +9,13 @@ void ConnectMenu::optionsMenu() { options = { +#ifndef LITE_VERSION {"Send File", [=]() { FileSharing().sendFile(); } }, {"Recv File", [=]() { FileSharing().receiveFile(); } }, + {"Send Cmds", [=]() { EspSerialCmd().sendCommands(); } }, {"Recv Cmds", [=]() { EspSerialCmd().receiveCommands(); }}, +#endif }; addOptionToMainMenu(); diff --git a/src/core/menu_items/EthernetMenu.cpp b/src/core/menu_items/EthernetMenu.cpp index d8d6f3db0..24d2ed9a5 100644 --- a/src/core/menu_items/EthernetMenu.cpp +++ b/src/core/menu_items/EthernetMenu.cpp @@ -21,15 +21,14 @@ void EthernetMenu::optionsMenu() { start_ethernet(); run_arp_scanner(); eth->stop(); - }}, + } }, {"DHCP Starvation", [=]() { start_ethernet(); DHCPStarvation(); eth->stop(); - }}, - {"MAC Flooding", - [=]() { + } }, + {"MAC Flooding", [=]() { start_ethernet(); MACFlooding(); eth->stop(); diff --git a/src/core/menu_items/FMMenu.cpp b/src/core/menu_items/FMMenu.cpp index 7dc2daf7e..69a84e426 100644 --- a/src/core/menu_items/FMMenu.cpp +++ b/src/core/menu_items/FMMenu.cpp @@ -5,8 +5,8 @@ void FMMenu::optionsMenu() { options = { - // #if !defined(LITE_VERSION) and defined(FM_SI4713) -#if defined(FM_SI4713) +#if !defined(LITE_VERSION) and defined(FM_SI4713) + // #if defined(FM_SI4713) {"Brdcast std", lambdaHelper(fm_live_run, false)}, {"Brdcast rsvd", lambdaHelper(fm_live_run, true)}, {"Brdcast stop", fm_stop}, diff --git a/src/core/menu_items/FileMenu.cpp b/src/core/menu_items/FileMenu.cpp index 4fd03487a..ee58cb523 100644 --- a/src/core/menu_items/FileMenu.cpp +++ b/src/core/menu_items/FileMenu.cpp @@ -7,10 +7,11 @@ void FileMenu::optionsMenu() { options.clear(); - if(sdcardMounted) options.push_back({"SD Card", [=]() { loopSD(SD); }}); + if (sdcardMounted) options.push_back({"SD Card", [=]() { loopSD(SD); }}); options.push_back({"LittleFS", [=]() { loopSD(LittleFS); }}); options.push_back({"WebUI", loopOptionsWebUi}); -#if defined(ARDUINO_USB_MODE) && !defined(USE_SD_MMC) + +#if defined(SOC_USB_OTG_SUPPORTED) && !defined(USE_SD_MMC) options.push_back({"Mass Storage", [=]() { MassStorage(); }}); #endif addOptionToMainMenu(); diff --git a/src/core/menu_items/IRMenu.cpp b/src/core/menu_items/IRMenu.cpp index ce4192c0a..dab4d3eea 100644 --- a/src/core/menu_items/IRMenu.cpp +++ b/src/core/menu_items/IRMenu.cpp @@ -3,8 +3,8 @@ #include "core/settings.h" #include "core/utils.h" #include "modules/ir/TV-B-Gone.h" -#include "modules/ir/ir_jammer.h" #include "modules/ir/custom_ir.h" +#include "modules/ir/ir_jammer.h" #include "modules/ir/ir_read.h" void IRMenu::optionsMenu() { @@ -12,7 +12,9 @@ void IRMenu::optionsMenu() { {"TV-B-Gone", StartTvBGone }, {"Custom IR", otherIRcodes }, {"IR Read", [=]() { IrRead(); } }, +#if !defined(LITE_VERSION) {"IR Jammer", startIrJammer }, // Simple frequency-adjustable jammer +#endif {"Config", [=]() { configMenu(); }}, }; addOptionToMainMenu(); diff --git a/src/core/menu_items/NRF24.cpp b/src/core/menu_items/NRF24.cpp index fd131f2ee..ee988a06d 100644 --- a/src/core/menu_items/NRF24.cpp +++ b/src/core/menu_items/NRF24.cpp @@ -51,6 +51,7 @@ void NRF24Menu::configMenu() { GPIO_NUM_NC} ); } +#if CONFIG_SOC_GPIO_OUT_RANGE_MAX > 30 if (opt == 2) { bruceConfigPins.setNrf24Pins( {(gpio_num_t)SDCARD_SCK, @@ -61,6 +62,7 @@ void NRF24Menu::configMenu() { GPIO_NUM_NC} ); } +#endif } void NRF24Menu::drawIconImg() { drawImg( diff --git a/src/core/menu_items/OthersMenu.cpp b/src/core/menu_items/OthersMenu.cpp index 0149c49b9..d541f7836 100644 --- a/src/core/menu_items/OthersMenu.cpp +++ b/src/core/menu_items/OthersMenu.cpp @@ -6,7 +6,6 @@ #include "modules/others/clicker.h" #include "modules/others/ibutton.h" #include "modules/others/mic.h" -#include "modules/others/openhaystack.h" #include "modules/others/qrcode_menu.h" #include "modules/others/timer.h" #include "modules/others/tururururu.h" @@ -25,10 +24,9 @@ void OthersMenu::optionsMenu() { {"Clicker", clicker_setup }, #endif #ifndef LITE_VERSION - {"Openhaystack", openhaystack_setup }, {"Interpreter", run_bjs_script }, -#endif {"iButton", setup_ibutton }, +#endif {"Timer", [=]() { Timer(); } }, }; addOptionToMainMenu(); diff --git a/src/core/menu_items/RFIDMenu.cpp b/src/core/menu_items/RFIDMenu.cpp index d8678a87a..6cb2c84db 100644 --- a/src/core/menu_items/RFIDMenu.cpp +++ b/src/core/menu_items/RFIDMenu.cpp @@ -17,10 +17,14 @@ void RFIDMenu::optionsMenu() { {"Load file", [=]() { TagOMatic(TagOMatic::LOAD_MODE); } }, {"Erase data", [=]() { TagOMatic(TagOMatic::ERASE_MODE); } }, {"Write NDEF", [=]() { TagOMatic(TagOMatic::WRITE_NDEF_MODE); }}, +#ifndef LITE_VERSION {"Amiibolink", [=]() { Amiibo(); } }, +#endif {"Chameleon", [=]() { Chameleon(); } }, +#ifndef LITE_VERSION {"PN532 BLE", [=]() { Pn532ble(); } }, {"PN532 UART", [=]() { PN532KillerTools(); } }, +#endif {"Config", [=]() { configMenu(); } }, }; addOptionToMainMenu(); diff --git a/src/core/menu_items/RFMenu.cpp b/src/core/menu_items/RFMenu.cpp index 4174ed4a0..61fb40283 100644 --- a/src/core/menu_items/RFMenu.cpp +++ b/src/core/menu_items/RFMenu.cpp @@ -14,9 +14,12 @@ void RFMenu::optionsMenu() { options = { {"Scan/copy", [=]() { RFScan(); } }, +#if !defined(LITE_VERSION) {"Record RAW", rf_raw_record }, // Pablo-Ortiz-Lopez {"Custom SubGhz", sendCustomRF }, +#endif {"Spectrum", rf_spectrum }, +#if !defined(LITE_VERSION) {"SquareWave Spec", rf_SquareWave }, // @Pirata {"Spectogram", rf_waterfall }, // dev_eclipse #if defined(BUZZ_PIN) or defined(HAS_NS4168_SPKR) and defined(RF_LISTEN_H) @@ -24,6 +27,7 @@ void RFMenu::optionsMenu() { #endif {"Bruteforce", rf_bruteforce }, // dev_eclipse {"Jammer Itmt", [=]() { RFJammer(false); }}, +#endif {"Jammer Full", [=]() { RFJammer(true); } }, {"Config", [=]() { configMenu(); } }, }; diff --git a/src/core/menu_items/ScriptsMenu.cpp b/src/core/menu_items/ScriptsMenu.cpp index 95326dfad..9310779d3 100644 --- a/src/core/menu_items/ScriptsMenu.cpp +++ b/src/core/menu_items/ScriptsMenu.cpp @@ -25,6 +25,7 @@ String getScriptsFolder(FS *&fs) { std::vector