# Add your source files here.
SRCS += \
- ./watch-library/hardware/watch/watch_buzzer.c \
./watch-library/hardware/watch/watch_gpio.c \
- ./watch-library/hardware/watch/watch_led.c \
+ ./watch-library/hardware/watch/watch_tcc.c \
./app.c \
# Finally, leave this line at the bottom of the file.
+++ /dev/null
-/*
- * 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_buzzer.h"
-#include "watch_private.h"
-#include "delay.h"
-#include "tcc.h"
-
-void _watch_enable_tcc(void);
-
-bool watch_is_buzzer_or_led_enabled(void){
- return tcc_is_enabled(0);
-}
-
-inline void watch_enable_buzzer(void) {
- if (!tcc_is_enabled(0)) {
- _watch_enable_tcc();
- }
-}
-
-inline void watch_set_buzzer_period(uint32_t period) {
- tcc_set_period(0, period, true);
- tcc_set_cc(0, (WATCH_BUZZER_TCC_CHANNEL) % 4, period / 2, true);
-}
-
-void watch_disable_buzzer(void) {
- _watch_disable_tcc();
-}
-
-inline void watch_set_buzzer_on(void) {
- HAL_GPIO_BUZZER_out();
- HAL_GPIO_BUZZER_pmuxen(HAL_GPIO_PMUX_TCC_ALT);
-}
-
-inline void watch_set_buzzer_off(void) {
- HAL_GPIO_BUZZER_pmuxdis();
- HAL_GPIO_BUZZER_off();
-}
-
-void watch_buzzer_play_note(BuzzerNote note, uint16_t duration_ms) {
- if (note == BUZZER_NOTE_REST) {
- watch_set_buzzer_off();
- } else {
- watch_set_buzzer_period(NotePeriods[note]);
- watch_set_buzzer_on();
- }
- delay_ms(duration_ms);
- watch_set_buzzer_off();
-}
-
-void _watch_enable_tcc(void) {
- // set up the TCC with a 1 MHz clock, but there's a trick:
- if (USB->DEVICE.CTRLA.bit.ENABLE) {
- // if USB is enabled, we are running an 8 MHz clock, so we divide by 8.
- tcc_init(0, GENERIC_CLOCK_0, TCC_PRESCALER_DIV8);
- } else {
- // otherwise it's 4 Mhz and we divide by 4.
- tcc_init(0, GENERIC_CLOCK_0, TCC_PRESCALER_DIV4);
- }
- // We're going to use normal PWM mode, which means period is controlled by PER, and duty cycle is controlled by
- // each compare channel's value:
- // * Buzzer tones are set by setting PER to the desired period for a given frequency, and CC[1] to half of that
- // period (i.e. a square wave with a 50% duty cycle).
- // * LEDs on CC[0] CC[2] and CC[3] can be set to any value from 0 (off) to PER (fully on).
- tcc_set_wavegen(0, TCC_WAVEGEN_NORMAL_PWM);
-#ifdef WATCH_INVERT_LED_POLARITY
- // invert all channels, we'll flip the buzzer back in just a moment.
- // this is easier than writing a maze of #ifdefs.
- tcc_set_channel_polarity(0, 4, TCC_CHANNEL_POLARITY_INVERTED);
- tcc_set_channel_polarity(0, 5, TCC_CHANNEL_POLARITY_INVERTED);
- tcc_set_channel_polarity(0, 6, TCC_CHANNEL_POLARITY_INVERTED);
- tcc_set_channel_polarity(0, 7, TCC_CHANNEL_POLARITY_INVERTED);
-#endif // WATCH_INVERT_LED_POLARITY
- tcc_set_channel_polarity(0, WATCH_BUZZER_TCC_CHANNEL, TCC_CHANNEL_POLARITY_NORMAL);
-
- // Set the period to 1 kHz to start.
- tcc_set_period(0, 1000, false);
-
- // Set the duty cycle of all pins to 0: LED's off, buzzer not buzzing.
- tcc_set_cc(0, (WATCH_BUZZER_TCC_CHANNEL) % 4, 0, false);
- tcc_set_cc(0, (WATCH_RED_TCC_CHANNEL) % 4, 0, false);
-#ifdef WATCH_GREEN_TCC_CHANNEL
- tcc_set_cc(0, (WATCH_GREEN_TCC_CHANNEL) % 4, 0, false);
-#endif
-#ifdef WATCH_BLUE_TCC_CHANNEL
- tcc_set_cc(0, (WATCH_BLUE_TCC_CHANNEL) % 4, 0, false);
-#endif
-
- // enable LED PWM pins (the LED driver assumes if the TCC is on, the pins are enabled)
- HAL_GPIO_RED_pmuxen(HAL_GPIO_PMUX_TCC_ALT);
- HAL_GPIO_RED_out();
-#ifdef WATCH_GREEN_TCC_CHANNEL
- HAL_GPIO_GREEN_pmuxen(HAL_GPIO_PMUX_TCC_ALT);
- HAL_GPIO_GREEN_out();
-#endif
-#ifdef WATCH_BLUE_TCC_CHANNEL
- HAL_GPIO_BLUE_pmuxen(HAL_GPIO_PMUX_TCC_ALT);
- HAL_GPIO_BLUE_out();
-#endif
-
- // Enable the TCC
- tcc_enable(0);
-}
-
-void _watch_disable_tcc(void) {
- // disable all PWM pins
- HAL_GPIO_BUZZER_pmuxdis();
- HAL_GPIO_BUZZER_off();
- HAL_GPIO_RED_pmuxdis();
- HAL_GPIO_RED_off();
-#ifdef WATCH_GREEN_TCC_CHANNEL
- HAL_GPIO_GREEN_pmuxdis();
- HAL_GPIO_GREEN_off();
-#endif
-#ifdef WATCH_BLUE_TCC_CHANNEL
- HAL_GPIO_BLUE_pmuxdis();
- HAL_GPIO_BLUE_off();
-#endif
- tcc_disable(0);
-}
+++ /dev/null
-/*
- * 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);
-}
--- /dev/null
+/*
+ * 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_tcc.h"
+#include "delay.h"
+#include "tcc.h"
+
+void _watch_enable_tcc(void);
+void _watch_disable_tcc(void);
+
+bool watch_is_buzzer_or_led_enabled(void){
+ return tcc_is_enabled(0);
+}
+
+inline void watch_enable_buzzer(void) {
+ if (!tcc_is_enabled(0)) {
+ _watch_enable_tcc();
+ }
+}
+
+inline void watch_set_buzzer_period(uint32_t period) {
+ tcc_set_period(0, period, true);
+ tcc_set_cc(0, (WATCH_BUZZER_TCC_CHANNEL) % 4, period / 2, true);
+}
+
+void watch_disable_buzzer(void) {
+ _watch_disable_tcc();
+}
+
+inline void watch_set_buzzer_on(void) {
+ HAL_GPIO_BUZZER_out();
+ HAL_GPIO_BUZZER_pmuxen(HAL_GPIO_PMUX_TCC_ALT);
+}
+
+inline void watch_set_buzzer_off(void) {
+ HAL_GPIO_BUZZER_pmuxdis();
+ HAL_GPIO_BUZZER_off();
+}
+
+void watch_buzzer_play_note(BuzzerNote note, uint16_t duration_ms) {
+ if (note == BUZZER_NOTE_REST) {
+ watch_set_buzzer_off();
+ } else {
+ watch_set_buzzer_period(NotePeriods[note]);
+ watch_set_buzzer_on();
+ }
+ delay_ms(duration_ms);
+ watch_set_buzzer_off();
+}
+
+void _watch_enable_tcc(void) {
+ // set up the TCC with a 1 MHz clock, but there's a trick:
+ if (USB->DEVICE.CTRLA.bit.ENABLE) {
+ // if USB is enabled, we are running an 8 MHz clock, so we divide by 8.
+ tcc_init(0, GENERIC_CLOCK_0, TCC_PRESCALER_DIV8);
+ } else {
+ // otherwise it's 4 Mhz and we divide by 4.
+ tcc_init(0, GENERIC_CLOCK_0, TCC_PRESCALER_DIV4);
+ }
+ // We're going to use normal PWM mode, which means period is controlled by PER, and duty cycle is controlled by
+ // each compare channel's value:
+ // * Buzzer tones are set by setting PER to the desired period for a given frequency, and CC[1] to half of that
+ // period (i.e. a square wave with a 50% duty cycle).
+ // * LEDs on CC[0] CC[2] and CC[3] can be set to any value from 0 (off) to PER (fully on).
+ tcc_set_wavegen(0, TCC_WAVEGEN_NORMAL_PWM);
+#ifdef WATCH_INVERT_LED_POLARITY
+ // invert all channels, we'll flip the buzzer back in just a moment.
+ // this is easier than writing a maze of #ifdefs.
+ tcc_set_channel_polarity(0, 4, TCC_CHANNEL_POLARITY_INVERTED);
+ tcc_set_channel_polarity(0, 5, TCC_CHANNEL_POLARITY_INVERTED);
+ tcc_set_channel_polarity(0, 6, TCC_CHANNEL_POLARITY_INVERTED);
+ tcc_set_channel_polarity(0, 7, TCC_CHANNEL_POLARITY_INVERTED);
+#endif // WATCH_INVERT_LED_POLARITY
+ tcc_set_channel_polarity(0, WATCH_BUZZER_TCC_CHANNEL, TCC_CHANNEL_POLARITY_NORMAL);
+
+ // Set the period to 1 kHz to start.
+ tcc_set_period(0, 1000, false);
+
+ // Set the duty cycle of all pins to 0: LED's off, buzzer not buzzing.
+ tcc_set_cc(0, (WATCH_BUZZER_TCC_CHANNEL) % 4, 0, false);
+ tcc_set_cc(0, (WATCH_RED_TCC_CHANNEL) % 4, 0, false);
+#ifdef WATCH_GREEN_TCC_CHANNEL
+ tcc_set_cc(0, (WATCH_GREEN_TCC_CHANNEL) % 4, 0, false);
+#endif
+#ifdef WATCH_BLUE_TCC_CHANNEL
+ tcc_set_cc(0, (WATCH_BLUE_TCC_CHANNEL) % 4, 0, false);
+#endif
+
+ // enable LED PWM pins (the LED driver assumes if the TCC is on, the pins are enabled)
+ HAL_GPIO_RED_pmuxen(HAL_GPIO_PMUX_TCC_ALT);
+ HAL_GPIO_RED_out();
+#ifdef WATCH_GREEN_TCC_CHANNEL
+ HAL_GPIO_GREEN_pmuxen(HAL_GPIO_PMUX_TCC_ALT);
+ HAL_GPIO_GREEN_out();
+#endif
+#ifdef WATCH_BLUE_TCC_CHANNEL
+ HAL_GPIO_BLUE_pmuxen(HAL_GPIO_PMUX_TCC_ALT);
+ HAL_GPIO_BLUE_out();
+#endif
+
+ // Enable the TCC
+ tcc_enable(0);
+}
+
+void _watch_disable_tcc(void) {
+ // disable all PWM pins
+ HAL_GPIO_BUZZER_pmuxdis();
+ HAL_GPIO_BUZZER_off();
+ HAL_GPIO_RED_pmuxdis();
+ HAL_GPIO_RED_off();
+#ifdef WATCH_GREEN_TCC_CHANNEL
+ HAL_GPIO_GREEN_pmuxdis();
+ HAL_GPIO_GREEN_off();
+#endif
+#ifdef WATCH_BLUE_TCC_CHANNEL
+ HAL_GPIO_BLUE_pmuxdis();
+ HAL_GPIO_BLUE_off();
+#endif
+ 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);
+}
- @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.
- @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 buzzer - This section covers functions related to the piezo buzzer.
+ - @ref tcc - This section covers functions related to the LED and piezo buzzer, which are controlled by the
+ 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
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.
// #include "watch_rtc.h"
// #include "watch_slcd.h"
// #include "watch_extint.h"
-#include "watch_led.h"
-#include "watch_buzzer.h"
+#include "watch_tcc.h"
// #include "watch_adc.h"
#include "watch_gpio.h"
// #include "watch_i2c.h"
+++ /dev/null
-/*
- * 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_BUZZER_H_INCLUDED
-#define _WATCH_BUZZER_H_INCLUDED
-////< @file watch_buzzer.h
-
-#include "watch.h"
-
-/** @brief Returns true if either the buzzer or the LED driver is enabled.
- * @details Both the buzzer and the LED use the TCC peripheral to drive their behavior. This function returns true if that
- * peripheral is enabled. You can use this function to determine whether you need to call the watch_disable_leds or
- * or watch_enable_buzzer functions before using these peripherals.
- */
-bool watch_is_buzzer_or_led_enabled(void);
-
-/** @addtogroup tcc Buzzer and LED Control (via the TCC peripheral)
- * @brief This section covers functions related to the piezo buzzer embedded in the F-91W's back plate.
- */
-/// @{
-/** @brief Enables the TCC peripheral, which drives the buzzer.
- */
-void watch_enable_buzzer(void);
-
-/** @brief Sets the period of the buzzer.
- * @param period The period of a single cycle for the TCC peripheral. You can determine the period for
- * a desired frequency with the following formula: period = 1000000 / freq
- */
-void watch_set_buzzer_period(uint32_t period);
-
-/** @brief Disables the TCC peripheral that drives the buzzer.
- * @note If you are using PWM to set custom LED colors, this method will also disable the LED PWM driver,
- * since the buzzer and LED both make use of the same peripheral to drive their PWM behavior.
- */
-void watch_disable_buzzer(void);
-
-/** @brief Turns the buzzer output on. It will emit a continuous sound at the given frequency.
- * @note The TCC peripheral that drives the buzzer does not run in standby mode; if you wish for buzzer
- * output to continue, you should prevent your app from going to sleep.
- */
-void watch_set_buzzer_on(void);
-
-/** @brief Turns the buzzer output off.
- */
-void watch_set_buzzer_off(void);
-
-/// @brief 87 notes for use with watch_buzzer_play_note
-typedef enum BuzzerNote {
- BUZZER_NOTE_A1, ///< 55.00 Hz
- BUZZER_NOTE_A1SHARP_B1FLAT, ///< 58.27 Hz
- BUZZER_NOTE_B1, ///< 61.74 Hz
- BUZZER_NOTE_C2, ///< 65.41 Hz
- BUZZER_NOTE_C2SHARP_D2FLAT, ///< 69.30 Hz
- BUZZER_NOTE_D2, ///< 73.42 Hz
- BUZZER_NOTE_D2SHARP_E2FLAT, ///< 77.78 Hz
- BUZZER_NOTE_E2, ///< 82.41 Hz
- BUZZER_NOTE_F2, ///< 87.31 Hz
- BUZZER_NOTE_F2SHARP_G2FLAT, ///< 92.50 Hz
- BUZZER_NOTE_G2, ///< 98.00 Hz
- BUZZER_NOTE_G2SHARP_A2FLAT, ///< 103.83 Hz
- BUZZER_NOTE_A2, ///< 110.00 Hz
- BUZZER_NOTE_A2SHARP_B2FLAT, ///< 116.54 Hz
- BUZZER_NOTE_B2, ///< 123.47 Hz
- BUZZER_NOTE_C3, ///< 130.81 Hz
- BUZZER_NOTE_C3SHARP_D3FLAT, ///< 138.59 Hz
- BUZZER_NOTE_D3, ///< 146.83 Hz
- BUZZER_NOTE_D3SHARP_E3FLAT, ///< 155.56 Hz
- BUZZER_NOTE_E3, ///< 164.81 Hz
- BUZZER_NOTE_F3, ///< 174.61 Hz
- BUZZER_NOTE_F3SHARP_G3FLAT, ///< 185.00 Hz
- BUZZER_NOTE_G3, ///< 196.00 Hz
- BUZZER_NOTE_G3SHARP_A3FLAT, ///< 207.65 Hz
- BUZZER_NOTE_A3, ///< 220.00 Hz
- BUZZER_NOTE_A3SHARP_B3FLAT, ///< 233.08 Hz
- BUZZER_NOTE_B3, ///< 246.94 Hz
- BUZZER_NOTE_C4, ///< 261.63 Hz
- BUZZER_NOTE_C4SHARP_D4FLAT, ///< 277.18 Hz
- BUZZER_NOTE_D4, ///< 293.66 Hz
- BUZZER_NOTE_D4SHARP_E4FLAT, ///< 311.13 Hz
- BUZZER_NOTE_E4, ///< 329.63 Hz
- BUZZER_NOTE_F4, ///< 349.23 Hz
- BUZZER_NOTE_F4SHARP_G4FLAT, ///< 369.99 Hz
- BUZZER_NOTE_G4, ///< 392.00 Hz
- BUZZER_NOTE_G4SHARP_A4FLAT, ///< 415.30 Hz
- BUZZER_NOTE_A4, ///< 440.00 Hz
- BUZZER_NOTE_A4SHARP_B4FLAT, ///< 466.16 Hz
- BUZZER_NOTE_B4, ///< 493.88 Hz
- BUZZER_NOTE_C5, ///< 523.25 Hz
- BUZZER_NOTE_C5SHARP_D5FLAT, ///< 554.37 Hz
- BUZZER_NOTE_D5, ///< 587.33 Hz
- BUZZER_NOTE_D5SHARP_E5FLAT, ///< 622.25 Hz
- BUZZER_NOTE_E5, ///< 659.25 Hz
- BUZZER_NOTE_F5, ///< 698.46 Hz
- BUZZER_NOTE_F5SHARP_G5FLAT, ///< 739.99 Hz
- BUZZER_NOTE_G5, ///< 783.99 Hz
- BUZZER_NOTE_G5SHARP_A5FLAT, ///< 830.61 Hz
- BUZZER_NOTE_A5, ///< 880.00 Hz
- BUZZER_NOTE_A5SHARP_B5FLAT, ///< 932.33 Hz
- BUZZER_NOTE_B5, ///< 987.77 Hz
- BUZZER_NOTE_C6, ///< 1046.50 Hz
- BUZZER_NOTE_C6SHARP_D6FLAT, ///< 1108.73 Hz
- BUZZER_NOTE_D6, ///< 1174.66 Hz
- BUZZER_NOTE_D6SHARP_E6FLAT, ///< 1244.51 Hz
- BUZZER_NOTE_E6, ///< 1318.51 Hz
- BUZZER_NOTE_F6, ///< 1396.91 Hz
- BUZZER_NOTE_F6SHARP_G6FLAT, ///< 1479.98 Hz
- BUZZER_NOTE_G6, ///< 1567.98 Hz
- BUZZER_NOTE_G6SHARP_A6FLAT, ///< 1661.22 Hz
- BUZZER_NOTE_A6, ///< 1760.00 Hz
- BUZZER_NOTE_A6SHARP_B6FLAT, ///< 1864.66 Hz
- BUZZER_NOTE_B6, ///< 1975.53 Hz
- BUZZER_NOTE_C7, ///< 2093.00 Hz
- BUZZER_NOTE_C7SHARP_D7FLAT, ///< 2217.46 Hz
- BUZZER_NOTE_D7, ///< 2349.32 Hz
- BUZZER_NOTE_D7SHARP_E7FLAT, ///< 2489.02 Hz
- BUZZER_NOTE_E7, ///< 2637.02 Hz
- BUZZER_NOTE_F7, ///< 2793.83 Hz
- BUZZER_NOTE_F7SHARP_G7FLAT, ///< 2959.96 Hz
- BUZZER_NOTE_G7, ///< 3135.96 Hz
- BUZZER_NOTE_G7SHARP_A7FLAT, ///< 3322.44 Hz
- BUZZER_NOTE_A7, ///< 3520.00 Hz
- BUZZER_NOTE_A7SHARP_B7FLAT, ///< 3729.31 Hz
- BUZZER_NOTE_B7, ///< 3951.07 Hz
- BUZZER_NOTE_C8, ///< 4186.01 Hz
- BUZZER_NOTE_C8SHARP_D8FLAT, ///< 4434.92 Hz
- BUZZER_NOTE_D8, ///< 4698.63 Hz
- BUZZER_NOTE_D8SHARP_E8FLAT, ///< 4978.03 Hz
- BUZZER_NOTE_E8, ///< 5274.04 Hz
- BUZZER_NOTE_F8, ///< 5587.65 Hz
- BUZZER_NOTE_F8SHARP_G8FLAT, ///< 5919.91 Hz
- BUZZER_NOTE_G8, ///< 6271.93 Hz
- BUZZER_NOTE_G8SHARP_A8FLAT, ///< 6644.88 Hz
- BUZZER_NOTE_A8, ///< 7040.00 Hz
- BUZZER_NOTE_A8SHARP_B8FLAT, ///< 7458.62 Hz
- BUZZER_NOTE_B8, ///< 7902.13 Hz
- BUZZER_NOTE_REST ///< no sound
-} BuzzerNote;
-
-/** @brief Plays the given note for a set duration.
- * @param note The note you wish to play, or BUZZER_NOTE_REST to disable output for the given duration.
- * @param duration_ms The duration of the note.
- * @note Note that this will block your UI for the duration of the note's play time, and it will
- * after this call, the buzzer period will be set to the period of this note.
- */
-void watch_buzzer_play_note(BuzzerNote note, uint16_t duration_ms);
-
-/// @brief An array of periods for all the notes on a piano, corresponding to the names in BuzzerNote.
-extern const uint16_t NotePeriods[108];
-
-/** @brief Plays the given sequence of notes in a non-blocking way.
- * @param note_sequence A pointer to the sequence of buzzer note & duration tuples, ending with a zero. A simple
- * RLE logic is implemented: a negative number instead of a buzzer note means that the sequence
- * is rewound by the given number of notes. The byte following a negative number determines the number
- * of loops. I.e. if you want to repeat the last three notes of the sequence one time, you should provide
- * the tuple -3, 1. The repeated notes must not contain any other repeat markers, or you will end up with
- * an eternal loop.
- * @param callback_on_end A pointer to a callback function to be invoked when the sequence has finished playing.
- * @note This function plays the sequence asynchronously, so the UI will not be blocked.
- * Hint: It is not possible to play the lowest note BUZZER_NOTE_A1 (55.00 Hz). The note is represented by a
- * zero byte, which is used here as the end-of-sequence marker. But hey, a frequency that low cannot be
- * played properly by the watch's buzzer, anyway.
- */
-void watch_buzzer_play_sequence(int8_t *note_sequence, void (*callback_on_end)(void));
-
-/** @brief Aborts a playing sequence.
- */
-void watch_buzzer_abort_sequence(void);
-
-#ifndef __EMSCRIPTEN__
-void TC3_Handler(void);
-#endif
-
-/// @}
-#endif
+++ /dev/null
-/*
- * 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
--- /dev/null
+/*
+ * 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_BUZZER_H_INCLUDED
+#define _WATCH_BUZZER_H_INCLUDED
+////< @file watch_buzzer.h
+
+#include "watch.h"
+
+/** @brief Returns true if either the buzzer or the LED driver is enabled.
+ * @details Both the buzzer and the LED use the TCC peripheral to drive their behavior. This function returns true if that
+ * peripheral is enabled. You can use this function to determine whether you need to call the watch_disable_leds or
+ * or watch_enable_buzzer functions before using these peripherals.
+ */
+bool watch_is_buzzer_or_led_enabled(void);
+
+/** @addtogroup tcc Buzzer and LED Control (via the TCC peripheral)
+ * @brief This section covers functions related to the piezo buzzer embedded in the F-91W's back plate.
+ */
+/// @{
+/** @brief Enables the TCC peripheral, which drives the buzzer.
+ */
+void watch_enable_buzzer(void);
+
+/** @brief Sets the period of the buzzer.
+ * @param period The period of a single cycle for the TCC peripheral. You can determine the period for
+ * a desired frequency with the following formula: period = 1000000 / freq
+ */
+void watch_set_buzzer_period(uint32_t period);
+
+/** @brief Disables the TCC peripheral that drives the buzzer.
+ * @note If you are using PWM to set custom LED colors, this method will also disable the LED PWM driver,
+ * since the buzzer and LED both make use of the same peripheral to drive their PWM behavior.
+ */
+void watch_disable_buzzer(void);
+
+/** @brief Turns the buzzer output on. It will emit a continuous sound at the given frequency.
+ * @note The TCC peripheral that drives the buzzer does not run in standby mode; if you wish for buzzer
+ * output to continue, you should prevent your app from going to sleep.
+ */
+void watch_set_buzzer_on(void);
+
+/** @brief Turns the buzzer output off.
+ */
+void watch_set_buzzer_off(void);
+
+/// @brief 87 notes for use with watch_buzzer_play_note
+typedef enum BuzzerNote {
+ BUZZER_NOTE_A1, ///< 55.00 Hz
+ BUZZER_NOTE_A1SHARP_B1FLAT, ///< 58.27 Hz
+ BUZZER_NOTE_B1, ///< 61.74 Hz
+ BUZZER_NOTE_C2, ///< 65.41 Hz
+ BUZZER_NOTE_C2SHARP_D2FLAT, ///< 69.30 Hz
+ BUZZER_NOTE_D2, ///< 73.42 Hz
+ BUZZER_NOTE_D2SHARP_E2FLAT, ///< 77.78 Hz
+ BUZZER_NOTE_E2, ///< 82.41 Hz
+ BUZZER_NOTE_F2, ///< 87.31 Hz
+ BUZZER_NOTE_F2SHARP_G2FLAT, ///< 92.50 Hz
+ BUZZER_NOTE_G2, ///< 98.00 Hz
+ BUZZER_NOTE_G2SHARP_A2FLAT, ///< 103.83 Hz
+ BUZZER_NOTE_A2, ///< 110.00 Hz
+ BUZZER_NOTE_A2SHARP_B2FLAT, ///< 116.54 Hz
+ BUZZER_NOTE_B2, ///< 123.47 Hz
+ BUZZER_NOTE_C3, ///< 130.81 Hz
+ BUZZER_NOTE_C3SHARP_D3FLAT, ///< 138.59 Hz
+ BUZZER_NOTE_D3, ///< 146.83 Hz
+ BUZZER_NOTE_D3SHARP_E3FLAT, ///< 155.56 Hz
+ BUZZER_NOTE_E3, ///< 164.81 Hz
+ BUZZER_NOTE_F3, ///< 174.61 Hz
+ BUZZER_NOTE_F3SHARP_G3FLAT, ///< 185.00 Hz
+ BUZZER_NOTE_G3, ///< 196.00 Hz
+ BUZZER_NOTE_G3SHARP_A3FLAT, ///< 207.65 Hz
+ BUZZER_NOTE_A3, ///< 220.00 Hz
+ BUZZER_NOTE_A3SHARP_B3FLAT, ///< 233.08 Hz
+ BUZZER_NOTE_B3, ///< 246.94 Hz
+ BUZZER_NOTE_C4, ///< 261.63 Hz
+ BUZZER_NOTE_C4SHARP_D4FLAT, ///< 277.18 Hz
+ BUZZER_NOTE_D4, ///< 293.66 Hz
+ BUZZER_NOTE_D4SHARP_E4FLAT, ///< 311.13 Hz
+ BUZZER_NOTE_E4, ///< 329.63 Hz
+ BUZZER_NOTE_F4, ///< 349.23 Hz
+ BUZZER_NOTE_F4SHARP_G4FLAT, ///< 369.99 Hz
+ BUZZER_NOTE_G4, ///< 392.00 Hz
+ BUZZER_NOTE_G4SHARP_A4FLAT, ///< 415.30 Hz
+ BUZZER_NOTE_A4, ///< 440.00 Hz
+ BUZZER_NOTE_A4SHARP_B4FLAT, ///< 466.16 Hz
+ BUZZER_NOTE_B4, ///< 493.88 Hz
+ BUZZER_NOTE_C5, ///< 523.25 Hz
+ BUZZER_NOTE_C5SHARP_D5FLAT, ///< 554.37 Hz
+ BUZZER_NOTE_D5, ///< 587.33 Hz
+ BUZZER_NOTE_D5SHARP_E5FLAT, ///< 622.25 Hz
+ BUZZER_NOTE_E5, ///< 659.25 Hz
+ BUZZER_NOTE_F5, ///< 698.46 Hz
+ BUZZER_NOTE_F5SHARP_G5FLAT, ///< 739.99 Hz
+ BUZZER_NOTE_G5, ///< 783.99 Hz
+ BUZZER_NOTE_G5SHARP_A5FLAT, ///< 830.61 Hz
+ BUZZER_NOTE_A5, ///< 880.00 Hz
+ BUZZER_NOTE_A5SHARP_B5FLAT, ///< 932.33 Hz
+ BUZZER_NOTE_B5, ///< 987.77 Hz
+ BUZZER_NOTE_C6, ///< 1046.50 Hz
+ BUZZER_NOTE_C6SHARP_D6FLAT, ///< 1108.73 Hz
+ BUZZER_NOTE_D6, ///< 1174.66 Hz
+ BUZZER_NOTE_D6SHARP_E6FLAT, ///< 1244.51 Hz
+ BUZZER_NOTE_E6, ///< 1318.51 Hz
+ BUZZER_NOTE_F6, ///< 1396.91 Hz
+ BUZZER_NOTE_F6SHARP_G6FLAT, ///< 1479.98 Hz
+ BUZZER_NOTE_G6, ///< 1567.98 Hz
+ BUZZER_NOTE_G6SHARP_A6FLAT, ///< 1661.22 Hz
+ BUZZER_NOTE_A6, ///< 1760.00 Hz
+ BUZZER_NOTE_A6SHARP_B6FLAT, ///< 1864.66 Hz
+ BUZZER_NOTE_B6, ///< 1975.53 Hz
+ BUZZER_NOTE_C7, ///< 2093.00 Hz
+ BUZZER_NOTE_C7SHARP_D7FLAT, ///< 2217.46 Hz
+ BUZZER_NOTE_D7, ///< 2349.32 Hz
+ BUZZER_NOTE_D7SHARP_E7FLAT, ///< 2489.02 Hz
+ BUZZER_NOTE_E7, ///< 2637.02 Hz
+ BUZZER_NOTE_F7, ///< 2793.83 Hz
+ BUZZER_NOTE_F7SHARP_G7FLAT, ///< 2959.96 Hz
+ BUZZER_NOTE_G7, ///< 3135.96 Hz
+ BUZZER_NOTE_G7SHARP_A7FLAT, ///< 3322.44 Hz
+ BUZZER_NOTE_A7, ///< 3520.00 Hz
+ BUZZER_NOTE_A7SHARP_B7FLAT, ///< 3729.31 Hz
+ BUZZER_NOTE_B7, ///< 3951.07 Hz
+ BUZZER_NOTE_C8, ///< 4186.01 Hz
+ BUZZER_NOTE_C8SHARP_D8FLAT, ///< 4434.92 Hz
+ BUZZER_NOTE_D8, ///< 4698.63 Hz
+ BUZZER_NOTE_D8SHARP_E8FLAT, ///< 4978.03 Hz
+ BUZZER_NOTE_E8, ///< 5274.04 Hz
+ BUZZER_NOTE_F8, ///< 5587.65 Hz
+ BUZZER_NOTE_F8SHARP_G8FLAT, ///< 5919.91 Hz
+ BUZZER_NOTE_G8, ///< 6271.93 Hz
+ BUZZER_NOTE_G8SHARP_A8FLAT, ///< 6644.88 Hz
+ BUZZER_NOTE_A8, ///< 7040.00 Hz
+ BUZZER_NOTE_A8SHARP_B8FLAT, ///< 7458.62 Hz
+ BUZZER_NOTE_B8, ///< 7902.13 Hz
+ BUZZER_NOTE_REST ///< no sound
+} BuzzerNote;
+
+/** @brief Plays the given note for a set duration.
+ * @param note The note you wish to play, or BUZZER_NOTE_REST to disable output for the given duration.
+ * @param duration_ms The duration of the note.
+ * @note Note that this will block your UI for the duration of the note's play time, and it will
+ * after this call, the buzzer period will be set to the period of this note.
+ */
+void watch_buzzer_play_note(BuzzerNote note, uint16_t duration_ms);
+
+/// @brief An array of periods for all the notes on a piano, corresponding to the names in BuzzerNote.
+extern const uint16_t NotePeriods[108];
+
+/** @brief Plays the given sequence of notes in a non-blocking way.
+ * @param note_sequence A pointer to the sequence of buzzer note & duration tuples, ending with a zero. A simple
+ * RLE logic is implemented: a negative number instead of a buzzer note means that the sequence
+ * is rewound by the given number of notes. The byte following a negative number determines the number
+ * of loops. I.e. if you want to repeat the last three notes of the sequence one time, you should provide
+ * the tuple -3, 1. The repeated notes must not contain any other repeat markers, or you will end up with
+ * an eternal loop.
+ * @param callback_on_end A pointer to a callback function to be invoked when the sequence has finished playing.
+ * @note This function plays the sequence asynchronously, so the UI will not be blocked.
+ * Hint: It is not possible to play the lowest note BUZZER_NOTE_A1 (55.00 Hz). The note is represented by a
+ * zero byte, which is used here as the end-of-sequence marker. But hey, a frequency that low cannot be
+ * played properly by the watch's buzzer, anyway.
+ */
+void watch_buzzer_play_sequence(int8_t *note_sequence, void (*callback_on_end)(void));
+
+/** @brief Aborts a playing sequence.
+ */
+void watch_buzzer_abort_sequence(void);
+
+#ifndef __EMSCRIPTEN__
+void TC3_Handler(void);
+#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
+++ /dev/null
-/*
- * 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_buzzer.h"
-#include "watch_private_buzzer.h"
-#include "watch_main_loop.h"
-
-#include <emscripten.h>
-#include <emscripten/html5.h>
-
-static bool buzzer_enabled = false;
-static uint32_t buzzer_period;
-
-void cb_watch_buzzer_seq(void *userData);
-
-static uint16_t _seq_position;
-static int8_t _tone_ticks, _repeat_counter;
-static long _em_interval_id = 0;
-static int8_t *_sequence;
-static void (*_cb_finished)(void);
-
-void _watch_enable_tcc(void) {}
-
-static inline void _em_interval_stop() {
- emscripten_clear_interval(_em_interval_id);
- _em_interval_id = 0;
-}
-
-void watch_buzzer_play_sequence(int8_t *note_sequence, void (*callback_on_end)(void)) {
- if (_em_interval_id) _em_interval_stop();
- watch_set_buzzer_off();
- _sequence = note_sequence;
- _cb_finished = callback_on_end;
- _seq_position = 0;
- _tone_ticks = 0;
- _repeat_counter = -1;
- // prepare buzzer
- watch_enable_buzzer();
- // initiate 64 hz callback
- _em_interval_id = emscripten_set_interval(cb_watch_buzzer_seq, (double)(1000/64), (void *)NULL);
-}
-
-void cb_watch_buzzer_seq(void *userData) {
- // callback for reading the note sequence
- (void) userData;
- if (_tone_ticks == 0) {
- if (_sequence[_seq_position] < 0 && _sequence[_seq_position + 1]) {
- // repeat indicator found
- if (_repeat_counter == -1) {
- // first encounter: load repeat counter
- _repeat_counter = _sequence[_seq_position + 1];
- } else _repeat_counter--;
- if (_repeat_counter > 0)
- // rewind
- if (_seq_position > _sequence[_seq_position] * -2)
- _seq_position += _sequence[_seq_position] * 2;
- else
- _seq_position = 0;
- else {
- // continue
- _seq_position += 2;
- _repeat_counter = -1;
- }
- }
- if (_sequence[_seq_position] && _sequence[_seq_position + 1]) {
- // read note
- BuzzerNote note = _sequence[_seq_position];
- if (note == BUZZER_NOTE_REST) {
- watch_set_buzzer_off();
- } else {
- watch_set_buzzer_period(NotePeriods[note]);
- watch_set_buzzer_on();
- }
- // set duration ticks and move to next tone
- _tone_ticks = _sequence[_seq_position + 1];
- _seq_position += 2;
- } else {
- // end the sequence
- watch_buzzer_abort_sequence();
- if (_cb_finished) _cb_finished();
- }
- } else _tone_ticks--;
-}
-
-void watch_buzzer_abort_sequence(void) {
- // ends/aborts the sequence
- if (_em_interval_id) _em_interval_stop();
- watch_set_buzzer_off();
-}
-
-void watch_enable_buzzer(void) {
- buzzer_enabled = true;
- buzzer_period = NotePeriods[BUZZER_NOTE_A4];
-
- EM_ASM({
- Module['audioContext'] = new (window.AudioContext || window.webkitAudioContext)();
- });
-}
-
-void watch_set_buzzer_period(uint32_t period) {
- if (!buzzer_enabled) return;
- buzzer_period = period;
-}
-
-void watch_disable_buzzer(void) {
- buzzer_enabled = false;
- buzzer_period = NotePeriods[BUZZER_NOTE_A4];
-
- EM_ASM({
- if (Module['audioContext']) {
- Module['audioContext'].close();
- Module['audioContext'] = null;
- }
- });
-}
-
-void watch_set_buzzer_on(void) {
- if (!buzzer_enabled) return;
-
- EM_ASM({
- const audioContext = Module['audioContext'];
- if (!audioContext) return;
-
- if (!(audioContext._oscillator && audioContext._gain)) {
- const oscillator = audioContext.createOscillator();
- const gain = audioContext.createGain();
- oscillator.type = 'triangle';
- oscillator.connect(gain);
- gain.connect(audioContext.destination);
- oscillator.start(0);
-
- audioContext._oscillator = oscillator;
- audioContext._gain = gain;
- }
-
- audioContext._oscillator.frequency.value = 1e6/$0;
- audioContext._gain.gain.value = volumeGain;
- }, buzzer_period);
-}
-
-void watch_set_buzzer_off(void) {
- if (!buzzer_enabled) return;
-
- EM_ASM({
- const audioContext = Module['audioContext'];
- if (audioContext && audioContext._gain) {
- audioContext._gain.gain.value = 0;
- }
- });
-}
-
-void watch_buzzer_play_note(BuzzerNote note, uint16_t duration_ms) {
- if (note == BUZZER_NOTE_REST) {
- watch_set_buzzer_off();
- } else {
- watch_set_buzzer_period(NotePeriods[note]);
- watch_set_buzzer_on();
- }
-
- main_loop_sleep(duration_ms);
- watch_set_buzzer_off();
-}
+++ /dev/null
-/*
- * 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);
-}
--- /dev/null
+/*
+ * 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_buzzer.h"
+#include "watch_private_buzzer.h"
+#include "watch_main_loop.h"
+
+#include <emscripten.h>
+#include <emscripten/html5.h>
+
+static bool buzzer_enabled = false;
+static uint32_t buzzer_period;
+
+void cb_watch_buzzer_seq(void *userData);
+
+static uint16_t _seq_position;
+static int8_t _tone_ticks, _repeat_counter;
+static long _em_interval_id = 0;
+static int8_t *_sequence;
+static void (*_cb_finished)(void);
+
+void _watch_enable_tcc(void) {}
+
+static inline void _em_interval_stop() {
+ emscripten_clear_interval(_em_interval_id);
+ _em_interval_id = 0;
+}
+
+void watch_buzzer_play_sequence(int8_t *note_sequence, void (*callback_on_end)(void)) {
+ if (_em_interval_id) _em_interval_stop();
+ watch_set_buzzer_off();
+ _sequence = note_sequence;
+ _cb_finished = callback_on_end;
+ _seq_position = 0;
+ _tone_ticks = 0;
+ _repeat_counter = -1;
+ // prepare buzzer
+ watch_enable_buzzer();
+ // initiate 64 hz callback
+ _em_interval_id = emscripten_set_interval(cb_watch_buzzer_seq, (double)(1000/64), (void *)NULL);
+}
+
+void cb_watch_buzzer_seq(void *userData) {
+ // callback for reading the note sequence
+ (void) userData;
+ if (_tone_ticks == 0) {
+ if (_sequence[_seq_position] < 0 && _sequence[_seq_position + 1]) {
+ // repeat indicator found
+ if (_repeat_counter == -1) {
+ // first encounter: load repeat counter
+ _repeat_counter = _sequence[_seq_position + 1];
+ } else _repeat_counter--;
+ if (_repeat_counter > 0)
+ // rewind
+ if (_seq_position > _sequence[_seq_position] * -2)
+ _seq_position += _sequence[_seq_position] * 2;
+ else
+ _seq_position = 0;
+ else {
+ // continue
+ _seq_position += 2;
+ _repeat_counter = -1;
+ }
+ }
+ if (_sequence[_seq_position] && _sequence[_seq_position + 1]) {
+ // read note
+ BuzzerNote note = _sequence[_seq_position];
+ if (note == BUZZER_NOTE_REST) {
+ watch_set_buzzer_off();
+ } else {
+ watch_set_buzzer_period(NotePeriods[note]);
+ watch_set_buzzer_on();
+ }
+ // set duration ticks and move to next tone
+ _tone_ticks = _sequence[_seq_position + 1];
+ _seq_position += 2;
+ } else {
+ // end the sequence
+ watch_buzzer_abort_sequence();
+ if (_cb_finished) _cb_finished();
+ }
+ } else _tone_ticks--;
+}
+
+void watch_buzzer_abort_sequence(void) {
+ // ends/aborts the sequence
+ if (_em_interval_id) _em_interval_stop();
+ watch_set_buzzer_off();
+}
+
+void watch_enable_buzzer(void) {
+ buzzer_enabled = true;
+ buzzer_period = NotePeriods[BUZZER_NOTE_A4];
+
+ EM_ASM({
+ Module['audioContext'] = new (window.AudioContext || window.webkitAudioContext)();
+ });
+}
+
+void watch_set_buzzer_period(uint32_t period) {
+ if (!buzzer_enabled) return;
+ buzzer_period = period;
+}
+
+void watch_disable_buzzer(void) {
+ buzzer_enabled = false;
+ buzzer_period = NotePeriods[BUZZER_NOTE_A4];
+
+ EM_ASM({
+ if (Module['audioContext']) {
+ Module['audioContext'].close();
+ Module['audioContext'] = null;
+ }
+ });
+}
+
+void watch_set_buzzer_on(void) {
+ if (!buzzer_enabled) return;
+
+ EM_ASM({
+ const audioContext = Module['audioContext'];
+ if (!audioContext) return;
+
+ if (!(audioContext._oscillator && audioContext._gain)) {
+ const oscillator = audioContext.createOscillator();
+ const gain = audioContext.createGain();
+ oscillator.type = 'triangle';
+ oscillator.connect(gain);
+ gain.connect(audioContext.destination);
+ oscillator.start(0);
+
+ audioContext._oscillator = oscillator;
+ audioContext._gain = gain;
+ }
+
+ audioContext._oscillator.frequency.value = 1e6/$0;
+ audioContext._gain.gain.value = volumeGain;
+ }, buzzer_period);
+}
+
+void watch_set_buzzer_off(void) {
+ if (!buzzer_enabled) return;
+
+ EM_ASM({
+ const audioContext = Module['audioContext'];
+ if (audioContext && audioContext._gain) {
+ audioContext._gain.gain.value = 0;
+ }
+ });
+}
+
+void watch_buzzer_play_note(BuzzerNote note, uint16_t duration_ms) {
+ if (note == BUZZER_NOTE_REST) {
+ watch_set_buzzer_off();
+ } else {
+ watch_set_buzzer_period(NotePeriods[note]);
+ watch_set_buzzer_on();
+ }
+
+ main_loop_sleep(duration_ms);
+ 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);
+}