]> git.earman.xyz Git - sensor-watch.git/commitdiff
Added Timeout; Ability to turn off LED and Sound; Added doublespeed mode. (#1)
authorvoloved <36523934+voloved@users.noreply.github.com>
Sun, 7 Jul 2024 23:23:31 +0000 (19:23 -0400)
committerGitHub <noreply@github.com>
Sun, 7 Jul 2024 23:23:31 +0000 (19:23 -0400)
* Check that color is valid

Instead of merely checking that COLOR is set, check that it is one of
RED, BLUE or GREEN

* Added ability to turn off sound and timer with modes

* Added enum for mode

---------

Co-authored-by: Wesley Ellis <tahnok@gmail.com>
make.mk
movement/watch_faces/complication/simon_face.c
movement/watch_faces/complication/simon_face.h

diff --git a/make.mk b/make.mk
index bb2d153775e02321429eca20760552a6064f5e11..00933d08af53c3e09a4c7b4511e2523e24146a2d 100644 (file)
--- a/make.mk
+++ b/make.mk
@@ -213,6 +213,12 @@ 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
index 99fc16017ea022acca33e7f534cb9a4803cd031d..eb08f17ae218274dcff8e926c1ed0083eb350de0 100644 (file)
 #endif
 
 static char _simon_display_buf[12];
+static uint8_t _timer;
+static uint16_t _delay_beep;
+static uint16_t _timeout;
+static uint8_t _secSub;
 
 static inline uint8_t _simon_get_rand_num(uint8_t num_values) {
 #if __EMSCRIPTEN__
@@ -55,7 +59,26 @@ static void _simon_not_playing_display(simon_state_t *state) {
     _simon_clear_display(state);
 
     sprintf(_simon_display_buf, "SI  %d", state->best_score);
+    if (!state->soundOff)
+        watch_set_indicator(WATCH_INDICATOR_BELL);
+    else
+        watch_clear_indicator(WATCH_INDICATOR_BELL);
+    if (!state->lightOff)
+        watch_set_indicator(WATCH_INDICATOR_SIGNAL);
+    else
+        watch_clear_indicator(WATCH_INDICATOR_SIGNAL);
     watch_display_string(_simon_display_buf, 0);
+    switch (state->mode)
+    {
+    case SIMON_MODE_EASY:
+        watch_display_string("E", 9);
+        break;
+    case SIMON_MODE_HARD:
+        watch_display_string("H", 9);
+        break;
+    default:
+        break;
+    }
 }
 
 static void _simon_reset(simon_state_t *state) {
@@ -91,19 +114,31 @@ static void _simon_play_note(SimonNote note, simon_state_t *state, bool skip_res
     _simon_display_note(note, state);
     switch (note) {
         case SIMON_LED_NOTE:
-            watch_set_led_yellow();
-            watch_buzzer_play_note(BUZZER_NOTE_D3, 300);
+            if (!state->lightOff) watch_set_led_yellow();
+            if (state->soundOff)
+                delay_ms(_delay_beep);
+            else
+                watch_buzzer_play_note(BUZZER_NOTE_D3, _delay_beep);
             break;
         case SIMON_MODE_NOTE:
-            watch_set_led_red();
-            watch_buzzer_play_note(BUZZER_NOTE_E4, 300);
+            if (!state->lightOff) watch_set_led_red();
+            if (state->soundOff)
+                delay_ms(_delay_beep);
+            else
+               watch_buzzer_play_note(BUZZER_NOTE_E4, _delay_beep);
             break;
         case SIMON_ALARM_NOTE:
-            watch_set_led_green();
-            watch_buzzer_play_note(BUZZER_NOTE_C3, 300);
+            if (!state->lightOff) watch_set_led_green();
+            if (state->soundOff)
+                delay_ms(_delay_beep);
+            else
+               watch_buzzer_play_note(BUZZER_NOTE_C3, _delay_beep);
             break;
         case SIMON_WRONG_NOTE:
-            watch_buzzer_play_note(BUZZER_NOTE_A1, 800);
+            if (state->soundOff)
+                delay_ms(800);
+            else
+               watch_buzzer_play_note(BUZZER_NOTE_A1, 800);
             break;
     }
     watch_set_led_off();
@@ -111,7 +146,7 @@ static void _simon_play_note(SimonNote note, simon_state_t *state, bool skip_res
     if (note != SIMON_WRONG_NOTE) {
         _simon_clear_display(state);
         if (!skip_rest) {
-            watch_buzzer_play_note(BUZZER_NOTE_REST, 200);
+            watch_buzzer_play_note(BUZZER_NOTE_REST, (_delay_beep * 2)/3);
         }
     }
 }
@@ -134,6 +169,7 @@ static void _simon_listen(SimonNote note, simon_state_t *state) {
     if (state->sequence[state->listen_index] == note) {
         _simon_play_note(note, state, true);
         state->listen_index++;
+        _timer = 0;
 
         if (state->listen_index == state->sequence_length) {
             state->playing_state = SIMON_READY_FOR_NEXT_NOTE;
@@ -149,6 +185,22 @@ static void _simon_begin_listening(simon_state_t *state) {
     state->listen_index = 0;
 }
 
+static void _simon_change_speed(simon_state_t *state){
+      switch (state->mode)
+  {
+  case SIMON_MODE_HARD:
+        _delay_beep = DELAY_FOR_TONE_MS / 2;
+        _secSub = SIMON_FACE_FREQUENCY / 2;
+        _timeout = (TIMER_MAX * SIMON_FACE_FREQUENCY) / 2;
+    break;
+  default:
+        _delay_beep = DELAY_FOR_TONE_MS;
+        _secSub = SIMON_FACE_FREQUENCY;
+        _timeout = TIMER_MAX * SIMON_FACE_FREQUENCY;
+    break;
+  }
+}
+
 void simon_face_setup(movement_settings_t *settings, uint8_t watch_face_index,
         void **context_ptr) {
     (void)settings;
@@ -171,6 +223,10 @@ void simon_face_setup(movement_settings_t *settings, uint8_t watch_face_index,
 void simon_face_activate(movement_settings_t *settings, void *context) {
   (void) settings;
   (void) context;
+  simon_state_t *state = (simon_state_t *)context;
+  _simon_change_speed(state);
+  movement_request_tick_frequency(SIMON_FACE_FREQUENCY);
+   _timer = 0;
 }
 
 bool simon_face_loop(movement_event_t event, movement_settings_t *settings,
@@ -183,9 +239,16 @@ bool simon_face_loop(movement_event_t event, movement_settings_t *settings,
             _simon_reset(state);
             break;
         case EVENT_TICK:
-            if (state->playing_state == SIMON_READY_FOR_NEXT_NOTE) {
-                _simon_setup_next_note(state);
-            } else if (state->playing_state == SIMON_TEACHING) {
+            if (state->playing_state == SIMON_LISTENING_BACK && state->mode != SIMON_MODE_EASY)
+            {
+                _timer++;
+                if(_timer >= (_timeout)){
+                    _timer = 0;
+                    _simon_play_note(SIMON_WRONG_NOTE, state, true);
+                    _simon_reset(state);
+                }
+            }
+            else if (state->playing_state == SIMON_TEACHING && event.subsecond  == 0) {
                 SimonNote note = state->sequence[state->teaching_index];
                 // if this is the final note in the sequence, don't play the rest to let
                 // the player jump in faster
@@ -196,12 +259,32 @@ bool simon_face_loop(movement_event_t event, movement_settings_t *settings,
                     _simon_begin_listening(state);
                 }
             }
+            else if (state->playing_state == SIMON_READY_FOR_NEXT_NOTE && (event.subsecond % _secSub)  == 0) {
+                _timer = 0;
+                _simon_setup_next_note(state);
+            }
             break;
         case EVENT_LIGHT_BUTTON_DOWN:
             break;
+        case EVENT_LIGHT_LONG_PRESS:
+            if (state->playing_state == SIMON_NOT_PLAYING) {
+                state->lightOff = !state->lightOff;
+                _simon_not_playing_display(state);
+            }
+            break;
+        case EVENT_ALARM_LONG_PRESS:
+            if (state->playing_state == SIMON_NOT_PLAYING) {
+                state->soundOff = !state->soundOff;
+                _simon_not_playing_display(state);
+                if (!state->soundOff)
+                    watch_buzzer_play_note(BUZZER_NOTE_D3, _delay_beep);
+            }
+            break;
         case EVENT_LIGHT_BUTTON_UP:
             if (state->playing_state == SIMON_NOT_PLAYING) {
                 state->sequence_length = 0;
+                watch_clear_indicator(WATCH_INDICATOR_BELL);
+                watch_clear_indicator(WATCH_INDICATOR_SIGNAL);
                 _simon_setup_next_note(state);
             } else if (state->playing_state == SIMON_LISTENING_BACK) {
                 _simon_listen(SIMON_LED_NOTE, state);
@@ -226,6 +309,11 @@ bool simon_face_loop(movement_event_t event, movement_settings_t *settings,
             if (state->playing_state == SIMON_LISTENING_BACK) {
                 _simon_listen(SIMON_ALARM_NOTE, state);
             }
+            else if (state->playing_state == SIMON_NOT_PLAYING){
+                state->mode = (state->mode + 1) % SIMON_MODE_TOTAL;
+                _simon_change_speed(state);
+                _simon_not_playing_display(state);
+            }
             break;
         case EVENT_TIMEOUT:
             movement_move_to_face(0);
index b59d56c57c90a98873ad6ab7a6280e4b0960008e..44bc9f3c53c8723b31ab7f415783f4f787c1236a 100644 (file)
@@ -71,12 +71,22 @@ typedef enum SimonPlayingState {
     SIMON_READY_FOR_NEXT_NOTE
 } SimonPlayingState;
 
+typedef enum SimonMode {
+    SIMON_MODE_NORMAL = 0,  // 5 Second timeout if nothing is input
+    SIMON_MODE_EASY,  // There is no timeout in this mode
+    SIMON_MODE_HARD,  // The speed of the teaching is doubled and th etimeout is halved
+    SIMON_MODE_TOTAL
+} SimonMode;
+
 typedef struct {
     uint8_t best_score;
     SimonNote sequence[MAX_SEQUENCE];
     uint8_t sequence_length;
     uint8_t teaching_index;
     uint8_t listen_index;
+    bool soundOff;
+    bool lightOff;
+    uint8_t mode:6;
     SimonPlayingState playing_state;
 } simon_state_t;
 
@@ -94,4 +104,8 @@ void simon_face_resign(movement_settings_t *settings, void *context);
      NULL,                                                                    \
      })
 
+#define TIMER_MAX 5
+#define SIMON_FACE_FREQUENCY 8
+#define DELAY_FOR_TONE_MS 300
+
 #endif // SIMON_FACE_H_