diff options
author | joeycastillo <joeycastillo@utexas.edu> | 2023-04-16 10:46:52 -0400 |
---|---|---|
committer | joeycastillo <joeycastillo@utexas.edu> | 2023-04-16 10:46:52 -0400 |
commit | eb7168177957acae7cffc962e83f88893f867f23 (patch) | |
tree | f4a4f9fef74410c65eb86af39993babba1d7c84c /movement | |
parent | 00e641c2a7751f0967b384b4d009798f9ce2e47a (diff) | |
download | Sensor-Watch-eb7168177957acae7cffc962e83f88893f867f23.tar.gz Sensor-Watch-eb7168177957acae7cffc962e83f88893f867f23.tar.bz2 Sensor-Watch-eb7168177957acae7cffc962e83f88893f867f23.zip |
Revert "Coin & Dice Toss & Geomantic Divination Watch Faces (#235)"
This reverts commit 34030bf3e403b2043dcd9f960189d93190dcbb0c.
Diffstat (limited to 'movement')
-rw-r--r-- | movement/make/Makefile | 2 | ||||
-rw-r--r-- | movement/movement_faces.h | 2 | ||||
-rw-r--r-- | movement/watch_faces/complication/geomancy_face.c | 356 | ||||
-rw-r--r-- | movement/watch_faces/complication/geomancy_face.h | 99 | ||||
-rw-r--r-- | movement/watch_faces/complication/toss_up_face.c | 790 | ||||
-rw-r--r-- | movement/watch_faces/complication/toss_up_face.h | 112 |
6 files changed, 0 insertions, 1361 deletions
diff --git a/movement/make/Makefile b/movement/make/Makefile index 361f7c9d..50ba05cf 100644 --- a/movement/make/Makefile +++ b/movement/make/Makefile @@ -112,8 +112,6 @@ SRCS += \ ../watch_faces/complication/invaders_face.c \ ../watch_faces/clock/world_clock2_face.c \ ../watch_faces/complication/time_left_face.c \ - ../watch_faces/complication/toss_up_face.c \ - ../watch_faces/complication/geomancy_face.c \ # New watch faces go above this line. # Leave this line at the bottom of the file; it has all the targets for making your project. diff --git a/movement/movement_faces.h b/movement/movement_faces.h index a75deaec..358333ae 100644 --- a/movement/movement_faces.h +++ b/movement/movement_faces.h @@ -87,8 +87,6 @@ #include "invaders_face.h" #include "world_clock2_face.h" #include "time_left_face.h" -#include "toss_up_face.h" -#include "geomancy_face.h" #include "dual_timer_face.h" // New includes go above this line. diff --git a/movement/watch_faces/complication/geomancy_face.c b/movement/watch_faces/complication/geomancy_face.c deleted file mode 100644 index 689d4e18..00000000 --- a/movement/watch_faces/complication/geomancy_face.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2023 Tobias Raayoni Last / @randogoth - * - * 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 "toss_up_face.h" -#include "geomancy_face.h" - -// CONSTANTS ////////////////////////////////////////////////////////////////// - -// The Bagua 八卦 Trigrams encoded as 3bit tribbles, represented as binary integer -static const uint32_t bagua = 0b00000101001110010111011100000000; - -// The King Wen Sequence 文王卦序 of the I Ching 易經 Hexagrams 卦 encoded as an array -// of decimal integers in the order of two combined Trigram tribbles from 0b000000 to -// 0b111111 -static const uint8_t wen_order[] = { - 1, 22, 7, 19, 15, 34, 44, 11, - 14, 51, 38, 52, 61, 55, 30, 32, - 6, 3, 28, 58, 39, 63, 46, 5, - 45, 17, 47, 56, 31, 49, 27, 43, - 23, 26, 2, 41, 50, 20, 16, 24, - 35, 21, 62, 36, 54, 29, 48, 12, - 18, 40, 59, 60, 53, 37, 57, 9, - 10, 25, 4, 8, 33, 13, 42, 0 -}; - -// The geomantic figures encoded as 4 bit nibbles, represented as hexadecimal integer -static const uint64_t geomantic = 0x4ABF39D25E76C180; - -// Abbreviations of the Names of the Geomantic Figures in the order of the 4 bit nibbles -// from 0b0000 to 0b1111 -static const char figures[16][2] = { - "VI" /* Via */, "Hd" /* Head of the Dragon */, "PA" /* Puella */, "GF" /* Greater Fortune*/, - "PR" /* Puer */, "AQ" /* Acquisitio */, "CA" /* Carcer */, "TR" /* Tristitia */, - "Td" /* Tail of the Dragon */, "CO" /* Conjunctio */, "AM" /* Amissio */, "AL" /* Albus */, - "LF" /* Lesser Fortune */, "RU" /* Rubeus */, "LA" /* Laetitia */, "PO" /* Populus */ -}; - -// DECLARATIONS /////////////////////////////////////////////////////////////// - -static void geomancy_face_display(); -static nibble_t _geomancy_pick_figure(); -static tribble_t _iching_pick_trigram(); -static uint8_t _iching_form_hexagram(); -static void _geomancy_display(nibble_t code); -static void _display_hexagram(uint8_t hexagram, char* str); -static void _fix_broken_line(uint8_t hexagram); -static void _throw_animation(geomancy_state_t *state); - -// WATCH FACE FUNCTIONS /////////////////////////////////////////////////////// - -void geomancy_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) { - (void) settings; - if (*context_ptr == NULL) { - *context_ptr = malloc(sizeof(geomancy_state_t)); - memset(*context_ptr, 0, sizeof(geomancy_state_t)); - } -} - -void geomancy_face_activate(movement_settings_t *settings, void *context) { - (void) settings; - (void) context; -} - -bool geomancy_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { - geomancy_state_t *state = (geomancy_state_t *)context; - - switch (event.event_type) { - case EVENT_ACTIVATE: - state->animate = false; - state->animation = 0; - watch_display_string(" IChing", 0); - break; - case EVENT_TICK: - if ( state->animate ) { - state->animation = (state->animation + 1) % 39; - geomancy_face_display(state); - } - break; - case EVENT_LIGHT_BUTTON_DOWN: - break; - case EVENT_LIGHT_BUTTON_UP: - if ( state->animate ) break; - if ( state->mode <= 1 ) state->mode = 2; - else if ( state->mode >= 2 ) state->mode = 0; - geomancy_face_display(state); - break; - case EVENT_ALARM_BUTTON_UP: - if ( state->animate ) break; - switch ( state->mode ) { - case 0: - state->mode++; - case 1: - state->animate = true; - state->i_ching_hexagram = _iching_form_hexagram(); - break; - case 2: - state->mode++; - case 3: - state->animate = true; - state->geomantic_figure = _geomancy_pick_figure().bits; - break; - default: - break; - } - geomancy_face_display(state); - break; - case EVENT_ALARM_LONG_PRESS: - if ( state->animate ) break; - state->caption = !state->caption; - watch_display_string(" ", 0); - geomancy_face_display(state); - break; - default: - return movement_default_loop_handler(event, settings); - } - return true; -} - -void geomancy_face_resign(movement_settings_t *settings, void *context) { - (void) settings; - (void) context; -} - -// STATIC FUNCTIONS /////////////////////////////////////////////////////////// - -/** @brief display handler */ -static void geomancy_face_display(geomancy_state_t *state) { - char token[7] = {0}; - nibble_t figure = *((nibble_t*) &state->geomantic_figure); - switch ( state->mode ) { - case 0: - watch_display_string(" IChing", 0); - break; - case 1: - _throw_animation(state); - if ( !state->animate ) { - _display_hexagram(state->i_ching_hexagram, token); - watch_display_string(token, 4); - _fix_broken_line(state->i_ching_hexagram); - if (state->caption) { - sprintf(token, "%2d", wen_order[state->i_ching_hexagram] + 1); - watch_display_string(token, 2); - } - } - break; - case 2: - watch_display_string(" GeomCy", 0); - break; - case 3: - _throw_animation(state); - if ( !state->animate ) { - if ( state->caption ) { - sprintf(token, "%c%c", figures[state->geomantic_figure][0], figures[state->geomantic_figure][1]); - watch_display_string(token, 0); - } - _geomancy_display(figure); - } - break; - default: - break; - } -} - -/** @brief screen clearing animation between castings */ -static void _throw_animation(geomancy_state_t *state) { - movement_request_tick_frequency(16); - switch ( state->animation ) { - case 0: - watch_set_pixel(0, 22); - break; - case 1: - watch_set_pixel(2, 22); - watch_set_pixel(2, 23); - watch_clear_pixel(0, 22); - break; - case 2: - watch_set_pixel(1, 22); - watch_set_pixel(0, 23); - break; - case 3: - watch_set_pixel(2, 0); - watch_set_pixel(1, 0); - watch_set_pixel(2, 21); - watch_set_pixel(1, 21); - watch_clear_pixel(2, 22); - watch_clear_pixel(1, 22); - watch_clear_pixel(2, 23); - watch_clear_pixel(0, 23); - watch_clear_pixel(1, 23); - break; - case 4: - watch_set_pixel(1, 17); - watch_set_pixel(0, 20); - watch_set_pixel(2, 10); - watch_set_pixel(0, 1); - break; - case 5: - watch_clear_pixel(2, 21); - watch_clear_pixel(1, 21); - watch_clear_pixel(2, 0); - watch_clear_pixel(1, 0); - watch_clear_pixel(1, 20); - watch_clear_pixel(2, 20); - watch_clear_pixel(0, 21); - watch_clear_pixel(1, 1); - watch_clear_pixel(0, 0); - watch_clear_pixel(2, 1); - watch_set_pixel(2, 19); - watch_set_pixel(0, 19); - watch_set_pixel(1, 2); - watch_set_pixel(0, 2); - break; - case 6: - watch_clear_pixel(1, 17); - watch_clear_pixel(0, 20); - watch_clear_pixel(2, 10); - watch_clear_pixel(0, 1); - watch_set_pixel(2, 18); - watch_set_pixel(0, 18); - watch_set_pixel(2, 3); - watch_set_pixel(0, 4); - break; - case 7: - watch_clear_pixel(2, 19); - watch_clear_pixel(0, 19); - watch_clear_pixel(1, 18); - watch_clear_pixel(1, 19); - watch_clear_pixel(1, 2); - watch_clear_pixel(0, 2); - watch_clear_pixel(1, 3); - watch_clear_pixel(0, 3); - watch_clear_pixel(2, 2); - watch_set_pixel(1, 4); - watch_set_pixel(0, 5); - break; - case 8: - watch_clear_pixel(2, 18); - watch_clear_pixel(0, 18); - watch_clear_pixel(2, 3); - watch_clear_pixel(0, 4); - watch_set_pixel(2, 5); - watch_set_pixel(1, 6); - break; - case 9: - watch_clear_pixel(1, 4); - watch_clear_pixel(0, 5); - watch_clear_pixel(1, 5); - watch_clear_pixel(2, 4); - watch_clear_pixel(0, 6); - break; - case 10: - watch_clear_pixel(2, 5); - watch_clear_pixel(1, 6); - break; - case 11: - state->animate = false; - state->animation = 0; - movement_request_tick_frequency(1); - break; - } -} - -// I CHING FUNCTIONS ////////////////////////////////////////////////////////// - -/** @brief form a trigram from three random bit picks - */ -static tribble_t _iching_pick_trigram() { - uint8_t index = (divine_bit() << 2) | (divine_bit() << 1) | divine_bit(); - tribble_t trigram = {(bagua >> (3 * index)) & 0b111}; - return trigram; -} - -/** @brief form a hexagram from two trigrams - */ -static uint8_t _iching_form_hexagram() { - tribble_t inner = _iching_pick_trigram(); - tribble_t outer = _iching_pick_trigram(); - uint8_t hexagram = (inner.bits << 3) | outer.bits; - return hexagram; -} - -/** @brief display hexagram - * @details | for unbroken lines and Ξ for broken lines, left of display is bottom - */ -static void _display_hexagram(uint8_t hexagram, char* str) { - str[6] = '\0'; // Null-terminate the string - for (uint8_t i = 0; i < 6; i++) { - if (hexagram & (1 << (5 - i))) { - str[i] = '1'; - } else { - str[i] = '='; - } - } -} - -/** @brief when Ξ digits show as = then manually add a line on top - */ -static void _fix_broken_line(uint8_t hexagram) { - for (uint8_t i = 0; i < 6; i++) { - if (!(hexagram & (1 << (5 - i)))) { - if ( i == 1 ) watch_set_pixel(2, 20); - if ( i == 3 ) watch_set_pixel(2, 1); - if ( i == 4 ) watch_set_pixel(2, 2); - if ( i == 5 ) watch_set_pixel(2, 4); - } - } -} - -// GEOMANCY FUNCTIONS ///////////////////////////////////////////////////////// - -/** @brief choose a geomantic figure from four random bits - * @details 0 represents · and 1 represents : counting from the bottom - */ -static nibble_t _geomancy_pick_figure() { - uint8_t index = (divine_bit() << 3) | (divine_bit() << 2) | (divine_bit() << 1) | divine_bit(); - nibble_t figure = {(geomantic >> (4 * (15 - index))) & 0xF}; - return figure; -} - -/** @brief display the geomantic figure, left of display is bottom - */ -static void _geomancy_display(nibble_t code) { - // draw geomantic figures - bool row1 = (code.bits >> 3) & 1; - bool row2 = (code.bits >> 2) & 1; - bool row3 = (code.bits >> 1) & 1; - bool row4 = code.bits & 1; - - if ( row1 ) watch_set_pixel(1, 18); else watch_set_pixel(1, 19); - if ( row2 ) { watch_set_pixel(2, 20); watch_set_pixel(0, 21);} else watch_set_pixel(1, 20); - if ( row3 ) watch_set_pixel(0, 22); else watch_set_pixel(1, 23); - if ( row4 ) { watch_set_pixel(2, 1); watch_set_pixel(0, 0);} else watch_set_pixel(1, 1); -}
\ No newline at end of file diff --git a/movement/watch_faces/complication/geomancy_face.h b/movement/watch_faces/complication/geomancy_face.h deleted file mode 100644 index 4a19ba85..00000000 --- a/movement/watch_faces/complication/geomancy_face.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2023 Tobias Raayoni Last / @randogoth - * - * 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. - */ - -#ifndef GEOMANCY_FACE_H_ -#define GEOMANCY_FACE_H_ - -#include "movement.h" - -/* - * GEOMANCY WATCH FACE - * - * A simple and straightforward watch face for the ancient Eastern geomantic divination system - * of I Ching and the western system of "Geomancy". It is an optional addition to the Toss Up - * Face. - * - * The LIGHT button toggles between the two systems of geomancy. - * - * The ALARM button casts an I Ching hexagram or Geomantic figure based on drawing virtual - * stalks from the True Random Number Generator in the Sensor Watch. - * - * The figures are flipped 90 degrees clockwise, so the left side is the bottom and the - * right side the top. - * - * LONG PRESSING ALARM toggles the display of the King Wen sequence index for the cast I Ching - * Hexagram (https://en.wikipedia.org/wiki/King_Wen_sequence )or the abbreviated name for the - * cast Geomantic Figure: - * - * GF - Greater Fortune (Fortuna Major) - * LF - Lesser Fortune (Fortuna Minor) - * PO - Populus - * VI - Via - * AL - Albus - * CO - Conjunctio - * PA - Puella - * AM - Amissio - * PR - Puer - * RU - Rubeus - * AQ - Acquisitio - * LA - Laetitia - * TR - Tristitia - * CA - Carcer - * HD - Head of the Dragon (Caput Draconis) - * TD - Tail of the Dragon (Cauda Draconis) - * - */ - -typedef struct { - uint8_t bits : 4; -} nibble_t; - -typedef struct { - uint8_t bits : 3; -} tribble_t; - -typedef struct { - uint8_t mode : 3; - uint8_t geomantic_figure; - uint8_t i_ching_hexagram : 6; - bool caption; - uint8_t animation; - bool animate; -} geomancy_state_t; - -void geomancy_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); -void geomancy_face_activate(movement_settings_t *settings, void *context); -bool geomancy_face_loop(movement_event_t event, movement_settings_t *settings, void *context); -void geomancy_face_resign(movement_settings_t *settings, void *context); - -#define geomancy_face ((const watch_face_t){ \ - geomancy_face_setup, \ - geomancy_face_activate, \ - geomancy_face_loop, \ - geomancy_face_resign, \ - NULL, \ -}) - -#endif // GEOMANCY_FACE_H_ - diff --git a/movement/watch_faces/complication/toss_up_face.c b/movement/watch_faces/complication/toss_up_face.c deleted file mode 100644 index 1923302f..00000000 --- a/movement/watch_faces/complication/toss_up_face.c +++ /dev/null @@ -1,790 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2023 Tobias Raayoni Last / @randogoth - * - * 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 "toss_up_face.h" -#if __EMSCRIPTEN__ -#include <time.h> -#else -#include "saml22j18a.h" -#endif - -static const char heads[] = { '8', 'h', '4', 'E', '(' }; -static const char tails[] = { '0', '+', 'N', '3', ')' }; -static const uint8_t dd[] = {2, 4, 6, 8, 10,12,20,24,30,32,36,48,99}; - -static void _roll_dice_multiple(char* result, uint8_t* dice, uint8_t num_dice); -static void _sort_coins(char* token, uint8_t num_bits, uint8_t bits, char* heads, char* tails); -void _display_coins(char* token, bool* bit_array, uint8_t length, toss_up_state_t *state); -static void _toss_up_face_display(toss_up_state_t *state); -static void _dice_animation(toss_up_state_t *state); -static void _coin_animation(toss_up_state_t *state); - -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// - -void toss_up_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) { - (void) settings; - if (*context_ptr == NULL) { - *context_ptr = malloc(sizeof(toss_up_state_t)); - memset(*context_ptr, 0, sizeof(toss_up_state_t)); - toss_up_state_t *state = (toss_up_state_t *)*context_ptr; - - // defaults - state->coin_num = 1; - state->dice_num = 1; - state->dice_sides[0] = 6; - state->dice_sides[1] = 6; - state->dice_sides[2] = 6; - state->coin_style[0] = '8'; - state->coin_style[1] = '0'; - } -} - -void toss_up_face_activate(movement_settings_t *settings, void *context) { - (void) settings; - (void) context; -} - -bool toss_up_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { - toss_up_state_t *state = (toss_up_state_t *)context; - uint8_t i = 0; - switch (event.event_type) { - case EVENT_ACTIVATE: - watch_display_string(" Coins ", 0); - break; - case EVENT_TICK: - if ( state->animate ) { - state->animation = (state->animation + 1); - _toss_up_face_display(state); - } - break; - case EVENT_LIGHT_BUTTON_DOWN: - break; - case EVENT_LIGHT_BUTTON_UP: - if ( state->animate ) break; - // change between coins and dice - if ( state->mode <= 1 ) state->mode = 2; - else if ( state->mode >= 2 ) state->mode = 0; - _toss_up_face_display(state); - break; - case EVENT_ALARM_BUTTON_UP: - // toss - if ( state->animate ) break; - switch (state->mode) { - case 0: - state->mode++; - case 1: - state->animate = true; - for (i = 0; i < state->coin_num; i++) { - state->coins[i] = divine_bit(); - } - break; - case 2: - state->mode++; - case 3: - state->animate = true; - for (i = 0; i < state->dice_num; i++) { - state->dice[i] = roll_dice(state->dice_sides[i]); - } - break; - default: - break; - } - _toss_up_face_display(state); - break; - case EVENT_LIGHT_LONG_PRESS: - if ( state->animate ) break; - state->animate = false; - switch (state->mode) { - case 0: // change to default coin style - state->coin_style[0] = heads[0]; - state->coin_style[1] = tails[0]; - state->coinface = 0; - break; - case 1: // change the coin style - state->coinface = (state->coinface + 1) % 5; - state->coin_style[0] = heads[state->coinface]; - state->coin_style[1] = tails[state->coinface]; - break; - case 2: // change to default dice sides - state->dice_sides[0] = 6; - state->dice_sides[1] = 6; - state->dice_sides[2] = 6; - state->dd = 0; - break; - case 3: // change the sides of the dice - state->dd = (state->dd + 1) % 13; - state->dice_sides[state->dice_num-1] = dd[state->dd]; - state->dice[state->dice_num-1] = dd[state->dd]; - break; - default: - break; - } - _toss_up_face_display(state); - break; - case EVENT_ALARM_LONG_PRESS: - if ( state->animate ) break; - state->animate = false; - switch (state->mode) { - case 0: // back to one coin - state->coin_num = 1; - break; - case 1: // up to 6 coins total - state->coin_num = (state->coin_num % 6) + 1; - break; - case 2: // back to one dice - state->dice_num = 1; - break; - case 3: // add up to 3 dice total - state->dice_num = (state->dice_num % 3) + 1; - state->dd = 0; - break; - default: - break; - } - _toss_up_face_display(state); - break; - default: - return movement_default_loop_handler(event, settings); - } - - return true; -} - -void toss_up_face_resign(movement_settings_t *settings, void *context) { - (void) settings; - (void) context; -} - -// STATIC FUNCTIONS /////////////////////////////////////////////////////////// - -/** @brief handles the display - */ -static void _toss_up_face_display(toss_up_state_t *state) { - char buf[11] = {0}; - char token[7] = {0}; - switch ( state->mode ) { - case 0: // coins title - sprintf(buf, " Coins "); - break; - case 1: // coins divination - _coin_animation(state); - if ( !state->animate ) { - watch_clear_display(); - _display_coins(token, state->coins, state->coin_num, state); - sprintf(buf, " %s", token); - } - break; - case 2: // dice title - sprintf(buf, " Dice "); - break; - case 3: // dice divination - _dice_animation(state); - if ( !state->animate ) { - _roll_dice_multiple(token, state->dice, state->dice_num + 1); - sprintf(buf, " %s", token); - } - break; - default: - break; - } - watch_display_string(buf, 0); -} - -/** @brief divination method to derive a bit from 32 TRNG bits - */ -uint8_t divine_bit(void) { - uint32_t stalks; - do { // modulo bias filter - stalks = get_true_entropy(); // get 32 TRNG bits as stalks - } while (stalks >= INT32_MAX || stalks <= 0); - - uint8_t pile1_xor = 0; - uint8_t pile2_xor = 0; - // Divide the stalks into two piles, alternating ends - for (uint8_t i = 0; i < 16; i++) { - uint8_t left_bit = (stalks >> (31 - 2*i)) & 1; - uint8_t right_bit = (stalks >> (30 - 2*i)) & 1; - if (i % 2 == 0) { - pile1_xor ^= left_bit; - pile2_xor ^= right_bit; - } else { - pile1_xor ^= right_bit; - pile2_xor ^= left_bit; - } - } - // Take the XOR of the pile results - uint8_t result_xor = pile1_xor ^ pile2_xor; - // Output 1 if result_xor is 1, 0 otherwise - return result_xor; -} - -/** @brief get 32 True Random Number bits - */ -uint32_t get_true_entropy(void) { - #if __EMSCRIPTEN__ - return rand() % INT32_MAX; - #else - hri_mclk_set_APBCMASK_TRNG_bit(MCLK); - hri_trng_set_CTRLA_ENABLE_bit(TRNG); - - while (!hri_trng_get_INTFLAG_reg(TRNG, TRNG_INTFLAG_DATARDY)); // Wait for TRNG data to be ready - - hri_trng_clear_CTRLA_ENABLE_bit(TRNG); - hri_mclk_clear_APBCMASK_TRNG_bit(MCLK); - return hri_trng_read_DATA_reg(TRNG); // Read a single 32-bit word from TRNG and return it - #endif -} - -// COIN FUNCTIONS ///////////////////////////////////////////////////////////// - -/** @brief sort tossed coins into a pile of heads and a pile of tails - */ -static void _sort_coins(char* token, uint8_t num_bits, uint8_t bits, char* heads, char* tails) { - uint8_t num_ones = 0; - for (uint8_t i = 0; i < num_bits; i++) { - if ((bits >> i) & 1) { - *token++ = *heads; - num_ones++; - } - } - if ( num_bits < 6 ) { - for (uint8_t i = 0; i < (6 - num_bits); i++) { - *token++ = ' '; - } - } - for (uint8_t i = 0; i < (num_bits - num_ones); i++) { - - *token++ = *tails; - } -} - -/** @brief convert bool array of coinflips to integer for sorting - */ -void _display_coins(char* token, bool* bit_array, uint8_t length, toss_up_state_t *state) { - uint8_t bits = 0; - for (uint8_t i = 0; i < length; i++) { - if (bit_array[i]) { - bits |= (1 << (length - 1 - i)); - } - } - _sort_coins(token, length, bits, &state->coin_style[0], &state->coin_style[1]); -} - -/** @brief coin animation - */ -static void _coin_animation(toss_up_state_t *state) { - bool heads = false; - bool tails = false; - for (uint8_t i = 0; i < state->coin_num; i++) { - if (state->coins[i] == true) { - heads++; - } else { - tails++; - } - } - movement_request_tick_frequency(32); - switch ( state->animation ) { - case 0: - watch_display_string(" ", 4); - if ( heads ) { - watch_set_pixel(0, 18); - watch_set_pixel(2, 18); - } else { - state->animation = 12; - } - break; - case 1: - if ( heads ) { - watch_set_pixel(1, 18); - } - break; - case 2: - if ( heads ) { - watch_set_pixel(0, 19); - watch_set_pixel(2, 19); - } - break; - case 3: - if ( heads ) { - watch_clear_pixel(0, 18); - watch_clear_pixel(2, 18); - } - break; - case 4: - if ( heads ) { - watch_clear_pixel(1, 18); - } - break; - case 5: - if ( heads ) { - watch_clear_pixel(0, 19); - watch_clear_pixel(2, 19); - watch_set_pixel(1, 17); - watch_set_pixel(0, 20); - } - break; - case 6: - if ( heads ) { - watch_set_pixel(2, 20); - watch_set_pixel(0, 21); - } - break; - case 7: - if ( heads ) { - watch_set_pixel(1, 21); - watch_set_pixel(2, 21); - } - break; - case 8: - if ( heads ) { - watch_clear_pixel(1, 17); - watch_clear_pixel(0, 20); - } - break; - case 9: - if ( heads ) { - watch_clear_pixel(2, 20); - watch_clear_pixel(0, 21); - } - break; - case 10: - if ( heads ) { - watch_clear_pixel(1, 21); - watch_clear_pixel(2, 21); - watch_set_pixel(1, 22); - watch_set_pixel(2, 22); - } - break; - case 11: - if ( heads ) { - watch_set_pixel(0, 22); - } - break; - case 12: - if ( heads ) { - watch_set_pixel(2, 23); - watch_set_pixel(0, 23); - } - if ( tails ) { - watch_set_pixel(0, 18); - watch_set_pixel(2, 18); - } - break; - case 13: - if ( heads ) { - watch_clear_pixel(1, 22); - watch_clear_pixel(2, 22); - } - if ( tails ) { - watch_set_pixel(1, 18); - } - break; - case 14: - if ( heads ) { - watch_clear_pixel(0, 22); - } - if ( tails ) { - watch_set_pixel(0, 19); - watch_set_pixel(2, 19); - } - break; - case 15: - if ( heads ) { - watch_clear_pixel(2, 23); - watch_clear_pixel(0, 23); - watch_set_pixel(2, 0); - watch_set_pixel(1, 0); - } - if ( tails ) { - watch_clear_pixel(0, 18); - watch_clear_pixel(2, 18); - } - break; - case 16: - if ( heads ) { - watch_set_pixel(2, 1); - watch_set_pixel(0, 0); - } - if ( tails ) { - watch_clear_pixel(1, 18); - } - break; - case 17: - if ( heads ) { - watch_set_pixel(2, 10); - watch_set_pixel(0, 1); - } - if ( tails ) { - watch_clear_pixel(0, 19); - watch_clear_pixel(2, 19); - watch_set_pixel(1, 17); - watch_set_pixel(0, 20); - } - break; - case 18: - if ( heads ) { - watch_clear_pixel(2, 0); - watch_clear_pixel(1, 0); - } - if ( tails ) { - watch_set_pixel(2, 20); - watch_set_pixel(0, 21); - } - break; - case 19: - if ( heads ) { - watch_clear_pixel(2, 1); - watch_clear_pixel(0, 0); - } - if ( tails ) { - watch_set_pixel(1, 21); - watch_set_pixel(2, 21); - } - break; - case 20: - if ( heads ) { - watch_set_pixel(2, 1); - watch_set_pixel(0, 0); - } - if ( tails ) { - watch_clear_pixel(1, 17); - watch_clear_pixel(0, 20); - } - break; - case 21: - if ( heads ) { - watch_set_pixel(2, 0); - watch_set_pixel(1, 0); - } - if ( tails ) { - watch_clear_pixel(2, 20); - watch_clear_pixel(0, 21); - } - break; - case 22: - if ( heads ) { - watch_clear_pixel(2, 10); - watch_clear_pixel(0, 1); - } - if ( tails ) { - watch_clear_pixel(1, 21); - watch_clear_pixel(2, 21); - watch_set_pixel(1, 22); - watch_set_pixel(2, 22); - } - break; - case 23: - if ( heads ) { - watch_clear_pixel(2, 1); - watch_clear_pixel(0, 0); - } - if ( tails ) { - watch_set_pixel(0, 22); - } - break; - case 24: - if ( heads ) { - watch_set_pixel(2, 23); - watch_set_pixel(0, 23); - watch_clear_pixel(2, 0); - watch_clear_pixel(1, 0); - } - if ( tails ) { - watch_set_pixel(2, 23); - watch_set_pixel(0, 23); - } - break; - case 25: - if ( heads ) { - watch_set_pixel(0, 22); - } - if ( tails ) { - watch_clear_pixel(1, 22); - watch_clear_pixel(2, 22); - } - break; - case 26: - if ( heads ) { - watch_set_pixel(1, 22); - watch_set_pixel(2, 22); - } - if ( tails ) { - watch_clear_pixel(0, 22); - } - break; - case 27: - if ( heads ) { - watch_clear_pixel(2, 23); - watch_clear_pixel(0, 23); - } - if ( tails ) { - watch_clear_pixel(2, 23); - watch_clear_pixel(0, 23); - watch_set_pixel(2, 0); - watch_set_pixel(1, 0); - } - break; - case 28: - if ( heads ) { - watch_clear_pixel(0, 22); - } - if ( tails ) { - watch_set_pixel(2, 1); - watch_set_pixel(0, 0); - } - break; - case 29: - if ( heads ) { - watch_set_pixel(1, 21); - watch_set_pixel(2, 21); - watch_clear_pixel(1, 22); - watch_clear_pixel(2, 22); - } - if ( tails ) { - watch_set_pixel(2, 10); - watch_set_pixel(0, 1); - } - break; - case 30: - if ( heads ) { - watch_set_pixel(2, 20); - watch_set_pixel(0, 21); - } - if ( tails ) { - watch_clear_pixel(1, 0); - watch_clear_pixel(2, 0); - } - break; - case 31: - if ( heads ) { - watch_set_pixel(1, 17); - watch_set_pixel(0, 20); - } - if ( tails ) { - watch_clear_pixel(2, 1); - watch_clear_pixel(0, 0); - } - break; - case 32: - if ( heads ) { - watch_clear_pixel(1, 21); - watch_clear_pixel(2, 21); - } - if ( tails ) { - watch_clear_pixel(2, 10); - watch_clear_pixel(0, 1); - watch_set_pixel(0, 2); - watch_set_pixel(1, 2); - } - break; - case 33: - if ( heads ) { - watch_clear_pixel(2, 20); - watch_clear_pixel(0, 21); - } - if ( tails ) { - watch_set_pixel(2, 2); - watch_set_pixel(0, 3); - } - break; - case 34: - if ( heads ) { - watch_set_pixel(0, 19); - watch_set_pixel(2, 19); - watch_clear_pixel(1, 17); - watch_clear_pixel(0, 20); - } - if ( tails ) { - watch_set_pixel(2, 3); - watch_set_pixel(0, 4); - } - break; - case 35: - if ( heads ) { - watch_set_pixel(1, 18); - } - if ( tails ) { - watch_clear_pixel(1, 2); - watch_clear_pixel(0, 2); - } - break; - case 36: - if ( heads ) { - watch_set_pixel(0, 18); - watch_set_pixel(2, 18); - } - if ( tails ) { - watch_clear_pixel(2, 2); - watch_clear_pixel(0, 3); - } - break; - case 37: - if ( heads ) { - watch_clear_pixel(0, 19); - watch_clear_pixel(2, 19); - } - if ( tails ) { - watch_clear_pixel(2, 3); - watch_clear_pixel(0, 4); - watch_set_pixel(1, 4); - watch_set_pixel(0, 5); - } - break; - case 38: - if ( heads ) { - watch_clear_pixel(1, 18); - } - if ( tails ) { - watch_set_pixel(2, 4); - watch_set_pixel(0, 6); - } - break; - case 39: - if ( heads ) { - watch_clear_pixel(0, 18); - watch_clear_pixel(2, 18); - } - if ( tails ) { - watch_set_pixel(1, 6); - watch_set_pixel(2, 5); - } - state->animate = false; - state->animation = 0; - movement_request_tick_frequency(1); - } -} - -// DICE FUNCTIONS ///////////////////////////////////////////////////////////// - -/** @brief rolls a dice - */ -uint8_t roll_dice(uint8_t sides) { - uint8_t bits_needed = 0; - uint8_t temp_sides = sides - 1; - uint8_t result = 0; - while (temp_sides > 0) { - bits_needed++; // how many bits do we need to represent this number? - temp_sides >>= 1; // Shift right to check the next bit - } - do { - result = 0; - for (int i = 0; i < bits_needed; i++) { - result <<= 1; // Shift left to make room for the next bit - result |= divine_bit(); // Add the next bit to the result - } - } while ( result > sides -1 ); - return result + 1; // Add 1 to convert the range from 0 to sides-1 to 1 to sides -} - -/** @brief roll multiple dice and print a char array for displaying them - */ -static void _roll_dice_multiple(char* result, uint8_t* dice, uint8_t num_dice) { - // initialize the result array to all spaces - memset(result, ' ', 6); - - // roll the dice and write the result to the result array - for (uint8_t i = 0; i < num_dice-1; i++) { - uint8_t dice_result = dice[i]; - uint8_t tens_digit = dice_result / 10; - uint8_t ones_digit = dice_result % 10; - result[(i * 2)] = tens_digit == 0 ? ' ' : (char)('0' + tens_digit); - result[(i * 2) + 1] = (char)('0' + ones_digit); - } -} - -/** @brief dice animation - */ -static void _dice_animation(toss_up_state_t *state) { - watch_display_string(" ", 4); - for (uint8_t i = 0; i < state->dice_num; i++) { - watch_display_string("0",i*2 + 5); - } - movement_request_tick_frequency(16); - switch ( state->animation ) { - case 0: - watch_clear_pixel(1, 17); - watch_clear_pixel(0, 0); - watch_clear_pixel(1, 6); - break; - case 1: - watch_clear_pixel(2, 20); - watch_clear_pixel(1, 0); - watch_clear_pixel(0, 6); - break; - case 2: - watch_clear_pixel(2, 21); - watch_clear_pixel(2, 0); - watch_clear_pixel(0, 5); - break; - case 3: - watch_clear_pixel(1, 21); - watch_clear_pixel(2, 1); - watch_clear_pixel(1, 4); - break; - case 4: - watch_clear_pixel(0, 21); - watch_clear_pixel(2, 10); - watch_clear_pixel(2, 4); - break; - case 5: - watch_clear_pixel(0, 20); - watch_clear_pixel(0, 1); - watch_clear_pixel(2, 5); - break; - case 6: - watch_clear_pixel(1, 17); - watch_clear_pixel(0, 0); - watch_clear_pixel(1, 6); - break; - case 7: - watch_clear_pixel(2, 20); - watch_clear_pixel(1, 0); - watch_clear_pixel(0, 6); - break; - case 8: - watch_clear_pixel(2, 21); - watch_clear_pixel(2, 0); - watch_clear_pixel(0, 5); - break; - case 9: - watch_clear_pixel(1, 21); - watch_clear_pixel(2, 1); - watch_clear_pixel(1, 4); - break; - case 10: - watch_clear_pixel(0, 21); - watch_clear_pixel(2, 10); - watch_clear_pixel(2, 4); - break; - case 11: - watch_clear_pixel(0, 20); - watch_clear_pixel(0, 1); - watch_clear_pixel(2, 5); - state->animate = false; - state->animation = 0; - movement_request_tick_frequency(1); - } -}
\ No newline at end of file diff --git a/movement/watch_faces/complication/toss_up_face.h b/movement/watch_faces/complication/toss_up_face.h deleted file mode 100644 index ca6136a7..00000000 --- a/movement/watch_faces/complication/toss_up_face.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2023 Tobias Raayoni Last / @randogoth - * - * 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. - */ - -#ifndef TOSS_UP_FACE_H_ -#define TOSS_UP_FACE_H_ - -#include "movement.h" - -/* - * TOSS UP FACE - * ============ - * - * Playful watch face for games of chance or divination using coins or dice. - * - * LIGHT switches between Coins and Dice mode - * - * COINS - * ===== - * - * ALARM tosses a coin. If it lands on heads it gets sorted to the left side of the - * display, if it lands on tails then sorted to the right side. - * - * LONG PRESSING ALARM adds up to 5 more coins to the toss for more nuance in the decision - * making (e.g. three heads vs two tails could be read as "yes, but with serious doubts"). - * - * LONG PRESSING LIGHT flips through additional style for the coins from the default Ө/O - * to H/T (heads/tails), Y/N (yes/no), E/Ǝ, C/Ↄ - * - * LONG PRESSING ALARM on the "Coins" title page resets to one coin. - * LONG PRESSING LIGHT on the "Coins" title page resets the style to Ө/O - * - * DICE - * ==== - * - * ALARM rolls a six sided dice. - * - * LONG PRESSING ALARM adds up to 2 more dice to the roll. - * - * LONG PRESSING LIGHT flips through other available polyhedral dice types with less or more - * than the default 6 sides. The options are D2, D4, D6, D8, D10, D12, D20, D24, D30, D32, D36, - * D48, and a hypothetical D99. - * - * When more than one dice is used for a roll this changes only the last added dice. (see Note - * below) - * - * LONG PRESSING ALARM on the "Dice" title page resets to one dice. - * LONG PRESSING LIGHT on the "Dice" title page resets the dice to D6. - * - * Please Note: If you need let's say a D8, D12, and D20 for your rolls then the procedure to - * set this up would be as follows: from the default screen where you can roll the one D6 dice - * you would LONG PRESS LIGHT a few times to change the D6 to a D8, then LONG PRESS ALARM to add - * a second dice, LONG PRESS LIGHT again until the second dice changes to D12, then LONG PRESS - * ALARM to add the third dice and LONG PRESS LIGHT again a few times until it becomes a D20. - * - */ - -typedef struct { - // Anything you need to keep track of, put it here! - uint32_t entropy; - uint8_t mode : 4; // 1 coin, 2 coins, 3 coins, 4 coins, dice, iching, geomnc - bool setup; - bool coins[6]; - uint8_t coin_num : 3; - char coin_style[2]; - uint8_t coinface : 3; - uint8_t dice[3]; - uint8_t dice_num : 2; - uint8_t dd : 6; - uint8_t dice_sides[3]; - uint8_t animation; - bool animate; -} toss_up_state_t; - -uint32_t get_true_entropy(void); -uint8_t divine_bit(void); -uint8_t roll_dice(uint8_t sides); -void toss_up_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); -void toss_up_face_activate(movement_settings_t *settings, void *context); -bool toss_up_face_loop(movement_event_t event, movement_settings_t *settings, void *context); -void toss_up_face_resign(movement_settings_t *settings, void *context); - -#define toss_up_face ((const watch_face_t){ \ - toss_up_face_setup, \ - toss_up_face_activate, \ - toss_up_face_loop, \ - toss_up_face_resign, \ - NULL, \ -}) - -#endif // TOSS_UP_FACE_H_ - |