Merge PR #430 - improve tally face

Adds the ability to tally negative counts, tally quickly by holding down
the buttons as well as the ability to enable and cycle through multiple
preset initial values for numerous contexts such as card games.

Reviewed-by: Matheus Afonso Martins Moreira <matheus@matheusmoreira.com>
GitHub-Pull-Request: https://github.com/joeycastillo/Sensor-Watch/pull/430
This commit is contained in:
Matheus Afonso Martins Moreira 2024-09-08 21:20:25 -03:00
commit 44b543421d
2 changed files with 164 additions and 26 deletions

View file

@ -27,47 +27,162 @@
#include "tally_face.h" #include "tally_face.h"
#include "watch.h" #include "watch.h"
#define TALLY_FACE_MAX 9999
#define TALLY_FACE_MIN -99
static bool _init_val;
static bool _quick_ticks_running;
static const int16_t _tally_default[] = {
0,
#ifdef TALLY_FACE_PRESETS_MTG
20,
40,
#endif /* TALLY_FACE_PRESETS_MTG */
#ifdef TALLY_FACE_PRESETS_YUGIOH
4000,
8000,
#endif /* TALLY_FACE_PRESETS_YUGIOH */
};
#define TALLY_FACE_PRESETS_SIZE() (sizeof(_tally_default) / sizeof(int16_t))
void tally_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) { void tally_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
(void) settings; (void) settings;
(void) watch_face_index; (void) watch_face_index;
if (*context_ptr == NULL) { if (*context_ptr == NULL) {
*context_ptr = malloc(sizeof(tally_state_t)); *context_ptr = malloc(sizeof(tally_state_t));
memset(*context_ptr, 0, sizeof(tally_state_t)); memset(*context_ptr, 0, sizeof(tally_state_t));
tally_state_t *state = (tally_state_t *)*context_ptr;
state->tally_default_idx = 0;
state->tally_idx = _tally_default[state->tally_default_idx];
_init_val = true;
} }
} }
void tally_face_activate(movement_settings_t *settings, void *context) { void tally_face_activate(movement_settings_t *settings, void *context) {
(void) settings; (void) settings;
(void) context; (void) context;
_quick_ticks_running = false;
}
static void start_quick_cyc(void){
_quick_ticks_running = true;
movement_request_tick_frequency(8);
}
static void stop_quick_cyc(void){
_quick_ticks_running = false;
movement_request_tick_frequency(1);
}
static void tally_face_increment(tally_state_t *state, bool sound_on) {
bool soundOn = !_quick_ticks_running && sound_on;
_init_val = false;
if (state->tally_idx >= TALLY_FACE_MAX){
if (soundOn) watch_buzzer_play_note(BUZZER_NOTE_E7, 30);
}
else {
state->tally_idx++;
print_tally(state, sound_on);
if (soundOn) watch_buzzer_play_note(BUZZER_NOTE_E6, 30);
}
}
static void tally_face_decrement(tally_state_t *state, bool sound_on) {
bool soundOn = !_quick_ticks_running && sound_on;
_init_val = false;
if (state->tally_idx <= TALLY_FACE_MIN){
if (soundOn) watch_buzzer_play_note(BUZZER_NOTE_C5SHARP_D5FLAT, 30);
}
else {
state->tally_idx--;
print_tally(state, sound_on);
if (soundOn) watch_buzzer_play_note(BUZZER_NOTE_C6SHARP_D6FLAT, 30);
}
}
static bool tally_face_should_move_back(tally_state_t *state) {
if (TALLY_FACE_PRESETS_SIZE() <= 1) { return false; }
return state->tally_idx == _tally_default[state->tally_default_idx];
} }
bool tally_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { bool tally_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
(void) settings;
tally_state_t *state = (tally_state_t *)context; tally_state_t *state = (tally_state_t *)context;
static bool using_led = false;
if (using_led) {
if(!watch_get_pin_level(BTN_MODE) && !watch_get_pin_level(BTN_LIGHT) && !watch_get_pin_level(BTN_ALARM))
using_led = false;
else {
if (event.event_type == EVENT_LIGHT_BUTTON_DOWN || event.event_type == EVENT_ALARM_BUTTON_DOWN)
movement_illuminate_led();
return true;
}
}
switch (event.event_type) { switch (event.event_type) {
case EVENT_ALARM_BUTTON_UP: case EVENT_TICK:
// increment tally index if (_quick_ticks_running) {
state->tally_idx++; bool light_pressed = watch_get_pin_level(BTN_LIGHT);
if (state->tally_idx > 999999) { //0-999,999 bool alarm_pressed = watch_get_pin_level(BTN_ALARM);
//reset tally index and play a reset tune if (light_pressed && alarm_pressed) stop_quick_cyc();
state->tally_idx = 0; else if (light_pressed) tally_face_increment(state, settings->bit.button_should_sound);
watch_buzzer_play_note(BUZZER_NOTE_G6, 30); else if (alarm_pressed) tally_face_decrement(state, settings->bit.button_should_sound);
watch_buzzer_play_note(BUZZER_NOTE_REST, 30); else stop_quick_cyc();
} }
print_tally(state); break;
watch_buzzer_play_note(BUZZER_NOTE_E6, 30); case EVENT_ALARM_BUTTON_UP:
tally_face_decrement(state, settings->bit.button_should_sound);
break; break;
case EVENT_ALARM_LONG_PRESS: case EVENT_ALARM_LONG_PRESS:
state->tally_idx = 0; // reset tally index tally_face_decrement(state, settings->bit.button_should_sound);
start_quick_cyc();
break;
case EVENT_MODE_LONG_PRESS:
if (tally_face_should_move_back(state)) {
_init_val = true;
movement_move_to_face(0);
}
else {
state->tally_idx = _tally_default[state->tally_default_idx]; // reset tally index
_init_val = true;
//play a reset tune //play a reset tune
watch_buzzer_play_note(BUZZER_NOTE_G6, 30); if (settings->bit.button_should_sound) watch_buzzer_play_note(BUZZER_NOTE_G6, 30);
watch_buzzer_play_note(BUZZER_NOTE_REST, 30); if (settings->bit.button_should_sound) watch_buzzer_play_note(BUZZER_NOTE_REST, 30);
watch_buzzer_play_note(BUZZER_NOTE_E6, 30); if (settings->bit.button_should_sound) watch_buzzer_play_note(BUZZER_NOTE_E6, 30);
print_tally(state); print_tally(state, settings->bit.button_should_sound);
}
break;
case EVENT_LIGHT_BUTTON_UP:
tally_face_increment(state, settings->bit.button_should_sound);
break;
case EVENT_LIGHT_BUTTON_DOWN:
case EVENT_ALARM_BUTTON_DOWN:
if (watch_get_pin_level(BTN_MODE)) {
movement_illuminate_led();
using_led = true;
}
break;
case EVENT_LIGHT_LONG_PRESS:
if (TALLY_FACE_PRESETS_SIZE() > 1 && _init_val){
state->tally_default_idx = (state->tally_default_idx + 1) % TALLY_FACE_PRESETS_SIZE();
state->tally_idx = _tally_default[state->tally_default_idx];
if (settings->bit.button_should_sound) watch_buzzer_play_note(BUZZER_NOTE_E6, 30);
if (settings->bit.button_should_sound) watch_buzzer_play_note(BUZZER_NOTE_REST, 30);
if (settings->bit.button_should_sound) watch_buzzer_play_note(BUZZER_NOTE_G6, 30);
print_tally(state, settings->bit.button_should_sound);
}
else{
tally_face_increment(state, settings->bit.button_should_sound);
start_quick_cyc();
}
break; break;
case EVENT_ACTIVATE: case EVENT_ACTIVATE:
print_tally(state); print_tally(state, settings->bit.button_should_sound);
break; break;
case EVENT_TIMEOUT: case EVENT_TIMEOUT:
// ignore timeout // ignore timeout
@ -81,9 +196,16 @@ bool tally_face_loop(movement_event_t event, movement_settings_t *settings, void
} }
// print tally index at the center of display. // print tally index at the center of display.
void print_tally(tally_state_t *state) { void print_tally(tally_state_t *state, bool sound_on) {
char buf[14]; char buf[14];
sprintf(buf, "TA %06d", (int)(state->tally_idx)); // center of LCD display if (sound_on)
watch_set_indicator(WATCH_INDICATOR_BELL);
else
watch_clear_indicator(WATCH_INDICATOR_BELL);
if (state->tally_idx >= 0)
sprintf(buf, "TA %4d ", (int)(state->tally_idx)); // center of LCD display
else
sprintf(buf, "TA %-3d", (int)(state->tally_idx)); // center of LCD display
watch_display_string(buf, 0); watch_display_string(buf, 0);
} }

View file

@ -29,25 +29,41 @@
* TALLY face * TALLY face
* *
* Tally face is designed to act as a tally counter. * Tally face is designed to act as a tally counter.
* Based on the counter_face watch face by Shogo Okamoto.
* *
* To advance the counter, press the ALARM button. * Alarm
* To reset, long press the ALARM button. * Press: Decrement
* Hold : Fast Decrement
*
* Light
* Press: Increment
* Hold : On initial value: Cycles through other initial values.
* Else: Fast Increment
*
* Mode
* Press: Next face
* Hold : On initial value: Go to first face.
* Else: Resets counter
*
* Incrementing or Decrementing the tally will beep if Beeping is set in the global Preferences
*/ */
#include "movement.h" #include "movement.h"
typedef struct { typedef struct {
uint32_t tally_idx; int16_t tally_idx;
uint8_t tally_default_idx;
} tally_state_t; } tally_state_t;
//#define TALLY_FACE_PRESETS_MTG
//#define TALLY_FACE_PRESETS_YUGIOH
void tally_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); void tally_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
void tally_face_activate(movement_settings_t *settings, void *context); void tally_face_activate(movement_settings_t *settings, void *context);
bool tally_face_loop(movement_event_t event, movement_settings_t *settings, void *context); bool tally_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
void tally_face_resign(movement_settings_t *settings, void *context); void tally_face_resign(movement_settings_t *settings, void *context);
void print_tally(tally_state_t *state); void print_tally(tally_state_t *state, bool sound_on);
#define tally_face ((const watch_face_t){ \ #define tally_face ((const watch_face_t){ \
tally_face_setup, \ tally_face_setup, \