mirror of
https://github.com/jhbruhn/eurorack.git
synced 2025-03-15 02:55:49 +00:00
Add menu datastrctures
This commit is contained in:
parent
f8962fc9c4
commit
8b783287b4
5 changed files with 187 additions and 18 deletions
7
midi2cv/menu/menu.cc
Normal file
7
midi2cv/menu/menu.cc
Normal file
|
@ -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) {
|
||||||
|
|
||||||
|
}
|
35
midi2cv/menu/menu.h
Normal file
35
midi2cv/menu/menu.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "menu_items.h"
|
||||||
|
|
||||||
|
#include <u8g2.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
};
|
122
midi2cv/menu/menu_items.h
Normal file
122
midi2cv/menu/menu_items.h
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stmlib/stmlib.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// MenuItem without template so we can easily store pointers
|
||||||
|
class AbstractMenuItem {
|
||||||
|
public:
|
||||||
|
virtual const char* get_label();
|
||||||
|
virtual char* get_string_representation();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
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 T>
|
||||||
|
class NumberMenuItem : public MenuItem<T> {
|
||||||
|
private:
|
||||||
|
T step;
|
||||||
|
T minimumValue;
|
||||||
|
T maximumValue;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
NumberMenuItem(const char* _label, T _initialValue, T _minimumValue, T _maximumValue, T _step)
|
||||||
|
: MenuItem<T>(_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<uint32_t> {
|
||||||
|
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<int32_t> {
|
||||||
|
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<float> {
|
||||||
|
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) {};
|
||||||
|
};
|
|
@ -3,6 +3,8 @@
|
||||||
#include "drivers/display.h"
|
#include "drivers/display.h"
|
||||||
#include "drivers/encoder.h"
|
#include "drivers/encoder.h"
|
||||||
#include "drivers/gpio.h"
|
#include "drivers/gpio.h"
|
||||||
|
#include "menu/menu_items.h"
|
||||||
|
#include "menu/menu.h"
|
||||||
#include "part.h"
|
#include "part.h"
|
||||||
#include "stmlib/system/system_clock.h"
|
#include "stmlib/system/system_clock.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
@ -16,6 +18,12 @@ Encoder encoder;
|
||||||
UI ui;
|
UI ui;
|
||||||
Part part[PART_COUNT];
|
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.
|
// Default interrupt handlers.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void NMI_Handler() {}
|
void NMI_Handler() {}
|
||||||
|
@ -58,25 +66,15 @@ void TIM2_IRQHandler(void)
|
||||||
}
|
}
|
||||||
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
||||||
|
|
||||||
// this will get called with 192 kHz (foof)
|
// this will get called with 8kHz (foof)
|
||||||
// we want to reduce the amount of times the ui gets polled to 500 Hz
|
|
||||||
// which still is a lot (60fps would be enough tbh)
|
// which still is a lot (60fps would be enough tbh)
|
||||||
|
|
||||||
static uint8_t count = 0;
|
ui.Flush();
|
||||||
count++;
|
|
||||||
if (count % (192 * 2) == 0) {
|
|
||||||
ui.Flush();
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count % 48 == 0) { // write audiodac1
|
// write audiodac1
|
||||||
}
|
// write audiodac2
|
||||||
if (count % 48 == 1) { // write audiodac2
|
// write audiodac3
|
||||||
}
|
// write audiodac4
|
||||||
if (count % 48 == 2) { // write audiodac3
|
|
||||||
}
|
|
||||||
if (count % 48 == 3) { // write audiodac4
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +82,7 @@ void InitTimers(void)
|
||||||
{
|
{
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
||||||
TIM_TimeBaseInitTypeDef timer_init;
|
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_Prescaler = 0;
|
||||||
timer_init.TIM_ClockDivision = TIM_CKD_DIV1;
|
timer_init.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||||
timer_init.TIM_CounterMode = TIM_CounterMode_Up;
|
timer_init.TIM_CounterMode = TIM_CounterMode_Up;
|
||||||
|
@ -127,6 +125,13 @@ void Init(void)
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
|
|
||||||
|
menu.add_item(&item);
|
||||||
|
menu.add_item(&item2);
|
||||||
|
menu.add_item(&item3);
|
||||||
|
item.increase();
|
||||||
|
item2.increase();
|
||||||
|
item3.increase();
|
||||||
while (1) {
|
while (1) {
|
||||||
// In this loop we do things that dont depend on any timing, but that have to be done.
|
// 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
|
// you should not write on spi here because that should happen in the TIM2 interrupt
|
||||||
|
|
2
stmlib
2
stmlib
|
@ -1 +1 @@
|
||||||
Subproject commit 5a5264d54062915a60a4ed83e67c329e187e8e0c
|
Subproject commit f3fdd66a6c88812d653a07d307913a53ade81c79
|
Loading…
Reference in a new issue