Commit c4ebe9bf authored by Jan Kasprzak's avatar Jan Kasprzak
Browse files

Three-channel LED blinker

parent 85a86985
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
#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);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment