aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2026-02-05 13:05:52 +0530
committerAkshay Nair <phenax5@gmail.com>2026-02-06 15:35:15 +0530
commitd544925cf75a05b681cadfc11b7d8a2d98de6679 (patch)
tree5f563d5c3ac368ff7893cfd90c256afbf4b2d5e2
parenta40d8f331ba5b7ea239b35714eaa1cff504a086b (diff)
downloaddaft-watch-d544925cf75a05b681cadfc11b7d8a2d98de6679.tar.gz
daft-watch-d544925cf75a05b681cadfc11b7d8a2d98de6679.zip
Use timer interrupt for writing to display
-rw-r--r--src/display.c62
-rw-r--r--src/display.h4
-rw-r--r--src/main.c133
3 files changed, 160 insertions, 39 deletions
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 <avr/interrupt.h>
#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
@@ -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 <stdint.h>
+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 <avr/interrupt.h>
#include <avr/io.h>
-#include <avr/fuse.h>
+#include <stdbool.h>
#include <stdint.h>
#include <util/delay.h>
#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 <avr/fuse.h>
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;
}
-int main(void) {
- uint32_t count = 0;
- uint8_t is_button_on = 0;
+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);
- while (1) {
- DDRB &= ~(1 << PB2);
- is_button_on = (PINB & (1 << PB2)) > 0;
+ 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
+}
- 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;
- }
+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);
+ }
- setup_output();
- write_time(0, (count / 20) % 60);
+ 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) {
+ PRR = 0b0011; // Power reduction register. Shut down USI and ADC
+
+ setup_rtc();
+ setup_display();
+
+ sei();
- count = (count + 1) % 100000;
+ 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();
+ // ENABLE_BUTTON();
+ // _delay_ms(25); // Debounced
+ // if (IS_BUTTON_ON()) {
+ // seconds += 1;
+ // sei();
+ // _delay_ms(50);
+ // continue;
+ // }
+ // }
+ // sei();
+
+#ifdef STUBBED
+ stub_run_timers();
+ _delay_ms(100);
+#endif
}
+
return 0;
}