From 53362b81cceba396c11c98e71eb96fb5ec77d6fd Mon Sep 17 00:00:00 2001
From: Bob-the-Kuhn <bob.kuhn@att.net>
Date: Mon, 19 Mar 2018 04:48:06 -0500
Subject: [PATCH] Tone fixes/changes (#10151)

---
 Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp | 17 +++++++++--------
 Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h   | 12 ++++++++++++
 Marlin/src/HAL/HAL_DUE/Tone.cpp           | 10 +++++++---
 Marlin/src/Marlin.cpp                     |  2 +-
 4 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp b/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp
index 43e8a0691e..06b6d25b89 100644
--- a/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp
+++ b/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.cpp
@@ -61,15 +61,15 @@
 // --------------------------------------------------------------------------
 
 const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
-  { TC0, 0, TC0_IRQn, 0},  // 0 - [servo timer5]
-  { TC0, 1, TC1_IRQn, 0},  // 1
-  { TC0, 2, TC2_IRQn, 0},  // 2
-  { TC1, 0, TC3_IRQn, 2},  // 3 - stepper
+  { TC0, 0, TC0_IRQn,  0}, // 0 - [servo timer5]
+  { TC0, 1, TC1_IRQn,  0}, // 1
+  { TC0, 2, TC2_IRQn,  0}, // 2
+  { TC1, 0, TC3_IRQn,  2}, // 3 - stepper
   { TC1, 1, TC4_IRQn, 15}, // 4 - temperature
-  { TC1, 2, TC5_IRQn, 0},  // 5 - [servo timer3]
-  { TC2, 0, TC6_IRQn, 0},  // 6 - tone
-  { TC2, 1, TC7_IRQn, 0},  // 7
-  { TC2, 2, TC8_IRQn, 0},  // 8
+  { TC1, 2, TC5_IRQn,  0}, // 5 - [servo timer3]
+  { TC2, 0, TC6_IRQn, 15}, // 6 - tone
+  { TC2, 1, TC7_IRQn,  0}, // 7
+  { TC2, 2, TC8_IRQn,  0}, // 8
 };
 
 // --------------------------------------------------------------------------
@@ -100,6 +100,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
   pmc_enable_periph_clk((uint32_t)irq);
   NVIC_SetPriority(irq, TimerConfig [timer_num].priority);
 
+  // wave mode, reset counter on match with RC,
   TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
 
   TC_SetRC(tc, channel, VARIANT_MCK / 2 / frequency);
diff --git a/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h b/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h
index a38bc6978c..0429746e6b 100644
--- a/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h
+++ b/Marlin/src/HAL/HAL_DUE/HAL_timers_Due.h
@@ -109,11 +109,23 @@ FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
   return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_CV;
 }
 
+FORCE_INLINE static void HAL_timer_set_count(const uint8_t timer_num, const hal_timer_t counter) {
+  const tTimerConfig * const pConfig = &TimerConfig[timer_num];
+  pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_CV = counter;
+}
+
+// if counter too high then bump up compare
 FORCE_INLINE static void HAL_timer_restrain(const uint8_t timer_num, const uint16_t interval_ticks) {
   const hal_timer_t mincmp = HAL_timer_get_count(timer_num) + interval_ticks;
   if (HAL_timer_get_compare(timer_num) < mincmp) HAL_timer_set_compare(timer_num, mincmp);
 }
 
+// if counter too high then clear it
+FORCE_INLINE static void HAL_timer_restrain_count(const uint8_t timer_num, const uint16_t interval_ticks) {
+  const hal_timer_t mincmp = HAL_timer_get_count(timer_num) + interval_ticks;
+  if (HAL_timer_get_compare(timer_num) < mincmp) HAL_timer_set_count(timer_num, 0);
+}
+
 void HAL_timer_enable_interrupt(const uint8_t timer_num);
 void HAL_timer_disable_interrupt(const uint8_t timer_num);
 bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
diff --git a/Marlin/src/HAL/HAL_DUE/Tone.cpp b/Marlin/src/HAL/HAL_DUE/Tone.cpp
index 88f92243e3..1b8a3122b7 100644
--- a/Marlin/src/HAL/HAL_DUE/Tone.cpp
+++ b/Marlin/src/HAL/HAL_DUE/Tone.cpp
@@ -34,13 +34,15 @@ static pin_t tone_pin;
 volatile static int32_t toggles;
 
 void toneInit() {
-  HAL_timer_start(TONE_TIMER_NUM, 1); // Lowest frequency possible
+  HAL_timer_start(TONE_TIMER_NUM, 100000);
+  HAL_timer_disable_interrupt(TONE_TIMER_NUM);
 }
 
 void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) {
   tone_pin = _pin;
   toggles = 2 * frequency * duration / 1000;
-  HAL_timer_set_compare(TONE_TIMER_NUM, VARIANT_MCK / 2 / frequency); // 84MHz / 2 prescaler / Hz
+  HAL_timer_set_count(TONE_TIMER_NUM, 0);  // ensure first beep is correct (make sure counter is less than the compare value)
+  HAL_timer_set_compare(TONE_TIMER_NUM, VARIANT_MCK / 2 / 2 / frequency); // 84MHz / 2 prescaler / 2 interrupts per cycle /Hz
   HAL_timer_enable_interrupt(TONE_TIMER_NUM);
 }
 
@@ -52,11 +54,13 @@ void noTone(const pin_t _pin) {
 HAL_TONE_TIMER_ISR {
   static uint8_t pin_state = 0;
   HAL_timer_isr_prologue(TONE_TIMER_NUM);
+
   if (toggles) {
     toggles--;
     digitalWrite(tone_pin, (pin_state ^= 1));
   }
-  else noTone(tone_pin);                                  // seems superfluous ?
+  else noTone(tone_pin);                         // turn off interrupt
+  HAL_timer_restrain_count(TONE_TIMER_NUM, 10);  // make sure next ISR isn't delayed by up to 2 minutes
 }
 
 #endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp
index c70988fadf..5ffd30f539 100644
--- a/Marlin/src/Marlin.cpp
+++ b/Marlin/src/Marlin.cpp
@@ -648,7 +648,7 @@ void setup() {
 
   #ifdef HAL_INIT
     HAL_init();
-    #if defined(ARDUINO_ARCH_SAM) && PIN_EXISTS(BEEPER)
+    #if defined(ARDUINO_ARCH_SAM) && PIN_EXISTS(BEEPER) && ENABLED(SPEAKER)
       toneInit();
     #endif
   #endif