BUILD_MODE = Debug

# Toolchain prefix (arm-elf- -> arm-elf-gcc.exe)
TCHAIN_PREFIX = arm-none-eabi-
#TCHAIN_PREFIX = arm-eabi-
#TCHAIN_PREFIX = arm-elf-
# cs-rm is a standard GNU rm which gets installed with CS G++ lite.
# Just the filename is different. Use REMOVE_CMD=rm in environments
# with rm (Linux, BSD, msys, Cygwin etc.)
REMOVE_CMD=rm
#REMOVE_CMD=cs-rm

# YES enables -mthumb option to flags for source-files listed
# in SRC and CPPSRC and -mthumb-interwork option for all source
USE_THUMB_MODE = YES
#USE_THUMB_MODE = NO

# MCU name, submodel and board
# - MCU used for compiler-option (-mcpu)
# - SUBMDL used for linker-script name (-T) and passed as define
# - BOARD just passed as define (don't used '-' characters)
MCU      = cortex-m3
CHIP     = STM32F103RB

# *** This example only supports "FLASH_RUN" ***
# RUN_MODE is passed as define and used for the linker-script filename,
# the user has to implement the necessary operations for
# the used mode (i.e. no copy of .data, remapping...)
# Create FLASH-Image
RUN_MODE = Joystik
# Create RAM-Image
#RUN_MODE=RAM_RUN

# *** This example only supports "VECT_TAB_FLASH" ***
# Exception-vectors placement option is just passed as define,
# the user has to implement the necessary operations (i.e. remapping)
# Exception vectors in FLASH:
VECTOR_TABLE_LOCATION=VECT_TAB_FLASH
# Exception vectors in RAM:
#VECTOR_TABLE_LOCATION=VECT_TAB_RAM

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

# Directory for output files (lst, obj, dep, elf, sym, map, hex, bin etc.)
OUTDIR = $(TARGET)\$(BUILD_MODE)\bin
BUILDDIR = $(TARGET)\$(BUILD_MODE)\obj

# Utility variables
INCLUDES = \
	. \
	cmsis \
	cmsis_boot \
	stm_lib/inc \
	oculus/inc \
	stm_lib/inc \
	stm_usb/inc \
	usb/inc

