diff options
Diffstat (limited to 'watch-library/simulator/watch/watch_buzzer.c')
-rw-r--r-- | watch-library/simulator/watch/watch_buzzer.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/watch-library/simulator/watch/watch_buzzer.c b/watch-library/simulator/watch/watch_buzzer.c index 1c95a96d..68d9a139 100644 --- a/watch-library/simulator/watch/watch_buzzer.c +++ b/watch-library/simulator/watch/watch_buzzer.c @@ -26,10 +26,86 @@ #include "watch_main_loop.h" #include <emscripten.h> +#include <emscripten/html5.h> static bool buzzer_enabled = false; static uint32_t buzzer_period; +void cb_watch_buzzer_seq(void *userData); + +static uint16_t _seq_position; +static int8_t _tone_ticks, _repeat_counter; +static long _em_interval_id = 0; +static int8_t *_sequence; +static void (*_cb_finished)(void); + +static inline void _em_interval_stop() { + emscripten_clear_interval(_em_interval_id); + _em_interval_id = 0; +} + +void watch_buzzer_play_sequence(int8_t *note_sequence, void (*callback_on_end)(void)) { + if (_em_interval_id) _em_interval_stop(); + watch_set_buzzer_off(); + _sequence = note_sequence; + _cb_finished = callback_on_end; + _seq_position = 0; + _tone_ticks = 0; + _repeat_counter = -1; + // prepare buzzer + watch_enable_buzzer(); + // initiate 64 hz callback + _em_interval_id = emscripten_set_interval(cb_watch_buzzer_seq, (double)(1000/64), (void *)NULL); +} + +void cb_watch_buzzer_seq(void *userData) { + // callback for reading the note sequence + (void) userData; + if (_tone_ticks == 0) { + if (_sequence[_seq_position] < 0 && _sequence[_seq_position + 1]) { + // repeat indicator found + if (_repeat_counter == -1) { + // first encounter: load repeat counter + _repeat_counter = _sequence[_seq_position + 1]; + } else _repeat_counter--; + if (_repeat_counter > 0) + // rewind + if (_seq_position > _sequence[_seq_position] * -2) + _seq_position += _sequence[_seq_position] * 2; + else + _seq_position = 0; + else { + // continue + _seq_position += 2; + _repeat_counter = -1; + } + } + if (_sequence[_seq_position] && _sequence[_seq_position + 1]) { + // read note + BuzzerNote note = _sequence[_seq_position]; + if (note == BUZZER_NOTE_REST) { + watch_set_buzzer_off(); + } else { + watch_set_buzzer_period(NotePeriods[note]); + watch_set_buzzer_on(); + } + // set duration ticks and move to next tone + _tone_ticks = _sequence[_seq_position + 1]; + _seq_position += 2; + } else { + // end the sequence + watch_buzzer_abort_sequence(); + if (_cb_finished) _cb_finished(); + } + } else _tone_ticks--; +} + +void watch_buzzer_abort_sequence(void) { + // ends/aborts the sequence + if (_em_interval_id) _em_interval_stop(); + watch_set_buzzer_off(); +} + void watch_enable_buzzer(void) { buzzer_enabled = true; buzzer_period = NotePeriods[BUZZER_NOTE_A4]; |