diff --git a/midi2cv/menu/menu.cc b/midi2cv/menu/menu.cc index 537b025..9df46c7 100644 --- a/midi2cv/menu/menu.cc +++ b/midi2cv/menu/menu.cc @@ -15,27 +15,32 @@ void Menu::render(u8g2_t* u8g2_, uint8_t xStart, uint8_t yStart, uint8_t width, u8g2_SetFont(u8g2_, u8g2_font_6x12_tf); for (uint8_t i = 0; i < itemsToRender; i++) { bool selected = this->selectedItem == (i + this->currentScrollStart); + bool editing = this->currentEditingItem == (i + this->currentScrollStart); uint8_t yPosition = yStart + i * MENU_ITEM_HEIGHT; AbstractMenuItem* item = this->items[i + this->currentScrollStart]; u8g2_SetDrawColor(u8g2_, selected ? 1 : 0); - if (selected) { + if(editing) { + u8g2_DrawFrame(u8g2_, xStart, yPosition, width, MENU_ITEM_HEIGHT); + } else if (selected) { u8g2_DrawBox(u8g2_, xStart, yPosition, width, MENU_ITEM_HEIGHT); } - u8g2_SetDrawColor(u8g2_, !selected ? 1 : 0); - u8g2_DrawStr(u8g2_, xStart + 2, yPosition + MENU_ITEM_HEIGHT - 4, item->get_label()); + u8g2_SetDrawColor(u8g2_, editing || !selected ? 1 : 0); + u8g2_DrawStr(u8g2_, xStart + 2, yPosition + MENU_ITEM_HEIGHT - 3, item->get_label()); uint8_t valueStringWidth = u8g2_GetStrWidth(u8g2_, item->get_string_representation()); - u8g2_DrawStr(u8g2_, xStart + width - valueStringWidth - 2, yPosition + MENU_ITEM_HEIGHT - 4, item->get_string_representation()); + u8g2_DrawStr(u8g2_, xStart + width - valueStringWidth - 2, yPosition + MENU_ITEM_HEIGHT - 3, item->get_string_representation()); } } void Menu::up() { - if (this->selectedItem > 0) { + if (this->currentEditingItem >= 0) { + this->items[this->selectedItem]->decrease(); + } else if (this->selectedItem > 0) { if (this->selectedItem - this->currentScrollStart == 1) { // keep scroll start one up this->currentScrollStart--; } @@ -50,12 +55,25 @@ void Menu::up() void Menu::down() { - uint8_t maxVisibleItems = height / MENU_ITEM_HEIGHT; - if (this->selectedItem < this->itemCount - 1) { - if (this->selectedItem - this->currentScrollStart == maxVisibleItems - 2 && this->itemCount - this->currentScrollStart > maxVisibleItems) { - this->currentScrollStart++; - } + if (this->currentEditingItem >= 0) { + this->items[this->selectedItem]->increase(); + } else { + uint8_t maxVisibleItems = height / MENU_ITEM_HEIGHT; + if (this->selectedItem < this->itemCount - 1) { + if (this->selectedItem - this->currentScrollStart == maxVisibleItems - 2 && this->itemCount - this->currentScrollStart > maxVisibleItems) { + this->currentScrollStart++; + } - this->selectedItem++; + this->selectedItem++; + } } } + +void Menu::enter() +{ + if (this->currentEditingItem >= 0) { + this->currentEditingItem = -1; + return; + } + this->currentEditingItem = this->selectedItem; +} diff --git a/midi2cv/menu/menu_items.h b/midi2cv/menu/menu_items.h index 50cbde6..ab8e30a 100644 --- a/midi2cv/menu/menu_items.h +++ b/midi2cv/menu/menu_items.h @@ -8,6 +8,8 @@ class AbstractMenuItem { public: virtual const char* get_label(); virtual char* get_string_representation(); + virtual void increase(); + virtual void decrease(); }; template @@ -55,15 +57,16 @@ class MenuItem : public AbstractMenuItem { template class NumberMenuItem : public MenuItem { private: - T step; T minimumValue; T maximumValue; + T step; protected: NumberMenuItem(const char* _label, T _initialValue, T _minimumValue, T _maximumValue, T _step) : MenuItem(_label, _initialValue) , minimumValue(_minimumValue) - , maximumValue(_maximumValue) {}; + , maximumValue(_maximumValue) + , step(_step) {}; virtual const char* get_format_string() = 0; @@ -75,13 +78,13 @@ class NumberMenuItem : public MenuItem { public: void increase() { - if (this->get_value() + step <= maximumValue) + if (this->get_value() + step <= maximumValue && this->get_value() + step >= minimumValue) this->set_value(this->get_value() + step); }; void decrease() { - if (this->get_value() - step >= minimumValue) + if (this->get_value() - step >= minimumValue && this->get_value() - step <= maximumValue) this->set_value(this->get_value() - step); }; }; @@ -117,7 +120,7 @@ class FloatMenuItem : public NumberMenuItem { protected: const char* get_format_string() { - return "%f.2"; + return "%.2f"; } public: diff --git a/midi2cv/midi2cv.cc b/midi2cv/midi2cv.cc index 1326544..75c55e2 100644 --- a/midi2cv/midi2cv.cc +++ b/midi2cv/midi2cv.cc @@ -48,9 +48,8 @@ void PendSV_Handler() {} // called every 1ms void SysTick_Handler() { - IWDG_ReloadCounter(); - system_clock.Tick(); ui.Poll(); + system_clock.Tick(); } void TIM2_IRQHandler(void) @@ -110,7 +109,7 @@ void Init(void) RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); system_clock.Init(); - SysTick_Config(F_CPU / 8000); + SysTick_Config(F_CPU / 1000); //IWDG_Enable(); gpio.Init(); @@ -130,5 +129,6 @@ int main(void) // do we want to call the watchdog here? it's the only part thats getting interrupted after all // (next to the interrupts themselves potentially interrupting each other) ui.DoEvents(); + IWDG_ReloadCounter(); } } diff --git a/midi2cv/ui.cc b/midi2cv/ui.cc index 975df37..57460e4 100644 --- a/midi2cv/ui.cc +++ b/midi2cv/ui.cc @@ -9,7 +9,8 @@ using namespace stmlib; -#define HEADER_HEIGHT 16 +#define HEADER_HEIGHT 14 +const uint32_t kEncoderLongPressTime = 600; const char part_names[4][2] = { "A", "B", "C", "D" }; @@ -20,7 +21,7 @@ UIntMenuItem item3("ralle", 0, 0, 100, 1); UIntMenuItem item4("ralle1", 0, 0, 100, 1); UIntMenuItem item5("ralle2", 0, 0, 100, 1); UIntMenuItem item6("ralle3", 0, 0, 100, 1); -UIntMenuItem item7("ralle4", 0, 0, 100, 1); +FloatMenuItem item7("ralle4", 0, 0, 100, .25f); void UI::Init() { @@ -38,6 +39,24 @@ void UI::Init() void UI::Poll() { encoder.Debounce(); + + if (encoder.just_pressed()) { + encoder_press_time_ = system_clock.milliseconds(); + encoder_long_press_event_sent_ = false; + } + if (!encoder_long_press_event_sent_) { + if (encoder.pressed()) { + uint32_t duration = system_clock.milliseconds() - encoder_press_time_; + if (duration >= kEncoderLongPressTime && !encoder_long_press_event_sent_) { + input_queue.AddEvent(CONTROL_ENCODER_LONG_CLICK, 0, 0); + encoder_long_press_event_sent_ = true; + } + } + if (encoder.released()) { + input_queue.AddEvent(CONTROL_ENCODER_CLICK, 0, 0); + } + } + int32_t increment = encoder.increment(); if (increment != 0) { input_queue.AddEvent(CONTROL_ENCODER, 0, increment); @@ -53,9 +72,9 @@ void UI::Draw() case MENU_PART_2: case MENU_PART_3: case MENU_PART_4: - //DrawHeader(); + DrawHeader(); //DrawPartMenu(current_menu); - menu.render(display.u8g2(), 0, 0, 128, 64); + menu.render(display.u8g2(), 0, 15, 128, 64 - 15); break; default: @@ -77,7 +96,7 @@ void UI::DrawHeader() u8g2_DrawFrame(display.u8g2(), i * (DISPLAY_WIDTH / PART_COUNT), 0, (DISPLAY_WIDTH / PART_COUNT) - 1, HEADER_HEIGHT); u8g2_SetDrawColor(display.u8g2(), 2); - u8g2_DrawStr(display.u8g2(), i * (DISPLAY_WIDTH / PART_COUNT) + 5, 2 + 10, part_names[i]); + u8g2_DrawStr(display.u8g2(), i * (DISPLAY_WIDTH / PART_COUNT) + 5, 0 + 10, part_names[i]); u8g2_SetDrawColor(display.u8g2(), 1); } } @@ -120,6 +139,7 @@ bool UI::DoEvents() void UI::OnClick() { + menu.enter(); } void UI::OnLongClick() diff --git a/midi2cv/ui.h b/midi2cv/ui.h index d3e868a..aea1aa2 100644 --- a/midi2cv/ui.h +++ b/midi2cv/ui.h @@ -23,17 +23,21 @@ class UI { bool DoEvents(); private: - Menu_t current_menu; stmlib::EventQueue<16> input_queue; + bool long_press_event_sent_; + uint32_t start_stop_press_time_; + bool encoder_long_press_event_sent_; + uint32_t encoder_press_time_; + void Draw(); void DrawHeader(); void DrawPartMenu(Menu_t menu); void OnClick(); void OnLongClick(); - void OnIncrement(stmlib::Event &e); + void OnIncrement(stmlib::Event& e); DISALLOW_COPY_AND_ASSIGN(UI); };