]> git.earman.xyz Git - sensor-watch.git/commitdiff
Added simple coin flip watch face (#63)
authorVaipex <86567086+Vaipex@users.noreply.github.com>
Sun, 3 Aug 2025 17:16:34 +0000 (17:16 +0000)
committerGitHub <noreply@github.com>
Sun, 3 Aug 2025 17:16:34 +0000 (13:16 -0400)
movement_faces.h
watch-faces.mk
watch-faces/complication/simple_coin_flip_face.c [new file with mode: 0644]
watch-faces/complication/simple_coin_flip_face.h [new file with mode: 0644]

index ca270cc3bcd85107160b58e2411be9b2baf798f0..ded8e789008b686fe4379c3f18c5b624d9fa1bcd 100644 (file)
@@ -63,6 +63,7 @@
 #include "tally_face.h"
 #include "probability_face.h"
 #include "ke_decimal_time_face.h"
+#include "simple_coin_flip_face.h"
 #include "lis2dw_monitor_face.h"
 #include "wareki_face.h"
 #include "deadline_face.h"
index 91a0d9e9fd3c780ef06b658fb3d8c441120920ec..6b3264247c1240292d0a5801496243523bf5e3df 100644 (file)
@@ -38,6 +38,7 @@ SRCS += \
   ./watch-faces/complication/kitchen_conversions_face.c \
   ./watch-faces/complication/periodic_table_face.c \
   ./watch-faces/clock/ke_decimal_time_face.c \
+  ./watch-faces/complication/simple_coin_flip_face.c \
   ./watch-faces/sensor/lis2dw_monitor_face.c \
   ./watch-faces/complication/wareki_face.c \
   ./watch-faces/complication/deadline_face.c \
diff --git a/watch-faces/complication/simple_coin_flip_face.c b/watch-faces/complication/simple_coin_flip_face.c
new file mode 100644 (file)
index 0000000..446832b
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Wesley Aptekar-Cassels
+ * Copyright (c) 2025 Vaipex
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include "simple_coin_flip_face.h"
+
+void simple_coin_flip_face_setup(uint8_t watch_face_index, void ** context_ptr) {
+    (void) watch_face_index;
+    if (*context_ptr == NULL) {
+        *context_ptr = malloc(sizeof(simple_coin_flip_face_state_t));
+        memset(*context_ptr, 0, sizeof(simple_coin_flip_face_state_t));
+    }
+}
+
+void simple_coin_flip_face_activate(void *context) {
+    simple_coin_flip_face_state_t *state = (simple_coin_flip_face_state_t *)context;
+}
+
+static uint32_t get_random(uint32_t max) {
+    #if __EMSCRIPTEN__
+        return rand() % max;
+    #else
+        return arc4random_uniform(max);
+    #endif
+
+}
+
+void draw_start_face() {
+    watch_clear_display();
+    if (watch_get_lcd_type() == WATCH_LCD_TYPE_CLASSIC) {
+        watch_display_text(WATCH_POSITION_BOTTOM, " Flip");
+    } else {
+        watch_display_text(WATCH_POSITION_BOTTOM, "Flip");
+    }
+}
+
+void set_pixels(int pixels[3][4][2], int j_len) {
+    for(int loopruns = 0; loopruns<2; loopruns++) {
+        for(int i = 0; i<3; i++) {
+            watch_clear_display();
+            for(int j = 0; j<j_len; j++){
+                watch_set_pixel(pixels[i][j][0], pixels[i][j][1]);
+            }
+            delay_ms(150);
+        }
+    }
+}
+
+void load_animation() {
+    if (watch_get_lcd_type() == WATCH_LCD_TYPE_CLASSIC) {
+        int j_len = 2;
+        int pixels[3][4][2] = {
+            {
+                {0, 3},
+                {0, 6}
+            },
+            {
+                {1, 3},
+                {1, 5}
+            },
+            {
+                {2, 2},
+                {2, 4}
+            }
+        };
+        set_pixels(pixels, j_len);
+    } else{
+        int j_len = 4;
+        int pixels[3][4][2] = {
+            {
+                {2, 22},
+                {2, 15},
+                {1, 2},
+                {1, 4}
+            },
+            {
+                {0, 16},
+                {0, 15},
+                {0, 1},
+                {0, 3}
+            },
+            {
+                {3, 16},
+                {3, 14},
+                {3, 1},
+                {3, 3}
+            }
+        };
+        set_pixels(pixels, j_len);
+    }
+}
+
+static void _blink_face_update_lcd(simple_coin_flip_face_state_t *state) {
+    watch_clear_display();
+    load_animation();
+    watch_clear_display();
+    int r = get_random(2);
+    if(r){
+        watch_display_text(WATCH_POSITION_BOTTOM, "Heads");
+    }else{
+        if (watch_get_lcd_type() == WATCH_LCD_TYPE_CLASSIC) {
+            watch_display_text(WATCH_POSITION_BOTTOM, " Tails");
+        }else {
+            watch_display_text(WATCH_POSITION_BOTTOM, "Tails");
+        }
+    }
+}
+
+bool simple_coin_flip_face_loop(movement_event_t event, void *context) {
+    simple_coin_flip_face_state_t *state = (simple_coin_flip_face_state_t *)context;
+
+    switch (event.event_type) {
+        case EVENT_ACTIVATE:
+            draw_start_face();
+            break;
+        case EVENT_TICK:
+            if(!state->is_start_face && !state->active){
+                if(state->inactivity_ticks >= 15){
+                    state->is_start_face = false;
+                    state->inactivity_ticks = 0;
+                    draw_start_face();
+                }else{
+                    state->inactivity_ticks++;
+                }
+            } else {
+                state->inactivity_ticks = 0;
+            }
+            break;
+        //execute same action for light and alarm button
+        case EVENT_LIGHT_BUTTON_UP:
+        case EVENT_ALARM_BUTTON_UP:
+            if (!state->active) {
+                state->active = true;
+                _blink_face_update_lcd(state);
+                state->active = false;
+                state->is_start_face = false;
+                state->inactivity_ticks = 0;
+            }
+            break;
+        case EVENT_TIMEOUT:
+            movement_move_to_face(0);
+            break;
+        case EVENT_LOW_ENERGY_UPDATE:
+            break;
+        default:
+            return movement_default_loop_handler(event);
+    }
+
+    return true;
+}
+
+void simple_coin_flip_face_resign(void *context) {
+    (void) context;
+}
+
diff --git a/watch-faces/complication/simple_coin_flip_face.h b/watch-faces/complication/simple_coin_flip_face.h
new file mode 100644 (file)
index 0000000..f5c95a4
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2023 Wesley Aptekar-Cassels
+ * Copyright (c) 2025 Vaipex
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "movement.h"
+
+/*
+ * A extremely simple coin flip face updated from Wesley Aptekar-Cassels version.
+ *
+ * Press ALARM or LIGHT to flip a coin, after a short animation it will display
+ * "Heads" or "Tails". Press ALARM or LIGHT to flip again.
+ *
+ * This is for people who want a simpler UI than probability_face or
+ * randonaut_face. While those have more features, this one is more immediately
+ * obvious - useful, for instance, if you are using a coin flip to agree on
+ * something with someone, and want the operation to be clear to someone who
+ * has not had anything explained to them.
+ */
+
+typedef struct {
+    bool active;
+    bool is_start_face;
+    uint8_t inactivity_ticks;
+} simple_coin_flip_face_state_t;
+
+void simple_coin_flip_face_setup(uint8_t watch_face_index, void ** context_ptr);
+void simple_coin_flip_face_activate(void *context);
+bool simple_coin_flip_face_loop(movement_event_t event, void *context);
+void simple_coin_flip_face_resign(void *context);
+
+#define simple_coin_flip_face ((const watch_face_t){ \
+    simple_coin_flip_face_setup, \
+    simple_coin_flip_face_activate, \
+    simple_coin_flip_face_loop, \
+    simple_coin_flip_face_resign, \
+    NULL, \
+})