Commit d040ed5e authored by Daniel Friesel's avatar Daniel Friesel
Browse files

Initial commit. Working static light, but no rgbfade yet

parents
Loading
Loading
Loading
Loading

.gitignore

0 → 100644
+1 −0
Original line number Diff line number Diff line
build

Makefile

0 → 100644
+72 −0
Original line number Diff line number Diff line
MCU_AVRDUDE ?= t2313
MCU_AVRGCC ?= attiny2313a
AVRDUDE_PROGRAMMER ?= usbasp

AVRCC ?= avr-gcc
AVRCXX ?= avr-g++
AVRFLASH ?= avrdude
AVRNM ?= avr-nm
AVROBJCOPY ?= avr-objcopy
AVROBJDUMP ?= avr-objdump

MCU_FLAGS = -mmcu=${MCU_AVRGCC} -DF_CPU=8000000UL

SHARED_FLAGS = ${MCU_FLAGS} -I. -Os -Wall -Wextra -pedantic
SHARED_FLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
SHARED_FLAGS += -flto -mstrict-X

ifeq (${LANG},DE)
	SHARED_FLAGS += -DLANG_DE
endif

CFLAGS += ${SHARED_FLAGS} -std=c11
CXXFLAGS += ${SHARED_FLAGS} -std=c++11 -fno-rtti -fno-exceptions

ASFLAGS += ${MCU_FLAGS} -wA,--warn
LDFLAGS += -Wl,--gc-sections

#AVRFLAGS += -U lfuse:w:0xe4:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m
AVRFLAGS += -U flash:w:build/main.hex
#AVRFLAGS += -U eeprom:w:main.eep

