diff --git a/apps/pro-rainbow-test/app.c b/apps/pro-rainbow-test/app.c new file mode 100644 index 0000000..b26f39e --- /dev/null +++ b/apps/pro-rainbow-test/app.c @@ -0,0 +1,64 @@ +#include +#include +#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; +} diff --git a/apps/pro-rainbow-test/make/Makefile b/apps/pro-rainbow-test/make/Makefile new file mode 100755 index 0000000..c66ad20 --- /dev/null +++ b/apps/pro-rainbow-test/make/Makefile @@ -0,0 +1,10 @@ +TOP = ../../.. +include $(TOP)/make.mk + +INCLUDES += \ + -I../ + +SRCS += \ + ../app.c + +include $(TOP)/rules.mk diff --git a/boards/OSO-FEAL-A1-00/pins.h b/boards/OSO-FEAL-A1-00/pins.h index 7249f98..1f8ff80 100644 --- a/boards/OSO-FEAL-A1-00/pins.h +++ b/boards/OSO-FEAL-A1-00/pins.h @@ -120,4 +120,8 @@ #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 diff --git a/boards/OSO-SWAT-A1-02/pins.h b/boards/OSO-SWAT-A1-02/pins.h index 1711be2..efe7654 100644 --- a/boards/OSO-SWAT-A1-02/pins.h +++ b/boards/OSO-SWAT-A1-02/pins.h @@ -81,4 +81,8 @@ #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 diff --git a/boards/OSO-SWAT-A1-04/pins.h b/boards/OSO-SWAT-A1-04/pins.h index 2b851d9..ee91017 100644 --- a/boards/OSO-SWAT-A1-04/pins.h +++ b/boards/OSO-SWAT-A1-04/pins.h @@ -81,4 +81,8 @@ #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 diff --git a/boards/OSO-SWAT-A1-05/pins.h b/boards/OSO-SWAT-A1-05/pins.h index 7d31b26..227f9ef 100644 --- a/boards/OSO-SWAT-A1-05/pins.h +++ b/boards/OSO-SWAT-A1-05/pins.h @@ -81,4 +81,8 @@ #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 diff --git a/boards/OSO-SWAT-C1-00/pins.h b/boards/OSO-SWAT-C1-00/pins.h new file mode 100644 index 0000000..15c016e --- /dev/null +++ b/boards/OSO-SWAT-C1-00/pins.h @@ -0,0 +1,122 @@ +#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 diff --git a/make.mk b/make.mk index 00933d0..f4f796f 100644 --- a/make.mk +++ b/make.mk @@ -6,7 +6,19 @@ BUILD = ./build-sim 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 @@ -205,20 +217,6 @@ SRCS += \ 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 diff --git a/watch-library/hardware/hpl/eic/hpl_eic.c b/watch-library/hardware/hpl/eic/hpl_eic.c index 2bd3161..e74de75 100644 --- a/watch-library/hardware/hpl/eic/hpl_eic.c +++ b/watch-library/hardware/hpl/eic/hpl_eic.c @@ -37,6 +37,7 @@ #include #include #include +#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 */ diff --git a/watch-library/hardware/watch/watch_led.c b/watch-library/hardware/watch/watch_led.c index 5e2d8ec..ba5c043 100644 --- a/watch-library/hardware/watch/watch_led.c +++ b/watch-library/hardware/watch/watch_led.c @@ -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 } } diff --git a/watch-library/hardware/watch/watch_private.c b/watch-library/hardware/watch/watch_private.c index 67d8b51..85ada4e 100644 --- a/watch-library/hardware/watch/watch_private.c +++ b/watch-library/hardware/watch/watch_private.c @@ -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); diff --git a/watch-library/shared/config/hpl_eic_config.h b/watch-library/shared/config/hpl_eic_config.h index a687151..590109d 100644 --- a/watch-library/shared/config/hpl_eic_config.h +++ b/watch-library/shared/config/hpl_eic_config.h @@ -481,7 +481,7 @@ // Indicates whether the external interrupt 10 filter is enabled or not // eic_arch_filten10 #ifndef CONF_EIC_FILTEN10 -#define CONF_EIC_FILTEN10 0 +#define CONF_EIC_FILTEN10 1 #endif // External Interrupt 10 Event Output Enable @@ -523,7 +523,7 @@ // Indicates whether the external interrupt 11 filter is enabled or not // eic_arch_filten11 #ifndef CONF_EIC_FILTEN11 -#define CONF_EIC_FILTEN11 0 +#define CONF_EIC_FILTEN11 1 #endif // External Interrupt 11 Event Output Enable @@ -723,14 +723,6 @@ // -// 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 diff --git a/watch-library/shared/watch/watch.h b/watch-library/shared/watch/watch.h index 62e57a5..a447426 100644 --- a/watch-library/shared/watch/watch.h +++ b/watch-library/shared/watch/watch.h @@ -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__ diff --git a/watch-library/shared/watch/watch_led.h b/watch-library/shared/watch/watch_led.h index 7e2dea2..fcb8c5e 100644 --- a/watch-library/shared/watch/watch_led.h +++ b/watch-library/shared/watch/watch_led.h @@ -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). */ diff --git a/watch-library/simulator/watch/watch_led.c b/watch-library/simulator/watch/watch_led.c index 636dc74..584611f 100644 --- a/watch-library/simulator/watch/watch_led.c +++ b/watch-library/simulator/watch/watch_led.c @@ -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); }