aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2026-02-06 16:46:28 +0530
committerAkshay Nair <phenax5@gmail.com>2026-02-07 17:53:19 +0530
commiteef689b2e209dcf84c149ee4866c2a007676dc71 (patch)
treec814443ad4b19bebe8396d645520ce3db50bc04b /src
parentd544925cf75a05b681cadfc11b7d8a2d98de6679 (diff)
downloaddaft-watch-eef689b2e209dcf84c149ee4866c2a007676dc71.tar.gz
daft-watch-eef689b2e209dcf84c149ee4866c2a007676dc71.zip
Fix timer interrupt priority + refactor
Diffstat (limited to 'src')
-rw-r--r--src/display.c44
-rw-r--r--src/display.h8
-rw-r--r--src/main.c87
-rw-r--r--src/rtc.c36
-rw-r--r--src/rtc.h13
5 files changed, 90 insertions, 98 deletions
diff --git a/src/display.c b/src/display.c
index 5fccd50..8de5043 100644
--- a/src/display.c
+++ b/src/display.c
@@ -4,6 +4,7 @@
#include <util/delay.h>
#include "display.h"
+#include "rtc.h"
// "_gfedcba"
// Reversed because a-g is mapped to pa0-6. (pa7 is decimal)
@@ -13,20 +14,18 @@ const uint32_t digit_masks[] = {
0b00010010, 0b00000010, 0b01111000, 0b00000000, 0b00010000,
};
-void setup_display() {
- TIMSK1 = 0;
-
- // Set prescaler (Timer clock = F_CPU / 64)
+void display_setup() {
+ // Set prescaler CS01 + CS00 (F_CPU / 64) + CTC
// For 32768Hz -> 32768/64 = 512Hz
- TCCR1B = (1 << CS11) | (1 << CS10) | (1 << WGM12) | (1 << WGM13);
- TCCR1A = (1 << WGM11) | (1 << WGM10);
+ TCCR0B = (1 << CS01) | (1 << CS00) | (1 << WGM02);
+ TCCR0A = (1 << WGM01) | (1 << WGM00);
- TCNT1 = 0; // Start counting from 0
- OCR1A = 1; // 0-1 = 2 counts before timer interrupt (512/2 = 256Hz)
- OCR1B = 0;
+ TCNT0 = 0; // Start counting from 0
+ OCR0A = 1; // 0-1 = 2 counts before timer interrupt (512/2 = 256Hz)
+ OCR0B = 0;
- TIFR1 = (1 << OCF1A) | (1 << OCF1B) | (1 << TOV1); // Clear interrupt flags
- TIMSK1 = (1 << OCIE1A); // Enable timer overflow interrupt
+ TIFR0 = (1 << OCF0A) | (1 << OCF0B) | (1 << TOV0); // Clear interrupt flags
+ TIMSK0 = (1 << OCIE0A); // Enable timer overflow interrupt
// Draw startup state
DDRA |= 0b11111111;
@@ -35,6 +34,19 @@ void setup_display() {
PORTB = (1 << PB2);
}
+volatile uint8_t current_digit = 0;
+
+// Render current digit
+void display_render(void) {
+ DDRA |= 0b11111111;
+ DDRB |= 0b11111111;
+
+ write_time(minutes, seconds, current_digit);
+
+ // Next digit
+ current_digit = (current_digit + 1) % 4;
+}
+
void write_digit(uint8_t digit) {
if (digit > 9 || digit < 0)
return;
@@ -47,25 +59,23 @@ void write_time(uint16_t hour, uint16_t minute, uint8_t mask) {
// unsigned short hour_digit1 = hour % 10;
// unsigned short hour_digit2 = (hour / 10) % 10;
- // _delay_ms(4);
// Reset digit control pins
PORTA &= ~(1 << PA7); // minute digit 1
PORTB &= ~(1 << PB2); // minute digit 2
- // _delay_ms(4);
// cli();
- if (mask & 0b0001 || mask & 0b0100) {
+ if (mask == 0 || mask == 2) {
#ifdef STUBBED
- printf(":: %d\n", minute_digit1);
+ printf(" %d\n", minute_digit1);
fflush(stdout);
#endif
write_digit(minute_digit1);
PORTA |= (1 << PA7);
}
- if (mask & 0b0010 || mask & 0b1000) {
+ if (mask == 1 || mask == 3) {
#ifdef STUBBED
- printf(":: %d\n", minute_digit2);
+ printf(":: %d", minute_digit2);
fflush(stdout);
#endif
write_digit(minute_digit2);
diff --git a/src/display.h b/src/display.h
index 167374a..34a065d 100644
--- a/src/display.h
+++ b/src/display.h
@@ -2,10 +2,14 @@
#define _LOADED_DISPLAY
#include <stdint.h>
-void setup_display();
+volatile extern uint8_t current_digit;
+
+void display_setup(void);
void write_digit(uint8_t digit);
void write_time(uint16_t hour, uint16_t minute, uint8_t digit_mask);
-#endif
+void display_render(void);
+
+#endif \ No newline at end of file
diff --git a/src/main.c b/src/main.c
index b3fa431..cf6f7a8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,10 +1,10 @@
#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdbool.h>
-#include <stdint.h>
#include <util/delay.h>
#include "display.h"
+#include "rtc.h"
// Config for attiny84a + external 32KHz crystal osc taken from
// https://github.com/ingepnet/breadboardwatch/blob/master/Makefile#L26
@@ -15,68 +15,13 @@ FUSES = {
.extended = 0xff,
};
-void set_all_pins_output(void) {
- DDRA |= 0b11111111;
- DDRB |= 0b11111111;
-}
-
-void setup_rtc() {
- // Set prescaler (Timer clock = F_CPU / 1024)
- // For 32768Hz -> 32768/1024 = 32Hz
- TCCR0B = (1 << CS02) | (1 << CS00) | (1 << WGM02);
- TCCR0A = (1 << WGM01) | (1 << WGM00);
-
- TCNT0 = 0; // Start counting from 0
- OCR0A = 31; // 0-31 = 32 counts before timer interrupt (1Hz)
- OCR0B = 0;
-
- // TIFR0 = (1 << TOV0); // Clear interrupt flags
- TIFR0 = (1 << OCF0A) | (1 << OCF0B) | (1 << TOV0); // Clear interrupt flags
- // TIMSK0 = (1 << TOIE0); // Enable timer overflow interrupt
- TIMSK0 = (1 << OCIE0A); // Enable timer overflow interrupt
-}
-
-volatile uint8_t seconds = 10;
-volatile uint8_t minutes = 0;
-volatile uint8_t hours = 0;
-// Clock
-ISR(TIM0_COMPA_vect, ISR_FLATTEN) {
- // if (true) {
- // OCR0A = 32;
- // } else if (true) {
- // OCR0A = 31;
- // } else {
- // OCR0A = 30;
- // }
-
- uint8_t s = seconds + 1;
- seconds = s % 60;
- if (s >= 60) {
- uint8_t m = minutes + 1;
- minutes = m % 60;
- if (m >= 60) {
- hours = (hours + 1) % 24;
- }
- }
-}
-
-volatile static uint8_t digit_mask = 0b0001;
// Display
-ISR(TIM1_COMPA_vect, ISR_FLATTEN) {
- set_all_pins_output();
- write_time(minutes, seconds, digit_mask);
- if (seconds % 2) {
- PORTA &= ~(1 << PA5);
- PORTB &= ~(1 << PB3);
- } else {
- PORTA |= (1 << PA5);
- PORTB |= (1 << PB3);
- }
+// timer 0 has lower priority than timer 1, so some ticks could get skipped due
+// to interrupt starvation
+ISR(TIM0_COMPA_vect, ISR_FLATTEN) { display_render(); }
- digit_mask = digit_mask << 1;
- if (digit_mask > 0b1000)
- digit_mask = 0b0001;
-}
+// RTC interrupt
+ISR(TIM1_COMPA_vect, ISR_FLATTEN) { rtc_increment(); }
#define IS_BUTTON_ON() ((PINA & (1 << PA0)) == 0)
#define ENABLE_BUTTON() (DDRA &= ~(1 << PA0))
@@ -84,28 +29,12 @@ ISR(TIM1_COMPA_vect, ISR_FLATTEN) {
int main(void) {
PRR = 0b0011; // Power reduction register. Shut down USI and ADC
- setup_rtc();
- setup_display();
+ display_setup();
+ rtc_setup();
sei();
- set_all_pins_output();
-
while (1) {
- // cli();
- // set_all_pins_output();
- // write_time(minutes, seconds, digit_mask);
- // if (seconds % 2) {
- // PORTA &= ~(1 << PA5);
- // PORTB &= ~(1 << PB3);
- // } else {
- // PORTA |= (1 << PA5);
- // PORTB |= (1 << PB3);
- // }
- // digit_mask = digit_mask << 1;
- // if (digit_mask > 0b1000)
- // digit_mask = 0b0001;
-
// ENABLE_BUTTON();
// if (IS_BUTTON_ON()) {
// cli();
diff --git a/src/rtc.c b/src/rtc.c
new file mode 100644
index 0000000..1ac50c3
--- /dev/null
+++ b/src/rtc.c
@@ -0,0 +1,36 @@
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <stdint.h>
+#include <util/delay.h>
+
+#include "rtc.h"
+
+void rtc_setup(void) {
+ // Set prescaler CS12 + CS10 (F_CPU / 1024) + CTC
+ // For 32768Hz -> 32768/1024 = 32Hz
+ TCCR1B = (1 << CS12) | (1 << CS10) | (1 << WGM12) | (1 << WGM13);
+ TCCR1A = (1 << WGM11) | (1 << WGM10);
+
+ TCNT1 = 0; // Start counting from 0
+ OCR1A = 31; // 0-31 = 32 counts before timer interrupt (1Hz)
+ OCR1B = 0;
+
+ TIFR1 = (1 << OCF1A) | (1 << OCF1B) | (1 << TOV1); // Clear interrupt flags
+ TIMSK1 = (1 << OCIE1A); // Enable timer overflow interrupt
+}
+
+volatile uint8_t seconds = 10;
+volatile uint8_t minutes = 0;
+volatile uint8_t hours = 0;
+
+void rtc_increment(void) {
+ uint8_t s = seconds + 1;
+ seconds = s % 60;
+ if (s >= 60) {
+ uint8_t m = minutes + 1;
+ minutes = m % 60;
+ if (m >= 60) {
+ hours = (hours + 1) % 24;
+ }
+ }
+}
diff --git a/src/rtc.h b/src/rtc.h
new file mode 100644
index 0000000..f3f8f9c
--- /dev/null
+++ b/src/rtc.h
@@ -0,0 +1,13 @@
+#ifndef _LOADED_RTC
+#define _LOADED_RTC
+#include <stdint.h>
+
+volatile extern uint8_t seconds;
+volatile extern uint8_t minutes;
+volatile extern uint8_t hours;
+
+void rtc_setup(void);
+
+void rtc_increment(void);
+
+#endif