diff --git a/midi2cv/midi2cv.cc b/midi2cv/midi2cv.cc index 777e982..dbe7740 100644 --- a/midi2cv/midi2cv.cc +++ b/midi2cv/midi2cv.cc @@ -21,7 +21,7 @@ Settings settings; Part parts[PART_COUNT]; Part* part_pointers[PART_COUNT] = { &parts[0], &parts[1], &parts[2], &parts[3] }; -UI ui(part_pointers); +UI ui(part_pointers, &settings); // Default interrupt handlers. extern "C" { diff --git a/midi2cv/part.h b/midi2cv/part.h index 219575c..966041e 100644 --- a/midi2cv/part.h +++ b/midi2cv/part.h @@ -54,42 +54,39 @@ typedef enum : uint8_t { VOICE_DETAIL_XL = 3 } PartVoiceDetail_t; -class Part { - public: - Part() - : part_voice_count(VOICE_COUNT_1) - , part_voice_detail(VOICE_DETAIL_S) - , midi_filter_channel_enabled(true) - , midi_filter_channel(1) - , midi_filter_lowest_note(0) - , midi_filter_highest_note(127) - , midi_thru_mode(MIDI_THRU_OFF) - { - for (int i = 0; i < TOTAL_COLUMN_COUNT; i++) { - output_type_row_0[i] = BI_OFF; - output_type_row_1[i] = UNI_OFF; - output_type_row_2[i] = UNI_OFF; - output_type_row_3[i] = GATE_OFF; - } - } - void ProcessMidiInput(/* TODO: Inputs */); - - uint8_t RequiredColumns(); - - PartVoiceCount_t part_voice_count; - PartVoiceDetail_t part_voice_detail; - bool midi_filter_channel_enabled; - uint8_t midi_filter_channel; - uint8_t midi_filter_lowest_note; - uint8_t midi_filter_highest_note; - MIDIInput_t midi_filter_input; - MIDIThruMode_t midi_thru_mode; +struct PartData { // Everything defined here will be stored in flash even in power down + PartVoiceCount_t part_voice_count = VOICE_COUNT_1; + PartVoiceDetail_t part_voice_detail = VOICE_DETAIL_S; + bool midi_filter_channel_enabled = true; + uint8_t midi_filter_channel = 1; + uint8_t midi_filter_lowest_note = 0; + uint8_t midi_filter_highest_note = 127; + MIDIInput_t midi_filter_input = MIDI_INPUT_OMNI; + MIDIThruMode_t midi_thru_mode = MIDI_THRU_OFF; BiOutputType_t output_type_row_0[TOTAL_COLUMN_COUNT]; UniOutputType_t output_type_row_1[TOTAL_COLUMN_COUNT]; UniOutputType_t output_type_row_2[TOTAL_COLUMN_COUNT]; GateOutputType_t output_type_row_3[TOTAL_COLUMN_COUNT]; }; +class Part { + public: + Part() + { + for (int i = 0; i < TOTAL_COLUMN_COUNT; i++) { + data.output_type_row_0[i] = BI_OFF; + data.output_type_row_1[i] = UNI_OFF; + data.output_type_row_2[i] = UNI_OFF; + data.output_type_row_3[i] = GATE_OFF; + } + } + void ProcessMidiInput(/* TODO: Inputs */); + + uint8_t RequiredColumns(); + + PartData data; +}; + extern Part parts[]; #endif diff --git a/midi2cv/settings.cc b/midi2cv/settings.cc index a405480..68a77db 100644 --- a/midi2cv/settings.cc +++ b/midi2cv/settings.cc @@ -1,23 +1,11 @@ #include "settings.h" #include "midi2cv/part.h" -Settings::Settings() +Settings::Settings() : first_start(false) { persistent_data_.honor = 1; - for (int i = 0; i < PART_COUNT; i++) { - PartState* part = &state_.part_states[i]; - - part->midi_filter_channel = 1; - part->midi_filter_channel_enabled = true; - part->midi_filter_lowest_note = 0; - part->midi_filter_highest_note = 127; - part->midi_filter_input = MIDI_INPUT_OMNI; - part->part_voice_count = VOICE_COUNT_1; - part->part_voice_detail = VOICE_DETAIL_S; - } - - /*bool success =*/chunk_storage_.Init(&persistent_data_, &state_); + first_start = !chunk_storage_.Init(&persistent_data_, &state_); } void Settings::SavePersistentData() diff --git a/midi2cv/settings.h b/midi2cv/settings.h index fc4ce68..fb20b4b 100644 --- a/midi2cv/settings.h +++ b/midi2cv/settings.h @@ -7,23 +7,12 @@ struct PersistentData { uint8_t honor; - uint8_t padding[15]; + uint8_t padding[7]; enum { tag = 0x494C4143 }; // CALI }; -struct PartState { // 8 bytes, TODO: can these be pointers to the actual values, or can we do some other copying magic? - PartVoiceCount_t part_voice_count; - PartVoiceDetail_t part_voice_detail; - uint8_t midi_filter_channel_enabled; - uint8_t midi_filter_channel; - uint8_t midi_filter_lowest_note; - uint8_t midi_filter_highest_note; - MIDIInput_t midi_filter_input; - MIDIThruMode_t midi_thru_mode; -}; - struct State { - PartState part_states[PART_COUNT]; // 4 * 8 bytes + PartData part_datas[PART_COUNT]; //uint8_t padding[4]; enum { tag = 0x54415453 }; // STAT }; @@ -56,17 +45,22 @@ class Settings { return &state_; } - inline const PartState& part(int i) const + inline const PartData& part(int i) const { - return state_.part_states[i]; + return state_.part_datas[i]; } - inline PartState* mutable_part(int i) + inline PartData* mutable_part(int i) { - return &state_.part_states[i]; + return &state_.part_datas[i]; + } + + inline bool is_first_start() { + return this->first_start; } private: + bool first_start; PersistentData persistent_data_; State state_; @@ -79,5 +73,3 @@ class Settings { DISALLOW_COPY_AND_ASSIGN(Settings); }; - -extern Settings settings; diff --git a/midi2cv/ui.cc b/midi2cv/ui.cc index 7627b90..f027d52 100644 --- a/midi2cv/ui.cc +++ b/midi2cv/ui.cc @@ -14,11 +14,12 @@ using namespace stmlib; const uint32_t kEncoderLongPressTime = 600; -UI::UI(Part** part_pointers) +UI::UI(Part** part_pointers, Settings* settings) : main_menu(part_pointers) , parts(part_pointers) { this->input_queue.Init(); + this->settings = settings; LoadState(); } @@ -61,22 +62,17 @@ void UI::Draw() void UI::LoadState() { - for (size_t i = 0; i < PART_COUNT; i++) { - parts[i]->midi_filter_channel = settings.part(i).midi_filter_channel; - parts[i]->midi_filter_channel_enabled = settings.part(i).midi_filter_channel_enabled; - parts[i]->midi_filter_lowest_note = settings.part(i).midi_filter_lowest_note; - } + for(size_t i = 0; i < PART_COUNT; i++) + this->parts[i]->data = settings->part(i); } void UI::SaveState() { for (size_t i = 0; i < PART_COUNT; i++) { - settings.mutable_part(i)->midi_filter_channel = this->parts[i]->midi_filter_channel; - settings.mutable_part(i)->midi_filter_channel_enabled = this->parts[i]->midi_filter_channel_enabled; - settings.mutable_part(i)->midi_filter_lowest_note = this->parts[i]->midi_filter_lowest_note; + *(settings->mutable_part(i)) = this->parts[i]->data; } - settings.SaveState(); + settings->SaveState(); } void UI::Flush() diff --git a/midi2cv/ui.h b/midi2cv/ui.h index 1a4f463..b24c2d1 100644 --- a/midi2cv/ui.h +++ b/midi2cv/ui.h @@ -5,12 +5,13 @@ #include "stmlib/ui/event_queue.h" #include "config.h" +#include "settings.h" #include "ui/main_menu.h" #include class UI { public: - UI(Part** part_pointers); + UI(Part** part_pointers, Settings* settings); ~UI() {} void Poll(); @@ -20,6 +21,8 @@ class UI { private: stmlib::EventQueue<16> input_queue; + Settings* settings; + bool long_press_event_sent_; uint32_t start_stop_press_time_; bool encoder_long_press_event_sent_; diff --git a/midi2cv/ui/part_menu.cc b/midi2cv/ui/part_menu.cc index f15a681..cebb2e9 100644 --- a/midi2cv/ui/part_menu.cc +++ b/midi2cv/ui/part_menu.cc @@ -12,14 +12,14 @@ static const char* kMidiThruStrings[] = { "off", "on", "polychain" }; PartMenu::PartMenu(Part* _part) : part(_part) - , item_voice_count("voice count", (uint8_t*)&_part->part_voice_count, 1, 4, 1) - , item_voice_detail("voice detail", (uint8_t*)&_part->part_voice_detail, kVoiceDetailStrings, 4) - , item_midi_filter_enabled("MIDI filter", &_part->midi_filter_channel_enabled, "on", "off") - , item_midi_channel("MIDI channel", (uint8_t*)&_part->midi_filter_channel, kMidiChannelStrings, 17) - , item_midi_input("MIDI input", (uint8_t*)&_part->midi_filter_input, kMidiInputStrings, 3) - , item_midi_lowest_note("MIDI lowest", (uint8_t*)&_part->midi_filter_lowest_note) - , item_midi_highest_note("MIDI highest", (uint8_t*)&_part->midi_filter_highest_note) - , item_midi_thru_mode("MIDI thru", (uint8_t*)&_part->midi_thru_mode, kMidiThruStrings, 3) + , item_voice_count("voice count", (uint8_t*)&_part->data.part_voice_count, 1, 4, 1) + , item_voice_detail("voice detail", (uint8_t*)&_part->data.part_voice_detail, kVoiceDetailStrings, 4) + , item_midi_filter_enabled("MIDI filter", &_part->data.midi_filter_channel_enabled, "on", "off") + , item_midi_channel("MIDI channel", (uint8_t*)&_part->data.midi_filter_channel, kMidiChannelStrings, 17) + , item_midi_input("MIDI input", (uint8_t*)&_part->data.midi_filter_input, kMidiInputStrings, 3) + , item_midi_lowest_note("MIDI lowest", (uint8_t*)&_part->data.midi_filter_lowest_note) + , item_midi_highest_note("MIDI highest", (uint8_t*)&_part->data.midi_filter_highest_note) + , item_midi_thru_mode("MIDI thru", (uint8_t*)&_part->data.midi_thru_mode, kMidiThruStrings, 3) { this->menu.add_item(&this->item_voice_count); this->menu.add_item(&this->item_voice_detail);