+$(shell mkdir -p dist >/dev/null)
+$(shell mkdir -p build >/dev/null)
+$(shell mkdir -p sim >/dev/null)
+$(shell mkdir -p sim/build >/dev/null)
+$(shell mkdir -p release/sim >/dev/null)
+
+# --------------------------------------------------------------------------------
+# Variables configured by engineer
+
+BOARD=rpi-hot-water-controller
+DEFINE_BOARD=__RPI_HOT_WATER_CONTROLLER__
+DEVICE=atmega324p
+AVRDUDE_DEVICE=m324p
+CPU_FREQUENCY=12000000
+BAUDRATE=115200
+START_ADDRESS=0x7800
+FLASH_SIZE=0x8000
+
+NAME=bootloader_$(BOARD)_$(AVRDUDE_DEVICE)_12mhz-$(BAUDRATE)bps
+
+# --------------------------------------------------------------------------------
+# Automatic created Makefile variables
+
+SRC= $(wildcard src/*.c src/*.cpp src/*/*.c src/*/*.cpp)
+HDR= $(wildcard src/*.h src/*.hpp src/*/*.h src/*/*.hpp)
+MAINSRC= $(wildcard src/main.c src/main.cpp)
+OBJ_CPP = $(SRC:src/%.cpp=build/%.o)
+OBJ = $(OBJ_CPP:src/%.c=build/%.o)
+OBJ_SIM_CPP = $(SRC:src/%.cpp=sim/build/%.o)
+OBJ_SIM = $(OBJ_SIM_CPP:src/%.c=sim/build/%.o)
+
+CC= avr-g++
+CFLAGS= -Wall -mmcu=$(DEVICE) -Os -DF_CPU=$(CPU_FREQUENCY) -D$(DEFINE_BOARD) -DBAUD_RATE=$(BAUDRATE) -DDOUBLE_SPEED -DNUM_LED_FLASHES=4 '-DMAX_TIME_COUNT=F_CPU>>4' -c
+#LFLAGS= -Wall -mmcu=$(DEVICE) -Os -DF_CPU=$(CPU_FREQUENCY) -Wl,-u,vfprintf -lprintf_flt -lm
+LFLAGS= -Wall -mmcu=$(DEVICE) -Os -DF_CPU=$(CPU_FREQUENCY) -Wl,--section-start=.text=$(START_ADDRESS)
+
+CFLAGS_SIM= -Wall -mmcu=$(DEVICE) -Og -DF_CPU=$(CPU_FREQUENCY) -D$(DEFINE_BOARD) -g -DBAUD_RATE=$(BAUDRATE) -DDOUBLE_SPEED -DNUM_LED_FLASHES=4 '-DMAX_TIME_COUNT=F_CPU>>4' -c
+#LFLAGS_SIM= -Wall -mmcu=$(DEVICE) -Og -DF_CPU=$(CPU_FREQUENCY) -g -Wl,-u,vfprintf -lprintf_flt -lm
+LFLAGS_SIM= -Wall -mmcu=$(DEVICE) -Og -DF_CPU=$(CPU_FREQUENCY) -g -Wl,--section-start=.text=$(START_ADDRESS)
+
+# --------------------------------------------------------------------------------
+# make targets
+
+.PHONY: all
+all: dist/$(NAME).elf dist/$(NAME).s sim/$(NAME).elf dist/$(NAME).hex dist/$(NAME).bin sim/$(NAME).s info
+
+.PHONY: info
+info:
+ @echo
+ @avr-size --mcu=$(DEVICE) --format=avr dist/$(NAME).elf
+
+# --------------------------------------------------------------------------------
+# dependency make for hierarchical source file structure
+
+.depend: $(SRC) $(HDR)
+ $(CC) -mmcu=$(DEVICE) -MM $(SRC) | sed --regexp-extended 's/^(.*\.o)\: src\/(.*)(\.cpp|\.c) (.*)/build\/\2\.o\: src\/\2\3 \4/g' > .depend
+
+ifneq (clean,$(filter clean,$(MAKECMDGOALS)))
+-include .depend
+endif
+
+# --------------------------------------------------------------------------------
+# elf, hex and assembler file creation
+
+dist/$(NAME).elf: .depend $(OBJ)
+ $(CC) $(LFLAGS) -o $@ $(OBJ)
+
+dist/%.s: dist/%.elf
+ avr-objdump -d $< > $@
+
+dist/%.hex: dist/%.elf
+ avr-objcopy -O ihex $< $@
+
+dist/%.bin: dist/%.elf
+ avr-objcopy -O binary $< $@
+ @head -c $(shell printf "%d\n" $(START_ADDRESS)) /dev/zero | LC_ALL=C tr "\000" "\377" > /tmp/.m328_flash1.bin
+ @cat /tmp/.m328_flash1.bin $@ /tmp/.m328_flash1.bin > /tmp/.m328_flash2.bin
+ @dd if=/tmp/.m328_flash2.bin of=$@ bs=1 count=$(shell printf "%d\n" $(FLASH_SIZE)) 2>/dev/null
+ @rm /tmp/.m328_flash?.bin
+
+# --------------------------------------------------------------------------------
+# check if the macros __DATE__ or __TIME__ are used in src/main.cpp or src/main.c
+
+DATE_USED=
+ifneq ($(shell cat $(MAINSRC) | grep __DATE__),)
+ DATE_USED=true
+endif
+TIME_USED=
+ifneq ($(shell cat $(MAINSRC) | grep __TIME__),)
+ TIME_USED=true
+endif
+
+ifeq (true, $(filter true, $(DATE_USED) $(TIME_USED)))
+build/main.o: $(MAIN_SRC) $(SRC) $(HDR)
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) -o $@ $<
+endif
+
+# --------------------------------------------------------------------------------
+
+build/%.o: src/%.c
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) -o $@ $<
+
+build/%.o: src/%.cpp
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) -o $@ $<
+
+# --------------------------------------------------------------------------------
+# simulation/debugging with gdb or simuc
+
+sim/$(NAME).elf: .depend $(OBJ_SIM)
+ $(CC) $(LFLAGS_SIM) -o $@ $(OBJ_SIM)
+ @ln -sf $(NAME).elf sim/$(DEVICE).elf
+
+sim/build/%.o: src/%.c
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS_SIM) -o $@ $<
+
+sim/build/%.o: src/%.cpp
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS_SIM) -o $@ $<
+
+sim/%.s: sim/%.elf
+ avr-objdump -d $< > $@
+
+ifeq (m16, $(AVRDUDE_DEVICE))
+simuc: sim/$(NAME).elf
+ simuc --board sure $<
+endif
+
+ifeq (m328p, $(AVRDUDE_DEVICE))
+simuc: sim/$(NAME).elf
+ simuc --board arduino $<
+endif
+
+ifeq (m324p, $(AVRDUDE_DEVICE))
+simuc: sim/$(NAME).elf
+ simuc --board hot-water-controller $<
+endif
+
+ifeq (m644p, $(AVRDUDE_DEVICE))
+simuc: sim/$(NAME).elf
+ simuc --board nano-644 $<
+endif
+
+ifeq (m1284p, $(AVRDUDE_DEVICE))
+simuc: sim/$(NAME).elf
+ simuc --board nano-1284 $<
+endif
+
+gdb: sim/$(NAME).elf
+ avr-gdb $<
+
+# -------------------------------------------------------------
+# flash to target with arduino bootloader in bootloader-section
+
+.PHONY: flash
+flash: dist/$(NAME).elf all
+ avrdude -c arduino -P /dev/ttyUSB0 -b $(BAUDRATE) -p $(AVRDUDE_DEVICE) -e -U flash:w:$<
+
+.PHONY: flash0
+flash0: dist/$(NAME).elf all
+ avrdude -c arduino -P /dev/ttyUSB0 -b $(BAUDRATE) -p $(AVRDUDE_DEVICE) -e -U flash:w:$<
+
+.PHONY: flash1
+flash1: dist/$(NAME).elf all
+ avrdude -c arduino -P /dev/ttyUSB1 -b $(BAUDRATE) -p $(AVRDUDE_DEVICE) -e -U flash:w:$<
+
+.PHONY: flash2
+flash2: dist/$(NAME).elf all
+ avrdude -c arduino -P /dev/ttyUSB2 -b $(BAUDRATE) -p $(AVRDUDE_DEVICE) -e -U flash:w:$<
+
+.PHONY: flash-read
+flash-read:
+ avrdude -c arduino -P /dev/ttyUSB0 -b $(BAUDRATE) -p $(AVRDUDE_DEVICE) -U flash:r:/tmp/flash.bin
+
+.PHONY: flash-disassemble
+flash-disassemble: flash-read
+ avr-objdump -b binary -D -m avr5 /tmp/flash.bin > /tmp/flash.s
+ less /tmp/flash.s
+
+.PHONY: flash-hexdump
+flash-hexdump: flash-read
+ hexdump -C /tmp/flash.bin | less
+
+# ----------------------------------------------
+# flash to target with fischl programming device
+
+.PHONY: isp-flash-$(AVRDUDE_DEVICE)
+isp-$(AVRDUDE_DEVICE):
+ avrdude -c usbasp -p $(AVRDUDE_DEVICE) -U lock:r:-:h
+ avrdude -c usbasp -p $(AVRDUDE_DEVICE)
+
+.PHONY: isp-flash
+isp-flash: dist/$(NAME).elf all
+ avrdude -c usbasp -p $(AVRDUDE_DEVICE) -e -U flash:w:$<
+
+.PHONY: isp-flash-$(AVRDUDE_DEVICE)
+isp-flash-$(AVRDUDE_DEVICE): dist/$(NAME).elf all
+ avrdude -c usbasp -p $(AVRDUDE_DEVICE) -e -U flash:w:$<
+
+.PHONY: isp-read-flash-$(AVRDUDE_DEVICE)
+isp-read-flash-$(AVRDUDE_DEVICE):
+ avrdude -c usbasp -p m32$(AVRDUDE_DEVICE)8p -U flash:r:/tmp/flash-arduino-atmega328p__$(shell date +"%Y-%m-%d_%H%M%S")
+
+.PHONY: isp-fuse
+isp-fuse: isp-fuse-$(AVRDUDE_DEVICE)
+
+.PHONY: isp-fuse-$(AVRDUDE_DEVICE)
+ifeq (m16, $(AVRDUDE_DEVICE))
+isp-fuse-$(AVRDUDE_DEVICE):
+ avrdude -c usbasp -p $(AVRDUDE_DEVICE) -U lfuse:w:0x18:m -U hfuse:w:0xD8:m -U lock:w:0xEF:m
+endif
+ifeq (m328p, $(AVRDUDE_DEVICE))
+isp-fuse-$(AVRDUDE_DEVICE):
+ avrdude -c usbasp -p $(AVRDUDE_DEVICE) -U lfuse:w:0xEF:m -U hfuse:w:0xD8:m -U efuse:w:0xFD:m -U lock:w:0xEF:m
+endif
+ifeq (m324p, $(AVRDUDE_DEVICE))
+# https://eleccelerator.com/fusecalc/fusecalc.php?chip=atmega324p&LOW=FB&HIGH=D8&EXTENDED=FE&LOCKBIT=FF
+isp-fuse-$(AVRDUDE_DEVICE):
+ avrdude -c usbasp -p $(AVRDUDE_DEVICE) -U lfuse:w:0xFB:m -U hfuse:w:0xD8:m -U efuse:w:0xFE:m -U lock:w:0xEF:m
+endif
+ifeq (m644p, $(AVRDUDE_DEVICE))
+isp-fuse-$(AVRDUDE_DEVICE):
+ avrdude -c usbasp -p $(AVRDUDE_DEVICE) -U lfuse:w:0xEF:m -U hfuse:w:0xD8:m -U efuse:w:0xFD:m -U lock:w:0xEF:m
+endif
+ifeq (m1284p, $(AVRDUDE_DEVICE))
+isp-fuse-$(AVRDUDE_DEVICE):
+ avrdude -c usbasp -p $(AVRDUDE_DEVICE) -U lfuse:w:0xEF:m -U hfuse:w:0xD8:m -U efuse:w:0xFD:m -U lock:w:0xEF:m
+endif
+
+# --------------------------------------------------------
+# picocom sends CR for ENTER -> convert cr (\r) to lf (\n)
+
+.PHONY: picocom
+picocom:
+ picocom -b $(BAUDRATE) --omap crlf --raise-dtr /dev/ttyUSB0
+
+.PHONY: picocom0
+picocom0:
+ picocom -b $(BAUDRATE) --omap crlf --raise-dtr /dev/ttyUSB0
+
+.PHONY: picocom1
+picocom1:
+ picocom -b $(BAUDRATE) --omap crlf --raise-dtr /dev/ttyUSB1
+
+.PHONY: picocom2
+picocom2:
+ picocom -b $(BAUDRATE) --omap crlf --raise-dtr /dev/ttyUSB2
+
+# --------------------------------------------------------
+
+.PHONY: help
+help:
+ @echo
+ @echo "Possible targets are:"
+ @echo " clean"
+ @echo " all help info"
+ @echo " flash flash0 flash1 flash2 flash-read flash-disassemble flash-hexdump"
+ @echo " isp-$(AVRDUDE_DEVICE) isp-flash-$(AVRDUDE_DEVICE) isp-fuse-$(AVRDUDE_DEVICE)"
+ @echo " picocom picocom0 picocom1 picocom2"
+ @echo " gdb simuc"
+ @echo
+
+# --------------------------------------------------------
+
+.PHONY: release
+release: dist/$(NAME).elf sim/$(NAME).elf dist/$(NAME).hex dist/$(NAME).bin
+ ../create-release release $(word 1, $^) release/sim $(word 2, $^)
+
+# --------------------------------------------------------
+
+.PHONY: clean
+clean:
+ @rm -r dist
+ @rm -r build
+ @rm -r sim
+ @find . -type f -name ".depend" -exec rm {} \;
+ @echo "clean done"