#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make flash = Download the hex file to the device, using avrdude.
#                Please customize the avrdude settings below first!
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
#                   bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------

# MCU name: attiny13a attiny2313a attiny85 atmega8a atmega328p atmega128a
MCU = atmega8a

# Processor frequency.
#     This will define a symbol, F_CPU, in all source code files equal to the 
#     processor frequency. You can then use this symbol in your source code to 
#     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
#     automatically to create a 32-bit value in your source code.
F_CPU = 16000000

# Target file name (without extension).
TARGET = max6675

# Output format. (can be srec, ihex, binary)
FORMAT = ihex

# OPT_PRINTF, OPT_SCANF: min, default, float
# min - A minimized version of vfprintf() is available that only implements
#				the very basic integer and string conversion facilities,
#				but only the # additional option can be specified using conversion flags
#				(these flags are parsed correctly from the format specification, but then simply ignored).
# default - The default vfprintf() implements all the mentioned functionality
#				except floating point conversions.
# float - For floating-point conversions.
OPT_SCANF = 
OPT_PRINTF = 

# List C source files here. (C dependencies are automatically generated.)
CSRC = main.c heater.c logger.c parser.c

# Tactile
TACTILE_SUP = yes
ifeq ($(TACTILE_SUP),yes)
CDEFS += -DTACTILE=yes
CSRC  += Tactile.c
endif

# StdFix
STDFIX = yes
ifeq ($(STDFIX),yes)
CDEFS += -DUSE_STDFIX=yes
endif

# xprintf
# XPRINTF_SUP = yes
ifeq ($(XPRINTF_SUP),yes)
CDEFS += -DXPRINTF=yes
CSRC  += xprintf.c
endif

# USART
USART_SUP = yes
ifeq ($(USART_SUP),yes)
CDEFS += -DUSART=yes
CDEFS += -DEXTRABUFSIZE=64
CDEFS += -DTx_Option=yes
CDEFS += -DUSART_TX_BUFFER_SIZE=64
CDEFS += -DRx_Option=yes
CDEFS += -DUSART_RX_BUFFER_SIZE=32
CDEFS += -DBAUD=250000uL
CSRC  += USART.c
endif

# Encoder
# ENCODER_SUP = yes
ifeq ($(ENCODER_SUP),yes)
CDEFS += -DENCODER=yes
CSRC  += Encoder.c
endif

#Buttons
# BUTTON_SUP = yes
ifeq ($(BUTTON_SUP),yes)
CDEFS += -DBUTTON=yes
CSRC  += Button.c
endif

# PCD8544 84x48 display
# PCD8544_SUP = yes
ifeq ($(PCD8544_SUP),yes)
CDEFS += -DPCD8544=yes
CSRC  += pcd8544_hw.c 
endif

# List Assembler source files here.
#     Make them always end in a capital .S.  Files ending in a lowercase .s
#     will not be considered source files but generated files (assembler
#     output from the compiler), and will be deleted upon "make clean"!
#     Even though the DOS/Win* filesystem matches both .s and .S the same,
#     it will preserve the spelling of the filenames, and gcc itself does
#     care about how the name is spelled on its command-line.
ASRC = 

# Optimization level, can be [0, 1, 2, 3, s]. 
#     0 = turn off optimization. s = optimize for size.
#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s

# Debugging format.
#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
#     AVR Studio 4.10 requires dwarf-2.
#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2


# Compiler flag to set the C Standard level.
#     c89   = "ANSI" C
#     gnu89 = c89 plus GCC extensions
#     c99   = ISO C99 standard (not yet fully implemented)
#     gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99

# Use Link-Time Optimization
FLTO_SUP = yes

# List any extra directories to look for include files here.
#     Each directory must be seperated by a space.
#     Use forward slashes for directory separators.
#     For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS = ../Lib/My
# ../Lib/pms67pid
ifeq ($(XPRINTF_SUP),yes)
EXTRAINCDIRS += ../Lib/xprintf/src
endif

# VPATH: Search Path for All Prerequisites
# The value of the make variable VPATH specifies a list of directories
# that make should search. Most often, the directories are expected to contain
# prerequisite files that are not in the current directory; however,
# make uses VPATH as a search list for both prerequisites and targets of rules.
# In the VPATH variable, directory names are separated by colons or blanks.
VPATH = . ../Lib/My
# ../Lib/pms67pid
ifeq ($(XPRINTF_SUP),yes)
VPATH += ../Lib/xprintf/src
endif

WORKINGDIR = build

