Three-channel LED blinker
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Mon, 1 Dec 2014 12:05:17 +0000 (13:05 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Mon, 1 Dec 2014 12:08:14 +0000 (13:08 +0100)
projects/led-blinker/.gitignore [new file with mode: 0644]
projects/led-blinker/Makefile [new file with mode: 0644]
projects/led-blinker/main.c [new file with mode: 0644]

diff --git a/projects/led-blinker/.gitignore b/projects/led-blinker/.gitignore
new file mode 100644 (file)
index 0000000..324be1b
--- /dev/null
@@ -0,0 +1,4 @@
+*.eep
+*.elf
+*.hex
+*.o
diff --git a/projects/led-blinker/Makefile b/projects/led-blinker/Makefile
new file mode 100644 (file)
index 0000000..1bcbac1
--- /dev/null
@@ -0,0 +1,68 @@
+
+PROGRAM=blinker
+SRC=main.c
+OBJ=$(SRC:.c=.o)
+
+
+MCU=attiny25
+AVRDUDE_MCU=$(MCU)
+AVRDUDE_PROGRAMMER=usbasp
+
+CFLAGS=-Wall -Os -mmcu=$(MCU) -DUSE_LOGGING=1 -DF_CPU=1000000UL -std=gnu99
+LDFLAGS=
+AVRDUDE_FLAGS= -p$(AVRDUDE_MCU) -c $(AVRDUDE_PROGRAMMER) -B100
+
+FORMAT=ihex
+
+CC=avr-gcc
+OBJCOPY=avr-objcopy
+OBJDUMP=avr-objdump
+AVRDUDE=avrdude
+
+all: $(PROGRAM).hex $(PROGRAM).eep
+
+program: $(PROGRAM).hex $(PROGRAM).eep
+       $(AVRDUDE) $(AVRDUDE_FLAGS) -U flash:w:$(PROGRAM).hex:i -U eeprom:w:$(PROGRAM).eep:i
+
+program_flash: $(PROGRAM).hex
+       $(AVRDUDE) $(AVRDUDE_FLAGS) -U flash:w:$(PROGRAM).hex:i
+
+program_eeprom: $(PROGRAM).eep
+       $(AVRDUDE) $(AVRDUDE_FLAGS) eeprom:w:$(PROGRAM).eep:i
+
+dump_eeprom:
+       $(AVRDUDE) $(AVRDUDE_FLAGS) -U eeprom:r:eeprom.raw:r
+       od -tx1 eeprom.raw
+
+objdump: $(PROGRAM).elf
+       $(OBJDUMP) --disassemble $<
+
+.PRECIOUS : $(OBJ) $(PROGRAM).elf
+
+%.hex: %.elf
+       $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+
+%.eep: %.elf
+       $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+               --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+
+%.elf: $(OBJ)
+       $(CC) $(CFLAGS) $(OBJ) -o $@ $(LDFLAGS)
+
+%.o: %.c lights.h Makefile
+       $(CC) -c $(CFLAGS) $< -o $@
+
+%.s: %.c lights.h Makefile
+       $(CC) -S -c $(CFLAGS) $< -o $@
+
+%.o: %.S
+       $(CC) -c $(CFLAGS) $< -o $@
+
+clean:
+       rm -f $(PROGRAM).hex $(PROGRAM).eep $(PROGRAM).elf *.o *.s eeprom.raw
+
+version.c:
+       ./version.pl > version.c
+
+.PHONY: all clean dump_eeprom program program_flash program_eeprom objdump version.c
+
diff --git a/projects/led-blinker/main.c b/projects/led-blinker/main.c
new file mode 100644 (file)
index 0000000..70491ed
--- /dev/null
@@ -0,0 +1,134 @@
+#include <avr/io.h>
+#include <util/delay.h>
+#include <avr/sleep.h>
+#include <avr/power.h>
+
+/*
+ * Overview:
+ * three LEDs:
+ * PB1/OC1A     yellow
+ * PB2          yellow
+ * PB4/OC1B     red
+ */
+
+static void init()
+{
+       DDRB |= _BV(PB1) | _BV(PB2) | _BV(PB4);
+
+       // PWM setup, use T/C 1
+       TCCR1 = _BV(CS10)       // clock at CLK/1
+               | _BV(PWM1A)    // OCR1A in PWM mode
+               | _BV(COM1A1);  // clear on compare match
+       GTCCR = _BV(PWM1B)      // OCR1B in PWM mode
+               | _BV(COM1B1); // clear on compare match)
+
+       OCR1C = 255;
+       OCR1A = 0;
+       OCR1B = 0;
+}
+
+
+static unsigned char levels[] = {
+       0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 255
+};
+#define N_LEVELS (sizeof(levels)/sizeof(levels[0]))
+
+static void led_set(unsigned char led, unsigned char val)
+{
+       switch (led) {
+       case 0:
+               OCR1A = val < N_LEVELS ? levels[val] : levels[N_LEVELS-1];
+               break;
+       case 1:
+               if (val) {
+                       PORTB |= _BV(PB2);
+               } else {
+                       PORTB &= ~_BV(PB2);
+               }
+               break;
+       case 2:
+               OCR1B = val < N_LEVELS ? levels[val] : levels[N_LEVELS-1];
+               break;
+       }
+}
+
+static unsigned char rand[] = {
+193, 33, 133, 97, 139, 225, 40, 105, 110, 238, 57, 250, 26, 221, 166, 247, 138, 23, 107, 122, 154, 33, 201, 66, 154, 78, 137, 198, 86, 232, 38, 182, 16, 198, 73, 231, 58, 114, 58, 105,
+};
+#define N_RAND (sizeof(rand)/sizeof(rand[0]))
+
+static void led0()
+{
+       static unsigned char r, l, exp;
+
+again:
+       if (l == exp) {
+               r++;
+               if (r > N_RAND-7)
+                       r = 0;
+               exp = rand[r] >> 4;
+               if (exp >= N_LEVELS-4)
+                       goto again;
+       }
+
+       if (l < exp) {
+               l++;
+       } else if (l > exp) {
+               l--;
+       }
+
+       led_set(0, l);
+}
+
+static void led1()
+{
+       static unsigned char r;
+       unsigned char exp;
+
+       led_set(1, 1);
+#if 0
+again:
+       r++;
+       if (r > N_RAND)
+               r = 0;
+       exp = rand[r];
+
+       led_set(1, ((exp >> 3) & 1) ^ ((exp >> 5) & 1));
+#endif
+}
+
+static void led2()
+{
+       static unsigned char r, l, exp;
+
+again:
+       if (l == exp) {
+               r++;
+               if (r > N_RAND)
+                       r = 0;
+               exp = rand[r] & 0xF;
+               if (exp >= N_LEVELS)
+                       goto again;
+       }
+
+       if (l < exp) {
+               l++;
+       } else if (l > exp) {
+               l--;
+       }
+
+       led_set(2, l);
+}
+
+int main(void)
+{
+       init();
+
+       while (1) {
+               led0();
+               led1();
+               led2();
+               _delay_ms(40);
+       }
+
+}