Revamped screens to now be based upon CScreen class, along with a CScreenManager class.

This commit is contained in:
rljonesau 2018-11-25 15:45:17 +11:00
parent 346056f982
commit b77bbb127e
12 changed files with 557 additions and 413 deletions

View file

@ -132,6 +132,7 @@ CProtocol HeaterFrame2; // data packet received from heater in resp
CProtocol DefaultBTCParams(CProtocol::CtrlMode); // defines the default parameters, used in case of no OEM controller
CSmartError SmartError;
CKeyPad KeyPad;
CScreenManager ScreenManager;
sRxLine PCline;
long lastRxTime; // used to observe inter character delays
@ -193,6 +194,12 @@ CBluetoothAbstract& getBluetoothClient()
return Bluetooth;
}
// callback function for Keypad events.
// must be an absolute function, cannot be a class member due the "this" element!
void parentKeyHandler(uint8_t event)
{
ScreenManager.keyHandler(event); // call into the Screen Manager
}
void setup() {
@ -202,6 +209,8 @@ void setup() {
DebugPort.begin(115200);
KeyPad.init(keyLeft_pin, keyRight_pin, keyCentre_pin, keyUp_pin, keyDown_pin);
KeyPad.setCallback(parentKeyHandler);
// initialise DS18B20 temperature sensor(s)
TempSensor.begin();
@ -210,7 +219,8 @@ void setup() {
lastTemperatureTime = millis();
lastAnimationTime = millis();
initOLED();
ScreenManager.init();
// initOLED();
#if USE_WIFI == 1
@ -417,7 +427,7 @@ void loop()
///////////////////////////////////////////////////////////////////////////////////////////
// do our state machine to track the reception and delivery of blue wire data
unsigned long tDelta;
long tDelta;
switch(CommState.get()) {
case CommStates::Idle:
@ -886,15 +896,17 @@ void checkDisplayUpdate()
// only update OLED when not processing blue wire
if(bUpdateDisplay) {
if(pTxFrame && pRxFrame) {
updateOLED(*pTxFrame, *pRxFrame);
ScreenManager.update(*pTxFrame, *pRxFrame);
// updateOLED(*pTxFrame, *pRxFrame);
bUpdateDisplay = false;
}
}
unsigned long tDelta = millis() - lastAnimationTime;
long tDelta = millis() - lastAnimationTime;
if(tDelta >= 100) {
lastAnimationTime += 100;
animateOLED();
ScreenManager.animate();
// animateOLED();
}
}
@ -910,3 +922,8 @@ float getPumpHz()
}
return 0.0;
}
float getActualTemperature()
{
return fFilteredTemperature;
}

View file

@ -10,17 +10,6 @@
#include "helpers.h"
#include "Protocol.h"
bool animatePump = false;
bool animateRPM = false;
bool animateGlow = false;
unsigned long showTarget = 0;
void showThermometer(C128x64_OLED& display, float desired, float actual);
void showBodyThermometer(C128x64_OLED& display, int actual);
void showGlowPlug(C128x64_OLED& display, int power);
void showFan(C128x64_OLED& display, int RPM);
void showFuel(C128x64_OLED& display, float rate);
void showRunState(C128x64_OLED& display, int state, int errstate);
#define MAXIFONT tahoma_16ptFontInfo
#define MINIFONT miniFontInfo
@ -46,268 +35,282 @@ void showRunState(C128x64_OLED& display, int state, int errstate);
#define MINI_FUELLABEL
#define MINI_BODYLABEL
void showScreen1(C128x64_OLED& display, const CProtocol& CtlFrame, const CProtocol& HtrFrame)
CScreen1::CScreen1(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display, mgr)
{
_animatePump = false;
_animateRPM = false;
_animateGlow = false;
_fanAnimationState = 0;
_dripAnimationState = 0;
_heatAnimationState = 0;
_keyRepeatCount = -1;
_showTarget = 0;
}
void
CScreen1::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
{
CScreen::show(CtlFrame, HtrFrame);
const char* c = String(getActualTemperature()).c_str();
int runstate = HtrFrame.getRunState();
int errstate = HtrFrame.getErrState();
if(errstate) errstate--; // correct for +1 biased return value
long tDelta = millis() - showTarget;
if(showTarget && (tDelta > 0)) {
showTarget = 0;
long tDelta = millis() - _showTarget;
if(_showTarget && (tDelta > 0)) {
_showTarget = 0;
}
float desiredT = 0;
if((runstate && (runstate <= 5)) || showTarget) {
if((runstate && (runstate <= 5)) || _showTarget) {
if(CtlFrame.isThermostat())
desiredT = CtlFrame.getTemperature_Desired();
else
desiredT = -HtrFrame.getPump_Fixed() * 0.1f;
}
showThermometer(display,
desiredT, // read values from most recently sent [BTC] frame
fFilteredTemperature);
showThermometer(desiredT, // read values from most recently sent [BTC] frame
getActualTemperature());
animateRPM = false;
animatePump = false;
animateGlow = false;
_animateRPM = false;
_animatePump = false;
_animateGlow = false;
if(runstate) {
float power = HtrFrame.getGlowPlug_Current() * 0.01 * HtrFrame.getGlowPlug_Voltage() * 0.1;
if(power > 1) {
showGlowPlug(display, int(power));
showGlowPlug(int(power));
}
showFan(display, HtrFrame.getFan_Actual());
showFan(HtrFrame.getFan_Actual());
showFuel(display, HtrFrame.getPump_Actual() * 0.1f);
showFuel(HtrFrame.getPump_Actual() * 0.1f);
showBodyThermometer(display, HtrFrame.getTemperature_HeatExchg());
showBodyThermometer(HtrFrame.getTemperature_HeatExchg());
}
/* else {
if(isWifiConnected()) {
display.setCursor(display.width(), 57); // xPos irrelevant here - setting Y
display.printRightJustified(getWifiAddrStr());
}
}*/
showRunState(display, runstate, errstate);
showRunState(runstate, errstate);
}
void animateScreen1(C128x64_OLED& display)
void
CScreen1::animate()
{
static int fan = 0;
static int drip = 0;
static int heat = 0;
if(animatePump || animateRPM || animateGlow) {
if(_animatePump || _animateRPM || _animateGlow) {
if(animatePump) {
if(_animatePump) {
// erase region of fuel icon
display.fillRect(X_FUEL_ICON, Y_FUEL_ICON, W_FUEL_ICON, H_FUEL_ICON + 4, BLACK);
display.drawBitmap(X_FUEL_ICON, Y_FUEL_ICON+(drip/2), FuelIcon, W_FUEL_ICON, H_FUEL_ICON, WHITE);
drip++;
drip &= 0x07;
_display.fillRect(X_FUEL_ICON, Y_FUEL_ICON, W_FUEL_ICON, H_FUEL_ICON + 4, BLACK);
_display.drawBitmap(X_FUEL_ICON, Y_FUEL_ICON+(_dripAnimationState/2), FuelIcon, W_FUEL_ICON, H_FUEL_ICON, WHITE);
_dripAnimationState++;
_dripAnimationState &= 0x07;
}
if(animateRPM) {
if(_animateRPM) {
// erase region of fuel icon
display.fillRect(X_FAN_ICON, Y_FAN_ICON, W_FAN_ICON, H_FAN_ICON, BLACK);
switch(fan) {
case 0: display.drawBitmap(X_FAN_ICON, Y_FAN_ICON, FanIcon1, W_FAN_ICON, H_FAN_ICON, WHITE); break;
case 1: display.drawBitmap(X_FAN_ICON, Y_FAN_ICON, FanIcon2, W_FAN_ICON, H_FAN_ICON, WHITE); break;
case 2: display.drawBitmap(X_FAN_ICON, Y_FAN_ICON, FanIcon3, W_FAN_ICON, H_FAN_ICON, WHITE); break;
case 3: display.drawBitmap(X_FAN_ICON, Y_FAN_ICON, FanIcon4, W_FAN_ICON, H_FAN_ICON, WHITE); break;
_display.fillRect(X_FAN_ICON, Y_FAN_ICON, W_FAN_ICON, H_FAN_ICON, BLACK);
switch(_fanAnimationState) {
case 0: _display.drawBitmap(X_FAN_ICON, Y_FAN_ICON, FanIcon1, W_FAN_ICON, H_FAN_ICON, WHITE); break;
case 1: _display.drawBitmap(X_FAN_ICON, Y_FAN_ICON, FanIcon2, W_FAN_ICON, H_FAN_ICON, WHITE); break;
case 2: _display.drawBitmap(X_FAN_ICON, Y_FAN_ICON, FanIcon3, W_FAN_ICON, H_FAN_ICON, WHITE); break;
case 3: _display.drawBitmap(X_FAN_ICON, Y_FAN_ICON, FanIcon4, W_FAN_ICON, H_FAN_ICON, WHITE); break;
}
fan++;
fan &= 0x03;
_fanAnimationState++;
_fanAnimationState &= 0x03;
}
if(animateGlow) {
display.fillRect(X_GLOW_ICON, Y_GLOW_ICON, 17, 10, BLACK);
display.drawBitmap(X_GLOW_ICON, Y_GLOW_ICON, GlowPlugIcon, 16, 9, WHITE);
display.drawBitmap(X_GLOW_ICON, Y_GLOW_ICON + 2 + heat, GlowHeatIcon, 17, 2, WHITE);
heat -= 2;
heat &= 0x07;
if(_animateGlow) {
_display.fillRect(X_GLOW_ICON, Y_GLOW_ICON, 17, 10, BLACK);
_display.drawBitmap(X_GLOW_ICON, Y_GLOW_ICON, GlowPlugIcon, 16, 9, WHITE);
_display.drawBitmap(X_GLOW_ICON, Y_GLOW_ICON + 2 + _heatAnimationState, GlowHeatIcon, 17, 2, WHITE);
_heatAnimationState -= 2;
_heatAnimationState &= 0x07;
}
}
display.display();
_display.display();
}
void keyhandlerScreen1(uint8_t event)
void
CScreen1::keyHandler(uint8_t event)
{
static int repeatCount = -1;
if(event & keyPressed) {
repeatCount = 0; // unlock tracking of repeat events
_keyRepeatCount = 0; // unlock tracking of repeat events
if(event & key_Left) {
prevScreen();
_Manager.prevScreen();
}
if(event & key_Right) {
nextScreen();
_Manager.nextScreen();
}
if(event & key_Up) {
reqTempChange(+1);
showTarget = millis() + 3500;
_showTarget = millis() + 3500;
}
if(event & key_Down) {
reqTempChange(-1);
showTarget = millis() + 3500;
_showTarget = millis() + 3500;
}
}
// require hold to turn ON or OFF
if(event & keyRepeat) {
if(repeatCount >= 0) {
repeatCount++;
if(_keyRepeatCount >= 0) {
_keyRepeatCount++;
if(event & key_Centre) {
if(getRunState()) {
if(repeatCount > 5) {
repeatCount = -1; // prevent double handling
if(_keyRepeatCount > 5) {
_keyRepeatCount = -1; // prevent double handling
requestOff();
}
}
else {
if(repeatCount > 3) {
repeatCount = -1;
if(_keyRepeatCount > 3) {
_keyRepeatCount = -1;
requestOn();
}
}
}
}
}
// release event
if(event & keyReleased) {
repeatCount = -1;
_keyRepeatCount = -1;
}
}
#define TEMP_YPOS(A) ((((20 - A) * 3) / 2) + 22)
void showThermometer(C128x64_OLED& display, float desired, float actual)
void
CScreen1::showThermometer(float desired, float actual)
{
char msg[16];
// draw bulb design
display.drawBitmap(X_BULB, Y_BULB, thermometerBitmap, W_BULB_ICON, H_BULB_ICON, WHITE);
_display.drawBitmap(X_BULB, Y_BULB, thermometerBitmap, W_BULB_ICON, H_BULB_ICON, WHITE);
// draw mercury
int yPos = Y_BULB + TEMP_YPOS(actual);
display.drawLine(X_BULB + 3, yPos, X_BULB + 3, Y_BULB + 42, WHITE);
display.drawLine(X_BULB + 4, yPos, X_BULB + 4, Y_BULB + 42, WHITE);
_display.drawLine(X_BULB + 3, yPos, X_BULB + 3, Y_BULB + 42, WHITE);
_display.drawLine(X_BULB + 4, yPos, X_BULB + 4, Y_BULB + 42, WHITE);
// print actual temperature
#ifdef MINI_TEMPLABEL
sprintf(msg, "%.1f`C", actual);
display.setFontInfo(&MINIFONT); // select Mini Font
_display.setFontInfo(&MINIFONT); // select Mini Font
#else
sprintf(msg, "%.1f", actual);
#endif
display.setCursor(0, Y_BASELINE);
display.print(msg);
display.setFontInfo(NULL);
_display.setCursor(0, Y_BASELINE);
_display.print(msg);
_display.setFontInfo(NULL);
// draw target setting
if(desired) {
display.drawBitmap(X_TARGET_ICON, Y_TARGET_ICON, TargetIcon, W_TARGET_ICON, H_TARGET_ICON, WHITE); // set indicator against bulb
_display.drawBitmap(X_TARGET_ICON, Y_TARGET_ICON, TargetIcon, W_TARGET_ICON, H_TARGET_ICON, WHITE); // set indicator against bulb
char msg[16];
if(desired > 0) {
int yPos = Y_BULB + TEMP_YPOS(desired) - 2;
display.drawBitmap(X_BULB-1, yPos, thermoPtr, 3, 5, WHITE); // set indicator against bulb
_display.drawBitmap(X_BULB-1, yPos, thermoPtr, 3, 5, WHITE); // set indicator against bulb
sprintf(msg, "%.0f`C", desired);
}
else {
sprintf(msg, "%.1fHz", -desired);
}
#ifdef MINI_TARGETLABEL
display.setFontInfo(&MINIFONT); // select Mini Font
_display.setFontInfo(&MINIFONT); // select Mini Font
#endif
display.setCursor(X_TARGET_ICON + (W_TARGET_ICON/2),
_display.setCursor(X_TARGET_ICON + (W_TARGET_ICON/2),
Y_BASELINE); // set centre position of text
display.printCentreJustified(msg);
display.setFontInfo(NULL);
_display.printCentreJustified(msg);
_display.setFontInfo(NULL);
}
}
#define BODY_YPOS(A) ((((100 - A) * 3) / 16) + 22) // 100degC centre - ticks +- 80C
void showBodyThermometer(C128x64_OLED& display, int actual)
void
CScreen1::showBodyThermometer(int actual)
{
// draw bulb design
display.drawBitmap(X_BODY_BULB, Y_BULB, thermometerBitmap, 8, 50, WHITE);
_display.drawBitmap(X_BODY_BULB, Y_BULB, thermometerBitmap, 8, 50, WHITE);
// draw mercury
int yPos = Y_BULB + BODY_YPOS(actual);
display.drawLine(X_BODY_BULB + 3, yPos, X_BODY_BULB + 3, Y_BULB + 42, WHITE);
display.drawLine(X_BODY_BULB + 4, yPos, X_BODY_BULB + 4, Y_BULB + 42, WHITE);
_display.drawLine(X_BODY_BULB + 3, yPos, X_BODY_BULB + 3, Y_BULB + 42, WHITE);
_display.drawLine(X_BODY_BULB + 4, yPos, X_BODY_BULB + 4, Y_BULB + 42, WHITE);
// print actual temperature
display.setTextColor(WHITE);
_display.setTextColor(WHITE);
char label[16];
// determine width and position right justified
#ifdef MINI_BODYLABEL
sprintf(label, "%d`C", actual);
display.setFontInfo(&MINIFONT); // select Mini Font
_display.setFontInfo(&MINIFONT); // select Mini Font
#else
sprintf(label, "%d", actual);
#endif
display.setCursor(display.width(), Y_BASELINE);
display.printRightJustified(label);
display.setFontInfo(NULL);
_display.setCursor(_display.width(), Y_BASELINE);
_display.printRightJustified(label);
_display.setFontInfo(NULL);
}
void showGlowPlug(C128x64_OLED& display, int power)
void
CScreen1::showGlowPlug(int power)
{
display.drawBitmap(X_GLOW_ICON, Y_GLOW_ICON, GlowPlugIcon, W_GLOW_ICON, H_GLOW_ICON, WHITE);
// animateGlow = true;
_display.drawBitmap(X_GLOW_ICON, Y_GLOW_ICON, GlowPlugIcon, W_GLOW_ICON, H_GLOW_ICON, WHITE);
// _animateGlow = true;
char msg[16];
sprintf(msg, "%dW", power);
#ifdef MINI_GLOWLABEL
display.setFontInfo(&MINIFONT); // select Mini Font
_display.setFontInfo(&MINIFONT); // select Mini Font
#endif
display.setCursor(X_GLOW_ICON + (W_GLOW_ICON/2),
_display.setCursor(X_GLOW_ICON + (W_GLOW_ICON/2),
Y_GLOW_ICON + H_GLOW_ICON + 3); // set centre position of text
display.printCentreJustified(msg);
display.setFontInfo(NULL);
_display.printCentreJustified(msg);
_display.setFontInfo(NULL);
}
void showFan(C128x64_OLED& display, int RPM)
void
CScreen1::showFan(int RPM)
{
// NOTE: fan rotation animation performed in animateOLED
animateRPM = RPM != 0; // used by animation routine
_animateRPM = RPM != 0; // used by animation routine
display.setTextColor(WHITE);
_display.setTextColor(WHITE);
char msg[16];
sprintf(msg, "%d", RPM);
#ifdef MINI_FANLABEL
display.setFontInfo(&MINIFONT); // select Mini Font
_display.setFontInfo(&MINIFONT); // select Mini Font
#endif
display.setCursor(X_FAN_ICON + (W_FAN_ICON/2),
_display.setCursor(X_FAN_ICON + (W_FAN_ICON/2),
Y_BASELINE);
display.printCentreJustified(msg);
display.setFontInfo(NULL);
_display.printCentreJustified(msg);
_display.setFontInfo(NULL);
}
void showFuel(C128x64_OLED& display, float rate)
void
CScreen1::showFuel(float rate)
{
// NOTE: fuel drop animation performed in animateOLED
animatePump = rate != 0; // used by animation routine
_animatePump = rate != 0; // used by animation routine
if(rate) {
char msg[16];
sprintf(msg, "%.1f", rate);
#ifdef MINI_FUELLABEL
display.setFontInfo(&MINIFONT); // select Mini Font
_display.setFontInfo(&MINIFONT); // select Mini Font
#endif
display.setCursor(X_FUEL_ICON + (W_FUEL_ICON/2),
_display.setCursor(X_FUEL_ICON + (W_FUEL_ICON/2),
Y_BASELINE);
display.printCentreJustified(msg);
display.setFontInfo(NULL); // select Mini Font
_display.printCentreJustified(msg);
_display.setFontInfo(NULL); // select Mini Font
}
}
void showRunState(C128x64_OLED& display, int runstate, int errstate)
void
CScreen1::showRunState(int runstate, int errstate)
{
static bool toggle = false;
const char* toPrint = NULL;
int yPos = 25;
display.setTextColor(WHITE, BLACK);
_display.setTextColor(WHITE, BLACK);
if(runstate >= 0 && runstate <= 8) {
if(((runstate == 0) || (runstate > 5)) && errstate) {
// create an "E-XX" message to display
@ -315,14 +318,14 @@ void showRunState(C128x64_OLED& display, int runstate, int errstate)
sprintf(msg, "E-%02d", errstate);
if(runstate > 5)
yPos -= 8;
display.setCursor(display.xCentre(), yPos);
_display.setCursor(_display.xCentre(), yPos);
yPos += 8;
// flash error code
toggle = !toggle;
if(toggle)
display.printCentreJustified(msg);
_display.printCentreJustified(msg);
else {
display.printCentreJustified(" ");
_display.printCentreJustified(" ");
}
// bounds limit error and gather message
if(errstate > 10) errstate = 11;
@ -333,9 +336,10 @@ void showRunState(C128x64_OLED& display, int runstate, int errstate)
}
}
if(toPrint) {
display.setCursor(display.xCentre(), yPos);
display.printCentreJustified(toPrint);
_display.setCursor(_display.xCentre(), yPos);
_display.printCentreJustified(toPrint);
}
}

View file

@ -2,8 +2,30 @@
class C128x64_OLED;
class CProtocol;
class CScreenManager;
void showScreen1(C128x64_OLED& display, const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void animateScreen1(C128x64_OLED& display);
class CScreen1 : public CScreen
{
bool _animatePump;
bool _animateRPM;
bool _animateGlow;
int _fanAnimationState;
int _dripAnimationState;
int _heatAnimationState;
int _keyRepeatCount;
void keyhandlerScreen1(uint8_t event);
unsigned long _showTarget;
void showRunState();
void showThermometer(float desired, float actual);
void showBodyThermometer(int actual);
void showGlowPlug(int power);
void showFan(int RPM);
void showFuel(float rate);
void showRunState(int state, int errstate);
public:
CScreen1(C128x64_OLED& display, CScreenManager& mgr);
void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void animate();
void keyHandler(uint8_t event);
};

View file

@ -15,26 +15,30 @@
#define MAXIFONT tahoma_16ptFontInfo
#define MINIFONT miniFontInfo
unsigned long showSetMode = 0;
unsigned long showMode = 0;
unsigned char nModeSel;
void showRunState(C128x64_OLED& display);
void showScreen2(C128x64_OLED& display, const CProtocol& CtlFrame, const CProtocol& HtrFrame)
CScreen2::CScreen2(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display, mgr)
{
_showSetMode = 0;
_showMode = 0;
_nModeSel = 0;
}
void
CScreen2::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
{
CScreen::show(CtlFrame, HtrFrame);
char msg[20];
CRect textRect;
sprintf(msg, "%.1f`", fFilteredTemperature);
display.setFontInfo(&MAXIFONT); // Dot Factory Font
display.getTextExtents(msg, textRect);
textRect.xPos = (display.width()- textRect.width) / 2;
sprintf(msg, "%.1f`", getActualTemperature());
_display.setFontInfo(&MAXIFONT); // Dot Factory Font
_display.getTextExtents(msg, textRect);
textRect.xPos = (_display.width()- textRect.width) / 2;
textRect.yPos = 25;
display.fillRect(textRect.xPos, textRect.yPos, textRect.width, textRect.height, BLACK);
display.setCursor(textRect.xPos, textRect.yPos);
display.print(msg);
display.setFontInfo(NULL); // standard 5x7 font
_display.fillRect(textRect.xPos, textRect.yPos, textRect.width, textRect.height, BLACK);
_display.setCursor(textRect.xPos, textRect.yPos);
_display.print(msg);
_display.setFontInfo(NULL); // standard 5x7 font
// at bottom of screen show either:
@ -42,46 +46,46 @@ void showScreen2(C128x64_OLED& display, const CProtocol& CtlFrame, const CProtoc
// Current heat demand setting
// Run state of heater
if(showMode) {
if(_showMode) {
const int border = 3;
const int radius = 4;
// Show selection between Fixed or Thermostat mode
long tDelta = millis() - showMode;
long tDelta = millis() - _showMode;
if(tDelta < 0) {
// display "Fixed Hz" at lower left, allowing space for a selection surrounding box
strcpy(msg, "Fixed Hz");
display.getTextExtents(msg, textRect); // size of text to print
textRect.xPos = display.width()- textRect.width - border; // set X position to finish short of RHS
textRect.yPos = display.height() - textRect.height - border; // bottom of screen, with room for box
display.setCursor(textRect.xPos, // centre text in potential box
_display.getTextExtents(msg, textRect); // size of text to print
textRect.xPos = _display.width()- textRect.width - border; // set X position to finish short of RHS
textRect.yPos = _display.height() - textRect.height - border; // bottom of screen, with room for box
_display.setCursor(textRect.xPos, // centre text in potential box
textRect.yPos);
display.print(msg); // show the text
if(nModeSel == 1) { // add selection box if current selection
_display.print(msg); // show the text
if(_nModeSel == 1) { // add selection box if current selection
textRect.Expand(border); // expand about text position
display.drawRoundRect(textRect.xPos, textRect.yPos, textRect.width, textRect.height, radius, WHITE);
_display.drawRoundRect(textRect.xPos, textRect.yPos, textRect.width, textRect.height, radius, WHITE);
}
// display "Thermostat" at lower right, allowing space for a selection surrounding box
strcpy(msg, "Thermostat");
display.getTextExtents(msg, textRect);
_display.getTextExtents(msg, textRect);
textRect.xPos = border;
textRect.yPos = display.height() - textRect.height - border; // bottom of screen, with room for box
display.setCursor(textRect.xPos, // centre text in potential box
textRect.yPos = _display.height() - textRect.height - border; // bottom of screen, with room for box
_display.setCursor(textRect.xPos, // centre text in potential box
textRect.yPos);
display.print(msg); // show the text
if(nModeSel == 0) { // add selection box if current selection
_display.print(msg); // show the text
if(_nModeSel == 0) { // add selection box if current selection
textRect.Expand(border); // expand about text position
display.drawRoundRect(textRect.xPos, textRect.yPos, textRect.width, textRect.height, radius, WHITE);
_display.drawRoundRect(textRect.xPos, textRect.yPos, textRect.width, textRect.height, radius, WHITE);
}
setThermostatMode(nModeSel == 0 ? 1 : 0); // set the new mode
setThermostatMode(_nModeSel == 0 ? 1 : 0); // set the new mode
}
else {
// cancel selection mode, apply whatever is boxed
showMode = 0;
showSetMode = millis() + 5000; // then make the new mode setting be shown
_showMode = 0;
_showSetMode = millis() + 5000; // then make the new mode setting be shown
}
}
if((showMode == 0) && showSetMode) {
long tDelta = millis() - showSetMode;
if((_showMode == 0) && _showSetMode) {
long tDelta = millis() - _showSetMode;
if(tDelta < 0) {
// Show current heat demand setting
if(getThermostatMode()) {
@ -91,47 +95,44 @@ void showScreen2(C128x64_OLED& display, const CProtocol& CtlFrame, const CProtoc
sprintf(msg, "Setpoint = %.1fHz", getFixedHz());
}
// centre message at bottom of screen
display.getTextExtents(msg, textRect);
display.setCursor(display.xCentre(),
display.height() - textRect.height);
display.printCentreJustified(msg);
_display.getTextExtents(msg, textRect);
_display.setCursor(_display.xCentre(),
_display.height() - textRect.height);
_display.printCentreJustified(msg);
}
else {
showSetMode = 0;
_showSetMode = 0;
}
}
if((showMode == 0) && (showSetMode == 0)) {
showRunState(display);
if((_showMode == 0) && (_showSetMode == 0)) {
showRunState();
}
}
void animateScreen2(C128x64_OLED& display)
{
display.display();
}
void keyhandlerScreen2(uint8_t event)
void
CScreen2::keyHandler(uint8_t event)
{
static int repeatCount = -1;
if(event & keyPressed) {
repeatCount = 0; // unlock tracking of repeat events
// press LEFT to select previous screen, or Fixed Hz mode when in mode select
if(event & key_Left) {
if(!showMode)
prevScreen();
if(!_showMode)
_Manager.prevScreen();
else {
showMode = millis() + 5000;
nModeSel = 0;
_showMode = millis() + 5000;
_nModeSel = 0;
reqDisplayUpdate();
}
}
// press RIGHT to selecxt next screen, or Thermostat mode when in mode select
if(event & key_Right) {
if(!showMode)
nextScreen();
if(!_showMode)
_Manager.nextScreen();
else {
showMode = millis() + 5000;
nModeSel = 1;
_showMode = millis() + 5000;
_nModeSel = 1;
reqDisplayUpdate();
}
}
@ -140,7 +141,7 @@ void keyhandlerScreen2(uint8_t event)
uint8_t doubleKey = key_Down | key_Up;
if((event & doubleKey) == doubleKey) {
reqThermoToggle();
showSetMode = millis() + 2000;
_showSetMode = millis() + 2000;
}
}
// use repeat function for key hold detection
@ -151,8 +152,8 @@ void keyhandlerScreen2(uint8_t event)
if(event & key_Down) {
if(repeatCount > 2) {
repeatCount = -1; // prevent double handling
showMode = millis() + 5000;
nModeSel = getThermostatMode() ? 0 : 1;
_showMode = millis() + 5000;
_nModeSel = getThermostatMode() ? 0 : 1;
}
}
// hold CENTRE to turn ON or OFF
@ -175,25 +176,25 @@ void keyhandlerScreen2(uint8_t event)
}
}
if(event & keyReleased) {
if(!showMode) {
if(!_showMode) {
// release DOWN key to reduce set demand, provided we are not in mode select
if(event & key_Down) {
reqTempChange(-1);
showSetMode = millis() + 2000;
_showSetMode = millis() + 2000;
}
// release UP key to increase set demand, provided we are not in mode select
if(event & key_Up) {
reqTempChange(+1);
showSetMode = millis() + 2000;
_showSetMode = millis() + 2000;
}
}
// release CENTRE to accept new mode, and/or show current setting
if(event & key_Centre) {
if(repeatCount != -2) { // prevent after off commands
if(showMode) {
showMode = millis(); // force immediate cancellation of showmode (via screen update)
if(_showMode) {
_showMode = millis(); // force immediate cancellation of showmode (via screen update)
}
showSetMode = millis() + 2000;
_showSetMode = millis() + 2000;
}
reqDisplayUpdate();
}
@ -202,7 +203,8 @@ void keyhandlerScreen2(uint8_t event)
}
}
void showRunState(C128x64_OLED& display)
void
CScreen2::showRunState()
{
int runstate = getRunState();
int errstate = getErrState();
@ -211,7 +213,7 @@ void showRunState(C128x64_OLED& display)
static bool toggle = false;
const char* toPrint = NULL;
display.setTextColor(WHITE, BLACK);
_display.setTextColor(WHITE, BLACK);
if(runstate >= 0 && runstate <= 8) {
if(((runstate == 0) || (runstate > 5)) && errstate) {
// create an "E-XX" message to display
@ -219,15 +221,15 @@ void showRunState(C128x64_OLED& display)
sprintf(msg, "E-%02d", errstate);
// determine height of font
CRect textRect;
display.getTextExtents(msg, textRect);
display.setCursor(display.xCentre(), // locate at bottom centre, 1 line up
display.height() - 2*textRect.height);
_display.getTextExtents(msg, textRect);
_display.setCursor(_display.xCentre(), // locate at bottom centre, 1 line up
_display.height() - 2*textRect.height);
// flash error code
toggle = !toggle;
if(toggle)
display.printCentreJustified(msg);
_display.printCentreJustified(msg);
else {
display.printCentreJustified(" ");
_display.printCentreJustified(" ");
}
// bounds limit error and gather message
if(errstate > 10) errstate = 11;
@ -245,9 +247,9 @@ void showRunState(C128x64_OLED& display)
if(toPrint) {
// determine height of font
CRect textRect;
display.getTextExtents(toPrint, textRect);
display.setCursor(display.xCentre(), // locate at bottom centre
display.height() - textRect.height);
display.printCentreJustified(toPrint);
_display.getTextExtents(toPrint, textRect);
_display.setCursor(_display.xCentre(), // locate at bottom centre
_display.height() - textRect.height);
_display.printCentreJustified(toPrint);
}
}
}

View file

@ -1,9 +1,18 @@
#include "stdint.h"
#include "display.h"
class C128x64_OLED;
class CProtocol;
class CScreenManager;
void showScreen2(C128x64_OLED& display, const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void animateScreen2(C128x64_OLED& display);
void keyhandlerScreen2(uint8_t event);
class CScreen2 : public CScreen
{
unsigned long _showSetMode;
unsigned long _showMode;
unsigned char _nModeSel;
void showRunState();
public:
CScreen2(C128x64_OLED& display, CScreenManager& mgr);
void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void keyHandler(uint8_t event);
};

View file

@ -4,8 +4,6 @@
#include "helpers.h"
#include "Screen3.h"
int rowSel = 0;
int colSel = 0;
const int border = 3;
const int radius = 4;
const int Row[] = { 52, 40, 28, 16 } ;
@ -17,107 +15,108 @@ const char* Label2[] = { "Prime pump",
"OFF",
"ON" };
void deltaCol(int dir);
void stopPump();
unsigned long PrimeStop = 0;
unsigned long PrimeCheck = 0;
void showScreen3(C128x64_OLED& display)
CScreen3::CScreen3(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display, mgr)
{
_PrimeStop = 0;
_PrimeCheck = 0;
_rowSel = 0;
_colSel = 0;
}
void
CScreen3::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
{
CScreen::show(CtlFrame, HtrFrame);
CRect extents;
display.setCursor(display.xCentre(), Row[0]);
display.printCentreJustified(Label0);
if(rowSel == 0) {
display.getTextExtents(Label0, extents);
_display.setCursor(_display.xCentre(), Row[0]);
_display.printCentreJustified(Label0);
if(_rowSel == 0) {
_display.getTextExtents(Label0, extents);
extents.xPos = Col[0];
extents.yPos = Row[0];
extents.Expand(border);
display.drawRoundRect(display.xCentre() - extents.width/2, extents.yPos, extents.width, extents.height, radius, WHITE);
_display.drawRoundRect(_display.xCentre() - extents.width/2, extents.yPos, extents.width, extents.height, radius, WHITE);
}
// thermostat / fixed mode selection menu
// highlight active state
int col = getThermostatMode() ? 0 : 1; // follow actual heater settings
display.getTextExtents(Label1[col], extents);
extents.xPos = (col == 0) ? border : display.width() - extents.width - border;
_display.getTextExtents(Label1[col], extents);
extents.xPos = (col == 0) ? border : _display.width() - extents.width - border;
extents.yPos = Row[1];
if(rowSel == 1) {
if(_rowSel == 1) {
// draw selection box
extents.Expand(border);
display.drawRoundRect(extents.xPos, extents.yPos, extents.width, extents.height, radius, WHITE);
_display.drawRoundRect(extents.xPos, extents.yPos, extents.width, extents.height, radius, WHITE);
}
else {
// draw white background
extents.Expand(1);
display.fillRect(extents.xPos, extents.yPos, extents.width, extents.height, WHITE);
_display.fillRect(extents.xPos, extents.yPos, extents.width, extents.height, WHITE);
}
if(col == 0 && rowSel != 1)
display.setTextColor(BLACK);
display.setCursor(border, Row[1]);
display.print(Label1[0]);
display.setTextColor(WHITE);
if(col == 0 && _rowSel != 1)
_display.setTextColor(BLACK);
_display.setCursor(border, Row[1]);
_display.print(Label1[0]);
_display.setTextColor(WHITE);
if(col == 1 && rowSel != 1)
display.setTextColor(BLACK);
display.setCursor(display.width() - border, Row[1]);
display.printRightJustified(Label1[1]);
display.setTextColor(WHITE);
if(col == 1 && _rowSel != 1)
_display.setTextColor(BLACK);
_display.setCursor(_display.width() - border, Row[1]);
_display.printRightJustified(Label1[1]);
_display.setTextColor(WHITE);
// fuel pump priming menu
display.setCursor(Col[0], Row[2]);
display.print(Label2[0]);
if(rowSel == 2) {
_display.setCursor(Col[0], Row[2]);
_display.print(Label2[0]);
if(_rowSel == 2) {
for(int col = 1; col < 3; col++) {
display.setCursor(Col[col], Row[2]);
display.print(Label2[col]);
_display.setCursor(Col[col], Row[2]);
_display.print(Label2[col]);
}
display.getTextExtents(Label2[colSel], extents);
extents.xPos = Col[colSel];
_display.getTextExtents(Label2[_colSel], extents);
extents.xPos = Col[_colSel];
extents.yPos = Row[2];
extents.Expand(border);
display.drawRoundRect(extents.xPos, extents.yPos, extents.width, extents.height, radius, WHITE);
_display.drawRoundRect(extents.xPos, extents.yPos, extents.width, extents.height, radius, WHITE);
}
if(rowSel == 2 && colSel == 2) {
if(_rowSel == 2 && _colSel == 2) {
float pumpHz = getPumpHz();
long tDelta = millis() - PrimeCheck;
if(PrimeCheck && tDelta > 0) {
if(pumpHz < 0.1) {
stopPump();
}
long tDelta = millis() - _PrimeCheck;
if(_PrimeCheck && tDelta > 0 && pumpHz < 0.1) {
stopPump();
}
tDelta = millis() - PrimeStop;
if(PrimeStop && tDelta > 0) {
tDelta = millis() - _PrimeStop;
if(_PrimeStop && tDelta > 0) {
stopPump();
}
if(PrimeStop) {
if(_PrimeStop) {
char msg[16];
sprintf(msg, "%.1fHz", pumpHz);
display.getTextExtents(msg, extents);
extents.xPos = display.width() - extents.width - border;
_display.getTextExtents(msg, extents);
extents.xPos = _display.width() - extents.width - border;
extents.yPos = Row[2];
extents.Expand(border);
display.fillRect(extents.xPos, extents.yPos, extents.width, extents.height, BLACK);
display.drawRoundRect(extents.xPos, extents.yPos, extents.width, extents.height, radius, WHITE);
_display.fillRect(extents.xPos, extents.yPos, extents.width, extents.height, BLACK);
_display.drawRoundRect(extents.xPos, extents.yPos, extents.width, extents.height, radius, WHITE);
extents.Expand(-border);
display.setCursor(extents.xPos, extents.yPos);
display.print(msg);
_display.setCursor(extents.xPos, extents.yPos);
_display.print(msg);
}
}
}
void animateScreen3(C128x64_OLED& display)
{
display.display();
}
void keyhandlerScreen3(uint8_t event)
void
CScreen3::keyHandler(uint8_t event)
{
if(event & keyPressed) {
// press CENTRE
@ -126,56 +125,56 @@ void keyhandlerScreen3(uint8_t event)
}
// press LEFT
if(event & key_Left) {
switch(rowSel) {
switch(_rowSel) {
case 0:
prevScreen();
_Manager.prevScreen();
break;
case 1:
colSel = 0;
_colSel = 0;
setThermostatMode(1);
break;
case 2:
colSel = 1;
_colSel = 1;
break;
case 3: break;
}
}
// press RIGHT
if(event & key_Right) {
switch(rowSel) {
switch(_rowSel) {
case 0:
nextScreen();
_Manager.nextScreen();
break;
case 1:
colSel = 1;
_colSel = 1;
setThermostatMode(0);
break;
case 2:
if(!getRunState())
colSel = 2;
_colSel = 2;
break;
case 3: break;
}
}
// press UP
if(event & key_Up) {
rowSel++;
UPPERLIMIT(rowSel, 2);
if(rowSel == 2)
colSel = 1; // select OFF upon entry to priming menu
_rowSel++;
UPPERLIMIT(_rowSel, 2);
if(_rowSel == 2)
_colSel = 1; // select OFF upon entry to priming menu
}
// press DOWN
if(event & key_Down) {
rowSel--;
LOWERLIMIT(rowSel, 0);
colSel = 0;
_rowSel--;
LOWERLIMIT(_rowSel, 0);
_colSel = 0;
}
// check if fuel priming was selected
if(rowSel == 2 && colSel == 2) {
if(_rowSel == 2 && _colSel == 2) {
reqPumpPrime(true);
PrimeStop = millis() + 150000; // allow 2.5 minutes - much the same as the heater itself cuts out at
PrimeCheck = millis() + 3000; // holdoff upon start before testing for heater shutting off pump
_PrimeStop = millis() + 150000; // allow 2.5 minutes - much the same as the heater itself cuts out at
_PrimeCheck = millis() + 3000; // holdoff upon start before testing for heater shutting off pump
}
else {
stopPump();
@ -185,11 +184,12 @@ void keyhandlerScreen3(uint8_t event)
}
}
void stopPump()
void
CScreen3::stopPump()
{
reqPumpPrime(false);
PrimeCheck = 0;
PrimeStop = 0;
if(colSel == 2)
colSel = 1;
_PrimeCheck = 0;
_PrimeStop = 0;
if(_colSel == 2)
_colSel = 1;
}

View file

@ -1,7 +1,17 @@
#include "stdint.h"
class C128x64_OLED;
class CScreenManager;
class CProtocol;
void showScreen3(C128x64_OLED& display);
void animateScreen3(C128x64_OLED& display);
void keyhandlerScreen3(uint8_t event);
class CScreen3 : public CScreen {
unsigned long _PrimeStop;
unsigned long _PrimeCheck;
int _rowSel;
int _colSel;
void stopPump();
public:
CScreen3(C128x64_OLED& display, CScreenManager& mgr);
void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void keyHandler(uint8_t event);
};

View file

@ -6,29 +6,33 @@
#include "BTCWifi.h"
void showScreen4(C128x64_OLED& display)
CScreen4::CScreen4(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display, mgr)
{
}
void
CScreen4::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
{
CScreen::show(CtlFrame, HtrFrame);
CRect extents;
display.setCursor(0, 24);
display.print("IP addr:");
display.setCursor(display.width(), 24);
_display.setCursor(0, 24);
_display.print("IP addr:");
_display.setCursor(_display.width(), 24);
if(isWifiConnected()) {
display.printRightJustified(getWifiAddrStr());
_display.printRightJustified(getWifiAddrStr());
}
else {
display.printRightJustified("Not active");
_display.printRightJustified("Not active");
}
}
void animateScreen4(C128x64_OLED& display)
{
display.display();
}
void keyhandlerScreen4(uint8_t event)
void
CScreen4::keyHandler(uint8_t event)
{
if(event & keyPressed) {
// press CENTRE
@ -37,11 +41,11 @@ void keyhandlerScreen4(uint8_t event)
}
// press LEFT
if(event & key_Left) {
prevScreen();
_Manager.prevScreen();
}
// press RIGHT
if(event & key_Right) {
nextScreen();
_Manager.nextScreen();
}
}
}

View file

@ -1,7 +1,12 @@
#include "stdint.h"
class C128x64_OLED;
class CScreenManager;
class CProtocol;
void showScreen4(C128x64_OLED& display);
void animateScreen4(C128x64_OLED& display);
void keyhandlerScreen4(uint8_t event);
class CScreen4 : public CScreen {
public:
CScreen4(C128x64_OLED& display, CScreenManager& mgr);
void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void keyHandler(uint8_t event);
};

View file

@ -29,14 +29,6 @@
#define MINI_BATTLABEL
void showBTicon(C128x64_OLED& display);
void showWifiIcon(C128x64_OLED& display);
void showBatteryIcon(C128x64_OLED& display, float voltage);
void switchScreen();
static int currentScreen = 0;
const int maxScreens = 4;
//
// **** NOTE: There are two very lame libaries conspiring to make life difficult ****
// A/ The ESP32 SPI.cpp library instatiates an instance of SPI, using the VSPI port (and pins)
@ -47,129 +39,181 @@ const int maxScreens = 4;
// You **MUST comment out the SPIClass SPI(VSPI);** at the end of the ESP32 SPI library
// then we declare "SPI" here, which will use HSPI!!!!
// 128 x 64 OLED support
SPIClass SPI; // default constructor opens HSPI on standard pins : MOSI=13,CLK=14,MISO=12(unused)
C128x64_OLED display(OLED_DC_pin, -1, OLED_CS_pin);
//C128x64_OLED display(OLED_DC_pin, -1, OLED_CS_pin);
void initOLED()
CScreenManager::CScreenManager()
{
currentScreen = 1;
SPI.setFrequency(8000000);
// SH1106_SWITCHCAPVCC = generate display voltage from 3.3V internally
display.begin(SH1106_SWITCHCAPVCC, 0, false);
// Show initial display buffer contents on the screen --
display.display();
switchScreen();
_pDisplay = NULL;
_pActiveScreen = NULL;
for(int i = 0; i < _maxScreens; i++)
_pScreen[i] = NULL;
_currentScreen = 1;
}
void animateOLED()
CScreenManager::~CScreenManager()
{
switch(currentScreen) {
case 0: animateScreen1(display); break;
case 1: animateScreen2(display); break;
case 2: animateScreen3(display); break;
case 3: animateScreen4(display); break;
_pActiveScreen = NULL;
for(int i=0; i<_maxScreens; i++) {
if(_pScreen[i]) {
delete _pScreen[i]; _pScreen[i] = NULL;
}
}
if(_pDisplay) {
delete _pDisplay; _pDisplay = NULL;
}
}
void updateOLED(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
void
CScreenManager::init()
{
display.clearDisplay();
SPI.setFrequency(8000000);
// 128 x 64 OLED support (Hardware SPI)
_pDisplay = new C128x64_OLED(OLED_DC_pin, -1, OLED_CS_pin);
// SH1106_SWITCHCAPVCC = generate display voltage from 3.3V internally
_pDisplay->begin(SH1106_SWITCHCAPVCC, 0, false);
// Show initial display buffer contents on the screen --
_pDisplay->display();
_pScreen[0] = new CScreen1(*_pDisplay, *this);
_pScreen[1] = new CScreen2(*_pDisplay, *this);
_pScreen[2] = new CScreen3(*_pDisplay, *this);
_pScreen[3] = new CScreen4(*_pDisplay, *this);
_switchScreen();
}
void
CScreenManager::update(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
{
if(_pActiveScreen) _pActiveScreen->show(CtlFrame, HtrFrame);
}
void
CScreenManager::animate()
{
if(_pActiveScreen) _pActiveScreen->animate();
}
void
CScreenManager::_switchScreen()
{
if(_currentScreen < _maxScreens)
_pActiveScreen = _pScreen[_currentScreen];
reqDisplayUpdate();
}
void
CScreenManager::nextScreen()
{
_currentScreen++;
if(_currentScreen >= _maxScreens) {
_currentScreen = 0;
}
_switchScreen();
}
void
CScreenManager::prevScreen()
{
_currentScreen--;
if(_currentScreen < 0) {
_currentScreen = _maxScreens-1;
}
_switchScreen();
}
void
CScreenManager::keyHandler(uint8_t event)
{
if(_pActiveScreen) _pActiveScreen->keyHandler(event);
}
CScreen::CScreen(C128x64_OLED& disp, CScreenManager& mgr) :
_display(disp),
_Manager(mgr)
{
}
CScreen::~CScreen()
{
}
void
CScreen::animate()
{
_display.display();
}
void
CScreen::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
{
_display.clearDisplay();
// standard header items
//Bluetooth
if(getBluetoothClient().isConnected())
showBTicon(display);
showBTicon();
// WiFi
if(isWifiConnected()) {
showWifiIcon(display);
#ifdef DEMO_AP_MODE
display.fillRect(X_WIFI_ICON + 8, Y_WIFI_ICON + 5, 10, 7, BLACK);
display.setFontInfo(&MINIFONT); // select Mini Font
display.setCursor(X_WIFI_ICON+9, Y_WIFI_ICON+6);
display.print("AP");
display.setFontInfo(NULL);
#endif
showWifiIcon();
}
// battery
float voltage = HtrFrame.getVoltage_Supply() * 0.1f;
showBatteryIcon(display, voltage);
showBatteryIcon(voltage);
showTime(display);
switch(currentScreen) {
case 0: showScreen1(display, CtlFrame, HtrFrame); break;
case 1: showScreen2(display, CtlFrame, HtrFrame); break;
case 2: showScreen3(display); break;
case 3: showScreen4(display); break;
}
showTime(_display);
}
void showBTicon(C128x64_OLED& display)
void
CScreen::showBTicon()
{
display.drawBitmap(X_BT_ICON, Y_BT_ICON, BTicon, W_BT_ICON, H_BT_ICON, WHITE);
_display.drawBitmap(X_BT_ICON, Y_BT_ICON, BTicon, W_BT_ICON, H_BT_ICON, WHITE);
}
void showWifiIcon(C128x64_OLED& display)
void
CScreen::showWifiIcon()
{
display.drawBitmap(X_WIFI_ICON, Y_WIFI_ICON, wifiIcon, W_WIFI_ICON, H_WIFI_ICON, WHITE);
_display.drawBitmap(X_WIFI_ICON, Y_WIFI_ICON, wifiIcon, W_WIFI_ICON, H_WIFI_ICON, WHITE);
#ifdef DEMO_AP_MODE
_display.fillRect(X_WIFI_ICON + 8, Y_WIFI_ICON + 5, 10, 7, BLACK);
_display.setFontInfo(&MINIFONT); // select Mini Font
_display.setCursor(X_WIFI_ICON+9, Y_WIFI_ICON+6);
_display.print("AP");
_display.setFontInfo(NULL);
#endif
}
void showBatteryIcon(C128x64_OLED& display, float voltage)
void
CScreen::showBatteryIcon(float voltage)
{
display.drawBitmap(X_BATT_ICON, Y_BATT_ICON, BatteryIcon, W_BATT_ICON, H_BATT_ICON, WHITE);
_display.drawBitmap(X_BATT_ICON, Y_BATT_ICON, BatteryIcon, W_BATT_ICON, H_BATT_ICON, WHITE);
#ifdef MINI_BATTLABEL
char msg[16];
sprintf(msg, "%.1fV", voltage);
int xPos = X_BATT_ICON + 7 - strlen(msg) * 2;
display.setCursor(xPos, Y_BATT_ICON+H_BATT_ICON+2);
display.setFontInfo(&MINIFONT); // select Mini Font
display.print(msg);
display.setFontInfo(NULL);
_display.setCursor(xPos, Y_BATT_ICON+H_BATT_ICON+2);
_display.setFontInfo(&MINIFONT); // select Mini Font
_display.print(msg);
_display.setFontInfo(NULL);
#else
display.setCursor(85, 12);
display.setTextColor(WHITE);
display.print(voltage, 1);
display.print("V");
_display.setCursor(85, 12);
_display.setTextColor(WHITE);
_display.print(voltage, 1);
_display.print("V");
#endif
// nominal 10.5 -> 13.5V bargraph
int Capacity = (voltage - 10.7) * 4;
if(Capacity < 0) Capacity = 0;
if(Capacity > 11) Capacity = 11;
display.fillRect(X_BATT_ICON+2 + Capacity, Y_BATT_ICON+2, W_BATT_ICON-4-Capacity, 6, BLACK);
}
void nextScreen()
{
currentScreen++;
if(currentScreen >= maxScreens) {
currentScreen = 0;
}
switchScreen();
}
void prevScreen()
{
currentScreen--;
if(currentScreen < 0) {
currentScreen = maxScreens-1;
}
switchScreen();
}
void switchScreen()
{
switch(currentScreen) {
case 0: KeyPad.setCallback(keyhandlerScreen1); break;
case 1: KeyPad.setCallback(keyhandlerScreen2); break;
case 2: KeyPad.setCallback(keyhandlerScreen3); break;
case 3: KeyPad.setCallback(keyhandlerScreen4); break;
}
reqDisplayUpdate();
_display.fillRect(X_BATT_ICON+2 + Capacity, Y_BATT_ICON+2, W_BATT_ICON-4-Capacity, 6, BLACK);
}

View file

@ -3,14 +3,42 @@
#include <Arduino.h>
class CProtocol;
class C128x64_OLED;
class CScreen;
void initOLED();
void updateOLED(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void animateOLED();
void nextScreen();
void prevScreen();
class CScreenManager {
static const int _maxScreens = 4;
CScreen* _pScreen[_maxScreens];
CScreen* _pActiveScreen;
C128x64_OLED* _pDisplay;
int _currentScreen;
void _switchScreen();
public:
CScreenManager();
~CScreenManager();
void init();
void update(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void animate();
void nextScreen();
void prevScreen();
void keyHandler(uint8_t event);
};
class CScreen {
protected:
C128x64_OLED& _display;
CScreenManager& _Manager;
void showBTicon();
void showWifiIcon();
void showBatteryIcon(float voltage);
public:
CScreen(C128x64_OLED& disp, CScreenManager& mgr);
virtual ~CScreen();
virtual void animate();
virtual void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
virtual void keyHandler(uint8_t event) {};
};
#endif // __DISPLAY_H__

View file

@ -12,8 +12,7 @@ extern bool getThermostatMode();
extern float getFixedHz();
extern float getPumpHz();
extern void reqPumpPrime(bool on);
extern float fFilteredTemperature;
extern float getActualTemperature();
#define LOWERLIMIT(A, B) if(A < B) A = B
#define UPPERLIMIT(A, B) if(A > B) A = B