Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
9c036f07f8 |
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
Loading…
Reference in New Issue