123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- #include "audio.h"
- #include "ch.h"
- #include "hal.h"
- #if !defined(AUDIO_PIN)
- # error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings"
- #endif
- extern bool playing_note;
- extern bool playing_melody;
- extern uint8_t note_timbre;
- static void pwm_audio_period_callback(PWMDriver *pwmp);
- static void pwm_audio_channel_interrupt_callback(PWMDriver *pwmp);
- static PWMConfig pwmCFG = {
- .frequency = 100000,
-
- .period = 2,
- .callback = pwm_audio_period_callback,
- .channels =
- {
-
- {PWM_OUTPUT_ACTIVE_HIGH, pwm_audio_channel_interrupt_callback},
- {PWM_OUTPUT_DISABLED, NULL},
- {PWM_OUTPUT_DISABLED, NULL},
- {PWM_OUTPUT_DISABLED, NULL}
- },
- };
- static float channel_1_frequency = 0.0f;
- void channel_1_set_frequency(float freq) {
- channel_1_frequency = freq;
- if (freq <= 0.0)
- return;
- pwmcnt_t period = (pwmCFG.frequency / freq);
- pwmChangePeriod(&AUDIO_PWM_DRIVER, period);
- pwmEnableChannel(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1,
-
- PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100));
- }
- float channel_1_get_frequency(void) { return channel_1_frequency; }
- void channel_1_start(void) {
- pwmStop(&AUDIO_PWM_DRIVER);
- pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
- pwmEnablePeriodicNotification(&AUDIO_PWM_DRIVER);
- pwmEnableChannelNotification(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1);
- }
- void channel_1_stop(void) {
- pwmStop(&AUDIO_PWM_DRIVER);
- palClearLine(AUDIO_PIN);
- #if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE)
- palClearLine(AUDIO_PIN_ALT);
- #endif
- }
- static void pwm_audio_period_callback(PWMDriver *pwmp) {
- (void)pwmp;
- palClearLine(AUDIO_PIN);
- #if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE)
- palSetLine(AUDIO_PIN_ALT);
- #endif
- }
- static void pwm_audio_channel_interrupt_callback(PWMDriver *pwmp) {
- (void)pwmp;
- if (channel_1_frequency > 0) {
- palSetLine(AUDIO_PIN);
- #if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE)
- palClearLine(AUDIO_PIN_ALT);
- #endif
- }
- }
- static void gpt_callback(GPTDriver *gptp);
- GPTConfig gptCFG = {
-
- .frequency = 60 * 64,
- .callback = gpt_callback,
- };
- void audio_driver_initialize(void) {
- pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
- palSetLineMode(AUDIO_PIN, PAL_MODE_OUTPUT_PUSHPULL);
- palClearLine(AUDIO_PIN);
- #if defined(AUDIO_PIN_ALT) && defined(AUDIO_PIN_ALT_AS_NEGATIVE)
- palSetLineMode(AUDIO_PIN_ALT, PAL_MODE_OUTPUT_PUSHPULL);
- palClearLine(AUDIO_PIN_ALT);
- #endif
- pwmEnablePeriodicNotification(&AUDIO_PWM_DRIVER);
- pwmEnableChannelNotification(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1);
- gptStart(&AUDIO_STATE_TIMER, &gptCFG);
- }
- void audio_driver_start(void) {
- channel_1_stop();
- channel_1_start();
- if (playing_note || playing_melody) {
- gptStartContinuous(&AUDIO_STATE_TIMER, 64);
- }
- }
- void audio_driver_stop(void) {
- channel_1_stop();
- gptStopTimer(&AUDIO_STATE_TIMER);
- }
- static void gpt_callback(GPTDriver *gptp) {
- float freq;
- if (audio_update_state()) {
- freq = audio_get_processed_frequency(0);
- channel_1_set_frequency(freq);
- }
- }
|