From 721113ddcb2ca88c2119abc05ab37c3e333f3e62 Mon Sep 17 00:00:00 2001 From: Andrea Baccega Date: Sat, 27 Jan 2024 11:46:08 +0100 Subject: [PATCH] menu first work --- platformio.ini | 2 +- src/common.h | 1 + src/displays/menustatemachine.h | 128 +++++++++++++++++++++++ src/displays/oled.cpp | 175 ++++++++++++++++++-------------- src/displays/oled.h | 10 +- src/globals.h | 2 + src/leds/Leds.cpp | 1 + src/main.cpp | 77 +++++++------- 8 files changed, 272 insertions(+), 124 deletions(-) create mode 100644 src/displays/menustatemachine.h diff --git a/platformio.ini b/platformio.ini index d9f3887..d093c0c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,7 +12,7 @@ platform = atmelmegaavr board = ATmega4809 framework = arduino - +monitor_speed = 38400 upload_speed = 115200 board_hardware.uart = uart0 upload_protocol = arduino diff --git a/src/common.h b/src/common.h index b2b194b..8783f7c 100644 --- a/src/common.h +++ b/src/common.h @@ -50,6 +50,7 @@ template class Pair { public: + Pair(){}; Pair(First first, Second second) : first(first), second(second) {} First first; Second second; diff --git a/src/displays/menustatemachine.h b/src/displays/menustatemachine.h new file mode 100644 index 0000000..e212d82 --- /dev/null +++ b/src/displays/menustatemachine.h @@ -0,0 +1,128 @@ +#ifndef __OLEDSTATEMACHINE_H_ +#define __OLEDSTATEMACHINE_H_ +#include "../buttons/base.h" +#include "../common.h" +#include + + +class OledMenuItem { + public: + OledMenuItem(){}; + OledMenuItem(char *title): title(title), identifier(0) {}; + OledMenuItem(char *title, uint8_t identifier): title(title), identifier(identifier) {}; + + char const * title; + // Identifier c + uint8_t identifier; + + + +}; + +class OledMenu { + public: + OledMenu(){}; + OledMenu(uint8_t identifier): identifier(identifier), elementsLength(0), childrenLength(0) {}; + ~OledMenu() { + delete elements; + delete children; + delete childrenMatrix; + }; + uint8_t identifier; + + void setChildren(OledMenu **children, int length) { + this->children = children; + this->childrenLength = length; + for (int i=0; iparent = this; + } + } + + void setElements(OledMenuItem *elements, int length) { + this->elements = new OledMenuItem[length]; + + for (int i=0; ielements[i].title = malloc(strlen(elements[i].title) + 1); + memcpy(this->elements[i].title, elements[i].title, strlen(elements[i].title) + 1); + this->elements[i].identifier = elements[i].identifier; + + Serial.println(String(this->elements[i].title) + " " + String(elements[i].title)); + } + this->elementsLength = length; + } + + void setChildrenMatrix(int length, uint8_t (*matrix)[2]) { + this->childrenMatrix = matrix; + this->childrenMatrixLength = length; + } + + // To be invoked when the user presses the SELECT btn + // If null is returned then the menu should not be changed + OledMenu *getNextMenu() { + for (int i=0; i matrix[] = { CODE }; menuItem.setMatrix( sizeof(matrix)/sizeof(matrix[0]), matrix); } +#define UPBUTTON(index) Pair(ButtonKind::UP, index), +#define DOWNBUTTON(index) Pair(ButtonKind::DOWN, index), +#define SELECTBUTTON(index) Pair(ButtonKind::SELECT, index), +#define BACKBUTTON(index) Pair(ButtonKind::BACK, index), +// #define SETOLED_HANDLER(handler, CODE) { handler.buttonPressed = [](ButtonKind kind) -> OledInterfaceHandler* { CODE }; } +// #define BTNGOTOHANDLER(_kind, gotoHandler) if (kind == _kind) { return gotoHandler; } +// #define HANDLER_ONUP(gotoHandler) BTNGOTOHANDLER(ButtonKind::UP, gotoHandler) +// #define HANDLER_ONDOWN(gotoHandler) BTNGOTOHANDLER(ButtonKind::DOWN, gotoHandler) +// #define HANDLER_ONBACK(gotoHandler) BTNGOTOHANDLER(ButtonKind::BACK, gotoHandler) +// #define HANDLER_ONSELECT(gotoHandler) BTNGOTOHANDLER(ButtonKind::SELECT, gotoHandler) +// #define HANDLER_NULL return nullptr; + +#endif diff --git a/src/displays/oled.cpp b/src/displays/oled.cpp index 547bdfb..3c14ecb 100644 --- a/src/displays/oled.cpp +++ b/src/displays/oled.cpp @@ -1,9 +1,11 @@ #include "./oled.h" #include #include "../globals.h" +#include "./menustatemachine.h" #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) +#define MENUID_PLATERES 2 unsigned long lastProcessedReflowState = 0; OledDisplay::OledDisplay() @@ -12,8 +14,70 @@ OledDisplay::OledDisplay() display = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT); } +void OledDisplay::handleButtonStateChange(Pair> change) +{ + if (change.second.to == ButtonState::PRESSED) + { + if (change.first == ButtonKind::SELECT) + { + OledMenu *selectedMenu = curMenu->getNextMenu(); + if (selectedMenu != NULL) + { + curMenu = selectedMenu; + } + } else if (change.first == ButtonKind::BACK) { + OledMenu *selectedMenu = curMenu->parent; + if (selectedMenu != NULL) + { + curMenu = selectedMenu; + } + } else if (change.first == ButtonKind::UP) { + curMenu->goNextItem(); + } else if (change.first == ButtonKind::DOWN){ + curMenu->goPrevItem(); + } + } +} void OledDisplay::setup() { + curMenu = new OledMenu(); + curMenu->setElements(new OledMenuItem[3]{ + OledMenuItem("Reflow\0"), + OledMenuItem("PlateR\0"), + OledMenuItem("Temps\0"), + }, 3); + + OledMenu *pickProfilesMenu = new OledMenu(1); + OledMenuItem *pickProfilesMenuItems = new OledMenuItem[nReflowProfiles]; + for (int i=0; isetElements(pickProfilesMenuItems, nReflowProfiles); + + OledMenu *plateRMenu = new OledMenu(MENUID_PLATERES); + OledMenu *tempsMenu = new OledMenu(3); + tempsMenu->setElements(new OledMenuItem[6]{ + OledMenuItem("T1\0", 150), + OledMenuItem("T2\0", 151), + OledMenuItem("T3\0", 152), + OledMenuItem("T4\0", 153), + OledMenuItem("T5\0", 154), + OledMenuItem("T6\0", 155), + }, 6); + + curMenu->setChildren(new OledMenu*[3]{ + pickProfilesMenu, + plateRMenu, + tempsMenu, + }, 3); + curMenu->setChildrenMatrix(3, new uint8_t[3][2]{ + {0, 0}, + {1, 1}, + {2, 2}, + }); + + // curItem = 0; // ROOT + // Setup implementation bool initialized = display.begin(SSD1306_SWITCHCAPVCC, 0x3C); if (!initialized) @@ -25,51 +89,37 @@ void OledDisplay::setup() Serial.println("OLED Display initialized"); } display.setRotation(0); - display.setCursor(0, 0); - display.setTextSize(2); display.setTextColor(SSD1306_WHITE); // Defaults to white - } void OledDisplay::loop() { - StateChangeEvent *evt = reflowProcessState.getSince(lastProcessedReflowState); - // REdraw only on reflow state change - if (evt != NULL) + ReflowProcessState state = reflowProcessState.get(); + if (state == USER_INPUT) { - lastProcessedReflowState = millis(); - ReflowProcessState reflowState = reflowProcessState.get(); - if (reflowState == USER_INPUT) - { - handleUserInputState(); - return; - } - else if (reflowState == SOAK) - { - handleSoakState(); - return; - } - else if (reflowState == REFLOW) - { - handleReflowState(); - return; - } - else if (reflowState == ReflowProcessState::COOL) - { - handleCoolingState(); - return; - } - else if (reflowState == ReflowProcessState::DONE) - { - handleFinishedState(); - return; - } - } + display.clearDisplay(); + display.setTextSize(2); - if (reflowProcessState.get() == PREHEAT) - { - drawDebug(); + OledMenuItem menuItem = curMenu->getCurItem(); + display.setTextSize(2); + if (curMenu->identifier == MENUID_PLATERES) { + + } else { + + // draw menu item with selectors. + + display.setRotation(0); + centerText(menuItem.title); + display.setRotation(1); + display.setCursor(0,SCREEN_WIDTH/2-5); + display.print("<"); + display.setCursor(SCREEN_HEIGHT-14,SCREEN_WIDTH/2-5); + display.print(">"); + + } + + display.display(); } // Loop implementation } @@ -96,35 +146,24 @@ void OledDisplay::drawDebug() display.display(); } +void OledDisplay::centerText(const char *txt) +{ + int16_t x1, y1; + uint16_t w, h; + display.getTextBounds(txt, 0, 0, &x1, &y1, &w, &h); + display.setCursor(display.width() / 2 - w / 2, display.height() / 2 -h/2); + + display.println(txt); +} + void OledDisplay::handleUserInputState() { - Serial.println("USER_INPUT_STATE"); display.clearDisplay(); - display.setCursor(0, 0); + display.setCursor(0, SCREEN_HEIGHT / 2 + 10); display.setTextSize(2); - display.println("INPUT_STATE"); display.display(); } - -void OledDisplay::handlePreheatState() -{ - display.clearDisplay(); - display.setCursor(0, 0); - - display.println("PREHEATING"); - display.display(); -} - -void OledDisplay::handleSoakState() -{ - display.clearDisplay(); - display.setCursor(0, 0); - - display.println("SOAKING"); - display.display(); -} - void OledDisplay::handleReflowState() { display.clearDisplay(); @@ -133,21 +172,3 @@ void OledDisplay::handleReflowState() display.println("REFLOW"); display.display(); } - -void OledDisplay::handleCoolingState() -{ - display.clearDisplay(); - display.setCursor(0, 0); - - display.println("COOLING"); - display.display(); -} - -void OledDisplay::handleFinishedState() -{ - display.clearDisplay(); - display.setCursor(0, 0); - - display.println("Done :)"); - display.display(); -} \ No newline at end of file diff --git a/src/displays/oled.h b/src/displays/oled.h index 43ed50f..4bcb48f 100644 --- a/src/displays/oled.h +++ b/src/displays/oled.h @@ -2,22 +2,24 @@ #define __oled_h #include #include "../reflow.h" +#include "menustatemachine.h" + class OledDisplay { public: OledDisplay(); void setup(); void loop(); void teardown(); + void handleButtonStateChange(Pair> change); private: + OledMenu *curMenu; Adafruit_SSD1306 display; void drawDebug(); void handleUserInputState(); - void handlePreheatState(); - void handleSoakState(); void handleReflowState(); - void handleCoolingState(); - void handleFinishedState(); + + void centerText(const char * text); }; diff --git a/src/globals.h b/src/globals.h index 348e58d..6c831a9 100644 --- a/src/globals.h +++ b/src/globals.h @@ -12,4 +12,6 @@ extern Thermistor thermistor3; extern Thermistor thermistor4; extern Thermistor thermistor5; extern Thermistor thermistor6; +extern ReflowProfile reflowProfiles[]; +extern int nReflowProfiles; #endif \ No newline at end of file diff --git a/src/leds/Leds.cpp b/src/leds/Leds.cpp index 943f966..1279280 100644 --- a/src/leds/Leds.cpp +++ b/src/leds/Leds.cpp @@ -19,6 +19,7 @@ void LEDS::handleButtonStateChange(Pair