diff --git a/lib/matrix_orbital/AdafruitVfdDisplay.cpp b/lib/matrix_orbital/AdafruitVfdDisplay.cpp index 396a518..a0e3882 100644 --- a/lib/matrix_orbital/AdafruitVfdDisplay.cpp +++ b/lib/matrix_orbital/AdafruitVfdDisplay.cpp @@ -2,47 +2,60 @@ AdafruitVfdDisplay::AdafruitVfdDisplay(UART& lcdUart) : m_lcdUart{lcdUart} {} - void AdafruitVfdDisplay::createChar(uint8_t id, uint8_t* c) { + // todo: prolly doesnt work + uint8_t createChar[] = {0xfe, 0x4e, id}; + m_lcdUart.write_raw(createChar, sizeof(createChar)); + m_lcdUart.write_raw(c, 8); } void AdafruitVfdDisplay::drawBlinker() { - + uint8_t blockCursorOn[] = {0xfe, 0x53}; + m_lcdUart.write_raw(blockCursorOn, sizeof(blockCursorOn)); } void AdafruitVfdDisplay::clearBlinker() { - + uint8_t blockCursorOff[] = {0xfe, 0x54}; + m_lcdUart.write_raw(blockCursorOff, sizeof(blockCursorOff)); } void AdafruitVfdDisplay::begin() { delay(500); clear(); + show(); + uint8_t noAutoScroll[] = {0xFE, 0x52}; + m_lcdUart.write_raw(noAutoScroll, sizeof(noAutoScroll)); } void AdafruitVfdDisplay::clear() { - uint8_t clearCmd[] = {0xfe, 0x58}; + uint8_t clearCmd[] = {0xfe, 0x58, 0xfe, 0x48}; m_lcdUart.write_raw(clearCmd, sizeof(clearCmd)); } void AdafruitVfdDisplay::show() { - + uint8_t dispOn[] = {0xfe, 42}; + m_lcdUart.write_raw(dispOn, sizeof(dispOn)); + uint8_t brightnessUp[] = {0xfe, 0x99, 100}; + m_lcdUart.write_raw(brightnessUp, sizeof(brightnessUp)); } void AdafruitVfdDisplay::hide() { - + uint8_t dispOff[] = {0xfe, 0x46}; + m_lcdUart.write_raw(dispOff, sizeof(dispOff)); } void AdafruitVfdDisplay::draw(uint8_t byte) { - + m_lcdUart.write(byte); } void AdafruitVfdDisplay::draw(const char* text) { - + m_lcdUart.write(text); } void AdafruitVfdDisplay::setCursor(uint8_t col, uint8_t row) { - + uint8_t setCursorCmd[] = {0xfe, 0x47, col+1, row+1}; + m_lcdUart.write_raw(setCursorCmd, sizeof(setCursorCmd)); } void AdafruitVfdDisplay::setBacklight(bool enabled) { diff --git a/lib/matrix_orbital/AdafruitVfdDisplay.hpp b/lib/matrix_orbital/AdafruitVfdDisplay.hpp index 2509145..b0f45e2 100644 --- a/lib/matrix_orbital/AdafruitVfdDisplay.hpp +++ b/lib/matrix_orbital/AdafruitVfdDisplay.hpp @@ -21,15 +21,24 @@ class AdafruitVfdDisplay : public CharacterDisplayInterface { void clearBlinker() override; void begin() override; void clear() override; + + /// @brief turn display on, showing previously displayed text void show() override; + + /// @brief turn display off so text is no longer visible (but still present). void hide() override; void draw(uint8_t byte) override; void draw(const char* text) override; + + /// @brief Move display cursor to specified position + /// TODO: 0 based or 1-based col/row position??? + /// @param col + /// @param row void setCursor(uint8_t col, uint8_t row) override; void setBacklight(bool enabled) override; private: - UART m_lcdUart; + UART &m_lcdUart; }; #endif /* __ADAFRUITVFDDISPINTERFACE_H__ */ diff --git a/lib/ui/TrainUi.hpp b/lib/ui/TrainUi.hpp new file mode 100644 index 0000000..a55fc99 --- /dev/null +++ b/lib/ui/TrainUi.hpp @@ -0,0 +1,74 @@ +/** \File TrainUi.hpp + * \copyright (c) 2025 len0rd + * \date 2025-02-09 + * + * Menu and LCD UI/rotary encoder for train controller + */ +#ifndef __TRAINUI_H__ +#define __TRAINUI_H__ +#include +#include +#include "AdafruitVfdDisplay.hpp" +#include "LcdMenu.h" +#include "Serial.h" +#include "input/SimpleRotaryAdapter.h" +#include "renderer/CharacterDisplayRenderer.h" + +MENU_SCREEN(mainScreen, + mainItems, + ITEM_BASIC("Item Eins"), + ITEM_BASIC("Item Zwei"), + ITEM_BASIC("Item Drei")); + +#define ROT_ENC_A_PIN PIN_D6 +#define ROT_ENC_B_PIN PIN_D7 +#define ROT_ENC_BUTTON_PIN PIN_D8 + +#define DISP_NUM_ROWS 2 +#define DISP_NUM_COLS 16 + +class TrainUi { + public: + TrainUi() + : m_lcdUart{_UART2_}, + m_disp(m_lcdUart), + m_renderer(&m_disp, DISP_NUM_COLS, DISP_NUM_ROWS), + m_menu(m_renderer), + m_rotEnc(ROT_ENC_A_PIN, ROT_ENC_B_PIN, ROT_ENC_BUTTON_PIN), + m_rotaryInput(&m_menu, &m_rotEnc) {} + + inline void setup() { + m_lcdUart.begin(57600); + while (!m_lcdUart) + ; + + // m_disp.show(); + // m_disp.clear(); + // m_disp.drawBlinker(); + m_renderer.begin(); + m_menu.setScreen(mainScreen); + } + + inline void loop() { + // m_disp.clear(); + // // uint8_t clearCmd[] = {0xfe, 0x58, 0xfe, 0x48}; + // // m_lcdUart.write_raw(clearCmd, sizeof(clearCmd)); + + // char toPrint[16] = {}; + // snprintf(toPrint, 16, "enc: %d %d", m_rotEnc.rotate(), m_rotEnc.push()); + // m_disp.draw(toPrint); + // m_lcdUart.print("howdy do"); + m_rotaryInput.observe(); + } + + private: + UART& m_lcdUart; + AdafruitVfdDisplay m_disp; + CharacterDisplayRenderer m_renderer; + LcdMenu m_menu; + + SimpleRotary m_rotEnc; + SimpleRotaryAdapter m_rotaryInput; +}; + +#endif /* __TRAINUI_H__ */ diff --git a/platformio.ini b/platformio.ini index 5dcfbf9..8079616 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,3 +16,4 @@ monitor_speed = 115200 lib_deps = mathertel/OneButton@^2.6.1 forntoh/LcdMenu@^5.6.0 + mprograms/SimpleRotary@^1.1.3 diff --git a/src/main.cpp b/src/main.cpp index 6a6bfa0..3125815 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "NvmEeprom.hpp" #include "SingleAxis.hpp" #include "OneButton.h" +#include "TrainUi.hpp" // joystick calibration #define TIME_CAL_1 2000 @@ -14,18 +15,22 @@ AlignedJoy joystick_1(PIN_A0, PIN_A1); /// X on A0, Y on A1 ArduinoLEDMatrix ledMatrix; LinearSingleAxis lever0(PIN_A2); -enum Button : size_t { - RED_BUTTON = 0, - // WHITE_BUTTON, +TrainUi s_ui; - NUM_BUTTONS, -}; +UART *uOut = nullptr; + +// enum Button : size_t { +// RED_BUTTON = 0, +// // WHITE_BUTTON, + +// NUM_BUTTONS, +// }; -OneButton s_buttons[Button::NUM_BUTTONS] = { - [Button::RED_BUTTON] = OneButton(PIN_D2, true, false), - // [Button::WHITE_BUTTON] = OneButton(PIN_D3), -}; +// OneButton s_buttons[Button::NUM_BUTTONS] = { +// [Button::RED_BUTTON] = OneButton(PIN_D2, true, false), +// // [Button::WHITE_BUTTON] = OneButton(PIN_D3), +// }; static_assert(sizeof(void*) == sizeof(size_t)); @@ -154,6 +159,8 @@ void setup() { Serial.println("Wait for serial connection..."); delay(5000); + s_ui.setup(); + // run joystick calibration if needed // bool calibrationInvalid = !nvm.valid(); // do { @@ -190,28 +197,30 @@ void setup() { // configure buttons - for (size_t ii = 0; ii < NUM_BUTTONS; ii++) { - s_buttons[ii].attachClick(buttonClickHandler, (void*)ii); - } + // for (size_t ii = 0; ii < NUM_BUTTONS; ii++) { + // s_buttons[ii].attachClick(buttonClickHandler, (void*)ii); + // } } int loopCount = 0; void loop() { - loopCount++; - if (loopCount >= 50) { - loopCount = 0; - // print joystick axes value - Serial.print("joystick_1 X -> "); - Serial.print(joystick_1.read(X)); - Serial.print(" | Y -> "); - Serial.println(joystick_1.read(Y)); - Serial.print("lever0: "); - Serial.println(lever0.readRaw()); - } - for (size_t ii = 0; ii < NUM_BUTTONS; ii++) { - s_buttons[ii].tick(); - } + s_ui.loop(); delay(10); + // loopCount++; + // if (loopCount >= 50) { + // loopCount = 0; + // // print joystick axes value + // Serial.print("joystick_1 X -> "); + // Serial.print(joystick_1.read(X)); + // Serial.print(" | Y -> "); + // Serial.println(joystick_1.read(Y)); + // Serial.print("lever0: "); + // Serial.println(lever0.readRaw()); + // } + // for (size_t ii = 0; ii < NUM_BUTTONS; ii++) { + // s_buttons[ii].tick(); + // } + // delay(10); }