consolidate buzzer and LED into TCC file

This commit is contained in:
joeycastillo 2024-09-18 14:53:46 -04:00
parent 29f020e207
commit 0585a1d0d8
8 changed files with 163 additions and 252 deletions

View File

@ -29,9 +29,8 @@ INCLUDES += \
# Add your source files here. # Add your source files here.
SRCS += \ SRCS += \
./watch-library/hardware/watch/watch_buzzer.c \
./watch-library/hardware/watch/watch_gpio.c \ ./watch-library/hardware/watch/watch_gpio.c \
./watch-library/hardware/watch/watch_led.c \ ./watch-library/hardware/watch/watch_tcc.c \
./app.c \ ./app.c \
# Finally, leave this line at the bottom of the file. # Finally, leave this line at the bottom of the file.

View File

@ -1,80 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 Joey Castillo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "watch_led.h"
#include "watch_private.h"
#include "tcc.h"
void _watch_enable_tcc(void);
void watch_enable_leds(void) {
if (!tcc_is_enabled(0)) {
_watch_enable_tcc();
}
}
void watch_disable_leds(void) {
_watch_disable_tcc();
}
void watch_set_led_color(uint8_t red, uint8_t green) {
#ifdef WATCH_BLUE_TCC_CHANNEL
watch_set_led_color_rgb(red, green, 0);
#else
watch_set_led_color_rgb(red, green, green);
#endif
}
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
}
}
void watch_set_led_red(void) {
watch_set_led_color_rgb(255, 0, 0);
}
void watch_set_led_green(void) {
watch_set_led_color_rgb(0, 255, 0);
}
void watch_set_led_yellow(void) {
watch_set_led_color_rgb(255, 255, 0);
}
void watch_set_led_off(void) {
watch_set_led_color_rgb(0, 0, 0);
}

View File

@ -22,12 +22,12 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include "watch_buzzer.h" #include "watch_tcc.h"
#include "watch_private.h"
#include "delay.h" #include "delay.h"
#include "tcc.h" #include "tcc.h"
void _watch_enable_tcc(void); void _watch_enable_tcc(void);
void _watch_disable_tcc(void);
bool watch_is_buzzer_or_led_enabled(void){ bool watch_is_buzzer_or_led_enabled(void){
return tcc_is_enabled(0); return tcc_is_enabled(0);
@ -139,3 +139,54 @@ void _watch_disable_tcc(void) {
#endif #endif
tcc_disable(0); tcc_disable(0);
} }
void watch_enable_leds(void) {
if (!tcc_is_enabled(0)) {
_watch_enable_tcc();
}
}
void watch_disable_leds(void) {
_watch_disable_tcc();
}
void watch_set_led_color(uint8_t red, uint8_t green) {
#ifdef WATCH_BLUE_TCC_CHANNEL
watch_set_led_color_rgb(red, green, 0);
#else
watch_set_led_color_rgb(red, green, green);
#endif
}
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
}
}
void watch_set_led_red(void) {
watch_set_led_color_rgb(255, 0, 0);
}
void watch_set_led_green(void) {
watch_set_led_color_rgb(0, 255, 0);
}
void watch_set_led_yellow(void) {
watch_set_led_color_rgb(255, 255, 0);
}
void watch_set_led_off(void) {
watch_set_led_color_rgb(0, 0, 0);
}

View File

@ -44,8 +44,8 @@
- @ref slcd - This section covers functions related to the Segment LCD display driver, which is responsible - @ref slcd - This section covers functions related to the Segment LCD display driver, which is responsible
for displaying strings of characters and indicators on the main watch display. for displaying strings of characters and indicators on the main watch display.
- @ref buttons - This section covers functions related to the three buttons: Light, Mode and Alarm. - @ref buttons - This section covers functions related to the three buttons: Light, Mode and Alarm.
- @ref led - This section covers functions related to the bi-color red/green LED mounted behind the LCD. - @ref tcc - This section covers functions related to the LED and piezo buzzer, which are controlled by the
- @ref buzzer - This section covers functions related to the piezo buzzer. SAM L22's Timer Counter for Control, or TCC peripheral.
- @ref adc - This section covers functions related to the SAM L22's analog-to-digital converter, as well as - @ref adc - This section covers functions related to the SAM L22's analog-to-digital converter, as well as
configuring and reading values from the five analog-capable pins on the 9-pin connector. configuring and reading values from the five analog-capable pins on the 9-pin connector.
- @ref gpio - This section covers functions related to general-purpose input and output signals. - @ref gpio - This section covers functions related to general-purpose input and output signals.
@ -60,8 +60,7 @@
// #include "watch_rtc.h" // #include "watch_rtc.h"
// #include "watch_slcd.h" // #include "watch_slcd.h"
// #include "watch_extint.h" // #include "watch_extint.h"
#include "watch_led.h" #include "watch_tcc.h"
#include "watch_buzzer.h"
// #include "watch_adc.h" // #include "watch_adc.h"
#include "watch_gpio.h" #include "watch_gpio.h"
// #include "watch_i2c.h" // #include "watch_i2c.h"