#---------------- Compiler Options ----------------
#  -g*:          generate debugging information
#  -O*:          optimization level
#  -f...:        tuning, see GCC manual and avr-libc documentation
#  -Wall...:     warning level
#  -Wa,...:      tell GCC to pass this to the assembler.
#    -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += -DF_CPU=$(F_CPU)uL
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections
CFLAGS += -Wall
ifeq ($(FLTO_SUP),yes)
CFLAGS += -flto
endif
CFLAGS += -Wa,-adhlns=$(patsubst %.c,$(WORKINGDIR)/%.lst,$(notdir $<))
CFLAGS += $(CSTANDARD)


#---------------- Assembler Options ----------------
#  -Wa,...:   tell GCC to pass this to the assembler.
#  -ahlms:    create listing
#  -gstabs:   have the assembler create line number information; note that
#             for use in COFF files, additional information about filenames
#             and function names needs to be present in the assembler source
#             files -- see avr-libc docs [FIXME: not yet described there]
#  -listing-cont-lines: Sets the maximum number of continuation lines of hex 
#       dump that will be displayed for a given single line of source input.
ASFLAGS = -Wa,-adhlns=$(patsubst %.s,$(WORKINGDIR)/%.lst,$(notdir $<)),-gstabs,--listing-cont-lines=100


#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min

# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt

# If this is left blank, then it will use the Standard printf version.
#PRINTF_LIB = 
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)

# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min

# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt

# If this is left blank, then it will use the Standard scanf version.
#SCANF_LIB = 
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)

#MATH_LIB = -lm

ifeq ($(OPT_PRINTF),min)
PRINTF_LIB = $(PRINTF_LIB_MIN)
else ifeq ($(OPT_PRINTF),float)
PRINTF_LIB = $(PRINTF_LIB_FLOAT)
MATH_LIB = -lm
else
PRINTF_LIB = 
endif

ifeq ($(OPT_SCANF),min)
SCANF_LIB = $(SCANF_LIB_MIN)
else ifeq ($(OPT_SCANF),float)
SCANF_LIB = $(SCANF_LIB_FLOAT)
MATH_LIB = -lm
else
SCANF_LIB = 
endif

#---------------- Linker Options ----------------
#  -Wl,...:     tell GCC to pass this to linker.
#    -Map:      create map file
#    --cref:    add cross reference to  map file

LDFLAGS = -Wl,-Map=$(WORKINGDIR)/$(TARGET).map,--gc-sections,--print-gc-sections,--cref

ifeq ($(FLTO_SUP),yes)
LDFLAGS += -Wl,-flto
endif

LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)


## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings



#---------------- Programming Options (avrdude) ----------------

ifeq ($(MCU),attiny13a)
AVRDUDE_MCU = t13
else ifeq ($(MCU),attiny2313a)
AVRDUDE_MCU = t2313
else ifeq ($(MCU),attiny85)
AVRDUDE_MCU = t85
else ifeq ($(MCU),atmega8a)
AVRDUDE_MCU = m8
else ifeq ($(MCU),atmega328p)
AVRDUDE_MCU = m328p
else ifeq ($(MCU),atmega128a)
AVRDUDE_MCU = m128
else
AVRDUDE_MCU = 
endif

# Programming hardware
# Type: avrdude -c ?
#       avrdude -p ?
# to get a full listing.
#
# Valid programmers: arduino usbtiny usbasp

AVRDUDE_PROGRAMMER=arduino
AVRDUDE_PORT=COM4
AVRDUDE_BAUDRATE=250000

AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex

ifeq ($(AVRDUDE_PROGRAMMER),arduino)
AVRDUDE_WRITE_EEPROM =
else
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
endif 

# Disables the default behaviour of reading out the fuses three times before
# programming,then verifying at the end of programming that the fuses have not changed.
AVRDUDE_NOSAFE = -u

# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y

# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V

# Increase verbosity level.  Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> 
# to submit bug reports.
# AVRDUDE_VERBOSE = -v
# AVRDUDE_VERBOSE = -v -v
# AVRDUDE_VERBOSE = -v -v -v
# AVRDUDE_VERBOSE = -v -v -v -v

# Disable auto erase for flash memory
# AVRDUDE_NOEEPAUTOERASE = -D

AVRDUDE_FLAGS  = -c $(AVRDUDE_PROGRAMMER) -p $(AVRDUDE_MCU)
ifeq ($(AVRDUDE_PROGRAMMER),arduino)
AVRDUDE_FLAGS += -P $(AVRDUDE_PORT) -b $(AVRDUDE_BAUDRATE)
endif
AVRDUDE_FLAGS += $(AVRDUDE_NOSAFE)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
AVRDUDE_FLAGS += $(AVRDUDE_NOEEPAUTOERASE)


#============================================================================

