Sensor Watch Simulator (#35)
* Put something on screen * Use the 32bit watch_date_time repr to pass from JS * Implement periodic callbacks * Clear display on enabling * Hook up watch_set_led_color() to SVG (green-only) * Make debug output full-width * Remove default Emscripten canvas * Implement sleep and button clicks * Fix time zone conversion bug in beats-time app * Clean up warnings * Fix pin levels * Set time zone to browser value (if available) * Add basic backup data saving * Silence format specifier warnings in both targets * Remove unnecessary, copied files * Use RTC pointer to clear callbacks (if available) * Use preprocessor define to avoid hardcoding MOVEMENT_NUM_FACES * Change each face to const preprocessor definition * Remove Intl.DateTimeFormat usage * Update shell.html title, header * Add touch start/end event handlers on SVG buttons * Update shell.html * Update folder structure (shared, simulator, hardware under watch-library) * Tease out shared components from watch_slcd * Clean up simulator watch_slcd.c inline JS calls * Fix missing newlines at end of file * Add simulator warnings (except format, unused-paremter) * Implement remaining watch_rtc functions * Fix button bug on mouse down then drag out * Implement remaining watch_slcd functions * Link keyboard events to buttons (for keys A, L, M) * Rewrite event handling (mouse, touch, keyboard) in C * Set explicit text UTF-8 charset in shell.html * Address PR comments * Remove unused directories from include paths
This commit is contained in:
9
watch-library/simulator/watch/watch.c
Normal file
9
watch-library/simulator/watch/watch.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "watch.h"
|
||||
|
||||
bool watch_is_battery_low(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool watch_is_buzzer_or_led_enabled(void) {
|
||||
return false;
|
||||
}
|
||||
48
watch-library/simulator/watch/watch_adc.c
Normal file
48
watch-library/simulator/watch/watch_adc.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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 "watch_adc.h"
|
||||
|
||||
void watch_enable_adc(void) {}
|
||||
|
||||
void watch_enable_analog_input(const uint8_t pin) {}
|
||||
|
||||
uint16_t watch_get_analog_pin_level(const uint8_t pin) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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) {}
|
||||
|
||||
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_adc(void) {}
|
||||
60
watch-library/simulator/watch/watch_buzzer.c
Normal file
60
watch-library/simulator/watch/watch_buzzer.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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 "watch_buzzer.h"
|
||||
|
||||
inline void watch_enable_buzzer(void) {
|
||||
// TODO: (a2) hook to UI
|
||||
}
|
||||
inline void watch_set_buzzer_period(uint32_t period) {
|
||||
// TODO: (a2) hook to UI
|
||||
}
|
||||
|
||||
void watch_disable_buzzer(void) {
|
||||
_watch_disable_tcc();
|
||||
}
|
||||
|
||||
inline void watch_set_buzzer_on(void) {
|
||||
// TODO: (a2) hook to UI
|
||||
}
|
||||
|
||||
inline void watch_set_buzzer_off(void) {
|
||||
// TODO: (a2) hook to UI
|
||||
}
|
||||
|
||||
// note: the buzzer uses a 1 MHz clock. these values were determined by dividing 1,000,000 by the target frequency.
|
||||
// i.e. for a 440 Hz tone (A4 on the piano), 1MHz/440Hz = 2273
|
||||
const uint16_t NotePeriods[108] = {0};
|
||||
|
||||
void watch_buzzer_play_note(BuzzerNote note, uint16_t duration_ms) {
|
||||
if (note == BUZZER_NOTE_REST) {
|
||||
watch_set_buzzer_off();
|
||||
} // else {
|
||||
// hri_tcc_write_PERBUF_reg(TCC0, NotePeriods[note]);
|
||||
// hri_tcc_write_CCBUF_reg(TCC0, WATCH_BUZZER_TCC_CHANNEL, NotePeriods[note] / 2);
|
||||
// watch_set_buzzer_on();
|
||||
// }
|
||||
// delay_ms(duration_ms);
|
||||
// watch_set_buzzer_off();
|
||||
}
|
||||
99
watch-library/simulator/watch/watch_deepsleep.c
Normal file
99
watch-library/simulator/watch/watch_deepsleep.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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 "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
|
||||
|
||||
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) {
|
||||
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) {
|
||||
watch_register_interrupt_callback(pin, NULL, INTERRUPT_TRIGGER_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void watch_store_backup_data(uint32_t data, uint8_t reg) {
|
||||
if (reg < 8) {
|
||||
watch_backup_data[reg] = data;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t watch_get_backup_data(uint8_t reg) {
|
||||
if (reg < 8) {
|
||||
return watch_backup_data[reg];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void watch_enter_sleep_mode(void) {
|
||||
// TODO: (a2) hook to UI
|
||||
|
||||
// enter standby (4); we basically hang out here until an interrupt wakes us.
|
||||
// sleep(4);
|
||||
|
||||
// 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) {
|
||||
// identical to sleep mode except we disable the LCD first.
|
||||
// TODO: (a2) hook to UI
|
||||
|
||||
watch_enter_sleep_mode();
|
||||
}
|
||||
|
||||
void watch_enter_backup_mode(void) {
|
||||
// TODO: (a2) hook to UI
|
||||
|
||||
// go into backup sleep mode (5). when we exit, the reset controller will take over.
|
||||
// sleep(5);
|
||||
}
|
||||
|
||||
// deprecated
|
||||
void watch_enter_shallow_sleep(bool display_on) {
|
||||
if (display_on) watch_enter_sleep_mode();
|
||||
else watch_enter_deep_sleep_mode();
|
||||
}
|
||||
|
||||
// deprecated
|
||||
void watch_enter_deep_sleep(void) {
|
||||
watch_register_extwake_callback(BTN_ALARM, NULL, true);
|
||||
watch_enter_backup_mode();
|
||||
}
|
||||
191
watch-library/simulator/watch/watch_extint.c
Normal file
191
watch-library/simulator/watch/watch_extint.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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 "watch_extint.h"
|
||||
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
static bool output_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;
|
||||
|
||||
#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 void watch_invoke_interrupt_callback(const uint8_t button_id, watch_interrupt_trigger trigger);
|
||||
|
||||
static EM_BOOL watch_invoke_key_callback(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) {
|
||||
if (output_focused || keyEvent->repeat) return EM_FALSE;
|
||||
|
||||
const char *key = keyEvent->key;
|
||||
if (key[1] != 0) return EM_FALSE;
|
||||
|
||||
uint8_t button_id;
|
||||
switch (key[0]) {
|
||||
case 'A':
|
||||
case 'a':
|
||||
button_id = BTN_ID_ALARM;
|
||||
break;
|
||||
case 'L':
|
||||
case 'l':
|
||||
button_id = BTN_ID_LIGHT;
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
button_id = BTN_ID_MODE;
|
||||
break;
|
||||
default:
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
watch_interrupt_trigger trigger = eventType == EMSCRIPTEN_EVENT_KEYDOWN ? INTERRUPT_TRIGGER_RISING : INTERRUPT_TRIGGER_FALLING;
|
||||
watch_invoke_interrupt_callback(button_id, trigger);
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
watch_invoke_interrupt_callback(button_id, trigger);
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
watch_invoke_interrupt_callback(button_id, trigger);
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
static EM_BOOL watch_invoke_focus_callback(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData) {
|
||||
output_focused = eventType == EMSCRIPTEN_EVENT_FOCUS;
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
static void watch_install_button_callbacks(void) {
|
||||
emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, watch_invoke_key_callback);
|
||||
emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, watch_invoke_key_callback);
|
||||
|
||||
const char *target_output = "#output";
|
||||
emscripten_set_focus_callback(target_output, NULL, EM_FALSE, watch_invoke_focus_callback);
|
||||
emscripten_set_blur_callback(target_output, NULL, EM_FALSE, watch_invoke_focus_callback);
|
||||
|
||||
for (int i = 0, count = sizeof(BTN_IDS) / sizeof(BTN_IDS[0]); i < count; i++) {
|
||||
char target[] = "#btn_";
|
||||
target[4] = BTN_IDS[i] + '0';
|
||||
|
||||
emscripten_set_mousedown_callback(target, (void *)&BTN_IDS[i], EM_FALSE, watch_invoke_mouse_callback);
|
||||
emscripten_set_mouseup_callback(target, (void *)&BTN_IDS[i], EM_FALSE, watch_invoke_mouse_callback);
|
||||
emscripten_set_mouseout_callback(target, (void *)&BTN_IDS[i], EM_FALSE, watch_invoke_mouse_callback);
|
||||
|
||||
emscripten_set_touchstart_callback(target, (void *)&BTN_IDS[i], EM_FALSE, watch_invoke_touch_callback);
|
||||
emscripten_set_touchend_callback(target, (void *)&BTN_IDS[i], EM_FALSE, watch_invoke_touch_callback);
|
||||
}
|
||||
}
|
||||
|
||||
void watch_enable_external_interrupts(void) {
|
||||
external_interrupt_enabled = true;
|
||||
|
||||
if (!button_callbacks_installed) {
|
||||
watch_install_button_callbacks();
|
||||
button_callbacks_installed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void watch_disable_external_interrupts(void) {
|
||||
external_interrupt_enabled = false;
|
||||
}
|
||||
|
||||
static void watch_invoke_interrupt_callback(const uint8_t button_id, watch_interrupt_trigger event) {
|
||||
if (!external_interrupt_enabled) return;
|
||||
|
||||
ext_irq_cb_t callback;
|
||||
watch_interrupt_trigger trigger;
|
||||
uint8_t pin;
|
||||
switch (button_id) {
|
||||
case BTN_ID_MODE:
|
||||
pin = BTN_MODE;
|
||||
callback = external_interrupt_mode_callback;
|
||||
trigger = external_interrupt_mode_trigger;
|
||||
break;
|
||||
case BTN_ID_LIGHT:
|
||||
pin = BTN_LIGHT;
|
||||
callback = external_interrupt_light_callback;
|
||||
trigger = external_interrupt_light_trigger;
|
||||
break;
|
||||
case BTN_ID_ALARM:
|
||||
pin = BTN_ALARM;
|
||||
callback = external_interrupt_alarm_callback;
|
||||
trigger = external_interrupt_alarm_trigger;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
const bool level = (event & INTERRUPT_TRIGGER_RISING) != 0;
|
||||
EM_ASM({
|
||||
const classList = document.querySelector('#btn' + $0).classList;
|
||||
const highlight = 'highlight';
|
||||
$1 ? classList.add(highlight) : classList.remove(highlight);
|
||||
}, button_id, level);
|
||||
|
||||
watch_set_pin_level(pin, level);
|
||||
|
||||
if (callback && (event & trigger) != 0) {
|
||||
callback();
|
||||
|
||||
void resume_main_loop(void);
|
||||
resume_main_loop();
|
||||
}
|
||||
}
|
||||
|
||||
void watch_register_interrupt_callback(const uint8_t pin, ext_irq_cb_t callback, watch_interrupt_trigger trigger) {
|
||||
if (pin == BTN_MODE) {
|
||||
external_interrupt_mode_callback = callback;
|
||||
external_interrupt_mode_trigger = trigger;
|
||||
} else if (pin == BTN_LIGHT) {
|
||||
external_interrupt_light_callback = callback;
|
||||
external_interrupt_light_trigger = trigger;
|
||||
} else if (pin == BTN_ALARM) {
|
||||
external_interrupt_alarm_callback = callback;
|
||||
external_interrupt_alarm_trigger = trigger;
|
||||
}
|
||||
}
|
||||
|
||||
void watch_register_button_callback(const uint8_t pin, ext_irq_cb_t callback) {
|
||||
watch_register_interrupt_callback(pin, callback, INTERRUPT_TRIGGER_RISING);
|
||||
}
|
||||
|
||||
void watch_enable_buttons(void) {
|
||||
watch_enable_external_interrupts();
|
||||
}
|
||||
47
watch-library/simulator/watch/watch_gpio.c
Normal file
47
watch-library/simulator/watch/watch_gpio.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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 "watch_gpio.h"
|
||||
|
||||
static bool pin_levels[UINT8_MAX];
|
||||
|
||||
void watch_enable_digital_input(const uint8_t pin) {}
|
||||
|
||||
void watch_disable_digital_input(const uint8_t pin) {}
|
||||
|
||||
void watch_enable_pull_up(const uint8_t pin) {}
|
||||
|
||||
void watch_enable_pull_down(const uint8_t pin) {}
|
||||
|
||||
bool watch_get_pin_level(const uint8_t pin) {
|
||||
return pin_levels[pin];
|
||||
}
|
||||
|
||||
void watch_enable_digital_output(const uint8_t pin) {}
|
||||
|
||||
void watch_disable_digital_output(const uint8_t pin) {}
|
||||
|
||||
void watch_set_pin_level(const uint8_t pin, const bool level) {
|
||||
pin_levels[pin] = level;
|
||||
}
|
||||
51
watch-library/simulator/watch/watch_i2c.c
Normal file
51
watch-library/simulator/watch/watch_i2c.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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 "watch_i2c.h"
|
||||
|
||||
void watch_enable_i2c(void) {}
|
||||
|
||||
void watch_disable_i2c(void) {}
|
||||
|
||||
void watch_i2c_send(int16_t addr, uint8_t *buf, uint16_t length) {}
|
||||
|
||||
void watch_i2c_receive(int16_t addr, uint8_t *buf, uint16_t length) {}
|
||||
|
||||
void watch_i2c_write8(int16_t addr, uint8_t reg, uint8_t data) {}
|
||||
|
||||
uint8_t watch_i2c_read8(int16_t addr, uint8_t reg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t watch_i2c_read16(int16_t addr, uint8_t reg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t watch_i2c_read24(int16_t addr, uint8_t reg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t watch_i2c_read32(int16_t addr, uint8_t reg) {
|
||||
return 0;
|
||||
}
|
||||
63
watch-library/simulator/watch/watch_led.c
Normal file
63
watch-library/simulator/watch/watch_led.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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 "watch_led.h"
|
||||
|
||||
#include <emscripten.h>
|
||||
|
||||
void watch_enable_leds(void) {}
|
||||
|
||||
void watch_disable_leds(void) {}
|
||||
|
||||
void watch_enable_led(bool unused) {
|
||||
(void)unused;
|
||||
watch_enable_leds();
|
||||
}
|
||||
|
||||
void watch_disable_led(bool unused) {
|
||||
(void)unused;
|
||||
watch_disable_leds();
|
||||
}
|
||||
|
||||
void watch_set_led_color(uint8_t red, uint8_t green) {
|
||||
EM_ASM({
|
||||
document.getElementById('light').style.opacity = $1 / 255;
|
||||
}, red, green);
|
||||
}
|
||||
|
||||
void watch_set_led_red(void) {
|
||||
watch_set_led_color(255, 0);
|
||||
}
|
||||
|
||||
void watch_set_led_green(void) {
|
||||
watch_set_led_color(0, 255);
|
||||
}
|
||||
|
||||
void watch_set_led_yellow(void) {
|
||||
watch_set_led_color(255, 255);
|
||||
}
|
||||
|
||||
void watch_set_led_off(void) {
|
||||
watch_set_led_color(0, 0);
|
||||
}
|
||||
78
watch-library/simulator/watch/watch_private.c
Normal file
78
watch-library/simulator/watch/watch_private.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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 "watch_private.h"
|
||||
#include "watch_utility.h"
|
||||
#include <sys/time.h>
|
||||
|
||||
void _watch_init(void) {
|
||||
// External wake depends on RTC; calendar is a required module.
|
||||
_watch_rtc_init();
|
||||
}
|
||||
|
||||
// this function is called by arc4random to get entropy for random number generation.
|
||||
// let's use the SAM L22's true random number generator to seed the PRNG!
|
||||
int getentropy(void *buf, size_t buflen);
|
||||
int getentropy(void *buf, size_t buflen) {
|
||||
// TODO: (a2) hook to RNG
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _gettimeofday(struct timeval *tv, void *tzvp);
|
||||
int _gettimeofday(struct timeval *tv, void *tzvp) {
|
||||
(void)tzvp;
|
||||
watch_date_time date_time = watch_rtc_get_date_time();
|
||||
|
||||
// FIXME: this assumes the system time is UTC! Will break for any other time zone.
|
||||
tv->tv_sec = watch_utility_date_time_to_unix_time(date_time, 0);
|
||||
tv->tv_usec = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _watch_enable_tcc(void) {}
|
||||
|
||||
void _watch_disable_tcc(void) {}
|
||||
|
||||
void _watch_enable_usb(void) {}
|
||||
|
||||
// this function ends up getting called by printf to log stuff to the USB console.
|
||||
int _write(int file, char *ptr, int len) {
|
||||
// TODO: (a2) hook to UI
|
||||
return 0;
|
||||
}
|
||||
|
||||
// this method could be overridden to read stuff from the USB console? but no need rn.
|
||||
int _read(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Alternate function that outputs to the debug UART. useful for debugging USB issues.
|
||||
// int _write(int file, char *ptr, int len) {
|
||||
// (void)file;
|
||||
// int pos = 0;
|
||||
// while(pos < len) watch_debug_putc(ptr[pos++]);
|
||||
|
||||
// return 0;
|
||||
// }
|
||||
223
watch-library/simulator/watch/watch_rtc.c
Normal file
223
watch-library/simulator/watch/watch_rtc.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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 "watch_rtc.h"
|
||||
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
static double time_offset = 0;
|
||||
static long tick_callbacks[8];
|
||||
|
||||
static long alarm_interval_id;
|
||||
static long alarm_timeout_id;
|
||||
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;
|
||||
|
||||
bool _watch_rtc_is_enabled(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void _watch_rtc_init(void) {
|
||||
}
|
||||
|
||||
void watch_rtc_set_date_time(watch_date_time date_time) {
|
||||
time_offset = EM_ASM_DOUBLE({
|
||||
const year = 2020 + (($0 >> 26) & 0x3f);
|
||||
const month = ($0 >> 22) & 0xf;
|
||||
const day = ($0 >> 17) & 0x1f;
|
||||
const hour = ($0 >> 12) & 0x1f;
|
||||
const minute = ($0 >> 6) & 0x3f;
|
||||
const second = $0 & 0x3f;
|
||||
const date = new Date(year, month - 1, day, hour, minute, second);
|
||||
return date - Date.now();
|
||||
}, date_time.reg);
|
||||
}
|
||||
|
||||
watch_date_time watch_rtc_get_date_time(void) {
|
||||
watch_date_time retval;
|
||||
retval.reg = EM_ASM_INT({
|
||||
const date = new Date(Date.now() + $0);
|
||||
return date.getSeconds() |
|
||||
(date.getMinutes() << 6) |
|
||||
(date.getHours() << 12) |
|
||||
(date.getDate() << 17) |
|
||||
((date.getMonth() + 1) << 22) |
|
||||
((date.getFullYear() - 2020) << 26);
|
||||
}, time_offset);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void watch_rtc_register_tick_callback(ext_irq_cb_t callback) {
|
||||
watch_rtc_register_periodic_callback(callback, 1);
|
||||
}
|
||||
|
||||
void watch_rtc_disable_tick_callback(void) {
|
||||
watch_rtc_disable_periodic_callback(1);
|
||||
}
|
||||
|
||||
static void watch_invoke_periodic_callback(void *userData) {
|
||||
ext_irq_cb_t callback = userData;
|
||||
callback();
|
||||
|
||||
void resume_main_loop(void);
|
||||
resume_main_loop();
|
||||
}
|
||||
|
||||
void watch_rtc_register_periodic_callback(ext_irq_cb_t callback, uint8_t frequency) {
|
||||
// we told them, it has to be a power of 2.
|
||||
if (__builtin_popcount(frequency) != 1) return;
|
||||
|
||||
// this left-justifies the period in a 32-bit integer.
|
||||
uint32_t tmp = frequency << 24;
|
||||
// now we can count the leading zeroes to get the value we need.
|
||||
// 0x01 (1 Hz) will have 7 leading zeros for PER7. 0xF0 (128 Hz) will have no leading zeroes for PER0.
|
||||
uint8_t per_n = __builtin_clz(tmp);
|
||||
|
||||
// this also maps nicely to an index for our list of tick callbacks.
|
||||
double interval = 1000 / frequency; // in msec
|
||||
tick_callbacks[per_n] = emscripten_set_interval(watch_invoke_periodic_callback, interval, (void *)callback);
|
||||
}
|
||||
|
||||
void watch_rtc_disable_periodic_callback(uint8_t frequency) {
|
||||
if (__builtin_popcount(frequency) != 1) return;
|
||||
uint8_t per_n = __builtin_clz(frequency << 24);
|
||||
emscripten_clear_interval(tick_callbacks[per_n]);
|
||||
tick_callbacks[per_n] = 0;
|
||||
}
|
||||
|
||||
void watch_rtc_disable_all_periodic_callbacks(void) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (tick_callbacks[i] != 0) {
|
||||
emscripten_clear_interval(tick_callbacks[i]);
|
||||
tick_callbacks[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void watch_invoke_alarm_interval_callback(void *userData) {
|
||||
(void)userData;
|
||||
if (alarm_callback) alarm_callback();
|
||||
}
|
||||
|
||||
static void watch_invoke_alarm_callback(void *userData) {
|
||||
(void)userData;
|
||||
if (alarm_callback) alarm_callback();
|
||||
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 alarm_time, watch_rtc_alarm_match mask) {
|
||||
watch_rtc_disable_alarm_callback();
|
||||
|
||||
switch (mask) {
|
||||
case ALARM_MATCH_DISABLED:
|
||||
return;
|
||||
case ALARM_MATCH_SS:
|
||||
alarm_interval = 60 * 1000;
|
||||
break;
|
||||
case ALARM_MATCH_MMSS:
|
||||
alarm_interval = 60 * 60 * 1000;
|
||||
break;
|
||||
case ALARM_MATCH_HHMMSS:
|
||||
alarm_interval = 60 * 60 * 60 * 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
double timeout = EM_ASM_DOUBLE({
|
||||
const now = Date.now();
|
||||
const date = new Date(now + $0);
|
||||
|
||||
const hour = ($1 >> 12) & 0x1f;
|
||||
const minute = ($1 >> 6) & 0x3f;
|
||||
const second = $1 & 0x3f;
|
||||
|
||||
if ($2 == 1) { // SS
|
||||
if (second < date.getSeconds()) date.setMinutes(date.getMinutes() + 1);
|
||||
date.setSeconds(second);
|
||||
} else if ($2 == 2) { // MMSS
|
||||
if (second < date.getSeconds()) date.setMinutes(date.getMinutes() + 1);
|
||||
if (minute < date.getMinutes()) date.setHours(date.getHours() + 1);
|
||||
date.setMinutes(minute, second);
|
||||
} else if ($2 == 3) { // HHMMSS
|
||||
if (second < date.getSeconds()) date.setMinutes(date.getMinutes() + 1);
|
||||
if (minute < date.getMinutes()) date.setHours(date.getHours() + 1);
|
||||
if (hour < date.getHours()) date.setDate(date.getDate() + 1);
|
||||
date.setHours(hour, minute, second);
|
||||
} else {
|
||||
throw 'Invalid alarm match mask';
|
||||
}
|
||||
|
||||
return date - now;
|
||||
}, time_offset, alarm_time.reg, mask);
|
||||
|
||||
alarm_callback = callback;
|
||||
alarm_timeout_id = emscripten_set_timeout(watch_invoke_alarm_callback, timeout, NULL);
|
||||
}
|
||||
|
||||
void watch_rtc_disable_alarm_callback(void) {
|
||||
alarm_callback = NULL;
|
||||
alarm_interval = 0;
|
||||
|
||||
if (alarm_timeout_id) {
|
||||
emscripten_clear_timeout(alarm_timeout_id);
|
||||
alarm_timeout_id = 0;
|
||||
}
|
||||
|
||||
if (alarm_interval_id) {
|
||||
emscripten_clear_interval(alarm_interval_id);
|
||||
alarm_interval_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
// Deprecated functions
|
||||
|
||||
void watch_set_date_time(struct calendar_date_time date_time) {
|
||||
watch_date_time val;
|
||||
val.unit.second = date_time.time.sec;
|
||||
val.unit.minute = date_time.time.min;
|
||||
val.unit.hour = date_time.time.hour;
|
||||
val.unit.day = date_time.date.day;
|
||||
val.unit.month = date_time.date.month;
|
||||
val.unit.year = date_time.date.year - WATCH_RTC_REFERENCE_YEAR;
|
||||
watch_rtc_set_date_time(val);
|
||||
}
|
||||
|
||||
void watch_get_date_time(struct calendar_date_time *date_time) {
|
||||
if (date_time == NULL) return;
|
||||
watch_date_time val = watch_rtc_get_date_time();
|
||||
date_time->time.sec = val.unit.second;
|
||||
date_time->time.min = val.unit.minute;
|
||||
date_time->time.hour = val.unit.hour;
|
||||
date_time->date.day = val.unit.day;
|
||||
date_time->date.month = val.unit.month;
|
||||
date_time->date.year = val.unit.year + WATCH_RTC_REFERENCE_YEAR;
|
||||
}
|
||||
|
||||
void watch_register_tick_callback(ext_irq_cb_t callback) {
|
||||
watch_rtc_register_tick_callback(callback);
|
||||
}
|
||||
115
watch-library/simulator/watch/watch_slcd.c
Normal file
115
watch-library/simulator/watch/watch_slcd.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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 "watch_slcd.h"
|
||||
#include "watch_private_display.h"
|
||||
#include "hpl_slcd_config.h"
|
||||
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Segmented Display
|
||||
|
||||
static char blink_character;
|
||||
static bool blink_state;
|
||||
static long blink_interval_id;
|
||||
static bool tick_state;
|
||||
static long tick_interval_id;
|
||||
|
||||
void watch_enable_display(void) {
|
||||
watch_clear_display();
|
||||
}
|
||||
|
||||
void watch_set_pixel(uint8_t com, uint8_t seg) {
|
||||
EM_ASM({
|
||||
document.querySelectorAll("[data-com='" + $0 + "'][data-seg='" + $1 + "']")
|
||||
.forEach((e) => e.style.opacity = 1);
|
||||
}, com, seg);
|
||||
}
|
||||
|
||||
void watch_clear_pixel(uint8_t com, uint8_t seg) {
|
||||
EM_ASM({
|
||||
document.querySelectorAll("[data-com='" + $0 + "'][data-seg='" + $1 + "']")
|
||||
.forEach((e) => e.style.opacity = 0);
|
||||
}, com, seg);
|
||||
}
|
||||
|
||||
void watch_clear_display(void) {
|
||||
EM_ASM({
|
||||
document.querySelectorAll("[data-com][data-seg]")
|
||||
.forEach((e) => e.style.opacity = 0);
|
||||
});
|
||||
}
|
||||
|
||||
static void watch_invoke_blink_callback(void *userData) {
|
||||
blink_state = !blink_state;
|
||||
watch_display_character(blink_state ? blink_character : ' ', 7);
|
||||
watch_clear_pixel(2, 10); // clear segment B of position 7 since it can't blink
|
||||
}
|
||||
|
||||
void watch_start_character_blink(char character, uint32_t duration) {
|
||||
watch_display_character(character, 7);
|
||||
watch_clear_pixel(2, 10); // clear segment B of position 7 since it can't blink
|
||||
|
||||
blink_state = true;
|
||||
blink_character = character;
|
||||
blink_interval_id = emscripten_set_interval(watch_invoke_blink_callback, (double)duration, NULL);
|
||||
}
|
||||
|
||||
void watch_stop_blink(void) {
|
||||
emscripten_clear_timeout(blink_interval_id);
|
||||
blink_interval_id = 0;
|
||||
blink_state = false;
|
||||
}
|
||||
|
||||
static void watch_invoke_tick_callback(void *userData) {
|
||||
tick_state = !tick_state;
|
||||
if (tick_state) {
|
||||
watch_clear_pixel(0, 2);
|
||||
watch_set_pixel(0, 3);
|
||||
} else {
|
||||
watch_clear_pixel(0, 3);
|
||||
watch_set_pixel(0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void watch_start_tick_animation(uint32_t duration) {
|
||||
watch_display_character(' ', 8);
|
||||
|
||||
tick_state = true;
|
||||
tick_interval_id = emscripten_set_interval(watch_invoke_tick_callback, (double)duration, NULL);
|
||||
}
|
||||
|
||||
bool watch_tick_animation_is_running(void) {
|
||||
return tick_interval_id != 0;
|
||||
}
|
||||
|
||||
void watch_stop_tick_animation(void) {
|
||||
emscripten_clear_timeout(tick_interval_id);
|
||||
tick_interval_id = 0;
|
||||
tick_state = false;
|
||||
|
||||
watch_display_character(' ', 8);
|
||||
}
|
||||
65
watch-library/simulator/watch/watch_uart.c
Normal file
65
watch-library/simulator/watch/watch_uart.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* UART methods are Copyright (c) 2014-2017, Alex Taradov <alex@taradov.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "watch_uart.h"
|
||||
#include "peripheral_clk_config.h"
|
||||
|
||||
void watch_enable_debug_uart(uint32_t baud) {}
|
||||
|
||||
void watch_debug_putc(char c) {}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
void watch_debug_puts(char *s) {
|
||||
while (*s) watch_debug_putc(*s++);
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
Reference in New Issue
Block a user