From d544925cf75a05b681cadfc11b7d8a2d98de6679 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Thu, 5 Feb 2026 13:05:52 +0530 Subject: Use timer interrupt for writing to display --- src/display.c | 62 ++++++++++++++++++++------- src/display.h | 4 +- src/main.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 160 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/display.c b/src/display.c index 5f2d7f3..5fccd50 100644 --- a/src/display.c +++ b/src/display.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -12,30 +13,63 @@ const uint32_t digit_masks[] = { 0b00010010, 0b00000010, 0b01111000, 0b00000000, 0b00010000, }; +void setup_display() { + TIMSK1 = 0; + + // Set prescaler (Timer clock = F_CPU / 64) + // For 32768Hz -> 32768/64 = 512Hz + TCCR1B = (1 << CS11) | (1 << CS10) | (1 << WGM12) | (1 << WGM13); + TCCR1A = (1 << WGM11) | (1 << WGM10); + + TCNT1 = 0; // Start counting from 0 + OCR1A = 1; // 0-1 = 2 counts before timer interrupt (512/2 = 256Hz) + OCR1B = 0; + + TIFR1 = (1 << OCF1A) | (1 << OCF1B) | (1 << TOV1); // Clear interrupt flags + TIMSK1 = (1 << OCIE1A); // Enable timer overflow interrupt + + // Draw startup state + DDRA |= 0b11111111; + DDRB |= 0b11111111; + PORTA = (1 << PA7); + PORTB = (1 << PB2); +} + void write_digit(uint8_t digit) { if (digit > 9 || digit < 0) return; PORTA = digit_masks[digit]; } -void write_time(uint16_t hour, uint16_t minute) { +void write_time(uint16_t hour, uint16_t minute, uint8_t mask) { uint8_t minute_digit1 = minute % 10; - uint8_t minute_digit2 = minute / 10; + uint8_t minute_digit2 = (minute / 10) % 10; // unsigned short hour_digit1 = hour % 10; - // unsigned short hour_digit2 = 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) { #ifdef STUBBED - printf("\r:: %d %d", minute_digit2, minute_digit1); - fflush(stdout); + printf(":: %d\n", minute_digit1); + fflush(stdout); #endif + write_digit(minute_digit1); + PORTA |= (1 << PA7); + } - write_digit(minute_digit1); - PORTA |= (1 << PA7); - _delay_ms(10); - PORTA &= ~(1 << PA7); - - write_digit(minute_digit2); - PORTB |= (1 << PB2); - _delay_ms(10); - PORTB &= ~(1 << PB2); + if (mask & 0b0010 || mask & 0b1000) { +#ifdef STUBBED + printf(":: %d\n", minute_digit2); + fflush(stdout); +#endif + write_digit(minute_digit2); + PORTB |= (1 << PB2); + } + // sei(); } diff --git a/src/display.h b/src/display.h index a2bbc79..167374a 100644 --- a/src/display.h +++ b/src/display.h @@ -2,8 +2,10 @@ #define _LOADED_DISPLAY #include +void setup_display(); + void write_digit(uint8_t digit); -void write_time(uint16_t hour, uint16_t minute); +void write_time(uint16_t hour, uint16_t minute, uint8_t digit_mask); #endif diff --git a/src/main.c b/src/main.c index fd4a091..b3fa431 100644 --- a/src/main.c +++ b/src/main.c @@ -1,45 +1,130 @@ +#include #include -#include +#include #include #include #include "display.h" -// Config for attiny84a + 32KHz crystal osc taken from https://github.com/ingepnet/breadboardwatch/blob/master/Makefile#L26 +// Config for attiny84a + external 32KHz crystal osc taken from +// https://github.com/ingepnet/breadboardwatch/blob/master/Makefile#L26 +#include FUSES = { - .low = 0xe6, - .high = 0xd7, - .extended = 0xff, + .low = 0xe6, + .high = 0xd7, + .extended = 0xff, }; -void setup_output(void) { +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); + } + + digit_mask = digit_mask << 1; + if (digit_mask > 0b1000) + digit_mask = 0b0001; +} + +#define IS_BUTTON_ON() ((PINA & (1 << PA0)) == 0) +#define ENABLE_BUTTON() (DDRA &= ~(1 << PA0)) + int main(void) { - uint32_t count = 0; - uint8_t is_button_on = 0; + PRR = 0b0011; // Power reduction register. Shut down USI and ADC + + setup_rtc(); + setup_display(); + + sei(); + + set_all_pins_output(); while (1) { - DDRB &= ~(1 << PB2); - is_button_on = (PINB & (1 << PB2)) > 0; - - if (is_button_on) { - _delay_ms(30); - is_button_on = (PINB & (1 << PB2)) > 0; - if (is_button_on) { - setup_output(); - PORTA |= 0b10000000; - _delay_ms(500); - continue; - } - } + // 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; - setup_output(); - write_time(0, (count / 20) % 60); + // ENABLE_BUTTON(); + // if (IS_BUTTON_ON()) { + // cli(); + // ENABLE_BUTTON(); + // _delay_ms(25); // Debounced + // if (IS_BUTTON_ON()) { + // seconds += 1; + // sei(); + // _delay_ms(50); + // continue; + // } + // } + // sei(); - count = (count + 1) % 100000; +#ifdef STUBBED + stub_run_timers(); + _delay_ms(100); +#endif } + return 0; } -- cgit v1.3.1