Split GPIO so each pin's function is defined individually.

Adjusted DS18B20 timing to match Maxim's recommended values.
This commit is contained in:
Ray Jones 2019-08-09 06:13:02 +10:00
parent 48a0254f13
commit 4873fa8c71
9 changed files with 520 additions and 340 deletions

View File

@ -68,15 +68,19 @@ sample code bearing this copyright.
// bus reset: duration of low phase [us]
#define OW_DURATION_RESET 480
// overall slot duration
#define OW_DURATION_SLOT 75
//#define OW_DURATION_SLOT 75
#define OW_DURATION_SLOT 70
// write 1 slot and read slot durations [us]
#define OW_DURATION_1_LOW 2
//#define OW_DURATION_1_LOW 2
#define OW_DURATION_1_LOW 6
#define OW_DURATION_1_HIGH (OW_DURATION_SLOT - OW_DURATION_1_LOW)
// write 0 slot durations [us]
#define OW_DURATION_0_LOW 65
//#define OW_DURATION_0_LOW 65
#define OW_DURATION_0_LOW 60
#define OW_DURATION_0_HIGH (OW_DURATION_SLOT - OW_DURATION_0_LOW)
// sample time for read slot
#define OW_DURATION_SAMPLE (15-2)
//#define OW_DURATION_SAMPLE (15-2)
#define OW_DURATION_SAMPLE (15-0)
// RX idle threshold
// needs to be larger than any duration occurring during write slots
#define OW_DURATION_RX_IDLE (OW_DURATION_SLOT + 2)

View File

