Add menu datastrctures

This commit is contained in:
Jan-Henrik 2020-01-03 22:09:11 +01:00
parent f8962fc9c4
commit 8b783287b4
5 changed files with 187 additions and 18 deletions

7
midi2cv/menu/menu.cc Normal file
View 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
View 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
View 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) {};
};

View file

@ -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

@ -1 +1 @@
Subproject commit 5a5264d54062915a60a4ed83e67c329e187e8e0c
Subproject commit f3fdd66a6c88812d653a07d307913a53ade81c79