View File

@ -1,98 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 Joey Castillo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _WATCH_LED_H_INCLUDED
#define _WATCH_LED_H_INCLUDED
////< @file watch_led.h
#include "watch.h"
/** @addtogroup led LED Control
* @brief This section covers functions related to the bi-color red/green LED mounted behind the LCD.
* @details The SAM L22 is an exceedingly power efficient chip, whereas the LED's are relatively power-
* hungry. The green LED, at full power, consumes more power than the whole chip in active mode,
* and the red LED consumes about twelve times as much power! The LED's should thus be used only
* sparingly in order to preserve battery life.
* @note Some watches use a red/blue LED instead of a red/green LED. You will be able to determine this
* easily when you double tap the reset button: if the pulsing bootloader LED is red, you have a
* red/green edition; if it is blue, you have a red/blue edition. For red/blue watches, build your
* project with the command `make COLOR=BLUE`, and the watch library will automatically swap the pins
* so that watch_set_led_red sets the red LED, and watch_set_led_green sets the blue one.
*/
/// @{
/** @brief Enables the bi-color LED.
* @note The TCC peripheral that drives the LEDs does not run in STANDBY mode but the outputs do! This
* means that if you set either red, green or both LEDs to full power, they will shine even when
* your app is asleep. If, however, you set a custom color using watch_set_led_color, the color will
* not display correctly in STANDBY mode. You will need to keep your app running while the LED is on.
*/
void watch_enable_leds(void);
/** @brief Disables the LEDs.
* @note This method will also disable the buzzer, since the buzzer and LED both make use of the same
* peripheral to drive their PWM behavior.
*/
void watch_disable_leds(void);
/** @brief Sets the LED to a custom color by modulating each output's duty cycle.
* @param red The red value from 0-255.
* @param green The green value from 0-255. If your watch has a red/blue LED, this will be the blue value.
* @note If you are displaying a custom color, you will need to prevent your app from going to sleep
* while the LED is on; otherwise, the color will not display correctly. You can do this by
* returning false in your app_loop method.
*/
void watch_set_led_color(uint8_t red, uint8_t green);
/** @brief On boards with an RGB LED, sets the LED to a custom color by modulating each output's duty cycle.
* @param red The red value from 0-255.
* @param green The green value from 0-255.
* @param blue The blue value from 0-255.
* @note If you are displaying a custom color, you will need to prevent your app from going to sleep
* while the LED is on; otherwise, the color will not display correctly. You can do this by
* returning false in your app_loop method.
*/
void watch_set_led_color_rgb(uint8_t red, uint8_t green, uint8_t blue);
/** @brief Sets the red LED to full brightness, and turns the green LED off.
* @details Of the two LED's in the RG bi-color LED, the red LED is the less power-efficient one (~4.5 mA).
*/
void watch_set_led_red(void);
/** @brief Sets the green LED to full brightness, and turns the red LED off.
* @details Of the two LED's in the RG bi-color LED, the green LED is the more power-efficient one (~0.44 mA).
* @note If your watch has a red/blue LED, this method will set the LED to blue.
*/
void watch_set_led_green(void);
/** @brief Sets both red and green LEDs to full brightness.
* @details The total current draw between the two LED's in this mode will be ~5 mA, which is more than the
* watch draws in any other mode. Take care not to drain the battery.
* @note If your watch has a red/blue LED, this method will set the LED to pink.
*/
void watch_set_led_yellow(void);
/** @brief Turns both the red and the green LEDs off. */
void watch_set_led_off(void);
/// @}
#endif

View File

