diff --git a/firmware/code/run.c b/firmware/code/run.c index 53e7120..14333a0 100644 --- a/firmware/code/run.c +++ b/firmware/code/run.c @@ -106,7 +106,7 @@ static void _as_audio_packet(struct usb_endpoint *ep) { multicore_fifo_push_blocking(CORE0_READY); multicore_fifo_push_blocking(samples); - for (int j = 0; j < FILTER_STAGES; j++) { + for (int j = 0; j < filter_stages; j++) { // Left channel filter for (int i = 0; i < samples; i += 2) { fix16_t x_f16 = fix16_from_int((int16_t) out[i]); @@ -128,6 +128,23 @@ static void _as_audio_packet(struct usb_endpoint *ep) { usb_packet_done(ep); } +static void update_volume() +{ + if (audio_state._volume != audio_state._target_volume) { + // PCM3060 volume attenuation: + // 0: 0db (default) + // 55: -100db + // 56..: Mute + uint8_t buf[3]; + buf[0] = 65; // register addr + buf[1] = 255 + (audio_state.target_volume[0] / 128); // data left + buf[2] = 255 + (audio_state.target_volume[1] / 128); // data right + i2c_write_blocking(i2c0, PCM_I2C_ADDR, buf, 3, false); + + audio_state._volume = audio_state._target_volume; + } +} + void core1_entry() { uint8_t *userbuf = (uint8_t *) multicore_fifo_pop_blocking(); int32_t *out = (int32_t *) userbuf; @@ -142,7 +159,7 @@ void core1_entry() { uint32_t limit = multicore_fifo_pop_blocking(); - for (int j = 0; j < FILTER_STAGES; j++) { + for (int j = 0; j < filter_stages; j++) { for (int i = 1; i < limit; i += 2) { fix16_t x_f16 = fix16_from_int((int16_t) out[i]); @@ -159,26 +176,13 @@ void core1_entry() { // Update the volume if required. We do this from core1 as // core0 is more heavily loaded, doing this from core0 can // lead to audio crackling. - if (audio_state._volume != audio_state._target_volume) { - // PCM3060 volume attenuation: - // 0: 0db (default) - // 55: -100db - // 56..: Mute - uint8_t buf[3]; - buf[0] = 65; // register addr - buf[1] = 255 + (audio_state.target_volume[0] / 128); // data left - buf[2] = 255 + (audio_state.target_volume[1] / 128); // data right - i2c_write_blocking(i2c0, PCM_I2C_ADDR, buf, 3, false); - - audio_state._volume = audio_state._target_volume; - } + update_volume(); } } void setup() { set_sys_clock_khz(SYSTEM_FREQ / 1000, true); sleep_ms(100); - // stdio_init_all(); userbuf = malloc(sizeof(uint8_t) * RINGBUF_LEN_IN_BYTES); @@ -532,8 +536,7 @@ static bool do_get_current(struct usb_setup_packet *setup) { else if (cn == AUDIO_CHANNEL_RIGHT_FRONT) { usb_start_tiny_control_in_transfer(audio_state.target_volume[1], 2); } - else - { + else { return false; } return true; diff --git a/firmware/code/user.c b/firmware/code/user.c index f50bc8d..ac76599 100644 --- a/firmware/code/user.c +++ b/firmware/code/user.c @@ -19,7 +19,7 @@ #include "bqf.h" #include "run.h" -int FILTER_STAGES = 0; +int filter_stages = 0; /***************************************************************************** * Here is where your digital signal processing journey begins. Follow this @@ -33,32 +33,32 @@ int FILTER_STAGES = 0; void define_filters() { // First filter. - bqf_memreset(&bqf_filters_mem_left[FILTER_STAGES]); - bqf_memreset(&bqf_filters_mem_right[FILTER_STAGES]); - bqf_peaking_config(SAMPLING_FREQ, 38.0, -19.0, 0.9, &bqf_filters_left[FILTER_STAGES]); - bqf_peaking_config(SAMPLING_FREQ, 38.0, -19.0, 0.9, &bqf_filters_right[FILTER_STAGES++]); + bqf_memreset(&bqf_filters_mem_left[filter_stages]); + bqf_memreset(&bqf_filters_mem_right[filter_stages]); + bqf_peaking_config(SAMPLING_FREQ, 38.0, -19.0, 0.9, &bqf_filters_left[filter_stages]); + bqf_peaking_config(SAMPLING_FREQ, 38.0, -19.0, 0.9, &bqf_filters_right[filter_stages++]); // Second filter. - bqf_memreset(&bqf_filters_mem_left[FILTER_STAGES]); - bqf_memreset(&bqf_filters_mem_right[FILTER_STAGES]); - bqf_lowshelf_config(SAMPLING_FREQ, 2900.0, 3.0, 4.0, &bqf_filters_left[FILTER_STAGES]); - bqf_lowshelf_config(SAMPLING_FREQ, 2900.0, 3.0, 4.0, &bqf_filters_right[FILTER_STAGES++]); + bqf_memreset(&bqf_filters_mem_left[filter_stages]); + bqf_memreset(&bqf_filters_mem_right[filter_stages]); + bqf_lowshelf_config(SAMPLING_FREQ, 2900.0, 3.0, 4.0, &bqf_filters_left[filter_stages]); + bqf_lowshelf_config(SAMPLING_FREQ, 2900.0, 3.0, 4.0, &bqf_filters_right[filter_stages++]); // Third filter. - bqf_memreset(&bqf_filters_mem_left[FILTER_STAGES]); - bqf_memreset(&bqf_filters_mem_right[FILTER_STAGES]); - bqf_peaking_config(SAMPLING_FREQ, 430.0, 6.0, 3.5, &bqf_filters_left[FILTER_STAGES]); - bqf_peaking_config(SAMPLING_FREQ, 430.0, 6.0, 3.5, &bqf_filters_right[FILTER_STAGES++]); + bqf_memreset(&bqf_filters_mem_left[filter_stages]); + bqf_memreset(&bqf_filters_mem_right[filter_stages]); + bqf_peaking_config(SAMPLING_FREQ, 430.0, 6.0, 3.5, &bqf_filters_left[filter_stages]); + bqf_peaking_config(SAMPLING_FREQ, 430.0, 6.0, 3.5, &bqf_filters_right[filter_stages++]); // Fourth filter. - bqf_memreset(&bqf_filters_mem_left[FILTER_STAGES]); - bqf_memreset(&bqf_filters_mem_right[FILTER_STAGES]); - bqf_highshelf_config(SAMPLING_FREQ, 8400.0, 3.0, 4.0, &bqf_filters_left[FILTER_STAGES]); - bqf_highshelf_config(SAMPLING_FREQ, 8400.0, 3.0, 4.0, &bqf_filters_right[FILTER_STAGES++]); + bqf_memreset(&bqf_filters_mem_left[filter_stages]); + bqf_memreset(&bqf_filters_mem_right[filter_stages]); + bqf_highshelf_config(SAMPLING_FREQ, 8400.0, 3.0, 4.0, &bqf_filters_left[filter_stages]); + bqf_highshelf_config(SAMPLING_FREQ, 8400.0, 3.0, 4.0, &bqf_filters_right[filter_stages++]); // Fifth filter. - bqf_memreset(&bqf_filters_mem_left[FILTER_STAGES]); - bqf_memreset(&bqf_filters_mem_right[FILTER_STAGES]); - bqf_peaking_config(SAMPLING_FREQ, 4800.0, 6.0, 5.0, &bqf_filters_left[FILTER_STAGES]); - bqf_peaking_config(SAMPLING_FREQ, 4800.0, 6.0, 5.0, &bqf_filters_right[FILTER_STAGES++]); + bqf_memreset(&bqf_filters_mem_left[filter_stages]); + bqf_memreset(&bqf_filters_mem_right[filter_stages]); + bqf_peaking_config(SAMPLING_FREQ, 4800.0, 6.0, 5.0, &bqf_filters_left[filter_stages]); + bqf_peaking_config(SAMPLING_FREQ, 4800.0, 6.0, 5.0, &bqf_filters_right[filter_stages++]); } diff --git a/firmware/code/user.h b/firmware/code/user.h index c70da24..290aff2 100644 --- a/firmware/code/user.h +++ b/firmware/code/user.h @@ -20,8 +20,10 @@ #include "bqf.h" +// In reality we do not have enough CPU resource to run 8 filtering +// stages without some optimisation. #define MAX_FILTER_STAGES 8 -extern int FILTER_STAGES; +extern int filter_stages; extern bqf_coeff_t bqf_filters_left[MAX_FILTER_STAGES]; extern bqf_coeff_t bqf_filters_right[MAX_FILTER_STAGES]; diff --git a/firmware/tools/filter_test.c b/firmware/tools/filter_test.c index afe066b..045ee11 100644 --- a/firmware/tools/filter_test.c +++ b/firmware/tools/filter_test.c @@ -59,7 +59,7 @@ int main(int argc, char* argv[]) out[i] = in[i]; } - for (int j = 0; j < FILTER_STAGES; j++) + for (int j = 0; j < filter_stages; j++) { for (int i = 0; i < samples; i ++) {