diff options
| author | Akshay Nair <phenax5@gmail.com> | 2026-02-06 16:46:28 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2026-02-07 17:53:19 +0530 |
| commit | eef689b2e209dcf84c149ee4866c2a007676dc71 (patch) | |
| tree | c814443ad4b19bebe8396d645520ce3db50bc04b /src | |
| parent | d544925cf75a05b681cadfc11b7d8a2d98de6679 (diff) | |
| download | daft-watch-eef689b2e209dcf84c149ee4866c2a007676dc71.tar.gz daft-watch-eef689b2e209dcf84c149ee4866c2a007676dc71.zip | |
Fix timer interrupt priority + refactor
Diffstat (limited to 'src')
| -rw-r--r-- | src/display.c | 44 | ||||
| -rw-r--r-- | src/display.h | 8 | ||||
| -rw-r--r-- | src/main.c | 87 | ||||
| -rw-r--r-- | src/rtc.c | 36 | ||||
| -rw-r--r-- | src/rtc.h | 13 |
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 @@ -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 |
