diff --git a/Makefile b/Makefile index ab894cec..911b025c 100644 --- a/Makefile +++ b/Makefile @@ -7,24 +7,21 @@ BOARD=sensorwatch_red # Which screen are we building for? DISPLAY=CLASSIC +# Support USB features? TINYUSB_CDC=1 # Leave this line here. include $(GOSSAMER_PATH)/make.mk -# this is a hack and does not currently work; we need to integrate a bit of -# emscripten support into gossamer to actually build for the simulator ifdef EMSCRIPTEN -BUILD = ./build-sim -CC = emcc -all: $(BUILD)/$(BIN).html +all: $(BUILD)/$(BIN).elf $(BUILD)/$(BIN).html $(BUILD)/$(BIN).html: $(OBJS) @echo HTML $@ @$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ \ -s ASYNCIFY=1 \ -s EXPORTED_RUNTIME_METHODS=lengthBytesUTF8,printErr \ -s EXPORTED_FUNCTIONS=_main \ - --shell-file=$(TOP)/watch-library/simulator/shell.html + --shell-file=./watch-library/simulator/shell.html endif # Add your include directories here. @@ -37,7 +34,6 @@ INCLUDES += \ -I./shell \ -I./movement/lib/sunriset \ -I./watch-library/shared/watch \ - -I./watch-library/hardware/watch \ -I./watch-faces/clock \ -I./watch-faces/complication \ -I./watch-faces/demo \ @@ -57,6 +53,30 @@ SRCS += \ ./watch-library/shared/watch/watch_common_buzzer.c \ ./watch-library/shared/watch/watch_common_display.c \ ./watch-library/shared/watch/watch_utility.c \ + +ifdef EMSCRIPTEN + +INCLUDES += \ + -I./watch-library/simulator/watch \ + +SRCS += \ + ./watch-library/simulator/watch/watch.c \ + ./watch-library/simulator/watch/watch_adc.c \ + ./watch-library/simulator/watch/watch_deepsleep.c \ + ./watch-library/simulator/watch/watch_extint.c \ + ./watch-library/simulator/watch/watch_gpio.c \ + ./watch-library/simulator/watch/watch_private.c \ + ./watch-library/simulator/watch/watch_rtc.c \ + ./watch-library/simulator/watch/watch_slcd.c \ + ./watch-library/simulator/watch/watch_storage.c \ + ./watch-library/simulator/watch/watch_tcc.c \ + +else + +INCLUDES += \ + -I./watch-library/hardware/watch \ + +SRCS += \ ./watch-library/hardware/watch/watch.c \ ./watch-library/hardware/watch/watch_adc.c \ ./watch-library/hardware/watch/watch_deepsleep.c \ @@ -70,6 +90,8 @@ SRCS += \ ./watch-library/hardware/watch/watch_usb_descriptors.c \ ./watch-library/hardware/watch/watch_usb_cdc.c \ +endif + include watch-faces.mk SRCS += \ diff --git a/movement.c b/movement.c index e6614620..ee8f6cc6 100644 --- a/movement.c +++ b/movement.c @@ -34,7 +34,6 @@ #include "watch.h" #include "watch_utility.h" #include "usb.h" -#include "watch_usb_cdc.h" #include "watch_private.h" #include "movement.h" #include "filesystem.h" @@ -48,6 +47,8 @@ #if __EMSCRIPTEN__ #include +#else +#include "watch_usb_cdc.h" #endif movement_state_t movement_state; @@ -71,10 +72,15 @@ void cb_alarm_fired(void); void cb_fast_tick(void); void cb_tick(void); +#if __EMSCRIPTEN__ +void yield(void) { +} +#else void yield(void) { tud_task(); cdc_task(); } +#endif static udatetime_t _movement_convert_date_time_to_udate(watch_date_time_t date_time) { return (udatetime_t) { @@ -553,15 +559,16 @@ void app_init(void) { filesystem_init(); #if __EMSCRIPTEN__ - int32_t time_zone_offset = EM_ASM_INT({ - return -new Date().getTimezoneOffset(); - }); - for (int i = 0, count = sizeof(movement_timezone_offsets) / sizeof(movement_timezone_offsets[0]); i < count; i++) { - if (movement_timezone_offsets[i] == time_zone_offset) { - movement_state.settings.bit.time_zone = i; - break; - } - } + /// FIXME: for #SecondMovement: Figure out how to set the time zone automatically! This method no longer works. + // int32_t time_zone_offset = EM_ASM_INT({ + // return -new Date().getTimezoneOffset(); + // }); + // for (int i = 0, count = sizeof(movement_timezone_offsets) / sizeof(movement_timezone_offsets[0]); i < count; i++) { + // if (movement_timezone_offsets[i] == time_zone_offset) { + // movement_state.settings.bit.time_zone = i; + // break; + // } + // } #endif } diff --git a/shell/shell.c b/shell/shell.c index c028ed23..b145c87e 100644 --- a/shell/shell.c +++ b/shell/shell.c @@ -35,6 +35,12 @@ #if __EMSCRIPTEN__ #include + +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + #endif #include "watch.h" diff --git a/watch-library/simulator/main.c b/watch-library/simulator/main.c deleted file mode 100644 index 5e5070ff..00000000 --- a/watch-library/simulator/main.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022 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 -#include "watch.h" -#include "watch_main_loop.h" - -#include -#include - -#define ANIMATION_FRAME_ID_IS_VALID(id) ((id) >= 0) -#define ANIMATION_FRAME_ID_INVALID (-1) -#define ANIMATION_FRAME_ID_SUSPENDED (-2) - -static bool sleeping = true; -static volatile long animation_frame_id = ANIMATION_FRAME_ID_INVALID; - -// make compiler happy -static void main_loop_set_sleeping(bool sleeping); -static EM_BOOL main_loop(double time, void *userData); - -static inline void request_next_frame(void) { - if (animation_frame_id == ANIMATION_FRAME_ID_INVALID) { - animation_frame_id = emscripten_request_animation_frame(main_loop, NULL); - } -} - -static EM_BOOL main_loop(double time, void *userData) { - if (main_loop_is_sleeping()) { - request_next_frame(); - return EM_FALSE; - } - - if (sleeping) { - sleeping = false; - app_wake_from_standby(); - } - - animation_frame_id = ANIMATION_FRAME_ID_INVALID; - bool can_sleep = app_loop(); - - if (can_sleep) { - app_prepare_for_standby(); - sleeping = true; - animation_frame_id = ANIMATION_FRAME_ID_INVALID; - return EM_FALSE; - } - - request_next_frame(); - return EM_FALSE; -} - -void resume_main_loop(void) { - if (!ANIMATION_FRAME_ID_IS_VALID(animation_frame_id)) { - animation_frame_id = emscripten_request_animation_frame(main_loop, NULL); - } -} - -void suspend_main_loop(void) { - if (ANIMATION_FRAME_ID_IS_VALID(animation_frame_id)) { - emscripten_cancel_animation_frame(animation_frame_id); - } - - animation_frame_id = ANIMATION_FRAME_ID_SUSPENDED; -} - -void main_loop_sleep(uint32_t ms) { - main_loop_set_sleeping(true); - emscripten_sleep(ms); - main_loop_set_sleeping(false); - animation_frame_id = ANIMATION_FRAME_ID_INVALID; -} - -bool main_loop_is_sleeping(void) { - return EM_ASM_INT({ return Module['suspended']; }) != 0; -} - -static void main_loop_set_sleeping(bool sleeping) { - EM_ASM({ - Module['suspended'] = $0; - }, sleeping); -} - -void delay_ms(const uint16_t ms) { - main_loop_sleep(ms); -} - -int main(void) { - app_init(); - _watch_init(); - app_setup(); - - resume_main_loop(); - - return 0; -} diff --git a/watch-library/simulator/watch/watch_adc.c b/watch-library/simulator/watch/watch_adc.c index b03d68cb..c83dc3ed 100644 --- a/watch-library/simulator/watch/watch_adc.c +++ b/watch-library/simulator/watch/watch_adc.c @@ -26,9 +26,9 @@ void watch_enable_adc(void) {} -void watch_enable_analog_input(const uint8_t pin) {} +void watch_enable_analog_input(const uint16_t pin) {} -uint16_t watch_get_analog_pin_level(const uint8_t pin) { +uint16_t watch_get_analog_pin_level(const uint16_t pin) { return 32767; // pretend it's half of VCC } @@ -36,13 +36,13 @@ void watch_set_analog_num_samples(uint16_t samples) {} void watch_set_analog_sampling_length(uint8_t cycles) {} -void watch_set_analog_reference_voltage(watch_adc_reference_voltage reference) {} +void watch_set_analog_reference_voltage(uint8_t reference) {} uint16_t watch_get_vcc_voltage(void) { // TODO: (a2) hook to UI return 3000; } -inline void watch_disable_analog_input(const uint8_t pin) {} +inline void watch_disable_analog_input(const uint16_t pin) {} inline void watch_disable_adc(void) {} diff --git a/watch-library/simulator/watch/watch_deepsleep.c b/watch-library/simulator/watch/watch_deepsleep.c index 5add05e8..1bc4be73 100644 --- a/watch-library/simulator/watch/watch_deepsleep.c +++ b/watch-library/simulator/watch/watch_deepsleep.c @@ -22,26 +22,20 @@ * SOFTWARE. */ +#include #include "watch_extint.h" - -// this warning only appears when you `make BOARD=OSO-SWAT-A1-02`. it's annoying, -// but i'd rather have it warn us at build-time than fail silently at run-time. -// besides, no one but me really has any of these boards anyway. -#if BTN_ALARM != GPIO(GPIO_PORTA, 2) -#warning This board revision does not support external wake on BTN_ALARM, so watch_register_extwake_callback will not work with it. Use watch_register_interrupt_callback instead. -#endif - +#include "app.h" static uint32_t watch_backup_data[8]; -void watch_register_extwake_callback(uint8_t pin, ext_irq_cb_t callback, bool level) { - if (pin == BTN_ALARM) { +void watch_register_extwake_callback(uint8_t pin, watch_cb_t callback, bool level) { + if (pin == HAL_GPIO_BTN_ALARM_pin()) { watch_enable_external_interrupts(); watch_register_interrupt_callback(pin, callback, level ? INTERRUPT_TRIGGER_RISING : INTERRUPT_TRIGGER_FALLING); } } void watch_disable_extwake_interrupt(uint8_t pin) { - if (pin == BTN_ALARM) { + if (pin == HAL_GPIO_BTN_ALARM_pin()) { watch_register_interrupt_callback(pin, NULL, INTERRUPT_TRIGGER_NONE); } } @@ -68,9 +62,6 @@ void watch_enter_sleep_mode(void) { // call app_setup so the app can re-enable everything we disabled. app_setup(); - - // and call app_wake_from_standby (since main won't have a chance to do it) - app_wake_from_standby(); } void watch_enter_deep_sleep_mode(void) { diff --git a/watch-library/simulator/watch/watch_extint.c b/watch-library/simulator/watch/watch_extint.c index b5894b95..4c0dc7c0 100644 --- a/watch-library/simulator/watch/watch_extint.c +++ b/watch-library/simulator/watch/watch_extint.c @@ -33,18 +33,18 @@ static bool debug_console_focused = false; static bool external_interrupt_enabled = false; static bool button_callbacks_installed = false; -static ext_irq_cb_t external_interrupt_mode_callback = NULL; -static watch_interrupt_trigger external_interrupt_mode_trigger = INTERRUPT_TRIGGER_NONE; -static ext_irq_cb_t external_interrupt_light_callback = NULL; -static watch_interrupt_trigger external_interrupt_light_trigger = INTERRUPT_TRIGGER_NONE; -static ext_irq_cb_t external_interrupt_alarm_callback = NULL; -static watch_interrupt_trigger external_interrupt_alarm_trigger = INTERRUPT_TRIGGER_NONE; +static watch_cb_t external_interrupt_mode_callback = NULL; +static eic_interrupt_trigger_t external_interrupt_mode_trigger = INTERRUPT_TRIGGER_NONE; +static watch_cb_t external_interrupt_light_callback = NULL; +static eic_interrupt_trigger_t external_interrupt_light_trigger = INTERRUPT_TRIGGER_NONE; +static watch_cb_t external_interrupt_alarm_callback = NULL; +static eic_interrupt_trigger_t external_interrupt_alarm_trigger = INTERRUPT_TRIGGER_NONE; #define BTN_ID_ALARM 3 #define BTN_ID_LIGHT 1 #define BTN_ID_MODE 2 static const uint8_t BTN_IDS[] = { BTN_ID_ALARM, BTN_ID_LIGHT, BTN_ID_MODE }; -static EM_BOOL watch_invoke_interrupt_callback(const uint8_t button_id, watch_interrupt_trigger trigger); +static EM_BOOL watch_invoke_interrupt_callback(const uint8_t button_id, eic_interrupt_trigger_t trigger); static EM_BOOL watch_invoke_key_callback(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) { if (debug_console_focused || keyEvent->repeat) return EM_FALSE; @@ -90,20 +90,20 @@ static EM_BOOL watch_invoke_key_callback(int eventType, const EmscriptenKeyboard return EM_FALSE; } - watch_interrupt_trigger trigger = eventType == EMSCRIPTEN_EVENT_KEYDOWN ? INTERRUPT_TRIGGER_RISING : INTERRUPT_TRIGGER_FALLING; + eic_interrupt_trigger_t trigger = eventType == EMSCRIPTEN_EVENT_KEYDOWN ? INTERRUPT_TRIGGER_RISING : INTERRUPT_TRIGGER_FALLING; return watch_invoke_interrupt_callback(button_id, trigger); } static EM_BOOL watch_invoke_mouse_callback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) { if (eventType == EMSCRIPTEN_EVENT_MOUSEOUT && mouseEvent->buttons == 0) return EM_FALSE; uint8_t button_id = *(const char *)userData; - watch_interrupt_trigger trigger = eventType == EMSCRIPTEN_EVENT_MOUSEDOWN ? INTERRUPT_TRIGGER_RISING : INTERRUPT_TRIGGER_FALLING; + eic_interrupt_trigger_t trigger = eventType == EMSCRIPTEN_EVENT_MOUSEDOWN ? INTERRUPT_TRIGGER_RISING : INTERRUPT_TRIGGER_FALLING; return watch_invoke_interrupt_callback(button_id, trigger); } static EM_BOOL watch_invoke_touch_callback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData) { uint8_t button_id = *(const char *)userData; - watch_interrupt_trigger trigger = eventType == EMSCRIPTEN_EVENT_TOUCHSTART ? INTERRUPT_TRIGGER_RISING : INTERRUPT_TRIGGER_FALLING; + eic_interrupt_trigger_t trigger = eventType == EMSCRIPTEN_EVENT_TOUCHSTART ? INTERRUPT_TRIGGER_RISING : INTERRUPT_TRIGGER_FALLING; return watch_invoke_interrupt_callback(button_id, trigger); } @@ -150,23 +150,23 @@ void watch_disable_external_interrupts(void) { external_interrupt_enabled = false; } -static EM_BOOL watch_invoke_interrupt_callback(const uint8_t button_id, watch_interrupt_trigger event) { - ext_irq_cb_t callback; - watch_interrupt_trigger trigger; +static EM_BOOL watch_invoke_interrupt_callback(const uint8_t button_id, eic_interrupt_trigger_t event) { + watch_cb_t callback; + eic_interrupt_trigger_t trigger; uint8_t pin; switch (button_id) { case BTN_ID_MODE: - pin = BTN_MODE; + pin = HAL_GPIO_BTN_MODE_pin(); callback = external_interrupt_mode_callback; trigger = external_interrupt_mode_trigger; break; case BTN_ID_LIGHT: - pin = BTN_LIGHT; + pin = HAL_GPIO_BTN_LIGHT_pin(); callback = external_interrupt_light_callback; trigger = external_interrupt_light_trigger; break; case BTN_ID_ALARM: - pin = BTN_ALARM; + pin = HAL_GPIO_BTN_ALARM_pin(); callback = external_interrupt_alarm_callback; trigger = external_interrupt_alarm_trigger; break; @@ -195,14 +195,14 @@ static EM_BOOL watch_invoke_interrupt_callback(const uint8_t button_id, watch_in return EM_TRUE; } -void watch_register_interrupt_callback(const uint8_t pin, ext_irq_cb_t callback, watch_interrupt_trigger trigger) { - if (pin == BTN_MODE) { +void watch_register_interrupt_callback(const uint8_t pin, watch_cb_t callback, eic_interrupt_trigger_t trigger) { + if (pin == HAL_GPIO_BTN_MODE_pin()) { external_interrupt_mode_callback = callback; external_interrupt_mode_trigger = trigger; - } else if (pin == BTN_LIGHT) { + } else if (pin == HAL_GPIO_BTN_LIGHT_pin()) { external_interrupt_light_callback = callback; external_interrupt_light_trigger = trigger; - } else if (pin == BTN_ALARM) { + } else if (pin == HAL_GPIO_BTN_ALARM_pin()) { external_interrupt_alarm_callback = callback; external_interrupt_alarm_trigger = trigger; } diff --git a/watch-library/simulator/watch/watch_main_loop.h b/watch-library/simulator/watch/watch_main_loop.h index 7599f727..2b081a2d 100644 --- a/watch-library/simulator/watch/watch_main_loop.h +++ b/watch-library/simulator/watch/watch_main_loop.h @@ -22,8 +22,6 @@ * SOFTWARE. */ -#include "driver_init.h" - void suspend_main_loop(void); void resume_main_loop(void); diff --git a/watch-library/simulator/watch/watch_rtc.c b/watch-library/simulator/watch/watch_rtc.c index 3b244f24..852bf16e 100644 --- a/watch-library/simulator/watch/watch_rtc.c +++ b/watch-library/simulator/watch/watch_rtc.c @@ -34,10 +34,10 @@ static long tick_callbacks[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; static long alarm_interval_id = -1; static long alarm_timeout_id = -1; static double alarm_interval; -ext_irq_cb_t alarm_callback; -ext_irq_cb_t btn_alarm_callback; -ext_irq_cb_t a2_callback; -ext_irq_cb_t a4_callback; +watch_cb_t alarm_callback; +watch_cb_t btn_alarm_callback; +watch_cb_t a2_callback; +watch_cb_t a4_callback; bool _watch_rtc_is_enabled(void) { return true; @@ -73,7 +73,7 @@ watch_date_time_t watch_rtc_get_date_time(void) { return retval; } -void watch_rtc_register_tick_callback(ext_irq_cb_t callback) { +void watch_rtc_register_tick_callback(watch_cb_t callback) { watch_rtc_register_periodic_callback(callback, 1); } @@ -82,12 +82,12 @@ void watch_rtc_disable_tick_callback(void) { } static void watch_invoke_periodic_callback(void *userData) { - ext_irq_cb_t callback = userData; + watch_cb_t callback = userData; callback(); resume_main_loop(); } -void watch_rtc_register_periodic_callback(ext_irq_cb_t callback, uint8_t frequency) { +void watch_rtc_register_periodic_callback(watch_cb_t callback, uint8_t frequency) { // we told them, it has to be a power of 2. if (__builtin_popcount(frequency) != 1) return; @@ -134,7 +134,7 @@ static void watch_invoke_alarm_callback(void *userData) { alarm_interval_id = emscripten_set_interval(watch_invoke_alarm_interval_callback, alarm_interval, NULL); } -void watch_rtc_register_alarm_callback(ext_irq_cb_t callback, watch_date_time_t alarm_time, watch_rtc_alarm_match mask) { +void watch_rtc_register_alarm_callback(watch_cb_t callback, watch_date_time_t alarm_time, rtc_alarm_match_t mask) { watch_rtc_disable_alarm_callback(); switch (mask) { diff --git a/watch-library/simulator/watch/watch_slcd.c b/watch-library/simulator/watch/watch_slcd.c index b3e0f0ff..c248dcff 100644 --- a/watch-library/simulator/watch/watch_slcd.c +++ b/watch-library/simulator/watch/watch_slcd.c @@ -23,8 +23,7 @@ */ #include "watch_slcd.h" -#include "watch_private_display.h" -#include "hpl_slcd_config.h" +#include "watch_common_display.h" #include #include diff --git a/watch-library/simulator/watch/watch_tcc.c b/watch-library/simulator/watch/watch_tcc.c index 63c477b7..6cf7235c 100644 --- a/watch-library/simulator/watch/watch_tcc.c +++ b/watch-library/simulator/watch/watch_tcc.c @@ -22,8 +22,7 @@ * SOFTWARE. */ -#include "watch_buzzer.h" -#include "watch_private_buzzer.h" +#include "watch_tcc.h" #include "watch_main_loop.h" #include