# Define programs and commands.
CC = @avr-gcc
OBJCOPY = @avr-objcopy
OBJDUMP = @avr-objdump
SIZE = @avr-size
AVRDUDE = @avrdude
REMOVE = @rm -f


# Define Messages
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:


# Define all object files.
OBJ = $(patsubst %.c,$(WORKINGDIR)/%.o,$(notdir $(CSRC))) $(patsubst %.S,$(WORKINGDIR)/%.o,$(notdir $(ASRC)))

# Define all listing files.
LST = $(patsubst %.c,$(WORKINGDIR)/%.lst,$(notdir $(CSRC))) $(patsubst %.S,$(WORKINGDIR)/%.lst,$(notdir $(ASRC)))

# Compiler flags to generate dependency files.
GENDEPFLAGS = -MD -MP -MF $(WORKINGDIR)/$(@F).d


# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. $(ASFLAGS)


# Default target.
all: gccversion build size

# Display compiler version information.
# $(shell mkdir $(WORKINGDIR)>NUL)
gccversion:
	-$(CC) -dumpversion
	-$(shell mkdir $(WORKINGDIR))


size: $(WORKINGDIR)/${TARGET}.elf
	$(SIZE) $<


build: elf lss hex eep

elf: $(WORKINGDIR)/$(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(WORKINGDIR)/$(TARGET).lss 

.SECONDARY : $(WORKINGDIR)/$(TARGET).elf
.PRECIOUS : $(OBJ)

# Create preprocessed source for use in sending a bug report.
%.i: %.c
	$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 


# Create assembler file from C source files.
%.S : %.c
	$(CC) -S $(ALL_CFLAGS) $< -o $@


# Assemble: create object files from assembler source files.
$(WORKINGDIR)/%.o: %.S
	@echo $(MSG_ASSEMBLING) $<
	$(CC) -c $(ALL_ASFLAGS) $< -o $@

# Compile: create object files from C source files.
$(WORKINGDIR)/%.o: %.c
	@echo $(MSG_COMPILING) $<
	$(CC) -c $(ALL_CFLAGS) $< -o $@ 


# Link: create ELF output file from object files.

$(WORKINGDIR)/$(TARGET).elf: $(OBJ)
	@echo $(MSG_LINKING) $@
	$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)


# Create extended listing file from ELF output file.
%.lss: %.elf
	@echo $(MSG_EXTENDED_LISTING) $@
	$(OBJDUMP) -h -S $< > $@


# Create final output files (.hex, .eep) from ELF output file.

$(TARGET).hex: $(WORKINGDIR)/$(TARGET).elf
	@echo $(MSG_FLASH) $@
	$(OBJCOPY) -O $(FORMAT) $(HEX_FLASH_FLAGS) $< $@


$(TARGET).eep: $(WORKINGDIR)/$(TARGET).elf
	@echo $(MSG_EEPROM) $@
	$(OBJCOPY) $(HEX_EEPROM_FLAGS) -O $(FORMAT) $< $@


# Program the device.  
flash: $(TARGET).hex $(TARGET).eep
	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)

# Read EEPROM
readeeprom:
	$(AVRDUDE) $(AVRDUDE_FLAGS) -U eeprom:r:eeprom_dump.bin:r

# Check MCU
check:
	$(AVRDUDE) $(AVRDUDE_FLAGS) -q

# Target: clean project.
clean:
	@echo $(MSG_CLEANING) $(TARGET).hex
	-$(REMOVE) $(TARGET).hex
	@echo $(MSG_CLEANING) $(TARGET).eep
	-$(REMOVE) $(TARGET).eep
	@echo $(MSG_CLEANING) $(WORKINGDIR)/$(TARGET).elf
	-$(REMOVE) $(WORKINGDIR)/$(TARGET).elf
	@echo $(MSG_CLEANING) $(WORKINGDIR)/$(TARGET).map
	-$(REMOVE) $(WORKINGDIR)/$(TARGET).map
	@echo $(MSG_CLEANING) $(WORKINGDIR)/$(TARGET).lss
	-$(REMOVE) $(WORKINGDIR)/$(TARGET).lss
	@echo $(MSG_CLEANING) $(OBJ)
	-$(REMOVE) $(OBJ)
	@echo $(MSG_CLEANING) $(LST)
	-$(REMOVE) $(LST)
	@echo $(MSG_CLEANING) $(OBJ:.o=.s)
	-$(REMOVE) $(OBJ:.o=.s)
	@echo $(MSG_CLEANING) $(OBJ:.o=.o.d)
	-$(REMOVE) $(OBJ:.o=.o.d)


# Listing of phony targets.
.PHONY : all gccversion build size clean flash
