From 8b783287b4560eb3d6a3fcd150cd5ba0fcf11db3 Mon Sep 17 00:00:00 2001 From: Jan-Henrik Bruhn Date: Fri, 3 Jan 2020 22:09:11 +0100 Subject: [PATCH] Add menu datastrctures --- midi2cv/menu/menu.cc | 7 +++ midi2cv/menu/menu.h | 35 +++++++++++ midi2cv/menu/menu_items.h | 122 ++++++++++++++++++++++++++++++++++++++ midi2cv/midi2cv.cc | 39 ++++++------ stmlib | 2 +- 5 files changed, 187 insertions(+), 18 deletions(-) create mode 100644 midi2cv/menu/menu.cc create mode 100644 midi2cv/menu/menu.h create mode 100644 midi2cv/menu/menu_items.h diff --git a/midi2cv/menu/menu.cc b/midi2cv/menu/menu.cc new file mode 100644 index 0000000..97e793a --- /dev/null +++ b/midi2cv/menu/menu.cc @@ -0,0 +1,7 @@ +#include "menu.h" + +#define MENU_ITEM_HEIGHT 8 + +void Menu::render(u8g2_t* u8g2_, uint8_t x, uint8_t y, uint8_t width, uint8_t height) { + +} diff --git a/midi2cv/menu/menu.h b/midi2cv/menu/menu.h new file mode 100644 index 0000000..a6ad693 --- /dev/null +++ b/midi2cv/menu/menu.h @@ -0,0 +1,35 @@ +#pragma once + +#include "menu_items.h" + +#include + +#define MAXIMUM_MENU_ITEM_COUNT 16 + +class Menu { + private: + AbstractMenuItem* items[MAXIMUM_MENU_ITEM_COUNT]; + uint8_t itemCount; + uint8_t selectedItem; + uint8_t currentScrollStart; // index we start rendering the menu from (for scrolling) + int8_t currentEditingItem; + + public: + Menu() + : selectedItem(0) + , currentScrollStart(0) + , currentEditingItem(-1) {}; + + void up(); + void down(); + void enter(); + + void add_item(AbstractMenuItem* item) + { + if (itemCount < MAXIMUM_MENU_ITEM_COUNT) { + items[itemCount++] = item; + } + } + + void render(u8g2_t* u8g2_, uint8_t x, uint8_t y, uint8_t width, uint8_t height); +}; diff --git a/midi2cv/menu/menu_items.h b/midi2cv/menu/menu_items.h new file mode 100644 index 0000000..ec63522 --- /dev/null +++ b/midi2cv/menu/menu_items.h @@ -0,0 +1,122 @@ +#pragma once + +#include "stmlib/stmlib.h" +#include + +// MenuItem without template so we can easily store pointers +class AbstractMenuItem { + public: + virtual const char* get_label(); + virtual char* get_string_representation(); +}; + +template +class MenuItem : public AbstractMenuItem { + private: + const char* label; + T value; + T step; + char stringRepresentation[24]; + + protected: + MenuItem(const char* _label, T _initialValue) + : label(_label) + , value(_initialValue) {}; + + virtual void to_string(char* buf) = 0; + + void set_value(T value) + { + this->value = value; + this->to_string(stringRepresentation); + }; + + public: + T get_value() + { + return value; + } + + const char* get_label() + { + return label; + } + + char* get_string_representation() + { + return stringRepresentation; + } +}; + +template +class NumberMenuItem : public MenuItem { + private: + T step; + T minimumValue; + T maximumValue; + + protected: + NumberMenuItem(const char* _label, T _initialValue, T _minimumValue, T _maximumValue, T _step) + : MenuItem(_label, _initialValue) + , minimumValue(_minimumValue) + , maximumValue(_maximumValue) {}; + + virtual const char* get_format_string() = 0; + + void to_string(char* buf) + { + sprintf(buf, this->get_format_string(), this->get_value()); + } + + public: + void increase() + { + if (this->get_value() + step <= maximumValue) + this->set_value(this->get_value() + step); + }; + + void decrease() + { + if (this->get_value() - step >= minimumValue) + this->set_value(this->get_value() - step); + }; +}; + +class UIntMenuItem : public NumberMenuItem { + private: + protected: + const char* get_format_string() + { + return "%u"; + } + + public: + UIntMenuItem(const char* _label, uint32_t _initialValue, uint32_t _minimumValue, uint32_t _maximumValue, uint32_t _step) + : NumberMenuItem(_label, _initialValue, _minimumValue, _maximumValue, _step) {}; +}; + +class IntMenuItem : public NumberMenuItem { + private: + protected: + const char* get_format_string() + { + return "%d"; + } + + public: + IntMenuItem(const char* _label, int32_t _initialValue, int32_t _minimumValue, int32_t _maximumValue, int32_t _step) + : NumberMenuItem(_label, _initialValue, _minimumValue, _maximumValue, _step) {}; +}; + +class FloatMenuItem : public NumberMenuItem { + private: + protected: + const char* get_format_string() + { + return "%f.2"; + } + + public: + FloatMenuItem(const char* _label, float _initialValue, float _minimumValue, float _maximumValue, float _step) + : NumberMenuItem(_label, _initialValue, _minimumValue, _maximumValue, _step) {}; +}; diff --git a/midi2cv/midi2cv.cc b/midi2cv/midi2cv.cc index 8370f0e..77a9aef 100644 --- a/midi2cv/midi2cv.cc +++ b/midi2cv/midi2cv.cc @@ -3,6 +3,8 @@ #include "drivers/display.h" #include "drivers/encoder.h" #include "drivers/gpio.h" +#include "menu/menu_items.h" +#include "menu/menu.h" #include "part.h" #include "stmlib/system/system_clock.h" #include "ui.h" @@ -16,6 +18,12 @@ Encoder encoder; UI ui; Part part[PART_COUNT]; +UIntMenuItem item("peda", 0, 0, 42, 1); +FloatMenuItem item2("peda", 0, 0, 42, 1); +FloatMenuItem item3("peda", 0, 0, 42, 1); +Menu menu; + + // Default interrupt handlers. extern "C" { void NMI_Handler() {} @@ -58,25 +66,15 @@ void TIM2_IRQHandler(void) } TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - // this will get called with 192 kHz (foof) - // we want to reduce the amount of times the ui gets polled to 500 Hz + // this will get called with 8kHz (foof) // which still is a lot (60fps would be enough tbh) - static uint8_t count = 0; - count++; - if (count % (192 * 2) == 0) { - ui.Flush(); - count = 0; - } + ui.Flush(); - if (count % 48 == 0) { // write audiodac1 - } - if (count % 48 == 1) { // write audiodac2 - } - if (count % 48 == 2) { // write audiodac3 - } - if (count % 48 == 3) { // write audiodac4 - } + // write audiodac1 + // write audiodac2 + // write audiodac3 + // write audiodac4 } } @@ -84,7 +82,7 @@ void InitTimers(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseInitTypeDef timer_init; - timer_init.TIM_Period = F_CPU / (48000 * 4) - 1; // 192 kHz, 48kHz for each audio DAC + timer_init.TIM_Period = F_CPU / (8000) - 1; // 192 kHz, 48kHz for each audio DAC timer_init.TIM_Prescaler = 0; timer_init.TIM_ClockDivision = TIM_CKD_DIV1; timer_init.TIM_CounterMode = TIM_CounterMode_Up; @@ -127,6 +125,13 @@ void Init(void) int main(void) { Init(); + + menu.add_item(&item); + menu.add_item(&item2); + menu.add_item(&item3); + item.increase(); + item2.increase(); + item3.increase(); while (1) { // In this loop we do things that dont depend on any timing, but that have to be done. // you should not write on spi here because that should happen in the TIM2 interrupt diff --git a/stmlib b/stmlib index 5a5264d..f3fdd66 160000 --- a/stmlib +++ b/stmlib @@ -1 +1 @@ -Subproject commit 5a5264d54062915a60a4ed83e67c329e187e8e0c +Subproject commit f3fdd66a6c88812d653a07d307913a53ade81c79