diff --git a/README.md b/README.md index 238b99a..7935664 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ Template-oriented driver for e-paper displays using Arduino. Define a layout wi - [Setup](#setup) - [Requirements](#requirements) - [Quickstart](#quickstart) + - [Hardware Setup](#hardware-setup) - [Deep Sleep](#deep-sleep) - - [SPI Bus and Pin Selection](#spi-bus-and-pin-selection) - [Concepts](#concepts) - [Variables](#variables) - [Regions](#regions) @@ -59,7 +59,7 @@ The [examples directory](./examples) has a few sample templates. Here are a few ## Quickstart -1. Connect display to MCU. (see [waveshare site](https://www.waveshare.com/wiki/1.54inch_e-Paper_Module) and **SPI Bus and Pin Selection** below for more information) +1. Connect display to MCU. See [Hardware Setup](#hardware-setup) below for more information. 1. Flash your MCU. 1. Use a pre-compiled binary from the [releases page](https://github.com/sidoh/epaper_templates/releases). **Make sure to select the file starting with `INITIALIZER_`**. You can use [esptool](https://github.com/espressif/esptool) or the [ESP32 flash tool](https://www.espressif.com/en/support/download/other-tools). Example command: ``` @@ -67,34 +67,47 @@ The [examples directory](./examples) has a few sample templates. Here are a few ``` 2. With PlatformIO: for example `pio run -e esp32 -t upload`. You will need to have [nodejs](https://nodejs.org/en/) installed in order to buidl the web assets. 2. Setup WiFi. A setup AP will appear named `epaper_XXXXXX`. The default password is **waveshare**. -3. Visit the Web UI to configure further. +3. Visit the Web UI to configure further. If you used custom pins, make sure to configure those. -## Deep Sleep +## Hardware Setup -e-paper templates can function in _deep sleep_ mode. When configured, the system will continuously: +Waveshare SPI modules have six total data pins that needs to be mapped onto your ESP32. There are **3x SPI pins** and **3x configurable non-SPI pins** you'll need to connect: -1. Wake from sleep -2. Check if a configurable GPIO pin is set. If it is, stays awake until next reboot -3. Otherwise, stay awake for a configurable period to receive updates and refresh the screen. -4. Put both the ESP32 and the e-paper display into deep sleep mode. +|Pin Name|Description|Default pin| +|-|-|-| +|DIN|SPI MOSI|GPIO 13 (HSPI MOSI)| +|CLK|SPI clock|GPIO 14 (HSPI CLK)| +|CS|SPI chip select|GPIO 15 (HSPI SS) +|DC|Data/Command control pin (configurable)|GPIO 17| +|RST|External reset|GPIO 16| +|BUSY|Busy state output pin|GPIO 7| -This is useful if trying to conserve power. Deep sleep mode can be configured in the "Power" tab within the web UI. +If you wish to use different data (non-SPI) pins, those are all configurable in the UI. -## SPI Bus and Pin Selection +#### Custom SPI bus -The ESP32 has 4 SPI busses, however, one is reserved for the chips Flash. (SPI0) and another is often used by PSRAM (SP1). +The ESP32 has two available SPI busses. The default is HSPI, but you can select VSPI in the settings page. Some driver boards like the [Waveshare ESP32 Driver](https://www.waveshare.com/wiki/E-Paper_ESP32_Driver_Board) use custom SPI pins. In the **Hardware** tab of the settings page, you can select one of the two free SPI busses on the ESP32. (HSPI and VSPI) -| | VSPI | HSPI (default) | -|-----------|------|----------------| -| DI (MOSI) | 19 | 12 | -| CLK | 18 | 14 | -| CS (SS) | 5 | 15 | +| | VSPI | HSPI (default) | Waveshare Custom | +|-----------|------|----------------|-| +| DI (MOSI) | 19 | 12 |14| +| CLK | 18 | 14 |13| +| CS (SS) | 5 | 15 |15| -Additionally, the displays will require extra pins to be configured to work properly. These are also selectable in the **Hardware** tab. +Ensure that you do not select pins that conflict with the your SPI Bus/Deep Sleep configurations. + +## Deep Sleep -Please ensure that you do not select pins that conflict with the your SPI Bus/Deep Sleep configurations. +e-paper templates can function in _deep sleep_ mode. When configured, the system will continuously: + +1. Wake from sleep +2. Check if a configurable GPIO pin is set. If it is, stays awake until next reboot +3. Otherwise, stay awake for a configurable period to receive updates and refresh the screen. +4. Put both the ESP32 and the e-paper display into deep sleep mode. + +This is useful if trying to conserve power. Deep sleep mode can be configured in the "Power" tab within the web UI. # Concepts diff --git a/lib/Display/DisplayTemplateDriver.cpp b/lib/Display/DisplayTemplateDriver.cpp index dd03f1a..64ca870 100644 --- a/lib/Display/DisplayTemplateDriver.cpp +++ b/lib/Display/DisplayTemplateDriver.cpp @@ -26,6 +26,17 @@ DisplayTemplateDriver::DisplayTemplateDriver( void DisplayTemplateDriver::init() { display->init(115200); display->mirror(false); + + #if defined(ESP32) + if (settings.hardware.spi_bus == VSPI){ + SPI.end(); + SPI.begin(18, 23, 19, settings.hardware.getSsPin()); + } else if (settings.hardware.spi_bus == HardwareSettings::WAVESHARE_SPI) { + SPI.end(); + SPI.begin(13, 12, 14, settings.hardware.getSsPin()); + } + #endif + vars.load(); } diff --git a/lib/Display/DisplayTypeHelpers.cpp b/lib/Display/DisplayTypeHelpers.cpp index c4dab53..fb8700e 100644 --- a/lib/Display/DisplayTypeHelpers.cpp +++ b/lib/Display/DisplayTypeHelpers.cpp @@ -8,13 +8,13 @@ #include template -inline static GxEPD2_GFX* __gxepd2_build_bw_driver(const uint8_t dc, const uint8_t rst, const uint8_t busy) { - return new GxEPD2_BW(Display(SS, dc, rst, busy)); +inline static GxEPD2_GFX* __gxepd2_build_bw_driver(const uint8_t dc, const uint8_t rst, const uint8_t busy, const uint8_t ssPin) { + return new GxEPD2_BW(Display(ssPin, dc, rst, busy)); } template -inline static GxEPD2_GFX* __gxepd2_build_3c_driver(const uint8_t dc, const uint8_t rst, const uint8_t busy) { - return new GxEPD2_3C(Display(SS, dc, rst, busy)); +inline static GxEPD2_GFX* __gxepd2_build_3c_driver(const uint8_t dc, const uint8_t rst, const uint8_t busy, const uint8_t ssPin) { + return new GxEPD2_3C(Display(ssPin, dc, rst, busy)); } const std::map DisplayTypeHelpers::PANELS_BY_NAME = { @@ -162,59 +162,59 @@ bool DisplayTypeHelpers::is3Color(GxEPD2::Panel type) { } } -GxEPD2_GFX* DisplayTypeHelpers::buildDisplay(GxEPD2::Panel type, uint8_t dc, uint8_t rst, uint8_t busy) { +GxEPD2_GFX* DisplayTypeHelpers::buildDisplay(GxEPD2::Panel type, uint8_t dc, uint8_t rst, uint8_t busy, uint8_t ss) { switch (type) { // black/white displays case GxEPD2::Panel::GDEP015OC1: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDE0213B1: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEH0213B72: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW0213I5F: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEH029A1: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW029T5: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW027W3: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW042T2: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW0583T7: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW075T8: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEH0213B73: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW026T0: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW0371W7: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW075T7: - return __gxepd2_build_bw_driver(dc, rst, busy); + return __gxepd2_build_bw_driver(dc, rst, busy, ss); // Color displays case GxEPD2::Panel::ED060SCT: - return __gxepd2_build_3c_driver(dc, rst, busy); + return __gxepd2_build_3c_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW0154Z04: - return __gxepd2_build_3c_driver(dc, rst, busy); + return __gxepd2_build_3c_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW0213Z16: - return __gxepd2_build_3c_driver(dc, rst, busy); + return __gxepd2_build_3c_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW029Z10: - return __gxepd2_build_3c_driver(dc, rst, busy); + return __gxepd2_build_3c_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW027C44: - return __gxepd2_build_3c_driver(dc, rst, busy); + return __gxepd2_build_3c_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW042Z15: - return __gxepd2_build_3c_driver(dc, rst, busy); + return __gxepd2_build_3c_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW0583Z21: - return __gxepd2_build_3c_driver(dc, rst, busy); + return __gxepd2_build_3c_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW075Z09: - return __gxepd2_build_3c_driver(dc, rst, busy); + return __gxepd2_build_3c_driver(dc, rst, busy, ss); case GxEPD2::Panel::GDEW075Z08: - return __gxepd2_build_3c_driver(dc, rst, busy); + return __gxepd2_build_3c_driver(dc, rst, busy, ss); default: Serial.printf_P(PSTR("Unsupported display type, using default. Provided display: %d\n"), static_cast(type)); - return buildDisplay(DisplayTypeHelpers::DEFAULT_PANEL, dc, rst, busy); + return buildDisplay(DisplayTypeHelpers::DEFAULT_PANEL, dc, rst, busy, ss); } } \ No newline at end of file diff --git a/lib/Display/DisplayTypeHelpers.h b/lib/Display/DisplayTypeHelpers.h index 60941c8..2e3230a 100644 --- a/lib/Display/DisplayTypeHelpers.h +++ b/lib/Display/DisplayTypeHelpers.h @@ -15,7 +15,7 @@ class DisplayTypeHelpers { static GxEPD2::Panel stringToDisplayType(const String& displayType); static bool is3Color(GxEPD2::Panel type); - static GxEPD2_GFX* buildDisplay(GxEPD2::Panel type, uint8_t dcPin, uint8_t rstPin, uint8_t busyPin); + static GxEPD2_GFX* buildDisplay(GxEPD2::Panel type, uint8_t dcPin, uint8_t rstPin, uint8_t busyPin, uint8_t ssPin); static const GxEPD2::Panel DEFAULT_PANEL; static const char* DISPLAY_NAMES[]; diff --git a/lib/Settings/Settings.cpp b/lib/Settings/Settings.cpp index d5acb2f..2376df8 100644 --- a/lib/Settings/Settings.cpp +++ b/lib/Settings/Settings.cpp @@ -69,4 +69,19 @@ void SettingsCallbackObserver::onConfigurationChanged(const ConfigurationPropert if (this->callback) { this->callback(value); } +} + +const uint8_t HardwareSettings::getSsPin() const { + if (this->ss_pin_override != -1) { + return static_cast(this->ss_pin_override); + } + + switch (this->spi_bus) { + case HSPI: + case WAVESHARE_SPI: + return 15; + case VSPI: + default: + return 5; + } } \ No newline at end of file diff --git a/lib/Settings/Settings.h b/lib/Settings/Settings.h index 090680c..3b120e7 100644 --- a/lib/Settings/Settings.h +++ b/lib/Settings/Settings.h @@ -79,6 +79,9 @@ class WebSettings : public Configuration { class HardwareSettings : public Configuration { public: + static const uint8_t WAVESHARE_SPI = VSPI + HSPI; + static const uint8_t WAVESHARE_SS_PIN = 15; + persistentVar( uint8_t, spi_bus, @@ -86,6 +89,8 @@ class HardwareSettings : public Configuration { { if (spi_busString.equalsIgnoreCase("vspi")) { spi_bus = VSPI; + } else if (spi_busString.equalsIgnoreCase("waveshare")) { + spi_bus = WAVESHARE_SPI; } else { spi_bus = HSPI; } @@ -93,6 +98,8 @@ class HardwareSettings : public Configuration { { if (spi_bus == VSPI) { spi_busString = "VSPI"; + } else if (spi_bus == WAVESHARE_SPI) { + spi_busString = "waveshare"; } else { spi_busString = "HSPI"; } @@ -101,12 +108,16 @@ class HardwareSettings : public Configuration { persistentIntVar(dc_pin, EPD_DEFAULT_DC_PIN); persistentIntVar(rst_pin, EPD_DEFAULT_RST_PIN); persistentIntVar(busy_pin, EPD_DEFAULT_BUSY_PIN); + persistentIntVar(ss_pin_override, -1); + + const uint8_t getSsPin() const; }; class NetworkSettings : public Configuration { public: persistentStringVar(hostname, DEFAULT_DISPLAY_NAME); persistentStringVar(mdns_name, DEFAULT_DISPLAY_NAME); + persistentStringVar(ntp_server, "pool.ntp.org"); persistentStringVar(setup_ap_password, "waveshare"); persistentStringVar(wifi_ssid, ""); persistentStringVar(wifi_password, ""); diff --git a/lib/Variables/VariableDictionary.cpp b/lib/Variables/VariableDictionary.cpp index faba89e..3c82ada 100644 --- a/lib/Variables/VariableDictionary.cpp +++ b/lib/Variables/VariableDictionary.cpp @@ -38,6 +38,7 @@ String VariableDictionary::get(const String &key) { } void VariableDictionary::clear() { + SPIFFS.remove(VariableDictionary::FILENAME); SPIFFS.open(VariableDictionary::FILENAME, "w").close(); db.open(SPIFFS.open(VariableDictionary::FILENAME, "r+")); diff --git a/platformio.ini b/platformio.ini index 68cad5e..753ecfc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,7 +13,7 @@ framework = arduino board_f_cpu = 80000000L lib_deps_builtin = lib_deps_external = - ArduinoJson@~6.10.1 + ArduinoJson@~6.17.1 Adafruit GFX Library@~1.6.1 Timezone@~1.2.2 AsyncMqttClient@~0.8.2 @@ -31,7 +31,7 @@ lib_deps_external = ; and the webserver builtin to the espressif SDKs define. WiFiManager=https://github.com/sidoh/WiFiManager#async_support - GxEPD2=https://github.com/ZinggJM/GxEPD2#1.2.3 + GxEPD2=https://github.com/ZinggJM/GxEPD2#1.2.14 extra_scripts = pre:scripts/platformio/build_web.py post:scripts/platformio/build_full_image.py diff --git a/src/main.cpp b/src/main.cpp index b4481d9..813f040 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -37,13 +37,13 @@ GxEPD2_GFX* display = NULL; DisplayTemplateDriver* driver = NULL; EpaperWebServer* webServer = NULL; MqttClient* mqttClient = NULL; +NTPClient* timeClient; // Don't attempt to reconnect to wifi if we've never connected volatile bool hasConnected = false; volatile bool shouldRestart = false; WiFiUDP ntpUDP; -NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000); uint8_t lastSecond = 60; @@ -73,13 +73,6 @@ void cancelSleep() { } void initDisplay() { - #if defined(ESP32) - if (settings.hardware.spi_bus == VSPI){ - SPI.end(); - SPI.begin(18, 23, 19, 5); - } - #endif - if (display) { delete display; display = NULL; @@ -88,7 +81,8 @@ void initDisplay() { display = DisplayTypeHelpers::buildDisplay(settings.display.display_type, settings.hardware.dc_pin, settings.hardware.rst_pin, - settings.hardware.busy_pin); + settings.hardware.busy_pin, + settings.hardware.getSsPin()); if (driver != NULL) { delete driver; @@ -115,6 +109,14 @@ void applySettings() { Timezones.setDefaultTimezone(*settings.system.timezone); + if (timeClient != NULL) { + delete timeClient; + timeClient = NULL; + } + + timeClient = new NTPClient(ntpUDP, settings.network.ntp_server.c_str(), 0, 60000); + timeClient->begin(); + if (hasConnected && settings.network.wifi_ssid.length() > 0 && settings.network.wifi_ssid != WiFi.SSID()) { Serial.println(F("Switching WiFi networks")); @@ -255,8 +257,6 @@ void setup() { } } - timeClient.begin(); - applySettings(); } @@ -265,9 +265,9 @@ void loop() { ESP.restart(); } - if (timeClient.update() && lastSecond != second()) { + if (timeClient != NULL && timeClient->update() && lastSecond != second()) { lastSecond = second(); - driver->updateVariable("timestamp", String(timeClient.getEpochTime())); + driver->updateVariable("timestamp", String(timeClient->getEpochTime())); } if (webServer) { diff --git a/web/package-lock.json b/web/package-lock.json index 2e31d6c..0933c87 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -3043,6 +3043,11 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==" } } }, @@ -3896,9 +3901,9 @@ } }, "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", + "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", "requires": { "is-obj": "^1.0.0" } @@ -3963,9 +3968,9 @@ "integrity": "sha512-1qConyiVEbj4xZRBXqtGR003+9tV0rJF0PS6aeO0Ln/UL637js9hdwweCl07meh/kJoI2N4W8q3R3g3F5z46ww==" }, "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -5174,12 +5179,6 @@ "dev": true, "optional": true }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, @@ -6102,9 +6101,9 @@ "dev": true }, "http-proxy": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", - "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "requires": { "eventemitter3": "^4.0.0", @@ -6238,9 +6237,9 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, "inline-style-prefixer": { @@ -9186,7 +9185,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "requires": { "safe-buffer": "^5.1.0" } @@ -10263,9 +10261,12 @@ } }, "serialize-javascript": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", - "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "requires": { + "randombytes": "^2.1.0" + } }, "serve-index": { "version": "1.9.1", @@ -11431,6 +11432,12 @@ "ajv-keywords": "^3.1.0" } }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", diff --git a/web/package.json b/web/package.json index 4821134..e84b854 100644 --- a/web/package.json +++ b/web/package.json @@ -41,7 +41,7 @@ "react-switch": "^5.0.1", "react-use": "^13.27.1", "react-use-websocket": "^1.3.4", - "serialize-javascript": "^2.1.2", + "serialize-javascript": "^3.1.0", "use-global-hook": "^0.1.12" }, "devDependencies": { diff --git a/web/src/settings/schema/hardware.js b/web/src/settings/schema/hardware.js index 75a74d2..1956a65 100644 --- a/web/src/settings/schema/hardware.js +++ b/web/src/settings/schema/hardware.js @@ -1,12 +1,14 @@ +const VALID_PINS = [ + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39 +]; + export default { key: "hardware", title: "Hardware", definitions: { pin: { type: "integer", - enum: [ - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39 - ] + enum: VALID_PINS } }, properties: { @@ -30,10 +32,21 @@ export default { title: "SPI Bus", oneOf: [ { const: "HSPI", title: "HSPI (default)" }, - { const: "VSPI", title: "VSPI" } + { const: "VSPI", title: "VSPI" }, + { const: "waveshare", title: "Waveshare ESP32 Driver (custom)" }, ], type: "string", default: "HSPI" + }, + "hardware.ss_pin_override": { + $id: "#/properties/hardware.ss_pin_override", + title: "SPI SS Pin Override", + oneOf: [ + { const: -1, title: "default" }, + ...VALID_PINS.map(x => ({const: x, title: String(x)})) + ], + type: "integer", + default: -1 } } }; diff --git a/web/src/settings/schema/network.js b/web/src/settings/schema/network.js index aa5a131..6bd39c3 100644 --- a/web/src/settings/schema/network.js +++ b/web/src/settings/schema/network.js @@ -9,6 +9,14 @@ export default { examples: ["epaper-display"], pattern: "^(.*)$" }, + "network.ntp_server": { + $id: "#/properties/network.ntp_server", + type: "string", + title: "NTP Server", + default: "pool.ntp.org", + examples: ["pool.ntp.org"], + pattern: "^(.*)$" + }, "network.mdns_name": { $id: "#/properties/network.mdns_name", type: "string", diff --git a/web/src/settings/ui_schema.js b/web/src/settings/ui_schema.js index a3ea5cd..24da973 100644 --- a/web/src/settings/ui_schema.js +++ b/web/src/settings/ui_schema.js @@ -52,7 +52,8 @@ export default { "hardware.rst_pin": { transformer: parseInt }, - "hardware.spi_bus": { + "hardware.ss_pin_override": { + transformer: parseInt, "ui:help": <>
SPI bus to use. HSPI uses GPIOs 12, 14, 15. VSPI uses 5, 18, 19. See README for more details. @@ -63,6 +64,8 @@ export default {
}, + "hardware.spi_bus": { + }, "web.port": { transformer: parseInt },