From 17295648c9a12d6168c311ce64ae1408bbd2c8df Mon Sep 17 00:00:00 2001 From: kisslorand Date: Wed, 27 Sep 2023 10:22:12 +0300 Subject: [PATCH] Buzzer - No polling --- TFT/src/User/API/BuzzerControl.c | 68 ++++++------- TFT/src/User/API/interfaceCmd.c | 2 +- TFT/src/User/API/menu.c | 5 - TFT/src/User/Hal/buzzer.c | 157 ++++++++++++++++++++----------- TFT/src/User/Hal/buzzer.h | 9 +- 5 files changed, 140 insertions(+), 101 deletions(-) diff --git a/TFT/src/User/API/BuzzerControl.c b/TFT/src/User/API/BuzzerControl.c index 6a55f30963..0d871954df 100644 --- a/TFT/src/User/API/BuzzerControl.c +++ b/TFT/src/User/API/BuzzerControl.c @@ -51,93 +51,93 @@ void Buzzer_play(SOUND sound) case SOUND_OK: if (GET_BIT(infoSettings.sounds, SOUND_TYPE_ALERT)) { - Buzzer_TurnOn(A_BASE, 50); - Buzzer_TurnOn(SILENCE, 40); - Buzzer_TurnOn(E_OCTAVE1, 50); + Buzzer_AddSound(A_BASE, 50); + Buzzer_AddSound(SILENCE, 40); + Buzzer_AddSound(E_OCTAVE1, 50); } break; case SOUND_SUCCESS: if (GET_BIT(infoSettings.sounds, SOUND_TYPE_ALERT)) { - Buzzer_TurnOn(A_BASE, 50); - Buzzer_TurnOn(SILENCE, 50); - Buzzer_TurnOn(A_BASE, 50); - Buzzer_TurnOn(SILENCE, 50); - Buzzer_TurnOn(A_BASE, 50); + Buzzer_AddSound(A_BASE, 50); + Buzzer_AddSound(SILENCE, 50); + Buzzer_AddSound(A_BASE, 50); + Buzzer_AddSound(SILENCE, 50); + Buzzer_AddSound(A_BASE, 50); } break; case SOUND_CANCEL: if (GET_BIT(infoSettings.sounds, SOUND_TYPE_ALERT)) { - Buzzer_TurnOn(E_OCTAVE1, 50); - Buzzer_TurnOn(SILENCE, 20); - Buzzer_TurnOn(A_BASE, 40); + Buzzer_AddSound(E_OCTAVE1, 50); + Buzzer_AddSound(SILENCE, 20); + Buzzer_AddSound(A_BASE, 40); } break; case SOUND_NOTIFY: if (GET_BIT(infoSettings.sounds, SOUND_TYPE_ALERT)) { - Buzzer_TurnOn(G_BASE, 50); - Buzzer_TurnOn(SILENCE, 50); - Buzzer_TurnOn(C_OCTAVE1, 50); + Buzzer_AddSound(G_BASE, 50); + Buzzer_AddSound(SILENCE, 50); + Buzzer_AddSound(C_OCTAVE1, 50); } break; case SOUND_ERROR: { - Buzzer_TurnOn(C_SHARP_BASE, 200); - Buzzer_TurnOn(SILENCE, 60); - Buzzer_TurnOn(C_SHARP_BASE, 200); - Buzzer_TurnOn(SILENCE, 60); - Buzzer_TurnOn(C_SHARP_BASE, 200); + Buzzer_AddSound(C_SHARP_BASE, 200); + Buzzer_AddSound(SILENCE, 60); + Buzzer_AddSound(C_SHARP_BASE, 200); + Buzzer_AddSound(SILENCE, 60); + Buzzer_AddSound(C_SHARP_BASE, 200); } break; case SOUND_DENY: if (GET_BIT(infoSettings.sounds, SOUND_TYPE_ALERT)) { - Buzzer_TurnOn(B_SUBOCTAVE3, 10); - Buzzer_TurnOn(E_OCTAVE2, 20); + Buzzer_AddSound(B_SUBOCTAVE3, 10); + Buzzer_AddSound(E_OCTAVE2, 20); } break; case SOUND_TOAST: if (GET_BIT(infoSettings.sounds, SOUND_TYPE_TOAST)) { - Buzzer_TurnOn(F_SHARP_SUBOCTAVE1, 30); - Buzzer_TurnOn(B_SUBOCTAVE1, 30); + Buzzer_AddSound(F_SHARP_SUBOCTAVE1, 30); + Buzzer_AddSound(B_SUBOCTAVE1, 30); } break; case SOUND_HEATED: if (GET_BIT(infoSettings.sounds, SOUND_TYPE_HEATER)) { - Buzzer_TurnOn(G_BASE, 50); - Buzzer_TurnOn(SILENCE, 50); - Buzzer_TurnOn(B_BASE, 50); - Buzzer_TurnOn(SILENCE, 100); - Buzzer_TurnOn(B_BASE, 50); + Buzzer_AddSound(G_BASE, 50); + Buzzer_AddSound(SILENCE, 50); + Buzzer_AddSound(B_BASE, 50); + Buzzer_AddSound(SILENCE, 100); + Buzzer_AddSound(B_BASE, 50); } break; case SOUND_COOLED: if (GET_BIT(infoSettings.sounds, SOUND_TYPE_HEATER)) { - Buzzer_TurnOn(B_BASE, 50); - Buzzer_TurnOn(SILENCE, 50); - Buzzer_TurnOn(G_BASE, 50); - Buzzer_TurnOn(SILENCE, 100); - Buzzer_TurnOn(G_BASE, 50); + Buzzer_AddSound(B_BASE, 50); + Buzzer_AddSound(SILENCE, 50); + Buzzer_AddSound(G_BASE, 50); + Buzzer_AddSound(SILENCE, 100); + Buzzer_AddSound(G_BASE, 50); } break; case SOUND_KEYPRESS: default: if (GET_BIT(infoSettings.sounds, SOUND_TYPE_TOUCH)) - Buzzer_TurnOn(BUZZER_FREQUENCY_HZ, BUZZER_FREQUENCY_DURATION_MS); + Buzzer_AddSound(BUZZER_FREQUENCY_HZ, BUZZER_FREQUENCY_DURATION_MS); break; } } // Buzzer_play diff --git a/TFT/src/User/API/interfaceCmd.c b/TFT/src/User/API/interfaceCmd.c index 8173857671..f7e387ffa7 100644 --- a/TFT/src/User/API/interfaceCmd.c +++ b/TFT/src/User/API/interfaceCmd.c @@ -1150,7 +1150,7 @@ void sendQueueCmd(void) { uint16_t ms = cmd_value(); - Buzzer_TurnOn(hz, ms); + Buzzer_AddSound(hz, ms); if (!fromTFT && cmd_seen_from(cmd_base_index, "TFT")) // "M300 TFT" { diff --git a/TFT/src/User/API/menu.c b/TFT/src/User/API/menu.c index acfdadf89b..634ba330b6 100644 --- a/TFT/src/User/API/menu.c +++ b/TFT/src/User/API/menu.c @@ -1236,11 +1236,6 @@ void loopBackEnd(void) // Speed & flow monitor loopSpeed(); - // Buzzer handling - #ifdef BUZZER_PIN - loopBuzzer(); - #endif - // Handle a print from (remote) onboard media, if any if (infoMachineSettings.onboardSD == ENABLED) loopPrintFromOnboard(); diff --git a/TFT/src/User/Hal/buzzer.c b/TFT/src/User/Hal/buzzer.c index 2defc7591a..cedcfbd768 100644 --- a/TFT/src/User/Hal/buzzer.c +++ b/TFT/src/User/Hal/buzzer.c @@ -15,11 +15,10 @@ typedef struct uint16_t count; } BUZZER; -static BUZZER buzzer; -volatile uint32_t buzzerEndTime = 0; +volatile static BUZZER buzzer; volatile uint32_t toggles = 0; -void TIM3_Config(void) +static inline void BuzzerTimerConfig(void) { #ifdef GD32F2XX nvic_irq_enable(TIMER2_IRQn, 1U, 0U); @@ -28,7 +27,10 @@ void TIM3_Config(void) TIMER_CTL0(TIMER2) &= ~TIMER_CTL0_CEN; TIMER_DMAINTEN(TIMER2) |= TIMER_DMAINTEN_UPIE; TIMER_INTF(TIMER2) &= ~TIMER_INTF_UPIF; - TIMER_CAR(TIMER2) = mcuClocks.PCLK1_Timer_Frequency / 1000000 - 1; + + // initial values + TIMER_CAR(TIMER2) = 10 - 1; + TIMER_PSC(TIMER2) = mcuClocks.PCLK1_Timer_Frequency / 1000000 - 1; #else NVIC_InitTypeDef NVIC_InitStructure; @@ -42,7 +44,10 @@ void TIM3_Config(void) TIM3->CR1 &= ~TIM_CR1_CEN; TIM3->DIER |= TIM_DIER_UIE; TIM3->SR &= ~TIM_SR_UIF; - TIM3->ARR = mcuClocks.PCLK1_Timer_Frequency / 1000000 - 1; // 20hz to 1Mhz + + // initial values + TIM3->ARR = 10 - 1; + TIM3->PSC = mcuClocks.PCLK1_Timer_Frequency / 1000000 - 1; #endif } @@ -58,7 +63,40 @@ void TIMER2_IRQHandler(void) } else { - TIMER_CTL0(TIMER2) &= ~TIMER_CTL0_CEN; // stop timer + TIMER_CTL0(TIMER2) &= ~TIMER_CTL0_CEN; // disable timer + TIMER_CNT(TIMER2) = 0; + + if (buzzer.count == 0) // end sound generation + { + GPIO_SetLevel(BUZZER_PIN, BUZZER_STOP_LEVEL); + + // initial values + TIMER_CAR(TIMER2) = 10 - 1; + TIMER_PSC(TIMER2) = mcuClocks.PCLK1_Timer_Frequency / 1000000 - 1; + } + else // step to the sound to play + { + toggles = 2 * ((buzzer.frequency[buzzer.rIndex]) * buzzer.duration[buzzer.rIndex] / 1000); // must have an even value + + if (buzzer.frequency[buzzer.rIndex] == 0) // handle pause (silence) + { // handle pause (silence) + TIMER_CAR(TIMER2) = (10 * buzzer.duration[buzzer.rIndex]) - 1; // keep values in range (TIMER2 CAR is only 16 bit) + TIMER_PSC(TIMER2) = mcuClocks.PCLK1_Timer_Frequency / 10000 - 1; // keep values in range (TIMER2 PSC is only 16 bit) + } + else + { // handle sound + TIMER_CAR(TIMER2) = (1000000 / (2 * buzzer.frequency[buzzer.rIndex])) - 1; // keep values in range (TIMER2 CAR is only 16 bit) + TIMER_PSC(TIMER2) = mcuClocks.PCLK1_Timer_Frequency / 1000000 - 1; // keep values in range (TIMER2 PSC is only 16 bit) + } + + TIMER_SWEVG(TIMER2) |= TIMER_SWEVG_UPG; // initialize PSC and CAR + TIMER_CTL0(TIMER2) |= TIMER_CTL0_CEN; // re-enable timer + + if (++buzzer.rIndex == BUZZER_CACHE_SIZE) + buzzer.rIndex = 0; + + buzzer.count--; + } } TIMER_INTF(TIMER2) &= ~TIMER_INTF_UPIF; // clear interrupt flag } @@ -76,6 +114,39 @@ void TIM3_IRQHandler(void) else { TIM3->CR1 &= ~TIM_CR1_CEN; // stop timer + TIM3->CNT = 0; + + if (buzzer.count == 0) // end sound generation + { + GPIO_SetLevel(BUZZER_PIN, BUZZER_STOP_LEVEL); + + // initial values + TIM3->ARR = 10 - 1; + TIM3->PSC = mcuClocks.PCLK1_Timer_Frequency / 1000000 - 1; + } + else // step to the sound to play + { + toggles = 2 * ((buzzer.frequency[buzzer.rIndex]) * buzzer.duration[buzzer.rIndex] / 1000); // must have an even value + + if (buzzer.frequency[buzzer.rIndex] == 0) // handle pause (silence) + { // handle pause (silence) + TIM3->ARR = (10 * buzzer.duration[buzzer.rIndex]) - 1; // keep values in range (TIMER3 ARR is only 16 bit) + TIM3->PSC = mcuClocks.PCLK1_Timer_Frequency / 10000 - 1; // keep values in range (TIMER3 PSC is only 16 bit) + } + else + { // handle sound + TIM3->ARR = (1000000 / (2 * buzzer.frequency[buzzer.rIndex])) - 1; // keep values in range (TIMER3 ARR is only 16 bit) + TIM3->PSC = mcuClocks.PCLK1_Timer_Frequency / 1000000 - 1; // keep values in range (TIMER3 PSC is only 16 bit) + } + + TIM3->EGR |= TIM_EGR_UG; // initialize PSC and ARR + TIM3->CR1 |= TIM_CR1_CEN; // re-enable timer + + if (++buzzer.rIndex == BUZZER_CACHE_SIZE) + buzzer.rIndex = 0; + + buzzer.count--; + } } TIM3->SR &= ~TIM_SR_UIF; // clear interrupt flag } @@ -85,7 +156,7 @@ void TIM3_IRQHandler(void) void Buzzer_Config(void) { GPIO_InitSet(BUZZER_PIN, MGPIO_MODE_OUT_PP, 0); - TIM3_Config(); + BuzzerTimerConfig(); } void Buzzer_DeConfig(void) @@ -93,67 +164,39 @@ void Buzzer_DeConfig(void) GPIO_InitSet(BUZZER_PIN, MGPIO_MODE_IPN, 0); } -void Buzzer_TurnOn(const uint16_t frequency, const uint16_t duration) +void Buzzer_AddSound(const uint16_t frequency, const uint16_t duration) { - while (buzzer.count == BUZZER_CACHE_SIZE) - { - loopBuzzer(); - } + // If the sound cache is full than the oldest sound data + // will be overwritten with the newest one that arrives. + buzzer.duration[buzzer.wIndex] = duration; buzzer.frequency[buzzer.wIndex] = frequency; - buzzer.wIndex = (buzzer.wIndex + 1) % BUZZER_CACHE_SIZE; - buzzer.count++; -} - -void tone(const uint16_t frequency, const uint16_t duration) -{ - if (frequency == 0 || duration == 0) return; -#ifdef GD32F2XX - nvic_irq_disable(TIMER2_IRQn); - toggles = 2 * (frequency * duration / 1000); // must have an even value - - TIMER_CTL0(TIMER2) &= ~TIMER_CTL0_CEN; // disable timer2 - TIMER_CNT(TIMER2) = 0; - TIMER_PSC(TIMER2) = (1000000 / (2 * frequency)) - 1; - TIMER_CTL0(TIMER2) |= TIMER_CTL0_CEN; - - nvic_irq_enable(TIMER2_IRQn, 1, 0); -#else - NVIC_DisableIRQ(TIM3_IRQn); - toggles = 2 * (frequency * duration / 1000); // must have an even value - - TIM3->CR1 &= ~TIM_CR1_CEN; - TIM3->CNT =0; - TIM3->PSC = (1000000 / (2 * frequency)) - 1; - TIM3->CR1 |= TIM_CR1_CEN; - NVIC_EnableIRQ(TIM3_IRQn); -#endif -} + if (++buzzer.wIndex == BUZZER_CACHE_SIZE) + buzzer.wIndex = 0; -void loopBuzzer(void) -{ - if (!buzzerEndTime) + if (buzzer.count == BUZZER_CACHE_SIZE) { - if (buzzer.count == 0) return; - buzzerEndTime = OS_GetTimeMs() + buzzer.duration[buzzer.rIndex]; - if (buzzer.frequency[buzzer.rIndex] > 0) - { - tone(buzzer.frequency[buzzer.rIndex], buzzer.duration[buzzer.rIndex]); - } - buzzer.rIndex = (buzzer.rIndex + 1) % BUZZER_CACHE_SIZE; - buzzer.count--; + // disable timer to avoid an eventual race condition + #ifdef GD32F2XX + TIMER_CTL0(TIMER2) &= ~TIMER_CTL0_CEN; + #else + TIM3->CR1 &= ~TIM_CR1_CEN; + #endif + + buzzer.rIndex = buzzer.wIndex; } - else if (OS_GetTimeMs() > buzzerEndTime && toggles == 0) + else { - buzzerEndTime = 0; + buzzer.count++; + } + + // (re)enable timer #ifdef GD32F2XX - TIMER_CTL0(TIMER2) &= ~TIMER_CTL0_CEN; + TIMER_CTL0(TIMER2) |= TIMER_CTL0_CEN; #else - TIM3->CR1 &= ~TIM_CR1_CEN; // stop timer (for safety) + TIM3->CR1 |= TIM_CR1_CEN; #endif - GPIO_SetLevel(BUZZER_PIN, BUZZER_STOP_LEVEL); - } } #endif // BUZZER_PIN diff --git a/TFT/src/User/Hal/buzzer.h b/TFT/src/User/Hal/buzzer.h index bce9521e1c..f1fe01ae34 100644 --- a/TFT/src/User/Hal/buzzer.h +++ b/TFT/src/User/Hal/buzzer.h @@ -9,10 +9,11 @@ extern "C" { #include "variants.h" // for BUZZER_PIN etc... #ifdef BUZZER_PIN - void Buzzer_Config(void); - void Buzzer_DeConfig(void); - void Buzzer_TurnOn(const uint16_t frequency, const uint16_t duration); - void loopBuzzer(void); + +void Buzzer_Config(void); +void Buzzer_DeConfig(void); +void Buzzer_AddSound(const uint16_t frequency, const uint16_t duration); + #endif #ifdef __cplusplus