/*
MIT License
Copyright (c) 2022 MicroBeaut
*/
#include <MicroBeaut.h>
#include <LiquidCrystal_I2C.h>
#include "IQueue.h"
//
class Menu {
public:
char Name[10] = "";
float Duration = 0.0f;
public:
Menu() {}
Menu(String const& name, float durationSeconds) {
name.toCharArray(Name, 10);
Duration = durationSeconds > 0 ? durationSeconds : 0.0f;
}
};
Menu myMenu[] = { Menu("Potato", 2.0f)
, Menu("Sandwich", 3.0f)
, Menu("Burger", 4.0f)
, Menu("Chicken", 5.0f)
};
const int inputPin[] = {9, 8, 7, 6}; //
#define cookingLEDPin 12
#define readyLEDPin 11
#define newLEDPin 10
LiquidCrystal_I2C myLCD(0x27, 20, 4);
const String menuList[4] = {"OInQ.: ", "NextQ: ", "CurrQ: ", "Cooki: "};
String lcdBuffer[4];
MicroBeaut_TimeSchedule tslcdDisplay;
const float displayInterval = 0.05; // 100 miliseconds
const bool initialAddQ = false;
const int maxQueue = 36;
MicroBeaut_IQueue<Menu> order(maxQueue);
MicroBeaut_Rising reInput[4];
float remainingTime;
MicroBeaut_TimerOn cookingTimer;
MicroBeaut_TimerOff readyTimer;
MicroBeaut_TimerOff newTimer;
MicroBeaut_Blink blinkStatus;
void Cooking();
void RaiseOrder();
void QueueChanged(Menu m, QueueEventArgs e);
void setup() {
Serial.begin(115200);
myLCD.init();
myLCD.backlight();
tslcdDisplay.Config(displayInterval, LCDDisplay);
for (int index = 0 ; index < sizeof(inputPin) / sizeof(int) ; index++) {
pinMode(inputPin[index], INPUT_PULLUP);
}
pinMode(cookingLEDPin, OUTPUT);
pinMode(readyLEDPin, OUTPUT);
pinMode(newLEDPin, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
for (int index = 0 ; index < initialAddQ && order.Length /*sizeof(myMenu)/sizeof(Menu)*/ ; index++) {
order.Enqueue(myMenu[random(0, 3)]);
}
order.EventOnChanged = QueueChanged;
ReadQueue();
Cokking();
LCDDisplay();
blinkStatus.SetTimeDelay(0.5, 0.5);
readyTimer.SetTimeDelay(1.0);
newTimer.SetTimeDelay(0.25);
delay(1000);
}
void loop() {
tslcdDisplay.Run();
RaiseOrder(); // Raise an Order
ReadQueue(); // Update LCD Buffer
Cokking();
blinkStatus.Blink(true);
readyTimer.TimerOff(false);
newTimer.TimerOff(false);
digitalWrite(LED_BUILTIN, blinkStatus.Output());
}
void RaiseOrder() {
for (int index = 0 ; index < sizeof(inputPin) / sizeof(int) ; index++) {
if (reInput[index].Rising(!digitalRead(inputPin[index]))) {
order.Enqueue(myMenu[index]);
}
}
}
void Cokking() {
int count = order.Count;
if (!order.IsEmpty() ) {
digitalWrite(cookingLEDPin, blinkStatus.Output());
Menu currOrder = order.Peek();
cookingTimer.SetTimeDelay(currOrder.Duration);
cookingTimer.TimerOn(true);
if (cookingTimer.Output()) {
cookingTimer.TimerOn(false);
order.Dequeue();
}
remainingTime = cookingTimer.GetTimeDelay() - cookingTimer.GetElapsedTime();
}
else {
remainingTime = 0.0;
digitalWrite(cookingLEDPin, 0);
}
digitalWrite(readyLEDPin, blinkStatus.Output() & readyTimer.Output());
digitalWrite(newLEDPin, blinkStatus.Output() & newTimer.Output());
}
void ReadQueue() {
Menu currOrder;
Menu nexOrder;
int count = order.Count;
// Get Current Queue
if (count > 0) {
currOrder = order.Peek();
}
// Get Next Queue
if (count > 1) {
nexOrder = order[1];
}
// Set LCD Information to Buffers : 13 characters per Line (7 charactors Reserved for Title)
lcdBuffer[0] = PadMid(String(count), "(MQ" + String(order.Length) + ")", 13, ' ' );
lcdBuffer[1] = PadMid(nexOrder.Name, (order.Count > 1 ? " " + String(nexOrder.Duration, 1) + "s" : "-"), 13, ' ');
lcdBuffer[2] = PadMid(currOrder.Name, (order.Count > 0 ? " " + String(currOrder.Duration, 1) + "s" : "-"), 13, ' ');
lcdBuffer[3] = PadMid(order.Count > 0 ? (blinkStatus.Output() == 1 ? (String)currOrder.Name + " " : "") : " ", order.Count > 0 ? String(remainingTime, 1) + "s" : "-", 13, ' ');
}
void QueueChanged(Menu m, QueueEventArgs e) {
switch (e) {
case OnEnqueue:
newTimer.TimerOff(true);
Serial.println("Enqueue: " + String(m.Name) + " New Order!");
break;
case OnDequeue:
readyTimer.TimerOff(true);
Serial.println("Dequeue: " + String(m.Name) + " Ready to serve!");
break;
};
}
void LCDDisplay() {
String strLCD = "";
for (int index = 0 ; index < 4 ; index++) {
myLCD.setCursor(0, index);
strLCD = menuList[index];
strLCD = strLCD + lcdBuffer[index];
myLCD.print(strLCD);
}
}
// Return string by padding charecter on the Left and the Right of the String
String Pad(String oldString, int length, char paddingChar) {
int lenPad = length - oldString.length();
int lenPadLeft = lenPad / 2;
int lenPadRight = lenPad - lenPadLeft;
for (int index = 0; index < lenPadLeft || index < lenPadRight; index++) {
if (index < lenPadLeft) oldString = paddingChar + oldString;
if (index < lenPadRight) oldString += paddingChar;
}
return oldString;
}
// return string by padding charecter on the Right of the String
String PadRight(String oldString, int length, char paddingChar) {
int lenPad = length - oldString.length();
for (int index = 0; index < lenPad; index++) {
oldString += paddingChar;
}
return oldString;
}
// return string by padding charecter in the middle of 2 strings
String PadMid(String leftString, String rightString, int length, char paddingChar) {
int lenPad = length - leftString.length() - rightString.length();
for (int index = 0; index < lenPad; index++) {
leftString += paddingChar;
}
return (leftString + rightString);
}