Split CScreen base class out for fundamental screen functions

Added CScreenHeader for standard header items, then all other screens inherit from there.
Removed "get" helpers, now use getHeaterInfo() "CProtocolPackage"
This commit is contained in:
rljonesau 2018-12-01 11:36:25 +11:00
parent 891fa9f5c3
commit 27d7c70068
22 changed files with 504 additions and 363 deletions

View file

@ -19,6 +19,9 @@
*
*/
#ifndef __128x64OLED_H__
#define __128x64OLED_H__
#include "Adafruit_SH1106.h"
#include "FontTypes.h"
@ -45,3 +48,5 @@ public:
size_t write(uint8_t c);
};
#endif // __128x64OLED_H__

View file

@ -98,7 +98,8 @@
#include "UtilClasses.h"
#include "BTCota.h"
#include "BTCWebServer.h"
#include "display.h"
//#include "display.h"
#include "ScreenManager.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include "keypad.h"
@ -162,8 +163,9 @@ sRxLine PCline;
long lastRxTime; // used to observe inter character delays
bool hasOEMController = false;
const CProtocol* pRxFrame = NULL;
const CProtocol* pTxFrame = NULL;
//const CProtocol* pRxFrame = NULL;
//const CProtocol* pTxFrame = NULL;
CProtocolPackage HeaterData;
unsigned long moderator;
bool bUpdateDisplay = false;
@ -595,8 +597,9 @@ void loop()
}
else {
// CommState.set(CommStates::Idle); // "Listen Only" input is held low, don't send out Tx
pRxFrame = &HeaterFrame1;
pTxFrame = &OEMCtrlFrame;
HeaterData.set(HeaterFrame1, OEMCtrlFrame);
// pRxFrame = &HeaterFrame1;
// pTxFrame = &OEMCtrlFrame;
CommState.set(CommStates::TemperatureRead); // "Listen Only" input is held low, don't send out Tx
}
break;
@ -663,8 +666,9 @@ void loop()
Bluetooth.sendFrame("[HTR]", HeaterFrame2, true); // pin not grounded, suppress duplicate to BT
}
CommState.set(CommStates::TemperatureRead);
pRxFrame = &HeaterFrame2;
pTxFrame = &TxManage.getFrame();
HeaterData.set(HeaterFrame2, TxManage.getFrame());
// pRxFrame = &HeaterFrame2;
// pTxFrame = &TxManage.getFrame();
break;
case CommStates::TemperatureRead:
@ -682,7 +686,6 @@ void loop()
fFilteredTemperature = fFilteredTemperature * fAlpha + (1-fAlpha) * fTemperature;
DefaultBTCParams.setTemperature_Actual((unsigned char)(fFilteredTemperature + 0.5)); // update [BTC] frame to send
TempSensor.requestTemperatures(); // prep sensor for future reading
// reqDisplayUpdate();
ScreenManager.reqUpdate();
}
CommState.set(CommStates::Idle);
@ -816,7 +819,7 @@ bool validateFrame(const CProtocol& frame, const char* name)
}
int getRunState()
/*int getRunState()
{
if(pRxFrame)
return pRxFrame->getRunState();
@ -828,7 +831,7 @@ int getErrState()
if(pRxFrame)
return pRxFrame->getErrState();
return 8; // Comms error!
}
}*/
void requestOn()
{
@ -846,7 +849,7 @@ void requestOff()
void ToggleOnOff()
{
if(getRunState()) {
if(HeaterData.getRunState()) {
DebugPort.println("ToggleOnOff: Heater OFF");
requestOff();
}
@ -881,14 +884,14 @@ int getSetTemp()
return NVstore.getTemperature();
}
float getFixedHz()
/*float getFixedHz()
{
if(pRxFrame) {
return pRxFrame->getPump_Fixed();
}
return 0.0;
}
*/
void reqThermoToggle()
{
@ -909,9 +912,9 @@ bool getThermostatMode()
void checkDisplayUpdate()
{
// only update OLED when not processing blue wire
if(pTxFrame && pRxFrame) {
ScreenManager.checkUpdate(*pTxFrame, *pRxFrame);
}
// if(pTxFrame && pRxFrame) {
ScreenManager.checkUpdate();
// }
long tDelta = millis() - lastAnimationTime;
if(tDelta >= 100) {
@ -925,20 +928,20 @@ void reqPumpPrime(bool on)
DefaultBTCParams.setPump_Prime(on);
}
float getPumpHz()
/*float getPumpHz()
{
if(pRxFrame) {
return pRxFrame->getPump_Actual();
}
return 0.0;
}
*/
float getActualTemperature()
{
return fFilteredTemperature;
}
float getPumpMin()
/*float getPumpMin()
{
if(pTxFrame) {
return pTxFrame->getPump_Min();
@ -968,7 +971,7 @@ short getFanMax()
return pTxFrame->getFan_Max();
}
return 0.0;
}
}*/
void setPumpMin(float val)
{
@ -994,3 +997,8 @@ void saveNV()
{
NVstore.save();
}
const CProtocolPackage& getHeaterInfo()
{
return HeaterData;
}

View file

@ -231,14 +231,15 @@ CProtocol::setVoltage_Supply(short voltsx10)
Heater.SupplyV_LSB = (voltsx10 >> 0) & 0xff;
}
short
float
CProtocol::getVoltage_Supply() const
{
short retval = 0;
retval = Heater.SupplyV_MSB & 0xff;
retval <<= 8;
retval |= Heater.SupplyV_LSB & 0xff;
return retval;
short val = 0;
val = Heater.SupplyV_MSB & 0xff;
val <<= 8;
val |= Heater.SupplyV_LSB & 0xff;
float voltage = float(val) * 0.1f;
return voltage;
}
void
@ -303,3 +304,10 @@ CProtocol::DebugReport(const char* hdr, const char* ftr)
DebugPort.print(ftr); // footer
}
void
CProtocol::setThermostatMode(unsigned on)
{
Controller.OperatingMode = on ? 0x32 : 0xCD;
if(!on)
setTemperature_Actual(0); // if using fixed mode, actual must be reported as 0
};

View file

@ -147,7 +147,7 @@ public:
unsigned char getStoredErrCode() const { return Heater.StoredErrorCode; };
void setStoredErrCode(unsigned char state) { Heater.StoredErrorCode = state; };
//
short getVoltage_Supply() const;
float getVoltage_Supply() const;
void setVoltage_Supply(short voltsx10);
// fan set/get
@ -179,7 +179,7 @@ public:
unsigned char getTemperature_Min() const { return Controller.MinTemperature; };
unsigned char getTemperature_Max() const { return Controller.MaxTemperature; };
unsigned char getTemperature_Actual() const { return Controller.ActualTemperature; };
void setThermostatMode(unsigned on) { Controller.OperatingMode = on ? 0x32 : 0xCD; };
void setThermostatMode(unsigned on);
bool isThermostat() const { return Controller.OperatingMode == 0x32; };
// glow plug
float getGlowPlug_Current() const; // glow plug current
@ -203,5 +203,25 @@ public:
long elapsedTime() { return millis() - lastTime; };
};
class CProtocolPackage {
CProtocol Heater;
CProtocol Controller;
public:
void set(const CProtocol& htr, const CProtocol& ctl) { Heater = htr; Controller = ctl; };
int getRunState() const { return Heater.getRunState(); };
int getErrState() const { return Heater.getErrState(); };
float getBattVoltage() const { return Heater.getVoltage_Supply(); };
bool isThermostat() const { return Controller.isThermostat(); };
float getTemperature_Desired() const { return Controller.getTemperature_Desired(); };
float getTemperature_HeatExchg() const { return Heater.getTemperature_HeatExchg(); };
float getPump_Fixed() const { return Heater.getPump_Fixed(); };
float getPump_Actual() const { return Heater.getPump_Actual(); };
float getPump_Min() const { return Controller.getPump_Min(); };
float getPump_Max() const { return Controller.getPump_Max(); };
float getFan_Actual() const { return Heater.getFan_Actual(); };
short getFan_Min() const { return Controller.getFan_Min(); };
short getFan_Max() const { return Controller.getFan_Max(); };
float getGlowPlug_Power() const { return Heater.getGlowPlug_Current() * Heater.getGlowPlug_Voltage(); };
};
#endif

View file

@ -0,0 +1,101 @@
#include <Arduino.h>
#include "Screen.h"
#include "128x64OLED.h"
#include "ScreenManager.h"
// base class functionality for screens
CScreen::CScreen(C128x64_OLED& disp, CScreenManager& mgr) :
_display(disp),
_ScreenManager(mgr)
{
}
CScreen::~CScreen()
{
}
void
CScreen::animate()
{
}
void
CScreen::show()
{
}
void
CScreen::_drawMenuText(int x, int y, const char* str, bool selected, eJUSTIFY justify, int border, int radius)
{
// position output, according to justification
CRect extents;
extents.xPos = x;
extents.yPos = y;
_display.getTextExtents(str, extents);
_adjustExtents(extents, justify, str);
_display.setCursor(extents.xPos, extents.yPos);
_display.print(str);
if(selected) {
extents.Expand(border);
_display.drawRoundRect(extents.xPos, extents.yPos, extents.width, extents.height, radius, WHITE);
}
}
void
CScreen::_printInverted(int x, int y, const char* str, bool selected, eJUSTIFY justify)
{
// position output, according to justification
CRect extents;
extents.xPos = x;
extents.yPos = y;
_adjustExtents(extents, justify, str);
if(selected) {
_display.setTextColor(BLACK, WHITE);
extents.Expand(1);
_display.fillRect(extents.xPos, extents.yPos, extents.width, extents.height, WHITE);
extents.Expand(-1);
}
_display.setCursor(extents.xPos, extents.yPos);
_display.print(str);
_display.setTextColor(WHITE, BLACK);
}
void
CScreen::_adjustExtents(CRect& extents, eJUSTIFY justify, const char* str)
{
_display.getTextExtents(str, extents);
switch(justify) {
case eCentreJustify:
extents.xPos -= extents.width/2;
break;
case eRightJustify:
extents.xPos -= extents.width;
break;
}
}
// a class used for temporary alternate fonts usage
// Reverts to standard inbuilt font when the instance falls out of scope
CTransientFont::CTransientFont(C128x64_OLED& disp, const FONT_INFO* pFont) :
_display(disp)
{
_display.setFontInfo(pFont);
_display.setTextColor(WHITE, BLACK);
}
CTransientFont::~CTransientFont()
{
_display.setFontInfo(NULL);
}

View file

@ -19,50 +19,28 @@
*
*/
#ifndef __DISPLAY_H__
#define __DISPLAY_H__
#ifndef __SCREEN_H__
#define __SCREEN_H__
#include <Arduino.h>
#include "FontTypes.h"
#include "UtilClasses.h"
#include "ScreenManager.h"
#include "128x64OLED.h"
class CProtocol;
class C128x64_OLED;
class CScreen;
struct CRect;
enum eJUSTIFY {
eLeftJustify, eCentreJustify, eRightJustify
};
class CScreenManager {
static const int _maxScreens = 5;
CScreen* _pScreen[_maxScreens];
CScreen* _pActiveScreen;
C128x64_OLED* _pDisplay;
int _currentScreen;
bool _bReqUpdate;
void _switchScreen();
public:
CScreenManager();
~CScreenManager();
void init();
void checkUpdate(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void animate();
void nextScreen();
void prevScreen();
void keyHandler(uint8_t event);
void reqUpdate();
};
const int border = 3;
const int radius = 4;
class CScreen {
protected:
C128x64_OLED& _display;
CScreenManager& _ScreenManager;
void showBTicon();
void showWifiIcon();
void showBatteryIcon(float voltage);
void _drawMenuText(int x, int y, const char* str, bool selected = false, eJUSTIFY justify = eLeftJustify, int border = 3, int radius = 4);
void _printInverted(int x, int y, const char* str, bool selected, eJUSTIFY justify = eLeftJustify);
void _adjustExtents(CRect& rect, eJUSTIFY justify, const char* str);
@ -70,15 +48,16 @@ public:
CScreen(C128x64_OLED& disp, CScreenManager& mgr);
virtual ~CScreen();
virtual void animate();
virtual void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
virtual void show();
virtual void keyHandler(uint8_t event) {};
};
class CAutoFont {
class CTransientFont {
C128x64_OLED& _display;
public:
CAutoFont(C128x64_OLED& disp, const FONT_INFO* pFont);
~CAutoFont();
CTransientFont(C128x64_OLED& disp, const FONT_INFO* pFont);
~CTransientFont();
};
#endif // __DISPLAY_H__
#endif // __SCREEN_H__

View file

@ -21,8 +21,6 @@
#include "128x64OLED.h"
#include "MiniFont.h"
#include "display.h"
#include "tahoma16.h"
#include "OLEDconsts.h"
#include "BluetoothAbstract.h"
#include "Screen1.h"
@ -32,7 +30,6 @@
#include "Protocol.h"
#define MAXIFONT tahoma_16ptFontInfo
#define MINIFONT miniFontInfo
#define X_FAN_ICON 55
@ -48,7 +45,6 @@
#define X_BULB 1 // >= 1
#define Y_BULB 4
#define MINI_BATTLABEL
#define MINI_TEMPLABEL
#define MINI_TARGETLABEL
#define MINI_FANLABEL
@ -56,7 +52,15 @@
#define MINI_FUELLABEL
#define MINI_BODYLABEL
CScreen1::CScreen1(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display, mgr)
///////////////////////////////////////////////////////////////////////////
//
// CScreen1
//
// This screen provides a detailed control/status function
//
///////////////////////////////////////////////////////////////////////////
CScreen1::CScreen1(C128x64_OLED& display, CScreenManager& mgr) : CScreenHeader(display, mgr)
{
_animatePump = false;
_animateRPM = false;
@ -70,14 +74,14 @@ CScreen1::CScreen1(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display
void
CScreen1::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
CScreen1::show()
{
CScreen::show(CtlFrame, HtrFrame);
CScreenHeader::show();
const char* c = String(getActualTemperature()).c_str();
int runstate = HtrFrame.getRunState();
int errstate = HtrFrame.getErrState();
int runstate = getHeaterInfo().getRunState();//HtrFrame.getRunState();
int errstate = getHeaterInfo().getErrState(); //HtrFrame.getErrState();
if(errstate) errstate--; // correct for +1 biased return value
long tDelta = millis() - _showTarget;
@ -87,10 +91,14 @@ CScreen1::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
float desiredT = 0;
if((runstate && (runstate <= 5)) || _showTarget) {
if(CtlFrame.isThermostat())
desiredT = CtlFrame.getTemperature_Desired();
// if(CtlFrame.isThermostat())
// desiredT = CtlFrame.getTemperature_Desired();
// else
// desiredT = -HtrFrame.getPump_Fixed();
if(getHeaterInfo().isThermostat())
desiredT = getHeaterInfo().getTemperature_Desired();
else
desiredT = -HtrFrame.getPump_Fixed();
desiredT = -getHeaterInfo().getPump_Fixed();
}
showThermometer(desiredT, // read values from most recently sent [BTC] frame
@ -101,16 +109,20 @@ CScreen1::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
_animateGlow = false;
if(runstate) {
float power = HtrFrame.getGlowPlug_Current() * HtrFrame.getGlowPlug_Voltage();
// float power = HtrFrame.getGlowPlug_Current() * HtrFrame.getGlowPlug_Voltage();
float power = getHeaterInfo().getGlowPlug_Power();
if(power > 1) {
showGlowPlug(power);
}
showFan(HtrFrame.getFan_Actual());
// showFan(HtrFrame.getFan_Actual());
showFan(getHeaterInfo().getFan_Actual());
showFuel(HtrFrame.getPump_Actual());
// showFuel(HtrFrame.getPump_Actual());
showFuel(getHeaterInfo().getPump_Actual());
showBodyThermometer(HtrFrame.getTemperature_HeatExchg());
// showBodyThermometer(HtrFrame.getTemperature_HeatExchg());
showBodyThermometer(getHeaterInfo().getTemperature_HeatExchg());
}
showRunState(runstate, errstate);
@ -159,6 +171,7 @@ CScreen1::animate()
void
CScreen1::keyHandler(uint8_t event)
{
if(event & keyPressed) {
_keyRepeatCount = 0; // unlock tracking of repeat events
if(event & key_Left) {
@ -181,7 +194,7 @@ CScreen1::keyHandler(uint8_t event)
if(_keyRepeatCount >= 0) {
_keyRepeatCount++;
if(event & key_Centre) {
if(getRunState()) {
if(getHeaterInfo().getRunState()) {
if(_keyRepeatCount > 5) {
_keyRepeatCount = -1; // prevent double handling
requestOff();
@ -217,7 +230,7 @@ CScreen1::showThermometer(float desired, float actual)
// print actual temperature
{
#ifdef MINI_TEMPLABEL
CAutoFont AF(_display, &MINIFONT); // temporarily use a mini font
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
sprintf(msg, "%.1f`C", actual);
#else
sprintf(msg, "%.1f", actual);
@ -238,7 +251,7 @@ CScreen1::showThermometer(float desired, float actual)
sprintf(msg, "%.1fHz", -desired);
}
#ifdef MINI_TARGETLABEL
CAutoFont AF(_display, &MINIFONT); // temporarily use a mini font
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
#endif
_drawMenuText(X_TARGET_ICON + (W_TARGET_ICON/2), Y_BASELINE, msg, false, eCentreJustify);
}
@ -259,7 +272,7 @@ CScreen1::showBodyThermometer(int actual)
char label[16];
// determine width and position right justified
#ifdef MINI_BODYLABEL
CAutoFont AF(_display, &MINIFONT); // temporarily use a mini font
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
sprintf(label, "%d`C", actual);
#else
sprintf(label, "%d", actual);
@ -276,7 +289,7 @@ CScreen1::showGlowPlug(float power)
char msg[16];
sprintf(msg, "%.0fW", power);
#ifdef MINI_GLOWLABEL
CAutoFont AF(_display, &MINIFONT); // temporarily use a mini font
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
#endif
_drawMenuText(X_GLOW_ICON + (W_GLOW_ICON/2),
Y_GLOW_ICON + H_GLOW_ICON + 3,
@ -293,7 +306,7 @@ CScreen1::showFan(int RPM)
char msg[16];
sprintf(msg, "%d", RPM);
#ifdef MINI_FANLABEL
CAutoFont AF(_display, &MINIFONT); // temporarily use a mini font
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
#endif
_drawMenuText(X_FAN_ICON + (W_FAN_ICON/2), Y_BASELINE, msg, false, eCentreJustify);
}
@ -307,7 +320,7 @@ CScreen1::showFuel(float rate)
char msg[16];
sprintf(msg, "%.1f", rate);
#ifdef MINI_FUELLABEL
CAutoFont AF(_display, &MINIFONT); // temporarily use a mini font
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
#endif
_drawMenuText(X_FUEL_ICON + (W_FUEL_ICON/2), Y_BASELINE, msg, false, eCentreJustify);
}

View file

@ -20,12 +20,12 @@
*/
#include "stdint.h"
#include "ScreenHeader.h"
class C128x64_OLED;
class CProtocol;
class CScreenManager;
class CScreen1 : public CScreen
class CScreen1 : public CScreenHeader
{
bool _animatePump;
bool _animateRPM;
@ -46,7 +46,7 @@ class CScreen1 : public CScreen
void showRunState(int state, int errstate);
public:
CScreen1(C128x64_OLED& display, CScreenManager& mgr);
void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void show();
void animate();
void keyHandler(uint8_t event);
};

View file

@ -20,23 +20,25 @@
*/
#include "128x64OLED.h"
#include "display.h"
#include "MiniFont.h"
#include "tahoma16.h"
#include "OLEDconsts.h"
#include "BluetoothAbstract.h"
#include "Screen2.h"
#include "BTCWifi.h"
#include "KeyPad.h"
#include "helpers.h"
#include "Protocol.h"
#include "UtilClasses.h"
#define MAXIFONT tahoma_16ptFontInfo
#define MINIFONT miniFontInfo
CScreen2::CScreen2(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display, mgr)
///////////////////////////////////////////////////////////////////////////
//
// CScreen2
//
// This screen provides a basic control function
//
///////////////////////////////////////////////////////////////////////////
CScreen2::CScreen2(C128x64_OLED& display, CScreenManager& mgr) : CScreenHeader(display, mgr)
{
_showSetMode = 0;
_showMode = 0;
@ -44,16 +46,16 @@ CScreen2::CScreen2(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display
}
void
CScreen2::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
CScreen2::show()
{
CScreen::show(CtlFrame, HtrFrame);
CScreenHeader::show();
char msg[20];
int xPos, yPos;
sprintf(msg, "%.1f`", getActualTemperature());
{
CAutoFont AF(_display, &MAXIFONT); // temporarily use a large font
CTransientFont AF(_display, &MAXIFONT); // temporarily use a large font
_drawMenuText(_display.xCentre(), 25, msg, false, eCentreJustify);
}
@ -94,11 +96,11 @@ CScreen2::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
long tDelta = millis() - _showSetMode;
if(tDelta < 0) {
// Show current heat demand setting
if(getThermostatMode()) {
sprintf(msg, "Setpoint = %d`C", getSetTemp());
if(getHeaterInfo().isThermostat()) {
sprintf(msg, "Setpoint = %d`C", getHeaterInfo().getTemperature_Desired());
}
else {
sprintf(msg, "Setpoint = %.1fHz", getFixedHz());
sprintf(msg, "Setpoint = %.1fHz", getHeaterInfo().getPump_Fixed());
}
// centre message at bottom of screen
_drawMenuText(_display.xCentre(), _display.height() - 8, msg, false, eCentreJustify);
@ -126,6 +128,7 @@ 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
@ -165,12 +168,12 @@ CScreen2::keyHandler(uint8_t event)
if(repeatCount > 2) {
repeatCount = -1; // prevent double handling
_showMode = millis() + 5000;
_nModeSel = getThermostatMode() ? 0 : 1;
_nModeSel = getHeaterInfo().isThermostat() ? 0 : 1;
}
}
// hold CENTRE to turn ON or OFF
if(event & key_Centre) {
if(getRunState()) {
if(getHeaterInfo().getRunState()) {
// running, request OFF
if(repeatCount > 5) {
repeatCount = -2; // prevent double handling
@ -218,8 +221,8 @@ CScreen2::keyHandler(uint8_t event)
void
CScreen2::showRunState()
{
int runstate = getRunState();
int errstate = getErrState();
int runstate = getHeaterInfo().getRunState();
int errstate = getHeaterInfo().getErrState();
if(errstate) errstate--; // correct for +1 biased return value

View file

@ -20,13 +20,13 @@
*/
#include "stdint.h"
#include "display.h"
#include "ScreenHeader.h"
class C128x64_OLED;
class CProtocol;
class CScreenManager;
class CProtocolPackage;
class CScreen2 : public CScreen
class CScreen2 : public CScreenHeader
{
unsigned long _showSetMode;
unsigned long _showMode;
@ -34,7 +34,7 @@ class CScreen2 : public CScreen
void showRunState();
public:
CScreen2(C128x64_OLED& display, CScreenManager& mgr);
void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void show();
void animate();
void keyHandler(uint8_t event);
};

View file

@ -20,24 +20,21 @@
*/
#include "128x64OLED.h"
#include "display.h"
#include "KeyPad.h"
#include "helpers.h"
#include "Screen3.h"
const int border = 3;
const int radius = 4;
const int Row[] = { 52, 40, 28, 16 } ;
const int Col[] = { border, 70, 100};
const char* Label0 = "<- ->";
const char* Label1[] = { "Thermostat",
"Fixed Hz" };
const char* Label2[] = { "Prime pump",
"OFF",
"ON" };
///////////////////////////////////////////////////////////////////////////
//
// CScreen3
//
// This screen allows the temeprature control mode to be selected and
// allows pump priming
//
///////////////////////////////////////////////////////////////////////////
CScreen3::CScreen3(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display, mgr)
CScreen3::CScreen3(C128x64_OLED& display, CScreenManager& mgr) : CScreenHeader(display, mgr)
{
_PrimeStop = 0;
_PrimeCheck = 0;
@ -47,36 +44,39 @@ CScreen3::CScreen3(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display
void
CScreen3::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
CScreen3::show()
{
CScreen::show(CtlFrame, HtrFrame);
CScreenHeader::show();
CRect extents;
int yPos = 52;
// show next/prev screen navigation line
_drawMenuText(_display.xCentre(), Row[0], Label0, _rowSel == 0, eCentreJustify);
_drawMenuText(_display.xCentre(), yPos, "<- ->", _rowSel == 0, eCentreJustify);
int col = getThermostatMode() ? 0 : 1; // follow actual heater settings
yPos = 40;
int col = getHeaterInfo().isThermostat() ? 0 : 1; // follow actual heater settings
if(_rowSel == 1) {
_drawMenuText(border, Row[1], Label1[0], col == 0);
_drawMenuText(_display.width()-border, Row[1], Label1[1], col == 1, eRightJustify);
_drawMenuText(border, yPos, "Thermostat", col == 0);
_drawMenuText(_display.width()-border, yPos, "Fixed Hz", col == 1, eRightJustify);
}
else {
_printInverted(border, Row[1], Label1[0], col == 0);
_printInverted(_display.width()-border, Row[1], Label1[1], col == 1, eRightJustify);
_printInverted(border, yPos, "Thermostat", col == 0);
_printInverted(_display.width()-border, yPos, "Fixed Hz", col == 1, eRightJustify);
}
// fuel pump priming menu
_drawMenuText(Col[0], Row[2], "Prime pump");
yPos = 28;
_drawMenuText(border, yPos, "Prime pump");
if(_rowSel == 2) {
_drawMenuText(Col[1], Row[2], "OFF", _colSel == 1);
_drawMenuText(70, yPos, "OFF", _colSel == 1);
if(_colSel != 2) {
if(!getRunState()) { // prevent option if heater is running
_drawMenuText(Col[2], Row[2], "ON"); // becomes Hz when actually priming
if(!getHeaterInfo().getRunState()) { // prevent option if heater is running
_drawMenuText(100, yPos, "ON"); // becomes Hz when actually priming
}
}
else {
float pumpHz = getPumpHz();
float pumpHz = getHeaterInfo().getPump_Actual();
// recognise if heater has stopped pump, after an initial holdoff upon first starting
long tDelta = millis() - _PrimeCheck;
if(_PrimeCheck && tDelta > 0 && pumpHz < 0.1) {
@ -91,7 +91,7 @@ CScreen3::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
if(_PrimeStop) {
char msg[16];
sprintf(msg, "%.1fHz", pumpHz);
_drawMenuText(_display.width()-border, Row[2], msg, true, eRightJustify);
_drawMenuText(_display.width()-border, yPos, msg, true, eRightJustify);
}
}
}
@ -111,6 +111,7 @@ CScreen3::animate()
void
CScreen3::keyHandler(uint8_t event)
{
if(event & keyPressed) {
// press CENTRE
if(event & key_Centre) {
@ -143,7 +144,7 @@ CScreen3::keyHandler(uint8_t event)
setThermostatMode(0);
break;
case 2:
if(!getRunState())
if(!getHeaterInfo().getRunState())
_colSel = 2;
break;
case 3: break;

View file

@ -20,12 +20,12 @@
*/
#include "stdint.h"
#include "ScreenHeader.h"
class C128x64_OLED;
class CScreenManager;
class CProtocol;
class CScreen3 : public CScreen {
class CScreen3 : public CScreenHeader {
unsigned long _PrimeStop;
unsigned long _PrimeCheck;
int _rowSel;
@ -33,7 +33,7 @@ class CScreen3 : public CScreen {
void stopPump();
public:
CScreen3(C128x64_OLED& display, CScreenManager& mgr);
void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void show();
void animate();
void keyHandler(uint8_t event);
};

View file

@ -20,22 +20,30 @@
*/
#include "128x64OLED.h"
#include "display.h"
#include "KeyPad.h"
#include "helpers.h"
#include "Screen4.h"
#include "BTCWifi.h"
///////////////////////////////////////////////////////////////////////////
//
// CScreen4
//
// This screen presents sundry information
// eg WiFi status
//
///////////////////////////////////////////////////////////////////////////
CScreen4::CScreen4(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display, mgr)
CScreen4::CScreen4(C128x64_OLED& display, CScreenManager& mgr) : CScreenHeader(display, mgr)
{
}
void
CScreen4::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
CScreen4::show()
{
CScreen::show(CtlFrame, HtrFrame);
CScreenHeader::show();
CRect extents;

View file

@ -20,15 +20,15 @@
*/
#include "stdint.h"
#include "ScreenHeader.h"
class C128x64_OLED;
class CScreenManager;
class CProtocol;
class CScreen4 : public CScreen {
class CScreen4 : public CScreenHeader {
public:
CScreen4(C128x64_OLED& display, CScreenManager& mgr);
void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void show();
void animate();
void keyHandler(uint8_t event);
};

View file

@ -19,18 +19,23 @@
*
*/
///////////////////////////////////////////////////////////////////////////
//
// CScreen5
//
// This screen allows the fuel mixture endpoints to be adjusted
//
///////////////////////////////////////////////////////////////////////////
#include "128x64OLED.h"
#include "display.h"
#include "KeyPad.h"
#include "helpers.h"
#include "Screen5.h"
#include "BTCWifi.h"
const int border = 4;
const int radius = 4;
const char* baseLabel = "<- ->";
CScreen5::CScreen5(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display, mgr)
CScreen5::CScreen5(C128x64_OLED& display, CScreenManager& mgr) : CScreenHeader(display, mgr)
{
_rowSel = 0;
_colSel = 0;
@ -40,9 +45,9 @@ CScreen5::CScreen5(C128x64_OLED& display, CScreenManager& mgr) : CScreen(display
void
CScreen5::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
CScreen5::show()
{
CScreen::show(CtlFrame, HtrFrame);
CScreenHeader::show();
CRect extents;
char str[16];
@ -60,22 +65,22 @@ CScreen5::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
yPos = 28;
_display.setCursor(0, yPos);
_display.print("Pump (Hz)");
sprintf(str, "%.1f", getPumpMin());
sprintf(str, "%.1f", getHeaterInfo().getPump_Min());
_drawMenuText(col2, yPos, str, false, eRightJustify);
sprintf(str, "%.1f", getPumpMax());
sprintf(str, "%.1f", getHeaterInfo().getPump_Max());
_drawMenuText(col3, yPos, str, false, eRightJustify);
// fan max/min
yPos = 40;
_display.setCursor(0, yPos);
_display.print("Fan (RPM)");
sprintf(str, "%d", getFanMin());
sprintf(str, "%d", getHeaterInfo().getFan_Min());
_drawMenuText(col2, yPos, str, false, eRightJustify);
sprintf(str, "%d", getFanMax());
sprintf(str, "%d", getHeaterInfo().getFan_Max());
_drawMenuText(col3, yPos, str, false, eRightJustify);
// navigation line
yPos = 53;
xPos = _display.xCentre();
_drawMenuText(xPos, yPos, baseLabel, true, eCentreJustify);
_drawMenuText(xPos, yPos, "<- ->", true, eCentreJustify);
break;
case 1:
@ -114,7 +119,7 @@ CScreen5::show(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
_drawMenuText(col3, yPos, str, _rowSel == 5, eRightJustify);
// navigation line
yPos = 53;
_drawMenuText(_display.xCentre(), yPos, baseLabel, false, eCentreJustify);
_drawMenuText(_display.xCentre(), yPos, "<- ->", false, eCentreJustify);
break;
case 6:
@ -137,6 +142,7 @@ CScreen5::animate()
void
CScreen5::keyHandler(uint8_t event)
{
if(event & keyPressed) {
// press CENTRE
if(event & key_Centre) {
@ -150,10 +156,10 @@ CScreen5::keyHandler(uint8_t event)
_rowSel = 2;
_colSel = 0;
// grab current settings upon entry to edit mode
adjPump[0] = getPumpMin();
adjPump[1] = getPumpMax();
adjFan[0] = getFanMin();
adjFan[1] = getFanMax();
adjPump[0] = getHeaterInfo().getPump_Min();
adjPump[1] = getHeaterInfo().getPump_Max();
adjFan[0] = getHeaterInfo().getFan_Min();
adjFan[1] = getHeaterInfo().getFan_Max();
}
// reset PW digits
for(int i= 0; i < 4; i++)

View file

@ -20,12 +20,13 @@
*/
#include "stdint.h"
#include "ScreenHeader.h"
class C128x64_OLED;
class CScreenManager;
class CProtocol;
class CScreen5 : public CScreen {
class CScreen5 : public CScreenHeader {
int _PWdig[4];
float adjPump[2];
short adjFan[2];
@ -36,7 +37,7 @@ class CScreen5 : public CScreen {
public:
CScreen5(C128x64_OLED& display, CScreenManager& mgr);
void show(const CProtocol& CtlFrame, const CProtocol& HtrFrame);
void show();
void animate();
void keyHandler(uint8_t event);
};

View file

@ -0,0 +1,85 @@
#include <Arduino.h>
#include "ScreenHeader.h"
#include "Protocol.h"
#include "128x64OLED.h"
#include "BTCWifi.h"
#include "BluetoothAbstract.h"
#include "clock.h"
#include "OLEDconsts.h"
#include "MiniFont.h"
#include "helpers.h"
#define MINIFONT miniFontInfo
#define X_BATT_ICON 95
#define Y_BATT_ICON 0
#define X_WIFI_ICON 22
#define Y_WIFI_ICON 0
#define X_BT_ICON 12
#define Y_BT_ICON 0
#define MINI_BATTLABEL
CScreenHeader::CScreenHeader(C128x64_OLED& disp, CScreenManager& mgr) : CScreen(disp, mgr)
{
}
void
CScreenHeader::show()
{
_display.clearDisplay();
// standard header items
//Bluetooth
if(getBluetoothClient().isConnected())
showBTicon();
// WiFi
if(isWifiConnected()) {
showWifiIcon();
}
// battery
showBatteryIcon(getHeaterInfo().getBattVoltage());
showTime(_display);
}
void
CScreenHeader::showBTicon()
{
_display.drawBitmap(X_BT_ICON, Y_BT_ICON, BTicon, W_BT_ICON, H_BT_ICON, WHITE);
}
void
CScreenHeader::showWifiIcon()
{
_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);
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
_display.setCursor(X_WIFI_ICON+9, Y_WIFI_ICON+6);
_display.print("AP");
#endif
}
void
CScreenHeader::showBatteryIcon(float voltage)
{
_display.drawBitmap(X_BATT_ICON, Y_BATT_ICON, BatteryIcon, W_BATT_ICON, H_BATT_ICON, WHITE);
char msg[16];
sprintf(msg, "%.1fV", voltage);
#ifdef MINI_BATTLABEL
CTransientFont AF(_display, &MINIFONT); // temporarily use a mini font
#endif
_display.setCursor(X_BATT_ICON + W_BATT_ICON/2,
Y_BATT_ICON + H_BATT_ICON + 2);
_display.printCentreJustified(msg);
// 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);
}

View file

@ -0,0 +1,41 @@
/*
* This file is part of the "bluetoothheater" distribution
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
*
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef __SCREEN_HEADER_H__
#define __SCREEN_HEADER_H__
#include <Arduino.h>
#include "FontTypes.h"
#include "UtilClasses.h"
#include "Screen.h"
class CScreenHeader : public CScreen {
protected:
void showBTicon();
void showWifiIcon();
void showBatteryIcon(float voltage);
public:
CScreenHeader(C128x64_OLED& disp, CScreenManager& mgr);
virtual void show();
};
#endif // __SCREEN_HEADER_H__

View file

@ -1,57 +1,14 @@
/*
* This file is part of the "bluetoothheater" distribution
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
*
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "ScreenManager.h"
#include <SPI.h>
#include <Wire.h>
#include "128x64OLED.h"
#include "MiniFont.h"
#include "tahoma16.h"
#include "protocol.h"
#include "display.h"
#include "pins.h"
#include "BluetoothAbstract.h"
#include "OLEDconsts.h"
#include "BTCWifi.h"
#include "BluetoothAbstract.h"
#include "Screen1.h"
#include "Screen2.h"
#include "Screen3.h"
#include "Screen4.h"
#include "Screen5.h"
#include "KeyPad.h"
#include "helpers.h"
#include "clock.h"
#include "BTCConfig.h"
#define MAXIFONT tahoma_16ptFontInfo
#define MINIFONT miniFontInfo
#define X_BATT_ICON 95
#define Y_BATT_ICON 0
#define X_WIFI_ICON 22
#define Y_WIFI_ICON 0
#define X_BT_ICON 12
#define Y_BT_ICON 0
#define MINI_BATTLABEL
//
// **** NOTE: There are two very lame libaries conspiring to make life difficult ****
@ -143,6 +100,7 @@ const unsigned char DieselSplash [] PROGMEM = {
0x11, 0x39, 0x8e, 0x93, 0x18, 0xe1, 0x13, 0x1c, 0xcc, 0x80, 0x78, 0xc9, 0x34, 0x19, 0x4c, 0x80
};
CScreenManager::CScreenManager()
{
_pDisplay = NULL;
@ -199,11 +157,11 @@ CScreenManager::init()
}
void
CScreenManager::checkUpdate(const CProtocol& CtlFrame, const CProtocol& HtrFrame)
CScreenManager::checkUpdate()
{
if(_bReqUpdate) {
if(_pActiveScreen) {
_pActiveScreen->show(CtlFrame, HtrFrame);
_pActiveScreen->show();
_bReqUpdate = false;
}
}
@ -258,143 +216,3 @@ CScreenManager::keyHandler(uint8_t event)
}
CScreen::CScreen(C128x64_OLED& disp, CScreenManager& mgr) :
_display(disp),
_ScreenManager(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();
// WiFi
if(isWifiConnected()) {
showWifiIcon();
}
// battery
float voltage = HtrFrame.getVoltage_Supply() * 0.1f;
showBatteryIcon(voltage);
showTime(_display);
}
void
CScreen::showBTicon()
{
_display.drawBitmap(X_BT_ICON, Y_BT_ICON, BTicon, W_BT_ICON, H_BT_ICON, WHITE);
}
void
CScreen::showWifiIcon()
{
_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);
CAutoFont AF(_display, &MINIFONT); // temporarily use a mini font
_display.setCursor(X_WIFI_ICON+9, Y_WIFI_ICON+6);
_display.print("AP");
#endif
}
void
CScreen::showBatteryIcon(float voltage)
{
_display.drawBitmap(X_BATT_ICON, Y_BATT_ICON, BatteryIcon, W_BATT_ICON, H_BATT_ICON, WHITE);
char msg[16];
sprintf(msg, "%.1fV", voltage);
#ifdef MINI_BATTLABEL
CAutoFont AF(_display, &MINIFONT); // temporarily use a mini font
#endif
_display.setCursor(X_BATT_ICON + W_BATT_ICON/2,
Y_BATT_ICON + H_BATT_ICON + 2);
_display.printCentreJustified(msg);
// 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
CScreen::_drawMenuText(int x, int y, const char* str, bool selected, eJUSTIFY justify, int border, int radius)
{
// position output, according to justification
CRect extents;
extents.xPos = x;
extents.yPos = y;
_display.getTextExtents(str, extents);
_adjustExtents(extents, justify, str);
_display.setCursor(extents.xPos, extents.yPos);
_display.print(str);
if(selected) {
extents.Expand(border);
_display.drawRoundRect(extents.xPos, extents.yPos, extents.width, extents.height, radius, WHITE);
}
}
void
CScreen::_printInverted(int x, int y, const char* str, bool selected, eJUSTIFY justify)
{
// position output, according to justification
CRect extents;
extents.xPos = x;
extents.yPos = y;
_adjustExtents(extents, justify, str);
if(selected) {
_display.setTextColor(BLACK, WHITE);
extents.Expand(1);
_display.fillRect(extents.xPos, extents.yPos, extents.width, extents.height, WHITE);
extents.Expand(-1);
}
_display.setCursor(extents.xPos, extents.yPos);
_display.print(str);
_display.setTextColor(WHITE, BLACK);
}
CAutoFont::CAutoFont(C128x64_OLED& disp, const FONT_INFO* pFont) :
_display(disp)
{
_display.setFontInfo(pFont);
_display.setTextColor(WHITE, BLACK);
}
CAutoFont::~CAutoFont()
{
_display.setFontInfo(NULL);
}
void
CScreen::_adjustExtents(CRect& extents, eJUSTIFY justify, const char* str)
{
_display.getTextExtents(str, extents);
switch(justify) {
case eCentreJustify:
extents.xPos -= extents.width/2;
break;
case eRightJustify:
extents.xPos -= extents.width;
break;
}
}

View file

@ -0,0 +1,51 @@
/*
* This file is part of the "bluetoothheater" distribution
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
*
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef __SCREEN_MANAGER_H__
#define __SCREEN_MANAGER_H__
#include <Arduino.h>
class CProtocol;
class C128x64_OLED;
class CScreen;
class CScreenManager {
static const int _maxScreens = 5;
CScreen* _pScreen[_maxScreens];
CScreen* _pActiveScreen;
C128x64_OLED* _pDisplay;
int _currentScreen;
bool _bReqUpdate;
void _switchScreen();
public:
CScreenManager();
~CScreenManager();
void init();
void checkUpdate();
void animate();
void nextScreen();
void prevScreen();
void keyHandler(uint8_t event);
void reqUpdate();
};
#endif // __SCREEN_MANAGER_H__

View file

@ -23,7 +23,7 @@
#include <sys/time.h> /* gettimeofday(), settimeofday() */
#include "stdint.h"
#include "128x64OLED.h"
#include "display.h"
#include "Screen.h"
#include "OCRfont.h"
#include "FranklinGothic.h"
@ -54,7 +54,7 @@ void showTime(C128x64_OLED& display)
else
sprintf(msg, "%02d %02d", timeinfo.tm_hour, timeinfo.tm_min);
{
CAutoFont AF(display, &franklinGothicMediumCond_8ptFontInfo);
CTransientFont AF(display, &franklinGothicMediumCond_8ptFontInfo);
display.setCursor(display.xCentre(), 0);
display.printCentreJustified(msg);
}

View file

@ -20,29 +20,22 @@
*
*/
class CProtocolPackage;
extern void ToggleOnOff();
extern void requestOn();
extern void requestOff();
extern int getRunState();
extern int getErrState();
extern void reqTempChange(int val);
extern int getSetTemp();
extern void reqThermoToggle();
extern void setThermostatMode(unsigned char);
extern bool getThermostatMode();
extern float getFixedHz();
extern float getPumpHz();
extern void reqPumpPrime(bool on);
extern float getActualTemperature();
extern float getPumpMin();
extern float getPumpMax();
extern short getFanMin();
extern short getFanMax();
extern void setPumpMin(float);
extern void setPumpMax(float);
extern void setFanMin(short);
extern void setFanMax(short);
extern void saveNV();
extern const CProtocolPackage& getHeaterInfo();
#define LOWERLIMIT(A, B) if(A < B) A = B
#define UPPERLIMIT(A, B) if(A > B) A = B