Compare commits

..

1 Commits
PM15 ... master

Author SHA1 Message Date
George Norton 9c036f07f8
Fix save config (#27)
* Fix save config

* Fix save config when no audio is playing

* Fix build issue with the github workflow compiler
2023-10-16 18:35:38 -04:00
4 changed files with 68 additions and 30 deletions

View File

@ -96,6 +96,13 @@ static bool reload_config = false;
static uint16_t write_offset = 0;
static uint16_t read_offset = 0;
typedef enum {
NormalOperation,
SaveRequested,
Saving
} State;
static State saveState = NormalOperation;
bool validate_filter_configuration(filter_configuration_tlv *filters)
{
if (filters->header.type != FILTER_CONFIGURATION) {
@ -357,37 +364,47 @@ void load_config() {
}
#ifndef TEST_TARGET
bool __no_inline_not_in_flash_func(save_configuration)() {
bool __no_inline_not_in_flash_func(save_config)() {
const uint8_t active_configuration = inactive_working_configuration ? 0 : 1;
tlv_header* config = (tlv_header*) working_configuration[active_configuration];
if (validate_configuration(config)) {
switch (saveState) {
case SaveRequested:
if (validate_configuration(config)) {
/* Turn the DAC off so we don't make a huge noise when disrupting
real time audio operation. */
power_down_dac();
const size_t config_length = config->length - ((size_t)config->value - (size_t)config);
// Write data to flash
uint8_t flash_buffer[CFG_BUFFER_SIZE];
flash_header_tlv* flash_header = (flash_header_tlv*) flash_buffer;
flash_header->header.type = FLASH_HEADER;
flash_header->header.length = sizeof(flash_header_tlv) + config_length;
flash_header->magic = FLASH_MAGIC;
flash_header->version = CONFIG_VERSION;
memcpy((void*)(flash_header->tlvs), config->value, config_length);
const size_t config_length = config->length - ((size_t)config->value - (size_t)config);
// Write data to flash
uint8_t flash_buffer[CFG_BUFFER_SIZE];
flash_header_tlv* flash_header = (flash_header_tlv*) flash_buffer;
flash_header->header.type = FLASH_HEADER;
flash_header->header.length = sizeof(flash_header_tlv) + config_length;
flash_header->magic = FLASH_MAGIC;
flash_header->version = CONFIG_VERSION;
memcpy((void*)(flash_header->tlvs), config->value, config_length);
/* Turn the DAC off so we don't make a huge noise when disrupting
real time audio operation. */
power_down_dac();
uint32_t ints = save_and_disable_interrupts();
flash_range_erase(USER_CONFIGURATION_OFFSET, FLASH_SECTOR_SIZE);
flash_range_program(USER_CONFIGURATION_OFFSET, flash_buffer, CFG_BUFFER_SIZE);
restore_interrupts(ints);
saveState = Saving;
uint32_t ints = save_and_disable_interrupts();
flash_range_erase(USER_CONFIGURATION_OFFSET, FLASH_SECTOR_SIZE);
flash_range_program(USER_CONFIGURATION_OFFSET, flash_buffer, CFG_BUFFER_SIZE);
restore_interrupts(ints);
power_up_dac();
return true;
// Return true, so the caller skips processing audio
return true;
}
// Validation failed, give up.
saveState = NormalOperation;
break;
case Saving:
/* Turn the DAC off so we don't make a huge noise when disrupting
real time audio operation. */
power_up_dac();
saveState = NormalOperation;
return false;
default:
break;
}
return false;
@ -415,7 +432,14 @@ bool process_cmd(tlv_header* cmd) {
}
break;
case SAVE_CONFIGURATION: {
if (cmd->length == 4 && save_configuration()) {
if (cmd->length == 4) {
saveState = SaveRequested;
if (audio_state.interface == 0) {
// The OS will configure the alternate "zero" interface when the device is not in use
// in this sate we can write to flash now. Otherwise, defer the save until we get the next
// usb packet.
save_config();
}
result->type = OK;
result->length = 4;
return true;

View File

@ -52,6 +52,7 @@ void config_in_packet(struct usb_endpoint *ep);
void config_out_packet(struct usb_endpoint *ep);
void configuration_ep_on_cancel(struct usb_endpoint *ep);
extern void load_config();
extern bool save_config();
extern void apply_config_changes();
#endif // CONFIGURATION_MANAGER_H

View File

@ -52,6 +52,7 @@ static uint8_t *userbuf;
audio_state_config audio_state = {
.freq = 48000,
.de_emphasis_frequency = 0x1, // 48khz
.interface = 0
};
preprocessing_config preprocessing = {
@ -125,6 +126,18 @@ static void __no_inline_not_in_flash_func(_as_audio_packet)(struct usb_endpoint
int32_t *out = (int32_t *) userbuf;
int samples = usb_buffer->data_len / 2;
// Make sure core 1 is ready for us.
multicore_fifo_pop_blocking();
if (save_config()) {
// Skip processing while we are writing to flash
multicore_fifo_push_blocking(CORE0_ABORTED);
// keep on truckin'
usb_grow_transfer(ep->current_transfer, 1);
usb_packet_done(ep);
return;
}
if (preprocessing.reverse_stereo) {
for (int i = 0; i < samples; i+=2) {
out[i] = in[i+1];
@ -136,8 +149,6 @@ static void __no_inline_not_in_flash_func(_as_audio_packet)(struct usb_endpoint
out[i] = in[i];
}
// Make sure core 1 is ready for us.
multicore_fifo_pop_blocking();
multicore_fifo_push_blocking(CORE0_READY);
multicore_fifo_push_blocking(samples);
@ -186,8 +197,7 @@ void __no_inline_not_in_flash_func(core1_entry)() {
// Block until the userbuf is filled with data
uint32_t ready = multicore_fifo_pop_blocking();
while (ready != CORE0_READY)
ready = multicore_fifo_pop_blocking();
if (ready == CORE0_ABORTED) continue;
const uint32_t samples = multicore_fifo_pop_blocking();
@ -760,6 +770,7 @@ static const struct usb_transfer_type _audio_cmd_transfer_type = {
static bool as_set_alternate(struct usb_interface *interface, uint alt) {
assert(interface == &as_op_interface);
audio_state.interface = alt;
switch (alt) {
case 0: power_down_dac(); return true;
case 1: power_up_dac(); return true;

View File

@ -76,6 +76,7 @@ typedef struct _audio_state_config {
int16_t _target_pcm3060_registers;
};
int16_t pcm3060_registers;
int8_t interface;
} audio_state_config;
extern audio_state_config audio_state;
@ -149,6 +150,7 @@ static char *descriptor_strings[] = {
#define SAMPLING_FREQ (CODEC_FREQ / 192)
#define CORE0_READY 19813219
#define CORE0_ABORTED 91231891
#define CORE1_READY 72965426
/*****************************************************************************