]> git.earman.xyz Git - sensor-watch.git/commitdiff
initial pass at simulator support
authorjoeycastillo <joeycastillo@utexas.edu>
Sun, 6 Oct 2024 21:14:46 +0000 (17:14 -0400)
committerjoeycastillo <joeycastillo@utexas.edu>
Sun, 6 Oct 2024 21:14:46 +0000 (17:14 -0400)
Makefile
movement.c
shell/shell.c
watch-library/simulator/main.c [deleted file]
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_main_loop.h
watch-library/simulator/watch/watch_rtc.c
watch-library/simulator/watch/watch_slcd.c
watch-library/simulator/watch/watch_tcc.c

index ab894cec962d2a60e1df637778758bd2fe209b75..911b025c90dc304dcb0582c9a872bb914175da91 100644 (file)
--- 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 += \
index e661462076ad90254ab963599d1bc737e64ced26..ee8f6cc6b14a8b1d23eb535503d1f66a45308215 100644 (file)
@@ -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 <emscripten.h>
+#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
 }
 
index c028ed23c96e0015aed28981b3d06c9ee491dea6..b145c87ef3b709560bd5bb9ec1c866a508671d87 100644 (file)
 
 #if __EMSCRIPTEN__
 #include <emscripten.h>
+
+#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 (file)
index 5e5070f..0000000
+++ /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 <stdio.h>
-#include "watch.h"
-#include "watch_main_loop.h"
-
-#include <emscripten.h>
-#include <emscripten/html5.h>
-
-#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;
-}
index b03d68cb7c814abbe7263fd668be940a47cdcf32..c83dc3ed6d0f3670788f05f8e934577fcbd9534d 100644 (file)
@@ -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) {}
index 5add05e80c50486be143809f686f5e82804356e1..1bc4be7392739b570d5ff2239af40cc6938f7730 100644 (file)
  * SOFTWARE.
  */
 
+#include <stddef.h>
 #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) {
index b5894b9579dcae71f45673c527eba8cd28366b9d..4c0dc7c02d9749b9984957f526c7eaf74119de36 100644 (file)
 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;
     }
index 7599f7275541d289674de1f4a20b7992eb23fd07..2b081a2d4aae0c5cb9fe93cddb652fe9a0cde2bd 100644 (file)
@@ -22,8 +22,6 @@
  * SOFTWARE.
  */
 
-#include "driver_init.h"
-
 void suspend_main_loop(void);
 
 void resume_main_loop(void);
index 3b244f2418bc89b18bbaf57015040c299bed6928..852bf16eb76b2a93b23af4e78ee16dd46702eddf 100644 (file)
@@ -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) {
index b3e0f0ff553117ec8e3d0582de660df88daba227..c248dcffe121396a67c96bef051d048f27ff5321 100644 (file)
@@ -23,8 +23,7 @@
  */
 
 #include "watch_slcd.h"
-#include "watch_private_display.h"
-#include "hpl_slcd_config.h"
+#include "watch_common_display.h"
 
 #include <emscripten.h>
 #include <emscripten/html5.h>
index 63c477b71a7f49bf1b3b55000133d0af8989d4b7..6cf7235c9e3c27392fed1339f08e276c430ed9ef 100644 (file)
@@ -22,8 +22,7 @@
  * SOFTWARE.
  */
 
-#include "watch_buzzer.h"
-#include "watch_private_buzzer.h"
+#include "watch_tcc.h"
 #include "watch_main_loop.h"
 
 #include <emscripten.h>