diff --git a/include/peripherals/Display.h b/include/peripherals/Display.h index 9f7d2ac..7a7821e 100644 --- a/include/peripherals/Display.h +++ b/include/peripherals/Display.h @@ -3,6 +3,7 @@ #include "usb/usb_driver.h" #include "utils/InputState.h" +#include "utils/Menu.h" #include @@ -33,6 +34,8 @@ class Display { usb_mode_t m_usb_mode; uint8_t m_player_id; + Utils::Menu::State m_menu_state; + ssd1306_t m_display; void drawIdleScreen(); @@ -45,6 +48,8 @@ class Display { void setUsbMode(usb_mode_t mode); void setPlayerId(uint8_t player_id); + void setMenuState(const Utils::Menu::State &menu_state); + void showIdle(); void showMenu(); diff --git a/src/main.cpp b/src/main.cpp index 4d269e1..3637c22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,7 @@ using namespace Doncon; queue_t control_queue; +queue_t menu_display_queue; queue_t drum_input_queue; queue_t controller_input_queue; @@ -24,6 +25,8 @@ enum class ControlCommand { SetUsbMode, SetPlayerLed, SetLedBrightness, + EnterMenu, + ExitMenu, }; struct ControlMessage { @@ -49,9 +52,15 @@ void core1_task() { Peripherals::Display display(Config::Default::display_config); Utils::InputState input_state; + Utils::Menu::State menu_display_msg; ControlMessage control_msg; while (true) { + buttons.updateInputState(input_state); + + queue_try_add(&controller_input_queue, &input_state.controller); + queue_try_remove(&drum_input_queue, &input_state.drum); + if (queue_try_remove(&control_queue, &control_msg)) { switch (control_msg.command) { case ControlCommand::SetUsbMode: @@ -66,13 +75,17 @@ void core1_task() { case ControlCommand::SetLedBrightness: led.setBrightness(control_msg.data.brightness); break; + case ControlCommand::EnterMenu: + display.showMenu(); + break; + case ControlCommand::ExitMenu: + display.showIdle(); + break; } } - - buttons.updateInputState(input_state); - - queue_try_add(&controller_input_queue, &input_state.controller); - queue_try_remove(&drum_input_queue, &input_state.drum); + if (queue_try_remove(&menu_display_queue, &menu_display_msg)) { + display.setMenuState(menu_display_msg); + } led.setInputState(input_state); display.setInputState(input_state); @@ -86,6 +99,7 @@ void core1_task() { int main() { queue_init(&control_queue, sizeof(ControlMessage), 1); + queue_init(&menu_display_queue, sizeof(Utils::Menu::State), 1); queue_init(&drum_input_queue, sizeof(Utils::InputState::Drum), 1); queue_init(&controller_input_queue, sizeof(Utils::InputState::Controller), 1); multicore_launch_core1(core1_task); @@ -125,13 +139,13 @@ int main() { if (menu.active()) { menu.update(input_state.controller); if (menu.active()) { - // auto display_msg = menu.getState(); - // queue_add_blocking(&menu_display_queue, &display_msg); + auto display_msg = menu.getState(); + queue_add_blocking(&menu_display_queue, &display_msg); } else { settings_store->store(); - // ControlMessage ctrl_message = {ControlCommand::ExitMenu, {}}; - // queue_add_blocking(&control_queue, &ctrl_message); + ControlMessage ctrl_message = {ControlCommand::ExitMenu, {}}; + queue_add_blocking(&control_queue, &ctrl_message); } readSettings(); @@ -139,8 +153,8 @@ int main() { } else if (input_state.checkHotkey()) { menu.activate(); - // ControlMessage ctrl_message{ControlCommand::EnterMenu, {}}; - // queue_add_blocking(&control_queue, &ctrl_message); + ControlMessage ctrl_message{ControlCommand::EnterMenu, {}}; + queue_add_blocking(&control_queue, &ctrl_message); } else { usb_driver_send_and_receive_report(input_state.getReport(mode)); } diff --git a/src/peripherals/Display.cpp b/src/peripherals/Display.cpp index 4b19ea2..c44f278 100644 --- a/src/peripherals/Display.cpp +++ b/src/peripherals/Display.cpp @@ -176,6 +176,8 @@ void Display::setInputState(const Utils::InputState &state) { m_input_state = st void Display::setUsbMode(usb_mode_t mode) { m_usb_mode = mode; }; void Display::setPlayerId(uint8_t player_id) { m_player_id = player_id; }; +void Display::setMenuState(const Utils::Menu::State &menu_state) { m_menu_state = menu_state; } + void Display::showIdle() { m_state = State::Idle; } void Display::showMenu() { m_state = State::Menu; } @@ -220,9 +222,77 @@ void Display::drawIdleScreen() { if (m_input_state.drum.ka_right.triggered) { ssd1306_bmp_show_image_with_offset(&m_display, ka_r_bmp.data(), ka_r_bmp.size(), 64 - 26, 12); } + // Player "LEDs" + if (m_player_id != 0) { + for (uint8_t i = 0; i < 4; ++i) { + if (m_player_id & (1 << i)) { + ssd1306_draw_square(&m_display, ((127) - ((4 - i) * 6)) - 1, 2, 4, 4); + } else { + ssd1306_draw_square(&m_display, (127) - ((4 - i) * 6), 3, 2, 2); + } + } + } + + // Menu hint + ssd1306_draw_line(&m_display, 0, 54, 128, 54); + ssd1306_draw_string(&m_display, 0, 56, 1, "Hold STA+SEL for Menu"); } -void Display::drawMenuScreen() {} +void Display::drawMenuScreen() { + auto descriptor_it = Utils::Menu::descriptors.find(m_menu_state.page); + if (descriptor_it == Utils::Menu::descriptors.end()) { + return; + } + + // Background + switch (descriptor_it->second.type) { + case Utils::Menu::Descriptor::Type::Root: + // ssd1306_bmp_show_image(&m_display, menu_screen_top.data(), menu_screen_top.size()); + break; + case Utils::Menu::Descriptor::Type::Selection: + case Utils::Menu::Descriptor::Type::Value: + // ssd1306_bmp_show_image(&m_display, menu_screen_sub.data(), menu_screen_sub.size()); + break; + case Utils::Menu::Descriptor::Type::RebootInfo: + break; + } + + // Heading + ssd1306_draw_string(&m_display, 0, 0, 1, descriptor_it->second.name.c_str()); + + // Current Selection + std::string selection; + switch (descriptor_it->second.type) { + case Utils::Menu::Descriptor::Type::Root: + case Utils::Menu::Descriptor::Type::Selection: + case Utils::Menu::Descriptor::Type::RebootInfo: + selection = descriptor_it->second.items.at(m_menu_state.selection).first; + break; + case Utils::Menu::Descriptor::Type::Value: + selection = std::to_string(m_menu_state.selection); + break; + } + ssd1306_draw_string(&m_display, (127 - (selection.length() * 12)) / 2, 15, 2, selection.c_str()); + + // Breadcrumbs + switch (descriptor_it->second.type) { + case Utils::Menu::Descriptor::Type::Root: + case Utils::Menu::Descriptor::Type::Selection: { + auto selection_count = descriptor_it->second.items.size(); + for (uint8_t i = 0; i < selection_count; ++i) { + if (i == m_menu_state.selection) { + ssd1306_draw_square(&m_display, ((127) - ((selection_count - i) * 6)) - 1, 2, 4, 4); + } else { + ssd1306_draw_square(&m_display, (127) - ((selection_count - i) * 6), 3, 2, 2); + } + } + } break; + case Utils::Menu::Descriptor::Type::RebootInfo: + break; + case Utils::Menu::Descriptor::Type::Value: + break; + } +} void Display::update() { static const uint32_t interval_ms = 17; // Limit to ~60fps