PROJECT_NAME := naga

export OUTPUT_FILENAME
#MAKEFILE_NAME := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
MAKEFILE_NAME := $(MAKEFILE_LIST)
MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) )

TEMPLATE_PATH = .
ifeq ($(OS),Windows_NT)
include $(TEMPLATE_PATH)/Makefile.windows
else
include $(TEMPLATE_PATH)/Makefile.posix
endif

# Path to naga /lib directory.
NAGA_LIB_PATH := $(abspath ../../lib)
# Path to naga's own source and header files
NAGA_SRC_PATH := $(abspath ../../src)
# Path to nRF51 SDK source and header files
NRF51_SDK_PATH := $(NAGA_LIB_PATH)/nrf51_sdk

MK := mkdir
RM := rm -rf

#echo suspend
ifeq ("$(VERBOSE)","1")
NO_ECHO :=
else
NO_ECHO := @
endif

# Toolchain commands
CC              := '$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-gcc'
AS              := '$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-as'
AR              := '$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-ar' -r
LD              := '$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-ld'
NM              := '$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-nm'
OBJDUMP         := '$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-objdump'
OBJCOPY         := '$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-objcopy'
SIZE            := '$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-size'

#function for removing duplicates in a list
remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1))))


# nRF51 SDK C files
C_SOURCE_FILES = \
$(NRF51_SDK_PATH)/libraries/button/app_button.c \
$(NRF51_SDK_PATH)/libraries/util/app_error.c \
$(NRF51_SDK_PATH)/libraries/timer/app_timer.c \
$(NRF51_SDK_PATH)/libraries/pwm/app_pwm.c \
$(NRF51_SDK_PATH)/libraries/trace/app_trace.c \
$(NRF51_SDK_PATH)/libraries/util/nrf_assert.c \
$(NRF51_SDK_PATH)/libraries/util/app_util_platform.c \
$(NRF51_SDK_PATH)/drivers_nrf/delay/nrf_delay.c \
$(NRF51_SDK_PATH)/drivers_nrf/common/nrf_drv_common.c \
$(NRF51_SDK_PATH)/drivers_nrf/gpiote/nrf_drv_gpiote.c \
$(NRF51_SDK_PATH)/drivers_nrf/pstorage/pstorage.c \
$(NRF51_SDK_PATH)/drivers_nrf/ppi/nrf_drv_ppi.c \
$(NRF51_SDK_PATH)/drivers_nrf/timer/nrf_drv_timer.c \
$(NRF51_SDK_PATH)/ble/common/ble_advdata.c \
$(NRF51_SDK_PATH)/ble/common/ble_conn_params.c \
$(NRF51_SDK_PATH)/ble/common/ble_srv_common.c \
$(NRF51_SDK_PATH)/ble/ble_advertising/ble_advertising.c \
$(NRF51_SDK_PATH)/ble/device_manager/device_manager_peripheral.c \
$(NRF51_SDK_PATH)/toolchain/system_nrf51.c \
$(NRF51_SDK_PATH)/softdevice/common/softdevice_handler/softdevice_handler.c

# Probably should not include this, since we are using a softdevice and have a handler for that.
#$(NRF51_SDK_PATH)/drivers_nrf/nrf_soc_nosd/nrf_soc.c

# Deactivated Nordic modules
# $(NRF51_SDK_PATH)/libraries/uart/app_uart.c \
# $(NRF51_SDK_PATH)/drivers_nrf/uart/nrf_drv_uart.c \

# SEGGER RTT C files
C_SOURCE_FILES += \
$(NAGA_LIB_PATH)/rtt/RTT/SEGGER_RTT.c \
$(NAGA_LIB_PATH)/rtt/RTT/SEGGER_RTT_printf.c \
$(NAGA_LIB_PATH)/rtt/Syscalls/RTT_Syscalls_GCC.c

# libfixmath C files
C_SOURCE_FILES += \
$(NAGA_LIB_PATH)/fixmath/fix16.c \
$(NAGA_LIB_PATH)/fixmath/fract32.c \
$(NAGA_LIB_PATH)/fixmath/uint32.c

# naga's own C files
C_SOURCE_FILES += $(NAGA_SRC_PATH)/main.c \
$(NAGA_SRC_PATH)/bsp/bsp.c \
$(NAGA_SRC_PATH)/bsp/bsp_btn_ble.c \
$(NAGA_SRC_PATH)/model/m_common.c \
$(NAGA_SRC_PATH)/model/m_light.c \
$(NAGA_SRC_PATH)/model/m_linflux.c \
$(NAGA_SRC_PATH)/model/m_sun.c \
$(NAGA_SRC_PATH)/driver/d_pwm.c \
$(NAGA_SRC_PATH)/service/s_light.c \
$(NAGA_SRC_PATH)/service/s_whisper.c \
$(NAGA_SRC_PATH)/service/debug.c \
$(NAGA_SRC_PATH)/controller/c_color_run.c \
$(NAGA_SRC_PATH)/controller/c_interactive.c \
$(NAGA_SRC_PATH)/controller/c_rhythm.c

