]> git.earman.xyz Git - sensor-watch.git/commitdiff
Fix LED flickering while the buzzer is playing
authorAlessandro Genova <ales.genova@gmail.com>
Sat, 16 Aug 2025 01:34:29 +0000 (21:34 -0400)
committerAlessandro Genova <ales.genova@gmail.com>
Sat, 3 Jan 2026 01:07:56 +0000 (20:07 -0500)
watch-library/hardware/watch/watch_tcc.c

index 8624ffccbec54026d5b40518eb6c0437f80db7b0..fa81d0749b08b6da12987ebe2b050af4b6693235 100644 (file)
@@ -43,6 +43,9 @@ static watch_cb_t _cb_start_global = NULL;
 static watch_cb_t _cb_stop_global = NULL;
 static volatile bool _led_is_active = false;
 static volatile bool _buzzer_is_active = false;
+static volatile uint8_t _current_led_color[3] = {0, 0, 0};
+
+static void _watch_set_led_duty_cycle(uint32_t period, uint8_t red, uint8_t green, uint8_t blue);
 
 static void _tcc_write_RUNSTDBY(bool value) {
     // enables or disables RUNSTDBY of the tcc
@@ -276,6 +279,11 @@ void watch_enable_buzzer(void) {
 void watch_set_buzzer_period_and_duty_cycle(uint32_t period, uint8_t duty) {
     tcc_set_period(0, period, true);
     tcc_set_cc(0, (WATCH_BUZZER_TCC_CHANNEL) % 4, period / (100 / duty), true);
+    // The buzzer determines the period, which means that if the LED was active before it will flicker
+    // Update the LED duty cycle to match the new period required by the buzzer.
+    if (_led_is_active) {
+        _watch_set_led_duty_cycle(period, _current_led_color[0], _current_led_color[1], _current_led_color[2]);
+    }
 }
 
 void watch_disable_buzzer(void) {
@@ -400,10 +408,27 @@ void watch_set_led_color(uint8_t red, uint8_t green) {
 #endif
 }
 
+static void _watch_set_led_duty_cycle(uint32_t period, uint8_t red, uint8_t green, uint8_t blue) {
+    tcc_set_cc(0, (WATCH_RED_TCC_CHANNEL) % 4, ((period * (uint32_t)red * 1000ull) / 255000ull), true);
+#ifdef WATCH_GREEN_TCC_CHANNEL
+    tcc_set_cc(0, (WATCH_GREEN_TCC_CHANNEL) % 4, ((period * (uint32_t)green * 1000ull) / 255000ull), true);
+#else
+    (void) green; // silence warning
+#endif
+#ifdef WATCH_BLUE_TCC_CHANNEL
+    tcc_set_cc(0, (WATCH_BLUE_TCC_CHANNEL) % 4, ((period * (uint32_t)blue * 1000ull) / 255000ull), true);
+#else
+    (void) blue; // silence warning
+#endif
+}
+
 void watch_set_led_color_rgb(uint8_t red, uint8_t green, uint8_t blue) {
     bool turning_on = (red | green | blue) != 0;
 
     if (turning_on) {
+        _current_led_color[0] = red;
+        _current_led_color[1] = green;
+        _current_led_color[2] = blue;
         _led_is_active = true;
         watch_enable_buzzer_and_leds();
     } else {
@@ -412,17 +437,7 @@ void watch_set_led_color_rgb(uint8_t red, uint8_t green, uint8_t blue) {
 
     if (tcc_is_enabled(0)) {
         uint32_t period = tcc_get_period(0);
-        tcc_set_cc(0, (WATCH_RED_TCC_CHANNEL) % 4, ((period * (uint32_t)red * 1000ull) / 255000ull), true);
-#ifdef WATCH_GREEN_TCC_CHANNEL
-        tcc_set_cc(0, (WATCH_GREEN_TCC_CHANNEL) % 4, ((period * (uint32_t)green * 1000ull) / 255000ull), true);
-#else
-        (void) green; // silence warning
-#endif
-#ifdef WATCH_BLUE_TCC_CHANNEL
-        tcc_set_cc(0, (WATCH_BLUE_TCC_CHANNEL) % 4, ((period * (uint32_t)blue * 1000ull) / 255000ull), true);
-#else
-        (void) blue; // silence warning
-#endif
+        _watch_set_led_duty_cycle(period, red, green, blue);
     }
 
     if (!turning_on) {