diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index 59460d5c..ffde2d21 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -47,7 +47,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus + run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus --environment opendtufusionv1-release - name: Rename Binary files id: rename-binary-files diff --git a/.github/workflows/compile_release.yml b/.github/workflows/compile_release.yml index bd7cef5a..84ad5111 100644 --- a/.github/workflows/compile_release.yml +++ b/.github/workflows/compile_release.yml @@ -51,7 +51,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus + run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus --environment opendtufusionv1-release - name: Rename Binary files id: rename-binary-files diff --git a/.gitignore b/.gitignore index d6a35860..2ee4b679 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ src/web/html/tmp/* *.db *.suo *.ipch +src/output.map diff --git a/scripts/getVersion.py b/scripts/getVersion.py index 77c5816b..0ebe1ec2 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -78,6 +78,11 @@ def readVersion(path, infile): dst = path + "firmware/" + versionout os.rename(src, dst) + versionout = version[:-1] + "_" + sha + "_esp32s3.bin" + src = path + ".pio/build/opendtufusionv1-release/firmware.bin" + dst = path + "firmware/" + versionout + os.rename(src, dst) + # other ESP32 bin files src = path + ".pio/build/esp32-wroom32-release/" dst = path + "firmware/" diff --git a/src/.vscode/settings.json b/src/.vscode/settings.json index c0becfd1..58a2c3c7 100644 --- a/src/.vscode/settings.json +++ b/src/.vscode/settings.json @@ -4,20 +4,16 @@ "workbench.colorCustomizations": { "editorLineNumber.foreground": "#00ff00" }, - "editor.wordWrap": "off", - "files.eol" : "\n", - "files.trimTrailingWhitespace" : true, - + "files.eol": "\n", + "files.trimTrailingWhitespace": true, "diffEditor.ignoreTrimWhitespace": true, "files.autoSave": "afterDelay", - "editor.tabSize": 4, "editor.insertSpaces": true, // `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents. // Set to false to keep the values you've explicitly set, above. "editor.detectIndentation": false, - // https://clang.llvm.org/docs/ClangFormatStyleOptions.html "C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0}", "files.associations": { @@ -86,4 +82,5 @@ "thread": "cpp" }, "cmake.configureOnOpen": false, + "editor.formatOnSave": false, } \ No newline at end of file diff --git a/src/app.cpp b/src/app.cpp index 23030d76..d3fba12a 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -30,9 +30,9 @@ void app::setup() { DBGPRINTLN(F("false")); mSys.enableDebug(); - mSys.setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); + mSys.setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs, mConfig->nrf.pinSclk, mConfig->nrf.pinMosi, mConfig->nrf.pinMiso); - #if defined(AP_ONLY) +#if defined(AP_ONLY) mInnerLoopCb = std::bind(&app::loopStandard, this); #else mInnerLoopCb = std::bind(&app::loopWifi, this); diff --git a/src/config/config.h b/src/config/config.h index 5bb085f4..ac28c1a2 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -44,13 +44,25 @@ // default pinout (GPIO Number) #if defined(ESP32) + // this is the default ESP32 (son-S) pinout on the WROOM modules for VSPI, + // for the ESP32-S3 there is no sane 'default', as it has full flexibility + // to map its two HW SPIs anywhere and PCBs differ materially, + // so it has to be selected in the Web UI #define DEF_CS_PIN 5 #define DEF_CE_PIN 4 #define DEF_IRQ_PIN 16 + #define DEF_MISO_PIN 19 + #define DEF_MOSI_PIN 23 + #define DEF_SCLK_PIN 18 #else #define DEF_CS_PIN 15 #define DEF_CE_PIN 2 #define DEF_IRQ_PIN 0 + // these are given to relay the correct values via API + // they cannot actually be moved for ESP82xx models + #define DEF_MISO_PIN 12 + #define DEF_MOSI_PIN 13 + #define DEF_SCLK_PIN 14 #endif // default NRF24 power, possible values (0 - 3) diff --git a/src/config/config_override_example.h b/src/config/config_override_example.h index ed976ceb..e7c06b77 100644 --- a/src/config/config_override_example.h +++ b/src/config/config_override_example.h @@ -17,14 +17,19 @@ #undef FB_WIFI_PWD #define FB_WIFI_PWD "MY_WIFI_KEY" -// ESP32 default pinout -#undef DEF_RF24_CS_PIN -#define DEF_RF24_CS_PIN 5 -#undef DEF_RF24_CE_PIN -#define DEF_RF24_CE_PIN 4 -#undef DEF_RF24_IRQ_PIN -#define DEF_RF24_IRQ_PIN 16 - +// ESP32-S3 example pinout +#undef DEF_CS_PIN +#define DEF_CS_PIN 37 +#undef DEF_CE_PIN +#define DEF_CE_PIN 38 +#undef DEF_IRQ_PIN +#define DEF_IRQ_PIN 47 +#undef DEF_MISO_PIN +#define DEF_MISO_PIN 48 +#undef DEF_MOSI_PIN +#define DEF_MOSI_PIN 35 +#undef DEF_SCLK_PIN +#define DEF_SCLK_PIN 36 // Offset for midnight Ticker Example: 1 second before midnight (local time) #undef MIDNIGHTTICKER_OFFSET diff --git a/src/config/settings.h b/src/config/settings.h index a1c5a85f..6d58b406 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -73,6 +73,9 @@ typedef struct { uint8_t pinCs; uint8_t pinCe; uint8_t pinIrq; + uint8_t pinMiso; + uint8_t pinMosi; + uint8_t pinSclk; uint8_t amplifierPower; } cfgNrf24_t; @@ -344,6 +347,10 @@ class settings { mCfg.nrf.pinCs = DEF_CS_PIN; mCfg.nrf.pinCe = DEF_CE_PIN; mCfg.nrf.pinIrq = DEF_IRQ_PIN; + mCfg.nrf.pinMiso = DEF_MISO_PIN; + mCfg.nrf.pinMosi = DEF_MOSI_PIN; + mCfg.nrf.pinSclk = DEF_SCLK_PIN; + mCfg.nrf.amplifierPower = DEF_AMPLIFIERPOWER & 0x03; snprintf(mCfg.ntp.addr, NTP_ADDR_LEN, "%s", DEF_NTP_SERVER_NAME); @@ -426,6 +433,9 @@ class settings { obj[F("cs")] = mCfg.nrf.pinCs; obj[F("ce")] = mCfg.nrf.pinCe; obj[F("irq")] = mCfg.nrf.pinIrq; + obj[F("sclk")] = mCfg.nrf.pinSclk; + obj[F("mosi")] = mCfg.nrf.pinMosi; + obj[F("miso")] = mCfg.nrf.pinMiso; obj[F("pwr")] = mCfg.nrf.amplifierPower; } else { mCfg.nrf.sendInterval = obj[F("intvl")]; @@ -433,11 +443,17 @@ class settings { mCfg.nrf.pinCs = obj[F("cs")]; mCfg.nrf.pinCe = obj[F("ce")]; mCfg.nrf.pinIrq = obj[F("irq")]; + mCfg.nrf.pinSclk = obj[F("sclk")]; + mCfg.nrf.pinMosi = obj[F("mosi")]; + mCfg.nrf.pinMiso = obj[F("miso")]; mCfg.nrf.amplifierPower = obj[F("pwr")]; if((obj[F("cs")] == obj[F("ce")])) { - mCfg.nrf.pinCs = DEF_CS_PIN; - mCfg.nrf.pinCe = DEF_CE_PIN; - mCfg.nrf.pinIrq = DEF_IRQ_PIN; + mCfg.nrf.pinCs = DEF_CS_PIN; + mCfg.nrf.pinCe = DEF_CE_PIN; + mCfg.nrf.pinIrq = DEF_IRQ_PIN; + mCfg.nrf.pinSclk = DEF_SCLK_PIN; + mCfg.nrf.pinMosi = DEF_MOSI_PIN; + mCfg.nrf.pinMiso = DEF_MISO_PIN; } } } diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index a9564196..c37ab7d0 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -10,6 +10,7 @@ #include #include "../utils/crc.h" #include "../config/config.h" +#include "SPI.h" #define SPI_SPEED 1000000 @@ -47,7 +48,7 @@ const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"}; //----------------------------------------------------------------------------- // HM Radio class //----------------------------------------------------------------------------- -template +template class HmRadio { public: HmRadio() : mNrf24(CE_PIN, CS_PIN, SPI_SPEED) { @@ -78,7 +79,7 @@ class HmRadio { } ~HmRadio() {} - void setup(uint8_t ampPwr = RF24_PA_LOW, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN) { + void setup(uint8_t ampPwr = RF24_PA_LOW, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN, uint8_t sclk = SCLK_PIN, uint8_t mosi = MOSI_PIN, uint8_t miso = MISO_PIN) { DPRINTLN(DBG_VERBOSE, F("hmRadio.h:setup")); pinMode(irq, INPUT_PULLUP); @@ -100,7 +101,19 @@ class HmRadio { // change the byte order of the DTU serial number and append the required 0x01 at the end DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; - mNrf24.begin(ce, cs); + #ifdef ESP32 + #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + mSpi = new SPIClass(FSPI); + #else + mSpi = new SPIClass(VSPI); + #endif + mSpi->begin(sclk, miso, mosi, cs); + #else + //the old ESP82xx cannot freely place their SPI pins + mSpi = new SPIClass(); + mSpi->begin(); + #endif + mNrf24.begin(mSpi, ce, cs); mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24.setChannel(mRfChLst[mRxChIdx]); @@ -350,6 +363,7 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRxChIdx; + SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; }; diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 3f3b29a7..a95d4d24 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -21,9 +21,9 @@ class HmSystem { Radio.setup(); } - void setup(uint8_t ampPwr, uint8_t irqPin, uint8_t cePin, uint8_t csPin) { + void setup(uint8_t ampPwr, uint8_t irqPin, uint8_t cePin, uint8_t csPin, uint8_t sclkPin, uint8_t mosiPin, uint8_t misoPin) { mNumInv = 0; - Radio.setup(ampPwr, irqPin, cePin, csPin); + Radio.setup(ampPwr, irqPin, cePin, csPin, sclkPin, mosiPin, misoPin); } void addInverters(cfgInst_t *config) { diff --git a/src/platformio.ini b/src/platformio.ini index 38e67c95..4e2e92fd 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -133,3 +133,13 @@ monitor_filters = ;default ; Remove typical terminal control codes from input time ; Add timestamp with milliseconds for each new line log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory + +[env:opendtufusionv1-release] +platform = espressif32 +board = esp32-s3-devkitc-1 +build_flags = -D RELEASE -std=gnu++14 +build_unflags = -std=gnu++11 +monitor_filters = + ;default ; Remove typical terminal control codes from input + time ; Add timestamp with milliseconds for each new line + ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 15402e7a..b224f239 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -386,6 +386,9 @@ class RestApi { obj[F("cs")] = mConfig->nrf.pinCs; obj[F("ce")] = mConfig->nrf.pinCe; obj[F("irq")] = mConfig->nrf.pinIrq; + obj[F("sclk")] = mConfig->nrf.pinSclk; + obj[F("mosi")] = mConfig->nrf.pinMosi; + obj[F("miso")] = mConfig->nrf.pinMiso; obj[F("led0")] = mConfig->led.led0; obj[F("led1")] = mConfig->led.led1; } diff --git a/src/web/html/setup.html b/src/web/html/setup.html index a335f76f..bfbda402 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -363,6 +363,54 @@ [36, "VP (GPIO36)"], [39, "VN (GPIO39)"] ]; + var esp32s3pins = [ + [255, "off / default"], + [0, "GPIO0 (DONT USE - BOOT)"], + [1, "GPIO1"], + [2, "GPIO2"], + [3, "GPIO3"], + [4, "GPIO4"], + [5, "GPIO5"], + [6, "GPIO6"], + [7, "GPIO7"], + [8, "GPIO8"], + [9, "GPIO9"], + [10, "GPIO10"], + [11, "GPIO11"], + [12, "GPIO12"], + [13, "GPIO13"], + [14, "GPIO14"], + [15, "GPIO15"], + [16, "GPIO16"], + [17, "GPIO17"], + [18, "GPIO18"], + [19, "GPIO19 (DONT USE - USB-)"], + [20, "GPIO20 (DONT USE - USB+)"], + [21, "GPIO21"], + [26, "GPIO26 (PSRAM - not available)"], + [27, "GPIO27 (FLASH - not available)"], + [28, "GPIO28 (FLASH - not available)"], + [29, "GPIO29 (FLASH - not available)"], + [30, "GPIO30 (FLASH - not available)"], + [31, "GPIO31 (FLASH - not available)"], + [32, "GPIO32 (FLASH - not available)"], + [33, "GPIO33 (not exposed on WROOM modules)"], + [34, "GPIO34 (not exposed on WROOM modules)"], + [35, "GPIO35"], + [36, "GPIO36"], + [37, "GPIO37"], + [38, "GPIO38"], + [39, "GPIO39"], + [40, "GPIO40"], + [41, "GPIO41"], + [42, "GPIO42"], + [43, "GPIO43"], + [44, "GPIO44"], + [45, "GPIO45 (DONT USE - STRAPPING PIN)"], + [46, "GPIO46 (DONT USE - STRAPPING PIN)"], + [47, "GPIO47"], + [48, "GPIO48"], + ]; const re = /11[2,4,6]1.*/; @@ -605,15 +653,19 @@ } } - function parsePinout(obj, type) { + function parsePinout(obj, type, system) { var e = document.getElementById("pinout"); - pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['led0', 'pinLed0'], ['led1', 'pinLed1']]; + if ("ESP8266" == type) { + pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['led0', 'pinLed0'], ['led1', 'pinLed1']]; + } else { + pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['sclk', 'pinSclk'], ['mosi', 'pinMosi'], ['miso', 'pinMiso'], ['led0', 'pinLed0'], ['led1', 'pinLed1']]; + } for(p of pins) { e.append( ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), ml("div", {class: "col-12 col-sm-9"}, - sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]]) + sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj[p[0]]) ) ]) ); @@ -642,7 +694,7 @@ document.getElementsByName("serIntvl")[0].value = obj["interval"]; } - function parseDisplay(obj, type) { + function parseDisplay(obj, type, system) { for(var i of ["disp_pwr", "disp_pxshift"]) document.getElementsByName(i)[0].checked = obj[i]; @@ -655,7 +707,7 @@ ml("div", {class: "row mb-3", id: "row_" + p[1]}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), ml("div", {class: "col-12 col-sm-9"}, - sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[1]]) + sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj[p[1]]) ) ]) ); @@ -720,10 +772,10 @@ parseMqtt(root["mqtt"]); parseNtp(root["ntp"]); parseSun(root["sun"]); - parsePinout(root["pinout"], root["system"]["esp_type"]); + parsePinout(root["pinout"], root["system"]["esp_type"], root["system"]); parseRadio(root["radio"]); parseSerial(root["serial"]); - parseDisplay(root["display"], root["system"]["esp_type"]); + parseDisplay(root["display"], root["system"]["esp_type"], root["system"]); getAjax("/api/inverter/list", parseIv); } } diff --git a/src/web/web.h b/src/web/web.h index eca78f87..c141e013 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -33,7 +33,7 @@ #define WEB_SERIAL_BUF_SIZE 2048 -const char *const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinLed0", "pinLed1"}; +const char *const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinSclk", "pinMosi", "pinMiso", "pinLed0", "pinLed1"}; template class Web { @@ -521,14 +521,17 @@ class Web { // pinout uint8_t pin; - for (uint8_t i = 0; i < 5; i++) { + for (uint8_t i = 0; i < 8; i++) { pin = request->arg(String(pinArgNames[i])).toInt(); switch(i) { default: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_CS_PIN); break; case 1: mConfig->nrf.pinCe = ((pin != 0xff) ? pin : DEF_CE_PIN); break; case 2: mConfig->nrf.pinIrq = ((pin != 0xff) ? pin : DEF_IRQ_PIN); break; - case 3: mConfig->led.led0 = pin; break; - case 4: mConfig->led.led1 = pin; break; + case 3: mConfig->nrf.pinSclk = ((pin != 0xff) ? pin : DEF_SCLK_PIN); break; + case 4: mConfig->nrf.pinMosi = ((pin != 0xff) ? pin : DEF_MOSI_PIN); break; + case 5: mConfig->nrf.pinMiso = ((pin != 0xff) ? pin : DEF_MISO_PIN); break; + case 6: mConfig->led.led0 = pin; break; + case 7: mConfig->led.led1 = pin; break; } }