# nRF51 SDK: assembly files common to all targets
ASM_SOURCE_FILES  = $(NRF51_SDK_PATH)/toolchain/gcc/gcc_startup_nrf51.s

# SEGGER RTT
INC_PATHS = -I$(NAGA_LIB_PATH)/rtt/RTT

# nRF51 SDK: includes common to all targets
INC_PATHS += -I$(NRF51_SDK_PATH)/device
INC_PATHS += -I$(NRF51_SDK_PATH)/libraries/util
INC_PATHS += -I$(NRF51_SDK_PATH)/libraries/uart
INC_PATHS += -I$(NRF51_SDK_PATH)/libraries/fifo
INC_PATHS += -I$(NRF51_SDK_PATH)/libraries/trace
INC_PATHS += -I$(NRF51_SDK_PATH)/libraries/timer
INC_PATHS += -I$(NRF51_SDK_PATH)/libraries/button
INC_PATHS += -I$(NRF51_SDK_PATH)/libraries/pwm
INC_PATHS += -I$(NRF51_SDK_PATH)/drivers_nrf/pstorage
INC_PATHS += -I$(NRF51_SDK_PATH)/drivers_nrf/common
INC_PATHS += -I$(NRF51_SDK_PATH)/drivers_nrf/gpiote
INC_PATHS += -I$(NRF51_SDK_PATH)/drivers_nrf/delay
INC_PATHS += -I$(NRF51_SDK_PATH)/drivers_nrf/timer
INC_PATHS += -I$(NRF51_SDK_PATH)/drivers_nrf/ppi
INC_PATHS += -I$(NRF51_SDK_PATH)/drivers_nrf/hal
INC_PATHS += -I$(NRF51_SDK_PATH)/toolchain/gcc
INC_PATHS += -I$(NRF51_SDK_PATH)/toolchain
INC_PATHS += -I$(NRF51_SDK_PATH)/ble/common
INC_PATHS += -I$(NRF51_SDK_PATH)/ble/ble_advertising
INC_PATHS += -I$(NRF51_SDK_PATH)/ble/device_manager
INC_PATHS += -I$(NRF51_SDK_PATH)/softdevice/common/softdevice_handler
INC_PATHS += -I$(NRF51_SDK_PATH)/softdevice/s110/headers

# libfixmath library headers
INC_PATHS += -I$(NAGA_LIB_PATH)/fixmath

# Do not include /drivers_nrf/config!
# This seems to be the default config, whereas we should actually use our own local one instead.
# INC_PATHS += -I$(NRF51_SDK_PATH)/drivers_nrf/config

# naga's subpaths for header files
INC_PATHS += -I$(NAGA_SRC_PATH)/config
INC_PATHS += -I$(NAGA_SRC_PATH)/table
INC_PATHS += -I$(NAGA_SRC_PATH)/bsp
INC_PATHS += -I$(NAGA_SRC_PATH)/model
INC_PATHS += -I$(NAGA_SRC_PATH)/driver
INC_PATHS += -I$(NAGA_SRC_PATH)/service
INC_PATHS += -I$(NAGA_SRC_PATH)/controller

# Deactivated modules
# INC_PATHS += -I$(NRF51_SDK_PATH)/drivers_nrf/uart

OBJECT_DIRECTORY = ../../_build
LISTING_DIRECTORY = $(OBJECT_DIRECTORY)
OUTPUT_BINARY_DIRECTORY = $(OBJECT_DIRECTORY)

# Sorting removes duplicates
BUILD_DIRECTORIES := $(sort $(OBJECT_DIRECTORY) $(OUTPUT_BINARY_DIRECTORY) $(LISTING_DIRECTORY) )

#flags common to all targets
# Rigado
# CFLAGS = -DBOARD03
# Nordic
CFLAGS += -DBOARD04
# Turn this option on to use Nordic's app_trace library. Should not use this when also using SEGGER RTT.
# CFLAGS += -DENABLE_DEBUG_LOG_SUPPORT
CFLAGS += -DSOFTDEVICE_PRESENT
CFLAGS += -DNRF51
# the S110 softdevice that we are using
CFLAGS += -DS110
CFLAGS += -DBLE_STACK_SUPPORT_REQD
CFLAGS += -DSWI_DISABLE0
# target CPU architecture
CFLAGS += -mcpu=cortex-m0
# use thumb instructions
CFLAGS += -mthumb
# ARM's AAPCS ABI
CFLAGS += -mabi=aapcs
CFLAGS += -Wall
#CFLAGS += -Werror
# nRF51 does not have an FPU
CFLAGS += -mfloat-abi=soft
# keep every function in separate section. This will allow linker to dump unused functions
CFLAGS += -ffunction-sections
CFLAGS += -fdata-sections
CFLAGS += -fno-strict-aliasing
# Do not optimize built-in functions as such. Setting breakpoints is not possible for builtin functions.
# raph: Nordic suggested this flag in the makefile template. Why do we need
# this?
CFLAGS += -fno-builtin
# Use the smallest possible data type for enums.
CFLAGS += --short-enums
# Turn off format warnings since nRF51 SDK 10.0 has bugs
CFLAGS += -Wformat=0
CFLAGS += -std=gnu11

