Skip to content

Commit da87201

Browse files
committed
firmware: Store quantizer table in flash
1 parent b9e33f6 commit da87201

File tree

5 files changed

+82
-40
lines changed

5 files changed

+82
-40
lines changed

firmware/scripts/samd21g18a.ld

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,6 @@ SECTIONS
552552

553553
References:
554554
* ../src/gem_quantizer.c
555-
TODO: Add a marker to the packed config, and hook up to this symbol
556555
*/
557556
_nvm_quantizer_base_address = ORIGIN(nvm);
558557
_nvm_quantizer_length = QUANTIZER_SIZE;

firmware/src/gem_quantizer.c

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222
#include "wntr_pack.h"
2323
#include <string.h>
2424

25+
#define QUANTIZER_MARKER_V1 0xA1
26+
27+
#define QUANTIZER_MARKER_MIN QUANTIZER_MARKER_V1
28+
#define QUANTIZER_MARKER_MAX QUANTIZER_MARKER_V1
29+
30+
extern uint8_t _nvm_quantizer_base_address;
31+
2532
/* Static variables */
2633

2734
/* Forward declarations */
@@ -32,9 +39,8 @@ static const struct GemQuantizerConfig default_quantizer_config;
3239

3340
struct GemQuantizerConfig gem_quantizer_config;
3441

