--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include "watch.h"
+
+void app_init(void) {
+}
+
+void app_wake_from_backup(void) {
+}
+
+void app_setup(void) {
+ watch_enable_leds();
+}
+
+void app_prepare_for_standby(void) {
+}
+
+void app_wake_from_standby(void) {
+}
+
+bool app_loop(void) {
+ static uint8_t red = 0;
+ static uint8_t green = 0;
+ static uint8_t blue = 255;
+ static uint8_t phase = 0;
+
+ switch (phase) {
+ case 0:
+ red++;
+ if (red == 255) phase = 1;
+ break;
+ case 1:
+ green++;
+ if (green == 255) phase = 2;
+ break;
+ case 2:
+ red--;
+ if (red == 0) phase = 3;
+ break;
+ case 3:
+ blue++;
+ if (blue == 255) phase = 4;
+ break;
+ case 4:
+ green--;
+ if (green == 0) phase = 5;
+ break;
+ case 5:
+ red++;
+ if (red == 255) phase = 6;
+ break;
+ case 6:
+ blue--;
+ if (blue == 0) {
+ phase = 1;
+ }
+ break;
+ }
+
+ watch_set_led_color_rgb(red, green, blue);
+ delay_ms(2);
+
+ return false;
+}
--- /dev/null
+TOP = ../../..
+include $(TOP)/make.mk
+
+INCLUDES += \
+ -I../
+
+SRCS += \
+ ../app.c
+
+include $(TOP)/rules.mk
#define D0 GPIO(GPIO_PORTB, 3)
#define D1 GPIO(GPIO_PORTB, 0)
+// interrupt mapping
+#define EXT_IRQ_AMOUNT 6
+#define CONFIG_EIC_EXTINT_MAP {0, PIN_PB00}, {1, PIN_PB01}, {2, PIN_PA02}, {3, PIN_PB03}, {5, PIN_PB05}, {7, PIN_PA07},
+
#endif // PINS_H_INCLUDED
#define D0 GPIO(GPIO_PORTB, 3)
#define D1 GPIO(GPIO_PORTB, 0)
+// interrupt mapping
+#define EXT_IRQ_AMOUNT 6
+#define CONFIG_EIC_EXTINT_MAP {0, PIN_PB00}, {1, PIN_PB01}, {2, PIN_PA02}, {3, PIN_PB03}, {6, PIN_PA22}, {7, PIN_PA23},
+
#endif // PINS_H_INCLUDED
#define D0 GPIO(GPIO_PORTB, 3)
#define D1 GPIO(GPIO_PORTB, 0)
+// interrupt mapping
+#define EXT_IRQ_AMOUNT 6
+#define CONFIG_EIC_EXTINT_MAP {0, PIN_PB00}, {1, PIN_PB01}, {2, PIN_PA02}, {3, PIN_PB03}, {6, PIN_PA22}, {7, PIN_PA23},
+
#endif // PINS_H_INCLUDED
#define D0 GPIO(GPIO_PORTB, 3)
#define D1 GPIO(GPIO_PORTB, 0)
+// interrupt mapping
+#define EXT_IRQ_AMOUNT 6
+#define CONFIG_EIC_EXTINT_MAP {0, PIN_PB00}, {1, PIN_PB01}, {2, PIN_PA02}, {3, PIN_PB03}, {6, PIN_PA22}, {7, PIN_PA23},
+
#endif // PINS_H_INCLUDED
--- /dev/null
+#ifndef PINS_H_INCLUDED
+#define PINS_H_INCLUDED
+
+// Detects if we are on USB power.
+#define VBUS_DET GPIO(GPIO_PORTB, 5)
+
+// Buttons
+#define BTN_ALARM GPIO(GPIO_PORTA, 2)
+#define WATCH_BTN_ALARM_EIC_CHANNEL 2
+#define BTN_LIGHT GPIO(GPIO_PORTA, 30)
+#define WATCH_BTN_LIGHT_EIC_CHANNEL 10
+#define BTN_MODE GPIO(GPIO_PORTA, 31)
+#define WATCH_BTN_MODE_EIC_CHANNEL 11
+
+// Buzzer
+#define BUZZER GPIO(GPIO_PORTA, 27)
+#define WATCH_BUZZER_TCC_PINMUX PINMUX_PA27F_TCC0_WO5
+#define WATCH_BUZZER_TCC_CHANNEL 1
+
+// LEDs
+#define WATCH_INVERT_LED_POLARITY
+
+#define RED GPIO(GPIO_PORTA, 12)
+#define WATCH_RED_TCC_CHANNEL 2
+#define WATCH_RED_TCC_PINMUX PINMUX_PA12F_TCC0_WO6
+
+#define BLUE GPIO(GPIO_PORTA, 13)
+#define WATCH_BLUE_TCC_CHANNEL 3
+#define WATCH_BLUE_TCC_PINMUX PINMUX_PA13F_TCC0_WO7
+
+#define GREEN GPIO(GPIO_PORTA, 22)
+#define WATCH_GREEN_TCC_CHANNEL 0
+#define WATCH_GREEN_TCC_PINMUX PINMUX_PA22F_TCC0_WO4
+
+// Segment LCD
+#define SLCD0 GPIO(GPIO_PORTB, 6)
+#define SLCD1 GPIO(GPIO_PORTB, 7)
+#define SLCD2 GPIO(GPIO_PORTB, 8)
+#define SLCD3 GPIO(GPIO_PORTB, 9)
+#define SLCD4 GPIO(GPIO_PORTA, 5)
+#define SLCD5 GPIO(GPIO_PORTA, 6)
+#define SLCD6 GPIO(GPIO_PORTA, 7)
+#define SLCD7 GPIO(GPIO_PORTA, 8)
+#define SLCD8 GPIO(GPIO_PORTA, 9)
+#define SLCD9 GPIO(GPIO_PORTA, 10)
+#define SLCD10 GPIO(GPIO_PORTA, 11)
+#define SLCD11 GPIO(GPIO_PORTB, 11)
+#define SLCD12 GPIO(GPIO_PORTB, 12)
+#define SLCD13 GPIO(GPIO_PORTB, 13)
+#define SLCD14 GPIO(GPIO_PORTB, 14)
+#define SLCD15 GPIO(GPIO_PORTB, 15)
+#define SLCD16 GPIO(GPIO_PORTA, 14)
+#define SLCD17 GPIO(GPIO_PORTA, 15)
+#define SLCD18 GPIO(GPIO_PORTA, 16)
+#define SLCD19 GPIO(GPIO_PORTA, 17)
+#define SLCD20 GPIO(GPIO_PORTA, 18)
+#define SLCD21 GPIO(GPIO_PORTA, 19)
+#define SLCD22 GPIO(GPIO_PORTB, 16)
+#define SLCD23 GPIO(GPIO_PORTB, 17)
+#define SLCD24 GPIO(GPIO_PORTA, 20)
+#define SLCD25 GPIO(GPIO_PORTA, 21)
+#define SLCD26 GPIO(GPIO_PORTA, 23)
+// This board uses a slightly different pin mapping from the standard watch, and it's not enough to
+// just declare the pins. We also have to set the LCD Pin Enable register with the SLCD pins we're
+// using. These numbers are not port/pin numbers, but the "SLCD/LP[x]" numbers in the pinmux table.
+// If not defined in pins.h, the LCD driver will fall back to the pin mapping in hpl_slcd_config.h.
+// LPENL is for pins SLCD/LP[0..31].
+#define CONF_SLCD_LPENL (\
+ (uint32_t)1 << 0 | \
+ (uint32_t)1 << 1 | \
+ (uint32_t)1 << 2 | \
+ (uint32_t)1 << 3 | \
+ (uint32_t)1 << 5 | \
+ (uint32_t)1 << 6 | \
+ (uint32_t)1 << 7 | \
+ (uint32_t)1 << 11 | \
+ (uint32_t)1 << 12 | \
+ (uint32_t)1 << 13 | \
+ (uint32_t)1 << 14 | \
+ (uint32_t)1 << 21 | \
+ (uint32_t)1 << 22 | \
+ (uint32_t)1 << 23 | \
+ (uint32_t)1 << 24 | \
+ (uint32_t)1 << 25 | \
+ (uint32_t)1 << 30 | \
+ (uint32_t)1 << 31 | 0)
+// LPENH is for pins SLCD/LP[32..51], where bit 0 represents pin 32.
+#define CONF_SLCD_LPENH (\
+ (uint32_t)1 << (32 - 32) | \
+ (uint32_t)1 << (33 - 32) | \
+ (uint32_t)1 << (34 - 32) | \
+ (uint32_t)1 << (35 - 32) | \
+ (uint32_t)1 << (42 - 32) | \
+ (uint32_t)1 << (43 - 32) | \
+ (uint32_t)1 << (48 - 32) | \
+ (uint32_t)1 << (49 - 32) | \
+ (uint32_t)1 << (51 - 32) | 0)
+
+
+// 9-pin connector
+#define A0 GPIO(GPIO_PORTB, 4)
+#define WATCH_A0_EIC_CHANNEL 4
+#define A1 GPIO(GPIO_PORTB, 1)
+#define WATCH_A1_EIC_CHANNEL 1
+#define A2 GPIO(GPIO_PORTB, 2)
+#define WATCH_A2_EIC_CHANNEL 2
+#define A3 GPIO(GPIO_PORTB, 3)
+#define WATCH_A3_EIC_CHANNEL 3
+#define A4 GPIO(GPIO_PORTB, 0)
+#define WATCH_A4_EIC_CHANNEL 0
+#define SDA GPIO(GPIO_PORTB, 30)
+#define SCL GPIO(GPIO_PORTB, 31)
+
+// aliases for as A3/A4; these were mentioned as D0/D1 in early documentation.
+#define D0 GPIO(GPIO_PORTB, 3)
+#define D1 GPIO(GPIO_PORTB, 0)
+
+// interrupt mapping
+#define EXT_IRQ_AMOUNT 6
+#define CONFIG_EIC_EXTINT_MAP {0, PIN_PB00}, {1, PIN_PB01}, {2, PIN_PA02}, {3, PIN_PB03}, {10, PIN_PA30}, {11, PIN_PA31},
+
+#endif // PINS_H_INCLUDED
endif
BIN = watch
-ifndef BOARD
+ifndef COLOR
+$(error Set the COLOR variable to RED, BLUE, GREEN or PRO depending on what board you have.)
+endif
+
+COLOR_VALID := $(filter $(COLOR),RED BLUE GREEN PRO)
+
+ifeq ($(COLOR_VALID),)
+$(error COLOR must be RED, BLUE, GREEN or PRO)
+endif
+
+ifeq ($(COLOR), PRO)
+override BOARD = OSO-SWAT-C1-00
+else
override BOARD = OSO-SWAT-A1-05
endif
endif
-ifeq ($(LED), BLUE)
-CFLAGS += -DWATCH_IS_BLUE_BOARD
-endif
-
-ifndef COLOR
-$(error Set the COLOR variable to RED, BLUE, or GREEN depending on what board you have.)
-endif
-
-COLOR_VALID := $(filter $(COLOR),RED BLUE GREEN)
-
-ifeq ($(COLOR_VALID),)
-$(error COLOR must be RED, BLUE, or GREEN)
-endif
-
ifeq ($(COLOR), BLUE)
CFLAGS += -DWATCH_IS_BLUE_BOARD
endif
#include <string.h>
#include <utils.h>
#include <utils_assert.h>
+#include "pins.h"
#ifdef __MINGW32__
#define ffs __builtin_ffs
#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
*/
}
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
}
}
// 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;
// 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);
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);
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) {
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);
// <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
// <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
// </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
#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__
*/
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).
*/
}, 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);
}