A => .gitignore +2 -0
@@ 1,2 @@
+blinky_binary
+blinky_binary.hex
A => build.sh +5 -0
@@ 1,5 @@
+avr-gcc -v \
+ -mmcu=attiny85 \
+ -Os -std=gnu99 -Wall \
+ -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
+ src/main.c -o blinky_binary
A => check_programmer_ready.sh +1 -0
@@ 1,1 @@
+avrdude -p attiny85 -c usbasp
A => configure_fuses.sh +1 -0
@@ 1,1 @@
+avrdude -v -p attiny85 -c usbasp -U lfuse:w:0x62:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m
A => pcb_kicad_project.zip +0 -0
A => src/main.c +93 -0
@@ 1,93 @@
+#define F_CPU 1000000UL
+#include <avr/io.h>
+#include <util/delay.h>
+#include <avr/power.h>
+
+#define EYES_STATE_OPEN 0
+#define EYES_STATE_CLOSING 1
+#define EYES_STATE_CLOSED 2
+#define EYES_STATE_OPENING 3
+uint8_t eyes_state;
+
+#define EYES_CLOSED_DURATION_MS 200
+#define EYES_OPEN_BASE_DURATION_MS 100
+#define EYES_OPENING_DT_US 1500
+#define EYES_CLOSING_DT_US 400
+uint8_t eyes_open_duration_multipliers_index = 0;
+uint16_t eyes_open_duration_multipliers[] = {
+ 50, 40, 79, 20, 91, 43, 68, 70, 40, 23, 33,
+};
+size_t eyes_open_duration_multipliers_count;
+
+int
+main(void)
+{
+ // Minimise power usage.
+ power_all_disable();
+ power_timer0_enable();
+
+ // Drive LEDs via PB0.
+ DDRB |= (1 << DDB0);
+
+ // Set waveform mode to fast PWM.
+ TCCR0A |= (1 << WGM00);
+ TCCR0A |= (1 << WGM01);
+ TCCR0B &= ~(1 << WGM02);
+
+ // Set overflow / match behavior.
+ TCCR0A |= (1 << COM0A1);
+ TCCR0A |= (1 << COM0B0);
+ TCCR0A |= (1 << COM0A0);
+ TCCR0A |= (1 << COM0B1);
+
+ // No pre-scaler.
+ TCCR0B |= (1 << CS00);
+
+ // Start with eyes open.
+ OCR0A = 0;
+ eyes_state = EYES_STATE_OPEN;
+
+ // Cache array size.
+ eyes_open_duration_multipliers_count = sizeof(eyes_open_duration_multipliers) / sizeof(eyes_open_duration_multipliers[0]);
+
+ while (1) {
+ switch (eyes_state) {
+
+ case EYES_STATE_OPEN:
+ OCR0A = 0x00;
+ uint16_t duration = eyes_open_duration_multipliers[eyes_open_duration_multipliers_index] * EYES_OPEN_BASE_DURATION_MS;
+ eyes_open_duration_multipliers_index++;
+ if (eyes_open_duration_multipliers_index >= eyes_open_duration_multipliers_count) {
+ eyes_open_duration_multipliers_index = 0;
+ }
+ for (uint16_t i = 0; i < duration; i++) {
+ _delay_ms(1);
+ }
+ eyes_state = EYES_STATE_CLOSING;
+ break;
+
+ case EYES_STATE_CLOSING:
+ OCR0A++;
+ _delay_us(EYES_CLOSING_DT_US);
+ if (OCR0A == 255) {
+ eyes_state = EYES_STATE_CLOSED;
+ }
+ break;
+
+ case EYES_STATE_CLOSED:
+ OCR0A = 0xFF;
+ _delay_ms(EYES_CLOSED_DURATION_MS);
+ eyes_state = EYES_STATE_OPENING;
+ break;
+
+ case EYES_STATE_OPENING:
+ OCR0A--;
+ _delay_us(EYES_OPENING_DT_US);
+ if (OCR0A == 0) {
+ eyes_state = EYES_STATE_OPEN;
+ }
+ break;
+ }
+ }
+ return 0;
+}
A => upload.sh +6 -0
@@ 1,6 @@
+if avr-objcopy -O ihex -j.text -j.data blinky_binary blinky_binary.hex
+then
+ avrdude -v -p attiny85 -c usbasp -U flash:w:blinky_binary.hex:i
+else
+ echo "...failed :("
+fi