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

Three-channel LED blinker

parent 85a86985
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
*.eep
*.elf
*.hex
*.o
+68 −0
Original line number Diff line number Diff line

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
+134 −0
Original line number Diff line number Diff line
#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);
	}

}