HEADERS  = $(wildcard src/*.h)
ASFILES  = $(wildcard src/*.S)
CFILES   = $(wildcard src/*.c)
CXXFILES = $(wildcard src/*.cc)
OBJECTS  = ${CFILES:src/%.c=build/%.o} ${CXXFILES:src/%.cc=build/%.o} ${ASFILES:src/%.S=build/%.o}

all: build build/main.elf

build:
	mkdir -p build

build/%.hex: build/%.elf
	${AVROBJCOPY} -O ihex -R .eeprom $< $@

build/%.eep: build/%.elf
	${AVROBJCOPY} -j .eeprom --set-section-flags=.eeprom="alloc,load" \
	--change-section-lma .eeprom=0 -O ihex $< $@

build/%.o: src/%.cc ${HEADERS}
	${AVRCXX} ${CXXFLAGS} -o $@ $< -c -Wl,-Map=main.map,--cref

build/%.o: src/%.c ${HEADERS}
	${AVRCC} ${CFLAGS} -o $@ $< -c -Wl,-Map=main.map,--cref

build/main.elf: ${OBJECTS}
	${AVRCXX} ${CXXFLAGS} -o $@ $^ ${LDFLAGS}
	@echo
	@avr-size --format=avr --mcu=${MCU_AVRGCC} $@

flash: program

program: build/main.hex #main.eep
	${AVRFLASH} -p ${MCU_AVRDUDE} -c ${AVRDUDE_PROGRAMMER} ${AVRFLAGS}

secsize: build/main.elf
	${AVROBJDUMP} -hw -j.text -j.bss -j.data $<

funsize: build/main.elf
	${AVRNM} --print-size --size-sort $<

.PHONY: all program secsize funsize

src/main.cc

0 → 100644
+15 −0
Original line number Diff line number Diff line
#include <avr/io.h>
#include <stdlib.h>

#include "system.h"

int main (void)
{
	blinkencat.initialize();

	while (1) {
		blinkencat.loop();
	}

	return 0;
}

src/system.cc

0 → 100644
+185 −0
Original line number Diff line number Diff line
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>

// Debian's avr-libc lacks the ATTiny2313A WDTCSR definition
#define WDTCSR  _SFR_IO8(0x21)

#include "system.h"

/*
 * Charge Status IN        -> PD3 (PCINT14)
 * Piezo IN                -X
 * Charge Status LED OUT   -> PD1
 * Vcc                     -> VCC
 * GND                     -> GND
 * Warm White OUT          -> PD5 (OC0B)
 * Blue OUT                -> PB2 (OC0A)
 * Button IN               -> PD2 (PCINT13)
 * Red OUT                 -> PB3 (OC1A)
 * Green OUT               -> PB4 (OC1B)
 *
 */

System blinkencat;

void System::initialize()
{

	// disable analog comparator
	ACSR |= _BV(ACD);

	// disable unused modules
	PRR |= _BV(PRUSI) | _BV(PRUSART);

	wdt_disable();

	DDRA = 0;
	DDRB = _BV(DDB2) | _BV(DDB3) | _BV(DDB4);
	DDRD = _BV(DDD1) | _BV(DDD5);
	PORTD = _BV(PD2);

	/*
	 * Pin change interrupts on PD2 and PD3.
	 * They are also used to wake the chip from sleep, hence we can't use
	 * INT0/INT1 directly. For those, only a level interrupt is detected
	 * asynchronously.
	 */

	PCMSK2 = _BV(PCINT13) | _BV(PCINT14);
	GIMSK = _BV(PCIE2);

	sei();
}

void System::idle()
{
	MCUCR &= ~_BV(SM0);
	MCUCR |= _BV(SE);
	asm("sleep");
	MCUCR &= ~_BV(SE);
}

void System::sleep()
{
	MCUCR |= _BV(SM0) | _BV(SE);
	asm("sleep");
	MCUCR &= ~_BV(SE);
}

void System::set_outputs()
{
	if (warmwhite) {
		PORTD |= _BV(PD5);
	} else {
		PORTD &= ~_BV(PD5);
	}
	if (red) {
		PORTB |= _BV(PB3);
	} else {
		PORTB &= ~_BV(PB3);
	}
	if (green) {
		PORTB |= _BV(PB4);
	} else {
		PORTB &= ~_BV(PB4);
	}
	if (blue) {
		PORTB |= _BV(PB2);
	} else {
		PORTB &= ~_BV(PB2);
	}
}

void System::loop()
{
	switch (mode) {
		case OFF:
			warmwhite = red = green = blue = 0;
			break;
		case WARMWHITE:
			warmwhite = 255;
			red = green = blue = 0;
			break;
		case RED:
			red = 255;
			warmwhite = green = blue = 0;
			break;
		case GREEN:
			green = 255;
			warmwhite = red = blue = 0;
			break;
		case BLUE:
			blue = 255;
			warmwhite = red = green = 0;
			break;
		case YELLOW:
			red = green = 255;
			warmwhite = blue = 0;
			break;
		case MAGENTA:
			red = blue = 255;
			warmwhite = green = 0;
			break;
		case CYAN:
			green = blue = 255;
			warmwhite = red = 0;
			break;
		case SUN:
			warmwhite = red = green = blue = 255;
			break;
		default:
			break;
	}
	set_outputs();

	if (mode == OFF && !btn_debounce) {
		sleep();
	} else {
		idle();
	}
}

void System::next_mode(void)
{
	if (!btn_debounce) {
		mode = (BCMode)((mode + 1) % MODE_ENUM_MAX);
	}
}

void System::debounce_start(void)
{
	btn_debounce = 1;
	wdt_reset();
	WDTCSR = _BV(WDE) | _BV(WDCE);
	WDTCSR = _BV(WDIE) | _BV(WDP1) | _BV(WDP0);
}

void System::debounce_done(void)
{
	btn_debounce = 0;
	wdt_disable();
}

ISR(WDT_OVERFLOW_vect)
{
	blinkencat.debounce_done();
}

ISR(PCINT2_vect)
{
	if (!(PIND & _BV(PD2))) {
		blinkencat.next_mode();
	}
	if (PIND & _BV(PD3)) {
		blinkencat.is_charging = 1;
		PORTD |= _BV(PD1);
	} else {
		blinkencat.is_charging = 0;
		PORTD &= ~_BV(PD1);
	}
	blinkencat.debounce_start();
}

src/system.h

0 → 100644
+52 −0
Original line number Diff line number Diff line
#ifndef __SYSTEM_H__
#define __SYSTEM_H__

class System {
	private:
		uint8_t btn_debounce;

		void idle(void);
		void sleep(void);

		uint8_t warmwhite;
		uint8_t red;
		uint8_t green;
		uint8_t blue;

		void set_outputs();

	public:

		void initialize(void);

		void loop(void);

		uint8_t is_charging;

		enum BCMode : uint8_t {
			OFF = 0,
			WARMWHITE,
			RED,
			GREEN,
			BLUE,
			YELLOW,
			MAGENTA,
			CYAN,
			SUN,
			MODE_ENUM_MAX,
		};

		BCMode mode;

		void next_mode(void);

		void debounce_done(void);

		void debounce_start(void);

		System() { btn_debounce = 0; mode = OFF; is_charging = 0; };
};

extern System blinkencat;

#endif