@ -1373,12 +1373,19 @@ void setupGPIO()
// V2.0+ PCBs use an input transistor buffer. Active state into ESP32 is HIGH (inverted).
int activePinState = (BoardRevision == 10) ? LOW : HIGH;
int Input1 = BoardRevision == 20 ? GPIOin1_pinV20 : GPIOin1_pinV21V10;
GPIOin.begin(Input1, GPIOin2_pin, NVstore.getUserSettings().GPIO.in1Mode, NVstore.getUserSettings().GPIO.in2Mode, activePinState);
GPIOin.begin(Input1,
GPIOin2_pin,
NVstore.getUserSettings().GPIO.in1Mode,
NVstore.getUserSettings().GPIO.in2Mode,
activePinState);
// GPIO out is always active high from ESP32
// V1.0 PCBs only expose the bare pins
// V2.0+ PCBs provide an open collector output that conducts when active
GPIOout.begin(GPIOout1_pin, GPIOout2_pin, NVstore.getUserSettings().GPIO.out1Mode, NVstore.getUserSettings().GPIO.out2Mode);
GPIOout.begin(GPIOout1_pin,
GPIOout2_pin,
NVstore.getUserSettings().GPIO.out1Mode,
NVstore.getUserSettings().GPIO.out2Mode);
// ### MAJOR ISSUE WITH ADC INPUTS ###
//
@ -1394,9 +1401,9 @@ void setupGPIO()
// This will be properly fixed in V2.1 PCBs
//
// As V1.0 PCBS expose the bare pins, the correct GPIO33 input can be readily chosen.
GPIOalgModes algMode = NVstore.getUserSettings().GPIO.algMode;
CGPIOalg::Modes algMode = NVstore.getUserSettings().GPIO.algMode;
if(BoardRevision == 20)
algMode = GPIOalgNone; // force off analogue support in V2.0 PCBs
algMode = CGPIOalg::Disabled; // force off analogue support in V2.0 PCBs
GPIOalg.begin(GPIOalg_pin, algMode);
}
else {
@ -1407,22 +1414,22 @@ void setupGPIO()
pinMode(GPIOin1_pinV20, INPUT_PULLUP);
pinMode(GPIOout1_pin, INPUT_PULLUP);
pinMode(GPIOout2_pin, INPUT_PULLUP);
GPIOin.begin(0, 0, GPIOin1None, GPIOin2None, LOW); // ensure modes disabled (should already be by constructors)
GPIOout.begin(0, 0, GPIOout1None, GPIOout2None);
GPIOalg.begin(ADC1_CHANNEL_5, GPIOalgNone);
GPIOin.begin(0, 0, CGPIOin1::Disabled, CGPIOin2::Disabled, LOW); // ensure modes disabled (should already be by constructors)
GPIOout.begin(0, 0, CGPIOout1::Disabled, CGPIOout2::Disabled);
GPIOalg.begin(ADC1_CHANNEL_5, CGPIOalg::Disabled);
}
}
bool toggleGPIOout(int channel)
{
if(channel == 0) {
if(NVstore.getUserSettings().GPIO.out1Mode == GPIOout1User) {
if(NVstore.getUserSettings().GPIO.out1Mode == CGPIOout1::User) {
setGPIOout(channel, !getGPIOout(channel)); // toggle selected GPIO output
return true;
}
}
else if(channel == 1) {
if(NVstore.getUserSettings().GPIO.out2Mode == GPIOout2User) {
if(NVstore.getUserSettings().GPIO.out2Mode == CGPIOout2::User) {
setGPIOout(channel, !getGPIOout(channel)); // toggle selected GPIO output
return true;
}
@ -1433,14 +1440,14 @@ bool toggleGPIOout(int channel)
bool setGPIOout(int channel, bool state)
{
if(channel == 0) {
if(GPIOout.getMode1() != GPIOout1None) {
if(GPIOout.getMode1() != CGPIOout1::Disabled) {
DebugPort.printf("setGPIO: Output #%d = %d\r\n", channel+1, state);
GPIOout.setState(channel, state);
return true;
}
}
else if(channel == 1) {
if(GPIOout.getMode2() != GPIOout2None) {
if(GPIOout.getMode2() != CGPIOout2::Disabled) {
DebugPort.printf("setGPIO: Output #%d = %d\r\n", channel+1, state);
GPIOout.setState(channel, state);
return true;

View File

@ -33,7 +33,7 @@ extern CGPIOalg GPIOalg;
///////////////////////////////////////////////////////////////////////////
//
// CGPIOScreen
// CGPIOSetupScreen
//
// This screen provides control over GPIO features
//
@ -45,18 +45,18 @@ static const int Line1 = 40;
static const int Column1 = 26;
static const int Column2 = 85;
CGPIOScreen::CGPIOScreen(C128x64_OLED& display, CScreenManager& mgr) : CPasswordScreen(display, mgr)
CGPIOSetupScreen::CGPIOSetupScreen(C128x64_OLED& display, CScreenManager& mgr) : CPasswordScreen(display, mgr)
{
_initUI();
_GPIOparams.in1Mode = GPIOin1None;
_GPIOparams.in2Mode = GPIOin2None;
_GPIOparams.out1Mode = GPIOout1None;
_GPIOparams.out2Mode = GPIOout2None;
_GPIOparams.algMode = GPIOalgNone;
_GPIOparams.in1Mode = CGPIOin1::Disabled;
_GPIOparams.in2Mode = CGPIOin2::Disabled;
_GPIOparams.out1Mode = CGPIOout1::Disabled;
_GPIOparams.out2Mode = CGPIOout2::Disabled;
_GPIOparams.algMode = CGPIOalg::Disabled;
}
void
CGPIOScreen::onSelect()
CGPIOSetupScreen::onSelect()
{
CPasswordScreen::onSelect();
_initUI();
@ -64,14 +64,14 @@ CGPIOScreen::onSelect()
}
void
CGPIOScreen::_initUI()
CGPIOSetupScreen::_initUI()
{
_rowSel = 0;
_animateCount = 0;
}
bool
CGPIOScreen::show()
CGPIOSetupScreen::show()
{
_display.clearDisplay();
@ -89,10 +89,10 @@ CGPIOScreen::show()
{
const char* msgText = NULL;
switch(_GPIOparams.in1Mode) {
case GPIOin1None: msgText = "1: --- "; break;
case GPIOin1On: msgText = "1:Start"; break;
case GPIOin1Hold: msgText = "1: Run "; break;
case GPIOin1OnOff: msgText = animated ? "1:Start" : "1: Stop"; break;
case CGPIOin1::Disabled: msgText = "1: --- "; break;
case CGPIOin1::On: msgText = "1:Start"; break;
case CGPIOin1::Hold: msgText = "1: Run "; break;
case CGPIOin1::OnOff: msgText = animated ? "1:Start" : "1: Stop"; break;
}
if(msgText)
_printMenuText(Column1, Line3, msgText, _rowSel == 4);
@ -100,9 +100,9 @@ CGPIOScreen::show()
{
const char* msgText = NULL;
switch(_GPIOparams.in2Mode) {
case GPIOin2None: msgText = "2: ---"; break;
case GPIOin2Off: msgText = "2:Stop"; break;
case GPIOin2ExtThermostat: msgText = "2: \352T "; break;
case CGPIOin2::Disabled: msgText = "2: ---"; break;
case CGPIOin2::Off: msgText = "2:Stop"; break;
case CGPIOin2::Thermostat: msgText = "2: \352T "; break;
}
if(msgText)
_printMenuText(Column2, Line3, msgText, _rowSel == 5);
@ -111,9 +111,9 @@ CGPIOScreen::show()
{
const char* msgText = NULL;
switch(_GPIOparams.out1Mode) {
case GPIOout1None: msgText = "1: --- "; break;
case GPIOout1Status: msgText = "1:Status"; break;
case GPIOout1User: msgText = "1: User "; break;
case CGPIOout1::Disabled: msgText = "1: --- "; break;
case CGPIOout1::Status: msgText = "1:Status"; break;
case CGPIOout1::User: msgText = "1: User "; break;
}
if(msgText)
_printMenuText(Column1, Line2, msgText, _rowSel == 2);
@ -121,8 +121,8 @@ CGPIOScreen::show()
{
const char* msgText = NULL;
switch(_GPIOparams.out2Mode) {
case GPIOout2None: msgText = "2: ---"; break;
case GPIOout2User: msgText = "2:User"; break;
case CGPIOout2::Disabled: msgText = "2: ---"; break;
case CGPIOout2::User: msgText = "2:User"; break;
}
if(msgText)
_printMenuText(Column2, Line2, msgText, _rowSel == 3);
@ -131,8 +131,8 @@ CGPIOScreen::show()
if(getBoardRevision() != BRD_V2_GPIO_NOALG) { // Not No Analog support
const char* msgText = NULL;
switch(_GPIOparams.algMode) {
case GPIOalgNone: msgText = "Disabled"; break;
case GPIOalgHeatDemand: msgText = "Ip1 allows"; break;
case CGPIOalg::Disabled: msgText = "Disabled"; break;
case CGPIOalg::HeatDemand: msgText = "Ip1 allows"; break;
}
if(msgText)
_printMenuText(Column1, Line1, msgText, _rowSel == 1);
@ -144,7 +144,7 @@ CGPIOScreen::show()
}
bool
CGPIOScreen::animate()
CGPIOSetupScreen::animate()
{
CPasswordScreen::animate();
@ -160,8 +160,8 @@ CGPIOScreen::animate()
case 1:
_display.drawFastHLine(0, 52, 128, WHITE);
switch(_GPIOparams.algMode) {
case GPIOalgNone: pMsg = " Analogue input is ignored. "; break;
case GPIOalgHeatDemand: pMsg = " Input 1 enables reading of analogue input to set temperature. "; break;
case CGPIOalg::Disabled: pMsg = " Analogue input is ignored. "; break;
case CGPIOalg::HeatDemand: pMsg = " Input 1 enables reading of analogue input to set temperature. "; break;
}
if(pMsg)
_scrollMessage(56, pMsg, _scrollChar);
@ -170,9 +170,9 @@ CGPIOScreen::animate()
case 2:
_display.drawFastHLine(0, 52, 128, WHITE);
switch(_GPIOparams.out1Mode) {
case GPIOout1None: pMsg = " Output 1: DISABLED. "; break;
case GPIOout1Status: pMsg = " Output 1: LED status indicator. "; break;
case GPIOout1User: pMsg = " Output 1: User controlled. "; break;
case CGPIOout1::Disabled: pMsg = " Output 1: DISABLED. "; break;
case CGPIOout1::Status: pMsg = " Output 1: LED status indicator. "; break;
case CGPIOout1::User: pMsg = " Output 1: User controlled. "; break;
}
if(pMsg)
_scrollMessage(56, pMsg, _scrollChar);
@ -180,8 +180,8 @@ CGPIOScreen::animate()
case 3:
_display.drawFastHLine(0, 52, 128, WHITE);
switch(_GPIOparams.out2Mode) {
case GPIOout2None: pMsg = " Output 2: DISABLED. "; break;
case GPIOout2User: pMsg = " Output 2: User controlled. "; break;
case CGPIOout2::Disabled: pMsg = " Output 2: DISABLED. "; break;
case CGPIOout2::User: pMsg = " Output 2: User controlled. "; break;
}
if(pMsg)
_scrollMessage(56, pMsg, _scrollChar);
@ -190,10 +190,10 @@ CGPIOScreen::animate()
case 4:
_display.drawFastHLine(0, 52, 128, WHITE);
switch(_GPIOparams.in1Mode) {
case GPIOin1None: pMsg = " Input 1: DISABLED. "; break;
case GPIOin1On: pMsg = " Input 1: Starts heater upon closure. "; break;
case GPIOin1Hold: pMsg = " Input 1: Starts heater when held closed, stops when opened. "; break;
case GPIOin1OnOff: pMsg = " Input 1: Starts or Stops heater upon closure. "; break;
case CGPIOin1::Disabled: pMsg = " Input 1: DISABLED. "; break;
case CGPIOin1::On: pMsg = " Input 1: Starts heater upon closure. "; break;
case CGPIOin1::Hold: pMsg = " Input 1: Starts heater when held closed, stops when opened. "; break;
case CGPIOin1::OnOff: pMsg = " Input 1: Starts or Stops heater upon closure. "; break;
}
if(pMsg)
_scrollMessage(56, pMsg, _scrollChar);
@ -201,9 +201,9 @@ CGPIOScreen::animate()
case 5:
_display.drawFastHLine(0, 52, 128, WHITE);
switch(_GPIOparams.in2Mode) {
case GPIOin2None: pMsg = " Input 2: DISABLED. "; break;
case GPIOin2Off: pMsg = " Input 2: Stops heater upon closure. "; break;
case GPIOin2ExtThermostat: pMsg = " Input 2: External thermostat. Max fuel when closed, min fuel when open. "; break;
case CGPIOin2::Disabled: pMsg = " Input 2: DISABLED. "; break;
case CGPIOin2::Off: pMsg = " Input 2: Stops heater upon closure. "; break;
case CGPIOin2::Thermostat: pMsg = " Input 2: External thermostat. Max fuel when closed, min fuel when open. "; break;
}
if(pMsg)
_scrollMessage(56, pMsg, _scrollChar);
@ -216,7 +216,7 @@ CGPIOScreen::animate()
}
bool
CGPIOScreen::keyHandler(uint8_t event)
CGPIOSetupScreen::keyHandler(uint8_t event)
{
sUserSettings us;
if(event & keyPressed) {
@ -297,7 +297,6 @@ CGPIOScreen::keyHandler(uint8_t event)
if(event & key_Centre) {
switch(_rowSel) {
case 0:
// _ScreenManager.selectMenu(CScreenManager::RootMenuLoop, CScreenManager::GPIOInfoUI); // force return to main menu GPIO view
_ScreenManager.selectMenu(CScreenManager::RootMenuLoop); // force return to main menu
break;
case 1:
@ -316,7 +315,7 @@ CGPIOScreen::keyHandler(uint8_t event)
}
void
CGPIOScreen::_adjust(int dir)
CGPIOSetupScreen::_adjust(int dir)
{
int tVal;
switch(_rowSel) {
@ -324,31 +323,31 @@ CGPIOScreen::_adjust(int dir)
tVal = _GPIOparams.algMode;
tVal += dir;
WRAPLIMITS(tVal, 0, 1);
_GPIOparams.algMode = (GPIOalgModes)tVal;
_GPIOparams.algMode = (CGPIOalg::Modes)tVal;
break;
case 2: // outputs mode
tVal = _GPIOparams.out1Mode;
tVal += dir;
WRAPLIMITS(tVal, 0, 2);
_GPIOparams.out1Mode = (GPIOout1Modes)tVal;
_GPIOparams.out1Mode = (CGPIOout1::Modes)tVal;
break;
case 3: // outputs mode
tVal = _GPIOparams.out2Mode;
tVal += dir;
WRAPLIMITS(tVal, 0, 1);
_GPIOparams.out2Mode = (GPIOout2Modes)tVal;
_GPIOparams.out2Mode = (CGPIOout2::Modes)tVal;
break;
case 4:
tVal = _GPIOparams.in1Mode;
tVal += dir;
WRAPLIMITS(tVal, 0, 3);
_GPIOparams.in1Mode = (GPIOin1Modes)tVal;
_GPIOparams.in1Mode = (CGPIOin1::Modes)tVal;
break;
case 5:
tVal = _GPIOparams.in2Mode;
tVal += dir;
WRAPLIMITS(tVal, 0, 2);
_GPIOparams.in2Mode = (GPIOin2Modes)tVal;
_GPIOparams.in2Mode = (CGPIOin2::Modes)tVal;
break;
}
}
@ -383,27 +382,24 @@ CGPIOInfoScreen::show()
if(getBoardRevision() == BRD_V2_FULLGPIO || getBoardRevision() == BRD_V1_FULLGPIO)
_printMenuText(55, Line1, "Analogue:", false, eRightJustify);
if(NVstore.getUserSettings().GPIO.in1Mode == GPIOin1None) {
_drawBitmap(7, 28, CrossLgIconInfo);
}
else {
_drawBitmap(4, 29, GPIOin.getState(0) ? CloseIconInfo : OpenIconInfo);
}
if(NVstore.getUserSettings().GPIO.in2Mode == GPIOin2None) {
_drawBitmap(30, 28, CrossLgIconInfo);
}
else {
_drawBitmap(27, 29, GPIOin.getState(1) ? CloseIconInfo : OpenIconInfo);
}
// if(NVstore.getUserSettings().GPIO.in1Mode == CGPIOin1::Disabled) {
// _display.drawFastHLine(7, 23, 7, WHITE);
// }
_drawBitmap(4, 29, GPIOin.getState(0) ? CloseIconInfo : OpenIconInfo);
// if(NVstore.getUserSettings().GPIO.in2Mode == CGPIOin2::Disabled) {
// _display.drawFastHLine(29, 23, 9, WHITE);
// }
_drawBitmap(27, 29, GPIOin.getState(1) ? CloseIconInfo : OpenIconInfo);
if(NVstore.getUserSettings().GPIO.out1Mode == GPIOout1None) {
if(NVstore.getUserSettings().GPIO.out1Mode == CGPIOout1::Disabled) {
_drawBitmap(87, 28, CrossLgIconInfo);
}
else {
_drawBitmap(86, 29, GPIOout.getState(0) ? BulbOnIconInfo : BulbOffIconInfo);
}
if(NVstore.getUserSettings().GPIO.out2Mode == GPIOout2None) {
if(NVstore.getUserSettings().GPIO.out2Mode == CGPIOout2::Disabled) {
_drawBitmap(114, 28, CrossLgIconInfo);
}
else {
@ -412,7 +408,7 @@ CGPIOInfoScreen::show()
if(getBoardRevision() == BRD_V2_FULLGPIO || getBoardRevision() == BRD_V1_FULLGPIO) {
if(NVstore.getUserSettings().GPIO.algMode == GPIOalgNone) {
if(NVstore.getUserSettings().GPIO.algMode == CGPIOalg::Disabled) {
_drawBitmap(58, Line1, CrossLgIconInfo);
}
else {

View File

@ -29,7 +29,7 @@
class C128x64_OLED;
class CScreenManager;
class CGPIOScreen : public CPasswordScreen
class CGPIOSetupScreen : public CPasswordScreen
{
int _rowSel;
void _adjust(int dir);
@ -38,7 +38,7 @@ class CGPIOScreen : public CPasswordScreen
int _scrollChar;
void _initUI();
public:
CGPIOScreen(C128x64_OLED& display, CScreenManager& mgr);
CGPIOSetupScreen(C128x64_OLED& display, CScreenManager& mgr);
bool show();
bool animate();
bool keyHandler(uint8_t event);

View File

@ -433,7 +433,7 @@ CScreenManager::begin(bool bNoClock)
menuloop.push_back(new CHomeMenuSelScreen(*_pDisplay, *this)); // Home menu settings screen
menuloop.push_back(new COtherOptionsScreen(*_pDisplay, *this)); // Other options screen
if(getBoardRevision() != 0 && getBoardRevision() != BRD_V2_NOGPIO) // has GPIO support ?
menuloop.push_back(new CGPIOScreen(*_pDisplay, *this)); // GPIO settings screen
menuloop.push_back(new CGPIOSetupScreen(*_pDisplay, *this)); // GPIO settings screen
_Screens.push_back(menuloop);
// create System Settings screens loop

View File

@ -30,14 +30,6 @@ const int FADEAMOUNT = 3;
const int FLASHPERIOD = 2000;
const int ONFLASHINTERVAL = 50;
// const char* GPIOinNames[] = {
// "Disabled",
// "On1Off2",
// "Hold1",
// "On1Off1",
// "ExtThermostat"
// };
const char* GPIOin1Names[] = {
"Disabled",
"Mom On",
@ -51,11 +43,6 @@ const char* GPIOin2Names[] = {
};
// const char* GPIOoutNames[] = {
// "Disabled",
// "Status",
// "User"
// };
const char* GPIOout1Names[] = {
"Disabled",
"Status",
@ -71,16 +58,132 @@ const char* GPIOalgNames[] = {
"HeatDemand"
};
CGPIOin1::CGPIOin1()
{
_Mode = Disabled;
}
void
CGPIOin1::begin(CGPIOin1::Modes mode)
{
setMode(mode);
}
CGPIOin1::Modes CGPIOin1::getMode() const
{
return _Mode;
};
void
CGPIOin1::manage(bool active)
{
switch (_Mode) {
case Disabled:
break;
case On:
_doOn(active);
break;
case Hold:
_doOnHold(active);
break;
case OnOff:
_doOnOff(active);
break;
}
}
void
CGPIOin1::_doOn(bool active)
{
if(active) {
requestOn();
}
}
// mode where heater runs if input 1 is shorted
// stops when open
void
CGPIOin1::_doOnHold(bool active)
{
if(active) {
requestOn();
}
else {
requestOff();
}
}
// mode where heater runs if input 1 is shorted
// stops when open
void
CGPIOin1::_doOnOff(bool active)
{
if(active) {
if(getHeaterInfo().getRunStateEx())
requestOff();
else
requestOn();
}
}
CGPIOin2::CGPIOin2()
{
_Mode = Disabled;
}
void
CGPIOin2::begin(CGPIOin2::Modes mode)
{
setMode(mode);
}
CGPIOin2::Modes CGPIOin2::getMode() const
{
return _Mode;
};
void
CGPIOin2::manage(bool active)
{
switch (_Mode) {
case Disabled:
break;
case Off:
_doOff(active);
break;
case Thermostat:
_doThermostat(active);
break;
}
}
void
CGPIOin2::_doOff(bool active)
{
if(active) {
requestOff();
}
}
// mode where heater runs if input 1 is shorted
// stops when open
void
CGPIOin2::_doThermostat(bool active)
{
// handling actually performed at Tx Manage for setting the fuel rate
}
CGPIOin::CGPIOin()
{
_Mode1 = GPIOin1None;
_Mode2 = GPIOin2None;
_Input1.setMode(CGPIOin1::Disabled);
_Input2.setMode(CGPIOin2::Disabled);
_lastKey = 0;
}
void
CGPIOin::begin(int pin1, int pin2, GPIOin1Modes mode1, GPIOin2Modes mode2, int activeState)
CGPIOin::begin(int pin1, int pin2, CGPIOin1::Modes mode1, CGPIOin2::Modes mode2, int activeState)
{
_Debounce.addPin(pin1);
_Debounce.addPin(pin2);
@ -112,14 +215,14 @@ CGPIOin::getState(int channel)
return retval;
}
GPIOin1Modes CGPIOin::getMode1() const
CGPIOin1::Modes CGPIOin::getMode1() const
{
return _Mode1;
return _Input1.getMode();
};
GPIOin2Modes CGPIOin::getMode2() const
CGPIOin2::Modes CGPIOin::getMode2() const
{
return _Mode2;
return _Input2.getMode();
};
void
@ -144,80 +247,81 @@ CGPIOin::manage()
void
CGPIOin::simulateKey(uint8_t newKey)
{
switch (_Mode1) {
case GPIOin1None:
break;
case GPIOin1On:
_doOn1(newKey);
break;
case GPIOin1Hold:
_doOnHold1(newKey);
break;
case GPIOin1OnOff:
_doOn1Off1(newKey);
break;
}
switch (_Mode2) {
case GPIOin2None:
break;
case GPIOin2Off:
_doOff2(newKey);
break;
case GPIOin2ExtThermostat:
break; // handling actually performed at Tx Manage for setting the fuel rate
}
}
void
CGPIOin::_doOn1(uint8_t newKey)
{
if(newKey & 0x01) {
requestOn();
}
}
void
CGPIOin::_doOff2(uint8_t newKey)
{
if(newKey & 0x02) {
requestOff();
}
}
// mode where heater runs if input 1 is shorted
// stops when open
void
CGPIOin::_doOnHold1(uint8_t newKey)
{
if(newKey & 0x01) {
requestOn();
}
else {
requestOff();
}
}
// mode where heater runs if input 1 is shorted
// stops when open
void
CGPIOin::_doOn1Off1(uint8_t newKey)
{
if(newKey & 0x01) {
if(getHeaterInfo().getRunStateEx())
requestOff();
else
requestOn();
}
_Input1.manage((newKey & 0x01) != 0);
_Input2.manage((newKey & 0x02) != 0);
}
/*********************************************************************************************************
** GPIO out root
*********************************************************************************************************/
CGPIOout::CGPIOout()
{
_Mode1 = GPIOout1None;
_Mode2 = GPIOout2None;
_pins[0] = 0;
_pins[1] = 0;
}
void
CGPIOout::begin(int pin1, int pin2, CGPIOout1::Modes mode1, CGPIOout2::Modes mode2)
{
_Out1.begin(pin1, mode1);
_Out2.begin(pin2, mode2);
}
void
CGPIOout::setMode(CGPIOout1::Modes mode1, CGPIOout2::Modes mode2)
{
_Out1.setMode(mode1);
_Out2.setMode(mode2);
};
CGPIOout1::Modes
CGPIOout::getMode1() const
{
return _Out1.getMode();
};
CGPIOout2::Modes
CGPIOout::getMode2() const
{
return _Out2.getMode();
};
void
CGPIOout::manage()
{
_Out1.manage();
_Out2.manage();
}
void
CGPIOout::setState(int channel, bool state)
{
if(channel)
_Out2.setState(state);
else
_Out1.setState(state);
}
bool
CGPIOout::getState(int channel)
{
if(channel)
return _Out2.getState();
else
return _Out1.getState();
}
/*********************************************************************************************************
** GPIO out #1
*********************************************************************************************************/
CGPIOout1::CGPIOout1()
{
_Mode = Disabled;
_pin = 0;
_breatheDelay = 0;
_statusState = 0;
_statusDelay = 0;
@ -226,62 +330,45 @@ CGPIOout::CGPIOout()
}
void
CGPIOout::begin(int pin1, int pin2, GPIOout1Modes mode1, GPIOout2Modes mode2)
CGPIOout1::begin(int pin, CGPIOout1::Modes mode)
{
_pins[0] = pin1;
_pins[1] = pin2;
if(pin1) {
pinMode(pin1, OUTPUT); // GPIO output pin #1
digitalWrite(pin1, LOW);
_pin = pin;
if(pin) {
pinMode(pin, OUTPUT); // GPIO output pin #1
digitalWrite(pin, LOW);
ledcSetup(0, 500, 8); // create PWM channel for GPIO1: 500Hz, 8 bits
}
if(pin2) {
pinMode(pin2, OUTPUT); // GPIO output pin #2
digitalWrite(pin2, LOW);
ledcSetup(1, 500, 8); // create PWM channel for GPIO2: 500Hz, 8 bits
}
setMode(mode1, mode2);
setMode(mode);
}
void
CGPIOout::setMode(GPIOout1Modes mode1, GPIOout2Modes mode2)
CGPIOout1::setMode(Modes mode)
{
_Mode1 = mode1;
_Mode2 = mode2;
_Mode = mode;
_prevState = -1;
ledcDetachPin(_pins[0]); // ensure PWM detached from IO line
ledcDetachPin(_pins[1]); // ensure PWM detached from IO line
ledcDetachPin(_pin); // ensure PWM detached from IO line
};
GPIOout1Modes CGPIOout::getMode1() const
CGPIOout1::Modes CGPIOout1::getMode() const
{
return _Mode1;
};
GPIOout2Modes CGPIOout::getMode2() const
{
return _Mode2;
return _Mode;
};
void
CGPIOout::manage()
CGPIOout1::manage()
{
switch (_Mode1) {
case GPIOout1None: break;
case GPIOout1Status: _doStatus(); break;
case GPIOout1User: _doUser1(); break;
}
switch (_Mode2) {
case GPIOout2None: break;
case GPIOout2User: _doUser2(); break;
switch (_Mode) {
case Disabled: break;
case Status: _doStatus(); break;
case User: _doUser(); break;
}
}
void
CGPIOout::_doStatus()
CGPIOout1::_doStatus()
{
if(_pins[0] == 0)
if(_pin == 0)
return;
// DebugPort.println("GPIOout::_doStatus()");
@ -322,28 +409,28 @@ CGPIOout::_doStatus()
_statusDelay = millis() + BREATHINTERVAL;
switch(statusMode) {
case 0:
ledcDetachPin(_pins[0]); // detach PWM from IO line
digitalWrite(_pins[0], LOW);
ledcDetachPin(_pin); // detach PWM from IO line
digitalWrite(_pin, LOW);
break;
case 1:
ledcAttachPin(_pins[0], 0); // attach PWM to GPIO line
ledcAttachPin(_pin, 0); // attach PWM to GPIO line
ledcWrite(0, _statusState);
_breatheDelay = millis() + BREATHINTERVAL;
break;
case 2:
ledcDetachPin(_pins[0]); // detach PWM from IO line
digitalWrite(_pins[0], HIGH);
ledcDetachPin(_pin); // detach PWM from IO line
digitalWrite(_pin, HIGH);
break;
case 3:
ledcAttachPin(_pins[0], 0); // attach PWM to GPIO line
ledcAttachPin(_pin, 0); // attach PWM to GPIO line
_statusState = 255;
ledcWrite(0, _statusState);
_breatheDelay = millis() + BREATHINTERVAL;
break;
case 4:
ledcDetachPin(_pins[0]); // detach PWM from IO line
ledcDetachPin(_pin); // detach PWM from IO line
_breatheDelay += (FLASHPERIOD - ONFLASHINTERVAL); // extended off
digitalWrite(_pins[0], LOW);
digitalWrite(_pin, LOW);
break;
}
}
@ -355,25 +442,16 @@ CGPIOout::_doStatus()
}
void
CGPIOout::_doUser1()
{
// DebugPort.println("GPIOout::_doUser1()");
if(_pins[0]) {
digitalWrite(_pins[0], (_userState & 0x01) ? HIGH : LOW);
}
}
void
CGPIOout::_doUser2()
CGPIOout1::_doUser()
{
// DebugPort.println("GPIOout::_doUser2()");
if(_pins[1]) {
digitalWrite(_pins[1], (_userState & 0x02) ? HIGH : LOW);
if(_pin) {
digitalWrite(_pin, _userState ? HIGH : LOW);
}
}
void
CGPIOout::_doStartMode() // breath up PWM
CGPIOout1::_doStartMode() // breath up PWM
{
long tDelta = millis() - _breatheDelay;
if(tDelta >= 0) {
@ -386,7 +464,7 @@ CGPIOout::_doStartMode() // breath up PWM
}
void
CGPIOout::_doStopMode() // breath down PWM
CGPIOout1::_doStopMode() // breath down PWM
{
long tDelta = millis() - _breatheDelay;
if(tDelta >= 0) {
@ -400,39 +478,98 @@ CGPIOout::_doStopMode() // breath down PWM
}
void
CGPIOout::_doSuspendMode() // brief flash
CGPIOout1::_doSuspendMode() // brief flash
{
long tDelta = millis() - _breatheDelay;
if(tDelta >= 0) {
_statusState++;
if(_statusState & 0x01) {
_breatheDelay += ONFLASHINTERVAL; // brief flash on
digitalWrite(_pins[0], HIGH);
digitalWrite(_pin, HIGH);
}
else {
_breatheDelay += (FLASHPERIOD - ONFLASHINTERVAL); // extended off
digitalWrite(_pins[0], LOW);
digitalWrite(_pin, LOW);
}
}
}
void
CGPIOout::setState(int channel, bool state)
CGPIOout1::setState(bool state)
{
int mask = 0x01 << (channel & 0x01);
if(state)
_userState |= mask;
else
_userState &= ~mask;
_userState = state;
}
bool
CGPIOout::getState(int channel)
CGPIOout1::getState()
{
int mask = 0x01 << (channel & 0x01);
return (_userState & mask) != 0;
return _userState;
}
/*********************************************************************************************************
** GPIO2
*********************************************************************************************************/
CGPIOout2::CGPIOout2()
{
_Mode = Disabled;
_pin = 0;
_userState = 0;
}
void
CGPIOout2::begin(int pin, Modes mode)
{
_pin = pin;
if(pin) {
pinMode(pin, OUTPUT); // GPIO output pin #2
digitalWrite(pin, LOW);
ledcSetup(1, 500, 8); // create PWM channel for GPIO2: 500Hz, 8 bits
}
setMode(mode);
}
void
CGPIOout2::setMode(CGPIOout2::Modes mode)
{
_Mode = mode;
if(_pin)
ledcDetachPin(_pin); // ensure PWM detached from IO line
};
CGPIOout2::Modes CGPIOout2::getMode() const
{
return _Mode;
};
void
CGPIOout2::manage()
{
switch (_Mode) {
case CGPIOout2::Disabled: break;
case CGPIOout2::User: _doUser(); break;
}
}
void
CGPIOout2::_doUser()
{
if(_pin) {
digitalWrite(_pin, _userState ? HIGH : LOW);
}
}
void
CGPIOout2::setState(bool state)
{
_userState = state;
}
bool
CGPIOout2::getState()
{
return _userState;
}
// expected external analogue circuit is a 10k pot.
// Top end of pot is connected to GPIO Vcc (red wire) via 5k6 fixed resistor. (GPIO Vcc is 5V via schottky diode)
@ -445,19 +582,19 @@ CGPIOalg::CGPIOalg()
}
void
CGPIOalg::begin(adc1_channel_t pin, GPIOalgModes mode)
CGPIOalg::begin(adc1_channel_t pin, CGPIOalg::Modes mode)
{
_pin = pin;
_Mode = mode;
if(_Mode != GPIOalgNone) {
if(_Mode != CGPIOalg::Disabled) {
adc_gpio_init(ADC_UNIT_1, ADC_CHANNEL_5);
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_5, ADC_ATTEN_11db);
}
}
GPIOalgModes CGPIOalg::getMode() const
CGPIOalg::Modes CGPIOalg::getMode() const
{
return _Mode;
};
@ -467,7 +604,7 @@ void CGPIOalg::manage()
{
const float fAlpha = 0.95; // exponential mean alpha
if(_Mode != GPIOalgNone) {
if(_Mode != CGPIOalg::Disabled) {
int read_raw;
char msg[32];
read_raw = adc1_get_raw( ADC1_CHANNEL_5);

View File

@ -33,125 +33,164 @@ extern const char* GPIOout1Names[];
extern const char* GPIOout2Names[];
extern const char* GPIOalgNames[];
enum GPIOin1Modes {
GPIOin1None,
GPIOin1On, // input 1 closure, heater starts; input2 closure, heater stops
GPIOin1Hold, // hold input 1 closure, heater runs; input 1 open, heater stops
GPIOin1OnOff // alternate input 1 closures start or stop the heater
};
enum GPIOin2Modes {
GPIOin2None,
GPIOin2Off, // input 2 closure stops heater
GPIOin2ExtThermostat // input 2 used to max/min heater if closed/open
class CGPIOin1 {
public:
enum Modes {
Disabled,
On, // input 1 closure, heater starts; input2 closure, heater stops
Hold, // hold input 1 closure, heater runs; input 1 open, heater stops
OnOff // alternate input 1 closures start or stop the heater
};
CGPIOin1();
void setMode(Modes mode) { _Mode = mode; };
void begin(Modes mode);
void manage(bool active);
Modes getMode() const;
private:
Modes _Mode;
void _doOn(bool active);
void _doOnHold(bool active);
void _doOnOff(bool active);
};
enum GPIOout1Modes {
GPIOout1None,
GPIOout1Status,
GPIOout1User
class CGPIOin2 {
public:
enum Modes {
Disabled,
Off, // input 2 closure stops heater
Thermostat // input 2 used to max/min heater if closed/open
};
CGPIOin2();
void setMode(Modes mode) { _Mode = mode; };
void begin(Modes mode);
void manage(bool active);
Modes getMode() const;
private:
Modes _Mode;
void _doOff(bool active);
void _doThermostat(bool active);
};
enum GPIOout2Modes {
GPIOout2None,
GPIOout2User
};
enum GPIOalgModes {
GPIOalgNone, // Unmodified V2.0 PCBs must use this - ADC2 / Wifi unresolvable conflict
GPIOalgHeatDemand,
};
struct sGPIOparams {
GPIOin1Modes in1Mode;
GPIOin2Modes in2Mode;
GPIOout1Modes out1Mode;
GPIOout2Modes out2Mode;
GPIOalgModes algMode;
};
class CGPIOin {
GPIOin1Modes _Mode1;
GPIOin2Modes _Mode2;
CGPIOin1 _Input1;
CGPIOin2 _Input2;
CDebounce _Debounce;
uint8_t _lastKey;
std::list<uint8_t> _eventList[2];
void _doOn1(uint8_t newKey);
void _doOff2(uint8_t newKey);
void _doOnHold1(uint8_t newKey);
void _doOn1Off1(uint8_t newKey);
public:
CGPIOin();
// void setMode(GPIOinModes mode) { _Mode = mode; };
// void begin(int pin1, int pin2, GPIOinModes mode, int activeState);
void setMode(GPIOin1Modes mode1, GPIOin2Modes mode2) { _Mode1 = mode1; _Mode2 = mode2; };
void begin(int pin1, int pin2, GPIOin1Modes mode1, GPIOin2Modes mode2, int activeState);
void setMode(CGPIOin1::Modes mode1, CGPIOin2::Modes mode2) { _Input1.setMode(mode1); _Input2.setMode(mode2); };
void begin(int pin1, int pin2, CGPIOin1::Modes mode1, CGPIOin2::Modes mode2, int activeState);
void manage();
uint8_t getState(int channel);
GPIOin1Modes getMode1() const;
GPIOin2Modes getMode2() const;
CGPIOin1::Modes getMode1() const;
CGPIOin2::Modes getMode2() const;
void simulateKey(uint8_t newKey);
bool usesExternalThermostat() const {
// return (_Mode == GPIOinOnHold1) || (_Mode == GPIOinExtThermostat2);
return (_Mode2 == GPIOin2ExtThermostat);
return (_Input2.getMode() == CGPIOin2::Thermostat);
};
};
class CGPIOout {
// GPIOoutModes _Mode;
GPIOout1Modes _Mode1;
GPIOout2Modes _Mode2;
class CGPIOout1 {
public:
enum Modes {
Disabled,
Status,
User
};
CGPIOout1();
void begin(int pin, Modes mode);
void setMode(Modes mode);
void manage();
void setState(bool state);
bool getState();
Modes getMode() const;
private:
Modes _Mode;
int _pin;
void _doStatus();
void _doUser1();
void _doUser2();
int _pins[2];
void _doUser();
int _prevState;
int _statusState;
int _statusDelay;
unsigned long _breatheDelay;
uint8_t _userState;
bool _userState;
void _doStartMode();
void _doStopMode();
void _doSuspendMode();
};
class CGPIOout2 {
public:
enum Modes {
Disabled,
User
};
CGPIOout2();
void begin(int pin, Modes mode);
void setMode(Modes mode);
void manage();
void setState(bool state);
bool getState();
Modes getMode() const;
private:
Modes _Mode;
int _pin;
bool _userState;
void _doUser();
};
class CGPIOout {
CGPIOout1 _Out1;
CGPIOout2 _Out2;
public:
CGPIOout();
// void setMode(GPIOoutModes mode);
// void begin(int pin1, int pin2, GPIOoutModes mode);
void setMode(GPIOout1Modes mode1, GPIOout2Modes mode2);
void begin(int pin1, int pin2, GPIOout1Modes mode1, GPIOout2Modes mode2);
void setMode(CGPIOout1::Modes mode1, CGPIOout2::Modes mode2);
void begin(int pin1, int pin2, CGPIOout1::Modes mode1, CGPIOout2::Modes mode2);
void manage();
void setState(int channel, bool state);
bool getState(int channel);
// GPIOoutModes getMode() const;
GPIOout1Modes getMode1() const;
GPIOout2Modes getMode2() const;
CGPIOout1::Modes getMode1() const;
CGPIOout2::Modes getMode2() const;
};
class CGPIOalg {
GPIOalgModes _Mode;
float _expMean;
adc1_channel_t _pin;
public:
enum Modes {
Disabled, // Unmodified V2.0 PCBs must use this - ADC2 / Wifi unresolvable conflict
HeatDemand,
};
CGPIOalg();
void begin(adc1_channel_t pin, GPIOalgModes mode);
void begin(adc1_channel_t pin, Modes mode);
void manage();
int getValue();
GPIOalgModes getMode() const;
Modes getMode() const;
private:
Modes _Mode;
float _expMean;
adc1_channel_t _pin;
};
struct sGPIOparams {
CGPIOin1::Modes in1Mode;
CGPIOin2::Modes in2Mode;
CGPIOout1::Modes out1Mode;
CGPIOout2::Modes out2Mode;
CGPIOalg::Modes algMode;
};
struct sGPIO {
bool outState[2];
bool inState[2];
int algVal;
// GPIOoutModes outMode;
// GPIOinModes inMode;
GPIOout1Modes out1Mode;
GPIOout2Modes out2Mode;
GPIOin1Modes in1Mode;
GPIOin2Modes in2Mode;
GPIOalgModes algMode;
CGPIOout1::Modes out1Mode;
CGPIOout2::Modes out2Mode;
CGPIOin1::Modes in1Mode;
CGPIOin2::Modes in2Mode;
CGPIOalg::Modes algMode;
sGPIO& operator=(const sGPIO& rhs) {
outState[0] = rhs.outState[0];
outState[1] = rhs.outState[1];

View File

@ -345,42 +345,39 @@ sUserSettings::load()
validatedLoad("cyclicStop", cyclic.Stop, 0, s8inBounds, 0, 10);
validatedLoad("cyclicStart", cyclic.Start, -1, s8inBounds, -20, 0);
uint8_t tVal;
// validatedLoad("GPIOinMode", tVal, 0, u8inBounds, 0, 4); GPIO.inMode = (GPIOinModes)tVal;
validatedLoad("GPIOinMode", tVal, 0, u8inBounds, 0, 255);
if(tVal <= 4) {
// migrate old GPIO input mode
GPIO.in1Mode = GPIOin1None;
GPIO.in2Mode = GPIOin2None;
GPIO.in1Mode = CGPIOin1::Disabled;
GPIO.in2Mode = CGPIOin2::Disabled;
switch(tVal) {
case 1: GPIO.in1Mode = GPIOin1On; GPIO.in2Mode = GPIOin2Off; break;
case 2: GPIO.in1Mode = GPIOin1Hold; GPIO.in2Mode = GPIOin2ExtThermostat; break;
case 3: GPIO.in1Mode = GPIOin1OnOff; break;
case 4: GPIO.in2Mode = GPIOin2ExtThermostat; break;
case 1: GPIO.in1Mode = CGPIOin1::On; GPIO.in2Mode = CGPIOin2::Off; break;
case 2: GPIO.in1Mode = CGPIOin1::Hold; GPIO.in2Mode = CGPIOin2::Thermostat; break;
case 3: GPIO.in1Mode = CGPIOin1::OnOff; break;
case 4: GPIO.in2Mode = CGPIOin2::Thermostat; break;
}
preferences.putUChar("GPIOinMode", 0xff); // cancel old
preferences.putUChar("GPIOin1Mode", GPIO.in1Mode); // set new
preferences.putUChar("GPIOin2Mode", GPIO.in2Mode); // set new
}
validatedLoad("GPIOin1Mode", tVal, 0, u8inBounds, 0, 3); GPIO.in1Mode = (GPIOin1Modes)tVal;
validatedLoad("GPIOin2Mode", tVal, 0, u8inBounds, 0, 2); GPIO.in2Mode = (GPIOin2Modes)tVal;
// validatedLoad("GPIOoutMode", tVal, 0, u8inBounds, 0, 2); GPIO.outMode = (GPIOoutModes)tVal;
validatedLoad("GPIOin1Mode", tVal, 0, u8inBounds, 0, 3); GPIO.in1Mode = (CGPIOin1::Modes)tVal;
validatedLoad("GPIOin2Mode", tVal, 0, u8inBounds, 0, 2); GPIO.in2Mode = (CGPIOin2::Modes)tVal;
validatedLoad("GPIOoutMode", tVal, 0, u8inBounds, 0, 255);
if(tVal <= 2) {
// migrate old GPIO output mode
GPIO.out1Mode = GPIOout1None;
GPIO.out2Mode = GPIOout2None;
GPIO.out1Mode = CGPIOout1::Disabled;
GPIO.out2Mode = CGPIOout2::Disabled;
switch(tVal) {
case 0: GPIO.out1Mode = GPIOout1None; GPIO.out2Mode = GPIOout2None; break;
case 1: GPIO.out1Mode = GPIOout1Status; GPIO.out2Mode = GPIOout2None; break;
case 2: GPIO.out1Mode = GPIOout1User; GPIO.out2Mode = GPIOout2User; break;
case 1: GPIO.out1Mode = CGPIOout1::Status; break;
case 2: GPIO.out1Mode = CGPIOout1::User; GPIO.out2Mode = CGPIOout2::User; break;
}
preferences.putUChar("GPIOoutMode", 0xff); // cancel old
preferences.putUChar("GPIOout1Mode", GPIO.out1Mode); // set new
preferences.putUChar("GPIOout2Mode", GPIO.out2Mode); // set new
}
validatedLoad("GPIOout1Mode", tVal, 0, u8inBounds, 0, 2); GPIO.out1Mode = (GPIOout1Modes)tVal;
validatedLoad("GPIOout2Mode", tVal, 0, u8inBounds, 0, 1); GPIO.out2Mode = (GPIOout2Modes)tVal;
validatedLoad("GPIOalgMode", tVal, 0, u8inBounds, 0, 2); GPIO.algMode = (GPIOalgModes)tVal;
validatedLoad("GPIOout1Mode", tVal, 0, u8inBounds, 0, 2); GPIO.out1Mode = (CGPIOout1::Modes)tVal;
validatedLoad("GPIOout2Mode", tVal, 0, u8inBounds, 0, 1); GPIO.out2Mode = (CGPIOout2::Modes)tVal;
validatedLoad("GPIOalgMode", tVal, 0, u8inBounds, 0, 2); GPIO.algMode = (CGPIOalg::Modes)tVal;
validatedLoad("MenuOnTimeout", HomeMenu.onTimeout, 0, u8inBounds, 0, 3);
validatedLoad("MenuonStart", HomeMenu.onStart, 0, u8inBounds, 0, 3);
validatedLoad("MenuonStop", HomeMenu.onStop, 0, u8inBounds, 0, 3);

View File

@ -286,11 +286,11 @@ struct sUserSettings : public CESP32_NVStorage {
useThermostat = 1;
enableWifi = 1;
enableOTA = 1;
GPIO.in1Mode = GPIOin1None;
GPIO.in2Mode = GPIOin2None;
GPIO.out1Mode = GPIOout1None;
GPIO.out2Mode = GPIOout2None;
GPIO.algMode = GPIOalgNone;
GPIO.in1Mode = CGPIOin1::Disabled;
GPIO.in2Mode = CGPIOin2::Disabled;
GPIO.out1Mode = CGPIOout1::Disabled;
GPIO.out2Mode = CGPIOout2::Disabled;
GPIO.algMode = CGPIOalg::Disabled;
FrameRate = 1000;
cyclic.init();
HomeMenu.init();