From 920a9f3fbf68ea093d9f0ac36bad7f74ffcaf8df Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Sun, 29 Jan 2023 12:07:54 +0100 Subject: [PATCH 1/6] WIP branch working on adding an external display. --- Makefile | 124 +++++++++++++++++++++++++++++++++++++++++++++++ OTGW-Display.h | 0 OTGW-Display.ino | 0 3 files changed, 124 insertions(+) create mode 100644 Makefile create mode 100644 OTGW-Display.h create mode 100644 OTGW-Display.ino diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..13fca1b7 --- /dev/null +++ b/Makefile @@ -0,0 +1,124 @@ +# -*- make -*- + +PROJ = $(notdir $(PWD)) +SOURCES = $(wildcard *.ino *.cpp *.h) +FSDIR = data +FILES = $(wildcard $(FSDIR)/*) + +# Don't use -DATOMIC_FS_UPDATE +CFLAGS_DEFAULT = -DNO_GLOBAL_HTTPUPDATE +CFLAGS = $(CFLAGS_DEFAULT) + +CLI := arduino-cli +PLATFORM := esp8266:esp8266 +CFGFILE := arduino-cli.yaml +ESP8266URL := https://github.com/esp8266/Arduino/releases/download/2.7.4/package_esp8266com_index.json +LIBRARIES := libraries/WiFiManager libraries/ArduinoJson libraries/pubsubclient libraries/TelnetStream libraries/Acetime libraries/Time libraries/OneWire libraries/DallasTemperature +BOARDS := arduino/package_esp8266com_index.json +# PORT can be overridden by the environment or on the command line. E.g.: +# export PORT=/dev/ttyUSB2; make upload, or: make upload PORT=/dev/ttyUSB2 +PORT ?= /dev/ttyUSB0 +BAUD ?= 460800 + +INO = $(PROJ).ino +MKFS = $(wildcard arduino/packages/esp8266/tools/mklittlefs/*/mklittlefs) +TOOLS = $(wildcard arduino/packages/esp8266/hardware/esp8266/*/tools) +ESPTOOL = python3 $(TOOLS)/esptool/esptool.py +BOARD = $(PLATFORM):d1_mini +FQBN = $(BOARD):eesz=4M1M +IMAGE = build/$(subst :,.,$(BOARD))/$(INO).bin +FILESYS = filesys.bin + +export PYTHONPATH = $(TOOLS)/pyserial + +binaries: $(IMAGE) + +publish: $(PROJ)-fs.bin $(PROJ)-fw.bin + +platform: $(BOARDS) + +clean: + find $(FSDIR) -name '*~' -exec rm {} + + +$(CFGFILE): + $(CLI) config init --dest-file $(CFGFILE) + $(CLI) config set board_manager.additional_urls $(ESP8266URL) + $(CLI) config set directories.data $(PWD)/arduino + $(CLI) config set directories.downloads $(PWD)/staging + $(CLI) config set directories.user $(PWD) + $(CLI) config set sketch.always_export_binaries true + $(CLI) config set library.enable_unsafe_install true + +$(BOARDS): | $(CFGFILE) + $(CLI) core update-index + $(CLI) core install $(PLATFORM) + +refresh: | $(CFGFILE) + $(CLI) lib update-index + +flush: | $(CFGFILE) + $(CLI) cache clean + +libraries/WiFiManager: | $(BOARDS) + $(CLI) lib install WiFiManager@2.0.15-rc.1 + +libraries/ArduinoJson: + $(CLI) lib install ArduinoJson@6.17.2 + +libraries/pubsubclient: + $(CLI) lib install pubsubclient@2.8.0 + +libraries/TelnetStream: + $(CLI) lib install TelnetStream@1.2.2 + +libraries/Acetime: + $(CLI) lib install Acetime@2.0.1 + +libraries/Time: + $(CLI) lib install --git-url https://github.com/PaulStoffregen/Time + # https://github.com/PaulStoffregen/Time/archive/refs/tags/v1.6.1.zip + +libraries/OneWire: + $(CLI) lib install OneWire@2.3.6 + +libraries/DallasTemperature: + $(CLI) lib install DallasTemperature@3.9.0 + +$(IMAGE): $(BOARDS) $(LIBRARIES) $(SOURCES) + $(CLI) compile --config-file $(CFGFILE) --fqbn=$(FQBN) --warnings default --verbose --build-property compiler.cpp.extra_flags="$(CFLAGS)" + +$(FILESYS): $(FILES) $(CONF) | $(BOARDS) clean + $(MKFS) -p 256 -b 8192 -s 1024000 -c $(FSDIR) $@ + +$(PROJ)-fs.bin: $(FILES) $(CONF) | $(BOARDS) clean + $(MKFS) -p 256 -b 8192 -s 1024000 -c $(FSDIR) $@ + +$(PROJ)-fw.bin: $(IMAGE) + cp $(IMAGE) $@ + +$(PROJ).zip: $(PROJ)-fw.bin $(PROJ)-fs.bin + rm -f $@ + zip $@ $^ + +# Build the image with debugging output +debug: CFLAGS = $(CFLAGS_DEFAULT) -DDEBUG +debug: $(IMAGE) + +# Load only the sketch into the device +upload: $(IMAGE) + $(ESPTOOL) --port $(PORT) -b $(BAUD) write_flash 0x0 $(IMAGE) + +# Load only the file system into the device +upload-fs: $(FILESYS) + $(ESPTOOL) --port $(PORT) -b $(BAUD) write_flash 0x300000 $(FILESYS) + +# Load both the sketch and the file system into the device +install: $(IMAGE) $(FILESYS) + $(ESPTOOL) --port $(PORT) -b $(BAUD) write_flash 0x0 $(IMAGE) 0x300000 $(FILESYS) + +.PHONY: binaries platform publish clean upload upload-fs install debug + +### Allow customization through a local Makefile: Makefile-local.mk + +# Include the local make file, if it exists +-include Makefile-local.mk diff --git a/OTGW-Display.h b/OTGW-Display.h new file mode 100644 index 00000000..e69de29b diff --git a/OTGW-Display.ino b/OTGW-Display.ino new file mode 100644 index 00000000..e69de29b From c15f36a9810cebc849ce2b373e845dd3b095fef2 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Sun, 29 Jan 2023 13:52:16 +0100 Subject: [PATCH 2/6] Add some initial code. This has been dry-coded, untested. --- Makefile | 5 +++- OTGW-Display.h | 34 +++++++++++++++++++++++ OTGW-Display.ino | 70 +++++++++++++++++++++++++++++++++++++++++++++++ OTGW-firmware.ino | 12 ++++++-- 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 13fca1b7..917b7801 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ CLI := arduino-cli PLATFORM := esp8266:esp8266 CFGFILE := arduino-cli.yaml ESP8266URL := https://github.com/esp8266/Arduino/releases/download/2.7.4/package_esp8266com_index.json -LIBRARIES := libraries/WiFiManager libraries/ArduinoJson libraries/pubsubclient libraries/TelnetStream libraries/Acetime libraries/Time libraries/OneWire libraries/DallasTemperature +LIBRARIES := libraries/WiFiManager libraries/ArduinoJson libraries/pubsubclient libraries/TelnetStream libraries/Acetime libraries/Time libraries/OneWire libraries/DallasTemperature libraries/U8g2 BOARDS := arduino/package_esp8266com_index.json # PORT can be overridden by the environment or on the command line. E.g.: # export PORT=/dev/ttyUSB2; make upload, or: make upload PORT=/dev/ttyUSB2 @@ -74,6 +74,9 @@ libraries/TelnetStream: libraries/Acetime: $(CLI) lib install Acetime@2.0.1 +libraries/u8g2: + $(CLI) lib install u8g2@2.33.15 + libraries/Time: $(CLI) lib install --git-url https://github.com/PaulStoffregen/Time # https://github.com/PaulStoffregen/Time/archive/refs/tags/v1.6.1.zip diff --git a/OTGW-Display.h b/OTGW-Display.h index e69de29b..447e7a81 100644 --- a/OTGW-Display.h +++ b/OTGW-Display.h @@ -0,0 +1,34 @@ +#ifndef OTGW_DISPLAY +#define OTGW_DISPLAY +#include +#include + +class OTGW_Display +{ + + public: + OTGW_Display (); + ~OTGW_Display (); + + // Start + void begin(); + + // Function to periodically call to update itself. + void tick (); + + // Put a message over top. + // This will also force an update. + void message ( const String &str = "" ); + + private: + void draw_welcome(); + void draw_message(); + void draw_main_screen(); + + private: + // U8g2 Object used for interaction with Oled. + U8G2 *u8g2 = nullptr; + String _message = ""; +}; + +#endif // OTGW_DISPLAY diff --git a/OTGW-Display.ino b/OTGW-Display.ino index e69de29b..868e01f3 100644 --- a/OTGW-Display.ino +++ b/OTGW-Display.ino @@ -0,0 +1,70 @@ +#include "OTGW-Display.h" +#include "Wire.h" + +OTGW_Display::~OTGW_Display() +{ + if ( u8g2 ) { + delete u8g2; + } +} + +void OTGW_Display::draw_welcome() +{ + + u8g2->drawFrame(0,0,128,64); + u8g2->sendBuffer(); +} + +OTGW_Display::OTGW_Display() +{ +} + +void OTGW_Display::begin() +{ + // Start looking for devices. + Wire.beginTransmission(0x8d); + int error = Wire.endTransmission(); + if ( error == 0 ) { + u8g2 = new U8G2_SH1106_128X64_NONAME_F_HW_I2C (U8G2_R0); + + // Set some defaults + u8g2->setFont(u8g2_font_logisoso22_tf); + u8g2->setFontRefHeightExtendedText(); + u8g2->setDrawColor(1); + u8g2->setFontPosTop(); + u8g2->setFontDirection(0); + draw_welcome (); + } + +} + +void OTGW_Display::draw_message() +{ + u8g2->drawUTF8(4,7, _message.c_str()); + +} + +void OTGW_Display::draw_main_screen() +{ + +} + +void OTGW_Display::tick() +{ + u8g2->drawFrame(0,0,128,64); + + if ( _message.length() > 0 ) { + draw_message (); + } else { + draw_main_screen (); + } + + // Send towards screen. + u8g2->sendBuffer(); +} + +void OTGW_Display::message(const String &str ) +{ + + this->tick(); +} diff --git a/OTGW-firmware.ino b/OTGW-firmware.ino index 2361aac5..eb5009d6 100644 --- a/OTGW-firmware.ino +++ b/OTGW-firmware.ino @@ -27,6 +27,7 @@ #include "version.h" #include "OTGW-firmware.h" +#include "OTGW-Display.h" #define SetupDebugTln(...) ({ if (bPICavailable) DebugTln(__VA_ARGS__); }) #define SetupDebugln(...) ({ if (bPICavailable) Debugln(__VA_ARGS__); }) @@ -41,6 +42,9 @@ DECLARE_TIMER_SEC(timerpollsensor, settingGPIOSENSORSinterval, CATCH_UP_MISSED_TICKS); DECLARE_TIMER_SEC(timers0counter, settingS0COUNTERinterval, CATCH_UP_MISSED_TICKS); + +// Small status display interface. +OTGW_Display display; //===================================================================== void setup() { @@ -53,8 +57,9 @@ void setup() { SetupDebugln(F("\r\n[OTGW firmware - Nodoshop version]\r\n")); SetupDebugf("Booting....[%s]\r\n\r\n", _VERSION); - - + + display.begin(); + detectPIC(); //setup randomseed the right way @@ -245,7 +250,8 @@ void doTaskEvery1s(){ //===[ Do task every 5s ]=== void doTaskEvery5s(){ //== do tasks == - + //== Update Display == + display.tick(); } //===[ Do task every 30s ]=== From 73e4da7847fc1c536486ffbbd600250ddadc90d2 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Sun, 29 Jan 2023 13:55:56 +0100 Subject: [PATCH 3/6] Guard the tick() function, set _message in ::message() --- OTGW-Display.ino | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/OTGW-Display.ino b/OTGW-Display.ino index 868e01f3..80d0024a 100644 --- a/OTGW-Display.ino +++ b/OTGW-Display.ino @@ -51,20 +51,24 @@ void OTGW_Display::draw_main_screen() void OTGW_Display::tick() { - u8g2->drawFrame(0,0,128,64); + // If no display is available, lets not do anything. + if ( u8g2 == nullptr ) { + return; + } + u8g2->drawFrame(0,0,128,64); - if ( _message.length() > 0 ) { - draw_message (); - } else { - draw_main_screen (); - } + if ( _message.length() > 0 ) { + draw_message (); + } else { + draw_main_screen (); + } - // Send towards screen. - u8g2->sendBuffer(); + // Send towards screen. + u8g2->sendBuffer(); } void OTGW_Display::message(const String &str ) { - + _message = str; this->tick(); } From 4d1515091ecd7a90a08c7d41fad1f85f39f32305 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Sun, 29 Jan 2023 19:30:17 +0100 Subject: [PATCH 4/6] This makes it work with a 128x64 SH1106 --- Debug.h | 1 + OTGW-Display.ino | 35 ++++++++++++++++++++++++++++------- OTGW-firmware.ino | 2 +- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/Debug.h b/Debug.h index 4e632092..9e9083e3 100644 --- a/Debug.h +++ b/Debug.h @@ -9,6 +9,7 @@ *************************************************************************** ** Modified: as OTGW actually uses the Serial interface, so no more debug to serial please. */ +#pragma once /*---- start macro's ------------------------------------------------------------------*/ diff --git a/OTGW-Display.ino b/OTGW-Display.ino index 80d0024a..3fa61d8a 100644 --- a/OTGW-Display.ino +++ b/OTGW-Display.ino @@ -1,5 +1,8 @@ #include "OTGW-Display.h" +#include "ESP8266WiFi.h" #include "Wire.h" +#include "Debug.h" +#include "clib/u8g2.h" OTGW_Display::~OTGW_Display() { @@ -7,11 +10,14 @@ OTGW_Display::~OTGW_Display() delete u8g2; } } - void OTGW_Display::draw_welcome() { u8g2->drawFrame(0,0,128,64); + u8g2->drawUTF8(4,7, "OTGW Booting.."); + char buf[16]; + snprintf(buf, sizeof(buf), "Version %s", _VERSION ); + u8g2->drawUTF8(4,20, buf ); u8g2->sendBuffer(); } @@ -21,21 +27,32 @@ OTGW_Display::OTGW_Display() void OTGW_Display::begin() { - // Start looking for devices. - Wire.beginTransmission(0x8d); + Wire.beginTransmission(0x3c); int error = Wire.endTransmission(); if ( error == 0 ) { u8g2 = new U8G2_SH1106_128X64_NONAME_F_HW_I2C (U8G2_R0); + } else { + // No display found. + } + + + if ( u8g2 != nullptr ) { + // Initialize u8g2 + u8g2->beginSimple(); + // Disable power save. + u8g2->setPowerSave(0); + // Lower the contrast, this will extend the lifetime of the + // OLED screen. + u8g2->setContrast(1); // Set some defaults - u8g2->setFont(u8g2_font_logisoso22_tf); + u8g2->setFont(u8g2_font_cu12_tf); u8g2->setFontRefHeightExtendedText(); u8g2->setDrawColor(1); u8g2->setFontPosTop(); u8g2->setFontDirection(0); draw_welcome (); } - } void OTGW_Display::draw_message() @@ -46,7 +63,9 @@ void OTGW_Display::draw_message() void OTGW_Display::draw_main_screen() { - + char buf[32]; + snprintf(buf, sizeof(buf), "IP: %d.%d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]); + u8g2->drawUTF8(4,7, buf); } void OTGW_Display::tick() @@ -55,6 +74,8 @@ void OTGW_Display::tick() if ( u8g2 == nullptr ) { return; } + // Draw border around the screen. + u8g2->clearBuffer(); u8g2->drawFrame(0,0,128,64); if ( _message.length() > 0 ) { @@ -63,7 +84,7 @@ void OTGW_Display::tick() draw_main_screen (); } - // Send towards screen. + // Send internal buffer towards screen. u8g2->sendBuffer(); } diff --git a/OTGW-firmware.ino b/OTGW-firmware.ino index eb5009d6..ecd2b082 100644 --- a/OTGW-firmware.ino +++ b/OTGW-firmware.ino @@ -58,7 +58,6 @@ void setup() { SetupDebugln(F("\r\n[OTGW firmware - Nodoshop version]\r\n")); SetupDebugf("Booting....[%s]\r\n\r\n", _VERSION); - display.begin(); detectPIC(); @@ -98,6 +97,7 @@ void setup() { rebootCount = updateRebootCount(); updateRebootLog(lastReset); + display.begin(); SetupDebugln(F("Setup finished!\r\n")); // After resetting the OTGW PIC never send anything to Serial for debug From 2eed8ee6c515779037d9ccdd874b02dd799d1056 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Sun, 29 Jan 2023 19:38:01 +0100 Subject: [PATCH 5/6] Add paging support and some demo pages. Also start with bar for icons. --- OTGW-Display.h | 13 +++++++- OTGW-Display.ino | 84 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/OTGW-Display.h b/OTGW-Display.h index 447e7a81..a2498f50 100644 --- a/OTGW-Display.h +++ b/OTGW-Display.h @@ -7,6 +7,12 @@ class OTGW_Display { public: + enum class Pages { + DISPLAY_IP, + DISPLAY_TIME, + DISPLAY_UPTIME, + DISPLAY_VERSION + }; OTGW_Display (); ~OTGW_Display (); @@ -23,12 +29,17 @@ class OTGW_Display private: void draw_welcome(); void draw_message(); - void draw_main_screen(); + + void draw_display_ip(); + void draw_display_time(); + void draw_display_uptime(); + void draw_display_version(); private: // U8g2 Object used for interaction with Oled. U8G2 *u8g2 = nullptr; String _message = ""; + Pages page = Pages::DISPLAY_IP; }; #endif // OTGW_DISPLAY diff --git a/OTGW-Display.ino b/OTGW-Display.ino index 3fa61d8a..4681031e 100644 --- a/OTGW-Display.ino +++ b/OTGW-Display.ino @@ -3,6 +3,7 @@ #include "Wire.h" #include "Debug.h" #include "clib/u8g2.h" +#include "OTGW-Core.h" OTGW_Display::~OTGW_Display() { @@ -17,7 +18,7 @@ void OTGW_Display::draw_welcome() u8g2->drawUTF8(4,7, "OTGW Booting.."); char buf[16]; snprintf(buf, sizeof(buf), "Version %s", _VERSION ); - u8g2->drawUTF8(4,20, buf ); + u8g2->drawUTF8(4,24, buf ); u8g2->sendBuffer(); } @@ -46,7 +47,7 @@ void OTGW_Display::begin() u8g2->setContrast(1); // Set some defaults - u8g2->setFont(u8g2_font_cu12_tf); + u8g2->setFont(u8g2_font_t0_14b_mr); u8g2->setFontRefHeightExtendedText(); u8g2->setDrawColor(1); u8g2->setFontPosTop(); @@ -61,13 +62,60 @@ void OTGW_Display::draw_message() } -void OTGW_Display::draw_main_screen() +void OTGW_Display::draw_display_ip() { char buf[32]; - snprintf(buf, sizeof(buf), "IP: %d.%d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]); - u8g2->drawUTF8(4,7, buf); + snprintf(buf, sizeof(buf), "IP"); + u8g2->drawUTF8(4,4, buf); + snprintf(buf, sizeof(buf), "%d.%d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]); + u8g2->drawUTF8(4,24, buf); } +void OTGW_Display::draw_display_time() +{ + + char buf[50]; + snprintf(buf, sizeof(buf), "Time"); + u8g2->drawUTF8(4,4, buf); + time_t now = time(nullptr); + //Timezone based devtime + TimeZone myTz = timezoneManager.createForZoneName(CSTR(settingNTPtimezone)); + ZonedDateTime myTime = ZonedDateTime::forUnixSeconds64(now, myTz); + snprintf(buf, 49, PSTR("%04d-%02d-%02d"), myTime.year(), myTime.month(), myTime.day()); + + u8g2->drawUTF8(4,24, buf); + snprintf(buf, 49, PSTR("%02d:%02d:%02d"), myTime.hour(), myTime.minute(), myTime.second()); + + u8g2->drawUTF8(4,40, buf); +} + +void OTGW_Display::draw_display_uptime() +{ + + char buf[50]; + snprintf(buf, sizeof(buf), "Uptime"); + u8g2->drawUTF8(4,4, buf); + uint32_t seconds= upTimeSeconds; + uint32_t days = seconds/(60*60*24); + seconds -= days*60*60*24; + uint16_t hours = seconds/(60*60); + seconds -= hours*60*60; + uint16_t minutes = seconds/(60); + seconds -= minutes*60; + snprintf(buf, 49, PSTR("%03dd %02d:%02d:%02d"), + days, hours, minutes,seconds); + + u8g2->drawUTF8(4,24, buf); +} +void OTGW_Display::draw_display_version() +{ + u8g2->drawUTF8(4,4, "OTGW version"); + char buf[12]; + snprintf(buf, sizeof(buf), "%s", _VERSION); + u8g2->drawUTF8(4,24, buf); +} + + void OTGW_Display::tick() { // If no display is available, lets not do anything. @@ -77,11 +125,35 @@ void OTGW_Display::tick() // Draw border around the screen. u8g2->clearBuffer(); u8g2->drawFrame(0,0,128,64); + u8g2->drawLine(108, 0,108, 64); if ( _message.length() > 0 ) { draw_message (); } else { - draw_main_screen (); + + switch ( page ) { + case OTGW_Display::Pages::DISPLAY_IP: + draw_display_ip (); + page = OTGW_Display::Pages::DISPLAY_TIME; + break; + case OTGW_Display::Pages::DISPLAY_TIME: + draw_display_time (); + page = OTGW_Display::Pages::DISPLAY_UPTIME; + break; + case OTGW_Display::Pages::DISPLAY_UPTIME: + draw_display_uptime (); + page = OTGW_Display::Pages::DISPLAY_VERSION; + break; + case OTGW_Display::Pages::DISPLAY_VERSION: + draw_display_version (); + page = OTGW_Display::Pages::DISPLAY_IP; + break; + } + } + if ( ((OTdata.valueLB) & 0x08) ) { + u8g2->drawUTF8( 112, 2, "F"); + } else { + u8g2->drawUTF8( 112, 2, "X"); } // Send internal buffer towards screen. From 77f8952e5e2ecbdf3e1b310e753c4ecb70fc2a60 Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Mon, 30 Jan 2023 19:19:08 +0100 Subject: [PATCH 6/6] Comment the code a bit and make message page, part of the message page. --- Debug.h | 1 - Makefile | 2 +- OTGW-Display.h | 47 +++++++++++---- OTGW-Display.ino | 151 +++++++++++++++++++++++++++++++--------------- OTGW-firmware.ino | 3 + 5 files changed, 144 insertions(+), 60 deletions(-) diff --git a/Debug.h b/Debug.h index 9e9083e3..4e632092 100644 --- a/Debug.h +++ b/Debug.h @@ -9,7 +9,6 @@ *************************************************************************** ** Modified: as OTGW actually uses the Serial interface, so no more debug to serial please. */ -#pragma once /*---- start macro's ------------------------------------------------------------------*/ diff --git a/Makefile b/Makefile index 917b7801..f2b4af02 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,7 @@ libraries/TelnetStream: libraries/Acetime: $(CLI) lib install Acetime@2.0.1 -libraries/u8g2: +libraries/U8g2: $(CLI) lib install u8g2@2.33.15 libraries/Time: diff --git a/OTGW-Display.h b/OTGW-Display.h index a2498f50..e583f366 100644 --- a/OTGW-Display.h +++ b/OTGW-Display.h @@ -3,17 +3,34 @@ #include #include +/** + * A small module that can use a small external display + * to provide some useful feedback to the user. + * For example: + * * Current IP address. + * * Current OTGW Version. + * * Uptime + * * Boiler status + * * etc. + * + * To use this class, instantiate it. Call the begin function + * after the iic is setup. Then periodically call tick() to draw a new page. + */ class OTGW_Display { - public: + public: + // The different pages we can display. enum class Pages { DISPLAY_IP, DISPLAY_TIME, DISPLAY_UPTIME, - DISPLAY_VERSION + DISPLAY_VERSION, + DISPLAY_MESSAGE }; - OTGW_Display (); + // Constructor + OTGW_Display (); + // Destructor ~OTGW_Display (); // Start @@ -27,18 +44,26 @@ class OTGW_Display void message ( const String &str = "" ); private: + // The welcome screen. void draw_welcome(); - void draw_message(); - - void draw_display_ip(); - void draw_display_time(); - void draw_display_uptime(); - void draw_display_version(); - - private: + + // Pages::DISPLAY_IP + void draw_display_page_ip(); + // Pages::DISPLAY_TIME + void draw_display_page_time(); + // Pages::DISPLAY_UPTIME + void draw_display_page_uptime(); + // Pages::DISPLAY_VERSION + void draw_display_page_version(); + // Pages::DISPLAY_MESSAGE + void draw_display_page_message(); + + private: // U8g2 Object used for interaction with Oled. U8G2 *u8g2 = nullptr; + // A message that can be set from the code. String _message = ""; + // Current page. Pages page = Pages::DISPLAY_IP; }; diff --git a/OTGW-Display.ino b/OTGW-Display.ino index 4681031e..48ead1b4 100644 --- a/OTGW-Display.ino +++ b/OTGW-Display.ino @@ -1,33 +1,36 @@ #include "OTGW-Display.h" #include "ESP8266WiFi.h" #include "Wire.h" -#include "Debug.h" #include "clib/u8g2.h" #include "OTGW-Core.h" +/** + * Deconstructor. + */ OTGW_Display::~OTGW_Display() { if ( u8g2 ) { delete u8g2; } } -void OTGW_Display::draw_welcome() -{ - - u8g2->drawFrame(0,0,128,64); - u8g2->drawUTF8(4,7, "OTGW Booting.."); - char buf[16]; - snprintf(buf, sizeof(buf), "Version %s", _VERSION ); - u8g2->drawUTF8(4,24, buf ); - u8g2->sendBuffer(); -} +/** + * Constructor + */ OTGW_Display::OTGW_Display() { } +/** + * This sets up the display. + */ void OTGW_Display::begin() { + /** + * Try to auto-detect if a display is connected + * to the iic connection. + */ + // Check 0x3c for a small oled screen. Wire.beginTransmission(0x3c); int error = Wire.endTransmission(); if ( error == 0 ) { @@ -35,8 +38,10 @@ void OTGW_Display::begin() } else { // No display found. } + // TODO: Add and test with more displays. u8g2 supports many. + // If we found a display, set it up and configure some defaults. if ( u8g2 != nullptr ) { // Initialize u8g2 u8g2->beginSimple(); @@ -46,36 +51,68 @@ void OTGW_Display::begin() // OLED screen. u8g2->setContrast(1); - // Set some defaults + // Set some defaults: + // Font u8g2->setFont(u8g2_font_t0_14b_mr); u8g2->setFontRefHeightExtendedText(); - u8g2->setDrawColor(1); u8g2->setFontPosTop(); u8g2->setFontDirection(0); + // Set drawing color + u8g2->setDrawColor(1); + // Draw the welcome screen. + // This will be redrawn once the ::tick() is called. draw_welcome (); } } -void OTGW_Display::draw_message() +/** + * Draw the welcome screen. + */ +void OTGW_Display::draw_welcome() { - u8g2->drawUTF8(4,7, _message.c_str()); + u8g2->drawFrame(0,0,128,64); + u8g2->drawUTF8(4,7, "OTGW Booting.."); + char buf[16]; + snprintf(buf, sizeof(buf), "Version %s", _VERSION ); + u8g2->drawUTF8(4,24, buf ); + u8g2->sendBuffer(); +} +/** + * Draw the message page. + * ::Pages::DISPLAY_MESSAGE + */ +void OTGW_Display::draw_display_page_message() +{ + // Clean out old buffer, and reset the frame. + u8g2->clearBuffer(); + u8g2->drawFrame(0,0,128,64); + u8g2->drawLine(108, 0,108, 64); + u8g2->drawUTF8(4,7, _message.c_str()); } -void OTGW_Display::draw_display_ip() +/** + * Draw the ip address page. + * ::Pages::DISPLAY_IP + */ +void OTGW_Display::draw_display_page_ip() { - char buf[32]; - snprintf(buf, sizeof(buf), "IP"); + char buf[32]; + snprintf(buf, sizeof(buf), "IP"); u8g2->drawUTF8(4,4, buf); - snprintf(buf, sizeof(buf), "%d.%d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]); + snprintf(buf, sizeof(buf), "%d.%d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]); u8g2->drawUTF8(4,24, buf); } -void OTGW_Display::draw_display_time() +/** + * Draw the time page. + * ::Pages::DISPLAY_TIME + */ +void OTGW_Display::draw_display_page_time() { char buf[50]; - snprintf(buf, sizeof(buf), "Time"); + snprintf(buf, sizeof(buf), "Time"); u8g2->drawUTF8(4,4, buf); time_t now = time(nullptr); //Timezone based devtime @@ -89,11 +126,15 @@ void OTGW_Display::draw_display_time() u8g2->drawUTF8(4,40, buf); } -void OTGW_Display::draw_display_uptime() +/** + * Draw the uptime page. + * ::Pages::DISPLAY_UPTIME + */ +void OTGW_Display::draw_display_page_uptime() { char buf[50]; - snprintf(buf, sizeof(buf), "Uptime"); + snprintf(buf, sizeof(buf), "Uptime"); u8g2->drawUTF8(4,4, buf); uint32_t seconds= upTimeSeconds; uint32_t days = seconds/(60*60*24); @@ -107,7 +148,12 @@ void OTGW_Display::draw_display_uptime() u8g2->drawUTF8(4,24, buf); } -void OTGW_Display::draw_display_version() + +/** + * Draw the version page. + * ::Pages::DISPLAY_VERSION + */ +void OTGW_Display::draw_display_page_version() { u8g2->drawUTF8(4,4, "OTGW version"); char buf[12]; @@ -115,7 +161,10 @@ void OTGW_Display::draw_display_version() u8g2->drawUTF8(4,24, buf); } - +/** + * Periodic update tick function. + * This will update the page and if needed switch to the next one. + */ void OTGW_Display::tick() { // If no display is available, lets not do anything. @@ -127,28 +176,27 @@ void OTGW_Display::tick() u8g2->drawFrame(0,0,128,64); u8g2->drawLine(108, 0,108, 64); - if ( _message.length() > 0 ) { - draw_message (); - } else { - - switch ( page ) { - case OTGW_Display::Pages::DISPLAY_IP: - draw_display_ip (); - page = OTGW_Display::Pages::DISPLAY_TIME; - break; - case OTGW_Display::Pages::DISPLAY_TIME: - draw_display_time (); - page = OTGW_Display::Pages::DISPLAY_UPTIME; - break; - case OTGW_Display::Pages::DISPLAY_UPTIME: - draw_display_uptime (); - page = OTGW_Display::Pages::DISPLAY_VERSION; - break; - case OTGW_Display::Pages::DISPLAY_VERSION: - draw_display_version (); - page = OTGW_Display::Pages::DISPLAY_IP; - break; - } + switch ( page ) { + case OTGW_Display::Pages::DISPLAY_IP: + draw_display_page_ip (); + page = OTGW_Display::Pages::DISPLAY_TIME; + break; + case OTGW_Display::Pages::DISPLAY_TIME: + draw_display_page_time (); + page = OTGW_Display::Pages::DISPLAY_UPTIME; + break; + case OTGW_Display::Pages::DISPLAY_UPTIME: + draw_display_page_uptime (); + page = OTGW_Display::Pages::DISPLAY_VERSION; + break; + case OTGW_Display::Pages::DISPLAY_VERSION: + draw_display_page_version (); + page = OTGW_Display::Pages::DISPLAY_IP; + break; + case OTGW_Display::Pages::DISPLAY_MESSAGE: + draw_display_page_message (); + page = OTGW_Display::Pages::DISPLAY_MESSAGE; + break; } if ( ((OTdata.valueLB) & 0x08) ) { u8g2->drawUTF8( 112, 2, "F"); @@ -160,8 +208,17 @@ void OTGW_Display::tick() u8g2->sendBuffer(); } +/** + * Set a message that override the current page. + */ void OTGW_Display::message(const String &str ) { _message = str; + if ( _message.length() > 0 ) { + page = OTGW_Display::Pages::DISPLAY_MESSAGE; + } else { + page = OTGW_Display::Pages::DISPLAY_VERSION; + } + // Force a page reload. Showing the message. this->tick(); } diff --git a/OTGW-firmware.ino b/OTGW-firmware.ino index ecd2b082..2fc5281c 100644 --- a/OTGW-firmware.ino +++ b/OTGW-firmware.ino @@ -97,6 +97,9 @@ void setup() { rebootCount = updateRebootCount(); updateRebootLog(lastReset); + // Initialize the display. + // We need to do this after the watchdog has initialized the TwoWire (IIC) + // module. display.begin(); SetupDebugln(F("Setup finished!\r\n"));