#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);
enum menuStates
{
ST_INIT = 0,
ST_MAIN,
ST_WIPE
};
enum menuReturns
{
MN_CONTINUE = 0,
MN_DONE
};
enum swReturns_e
{
NO_SW = 0,
UP,
DN,
SEL
};
const uint32_t BLNK_LEDDLY = 250ul;
const uint32_t BLNK_BIGDLY = 2000ul;
const uint8_t
grSwReturns[] = {NO_SW, UP, DN, SEL};
const uint8_t
grControlButtons[3] = {2, 3, 4};
const uint8_t pinLED = LED_BUILTIN;
bool bBlinkEnable = false;
uint8_t grPinLasts[3];
uint8_t numBlinks = 10;
typedef uint8_t (*pFunc_t)(uint8_t);
pFunc_t activeFunc;
uint8_t readButtons(void)
{
static uint8_t
idx = 0;
static uint32_t
tRead = 0ul;
uint32_t
tNow = millis();
uint8_t
retval,
swNow;
retval = NO_SW;
if (tNow - tRead >= 10ul)
{
tRead = tNow;
swNow = digitalRead(grControlButtons[idx]);
if (swNow != grPinLasts[idx])
{
grPinLasts[idx] = swNow;
if (swNow == LOW)
retval = grSwReturns[idx + 1];
}
idx++;
if (idx == 3)
idx = 0;
}
return retval;
}
void doLED(void)
{
static bool
lastEnable = bBlinkEnable;
static uint8_t
nBlinks = 10,
bLEDState = false;
static uint32_t
tBlink = 0ul,
tDelay = BLNK_BIGDLY;
uint32_t
tNow = millis();
if ((tNow - tBlink) < tDelay || bBlinkEnable == false)
return;
if (lastEnable != bBlinkEnable)
{
lastEnable = bBlinkEnable;
if (bBlinkEnable == true)
nBlinks = numBlinks;
}
tBlink = tNow;
bLEDState ^= true;
digitalWrite(pinLED, bLEDState ? HIGH : LOW);
tDelay = BLNK_LEDDLY;
if (bLEDState == false)
{
nBlinks--;
if (nBlinks == 0)
{
tDelay = BLNK_BIGDLY;
nBlinks = numBlinks;
}
}
}
bool WipeMenu(void)
{
static uint8_t
col = 0;
static uint32_t
tChar = 0ul;
uint32_t
tNow = micros();
if (tNow - tChar >= 15000ul)
{
tChar = tNow;
for (uint8_t i = 0; i < 2; i++)
{
lcd.setCursor(col, i);
lcd.print(F(" "));
}
col++;
if (col == 16)
{
col = 0;
return true;
}
}
return false;
}
void mnMainPage(uint8_t ctlButton)
{
static int8_t
highlight = 0;
static uint8_t
state = ST_INIT;
switch (state)
{
case ST_INIT:
lcd.clear();
lcd.setCursor(1, 0);
lcd.print(F("Set#LEDblnk"));
lcd.setCursor(1, 1);
lcd.print(F("TglLEDblnk"));
highlight = 0;
lcd.setCursor(0, highlight);
lcd.print(F(">"));
state = ST_MAIN;
break;
case ST_MAIN:
switch (ctlButton)
{
case UP:
lcd.setCursor(0, highlight);
lcd.print(F(" "));
highlight--;
if (highlight < 0)
highlight = 1;
lcd.setCursor(0, highlight);
lcd.print(F(">"));
break;
case DN:
lcd.setCursor(0, highlight);
lcd.print(F(" "));
highlight++;
if (highlight > 1)
highlight = 0;
lcd.setCursor(0, highlight);
lcd.print(F(">"));
break;
case SEL:
state = ST_WIPE;
break;
}
break;
case ST_WIPE:
if (WipeMenu() == true)
{
activeFunc = (highlight == 0) ? &mnSetNumBlinks : &mnEnableBlinks;
state = ST_INIT;
}
break;
}
}
void mnSetNumBlinks(uint8_t ctlButton)
{
char
szStr[10];
static int8_t
highlight = 0;
static uint8_t
state = ST_INIT;
switch (state)
{
case ST_INIT:
lcd.clear();
lcd.setCursor(1, 0);
lcd.print(F("Set#Blinks"));
lcd.setCursor(4, 1);
sprintf(szStr, "%3d", numBlinks);
lcd.print(szStr);
state = ST_MAIN;
break;
case ST_MAIN:
switch (ctlButton)
{
case UP:
if (numBlinks < 255)
numBlinks++;
lcd.setCursor(4, 1);
sprintf(szStr, "%3d", numBlinks);
lcd.print(szStr);
break;
case DN:
if (numBlinks > 10)
numBlinks--;
lcd.setCursor(4, 1);
sprintf(szStr, "%3d", numBlinks);
lcd.print(szStr);
break;
case SEL:
state = ST_WIPE;
break;
}
break;
case ST_WIPE:
if (WipeMenu() == true)
{
activeFunc = &mnMainPage;
state = ST_INIT;
}
break;
}
}
void mnEnableBlinks(uint8_t ctlButton)
{
char
szStr[10];
static int8_t
highlight = 0;
static uint8_t
state = ST_INIT;
switch (state)
{
case ST_INIT:
lcd.clear();
lcd.setCursor(1, 0);
lcd.print(F("Enable"));
lcd.setCursor(1, 1);
lcd.print(F("Disable"));
highlight = 0;
lcd.setCursor(0, highlight);
lcd.print(F(">"));
state = ST_MAIN;
break;
case ST_MAIN:
switch (ctlButton)
{
case UP:
lcd.setCursor(0, highlight);
lcd.print(F(" "));
highlight--;
if (highlight < 0)
highlight = 1;
lcd.setCursor(0, highlight);
lcd.print(F(">"));
break;
case DN:
lcd.setCursor(0, highlight);
lcd.print(F(" "));
highlight++;
if (highlight > 1)
highlight = 0;
lcd.setCursor(0, highlight);
lcd.print(F(">"));
break;
case SEL:
state = ST_WIPE;
break;
}
break;
case ST_WIPE:
if (WipeMenu() == true)
{
activeFunc = &mnMainPage;
bBlinkEnable = (highlight == 0) ? true : false;
state = ST_INIT;
}
break;
}
}
void setup()
{
for (uint8_t i = 0; i < 3; i++)
{
pinMode(grControlButtons[i], INPUT_PULLUP);
grPinLasts[i] = digitalRead(grControlButtons[i]);
}
lcd.init();
lcd.backlight();
pinMode(pinLED, OUTPUT);
activeFunc = &mnMainPage;
}
void loop()
{
doLED();
activeFunc(readButtons());
}