Rework Menu

- Live preview of all settings
- Settings will be applied with 'Select/Apply' or reset with 'Back'
- DS4 player color can be en-/disabled
This commit is contained in:
Frederik Walk 2024-11-04 23:09:47 +01:00
parent 55c9966b88
commit 5aceccc855
11 changed files with 380 additions and 297 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -20,7 +20,7 @@ struct I2c {
namespace Default {
const usb_mode_t usb_mode = USB_MODE_XBOX360;
const usb_mode_t usb_mode = USB_MODE_SWITCH_TATACON;
const I2c i2c_config = {
6, // SDA Pin
@ -39,10 +39,10 @@ const Peripherals::Drum::Config drum_config = {
},
// Trigger thresholds
{
80, // Don Left
50, // Ka Left
80, // Don Right
50, // Ka Right
30, // Don Left
10, // Ka Left
30, // Don Right
10, // Ka Right
},
16, // ADC sample count
@ -57,7 +57,7 @@ const Peripherals::Drum::Config drum_config = {
2, // SCLK Pin
1, // SCSn Pin
spi0, // Block
2000000, // Speed
2000000, // Speed // TODO Does lowring help?
},
};
@ -103,7 +103,9 @@ const Peripherals::StatusLed::Config led_config = {
11, // LED Enable Pin,
12, // LED Pin
false, // Is RGBW
255, // Brightness
true, // Idle Color is DS4 light bar color
};
const Peripherals::Display::Config display_config = {

View File

@ -137,12 +137,12 @@ static const std::array<uint8_t, 1154> menu_screen_value = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xed, 0xb1,
0xff, 0xff, 0x8c, 0x31, 0xff, 0xff, 0xff, 0x8c, 0xda, 0xf5, 0xae, 0xff, 0xff, 0xff, 0xed, 0x2f, 0xff, 0xff, 0xb5,
0xef, 0xff, 0xff, 0xff, 0x7b, 0x52, 0xf5, 0xae, 0xff, 0xff, 0xff, 0xed, 0x2f, 0xff, 0xff, 0xb5, 0xef, 0xff, 0xff,
0xff, 0x7b, 0x52, 0xf5, 0xaa, 0xff, 0xff, 0xff, 0xec, 0xaf, 0xff, 0xff, 0xb4, 0x6f, 0xff, 0xff, 0xff, 0x7b, 0x4a,
0x34, 0x6a, 0xff, 0xff, 0xff, 0xec, 0xaf, 0xff, 0xff, 0xb5, 0xef, 0xff, 0xff, 0xff, 0x7b, 0x4a, 0xf5, 0xa4, 0xff,
0xff, 0xff, 0xed, 0xaf, 0xff, 0xff, 0xb5, 0xef, 0xff, 0xff, 0xff, 0x7b, 0x5a, 0xf5, 0xa4, 0xff, 0xff, 0xff, 0xed,
0xb1, 0xff, 0xff, 0x8c, 0x31, 0xff, 0xff, 0xff, 0x8c, 0xda, 0x14, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x8c, 0x31, 0xff, 0xfc, 0x6d, 0x8b, 0x7f, 0xed, 0x7b, 0xc3, 0xbf, 0xff, 0xed, 0x2f, 0xff, 0xff, 0xb5,
0xef, 0xff, 0xfd, 0xad, 0x7b, 0x7f, 0xed, 0x7b, 0xdf, 0xbf, 0xff, 0xed, 0x2f, 0xff, 0xff, 0xb5, 0xef, 0xff, 0xfd,
0xa1, 0x7a, 0xff, 0xe1, 0x7b, 0xdf, 0xbf, 0xff, 0xec, 0xaf, 0xff, 0xff, 0xb4, 0x6f, 0xff, 0xfc, 0x6d, 0x79, 0xff,
0xed, 0x18, 0xdf, 0x5f, 0xff, 0xec, 0xaf, 0xff, 0xff, 0xb5, 0xef, 0xff, 0xfd, 0xad, 0x7a, 0xff, 0xed, 0x6b, 0x5e,
0xef, 0xff, 0xed, 0xaf, 0xff, 0xff, 0xb5, 0xef, 0xff, 0xfd, 0xad, 0x7b, 0x7f, 0xed, 0x6b, 0x5e, 0xef, 0xff, 0xed,
0xb1, 0xff, 0xff, 0x8c, 0x31, 0xff, 0xfc, 0x73, 0x8b, 0x7f, 0xf3, 0x18, 0xde, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfc, 0x3f, 0xff,
0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfb, 0xdf, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 0x1f,
0xff, 0xff, 0xfb, 0xdf, 0xff, 0xff, 0xf6, 0x6f, 0xff, 0xff, 0xf1, 0x8f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xf7,

View File

@ -3,6 +3,7 @@
#include "utils/InputState.h"
#include <optional>
#include <stdint.h>
namespace Doncon::Peripherals {
@ -25,19 +26,24 @@ class StatusLed {
uint8_t led_enable_pin;
uint8_t led_pin;
bool is_rgbw;
uint8_t brightness;
bool enable_player_color;
};
private:
Config m_config;
Utils::InputState m_input_state;
std::optional<Config::Color> m_player_color;
public:
StatusLed(const Config &config);
void setInputState(const Utils::InputState input_state);
void setBrightness(const uint8_t brightness);
void setEnablePlayerColor(const bool do_enable);
void setInputState(const Utils::InputState input_state);
void setPlayerColor(const Config::Color color);
void update();

View File

@ -7,7 +7,6 @@
#include <map>
#include <memory>
#include <stack>
#include <stddef.h>
#include <string>
#include <vector>
@ -17,29 +16,37 @@ class Menu {
public:
enum class Page {
Main,
DeviceMode,
TriggerThreshold,
TriggerThresholdKaLeft,
TriggerThresholdDonLeft,
TriggerThresholdDonRight,
TriggerThresholdKaRight,
DebounceDelay,
LedBrightness,
Drum,
Led,
Reset,
Bootsel,
DrumDebounceDelay,
DrumTriggerThresholdKaLeft,
DrumTriggerThresholdDonLeft,
DrumTriggerThresholdDonRight,
DrumTriggerThresholdKaRight,
LedBrightness,
LedEnablePlayerColor,
BootselMsg,
};
struct State {
Page page;
uint16_t selection;
uint16_t selected_value;
uint16_t original_value;
};
struct Descriptor {
enum class Type {
Root,
Menu,
Selection,
Value,
Toggle,
RebootInfo,
};
@ -48,38 +55,33 @@ class Menu {
GotoParent,
GotoPageDeviceMode,
GotoPageTriggerThreshold,
GotoPageTriggerThresholdKaLeft,
GotoPageTriggerThresholdDonLeft,
GotoPageTriggerThresholdDonRight,
GotoPageTriggerThresholdKaRight,
GotoPageDebounceDelay,
GotoPageLedBrightness,
GotoPageDrum,
GotoPageLed,
GotoPageReset,
GotoPageBootsel,
ChangeUsbModeSwitchTatacon,
ChangeUsbModeSwitchHoripad,
ChangeUsbModeDS3,
ChangeUsbModePS4Tatacon,
ChangeUsbModeDS4,
ChangeUsbModeKeyboardP1,
ChangeUsbModeKeyboardP2,
ChangeUsbModeXbox360,
ChangeUsbModeXbox360AnalogP1,
ChangeUsbModeXbox360AnalogP2,
ChangeUsbModeMidi,
ChangeUsbModeDebug,
GotoPageDrumDebounceDelay,
GotoPageDrumTriggerThresholdKaLeft,
GotoPageDrumTriggerThresholdDonLeft,
GotoPageDrumTriggerThresholdDonRight,
GotoPageDrumTriggerThresholdKaRight,
GotoPageLedBrightness,
GotoPageLedEnablePlayerColor,
SetUsbMode,
SetDrumDebounceDelay,
SetDrumTriggerThresholdKaLeft,
SetDrumTriggerThresholdDonLeft,
SetDrumTriggerThresholdDonRight,
SetDrumTriggerThresholdKaRight,
SetTriggerThresholdKaLeft,
SetTriggerThresholdDonLeft,
SetTriggerThresholdDonRight,
SetTriggerThresholdKaRight,
SetDebounceDelay,
SetLedBrightness,
SetLedEnablePlayerColor,
DoRebootToBootsel,
DoReset,
DoRebootToBootsel,
};
Type type;
@ -95,11 +97,11 @@ class Menu {
bool m_active;
std::stack<State> m_state_stack;
uint16_t getCurrentSelection(Page page);
uint16_t getCurrentValue(Page page);
void gotoPage(Page page);
void gotoParent();
void performSelectionAction(Descriptor::Action action);
void performValueAction(Descriptor::Action action, uint16_t value);
void gotoParent(bool do_restore);
void performAction(Descriptor::Action action, uint8_t value);
public:
Menu(std::shared_ptr<SettingsStore> settings_store);

View File

@ -21,10 +21,12 @@ class SettingsStore {
usb_mode_t usb_mode;
Peripherals::Drum::Config::Thresholds trigger_thresholds;
uint8_t led_brightness;
bool led_enable_player_color;
uint16_t debounce_delay;
uint8_t _padding[m_store_size - sizeof(uint8_t) - sizeof(usb_mode_t) -
sizeof(Peripherals::Drum::Config::Thresholds) - sizeof(uint8_t) - sizeof(uint16_t)];
sizeof(Peripherals::Drum::Config::Thresholds) - sizeof(uint8_t) - sizeof(bool) -
sizeof(uint16_t)];
};
static_assert(sizeof(Storecache) == m_store_size);
@ -54,6 +56,9 @@ class SettingsStore {
void setLedBrightness(const uint8_t brightness);
uint8_t getLedBrightness();
void setLedEnablePlayerColor(const bool do_enable);
bool getLedEnablePlayerColor();
void setDebounceDelay(const uint16_t delay);
uint16_t getDebounceDelay();

View File

@ -25,6 +25,7 @@ enum class ControlCommand {
SetUsbMode,
SetPlayerLed,
SetLedBrightness,
SetLedEnablePlayerColor,
EnterMenu,
ExitMenu,
};
@ -35,6 +36,7 @@ struct ControlMessage {
usb_mode_t usb_mode;
usb_player_led_t player_led;
uint8_t led_brightness;
bool led_enable_player_color;
} data;
};
@ -81,6 +83,9 @@ void core1_task() {
case ControlCommand::SetLedBrightness:
led.setBrightness(control_msg.data.led_brightness);
break;
case ControlCommand::SetLedEnablePlayerColor:
led.setEnablePlayerColor(control_msg.data.led_enable_player_color);
break;
case ControlCommand::EnterMenu:
display.showMenu();
break;
@ -112,7 +117,7 @@ int main() {
auto settings_store = std::make_shared<Utils::SettingsStore>();
Utils::Menu menu(settings_store);
auto mode = settings_store->getUsbMode();
const auto mode = settings_store->getUsbMode();
Peripherals::Drum drum(Config::Default::drum_config);
@ -120,13 +125,13 @@ int main() {
usbd_driver_init(mode);
usbd_driver_set_player_led_cb([](usb_player_led_t player_led) {
auto ctrl_message = ControlMessage{ControlCommand::SetPlayerLed, {.player_led = player_led}};
const auto ctrl_message = ControlMessage{ControlCommand::SetPlayerLed, {.player_led = player_led}};
queue_add_blocking(&control_queue, &ctrl_message);
});
stdio_init_all();
auto readSettings = [&]() {
const auto readSettings = [&]() {
ControlMessage ctrl_message;
ctrl_message = {ControlCommand::SetUsbMode, {.usb_mode = mode}};
@ -134,6 +139,9 @@ int main() {
ctrl_message = {ControlCommand::SetLedBrightness, {.led_brightness = settings_store->getLedBrightness()}};
queue_add_blocking(&control_queue, &ctrl_message);
ctrl_message = {ControlCommand::SetLedEnablePlayerColor,
{.led_enable_player_color = settings_store->getLedEnablePlayerColor()}};
queue_add_blocking(&control_queue, &ctrl_message);
drum.setDebounceDelay(settings_store->getDebounceDelay());
drum.setThresholds(settings_store->getTriggerThresholds());
@ -145,10 +153,12 @@ int main() {
drum.updateInputState(input_state);
queue_try_remove(&controller_input_queue, &input_state.controller);
const auto drum_message = input_state.drum;
if (menu.active()) {
menu.update(input_state.controller);
if (menu.active()) {
auto display_msg = menu.getState();
const auto display_msg = menu.getState();
queue_add_blocking(&menu_display_queue, &display_msg);
} else {
settings_store->store();
@ -170,8 +180,7 @@ int main() {
usbd_driver_send_report(input_state.getReport(mode));
usbd_driver_task();
// TODO don't send whole input_state
queue_try_add(&drum_input_queue, &input_state);
queue_try_add(&drum_input_queue, &drum_message);
}
return 0;

View File

@ -93,15 +93,20 @@ void Display::drawMenuScreen() {
// Background
switch (descriptor_it->second.type) {
case Utils::Menu::Descriptor::Type::Root:
case Utils::Menu::Descriptor::Type::Menu:
if (m_menu_state.page == Utils::Menu::Page::Main) {
ssd1306_bmp_show_image(&m_display, menu_screen_top.data(), menu_screen_top.size());
break;
case Utils::Menu::Descriptor::Type::Selection:
ssd1306_bmp_show_image(&m_display, menu_screen_sub.data(), menu_screen_value.size());
} else {
ssd1306_bmp_show_image(&m_display, menu_screen_sub.data(), menu_screen_sub.size());
}
break;
case Utils::Menu::Descriptor::Type::Value:
ssd1306_bmp_show_image(&m_display, menu_screen_value.data(), menu_screen_value.size());
break;
case Utils::Menu::Descriptor::Type::Selection:
case Utils::Menu::Descriptor::Type::Toggle:
ssd1306_bmp_show_image(&m_display, menu_screen_sub.data(), menu_screen_sub.size());
break;
case Utils::Menu::Descriptor::Type::RebootInfo:
break;
}
@ -112,24 +117,27 @@ void Display::drawMenuScreen() {
// Current Selection
std::string selection;
switch (descriptor_it->second.type) {
case Utils::Menu::Descriptor::Type::Root:
case Utils::Menu::Descriptor::Type::Menu:
case Utils::Menu::Descriptor::Type::Selection:
case Utils::Menu::Descriptor::Type::RebootInfo:
selection = descriptor_it->second.items.at(m_menu_state.selection).first;
selection = descriptor_it->second.items.at(m_menu_state.selected_value).first;
break;
case Utils::Menu::Descriptor::Type::Value:
selection = std::to_string(m_menu_state.selection);
selection = std::to_string(m_menu_state.selected_value);
break;
case Utils::Menu::Descriptor::Type::Toggle:
selection = m_menu_state.selected_value ? "On" : "Off";
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::Menu:
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) {
if (i == m_menu_state.selected_value) {
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);
@ -139,6 +147,7 @@ void Display::drawMenuScreen() {
case Utils::Menu::Descriptor::Type::RebootInfo:
break;
case Utils::Menu::Descriptor::Type::Value:
case Utils::Menu::Descriptor::Type::Toggle:
break;
}
}

View File

@ -5,7 +5,7 @@
namespace Doncon::Peripherals {
StatusLed::StatusLed(const Config &config) : m_config(config) {
StatusLed::StatusLed(const Config &config) : m_config(config), m_input_state({}), m_player_color(std::nullopt) {
gpio_init(m_config.led_enable_pin);
gpio_set_dir(m_config.led_enable_pin, GPIO_OUT);
gpio_put(m_config.led_enable_pin, 1);
@ -13,11 +13,11 @@ StatusLed::StatusLed(const Config &config) : m_config(config) {
ws2812_init(config.led_pin, m_config.is_rgbw);
}
void StatusLed::setInputState(const Utils::InputState input_state) { m_input_state = input_state; }
void StatusLed::setBrightness(const uint8_t brightness) { m_config.brightness = brightness; }
void StatusLed::setEnablePlayerColor(const bool do_enable) { m_config.enable_player_color = do_enable; }
void StatusLed::setPlayerColor(const Config::Color color) { m_config.idle_color = color; }
void StatusLed::setInputState(const Utils::InputState input_state) { m_input_state = input_state; }
void StatusLed::setPlayerColor(const Config::Color color) { m_player_color = color; }
void StatusLed::update() {
float brightness_factor = m_config.brightness / static_cast<float>(UINT8_MAX);
@ -28,6 +28,7 @@ void StatusLed::update() {
uint8_t num_colors = 0;
// TODO simply use max of each channel
if (m_input_state.drum.don_left.triggered) {
mixed_red += m_config.don_left_color.r;
mixed_green += m_config.don_left_color.g;
@ -59,10 +60,13 @@ void StatusLed::update() {
static_cast<uint8_t>((mixed_green / num_colors) * brightness_factor),
static_cast<uint8_t>((mixed_blue / num_colors) * brightness_factor)));
} else {
const auto idle_color =
m_config.enable_player_color ? m_player_color.value_or(m_config.idle_color) : m_config.idle_color;
ws2812_put_pixel(
ws2812_rgb_to_gamma_corrected_u32pixel(static_cast<uint8_t>((m_config.idle_color.r) * brightness_factor),
static_cast<uint8_t>((m_config.idle_color.g) * brightness_factor),
static_cast<uint8_t>((m_config.idle_color.b) * brightness_factor)));
ws2812_rgb_to_gamma_corrected_u32pixel(static_cast<uint8_t>((idle_color.r) * brightness_factor),
static_cast<uint8_t>((idle_color.g) * brightness_factor),
static_cast<uint8_t>((idle_color.b) * brightness_factor)));
}
}

View File

@ -4,12 +4,11 @@ namespace Doncon::Utils {
const std::map<Menu::Page, const Menu::Descriptor> Menu::descriptors = {
{Menu::Page::Main, //
{Menu::Descriptor::Type::Root, //
{Menu::Descriptor::Type::Menu, //
"Settings", //
{{"Mode", Menu::Descriptor::Action::GotoPageDeviceMode}, //
{"Brightness", Menu::Descriptor::Action::GotoPageLedBrightness}, //
{"Sensitvty", Menu::Descriptor::Action::GotoPageTriggerThreshold}, //
{"Hold Time", Menu::Descriptor::Action::GotoPageDebounceDelay}, //
{"Drum", Menu::Descriptor::Action::GotoPageDrum}, //
{"Led", Menu::Descriptor::Action::GotoPageLed}, //
{"Reset", Menu::Descriptor::Action::GotoPageReset}, //
{"USB Flash", Menu::Descriptor::Action::GotoPageBootsel}}, //
0}}, //
@ -17,58 +16,66 @@ const std::map<Menu::Page, const Menu::Descriptor> Menu::descriptors = {
{Menu::Page::DeviceMode, //
{Menu::Descriptor::Type::Selection, //
"Mode", //
{{"Swtch Tata", Menu::Descriptor::Action::ChangeUsbModeSwitchTatacon}, //
{"Swtch Pro", Menu::Descriptor::Action::ChangeUsbModeSwitchHoripad}, //
{"Dualshock3", Menu::Descriptor::Action::ChangeUsbModeDS3}, //
{"PS4 Tata", Menu::Descriptor::Action::ChangeUsbModePS4Tatacon}, //
{"Dualshock4", Menu::Descriptor::Action::ChangeUsbModeDS4}, //
{"Keybrd P1", Menu::Descriptor::Action::ChangeUsbModeKeyboardP1}, //
{"Keybrd P2", Menu::Descriptor::Action::ChangeUsbModeKeyboardP2}, //
{"Xbox 360", Menu::Descriptor::Action::ChangeUsbModeXbox360}, //
{"Analog P1", Menu::Descriptor::Action::ChangeUsbModeXbox360AnalogP1}, //
{"Analog P2", Menu::Descriptor::Action::ChangeUsbModeXbox360AnalogP2}, //
{"MIDI", Menu::Descriptor::Action::ChangeUsbModeMidi}, //
{"Debug", Menu::Descriptor::Action::ChangeUsbModeDebug}}, //
{{"Swtch Tata", Menu::Descriptor::Action::SetUsbMode}, //
{"Swtch Pro", Menu::Descriptor::Action::SetUsbMode}, //
{"Dualshock3", Menu::Descriptor::Action::SetUsbMode}, //
{"PS4 Tata", Menu::Descriptor::Action::SetUsbMode}, //
{"Dualshock4", Menu::Descriptor::Action::SetUsbMode}, //
{"Keybrd P1", Menu::Descriptor::Action::SetUsbMode}, //
{"Keybrd P2", Menu::Descriptor::Action::SetUsbMode}, //
{"Xbox 360", Menu::Descriptor::Action::SetUsbMode}, //
{"Analog P1", Menu::Descriptor::Action::SetUsbMode}, //
{"Analog P2", Menu::Descriptor::Action::SetUsbMode}, //
{"MIDI", Menu::Descriptor::Action::SetUsbMode}, //
{"Debug", Menu::Descriptor::Action::SetUsbMode}}, //
0}}, //
{Menu::Page::TriggerThreshold, //
{Menu::Descriptor::Type::Selection, //
"Sensitivity", //
{{"Ka Left", Menu::Descriptor::Action::GotoPageTriggerThresholdKaLeft}, //
{"Don Left", Menu::Descriptor::Action::GotoPageTriggerThresholdDonLeft}, //
{"Don Right", Menu::Descriptor::Action::GotoPageTriggerThresholdDonRight}, //
{"Ka Right", Menu::Descriptor::Action::GotoPageTriggerThresholdKaRight}}, //
{Menu::Page::Drum, //
{Menu::Descriptor::Type::Menu, //
"Drum Settings", //
{{"Hold Time", Menu::Descriptor::Action::GotoPageDrumDebounceDelay}, //
{"Left Ka", Menu::Descriptor::Action::GotoPageDrumTriggerThresholdKaLeft}, //
{"Left Don", Menu::Descriptor::Action::GotoPageDrumTriggerThresholdDonLeft}, //
{"Right Don", Menu::Descriptor::Action::GotoPageDrumTriggerThresholdDonRight}, //
{"Right Ka", Menu::Descriptor::Action::GotoPageDrumTriggerThresholdKaRight}}, //
0}}, //
{Menu::Page::TriggerThresholdKaLeft, //
{Menu::Descriptor::Type::Value, //
"Trg Level Ka Left", //
{{"", Menu::Descriptor::Action::SetTriggerThresholdKaLeft}}, //
4095}},
{Menu::Page::TriggerThresholdDonLeft, //
{Menu::Descriptor::Type::Value, //
"Trg Level Don Left", //
{{"", Menu::Descriptor::Action::SetTriggerThresholdDonLeft}}, //
4095}},
{Menu::Page::TriggerThresholdDonRight, //
{Menu::Descriptor::Type::Value, //
"Trg Level Don Right", //
{{"", Menu::Descriptor::Action::SetTriggerThresholdDonRight}}, //
4095}},
{Menu::Page::TriggerThresholdKaRight, //
{Menu::Descriptor::Type::Value, //
"Trg Level Ka Right", //
{{"", Menu::Descriptor::Action::SetTriggerThresholdKaRight}}, //
4095}},
{Menu::Page::DebounceDelay, //
{Menu::Page::DrumDebounceDelay, //
{Menu::Descriptor::Type::Value, //
"Hit Hold Time (ms)", //
{{"", Menu::Descriptor::Action::SetDebounceDelay}}, //
255}},
{{"", Menu::Descriptor::Action::SetDrumDebounceDelay}}, //
UINT8_MAX}},
{Menu::Page::DrumTriggerThresholdKaLeft, //
{Menu::Descriptor::Type::Value, //
"Trg Level Left Ka", //
{{"", Menu::Descriptor::Action::SetDrumTriggerThresholdKaLeft}}, //
4095}},
{Menu::Page::DrumTriggerThresholdDonLeft, //
{Menu::Descriptor::Type::Value, //
"Trg Level Left Don", //
{{"", Menu::Descriptor::Action::SetDrumTriggerThresholdDonLeft}}, //
4095}},
{Menu::Page::DrumTriggerThresholdDonRight, //
{Menu::Descriptor::Type::Value, //
"Trg Level Right Don", //
{{"", Menu::Descriptor::Action::SetDrumTriggerThresholdDonRight}}, //
4095}},
{Menu::Page::DrumTriggerThresholdKaRight, //
{Menu::Descriptor::Type::Value, //
"Trg Level Right Ka", //
{{"", Menu::Descriptor::Action::SetDrumTriggerThresholdKaRight}}, //
4095}},
{Menu::Page::Led, //
{Menu::Descriptor::Type::Menu, //
"LED Settings", //
{{"Brightness", Menu::Descriptor::Action::GotoPageLedBrightness}, //
{"Plyr Color", Menu::Descriptor::Action::GotoPageLedEnablePlayerColor}}, //
0}}, //
{Menu::Page::LedBrightness, //
{Menu::Descriptor::Type::Value, //
@ -76,15 +83,21 @@ const std::map<Menu::Page, const Menu::Descriptor> Menu::descriptors = {
{{"", Menu::Descriptor::Action::SetLedBrightness}}, //
UINT8_MAX}}, //
{Menu::Page::LedEnablePlayerColor, //
{Menu::Descriptor::Type::Toggle, //
"Player Color (PS4)", //
{{"", Menu::Descriptor::Action::SetLedEnablePlayerColor}}, //
0}}, //
{Menu::Page::Reset, //
{Menu::Descriptor::Type::Selection, //
{Menu::Descriptor::Type::Menu, //
"Reset all Settings?", //
{{"No", Menu::Descriptor::Action::GotoParent}, //
{"Yes", Menu::Descriptor::Action::DoReset}}, //
0}}, //
{Menu::Page::Bootsel, //
{Menu::Descriptor::Type::Selection, //
{Menu::Descriptor::Type::Menu, //
"Reboot to Flash Mode", //
{{"Reboot?", Menu::Descriptor::Action::DoRebootToBootsel}}, //
0}}, //
@ -97,10 +110,10 @@ const std::map<Menu::Page, const Menu::Descriptor> Menu::descriptors = {
};
Menu::Menu(std::shared_ptr<SettingsStore> settings_store)
: m_store(settings_store), m_active(false), m_state_stack({{Page::Main, 0}}) {};
: m_store(settings_store), m_active(false), m_state_stack({{Page::Main, 0, 0}}) {};
void Menu::activate() {
m_state_stack = std::stack<State>({{Page::Main, 0}});
m_state_stack = std::stack<State>({{Page::Main, 0, 0}});
m_active = true;
}
@ -181,31 +194,27 @@ static InputState::Controller checkPressed(const InputState::Controller &control
return result;
}
uint16_t Menu::getCurrentSelection(Menu::Page page) {
uint16_t Menu::getCurrentValue(Menu::Page page) {
switch (page) {
case Page::DeviceMode:
return static_cast<uint16_t>(m_store->getUsbMode());
break;
case Page::TriggerThresholdKaLeft:
return m_store->getTriggerThresholds().ka_left;
break;
case Page::TriggerThresholdDonLeft:
return m_store->getTriggerThresholds().don_left;
break;
case Page::TriggerThresholdDonRight:
return m_store->getTriggerThresholds().don_right;
break;
case Page::TriggerThresholdKaRight:
return m_store->getTriggerThresholds().ka_right;
break;
case Page::DebounceDelay:
case Page::DrumDebounceDelay:
return m_store->getDebounceDelay();
break;
case Page::DrumTriggerThresholdKaLeft:
return m_store->getTriggerThresholds().ka_left;
case Page::DrumTriggerThresholdDonLeft:
return m_store->getTriggerThresholds().don_left;
case Page::DrumTriggerThresholdDonRight:
return m_store->getTriggerThresholds().don_right;
case Page::DrumTriggerThresholdKaRight:
return m_store->getTriggerThresholds().ka_right;
case Page::LedBrightness:
return m_store->getLedBrightness();
break;
case Page::LedEnablePlayerColor:
return static_cast<uint16_t>(m_store->getLedEnablePlayerColor());
case Page::Main:
case Page::TriggerThreshold:
case Page::Drum:
case Page::Led:
case Page::Reset:
case Page::Bootsel:
case Page::BootselMsg:
@ -215,41 +224,85 @@ uint16_t Menu::getCurrentSelection(Menu::Page page) {
return 0;
}
void Menu::gotoPage(Menu::Page page) { m_state_stack.push({page, getCurrentSelection(page)}); }
void Menu::gotoPage(Menu::Page page) {
const auto current_value = getCurrentValue(page);
void Menu::gotoParent() { m_state_stack.pop(); }
void Menu::performSelectionAction(Menu::Descriptor::Action action) {
auto descriptor_it = descriptors.find(m_state_stack.top().page);
if (descriptor_it == descriptors.end()) {
assert(false);
return;
m_state_stack.push({page, current_value, current_value});
}
void Menu::gotoParent(bool do_restore) {
const auto current_state = m_state_stack.top();
if (current_state.page == Page::Main) {
m_active = false;
}
if (do_restore) {
switch (current_state.page) {
case Page::DeviceMode:
m_store->setUsbMode(static_cast<usb_mode_t>(current_state.original_value));
break;
case Page::DrumDebounceDelay:
m_store->setDebounceDelay(current_state.original_value);
break;
case Page::DrumTriggerThresholdKaLeft: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.ka_left = current_state.original_value;
m_store->setTriggerThresholds(thresholds);
} break;
case Page::DrumTriggerThresholdDonLeft: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.don_left = current_state.original_value;
m_store->setTriggerThresholds(thresholds);
} break;
case Page::DrumTriggerThresholdDonRight: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.don_right = current_state.original_value;
m_store->setTriggerThresholds(thresholds);
} break;
case Page::DrumTriggerThresholdKaRight: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.ka_right = current_state.original_value;
m_store->setTriggerThresholds(thresholds);
} break;
case Page::LedBrightness:
m_store->setLedBrightness(current_state.original_value);
break;
case Page::LedEnablePlayerColor:
m_store->setLedEnablePlayerColor(static_cast<bool>(current_state.original_value));
break;
case Page::Main:
case Page::Drum:
case Page::Led:
case Page::Reset:
case Page::Bootsel:
case Page::BootselMsg:
break;
}
}
m_state_stack.pop();
}
void Menu::performAction(Descriptor::Action action, uint8_t value) {
switch (action) {
case Descriptor::Action::None:
break;
case Descriptor::Action::GotoParent:
gotoParent(false);
break;
case Descriptor::Action::GotoPageDeviceMode:
gotoPage(Page::DeviceMode);
break;
case Descriptor::Action::GotoPageTriggerThreshold:
gotoPage(Page::TriggerThreshold);
case Descriptor::Action::GotoPageDrum:
gotoPage(Page::Drum);
break;
case Descriptor::Action::GotoPageTriggerThresholdKaLeft:
gotoPage(Page::TriggerThresholdKaLeft);
break;
case Descriptor::Action::GotoPageTriggerThresholdDonLeft:
gotoPage(Page::TriggerThresholdDonLeft);
break;
case Descriptor::Action::GotoPageTriggerThresholdDonRight:
gotoPage(Page::TriggerThresholdDonRight);
break;
case Descriptor::Action::GotoPageTriggerThresholdKaRight:
gotoPage(Page::TriggerThresholdKaRight);
break;
case Descriptor::Action::GotoPageLedBrightness:
gotoPage(Page::LedBrightness);
break;
case Descriptor::Action::GotoPageDebounceDelay:
gotoPage(Page::DebounceDelay);
case Descriptor::Action::GotoPageLed:
gotoPage(Page::Led);
break;
case Descriptor::Action::GotoPageReset:
gotoPage(Page::Reset);
@ -257,65 +310,62 @@ void Menu::performSelectionAction(Menu::Descriptor::Action action) {
case Descriptor::Action::GotoPageBootsel:
gotoPage(Page::Bootsel);
break;
case Descriptor::Action::ChangeUsbModeSwitchTatacon:
m_store->setUsbMode(USB_MODE_SWITCH_TATACON);
gotoParent();
case Descriptor::Action::GotoPageDrumDebounceDelay:
gotoPage(Page::DrumDebounceDelay);
break;
case Descriptor::Action::ChangeUsbModeSwitchHoripad:
m_store->setUsbMode(USB_MODE_SWITCH_HORIPAD);
gotoParent();
case Descriptor::Action::GotoPageDrumTriggerThresholdKaLeft:
gotoPage(Page::DrumTriggerThresholdKaLeft);
break;
case Descriptor::Action::ChangeUsbModeDS3:
m_store->setUsbMode(USB_MODE_DUALSHOCK3);
gotoParent();
case Descriptor::Action::GotoPageDrumTriggerThresholdDonLeft:
gotoPage(Page::DrumTriggerThresholdDonLeft);
break;
case Descriptor::Action::ChangeUsbModePS4Tatacon:
m_store->setUsbMode(USB_MODE_PS4_TATACON);
gotoParent();
case Descriptor::Action::GotoPageDrumTriggerThresholdDonRight:
gotoPage(Page::DrumTriggerThresholdDonRight);
break;
case Descriptor::Action::ChangeUsbModeDS4:
m_store->setUsbMode(USB_MODE_DUALSHOCK4);
gotoParent();
case Descriptor::Action::GotoPageDrumTriggerThresholdKaRight:
gotoPage(Page::DrumTriggerThresholdKaRight);
break;
case Descriptor::Action::ChangeUsbModeKeyboardP1:
m_store->setUsbMode(USB_MODE_KEYBOARD_P1);
gotoParent();
case Descriptor::Action::GotoPageLedBrightness:
gotoPage(Page::LedBrightness);
break;
case Descriptor::Action::ChangeUsbModeKeyboardP2:
m_store->setUsbMode(USB_MODE_KEYBOARD_P2);
gotoParent();
case Descriptor::Action::GotoPageLedEnablePlayerColor:
gotoPage(Page::LedEnablePlayerColor);
break;
case Descriptor::Action::ChangeUsbModeXbox360:
m_store->setUsbMode(USB_MODE_XBOX360);
gotoParent();
case Descriptor::Action::SetUsbMode:
m_store->setUsbMode(static_cast<usb_mode_t>(value));
break;
case Descriptor::Action::ChangeUsbModeXbox360AnalogP1:
m_store->setUsbMode(USB_MODE_XBOX360_ANALOG_P1);
gotoParent();
break;
case Descriptor::Action::ChangeUsbModeXbox360AnalogP2:
m_store->setUsbMode(USB_MODE_XBOX360_ANALOG_P2);
gotoParent();
break;
case Descriptor::Action::ChangeUsbModeMidi:
m_store->setUsbMode(USB_MODE_MIDI);
gotoParent();
break;
case Descriptor::Action::ChangeUsbModeDebug:
m_store->setUsbMode(USB_MODE_DEBUG);
gotoParent();
break;
case Descriptor::Action::SetTriggerThresholdKaLeft:
case Descriptor::Action::SetTriggerThresholdDonLeft:
case Descriptor::Action::SetTriggerThresholdDonRight:
case Descriptor::Action::SetTriggerThresholdKaRight:
gotoParent();
break;
case Descriptor::Action::SetDebounceDelay:
gotoParent();
case Descriptor::Action::SetDrumDebounceDelay:
m_store->setDebounceDelay(value);
break;
case Descriptor::Action::SetDrumTriggerThresholdKaLeft: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.ka_left = value;
m_store->setTriggerThresholds(thresholds);
} break;
case Descriptor::Action::SetDrumTriggerThresholdDonLeft: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.don_left = value;
m_store->setTriggerThresholds(thresholds);
} break;
case Descriptor::Action::SetDrumTriggerThresholdDonRight: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.don_right = value;
m_store->setTriggerThresholds(thresholds);
} break;
case Descriptor::Action::SetDrumTriggerThresholdKaRight: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.ka_right = value;
m_store->setTriggerThresholds(thresholds);
} break;
case Descriptor::Action::SetLedBrightness:
gotoParent();
m_store->setLedBrightness(value);
break;
case Descriptor::Action::SetLedEnablePlayerColor:
m_store->setLedEnablePlayerColor(static_cast<bool>(value));
break;
case Descriptor::Action::DoReset:
m_store->reset();
@ -324,53 +374,11 @@ void Menu::performSelectionAction(Menu::Descriptor::Action action) {
m_store->scheduleReboot(true);
gotoPage(Page::BootselMsg);
break;
case Descriptor::Action::GotoParent:
gotoParent();
break;
case Descriptor::Action::None:
break;
}
}
void Menu::performValueAction(Menu::Descriptor::Action action, uint16_t value) {
auto descriptor_it = descriptors.find(m_state_stack.top().page);
if (descriptor_it == descriptors.end()) {
assert(false);
return;
}
switch (action) {
case Descriptor::Action::SetTriggerThresholdKaLeft: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.ka_left = value;
m_store->setTriggerThresholds(thresholds);
} break;
case Descriptor::Action::SetTriggerThresholdDonLeft: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.don_left = value;
m_store->setTriggerThresholds(thresholds);
} break;
case Descriptor::Action::SetTriggerThresholdDonRight: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.don_right = value;
m_store->setTriggerThresholds(thresholds);
} break;
case Descriptor::Action::SetTriggerThresholdKaRight: {
auto thresholds = m_store->getTriggerThresholds();
thresholds.ka_right = value;
m_store->setTriggerThresholds(thresholds);
} break;
case Descriptor::Action::SetDebounceDelay:
m_store->setDebounceDelay(value);
break;
case Descriptor::Action::SetLedBrightness:
m_store->setLedBrightness(value);
break;
default:
break;
}
}
void Menu::update(const InputState::Controller &controller_state) {
InputState::Controller pressed = checkPressed(controller_state);
State &current_state = m_state_stack.top();
@ -386,13 +394,22 @@ void Menu::update(const InputState::Controller &controller_state) {
} else if (pressed.dpad.left) {
switch (descriptor_it->second.type) {
case Descriptor::Type::Value:
case Descriptor::Type::Toggle:
break;
case Descriptor::Type::Selection:
case Descriptor::Type::Root:
if (current_state.selection == 0) {
current_state.selection = descriptor_it->second.items.size() - 1;
if (current_state.selected_value == 0) {
current_state.selected_value = descriptor_it->second.items.size() - 1;
} else {
current_state.selection--;
current_state.selected_value--;
}
performAction(descriptor_it->second.items.at(current_state.selected_value).second,
current_state.selected_value);
break;
case Descriptor::Type::Menu:
if (current_state.selected_value == 0) {
current_state.selected_value = descriptor_it->second.items.size() - 1;
} else {
current_state.selected_value--;
}
break;
case Descriptor::Type::RebootInfo:
@ -401,13 +418,22 @@ void Menu::update(const InputState::Controller &controller_state) {
} else if (pressed.dpad.right) {
switch (descriptor_it->second.type) {
case Descriptor::Type::Value:
case Descriptor::Type::Toggle:
break;
case Descriptor::Type::Selection:
case Descriptor::Type::Root:
if (current_state.selection == descriptor_it->second.items.size() - 1) {
current_state.selection = 0;
if (current_state.selected_value == descriptor_it->second.items.size() - 1) {
current_state.selected_value = 0;
} else {
current_state.selection++;
current_state.selected_value++;
}
performAction(descriptor_it->second.items.at(current_state.selected_value).second,
current_state.selected_value);
break;
case Descriptor::Type::Menu:
if (current_state.selected_value == descriptor_it->second.items.size() - 1) {
current_state.selected_value = 0;
} else {
current_state.selected_value++;
}
break;
case Descriptor::Type::RebootInfo:
@ -416,49 +442,60 @@ void Menu::update(const InputState::Controller &controller_state) {
} else if (pressed.dpad.up) {
switch (descriptor_it->second.type) {
case Descriptor::Type::Value:
if (current_state.selection < descriptor_it->second.max_value) {
current_state.selection++;
performValueAction(descriptor_it->second.items.at(0).second, current_state.selection);
if (current_state.selected_value < UINT8_MAX) {
current_state.selected_value++;
performAction(descriptor_it->second.items.at(0).second, current_state.selected_value);
}
break;
case Descriptor::Type::Toggle:
current_state.selected_value = !current_state.selected_value;
performAction(descriptor_it->second.items.at(0).second, current_state.selected_value);
break;
case Descriptor::Type::Selection:
case Descriptor::Type::Root:
case Descriptor::Type::Menu:
case Descriptor::Type::RebootInfo:
break;
}
} else if (pressed.dpad.down) {
switch (descriptor_it->second.type) {
case Descriptor::Type::Value:
if (current_state.selection > 0) {
current_state.selection--;
performValueAction(descriptor_it->second.items.at(0).second, current_state.selection);
if (current_state.selected_value > 0) {
current_state.selected_value--;
performAction(descriptor_it->second.items.at(0).second, current_state.selected_value);
}
break;
case Descriptor::Type::Toggle:
current_state.selected_value = !current_state.selected_value;
performAction(descriptor_it->second.items.at(0).second, current_state.selected_value);
break;
case Descriptor::Type::Selection:
case Descriptor::Type::Root:
case Descriptor::Type::Menu:
case Descriptor::Type::RebootInfo:
break;
}
} else if (pressed.buttons.south) {
} else if (pressed.buttons.south) { // Back/Exit
switch (descriptor_it->second.type) {
case Descriptor::Type::Value:
case Descriptor::Type::Toggle:
case Descriptor::Type::Selection:
gotoParent();
gotoParent(true);
break;
case Descriptor::Type::Root:
m_active = false;
case Descriptor::Type::Menu:
gotoParent(false);
break;
case Descriptor::Type::RebootInfo:
break;
}
} else if (pressed.buttons.east) {
} else if (pressed.buttons.east) { // Select
switch (descriptor_it->second.type) {
case Descriptor::Type::Value:
performSelectionAction(descriptor_it->second.items.at(0).second);
break;
case Descriptor::Type::Toggle:
case Descriptor::Type::Selection:
case Descriptor::Type::Root:
performSelectionAction(descriptor_it->second.items.at(current_state.selection).second);
gotoParent(false);
break;
case Descriptor::Type::Menu:
performAction(descriptor_it->second.items.at(current_state.selected_value).second,
current_state.selected_value);
break;
case Descriptor::Type::RebootInfo:
break;

View File

@ -15,6 +15,7 @@ SettingsStore::SettingsStore()
Config::Default::usb_mode,
Config::Default::drum_config.trigger_thresholds,
Config::Default::led_config.brightness,
Config::Default::led_config.enable_player_color,
Config::Default::drum_config.debounce_delay_ms,
{}}),
m_dirty(true), m_scheduled_reboot(RebootType::None) {
@ -66,6 +67,14 @@ void SettingsStore::setLedBrightness(const uint8_t brightness) {
}
uint8_t SettingsStore::getLedBrightness() { return m_store_cache.led_brightness; }
void SettingsStore::setLedEnablePlayerColor(const bool do_enable) {
if (m_store_cache.led_enable_player_color != do_enable) {
m_store_cache.led_enable_player_color = do_enable;
m_dirty = true;
}
}
bool SettingsStore::getLedEnablePlayerColor() { return m_store_cache.led_enable_player_color; }
void SettingsStore::setDebounceDelay(const uint16_t delay) {
if (m_store_cache.debounce_delay != delay) {
m_store_cache.debounce_delay = delay;