diff options
Diffstat (limited to 'quantum/audio')
-rw-r--r-- | quantum/audio/audio_arm.c | 280 |
1 files changed, 230 insertions, 50 deletions
diff --git a/quantum/audio/audio_arm.c b/quantum/audio/audio_arm.c index 43c8d67c4..247dc337d 100644 --- a/quantum/audio/audio_arm.c +++ b/quantum/audio/audio_arm.c @@ -77,23 +77,48 @@ bool glissando = true; #endif float startup_song[][2] = STARTUP_SONG; -static void gpt_cb6(GPTDriver *gptp); -static void gpt_cb7(GPTDriver *gptp); static void gpt_cb8(GPTDriver *gptp); +#define DAC_BUFFER_SIZE 360 + +#define START_CHANNEL_1() gptStart(&GPTD6, &gpt6cfg1); \ + gptStartContinuous(&GPTD6, 2U) +#define START_CHANNEL_2() gptStart(&GPTD7, &gpt7cfg1); \ + gptStartContinuous(&GPTD7, 2U) +#define STOP_CHANNEL_1() gptStopTimer(&GPTD6) +#define STOP_CHANNEL_2() gptStopTimer(&GPTD7) +#define RESTART_CHANNEL_1() STOP_CHANNEL_1(); \ + START_CHANNEL_1() +#define RESTART_CHANNEL_2() STOP_CHANNEL_2(); \ + START_CHANNEL_2() +#define UPDATE_CHANNEL_1_FREQ(freq) gpt6cfg1.frequency = freq * DAC_BUFFER_SIZE; \ + RESTART_CHANNEL_1() +#define UPDATE_CHANNEL_2_FREQ(freq) gpt7cfg1.frequency = freq * DAC_BUFFER_SIZE; \ + RESTART_CHANNEL_2() +#define GET_CHANNEL_1_FREQ gpt6cfg1.frequency +#define GET_CHANNEL_2_FREQ gpt7cfg1.frequency + + /* * GPT6 configuration. */ +// static const GPTConfig gpt6cfg1 = { +// .frequency = 1000000U, +// .callback = NULL, +// .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ +// .dier = 0U +// }; + GPTConfig gpt6cfg1 = { - .frequency = 440, - .callback = gpt_cb6, + .frequency = 440U*DAC_BUFFER_SIZE, + .callback = NULL, .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ .dier = 0U }; GPTConfig gpt7cfg1 = { - .frequency = 440, - .callback = gpt_cb7, + .frequency = 440U*DAC_BUFFER_SIZE, + .callback = NULL, .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ .dier = 0U }; @@ -105,15 +130,169 @@ GPTConfig gpt8cfg1 = { .dier = 0U }; -static void gpt_cb6(GPTDriver *gptp) { - palTogglePad(GPIOA, 4); + +/* + * DAC test buffer (sine wave). + */ +// static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = { +// 2047, 2082, 2118, 2154, 2189, 2225, 2260, 2296, 2331, 2367, 2402, 2437, +// 2472, 2507, 2542, 2576, 2611, 2645, 2679, 2713, 2747, 2780, 2813, 2846, +// 2879, 2912, 2944, 2976, 3008, 3039, 3070, 3101, 3131, 3161, 3191, 3221, +// 3250, 3278, 3307, 3335, 3362, 3389, 3416, 3443, 3468, 3494, 3519, 3544, +// 3568, 3591, 3615, 3637, 3660, 3681, 3703, 3723, 3744, 3763, 3782, 3801, +// 3819, 3837, 3854, 3870, 3886, 3902, 3917, 3931, 3944, 3958, 3970, 3982, +// 3993, 4004, 4014, 4024, 4033, 4041, 4049, 4056, 4062, 4068, 4074, 4078, +// 4082, 4086, 4089, 4091, 4092, 4093, 4094, 4093, 4092, 4091, 4089, 4086, +// 4082, 4078, 4074, 4068, 4062, 4056, 4049, 4041, 4033, 4024, 4014, 4004, +// 3993, 3982, 3970, 3958, 3944, 3931, 3917, 3902, 3886, 3870, 3854, 3837, +// 3819, 3801, 3782, 3763, 3744, 3723, 3703, 3681, 3660, 3637, 3615, 3591, +// 3568, 3544, 3519, 3494, 3468, 3443, 3416, 3389, 3362, 3335, 3307, 3278, +// 3250, 3221, 3191, 3161, 3131, 3101, 3070, 3039, 3008, 2976, 2944, 2912, +// 2879, 2846, 2813, 2780, 2747, 2713, 2679, 2645, 2611, 2576, 2542, 2507, +// 2472, 2437, 2402, 2367, 2331, 2296, 2260, 2225, 2189, 2154, 2118, 2082, +// 2047, 2012, 1976, 1940, 1905, 1869, 1834, 1798, 1763, 1727, 1692, 1657, +// 1622, 1587, 1552, 1518, 1483, 1449, 1415, 1381, 1347, 1314, 1281, 1248, +// 1215, 1182, 1150, 1118, 1086, 1055, 1024, 993, 963, 933, 903, 873, +// 844, 816, 787, 759, 732, 705, 678, 651, 626, 600, 575, 550, +// 526, 503, 479, 457, 434, 413, 391, 371, 350, 331, 312, 293, +// 275, 257, 240, 224, 208, 192, 177, 163, 150, 136, 124, 112, +// 101, 90, 80, 70, 61, 53, 45, 38, 32, 26, 20, 16, +// 12, 8, 5, 3, 2, 1, 0, 1, 2, 3, 5, 8, +// 12, 16, 20, 26, 32, 38, 45, 53, 61, 70, 80, 90, +// 101, 112, 124, 136, 150, 163, 177, 192, 208, 224, 240, 257, +// 275, 293, 312, 331, 350, 371, 391, 413, 434, 457, 479, 503, +// 526, 550, 575, 600, 626, 651, 678, 705, 732, 759, 787, 816, +// 844, 873, 903, 933, 963, 993, 1024, 1055, 1086, 1118, 1150, 1182, +// 1215, 1248, 1281, 1314, 1347, 1381, 1415, 1449, 1483, 1518, 1552, 1587, +// 1622, 1657, 1692, 1727, 1763, 1798, 1834, 1869, 1905, 1940, 1976, 2012 +// }; + +// squarewave +static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = { + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// squarewave +static const dacsample_t dac_buffer_2[DAC_BUFFER_SIZE] = { + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * DAC streaming callback. + */ +size_t nx = 0, ny = 0, nz = 0; +static void end_cb1(DACDriver *dacp, dacsample_t *buffer, size_t n) { + + (void)dacp; + + nz++; + if (dac_buffer == buffer) { + nx += n; + } + else { + ny += n; + } + + if ((nz % 1000) == 0) { + // palTogglePad(GPIOD, GPIOD_LED3); + } } +/* + * DAC error callback. + */ +static void error_cb1(DACDriver *dacp, dacerror_t err) { + + (void)dacp; + (void)err; -static void gpt_cb7(GPTDriver *gptp) { - palTogglePad(GPIOA, 5); + chSysHalt("DAC failure"); } +static const DACConfig dac1cfg1 = { + .init = 2047U, + .datamode = DAC_DHRM_12BIT_RIGHT +}; + +static const DACConversionGroup dacgrpcfg1 = { + .num_channels = 1U, + .end_cb = end_cb1, + .error_cb = error_cb1, + .trigger = DAC_TRG(0) +}; + +static const DACConfig dac1cfg2 = { + .init = 2047U, + .datamode = DAC_DHRM_12BIT_RIGHT +}; + +static const DACConversionGroup dacgrpcfg2 = { + .num_channels = 1U, + .end_cb = end_cb1, + .error_cb = error_cb1, + .trigger = DAC_TRG(0) +}; + void audio_init() { @@ -128,8 +307,30 @@ void audio_init() // audio_config.raw = eeconfig_read_audio(); audio_config.enable = true; - palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); + /* + * Starting DAC1 driver, setting up the output pin as analog as suggested + * by the Reference Manual. + */ + palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); + palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); + dacStart(&DACD1, &dac1cfg1); + dacStart(&DACD2, &dac1cfg2); + + /* + * Starting GPT6 driver, it is used for triggering the DAC. + */ + START_CHANNEL_1(); + START_CHANNEL_2(); + + /* + * Starting a continuous conversion. + */ + dacStartConversion(&DACD1, &dacgrpcfg1, + (dacsample_t *)dac_buffer, DAC_BUFFER_SIZE); + dacStartConversion(&DACD2, &dacgrpcfg2, + (dacsample_t *)dac_buffer_2, DAC_BUFFER_SIZE); + // gptStartContinuous(&GPTD6, 2U); + audio_initialized = true; @@ -193,8 +394,8 @@ void stop_note(float freq) voice_place = 0; } if (voices == 0) { - gptStopTimer(&GPTD6); - gptStopTimer(&GPTD7); + STOP_CHANNEL_1(); + STOP_CHANNEL_2(); gptStopTimer(&GPTD8); frequency = 0; frequency_alt = 0; @@ -224,20 +425,6 @@ float vibrato(float average_freq) { #endif -static void restart_gpt6(void) { - // gptStopTimer(&GPTD6); - - gptStart(&GPTD6, &gpt6cfg1); - gptStartContinuous(&GPTD6, 2U); -} - -static void restart_gpt7(void) { - // gptStopTimer(&GPTD7); - - gptStart(&GPTD7, &gpt7cfg1); - gptStartContinuous(&GPTD7, 2U); -} - static void gpt_cb8(GPTDriver *gptp) { float freq; @@ -280,13 +467,10 @@ static void gpt_cb8(GPTDriver *gptp) { freq_alt = 30.52; } - if (gpt6cfg1.frequency != (uint16_t)freq_alt) { - gpt6cfg1.frequency = freq_alt; - restart_gpt6(); + if (GET_CHANNEL_2_FREQ != (uint16_t)freq_alt) { + UPDATE_CHANNEL_2_FREQ(freq_alt); } //note_timbre; - } else { - // gptStopTimer(&GPTD6); } if (polyphony_rate > 0) { @@ -342,13 +526,10 @@ static void gpt_cb8(GPTDriver *gptp) { } - if (gpt7cfg1.frequency != (uint16_t)freq) { - gpt7cfg1.frequency = freq; - restart_gpt7(); + if (GET_CHANNEL_1_FREQ != (uint16_t)freq) { + UPDATE_CHANNEL_1_FREQ(freq); } //note_timbre; - } else { - // gptStopTimer(&GPTD7); } } @@ -370,11 +551,9 @@ static void gpt_cb8(GPTDriver *gptp) { freq = voice_envelope(freq); - if (gpt6cfg1.frequency != (uint16_t)freq) { - gpt6cfg1.frequency = freq; - restart_gpt6(); - gpt7cfg1.frequency = freq; - restart_gpt7(); + if (GET_CHANNEL_1_FREQ != (uint16_t)freq) { + UPDATE_CHANNEL_1_FREQ(freq); + UPDATE_CHANNEL_2_FREQ(freq); } //note_timbre; } else { @@ -384,8 +563,8 @@ static void gpt_cb8(GPTDriver *gptp) { note_position++; bool end_of_note = false; - if (gpt6cfg1.frequency > 0) { - if (!note_resting) + if (GET_CHANNEL_1_FREQ > 0) { + if (!note_resting) end_of_note = (note_position >= (note_length*16 - 1)); else end_of_note = (note_position >= (note_length*16)); @@ -399,8 +578,8 @@ static void gpt_cb8(GPTDriver *gptp) { if (notes_repeat) { current_note = 0; } else { - gptStopTimer(&GPTD6); - gptStopTimer(&GPTD7); + STOP_CHANNEL_1(); + STOP_CHANNEL_2(); // gptStopTimer(&GPTD8); playing_notes = false; return; @@ -459,7 +638,8 @@ void play_note(float freq, int vol) { gptStart(&GPTD8, &gpt8cfg1); gptStartContinuous(&GPTD8, 2U); - + RESTART_CHANNEL_1(); + RESTART_CHANNEL_2(); } } @@ -492,8 +672,8 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) gptStart(&GPTD8, &gpt8cfg1); gptStartContinuous(&GPTD8, 2U); - restart_gpt6(); - restart_gpt7(); + RESTART_CHANNEL_1(); + RESTART_CHANNEL_2(); } } |