summaryrefslogtreecommitdiff
path: root/src/c
diff options
context:
space:
mode:
Diffstat (limited to 'src/c')
-rw-r--r--src/c/app.c4
-rw-r--r--src/c/config.c123
-rw-r--r--src/c/config.h26
-rw-r--r--src/c/metronome.c34
-rw-r--r--src/c/metronome.h2
5 files changed, 176 insertions, 13 deletions
diff --git a/src/c/app.c b/src/c/app.c
index 2ce9996..d74c5d3 100644
--- a/src/c/app.c
+++ b/src/c/app.c
@@ -4,6 +4,7 @@
#include <pebble.h>
#include "metronome.h"
+#include "config.h"
static Window *app_window;
static ActionBarLayer *action_bar;
@@ -86,6 +87,8 @@ static void primary_action_bar() {
}
static void init() {
+ config_init();
+
icon_left_arrows = gbitmap_create_with_resource(RESOURCE_ID_LEFT_ARROWS);
icon_right_arrows = gbitmap_create_with_resource(RESOURCE_ID_RIGHT_ARROWS);
icon_plus = gbitmap_create_with_resource(RESOURCE_ID_PLUS);
@@ -104,6 +107,7 @@ static void init() {
}
static void deinit() {
+ config_deinit();
window_destroy(app_window);
}
diff --git a/src/c/config.c b/src/c/config.c
new file mode 100644
index 0000000..0791b85
--- /dev/null
+++ b/src/c/config.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2026 Reiner Herrmann
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <pebble.h>
+#include "config.h"
+#include "metronome.h"
+
+struct Configuration {
+ uint8_t version;
+ uint16_t bpm;
+ uint8_t beats;
+ uint8_t volume;
+ uint8_t beat_indicators;
+} __attribute__((__packed__));
+
+#define SETTINGS_KEY 1
+#define CONFIG_VERSION 1
+
+static struct Configuration configuration;
+
+static void config_persist() {
+ persist_write_data(SETTINGS_KEY, &configuration, sizeof(configuration));
+}
+
+static void config_load_defaults() {
+ configuration.version = CONFIG_VERSION;
+ configuration.bpm = 90;
+ configuration.beats = 4;
+ configuration.volume = 100;
+ configuration.beat_indicators = 0xff;
+}
+
+static void config_load() {
+ config_load_defaults();
+
+ /* buffer remains unchanged if no data is persisted */
+ persist_read_data(SETTINGS_KEY, &configuration, sizeof(configuration));
+
+ if (configuration.version != CONFIG_VERSION) {
+ /* unknown persisted configuration format */
+ config_load_defaults();
+ }
+}
+
+static void config_inbox_received_handler(DictionaryIterator *iter, void *context) {
+ struct Configuration new_configuration;
+ memcpy(&new_configuration, &configuration, sizeof(configuration));
+
+ Tuple *bpm_tuple = dict_find(iter, MESSAGE_KEY_bpm);
+ if (bpm_tuple) {
+ int32_t bpm = bpm_tuple->value->int32;
+ configuration.bpm = (uint16_t) bpm;
+ }
+
+ Tuple *beats_tuple = dict_find(iter, MESSAGE_KEY_beats);
+ if (beats_tuple) {
+ int32_t beats = beats_tuple->value->int32;
+ configuration.beats = (uint8_t) beats;
+ }
+
+ Tuple *volume_tuple = dict_find(iter, MESSAGE_KEY_volume);
+ if (volume_tuple) {
+ int32_t volume = volume_tuple->value->int32;
+ configuration.volume = (uint8_t) volume;
+ }
+
+ const int num_beat_indicators = 3;
+ for (int i=0; i<num_beat_indicators; i++) {
+ Tuple *beat_indicator = dict_find(iter, MESSAGE_KEY_beat_indicators + i);
+ if (beat_indicator) {
+ bool val = beat_indicator->value->uint8;
+ /* clear bit */
+ configuration.beat_indicators &= ~(1 << i);
+ /* set value into bit */
+ configuration.beat_indicators |= (val << i);
+ }
+ }
+
+ if (memcmp(&new_configuration, &configuration, sizeof(configuration)) != 0) {
+ /* only persist if something changed */
+ config_persist();
+
+ update_display();
+ }
+}
+
+void config_init() {
+ config_load();
+
+ app_message_register_inbox_received(config_inbox_received_handler);
+ app_message_open(128, 128);
+}
+
+void config_deinit() {
+ app_message_deregister_callbacks();
+}
+
+uint16_t config_get_bpm() {
+ return configuration.bpm;
+}
+
+void config_set_bpm(uint16_t bpm) {
+ configuration.bpm = bpm;
+ config_persist();
+}
+
+uint8_t config_get_beats() {
+ return configuration.beats;
+}
+
+void config_set_beats(uint8_t beats) {
+ configuration.beats = beats;
+ config_persist();
+}
+
+uint8_t config_get_volume() {
+ return configuration.volume;
+}
+
+bool config_is_indicator_enabled(enum BeatIndicator indicator) {
+ return configuration.beat_indicators & (1 << indicator);
+}
diff --git a/src/c/config.h b/src/c/config.h
new file mode 100644
index 0000000..899c289
--- /dev/null
+++ b/src/c/config.h
@@ -0,0 +1,26 @@
+/* Copyright (C) 2026 Reiner Herrmann
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <pebble.h>
+
+enum BeatIndicator {
+ FLASHING = 0,
+ VIBRATION,
+ BEEP,
+};
+
+void config_init();
+void config_deinit();
+
+uint16_t config_get_bpm();
+void config_set_bpm(uint16_t bpm);
+uint8_t config_get_beats();
+void config_set_beats(uint8_t beats);
+uint8_t config_get_volume();
+bool config_is_indicator_enabled(enum BeatIndicator);
+
+#endif
diff --git a/src/c/metronome.c b/src/c/metronome.c
index f7a5bd3..58fdf18 100644
--- a/src/c/metronome.c
+++ b/src/c/metronome.c
@@ -3,6 +3,7 @@
*/
#include <pebble.h>
+#include "config.h"
static Window *metronome_window;
static Layer *draw_layer;
@@ -11,7 +12,7 @@ static TextLayer *bpm_text;
static AppTimer *beat_timer;
#define BPM_TO_MS(bpm) (60000/(bpm))
-#define IS_FIRST_BEAT() (current_beat % beats == 0)
+#define IS_FIRST_BEAT() (current_beat % config_get_beats() == 0)
#define COLOR_BG GColorWhite
#define COLOR_BG_INV GColorBlack
@@ -20,23 +21,17 @@ static AppTimer *beat_timer;
#define NOTE_C4 60
#define NOTE_C5 72
-static int bpm = 90;
-static int beats = 4;
static int current_beat = -1;
static bool playing = true;
-static bool flash_enabled = true;
-static bool vibrate_enabled = true;
-static bool beep_enabled = true;
-
static void restore_background_color() {
window_set_background_color(metronome_window, COLOR_BG);
}
static void metronome_flash() {
static const int flash_duration = 50;
- if (!flash_enabled) {
+ if (!config_is_indicator_enabled(FLASHING)) {
return;
}
window_set_background_color(metronome_window, COLOR_BG_INV);
@@ -44,7 +39,7 @@ static void metronome_flash() {
}
static void metronome_vibrate() {
- if (!vibrate_enabled) {
+ if (!config_is_indicator_enabled(VIBRATION)) {
return;
}
if (IS_FIRST_BEAT()) {
@@ -57,7 +52,7 @@ static void metronome_vibrate() {
static void metronome_beep() {
#if defined(PBL_SPEAKER)
- if (!beep_enabled || speaker_is_muted()) {
+ if (!config_is_indicator_enabled(BEEP) || speaker_is_muted()) {
return;
}
const SpeakerNote note = {
@@ -67,12 +62,12 @@ static void metronome_beep() {
.velocity = 0,
};
- speaker_play_notes(&note, 1, 0);
+ speaker_play_notes(&note, 1, config_get_volume());
#endif
}
static void beat_timer_callback() {
- beat_timer = app_timer_register(BPM_TO_MS(bpm), beat_timer_callback, NULL);
+ beat_timer = app_timer_register(BPM_TO_MS(config_get_bpm()), beat_timer_callback, NULL);
current_beat++;
@@ -85,11 +80,12 @@ static void beat_timer_callback() {
static void update_bpm_text() {
static char bpm_buf[6];
- snprintf(bpm_buf, sizeof(bpm_buf), "%d", bpm);
+ snprintf(bpm_buf, sizeof(bpm_buf), "%d", config_get_bpm());
text_layer_set_text(bpm_text, bpm_buf);
}
static void beat_indicators_update_proc(Layer *layer, GContext *ctx) {
+ int beats = config_get_beats();
GRect bounds = layer_get_unobstructed_bounds(layer);
const int rect_radius = 10;
@@ -170,36 +166,48 @@ Window *create_metronome_window() {
return metronome_window;
}
+void update_display() {
+ update_bpm_text();
+}
+
void increase_bpm() {
+ uint16_t bpm = config_get_bpm();
bpm++;
if (bpm > 600) {
bpm = 600;
}
+ config_set_bpm(bpm);
APP_LOG(APP_LOG_LEVEL_DEBUG, "increasing bpm to: %d", bpm);
update_bpm_text();
}
void decrease_bpm() {
+ uint16_t bpm = config_get_bpm();
bpm--;
if (bpm <= 0) {
bpm = 0;
}
+ config_set_bpm(bpm);
APP_LOG(APP_LOG_LEVEL_DEBUG, "decreasing bpm to: %d", bpm);
update_bpm_text();
}
void increase_beats() {
+ uint8_t beats = config_get_beats();
beats++;
if (beats > 16) {
beats = 16;
}
+ config_set_beats(beats);
APP_LOG(APP_LOG_LEVEL_DEBUG, "increasing beats to: %d", beats);
}
void decrease_beats() {
+ uint8_t beats = config_get_beats();
beats--;
if (beats < 1) {
beats = 1;
}
+ config_set_beats(beats);
APP_LOG(APP_LOG_LEVEL_DEBUG, "decreasing beats to: %d", beats);
}
diff --git a/src/c/metronome.h b/src/c/metronome.h
index ee9e5f0..15927ff 100644
--- a/src/c/metronome.h
+++ b/src/c/metronome.h
@@ -9,6 +9,8 @@ Window *create_metronome_window();
void beat_timer_callback();
+void update_display();
+
void increase_bpm();
void decrease_bpm();
void increase_beats();