# keep every function in separate section. This will allow linker to dump unused functions
LDFLAGS += -Xlinker -Map=$(LISTING_DIRECTORY)/$(OUTPUT_FILENAME).map
LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT)
LDFLAGS += -mcpu=cortex-m0
# let linker to dump unused sections
#TODO: Get back to dumping unused sections
LDFLAGS += -Wl,--gc-sections
# use newlib in nano version
LDFLAGS += --specs=nano.specs -lc -lnosys

# Optional: Add float support for printf
# LDFLAGS += -u _printf_float

# C standard math library
# LIBS = -lm
# ARM CMSIS DSP optimized math library
LIBS = -L$(NAGA_LIB_PATH)/cmsis -larm_cortexM0l_math

# Assembler flags
ASMFLAGS += -x assembler-with-cpp
ASMFLAGS += -DBOARD_PCA10028
ASMFLAGS += -DSOFTDEVICE_PRESENT
ASMFLAGS += -DNRF51
ASMFLAGS += -DS110
ASMFLAGS += -DBLE_STACK_SUPPORT_REQD
ASMFLAGS += -DSWI_DISABLE0

# Only plain C files.
C_SOURCE_FILE_NAMES = $(notdir $(C_SOURCE_FILES))
C_PATHS = $(call remduplicates, $(dir $(C_SOURCE_FILES) ) )
C_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_FILE_NAMES:.c=.o) )

# Assembler files.
ASM_SOURCE_FILE_NAMES = $(notdir $(ASM_SOURCE_FILES))
ASM_PATHS = $(call remduplicates, $(dir $(ASM_SOURCE_FILES) ))
ASM_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(ASM_SOURCE_FILE_NAMES:.s=.o) )

vpath %.c $(C_PATHS)
vpath %.s $(ASM_PATHS)

OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS)

#default target - first one defined
default: debug

# debug with clean before it
debug_clean: clean debug

# Use -O2 instead of -O3, because the latter produces bigger code which might actually be slower.	
debug: CFLAGS += -Og -g3 -DDEBUG -DDEBUG_ENABLED=1
debug: nrf51822_xxac_s110

test: CFLAGS += -Og -g3 -DDEBUG -DDEBUG_ENABLED=1 -DDEBUG_TESTS
test: nrf51822_xxac_s110
	
# test with clean before it
test_clean: clean test

#target for printing all targets
help:
	@echo following targets are available:
	@echo 	nrf51822_xxac_s110

nrf51822_xxac_s110: OUTPUT_FILENAME := naga_nrf51822_xxac_s110
nrf51822_xxac_s110: LINKER_SCRIPT=naga_gcc_nrf51.ld
nrf51822_xxac_s110: $(BUILD_DIRECTORIES) $(OBJECTS)
	@echo Linking target: $(OUTPUT_FILENAME).out
	$(NO_ECHO)$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
	$(NO_ECHO)$(MAKE) -f $(MAKEFILE_NAME) -C $(MAKEFILE_DIR) -e finalize

## Create build directories
$(BUILD_DIRECTORIES):
	echo $(MAKEFILE_NAME)
	$(MK) $@

# Create objects from C SRC files
$(OBJECT_DIRECTORY)/%.o: %.c
	@echo Compiling file: $(notdir $<)
	$(NO_ECHO)$(CC) $(CFLAGS) $(INC_PATHS) -c -o $@ $<

# Assemble files
$(OBJECT_DIRECTORY)/%.o: %.s
	@echo Compiling file: $(notdir $<)
	$(NO_ECHO)$(CC) $(ASMFLAGS) $(INC_PATHS) -c -o $@ $<

# Link
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out: $(BUILD_DIRECTORIES) $(OBJECTS)
	@echo Linking target: $(OUTPUT_FILENAME).out
	$(NO_ECHO)$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out

## Create binary .bin file from the .out file
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin: $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
	@echo Preparing: $(OUTPUT_FILENAME).bin
	$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin

## Create binary .hex file from the .out file
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex: $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
	@echo Preparing: $(OUTPUT_FILENAME).hex
	$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex

finalize: genbin genhex echosize

genbin:
	@echo Preparing: $(OUTPUT_FILENAME).bin
	$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin

## Create binary .hex file from the .out file
genhex:
	@echo Preparing: $(OUTPUT_FILENAME).hex
	$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex

echosize:
	-@echo ''
	$(NO_ECHO)$(SIZE) $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
	-@echo ''

clean:
	$(RM) $(BUILD_DIRECTORIES)

cleanobj:
	$(RM) $(BUILD_DIRECTORIES)/*.o