@ -190,5 +190,72 @@ void watch_buzzer_abort_sequence(void);
void TC3_Handler(void); void TC3_Handler(void);
#endif #endif
/** @addtogroup led LED Control
* @brief This section covers functions related to the bi-color red/green LED mounted behind the LCD.
* @details The SAM L22 is an exceedingly power efficient chip, whereas the LED's are relatively power-
* hungry. The green LED, at full power, consumes more power than the whole chip in active mode,
* and the red LED consumes about twelve times as much power! The LED's should thus be used only
* sparingly in order to preserve battery life.
* @note Some watches use a red/blue LED instead of a red/green LED. You will be able to determine this
* easily when you double tap the reset button: if the pulsing bootloader LED is red, you have a
* red/green edition; if it is blue, you have a red/blue edition. For red/blue watches, build your
* project with the command `make COLOR=BLUE`, and the watch library will automatically swap the pins
* so that watch_set_led_red sets the red LED, and watch_set_led_green sets the blue one.
*/
/// @{
/** @brief Enables the bi-color LED.
* @note The TCC peripheral that drives the LEDs does not run in STANDBY mode but the outputs do! This
* means that if you set either red, green or both LEDs to full power, they will shine even when
* your app is asleep. If, however, you set a custom color using watch_set_led_color, the color will
* not display correctly in STANDBY mode. You will need to keep your app running while the LED is on.
*/
void watch_enable_leds(void);
/** @brief Disables the LEDs.
* @note This method will also disable the buzzer, since the buzzer and LED both make use of the same
* peripheral to drive their PWM behavior.
*/
void watch_disable_leds(void);
/** @brief Sets the LED to a custom color by modulating each output's duty cycle.
* @param red The red value from 0-255.
* @param green The green value from 0-255. If your watch has a red/blue LED, this will be the blue value.
* @note If you are displaying a custom color, you will need to prevent your app from going to sleep
* while the LED is on; otherwise, the color will not display correctly. You can do this by
* returning false in your app_loop method.
*/
void watch_set_led_color(uint8_t red, uint8_t green);
/** @brief On boards with an RGB LED, sets the LED to a custom color by modulating each output's duty cycle.
* @param red The red value from 0-255.
* @param green The green value from 0-255.
* @param blue The blue value from 0-255.
* @note If you are displaying a custom color, you will need to prevent your app from going to sleep
* while the LED is on; otherwise, the color will not display correctly. You can do this by
* returning false in your app_loop method.
*/
void watch_set_led_color_rgb(uint8_t red, uint8_t green, uint8_t blue);
/** @brief Sets the red LED to full brightness, and turns the green LED off.
* @details Of the two LED's in the RG bi-color LED, the red LED is the less power-efficient one (~4.5 mA).
*/
void watch_set_led_red(void);
/** @brief Sets the green LED to full brightness, and turns the red LED off.
* @details Of the two LED's in the RG bi-color LED, the green LED is the more power-efficient one (~0.44 mA).
* @note If your watch has a red/blue LED, this method will set the LED to blue.
*/
void watch_set_led_green(void);
/** @brief Sets both red and green LEDs to full brightness.
* @details The total current draw between the two LED's in this mode will be ~5 mA, which is more than the
* watch draws in any other mode. Take care not to drain the battery.
* @note If your watch has a red/blue LED, this method will set the LED to pink.
*/
void watch_set_led_yellow(void);
/** @brief Turns both the red and the green LEDs off. */
void watch_set_led_off(void);
/// @} /// @}
#endif #endif

View File

@ -1,66 +0,0 @@
/*
* MIT License
*
* Copyright (c) 2020 Joey Castillo
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "watch_led.h"
#include <emscripten.h>
void watch_enable_leds(void) {}
void watch_disable_leds(void) {}
void watch_set_led_color(uint8_t red, uint8_t green) {
EM_ASM({
// the watch svg contains an feColorMatrix filter with id ledcolor
// and a green svg gradient that mimics the led being on
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feColorMatrix
// this changes the color of the gradient to match the red+green combination
let filter = document.getElementById("ledcolor");
let color_matrix = filter.children[0].values.baseVal;
color_matrix[1].value = $0 / 255; // red value
color_matrix[6].value = $1 / 255; // green value
document.getElementById('light').style.opacity = Math.min(255, $0 + $1) / 255;
}, red, green);
}
void watch_set_led_color_rgb(uint8_t red, uint8_t green, uint8_t blue) {
(void) blue;
watch_set_led_color(red, green);
}
void watch_set_led_red(void) {
watch_set_led_color(255, 0);
}
void watch_set_led_green(void) {
watch_set_led_color(0, 255);
}
void watch_set_led_yellow(void) {
watch_set_led_color(255, 255);
}
void watch_set_led_off(void) {
watch_set_led_color(0, 0);
}

View File

@ -181,3 +181,42 @@ void watch_buzzer_play_note(BuzzerNote note, uint16_t duration_ms) {
main_loop_sleep(duration_ms); main_loop_sleep(duration_ms);
watch_set_buzzer_off(); watch_set_buzzer_off();
} }
void watch_enable_leds(void) {}
void watch_disable_leds(void) {}
void watch_set_led_color(uint8_t red, uint8_t green) {
EM_ASM({
// the watch svg contains an feColorMatrix filter with id ledcolor
// and a green svg gradient that mimics the led being on
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feColorMatrix
// this changes the color of the gradient to match the red+green combination
let filter = document.getElementById("ledcolor");
let color_matrix = filter.children[0].values.baseVal;
color_matrix[1].value = $0 / 255; // red value
color_matrix[6].value = $1 / 255; // green value
document.getElementById('light').style.opacity = Math.min(255, $0 + $1) / 255;
}, red, green);
}
void watch_set_led_color_rgb(uint8_t red, uint8_t green, uint8_t blue) {
(void) blue;
watch_set_led_color(red, green);
}
void watch_set_led_red(void) {
watch_set_led_color(255, 0);
}
void watch_set_led_green(void) {
watch_set_led_color(0, 255);
}
void watch_set_led_yellow(void) {
watch_set_led_color(255, 255);
}
void watch_set_led_off(void) {
watch_set_led_color(0, 0);
}