Add support for Sensor Watch Pro (#412)

* Sensor Watch Pro board definition

* Disable hot-plugging on SWCLK

* Add rainbow test

* Move interrupt mapping to board config

* New color definition for Pro boards in makefile
This commit is contained in:
Jose Castillo
2024-07-06 11:07:02 -04:00
committed by GitHub
parent 89a2af92ef
commit d98d14d236
15 changed files with 282 additions and 38 deletions

View File

@@ -37,6 +37,7 @@
#include <string.h>
#include <utils.h>
#include <utils_assert.h>
#include "pins.h"
#ifdef __MINGW32__
#define ffs __builtin_ffs
@@ -62,16 +63,6 @@ static int ffs(int v)
#define INVALID_EXTINT_NUMBER 0xFF
#define INVALID_PIN_NUMBER 0xFFFFFFFF
#ifndef CONFIG_EIC_EXTINT_MAP
/** Dummy mapping to pass compiling. */
#define CONFIG_EIC_EXTINT_MAP \
{ \
INVALID_EXTINT_NUMBER, INVALID_PIN_NUMBER \
}
#endif
#define EXT_IRQ_AMOUNT 6
/**
* \brief EXTINTx and pin number map
*/

View File

@@ -35,10 +35,24 @@ void watch_disable_leds(void) {
}
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) {
#ifndef WATCH_BLUE_TCC_CHANNEL
(void) blue; // silence warning
#endif
if (hri_tcc_get_CTRLA_reg(TCC0, TCC_CTRLA_ENABLE)) {
uint32_t period = hri_tcc_get_PER_reg(TCC0, TCC_PER_MASK);
hri_tcc_write_CCBUF_reg(TCC0, WATCH_RED_TCC_CHANNEL, ((period * red * 1000ull) / 255000ull));
hri_tcc_write_CCBUF_reg(TCC0, WATCH_GREEN_TCC_CHANNEL, ((period * green * 1000ull) / 255000ull));
#ifdef WATCH_BLUE_TCC_CHANNEL
hri_tcc_write_CCBUF_reg(TCC0, WATCH_BLUE_TCC_CHANNEL, ((period * blue * 1000ull) / 255000ull));
#endif
}
}

View File

