aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2026-02-04 11:04:04 +0530
committerAkshay Nair <phenax5@gmail.com>2026-02-04 12:55:37 +0530
commitcc9d915435a61d71f11cffa264cf941de58fe444 (patch)
treedc190a76b952e26942c298745f5321c5fb0d95ac
parentf0423ae9af947512f5200da1ffd3c5adf81d5d7f (diff)
downloaddaft-watch-cc9d915435a61d71f11cffa264cf941de58fe444.tar.gz
daft-watch-cc9d915435a61d71f11cffa264cf941de58fe444.zip
Switch from internal clock to crystal + button
-rw-r--r--compile_flags.txt2
-rw-r--r--justfile28
-rw-r--r--src/display.c41
-rw-r--r--src/display.h9
-rw-r--r--src/main.c66
-rw-r--r--test/stubbed/avr/fuse.h12
-rw-r--r--test/stubbed/avr/io.h42
-rw-r--r--test/stubbed/util/delay.h6
8 files changed, 140 insertions, 66 deletions
diff --git a/compile_flags.txt b/compile_flags.txt
index 8720d77..2ec992d 100644
--- a/compile_flags.txt
+++ b/compile_flags.txt
@@ -3,7 +3,7 @@
-std=gnu99
-Isrc
-mmcu=attiny84a
--DF_CPU=1000000L
+-DF_CPU=32768L
-I/nix/store/ivhsczriimr31rrmly0bcj03gv4qa3q7-avr-libc-avr-2.2.1/avr/include
-L/nix/store/ivhsczriimr31rrmly0bcj03gv4qa3q7-avr-libc-avr-2.2.1/avr/lib
-funsigned-char
diff --git a/justfile b/justfile
index a7f3d12..575afa9 100644
--- a/justfile
+++ b/justfile
@@ -5,10 +5,10 @@ default:
just --choose || true
AVR_LIBC := env("AVR_LIBC", "/usr/lib/avr")
-F_CPU := "1000000"
+F_CPU := "32768"
MCU := "attiny84a"
MCU_PART := "attiny84"
-SRC := "./src/main.c"
+SRCS := "./src/main.c ./src/display.c"
OUTDIR := "./out"
PROGRAMMER := "arduino"
UPLOAD_SPEED := "19200"
@@ -18,23 +18,30 @@ CFLAGS := f"-g -Os -std=gnu99 -Isrc -mmcu={{MCU}} -DF_CPU={{F_CPU}}L \
-I{{AVR_LIBC}}/avr/include -L{{AVR_LIBC}}/avr/lib \
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall"
-AVRDUDE := f"avrdude -v -p {{MCU_PART}} -c {{PROGRAMMER}} -P {{SERIAL_PORT}} -b {{UPLOAD_SPEED}}"
+AVRDUDE := f"avrdude -v -p {{MCU_PART}} -c {{PROGRAMMER}} -P {{SERIAL_PORT}} -b {{UPLOAD_SPEED}} -F"
-build: compile_flags
+build: compile-flags
mkdir -p {{OUTDIR}}
- avr-gcc {{CFLAGS}} {{SRC}} -o {{OUTDIR}}/out.elf
+ avr-gcc {{CFLAGS}} {{SRCS}} -o {{OUTDIR}}/out.elf
avr-objcopy -O ihex -R .eeprom {{OUTDIR}}/out.elf {{OUTDIR}}/out.hex
du -bh "{{OUTDIR}}/out.hex"
-write:
- [ -f "{{OUTDIR}}/out.hex" ] || (echo "No out.hex. Run build"; exit 1);
+write: build flash
+
+flash: check-hexfile-exists
{{AVRDUDE}} -U "flash:w:{{OUTDIR}}/out.hex:i"
read:
{{AVRDUDE}} -F -U flash:r:-:h
+write-fuses: check-hexfile-exists
+ {{AVRDUDE}} -U lfuse:w:{{OUTDIR}}/out.elf:e -U hfuse:w:{{OUTDIR}}/out.elf:e -U efuse:w:{{OUTDIR}}/out.elf:e
+
+read-fuse:
+ {{AVRDUDE}} -U lfuse:r:-:h -U hfuse:r:-:h
+
test:
- gcc -g -std=gnu99 -Isrc -DF_CPU={{F_CPU}}L -DSTUBBED=1 -I./test/stubbed/ -Wall {{SRC}} -o {{OUTDIR}}/test
+ gcc -g -std=gnu99 -DSTUBBED=1 -I./src -I./test/stubbed/ -Wall -Wno-unused-variable {{SRCS}} -o {{OUTDIR}}/test
{{OUTDIR}}/test
clean:
@@ -43,5 +50,8 @@ clean:
format:
find src/ -iname '*.h' -o -iname '*.c' | xargs clang-format -i
-@compile_flags:
+@check-hexfile-exists:
+ [ -f "{{OUTDIR}}/out.hex" ] || (echo "No out.hex. Run build first"; exit 1);
+
+@compile-flags:
echo '{{CFLAGS}}' | tr ' ' '\n' > ./compile_flags.txt
diff --git a/src/display.c b/src/display.c
new file mode 100644
index 0000000..5f2d7f3
--- /dev/null
+++ b/src/display.c
@@ -0,0 +1,41 @@
+#include <avr/io.h>
+#include <stdint.h>
+#include <util/delay.h>
+
+#include "display.h"
+
+// "_gfedcba"
+// Reversed because a-g is mapped to pa0-6. (pa7 is decimal)
+// Complemented because display is common anode
+const uint32_t digit_masks[] = {
+ 0b01000000, 0b01111001, 0b00100100, 0b00110000, 0b00011001,
+ 0b00010010, 0b00000010, 0b01111000, 0b00000000, 0b00010000,
+};
+
+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) {
+ uint8_t minute_digit1 = minute % 10;
+ uint8_t minute_digit2 = minute / 10;
+ // unsigned short hour_digit1 = hour % 10;
+ // unsigned short hour_digit2 = hour / 10;
+
+#ifdef STUBBED
+ printf("\r:: %d %d", minute_digit2, minute_digit1);
+ fflush(stdout);
+#endif
+
+ 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);
+}
diff --git a/src/display.h b/src/display.h
new file mode 100644
index 0000000..a2bbc79
--- /dev/null
+++ b/src/display.h
@@ -0,0 +1,9 @@
+#ifndef _LOADED_DISPLAY
+#define _LOADED_DISPLAY
+#include <stdint.h>
+
+void write_digit(uint8_t digit);
+
+void write_time(uint16_t hour, uint16_t minute);
+
+#endif
diff --git a/src/main.c b/src/main.c
index c1dc647..fd4a091 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,51 +1,45 @@
#include <avr/io.h>
+#include <avr/fuse.h>
#include <stdint.h>
#include <util/delay.h>
-// a b c d e f g decimal
-// Reversed because a-g is mapped to pa0-6. (pa7 is decimal)
-// Complemented because display is common anode
-const uint32_t digits[] = {
- 0b01000000, 0b01111001, 0b00100100, 0b00110000, 0b00011001,
- 0b00010010, 0b00000010, 0b01111000, 0b00000000, 0b00010000,
+#include "display.h"
+
+// Config for attiny84a + 32KHz crystal osc taken from https://github.com/ingepnet/breadboardwatch/blob/master/Makefile#L26
+FUSES = {
+ .low = 0xe6,
+ .high = 0xd7,
+ .extended = 0xff,
};
-void write_digit(uint8_t digit) {
- if (digit > 9 || digit < 0)
- return;
- PORTA = digits[digit];
+void setup_output(void) {
+ DDRA |= 0b11111111;
+ DDRB |= 0b11111111;
}
-void write_time(uint16_t hour, uint16_t minute) {
- uint8_t minute_digit1 = minute % 10;
- uint8_t minute_digit2 = minute / 10;
- // unsigned short hour_digit1 = hour % 10;
- // unsigned short hour_digit2 = hour / 10;
+int main(void) {
+ uint32_t count = 0;
+ uint8_t is_button_on = 0;
-#ifdef STUBBED
- printf("\r:: %d %d", minute_digit2, minute_digit1);
- fflush(stdout);
-#endif
+ while (1) {
+ DDRB &= ~(1 << PB2);
+ is_button_on = (PINB & (1 << PB2)) > 0;
- write_digit(minute_digit1);
- PORTA |= (1 << PA7);
- _delay_ms(10);
- PORTA &= ~(1 << PA7);
+ 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;
+ }
+ }
- write_digit(minute_digit2);
- PORTB |= (1 << PB2);
- _delay_ms(10);
- PORTB &= ~(1 << PB2);
-}
+ setup_output();
+ write_time(0, (count / 20) % 60);
-int main(void) {
- DDRA |= 0b11111111;
- DDRB |= (1 << PB2);
-
- uint32_t i = 0;
- while (1) {
- write_time(0, (i / 20) % 60);
- i = (i + 1) % 100000;
+ count = (count + 1) % 100000;
}
return 0;
}
diff --git a/test/stubbed/avr/fuse.h b/test/stubbed/avr/fuse.h
new file mode 100644
index 0000000..be579d3
--- /dev/null
+++ b/test/stubbed/avr/fuse.h
@@ -0,0 +1,12 @@
+#ifndef STUB_AVR_FUSE
+#define STUB_AVR_FUSE
+
+struct __fuses_t {
+ int high;
+ int low;
+ int extended;
+};
+
+#define FUSES const struct __fuses_t _watch_mcu_fuses_configuration
+
+#endif
diff --git a/test/stubbed/avr/io.h b/test/stubbed/avr/io.h
index cd4a7bc..cfbdef3 100644
--- a/test/stubbed/avr/io.h
+++ b/test/stubbed/avr/io.h
@@ -1,24 +1,28 @@
+#ifndef STUB_AVR_IO
+#define STUB_AVR_IO
#include <stdio.h>
-int DDRA = 0;
-int DDRB = 0;
+static int DDRA = 0;
+static int DDRB = 0;
-int PORTA = 0;
-int PORTB = 0;
+static int PORTA = 0;
+static int PORTB = 0;
+static int PINA = 0;
+static int PINB = 0;
-int PA1 = 1;
-int PA2 = 2;
-int PA3 = 3;
-int PA4 = 4;
-int PA5 = 5;
-int PA6 = 6;
-int PA7 = 7;
-
-int PB1 = 1;
-int PB2 = 2;
-int PB3 = 3;
-int PB4 = 4;
-int PB5 = 5;
-int PB6 = 6;
-int PB7 = 7;
+#define PA1 1
+#define PA2 2
+#define PA3 3
+#define PA4 4
+#define PA5 5
+#define PA6 6
+#define PA7 7
+#define PB1 1
+#define PB2 2
+#define PB3 3
+#define PB4 4
+#define PB5 5
+#define PB6 6
+#define PB7 7
+#endif
diff --git a/test/stubbed/util/delay.h b/test/stubbed/util/delay.h
index ce4323e..db61690 100644
--- a/test/stubbed/util/delay.h
+++ b/test/stubbed/util/delay.h
@@ -1,5 +1,9 @@
+#ifndef STUB_UTIL_DELAY
+#define STUB_UTIL_DELAY
+
#include <unistd.h>
-void _delay_ms(int ms) {
+static void _delay_ms(int ms) {
usleep(ms * 1000);
}
+#endif