35-
void gem_quantizer_init() {
36-
// TODO: Load from flash
37-
gem_quantizer_config = default_quantizer_config;
42+
void GemQuantizer_init(GemQuantizer *config) {
43+
*config = default_quantizer_config;
3844
}
3945

4046
uint32_t GemQuantizer_search_table(fix16_t pitch_cv) {
@@ -73,12 +79,7 @@ uint32_t GemQuantizer_search_table(fix16_t pitch_cv) {
7379
return lo;
7480
}
7581

76-
void GemQuantizer_erase() {
77-
// TODO: Clear stored table instead
78-
gem_quantizer_config = default_quantizer_config;
79-
}
80-
81-
bool GemQuantizer_unpack(struct GemQuantizerConfig* config, const uint8_t* data) {
82+
bool GemQuantizer_unpack(struct GemQuantizerConfig *config, const uint8_t *data) {
8283
config->hysteresis = (fix16_t)WNTR_UNPACK_32(data, 0);
8384
config->notes_len = (uint32_t)data[4];
8485
for (uint32_t i = 0; i < config->notes_len; i++) {
@@ -103,6 +104,60 @@ bool GemQuantizer_pack(const struct GemQuantizerConfig* config, uint8_t* data) {
103104
return true;
104105
}
105106

107+
void GemQuantizer_erase() {
108+
/* Just erase the marker byte. */
109+
uint8_t data[1] = {0xFF};
110+
// NOLINTNEXTLINE(clang-diagnostic-pointer-to-int-cast)
111+
gem_nvm_write((uint32_t)(&_nvm_quantizer_base_address), data, 1);
112+
}
113+
114+
bool GemQuantizer_load(struct GemQuantizerConfig *config) {
115+
uint8_t data[GEMQUANTIZER_PACKED_SIZE + 1];
116+
117+
// NOLINTNEXTLINE(clang-diagnostic-pointer-to-int-cast)
118+
gem_nvm_read((uint32_t)(&_nvm_quantizer_base_address), data, GEMQUANTIZER_PACKED_SIZE + 1);
119+
120+
uint8_t marker = data[0];
121+
122+
if (marker < QUANTIZER_MARKER_MIN || marker > QUANTIZER_MARKER_MAX) {
123+
printf("Invalid quantizer config marker.\n");
124+
goto fail;
125+
}
126+
127+
bool result = GemQuantizer_unpack(config, data + 1);
128+
129+
// TODO
130+
/*
131+
if (result == true) {
132+
return GemQuantizer_check(marker, config);
133+
}
134+
*/
135+
136+
printf("Failed to load quantizer config.\n");
137+
138+
fail:
139+
printf("Loading default quantizer config.\n");
140+
GemQuantizer_init(config);
141+
return false;
142+
}
143+
144+
bool GemQuantizer_save(const struct GemQuantizerConfig *config) {
145+
uint8_t data[GEMQUANTIZER_PACKED_SIZE + 1];
146+
// We might not fill the entire data buffer, as the config struct is variable size.
147+
// So we zero out the buffer before starting, to avoid saving garbage off the stack
148+
memset(data, 0, sizeof(data));
149+
150+
data[0] = QUANTIZER_MARKER_MAX;
151+
bool result = GemQuantizer_pack(config, data + 1);
152+
WNTR_ASSERT(result == true);
153+
154+
// NOLINTNEXTLINE(clang-diagnostic-pointer-to-int-cast)
155+
gem_nvm_write((uint32_t)(&_nvm_quantizer_base_address), data, GEMQUANTIZER_PACKED_SIZE + 1);
156+
157+
printf("Saved quantizer config: \n");
158+
//GemQuantizer_print(config);
159+
}
160+
106161
/* Private functions */
107162

108163
/*

firmware/src/gem_quantizer.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,6 @@ struct GemQuantizerConfig {
9494

9595
uint32_t notes_len;
9696
struct GemQuantizerTableEntry notes[MAX_QUANTIZER_TABLE_SIZE];
97-
98-
// TODO: Add checksum
9997
};
10098

10199
// Maximum size of a packed quantizer table
@@ -107,13 +105,15 @@ struct GemQuantizerConfig {
107105

108106
extern struct GemQuantizerConfig gem_quantizer_config;
109107

110-
void gem_quantizer_init();
111-
112108
// Search the quantizer table to figure out which bin the incoming pitch CV
113109
// falls into.
114110
// Returns the index of the quantizer bin.
115111
uint32_t GemQuantizer_search_table(fix16_t pitch_cv);
116112

113+
void GemQuantizer_init(GemQuantizer *config);
114+
bool GemQuantizer_unpack(struct GemQuantizerConfig *config, const uint8_t *data);
115+
bool GemQuantizer_pack(const struct GemQuantizerConfig *config, uint8_t *data);
116+
117117
void GemQuantizer_erase();
118-
bool GemQuantizer_unpack(struct GemQuantizerConfig* config, const uint8_t* data);
119-
bool GemQuantizer_pack(const struct GemQuantizerConfig* config, uint8_t* data);
118+
bool GemQuantizer_load(struct GemQuantizerConfig *config);
119+
bool GemQuantizer_save(const struct GemQuantizerConfig *config);

firmware/src/gem_sysex_commands.c

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,11 @@ static void cmd_0x1A_read_quantizer_config_(const uint8_t* data, size_t len) {
434434
(void)data;
435435
(void)len;
436436

437-
/* Read live quantizer config. TODO: Read from flash instead */
437+
/* Read quantizer config from flash */
438+
GemQuantizerConfig config;
438439
uint8_t config_buf[GEMQUANTIZER_PACKED_SIZE];
439-
GemQuantizer_pack(&gem_quantizer_config, config_buf);
440+
GemQuantizer_load(&config);
441+
GemQuantizer_pack(&config, config_buf);
440442

441443
PREPARE_RESPONSE(0x1A, TEETH_ENCODED_LENGTH(GEMQUANTIZER_PACKED_SIZE));
442444
teeth_encode(config_buf, GEMQUANTIZER_PACKED_SIZE, response);
@@ -446,32 +448,18 @@ static void cmd_0x1A_read_quantizer_config_(const uint8_t* data, size_t len) {
446448
}
447449

448450
static void cmd_0x1B_write_quantizer_config_(const uint8_t* data, size_t len) {
449-
(void)data;
450-
(void)len;
451-
452-
#if 0
453-
/* Request (teeth): serialized settings */
454-
DECODE_TEETH_REQUEST(GEMSETTINGS_PACKED_SIZE);
451+
/* Write quantizer config to flash */
452+
DECODE_TEETH_REQUEST(GEMQUANTIZER_PACKED_SIZE);
455453

456-
struct GemSettings settings;
454+
GemQuantizerConfig config;
457455

458-
if (GemSettings_unpack(&settings, request).status == STRUCTY_RESULT_OKAY) {
459-
GemSettings_save(&settings);
456+
bool result = GemQuantizer_unpack(&config, request);
457+
if (result == true) {
458+
GemQuantizer_save(&config);
460459
} else {
461-
debug_printf("Failed to save settings, unable to deserialize.\n");
460+
debug_printf("Failed to save quantizer config, unable to deserialize.\n");
462461
}
463462

464-
/* Ack the data. */
465-
RESPONSE_0(0x19);
466-
467-
debug_printf("SysEx 0x19: Wrote settings\n");
468-
#endif
469-
470-
/* Write live quantizer config. TODO: Write to flash instead */
471-
DECODE_TEETH_REQUEST(GEMQUANTIZER_PACKED_SIZE);
472-
473-
GemQuantizer_unpack(&gem_quantizer_config, request);
474-
475463
/* Ack the data. */
476464
RESPONSE_0(0x1B);
477465

firmware/src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ static void init_() {
190190
/*
191191
Load quantizer configuration
192192
*/
193-
gem_quantizer_init();
193+
GemQuantizer_load(&gem_quantizer_config);
194194

195195
/*
196196
Gemini has two oscillators - Castor & Pollux. For the most part they're

0 commit comments

Comments
 (0)