# List C source files here. (C dependencies are automatically generated.)
# use file-extension c for "c-only"-files
SRC = \
	cmsis/core_cm3.c \
	cmsis_boot/system_stm32f10x.c \
	cmsis_boot/startup/startup_stm32f10x_md.c \
	oculus/src/data_packet.c \
	oculus/src/delay.c \
	oculus/src/gpio.c \
	oculus/src/invensense.c \
	oculus/src/spi.c \
	oculus/src/filter.c \
	$(wildcard stm_lib/src/*.c) \
	$(wildcard stm_usb/src/*.c) \
 	syscalls/syscalls.c \
	$(wildcard usb/src/*.c) \
	stm32_it.c \
	hw_config.c \
	main.c

#	oculus/src/i2c.c \


# List C source files here which must be compiled in ARM-Mode (no -mthumb).
# use file-extension c for "c-only"-files
## just for testing, timer.c classcould be compiled in thumb-mode too
SRCARM =

# 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 = vectors.S

# List Assembler source files here which must be assembled in ARM-Mode.
#ASRCARM  = vectors.S

# Place project-specific -D (define) and/or -U options for C here.
CDEFS += -D$(CHIP) -DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER -D__ASSEMBLY__

#     
#CDEFS += -DUSE_MAGNETOMETER
#   3-  HID ,   -   2  7  8
#CDEFS += -DHID_JOYSTIK

# ,  X - -, Y - , Z - .
# X - -, Y - , Z - 
#CDEFS += X_RIGHT

# Place project-specific -D and/or -U options for
# Assembler with preprocessor here.
ADEFS =

# List any extra directories to look for include files here.
#    Each directory must be seperated by a space.
EXTRAINCDIRS  = $(INCLUDES)

# Extra libraries
#    Each library-name must be seperated by a space.
#    i.e. to link with libxyz.a, libabc.a and libefsl.a:
#     EXTRA_LIBS = xyz abc efsl
#    for newlib-lpc (file: libnewlibc-lpc.a):
#     EXTRA_LIBS = newlib-lpc
EXTRA_LIBS =

# List non-source files which should trigger build here
#    Typically the Makefile and selected header-files
#    Entries must be seperated by a space.
BUILDONCHANGE = Makefile

# Path to linker-scripts (see -T option)
LINKERSCRIPTPATH = .

# List any directories with files included from linker-scripts.
#    Each directory must be seperated by a space.
LINKERSCRIPTINC  = .

ifeq ($(BUILD_MODE),Debug)
DOPT = -g
else
DOPT = -s
endif

# Compiler flags.

#  -g*:          generate debugging information
#  -O*:          optimization level
#  -f...:        tuning, see GCC manual
#  -Wall...:     warning level
#  -Wa,...:      tell GCC to pass this to the assembler.
#    -adhlns...: create assembler listing
#
# Flags for C and C++ (arm-elf-gcc/arm-elf-g++)
CFLAGS = -mcpu=$(MCU) -mthumb -Wall -ffunction-sections $(DOPT) -Os -flto -fno-builtin -std=c99
CFLAGS += $(CDEFS)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I.

# -L${linkdir};
# Linker flags.
#  -Wl,...:     tell GCC to pass this to linker.
#    -Map:      create map file
#    --cref:    add cross reference to  map file
LDFLAGS = -mcpu=$(MCU) -mthumb $(DOPT) -nostartfiles -flto -Os -L -lgcc -lc -lm
LDFLAGS += -Wl,-Map=$(BUILDDIR)/$(TARGET).map,--gc-sections,--entry=main
#LDFLAGS += $(patsubst %,-L%,$(LINKERSCRIPTINC))
#LDFLAGS += $(patsubst %,-l%,$(EXTRA_LIBS))

# Set linker-script name depending on selected run-mode and chip
#ifeq ($(RUN_MODE),RAM_RUN)
#LDFLAGS +=-T$(LINKERSCRIPTPATH)/$(CHIP)_ram.ld
#else
#LDFLAGS +=-T$(LINKERSCRIPTPATH)/$(CHIP)_flash.ld
#endif

LDFLAGS += -T./arm-gcc-link.ld

# Assembler flags.
#  -Wa,...:    tell GCC to pass this to the assembler.
#  -ahlns:     create listing
#  -g$(DEBUG): have the assembler create line number information
ASFLAGS  = -mcpu=$(MCU) -mthumb-interwork -I. -x assembler-with-cpp $(DOPT)
ASFLAGS += -D__ASSEMBLY__ $(ADEFS)
ASFLAGS += -Wa,-adhlns=$(addprefix $(BUILDDIR)/, $(notdir $(addsuffix .lst, $(basename $<))))
ASFLAGS += -Wa,-g$(DEBUG)
ASFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))

# Autodetect environment
SHELL   = sh
ifneq ($(or $(COMSPEC), $(ComSpec)),)
$(info COMSPEC detected $(COMSPEC) $(ComSpec))
ifeq ($(findstring cygdrive,$(shell set)),)
SHELL:=$(or $(COMSPEC),$(ComSpec))
SHELL_IS_WIN32=1
REMOVE_CMD:=del /f
else
$(info cygwin detected)
#override user-setting since cygwin has rm
REMOVE_CMD:=rm -f
endif
else
#most probaly a Unix/Linux/BSD system which should have rm
REMOVE_CMD:=rm -f
endif
$(info SHELL is $(SHELL), REMOVE_CMD is $(REMOVE_CMD))

# Define programs and commands.
CC      = $(TCHAIN_PREFIX)gcc
CPP     = $(TCHAIN_PREFIX)g++
AR      = $(TCHAIN_PREFIX)ar
OBJCOPY = $(TCHAIN_PREFIX)objcopy
OBJDUMP = $(TCHAIN_PREFIX)objdump
SIZE    = $(TCHAIN_PREFIX)size
NM      = $(TCHAIN_PREFIX)nm
REMOVE  = $(REMOVE_CMD)

# Define Messages
# English
MSG_BEGIN = --------  begin, mode: $(RUN_MODE)  --------
MSG_END = --------  end  --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after build:
MSG_COMPILING =        " CC      "
MSG_COMPILING_ARM =    " CC_ARM  "
MSG_COMPILINGCPP =     " CPP     "
MSG_COMPILINGCPP_ARM = " CPP_ARM "
MSG_ASSEMBLING =       " AS      "
MSG_ASSEMBLING_ARM =   " AS_ARM  "
MSG_CLEANING = Cleaning project:
MSG_ASMFROMC = "Creating asm-File from C-Source:"
MSG_ASMFROMC_ARM = "Creating asm-File from C-Source (ARM-only):"

# List of all source files.
ALLSRC     = $(SRC)
# List of all source files without directory and file-extension.
ALLSRCBASE = $(notdir $(basename $(ALLSRC)))

# Define all object files.
ALLOBJ     = $(addprefix $(BUILDDIR)/, $(addsuffix .o, $(ALLSRCBASE)))

# Define all listing files (used for make clean).
LSTFILES   = $(addprefix $(BUILDDIR)/, $(addsuffix .lst, $(ALLSRCBASE)))
# Define all depedency-files (used for make clean).
DEPFILES   = $(addprefix $(BUILDDIR)/dep/, $(addsuffix .o.d, $(ALLSRCBASE)))

# Default target.
all: begin gccversion createdirs build end

# Target for the build-sequence.
build: elf hex bin

elf: $(OUTDIR)/$(TARGET).elf
hex: $(OUTDIR)/$(TARGET).hex
bin: $(OUTDIR)/$(TARGET).bin

# Create output directories.
createdirs:
	-@md $(OUTDIR) >NUL 2>&1 || echo "" >NUL
	-@md $(BUILDDIR) >NUL 2>&1 || echo "" >NUL

# Eye candy.
begin:
	@echo $(MSG_BEGIN)

end:
	@echo $(MSG_END)

# Display sizes of sections.
ELFSIZE = $(SIZE) -A $(OUTDIR)/$(TARGET).elf | egrep '^(section|Total|\.(text|data|bss|stack|heap))'
sizebefore:
#	@if [ -f  $(OUTDIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi

sizeafter:
#	@if [ -f  $(OUTDIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
	@echo $(MSG_SIZE_AFTER)
	@$(ELFSIZE)

# Display compiler version information.
gccversion :
	@$(CC) --version

# Create final output file in ihex format from ELF output file (.hex).
%.hex: %.elf
	@echo " HEX  " $@
	@$(OBJCOPY) -O ihex $< $@

# Create final output file in raw binary format from ELF output file (.bin)
%.bin: %.elf
	@echo " BIN  " $@
	@$(OBJCOPY) -O binary $< $@

# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(ALLOBJ)
%.elf:  $(ALLOBJ) $(BUILDONCHANGE)
	@echo " LINK " $@
# use $(CC) for C-only projects or $(CPP) for C++-projects:
ifeq "$(strip $(CPPSRC)$(CPPARM))" ""
	@$(CC) $(CFLAGS) $(ALLOBJ) --output $@ -nostartfiles $(LDFLAGS)
else
	@$(CPP) $(CFLAGS) $(ALLOBJ) --output $@ $(LDFLAGS)
endif

# Compile: create object files from C source files.
define COMPILE_C_TEMPLATE
$(BUILDDIR)/$(notdir $(basename $(1))).o : $(1) $(BUILDONCHANGE)
	@echo " CC  " $$@
	@$(CC) -c $$(CFLAGS) $$< -o $$@
endef
$(foreach src, $(SRC), $(eval $(call COMPILE_C_TEMPLATE, $(src))))

# Target: clean project.
clean: begin clean_list end

clean_list :
	@echo $(MSG_CLEANING)
	@$(REMOVE) $(OUTDIR)\$(TARGET).elf
	@$(REMOVE) $(OUTDIR)\$(TARGET).hex
	@$(REMOVE) $(OUTDIR)\$(TARGET).bin
	@$(REMOVE) $(BUILDDIR)\*.o

# Include the dependency files.
-include $(wildcard $(OUTDIR)\dep\*)

# Listing of phony targets.
.PHONY : all begin end gccversion build elf hex bin lss sym clean clean_list program createdirs
