mirror of
https://github.com/jhbruhn/eurorack.git
synced 2025-03-15 11:05:49 +00:00
Implement settings storage for stereo_mix
This commit is contained in:
parent
f9dd6af68a
commit
0b59c9edb1
8 changed files with 160 additions and 22 deletions
4
stereo_mix/config.h
Normal file
4
stereo_mix/config.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define CHANNEL_COUNT (4)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "stm32f0xx_hal_gpio.h"
|
#include "stm32f0xx_hal_gpio.h"
|
||||||
#include <stm32f0xx_hal.h>
|
#include <stm32f0xx_hal.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
using namespace stereo_mix;
|
using namespace stereo_mix;
|
||||||
using namespace stmlib;
|
using namespace stmlib;
|
||||||
|
@ -21,8 +22,6 @@ enum LedColor {
|
||||||
LED_COLOR_ORANGE
|
LED_COLOR_ORANGE
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t kNumChannels = 4;
|
|
||||||
|
|
||||||
static GPIO_TypeDef* kGpioPorts[] = { GPIOA, GPIOA, GPIOA, GPIOA };
|
static GPIO_TypeDef* kGpioPorts[] = { GPIOA, GPIOA, GPIOA, GPIOA };
|
||||||
static const uint16_t kGpioPins[] = { GPIO_PIN_8, GPIO_PIN_9, GPIO_PIN_10, GPIO_PIN_11 };
|
static const uint16_t kGpioPins[] = { GPIO_PIN_8, GPIO_PIN_9, GPIO_PIN_10, GPIO_PIN_11 };
|
||||||
|
|
||||||
|
@ -41,7 +40,7 @@ class Leds {
|
||||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||||
|
|
||||||
GPIO_InitTypeDef gpioInit;
|
GPIO_InitTypeDef gpioInit;
|
||||||
for (size_t i = 0; i < kNumChannels; i++) {
|
for (size_t i = 0; i < CHANNEL_COUNT; i++) {
|
||||||
gpioInit.Mode = GPIO_MODE_OUTPUT_PP;
|
gpioInit.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
gpioInit.Pin = kGpioColorPins[i];
|
gpioInit.Pin = kGpioColorPins[i];
|
||||||
gpioInit.Pull = GPIO_NOPULL;
|
gpioInit.Pull = GPIO_NOPULL;
|
||||||
|
@ -71,7 +70,7 @@ class Leds {
|
||||||
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
|
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
|
||||||
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
|
||||||
|
|
||||||
for(size_t i = 0; i < kNumChannels; i++) {
|
for(size_t i = 0; i < CHANNEL_COUNT; i++) {
|
||||||
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, timer_channel[i]);
|
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, timer_channel[i]);
|
||||||
gpioInit.Mode = GPIO_MODE_AF_PP;
|
gpioInit.Mode = GPIO_MODE_AF_PP;
|
||||||
gpioInit.Pin = kGpioPins[i];
|
gpioInit.Pin = kGpioPins[i];
|
||||||
|
@ -86,7 +85,7 @@ class Leds {
|
||||||
|
|
||||||
void Write()
|
void Write()
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < kNumChannels; i++) {
|
for(size_t i = 0; i < CHANNEL_COUNT; i++) {
|
||||||
LedColor targetColor = colors[i];
|
LedColor targetColor = colors[i];
|
||||||
uint16_t intensity = intensities[i];
|
uint16_t intensity = intensities[i];
|
||||||
if(colors[i] == LED_COLOR_ORANGE) {
|
if(colors[i] == LED_COLOR_ORANGE) {
|
||||||
|
@ -108,7 +107,7 @@ class Leds {
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_intensity_signed(uint8_t channel, int16_t intensity) {
|
void set_intensity_signed(uint8_t channel, int16_t intensity) {
|
||||||
if(channel >= kNumChannels) return;
|
if(channel >= CHANNEL_COUNT) return;
|
||||||
|
|
||||||
if(intensity < 0) {
|
if(intensity < 0) {
|
||||||
colors[channel] = LED_COLOR_RED;
|
colors[channel] = LED_COLOR_RED;
|
||||||
|
@ -122,7 +121,7 @@ class Leds {
|
||||||
|
|
||||||
void set_intensity_unsigned(uint8_t channel, uint16_t intensity, LedColor color)
|
void set_intensity_unsigned(uint8_t channel, uint16_t intensity, LedColor color)
|
||||||
{
|
{
|
||||||
if (channel >= kNumChannels)
|
if (channel >= CHANNEL_COUNT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
intensities[channel] = intensity;
|
intensities[channel] = intensity;
|
||||||
|
@ -130,7 +129,7 @@ class Leds {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t intensities[kNumChannels];
|
uint16_t intensities[CHANNEL_COUNT];
|
||||||
bool toggle[kNumChannels];
|
bool toggle[CHANNEL_COUNT];
|
||||||
LedColor colors[kNumChannels];
|
LedColor colors[CHANNEL_COUNT];
|
||||||
};
|
};
|
||||||
|
|
21
stereo_mix/settings.cc
Normal file
21
stereo_mix/settings.cc
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include "stmlib/system/page_storage.h"
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
|
#include "midi2cv/part.h"
|
||||||
|
|
||||||
|
Settings::Settings() : first_start(false)
|
||||||
|
{
|
||||||
|
persistent_data_.honor = 1;
|
||||||
|
|
||||||
|
first_start = !chunk_storage_.Init(&persistent_data_, &state_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::SavePersistentData()
|
||||||
|
{
|
||||||
|
chunk_storage_.SavePersistentData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::SaveState()
|
||||||
|
{
|
||||||
|
chunk_storage_.SaveState();
|
||||||
|
}
|
75
stereo_mix/settings.h
Normal file
75
stereo_mix/settings.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stmlib/stmlib.h"
|
||||||
|
#include "stmlib/system/storage.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#define SETTINGS_START (0x08001800)
|
||||||
|
#define SETTINGS_END (0x08002000)
|
||||||
|
|
||||||
|
struct ChannelData {
|
||||||
|
bool mute;
|
||||||
|
int16_t vol_att;
|
||||||
|
int16_t pan_att;
|
||||||
|
uint8_t padding[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PersistentData {
|
||||||
|
uint8_t honor;
|
||||||
|
uint8_t padding[7];
|
||||||
|
enum { tag = 0x494C4143 }; // CALI
|
||||||
|
};
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
ChannelData channel_datas[CHANNEL_COUNT];
|
||||||
|
//uint8_t padding[4];
|
||||||
|
enum { tag = 0x54415453 }; // STAT
|
||||||
|
};
|
||||||
|
|
||||||
|
class Settings {
|
||||||
|
public:
|
||||||
|
Settings();
|
||||||
|
~Settings() {}
|
||||||
|
|
||||||
|
void SavePersistentData();
|
||||||
|
void SaveState();
|
||||||
|
|
||||||
|
inline const State& state() const
|
||||||
|
{
|
||||||
|
return state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline State* mutable_state()
|
||||||
|
{
|
||||||
|
return &state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ChannelData& channel(int i) const
|
||||||
|
{
|
||||||
|
return state_.channel_datas[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ChannelData* mutable_channel(int i)
|
||||||
|
{
|
||||||
|
return &state_.channel_datas[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_first_start() {
|
||||||
|
return this->first_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool first_start;
|
||||||
|
PersistentData persistent_data_;
|
||||||
|
State state_;
|
||||||
|
|
||||||
|
stmlib::ChunkStorage<
|
||||||
|
SETTINGS_START,
|
||||||
|
SETTINGS_END,
|
||||||
|
PersistentData,
|
||||||
|
State>
|
||||||
|
chunk_storage_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(Settings);
|
||||||
|
};
|
||||||
|
|
|
@ -19,7 +19,8 @@ Adc adc;
|
||||||
Leds leds;
|
Leds leds;
|
||||||
Switches switches;
|
Switches switches;
|
||||||
Processor processors[kNumChannels];
|
Processor processors[kNumChannels];
|
||||||
UI ui(&adc, &switches, &leds, processors);
|
Settings settings;
|
||||||
|
UI ui(&adc, &switches, &leds, processors, &settings);
|
||||||
|
|
||||||
bool mute[4];
|
bool mute[4];
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "pot_controller.h"
|
#include "pot_controller.h"
|
||||||
|
#include "settings.h"
|
||||||
#include <stm32f0xx_hal.h>
|
#include <stm32f0xx_hal.h>
|
||||||
|
|
||||||
const int kLongPressDuration = 2000;
|
static const int kLongPressDuration = 2000;
|
||||||
const int kShowChangedValueMilliseconds = 600;
|
static const int kShowChangedValueMilliseconds = 600;
|
||||||
|
|
||||||
void UI::Poll()
|
void UI::Poll()
|
||||||
{
|
{
|
||||||
|
@ -40,8 +41,10 @@ void UI::Poll()
|
||||||
system_clock.milliseconds() - press_time[i] + 1);
|
system_clock.milliseconds() - press_time[i] + 1);
|
||||||
ignore_release[i] = true;
|
ignore_release[i] = true;
|
||||||
}
|
}
|
||||||
for (size_t j = 0; j < kNumChannels * 2; j++)
|
for (size_t j = 0; j < kNumChannels * 2; j++) {
|
||||||
potControllers[j].Unlock();
|
potControllers[j].Unlock();
|
||||||
|
SaveState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +56,7 @@ void UI::Poll()
|
||||||
if (i < kNumChannels) {
|
if (i < kNumChannels) {
|
||||||
processors[i].set_pan_offset(pan_pots[i] - 32767);
|
processors[i].set_pan_offset(pan_pots[i] - 32767);
|
||||||
processors[i].set_volume_offset(volume_pots[i]);
|
processors[i].set_volume_offset(volume_pots[i]);
|
||||||
|
processors[i].set_muted(mute[i]);
|
||||||
}
|
}
|
||||||
if (abs(previous_pot_values[i] - adc->value(ADC_GROUP_POT + i)) > 1900) {
|
if (abs(previous_pot_values[i] - adc->value(ADC_GROUP_POT + i)) > 1900) {
|
||||||
previous_pot_values[i] = adc->value(ADC_GROUP_POT + i);
|
previous_pot_values[i] = adc->value(ADC_GROUP_POT + i);
|
||||||
|
@ -61,6 +65,33 @@ void UI::Poll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UI::LoadState() {
|
||||||
|
if(!settings->is_first_start()) {
|
||||||
|
for(size_t i = 0; i < kNumChannels; i++) {
|
||||||
|
ChannelData c = settings->channel(i);
|
||||||
|
mute[i] = c.mute;
|
||||||
|
this->pan_att_pots[i] = c.pan_att + 32767;
|
||||||
|
this->volume_att_pots[i] = c.vol_att + 32767;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(size_t i = 0; i < kNumChannels; i++) {
|
||||||
|
mute[i] = false;
|
||||||
|
this->pan_att_pots[i] = this->volume_att_pots[i] = 32767 + (32767 / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI::SaveState() {
|
||||||
|
for(size_t i = 0; i < kNumChannels; i++) {
|
||||||
|
ChannelData* c = settings->mutable_channel(i);
|
||||||
|
c->mute = this->mute[i];
|
||||||
|
c->pan_att = this->pan_att_pots[i] - 32767;
|
||||||
|
c->vol_att = this->volume_att_pots[i] - 32767;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings->SaveState();
|
||||||
|
}
|
||||||
|
|
||||||
void UI::OnSwitchPressed(const Event& e)
|
void UI::OnSwitchPressed(const Event& e)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -79,13 +110,12 @@ void UI::OnPotChanged(const Event& e)
|
||||||
void UI::OnSwitchReleased(const Event& e)
|
void UI::OnSwitchReleased(const Event& e)
|
||||||
{
|
{
|
||||||
mute[e.control_id] = !mute[e.control_id];
|
mute[e.control_id] = !mute[e.control_id];
|
||||||
processors[e.control_id].set_muted(mute[e.control_id]);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < kNumChannels; i++) {
|
for (size_t i = 0; i < kNumChannels; i++) {
|
||||||
last_pan_pot_touch[i] = last_vol_pot_touch[i] = 0;
|
last_pan_pot_touch[i] = last_vol_pot_touch[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: save state
|
SaveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UI::TaskProcessPotControllers()
|
void UI::TaskProcessPotControllers()
|
||||||
|
|
|
@ -6,30 +6,33 @@
|
||||||
#include "pot_controller.h"
|
#include "pot_controller.h"
|
||||||
#include "processor.h"
|
#include "processor.h"
|
||||||
#include "stmlib/ui/event_queue.h"
|
#include "stmlib/ui/event_queue.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
using namespace stmlib;
|
using namespace stmlib;
|
||||||
|
|
||||||
extern const uint8_t kNumChannels; // TODO
|
const uint8_t kNumChannels = CHANNEL_COUNT;
|
||||||
|
|
||||||
class UI {
|
class UI {
|
||||||
public:
|
public:
|
||||||
UI(Adc* adc_, Switches* switches_, Leds* leds_, Processor* processors_)
|
UI(Adc* adc_, Switches* switches_, Leds* leds_, Processor* processors_, Settings* settings)
|
||||||
: adc(adc_)
|
: adc(adc_)
|
||||||
, switches(switches_)
|
, switches(switches_)
|
||||||
, leds(leds_)
|
, leds(leds_)
|
||||||
, processors(processors_)
|
, processors(processors_)
|
||||||
|
, settings(settings)
|
||||||
{
|
{
|
||||||
queue.Init();
|
queue.Init();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Init() {
|
void Init() {
|
||||||
|
LoadState();
|
||||||
|
|
||||||
for (size_t i = 0; i < kNumChannels; i++) {
|
for (size_t i = 0; i < kNumChannels; i++) {
|
||||||
uint16_t* volume_hidden_params[] = {&volume_att_pots[i], &volume_att_pots[i], &volume_att_pots[i], &volume_att_pots[i]};
|
uint16_t* volume_hidden_params[] = {&volume_att_pots[i], &volume_att_pots[i], &volume_att_pots[i], &volume_att_pots[i]};
|
||||||
potControllers[i].Init(&volume_pots[i], volume_hidden_params);
|
potControllers[i].Init(&volume_pots[i], volume_hidden_params);
|
||||||
uint16_t* pan_hidden_params[] = {&pan_att_pots[i], &pan_att_pots[i], &pan_att_pots[i], &pan_att_pots[i]};
|
uint16_t* pan_hidden_params[] = {&pan_att_pots[i], &pan_att_pots[i], &pan_att_pots[i], &pan_att_pots[i]};
|
||||||
potControllers[i + kNumChannels].Init(&pan_pots[i], pan_hidden_params);
|
potControllers[i + kNumChannels].Init(&pan_pots[i], pan_hidden_params);
|
||||||
|
|
||||||
volume_att_pots[i] = pan_att_pots[i] = 32767 + (32767 / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,6 +48,9 @@ class UI {
|
||||||
void TaskDrawLeds(void);
|
void TaskDrawLeds(void);
|
||||||
void TaskProcessPotControllers(void);
|
void TaskProcessPotControllers(void);
|
||||||
|
|
||||||
|
void LoadState();
|
||||||
|
void SaveState();
|
||||||
|
|
||||||
uint8_t ui_task = 0;
|
uint8_t ui_task = 0;
|
||||||
|
|
||||||
EventQueue<> queue;
|
EventQueue<> queue;
|
||||||
|
@ -56,6 +62,8 @@ class UI {
|
||||||
|
|
||||||
Processor* processors;
|
Processor* processors;
|
||||||
|
|
||||||
|
Settings* settings;
|
||||||
|
|
||||||
uint16_t previous_pot_values[kNumChannels * 2];
|
uint16_t previous_pot_values[kNumChannels * 2];
|
||||||
|
|
||||||
uint16_t volume_pots[kNumChannels];
|
uint16_t volume_pots[kNumChannels];
|
||||||
|
|
2
stmlib
2
stmlib
|
@ -1 +1 @@
|
||||||
Subproject commit 727d85a263af4ee4c2d8dd75191e2611383b9d29
|
Subproject commit ed353ae21927643acffb86c96b69eec43879754d
|
Loading…
Reference in a new issue