aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2026-02-28 17:37:19 +0530
committerAkshay Nair <phenax5@gmail.com>2026-02-28 17:37:19 +0530
commit18268280dc6c0bd44035b53655ae43e9c88245bd (patch)
treec17b1703d8a3deb4cd67a6e6466d024f02a49bb7 /src
parent02c12bfedcf669df81491ea49502a982e980bcda (diff)
downloaddaft-watch-18268280dc6c0bd44035b53655ae43e9c88245bd.tar.gz
daft-watch-18268280dc6c0bd44035b53655ae43e9c88245bd.zip
Add set time mode + test for button
Diffstat (limited to 'src')
-rw-r--r--src/button.c51
-rw-r--r--src/button.h17
-rw-r--r--src/display.c34
-rw-r--r--src/display.h14
-rw-r--r--src/main.c2
-rw-r--r--src/mode.c74
-rw-r--r--src/mode.h22
-rw-r--r--src/rtc.c23
-rw-r--r--src/rtc.h4
9 files changed, 177 insertions, 64 deletions
diff --git a/src/button.c b/src/button.c
index dc52265..f7c2a07 100644
--- a/src/button.c
+++ b/src/button.c
@@ -2,42 +2,27 @@
#include <stdint.h>
#include "button.h"
-#include "rtc.h"
+#include "mode.h"
-enum ButtonState check_button_state();
-
-void button_tick() {
- enum ButtonState button_state = check_button_state();
- switch (button_state) {
- case BUTTON_PRESSED:
- if (seconds <= 10)
- seconds = 0;
- else
- seconds -= 10;
- break;
- case BUTTON_LONG_PRESSED:
- seconds += 10;
- break;
- default:
- break;
- }
-}
+void button_tick() { apply_button_state(check_button_state()); }
bool is_button_active = false;
uint16_t button_tick_count = 0;
+uint16_t button_inactive_for_ticks = 0;
enum ButtonState check_button_state() {
- if (is_button_active && button_tick_count >= LONG_PRESS_TICK_COUNT) {
- button_tick_count = 0;
- is_button_active = false;
- return BUTTON_LONG_PRESSED;
+ // Disable button for some time
+ if (button_inactive_for_ticks > 0) {
+ button_inactive_for_ticks--;
+ return ButtonIdle;
}
- bool in_debounce_period = is_button_active && button_tick_count > 0 &&
- button_tick_count < DEBOUNCE_TICK_COUNT;
+ bool was_active = is_button_active;
+ bool in_debounce_period =
+ button_tick_count > 0 && button_tick_count < DEBOUNCE_TICK_COUNT;
// Ignore readings from debounce period
- if (!in_debounce_period) {
+ if (!is_button_active || !in_debounce_period) {
DDRA &= ~(1 << PA0);
PORTA &= ~(1 << PA0);
is_button_active = (PINA & (1 << PA0)) == 0;
@@ -45,12 +30,22 @@ enum ButtonState check_button_state() {
if (is_button_active) {
button_tick_count++;
+ if (button_tick_count >= LONG_PRESS_TICK_COUNT) {
+ button_tick_count = 0;
+ is_button_active = false;
+ button_inactive_for_ticks = BUTTON_INACTIVE_TICK_COUNT;
+ return ButtonLongPressed;
+ }
+ return ButtonActive;
} else {
if (button_tick_count >= DEBOUNCE_TICK_COUNT) {
button_tick_count = 0;
- return BUTTON_PRESSED;
+ button_inactive_for_ticks = BUTTON_INACTIVE_TICK_COUNT;
+ return ButtonPressed;
}
+ if (!was_active)
+ button_tick_count = 0;
}
- return BUTTON_IDLE;
+ return ButtonIdle;
}
diff --git a/src/button.h b/src/button.h
index 8aa7442..5152336 100644
--- a/src/button.h
+++ b/src/button.h
@@ -1,19 +1,22 @@
#ifndef _LOADED_BUTTON
#define _LOADED_BUTTON
#include <stdbool.h>
-#include <stdint.h>
+
+#include "mode.h"
#define DEBOUNCE_TICK_COUNT 10
#define LONG_PRESS_TICK_COUNT 60
#define MAX_TICK_COUNT 80
+#define BUTTON_INACTIVE_TICK_COUNT 10
+
+bool extern is_button_active;
-enum ButtonState {
- BUTTON_IDLE = 0,
- BUTTON_PRESSED = 1,
- BUTTON_LONG_PRESSED = 2,
-};
+void button_tick();
+enum ButtonState check_button_state();
+
+// Exposed for test
uint16_t extern button_tick_count;
+uint16_t extern button_inactive_for_ticks;
-void button_tick();
#endif
diff --git a/src/display.c b/src/display.c
index 8380b81..3d83337 100644
--- a/src/display.c
+++ b/src/display.c
@@ -4,8 +4,17 @@
#include <util/delay.h>
#include "display.h"
+#include "mode.h"
#include "rtc.h"
+// "_gfedcba"
+// Reversed because a-g is mapped to pa0-6. (pa7 is decimal)
+// Complemented because display is common anode
+static const uint32_t digit_masks[] = {
+ 0b1000000, 0b1111001, 0b0100100, 0b0110000, 0b0011001,
+ 0b0010010, 0b0000010, 0b1111000, 0b0000000, 0b0010000,
+};
+
void display_setup() {
// Set prescaler CS01 + CS00 (F_CPU / 64) + CTC
// For 32768Hz -> 32768/64 = 512Hz
@@ -26,11 +35,27 @@ void display_setup() {
PORTB = (1 << PB2);
}
+void write_time(uint8_t digit_index, const uint8_t digits[4]);
+
+// Current digit position
volatile uint8_t current_digit = 0;
// Render current digit
void display_render(void) {
- write_time(current_digit);
+ switch (current_mode) {
+ case ModeDisplayTime: {
+ uint8_t digits[] = {minutes_digit1, minutes_digit2, seconds_digit1,
+ seconds_digit2};
+ write_time(current_digit, digits);
+ break;
+ }
+ case ModeSetTime: {
+ uint8_t digits[] = {new_hours / 10, new_hours % 10, new_minutes / 10,
+ new_minutes % 10};
+ write_time(current_digit, digits);
+ break;
+ }
+ }
// Cycle through the 4 digits
current_digit = (current_digit + 1) % 4;
@@ -53,14 +78,11 @@ static uint8_t special_segment_pins[] = {5, 10, 6, 7};
// Digit position -> special segment anti-pin (pair of pin)
static uint8_t special_segment_antipins[] = {10, 5, 7, 6};
-void write_time(uint8_t digit_index) {
+void write_time(uint8_t digit_index, const uint8_t digits[4]) {
// reset pins
uint16_t ddr = ~SPECIAL_SEGMENT_PINS;
uint16_t port = 0;
- uint8_t digits[] = {seconds_digit1, seconds_digit2, minutes_digit1,
- minutes_digit2};
-
uint8_t digit = digits[digit_index];
uint16_t segments = digit_masks[digit];
uint8_t pin = special_segment_pins[digit_index];
@@ -92,7 +114,7 @@ void write_time(uint8_t digit_index) {
}
DDRA = ddr;
- DDRB = ddr >> 8;
PORTA = port;
+ DDRB = ddr >> 8;
PORTB = port >> 8;
}
diff --git a/src/display.h b/src/display.h
index 44c0c0e..0353705 100644
--- a/src/display.h
+++ b/src/display.h
@@ -1,22 +1,8 @@
#ifndef _LOADED_DISPLAY
#define _LOADED_DISPLAY
-#include <stdint.h>
-
-// "_gfedcba"
-// Reversed because a-g is mapped to pa0-6. (pa7 is decimal)
-// Complemented because display is common anode
-static const uint32_t digit_masks[] = {
- 0b1000000, 0b1111001, 0b0100100, 0b0110000, 0b0011001,
- 0b0010010, 0b0000010, 0b1111000, 0b0000000, 0b0010000,
-};
-
-// Current digit position
-volatile extern uint8_t current_digit;
void display_setup(void);
-void write_time(uint8_t digit_index);
-
void display_render(void);
#endif
diff --git a/src/main.c b/src/main.c
index 98b63a2..2e20b7b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -28,7 +28,7 @@ ISR(TIM0_COMPA_vect, ISR_FLATTEN) {
ISR(TIM1_COMPA_vect, ISR_FLATTEN) { rtc_increment(); }
// Button interrupt
-ISR(PCINT0_vect, ISR_FLATTEN) { button_tick(); }
+// ISR(PCINT0_vect, ISR_FLATTEN) { button_tick(); }
int main(void) {
PRR = 0b0011; // Power reduction register. Shut down USI and ADC
diff --git a/src/mode.c b/src/mode.c
new file mode 100644
index 0000000..b6fad97
--- /dev/null
+++ b/src/mode.c
@@ -0,0 +1,74 @@
+#include <stdint.h>
+
+#include "mode.h"
+#include "rtc.h"
+
+enum Mode current_mode = ModeDisplayTime;
+volatile uint8_t new_minutes = 0;
+volatile uint8_t new_hours = 0;
+volatile uint8_t current_digit_index = 0;
+volatile uint16_t time_set_timeout_ticks = 0;
+
+void increment_digit() {
+ switch (current_digit_index) {
+ case 0:
+ new_hours = (new_hours + 10) % 24;
+ break;
+ case 1:
+ new_hours = (new_hours + 1) % 24;
+ break;
+ case 2:
+ new_minutes = (new_minutes + 10) % 60;
+ break;
+ case 3:
+ new_minutes = (new_minutes + 1) % 60;
+ break;
+ }
+}
+
+void apply_button_state(enum ButtonState button_state) {
+ switch (current_mode) {
+ case ModeDisplayTime:
+ switch (button_state) {
+ case ButtonLongPressed:
+ new_minutes = minutes;
+ new_hours = hours;
+ current_digit_index = 0;
+ current_mode = ModeSetTime;
+ break;
+ default:
+ break;
+ }
+ break;
+ case ModeSetTime:
+ if (button_state == ButtonIdle) {
+ time_set_timeout_ticks =
+ time_set_timeout_ticks == 0 ? 0 : time_set_timeout_ticks - 1;
+ if (time_set_timeout_ticks == 0) {
+ current_mode = ModeDisplayTime;
+ return;
+ }
+ } else {
+ time_set_timeout_ticks = 10 * 1024;
+ }
+
+ switch (button_state) {
+ case ButtonPressed:
+ increment_digit();
+ break;
+ case ButtonLongPressed:
+ if (current_digit_index == 3) {
+ rtc_set_minutes(new_minutes);
+ rtc_set_hours(new_hours);
+ current_mode = ModeDisplayTime;
+ current_digit_index = 0;
+ } else {
+ current_digit_index++;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+}
diff --git a/src/mode.h b/src/mode.h
new file mode 100644
index 0000000..db65fc8
--- /dev/null
+++ b/src/mode.h
@@ -0,0 +1,22 @@
+#ifndef _LOADED_MODE
+#define _LOADED_MODE
+#include <stdint.h>
+enum Mode {
+ ModeDisplayTime,
+ ModeSetTime,
+};
+
+enum ButtonState {
+ ButtonIdle = 0,
+ ButtonActive = 1,
+ ButtonPressed = 2,
+ ButtonLongPressed = 3,
+};
+
+extern enum Mode current_mode;
+extern volatile uint8_t new_minutes;
+extern volatile uint8_t new_hours;
+
+void apply_button_state(enum ButtonState button_state);
+
+#endif
diff --git a/src/rtc.c b/src/rtc.c
index 53a5983..bbf79e1 100644
--- a/src/rtc.c
+++ b/src/rtc.c
@@ -38,13 +38,20 @@ void rtc_increment(void) {
seconds_digit2 = (seconds / 10) % 10;
if (s >= 60) {
uint8_t m = minutes + 1;
- minutes = m % 60;
- minutes_digit1 = minutes % 10;
- minutes_digit2 = (minutes / 10) % 10;
- if (m >= 60) {
- hours = (hours + 1) % 24;
- hours_digit1 = hours % 10;
- hours_digit2 = (hours / 10) % 10;
- }
+ rtc_set_minutes(m);
+ if (m >= 60)
+ rtc_set_hours(hours + 1);
}
}
+
+void rtc_set_minutes(uint8_t m) {
+ minutes = m % 60;
+ minutes_digit1 = minutes % 10;
+ minutes_digit2 = (minutes / 10) % 10;
+}
+
+void rtc_set_hours(uint8_t h) {
+ hours = h % 24;
+ hours_digit1 = hours % 10;
+ hours_digit2 = (hours / 10) % 10;
+}
diff --git a/src/rtc.h b/src/rtc.h
index c1c1730..991c188 100644
--- a/src/rtc.h
+++ b/src/rtc.h
@@ -17,4 +17,8 @@ void rtc_setup(void);
void rtc_increment(void);
+void rtc_set_minutes(uint8_t m);
+
+void rtc_set_hours(uint8_t h);
+
#endif