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/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;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
2
stmlib
2
stmlib
|
@ -1 +1 @@
|
|||
Subproject commit 5a5264d54062915a60a4ed83e67c329e187e8e0c
|
||||
Subproject commit f3fdd66a6c88812d653a07d307913a53ade81c79
|
Loading…
Reference in a new issue