########################## CONFIG ##########################

# Controller
MCU=attiny10

# Id of controller
PROGRAMMER_MCU=t10

# Source files
PRJSRC=main.c asm_runtime.S

# Includes
INC=

# Libraries
LIBS=

# Optimization level
OPTLEVEL=s

# AVRDUDE Programmer
AVRDUDE_PROGRAMMERID=usbasp

# AVRDUDE port
AVRDUDE_PORT=usb

######################### /CONFIG ##########################

# HEXFORMAT -- format for .hex file output
HEXFORMAT=ihex

# Compiler
CFLAGS=-I. $(INC) -g -mmcu=$(MCU) -O$(OPTLEVEL) \
	-std=c99                                \
	-fpack-struct -fshort-enums             \
	-funsigned-bitfields -funsigned-char    \
	-fsplit-wide-types			\
	-Wall -Wstrict-prototypes               \
	-Wa,-ahlms=$(BUILD)/$(firstword         \
	$(filter %.lst, $(<:.c=.lst)))

# C++ specific flags
CPPFLAGS=-fno-exceptions                \
	-Wa,-ahlms=$(BUILD)/$(firstword \
	$(filter %.lst, $(<:.cpp=.lst)) \
	$(filter %.lst, $(<:.cc=.lst))  \
	$(filter %.lst, $(<:.C=.lst)))

# Assembler
ASMFLAGS =-I. $(INC) -mmcu=$(MCU)                 \
	-x assembler-with-cpp                     \
	-Wa,-gstabs,-ahlms=$(BUILD)/$(firstword   \
		$(<:.S=.lst) $(<.s=.lst))

# Linker
LDFLAGS=-Wl,-Map,$(BUILD)/$(TRG).map -mmcu=$(MCU) \
	-lm $(LIBS)

# Executables
CC=avr-gcc
OBJCOPY=avr-objcopy
OBJDUMP=avr-objdump
SIZE=avr-size
AVRDUDE=avrdude
REMOVE=rm -rf

# Build directory
BUILD=build

# Output names
TRG=_fw.out
DUMPTRG=_fw.s

HEXROMTRG=_fw.hex
HEXEEPTRG=_fw.ee.hex
HEXTRG=$(HEXROMTRG) $(HEXEEPTRG)

# Define all object files.

# Start by splitting source files by type
#  C++
CPPFILES=$(filter %.cpp, $(PRJSRC))
CCFILES=$(filter %.cc, $(PRJSRC))
BIGCFILES=$(filter %.C, $(PRJSRC))
#  C
CFILES=$(filter %.c, $(PRJSRC))
#  Assembly
ASMFILES=$(filter %.S, $(PRJSRC))

# List all object files we need to create
OBJDEPS=$(CFILES:.c=.o)    \
	$(CPPFILES:.cpp=.o)\
	$(BIGCFILES:.C=.o) \
	$(CCFILES:.cc=.o)  \
	$(ASMFILES:.S=.o)

OBJPATH=$(addprefix $(BUILD)/, $(OBJDEPS))

# Define all lst files.
LST=$(filter %.lst, $(OBJDEPS:.o=.lst))

# All the possible generated assembly 
# files (.s files)
GENASMFILES=$(filter %.s, $(OBJDEPS:.o=.s)) 

.SUFFIXES : .c .cc .cpp .C .o .out .s .S \
	.hex .ee.hex .h .hh .hpp

.PHONY: writeflash clean stats

# Make targets:
# all, disasm, stats, hex, writeflash/install, clean
all: $(BUILD)/$(TRG)

disasm: $(DUMPTRG) stats

#$(OBJDUMP) -h $(BUILD)/$(TRG)
stats: $(BUILD)/$(TRG)
	$(SIZE) $(BUILD)/$(TRG) -C --mcu=$(MCU)

hex: $(addprefix $(BUILD)/, $(HEXTRG))

writeflash: hex
	$(AVRDUDE) -c $(AVRDUDE_PROGRAMMERID)         \
	 -p $(PROGRAMMER_MCU) -P $(AVRDUDE_PORT) -e   \
	 -U flash:w:$(BUILD)/$(HEXROMTRG)             \
	 -B 10

install: writeflash

$(DUMPTRG): $(BUILD)/$(TRG) 
	$(OBJDUMP) -S  $< > $@

$(BUILD)/$(TRG): $(OBJPATH) 
	$(CC) $(LDFLAGS) -o $(BUILD)/$(TRG) $(OBJPATH)

# Generating assembly
# asm from C
$(BUILD)/%.s: %.c
	mkdir -p $(BUILD)
	$(CC) -S $(CFLAGS) $< -o $@

# asm from (hand coded) asm
$(BUILD)/%.s: %.S
	mkdir -p $(BUILD)
	$(CC) -S $(ASMFLAGS) $< > $@

# asm from C++
$(BUILD)/%.s: %.cpp
	mkdir -p $(BUILD)
	$(CC) -S $(CFLAGS) $(CPPFLAGS) $< -o $@

$(BUILD)/%.s: %.cc
	mkdir -p $(BUILD)
	$(CC) -S $(CFLAGS) $(CPPFLAGS) $< -o $@

$(BUILD)/%.s: %.C
	mkdir -p $(BUILD)
	$(CC) -S $(CFLAGS) $(CPPFLAGS) $< -o $@

# Generating object files
# object from C
$(BUILD)/%.o: %.c
	mkdir -p $(BUILD)
	$(CC) $(CFLAGS) -c $< -o $@


# object from C++ (.cc, .cpp, .C files)
$(BUILD)/%.o: %.ccp
	mkdir -p $(BUILD)
	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

# object from C++ (.cc, .cpp, .C files)
$(BUILD)/%.o: %.cc
	mkdir -p $(BUILD)
	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

# object from C++ (.cc, .cpp, .C files)
$(BUILD)/%.o: %.C
	mkdir -p $(BUILD)
	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@

# object from asm
$(BUILD)/%.o : %.S
	mkdir -p $(BUILD)
	$(CC) $(ASMFLAGS) -c $< -o $@


#### Generating hex files ####
# hex files from elf
$(BUILD)/$(HEXROMTRG) : $(BUILD)/$(TRG)
	$(OBJCOPY) -j .text                    \
		-j .data                       \
		-O $(HEXFORMAT) $< $@

$(BUILD)/$(HEXEEPTRG) : $(BUILD)/$(TRG)
	$(OBJCOPY) -j .eeprom                  \
		--change-section-lma .eeprom=0 \
		-O $(HEXFORMAT) $< $@

#### Cleanup ####
clean:
	$(REMOVE) $(BUILD)
#	$(REMOVE) $(TRG) $(TRG).map $(DUMPTRG)
#	$(REMOVE) $(OBJPATH)
#	$(REMOVE) $(GENASMFILES) # .S
#	$(REMOVE) $(HEXTRG)