@@ -31,6 +31,11 @@ void _watch_init(void) {
// disable the LED pin (it may have been enabled by the bootloader)
watch_disable_digital_output(GPIO(GPIO_PORTA, 20));
// disable debugger hot-plugging
gpio_set_pin_function(SWCLK, GPIO_PIN_FUNCTION_OFF);
gpio_set_pin_direction(SWCLK, GPIO_DIRECTION_OFF);
gpio_set_pin_pull_mode(SWCLK, GPIO_PULL_OFF);
// RAM should be back-biased in STANDBY
PM->STDBYCFG.bit.BBIASHS = 1;
@@ -152,11 +157,14 @@ void _watch_enable_tcc(void) {
// period (i.e. a square wave with a 50% duty cycle).
// * LEDs on CC[2] and CC[3] can be set to any value from 0 (off) to PER (fully on).
hri_tcc_write_WAVE_reg(TCC0, TCC_WAVE_WAVEGEN_NPWM);
#ifdef WATCH_INVERT_LED_POLARITY
// This is here for the dev board, which uses a common anode LED (instead of common cathode like the actual watch).
#ifdef WATCH_INVERT_LED_POLARITY
// This is here for the dev board and Pro, which use a common anode LED (instead of common cathode like the actual watch).
hri_tcc_set_WAVE_reg(TCC0, (1 << (TCC_WAVE_POL0_Pos + WATCH_RED_TCC_CHANNEL)) |
#ifdef WATCH_BLUE_TCC_CHANNEL
(1 << (TCC_WAVE_POL0_Pos + WATCH_BLUE_TCC_CHANNEL)) |
#endif // WATCH_BLUE_TCC_CHANNEL
(1 << (TCC_WAVE_POL0_Pos + WATCH_GREEN_TCC_CHANNEL)));
#endif
#endif // WATCH_INVERT_LED_POLARITY
// The buzzer will set the period depending on the tone it wants to play, but we have to set some period here to
// get the LED working. Almost any period will do, tho it should be below 20000 (i.e. 50 Hz) to avoid flickering.
hri_tcc_write_PER_reg(TCC0, 1024);
@@ -164,6 +172,9 @@ void _watch_enable_tcc(void) {
hri_tcc_write_CC_reg(TCC0, WATCH_BUZZER_TCC_CHANNEL, 0);
hri_tcc_write_CC_reg(TCC0, WATCH_RED_TCC_CHANNEL, 0);
hri_tcc_write_CC_reg(TCC0, WATCH_GREEN_TCC_CHANNEL, 0);
#ifdef WATCH_BLUE_TCC_CHANNEL
hri_tcc_write_CC_reg(TCC0, WATCH_BLUE_TCC_CHANNEL, 0);
#endif
// Enable the TCC
hri_tcc_set_CTRLA_ENABLE_bit(TCC0);
hri_tcc_wait_for_sync(TCC0, TCC_SYNCBUSY_ENABLE);
@@ -173,6 +184,10 @@ void _watch_enable_tcc(void) {
gpio_set_pin_function(RED, WATCH_RED_TCC_PINMUX);
gpio_set_pin_direction(GREEN, GPIO_DIRECTION_OUT);
gpio_set_pin_function(GREEN, WATCH_GREEN_TCC_PINMUX);
#ifdef WATCH_BLUE_TCC_CHANNEL
gpio_set_pin_direction(BLUE, GPIO_DIRECTION_OUT);
gpio_set_pin_function(BLUE, WATCH_BLUE_TCC_PINMUX);
#endif
}
void _watch_disable_tcc(void) {
@@ -183,6 +198,10 @@ void _watch_disable_tcc(void) {
gpio_set_pin_function(RED, GPIO_PIN_FUNCTION_OFF);
gpio_set_pin_direction(GREEN, GPIO_DIRECTION_OFF);
gpio_set_pin_function(GREEN, GPIO_PIN_FUNCTION_OFF);
#ifdef WATCH_BLUE_TCC_CHANNEL
gpio_set_pin_direction(BLUE, GPIO_DIRECTION_OFF);
gpio_set_pin_function(BLUE, GPIO_PIN_FUNCTION_OFF);
#endif
// disable the TCC
hri_tcc_clear_CTRLA_ENABLE_bit(TCC0);

View File

@@ -481,7 +481,7 @@
// <i> Indicates whether the external interrupt 10 filter is enabled or not
// <id> eic_arch_filten10
#ifndef CONF_EIC_FILTEN10
#define CONF_EIC_FILTEN10 0
#define CONF_EIC_FILTEN10 1
#endif
// <q> External Interrupt 10 Event Output Enable
@@ -523,7 +523,7 @@
// <i> Indicates whether the external interrupt 11 filter is enabled or not
// <id> eic_arch_filten11
#ifndef CONF_EIC_FILTEN11
#define CONF_EIC_FILTEN11 0
#define CONF_EIC_FILTEN11 1
#endif
// <q> External Interrupt 11 Event Output Enable
@@ -723,14 +723,6 @@
// </e>
// this is still a hack: if the user wants to use PA02 (alarm button) as an RTC interrupt pin and PB02 (9-pin A2) on the EIC, we don't support that.
// TODO item: refactor out our reliance on the ASF external interrupt driver. - joey 11/30
#ifdef CRYSTALLESS
#define CONFIG_EIC_EXTINT_MAP {0, PIN_PB00}, {1, PIN_PB01}, {2, PIN_PA02}, {3, PIN_PB03}, {5, PIN_PB05}, {7, PIN_PA07},
#else
#define CONFIG_EIC_EXTINT_MAP {0, PIN_PB00}, {1, PIN_PB01}, {2, PIN_PA02}, {3, PIN_PB03}, {6, PIN_PA22}, {7, PIN_PA23},
#endif
// <<< end of configuration section >>>
#endif // HPL_EIC_CONFIG_H

View File

@@ -30,6 +30,9 @@
#include "driver_init.h"
#include "pins.h"
#define SWCLK GPIO(GPIO_PORTA, 30)
#define SWDIO GPIO(GPIO_PORTA, 31)
#ifdef __EMSCRIPTEN__
#include "watch_main_loop.h"
#endif // __EMSCRIPTEN__

View File

@@ -63,6 +63,16 @@ void watch_disable_leds(void);
*/
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).
*/

View File

@@ -44,6 +44,11 @@ void watch_set_led_color(uint8_t red, uint8_t green) {
}, 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);
}