ifndef NRF52_SDK_ROOT
  $(error NRF52_SDK_ROOT not defined! You must specify where nRF52 SDK resides!)
endif

ifneq ($(filter %.flash erase,$(MAKECMDGOALS)),)
ifeq ($(NRF52_JLINK_PATH),)
NRF52_JLINK_PATH=$(shell location=$$(which JLinkExe) && dirname $$location)
endif
ifeq ($(NRF52_JLINK_PATH),)
  $(error JLink not found in PATH and NRF52_JLINK_PATH path is not defined)
endif
endif

ifeq ($(CONTIKI_WITH_RIME),1)
  $(error Rime stack is not supported!)
endif

ifneq ($(CONTIKI_WITH_IPV6),1)
  $(error Only IPv6 stack is supported!)
endif

$(info SDK: $(NRF52_SDK_ROOT))

ifeq ($(NRF52_DK_REVISION),)
NRF52_DK_REVISION=pca10040
endif

ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1)
  ifeq ($(NRF52_SOFTDEVICE),)
    NRF52_SOFTDEVICE := $(shell find $(NRF52_SDK_ROOT) -name *iot*_softdevice.hex | head -n 1)
  endif
  $(info SoftDevice: $(NRF52_SOFTDEVICE))
  LINKER_SCRIPT := $(CONTIKI_CPU)/ld/nrf52-$(NRF52_DK_REVISION)-sd.ld
else
  LINKER_SCRIPT := $(CONTIKI_CPU)/ld/nrf52.ld
endif

OUTPUT_FILENAME := $(CONTIKI_PROJECT)
MAKEFILE_NAME := $(MAKEFILE_LIST)
MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) ) 

TEMPLATE_PATH = $(NRF52_SDK_ROOT)/components/toolchain/gcc

OBJECT_DIRECTORY = $(OBJECTDIR)
LISTING_DIRECTORY := $(OBJECTDIR)
OUTPUT_BINARY_DIRECTORY := bin_$(TARGET)

MK := mkdir
RM := rm -rf

# Toolchain commands
CC := arm-none-eabi-gcc
AS := arm-none-eabi-as
AR := arm-none-eabi-ar
LD := arm-none-eabi-ld
NM := arm-none-eabi-nm
OBJDUMP := arm-none-eabi-objdump
OBJCOPY := arm-none-eabi-objcopy
SIZE := arm-none-eabi-size

# JLink
JLINK := $(NRF52_JLINK_PATH)/JLinkExe
JLINK_OPTS = -Device NRF52 -if swd -speed 1000
ifneq ($(NRF52_JLINK_SN),)
JLINK_OPTS += -SelectEmuBySN $(NRF52_JLINK_SN)
endif

#function for removing duplicates in a list
remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1))))

### CPU-dependent directories
CONTIKI_CPU_DIRS += . dev ble #compat

### CPU-dependent source files
CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart0.c putchar.c watchdog.c

ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1)
CONTIKI_CPU_SOURCEFILES += ble-core.c ble-mac.c
endif

CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES)

#source common to all targets
C_SOURCE_FILES += $(NRF52_SDK_ROOT)/components/drivers_nrf/common/nrf_drv_common.c \
                  $(NRF52_SDK_ROOT)/components/drivers_nrf/gpiote/nrf_drv_gpiote.c \
                  $(NRF52_SDK_ROOT)/components/drivers_nrf/rtc/nrf_drv_rtc.c \
                  $(NRF52_SDK_ROOT)/components/drivers_nrf/clock/nrf_drv_clock.c \
                  $(NRF52_SDK_ROOT)/components/drivers_nrf/timer/nrf_drv_timer.c \
                  $(NRF52_SDK_ROOT)/components/drivers_nrf/wdt/nrf_drv_wdt.c \
                  $(NRF52_SDK_ROOT)/components/drivers_nrf/rng/nrf_drv_rng.c \
                  $(NRF52_SDK_ROOT)/components/drivers_nrf/delay/nrf_delay.c \
                  $(NRF52_SDK_ROOT)/components/drivers_nrf/uart/nrf_drv_uart.c \
                  $(NRF52_SDK_ROOT)/components/libraries/util/app_error.c \
                  $(NRF52_SDK_ROOT)/components/toolchain/system_nrf52.c
                  
ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1)
C_SOURCE_FILES += $(NRF52_SDK_ROOT)/components/softdevice/common/softdevice_handler/softdevice_handler.c \
                  $(NRF52_SDK_ROOT)/components/ble/common/ble_advdata.c
else
C_SOURCE_FILES += $(NRF52_SDK_ROOT)/components/libraries/fifo/app_fifo.c \
                  $(NRF52_SDK_ROOT)/components/libraries/util/app_util_platform.c
endif

#assembly files common to all targets
ASM_SOURCE_FILES  = $(NRF52_SDK_ROOT)/components/toolchain/gcc/gcc_startup_nrf52.s

#includes common to all targets
INC_PATHS += components/drivers_nrf/gpiote
INC_PATHS += components/drivers_nrf/hal
INC_PATHS += components/drivers_nrf/config
INC_PATHS += components/drivers_nrf/delay
INC_PATHS += components/drivers_nrf/uart
INC_PATHS += components/drivers_nrf/common
INC_PATHS += components/drivers_nrf/rtc
INC_PATHS += components/drivers_nrf/wdt
INC_PATHS += components/drivers_nrf/rng
INC_PATHS += components/drivers_nrf/clock
INC_PATHS += components/drivers_nrf/timer
INC_PATHS += components/libraries/util
INC_PATHS += components/libraries/timer
INC_PATHS += components/device
INC_PATHS += components/toolchain/gcc
INC_PATHS += components/toolchain
INC_PATHS += examples/bsp

ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1)
INC_PATHS += components/softdevice/s1xx_iot/headers
INC_PATHS += components/softdevice/s1xx_iot/headers/nrf52
INC_PATHS += components/softdevice/common/softdevice_handler
INC_PATHS += components/ble/common
INC_PATHS += components/iot/common
INC_PATHS += components/iot/ble_ipsp
else
INC_PATHS += components/drivers_nrf/nrf_soc_nosd
INC_PATHS += components/libraries/fifo
endif

EXTERNALDIRS += $(addprefix $(NRF52_SDK_ROOT)/, $(INC_PATHS))

# Sorting removes duplicates
BUILD_DIRECTORIES := $(sort $(OUTPUT_BINARY_DIRECTORY) $(LISTING_DIRECTORY))

# Clean files and directories
CLEAN += bin_$(TARGET) lst_$(TARGET) nrf52832.a *.elf *.hex

#flags common to all targets
ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1)
CFLAGS += -DSOFTDEVICE_PRESENT
CFLAGS += -DS132
endif

ifeq ($(SMALL),1)
CFLAGS += -Os
else
CFLAGS += -O2
endif

CFLAGS += -DNRF52
CFLAGS += -DBOARD_$(shell echo $(NRF52_DK_REVISION) | tr a-z A-Z)
CFLAGS += -D__HEAP_SIZE=512
CFLAGS += -DSWI_DISABLE0
CFLAGS += -DCONFIG_GPIO_AS_PINRESET
CFLAGS += -DBLE_STACK_SUPPORT_REQD
CFLAGS += -mcpu=cortex-m4
CFLAGS += -mthumb -mabi=aapcs --std=gnu99
CFLAGS += -Wall -Werror
CFLAGS += -ggdb
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
# keep every function in separate section. This will allow linker to dump unused functions
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
CFLAGS += -fno-builtin --short-enums

# 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-m4
LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
# let linker to dump unused sections
LDFLAGS += -Wl,--gc-sections
# use newlib in nano version
LDFLAGS += --specs=nano.specs -lc -lnosys

# Assembler flags
ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1)
ASMFLAGS += -DSOFTDEVICE_PRESENT
ASMFLAGS += -DS132
endif
ASMFLAGS += -x assembler-with-cpp
ASMFLAGS += -DSWI_DISABLE0
ASMFLAGS += -DNRF52
ASMFLAGS += -DBOARD_$(shell echo $(NRF52_DK_REVISION) | tr a-z A-Z)
ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET
ASMFLAGS += -DBLE_STACK_SUPPORT_REQD

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) )

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)

TARGET_LIBS= nrf52832.a $(NRF52_SDK_ROOT)/components/iot/ble_6lowpan/lib/ble_6lowpan.a

### Don't treat the .elf as intermediate
.PRECIOUS: %.hex %.bin

nrf52832.a: $(OBJECTS)
	$(TRACE_AR)
	$(Q)$(AR) $(AROPTS) $@ $^

### Compilation rules
CUSTOM_RULE_LINK=1

%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(TARGET_LIBS)
	$(TRACE_LD)
	$(Q)$(CC) $(LDFLAGS) ${filter %o %.co %.a,$^} -o $@
	
# Assemble files
$(OBJECT_DIRECTORY)/%.o: %.s
	@echo Compiling file: $(notdir $<)
	$(Q)$(CC) $(ASMFLAGS) $(addprefix -I$(NRF52_SDK_ROOT)/, $(INC_PATHS)) -c -o $@ $<

# Create binary file from the .out file
%.bin: %.elf
	@echo Preparing: $@
	$(Q)$(OBJCOPY) -O binary $^ $@

# Create binary .hex file from the .out file
%.hex: %.elf 
	@echo Preparing: $@
	$(Q)$(OBJCOPY) -O ihex $^ $@

### We don't really need the .hex and .bin for the .$(TARGET) but let's make
### sure they get built
%.$(TARGET): %.elf %.hex %.bin
	cp $*.elf $@
	$(Q)$(SIZE) $@
	
%.jlink:
	sed -e 's/#OUTPUT_FILENAME#/$*.hex/' $(CONTIKI_CPU)/flash.jlink > $@

%.flash: %.hex %.jlink 
	@echo Flashing: $^
	$(JLINK) $(JLINK_OPTS) -CommanderScript $*.jlink

softdevice.jlink:
	sed -e 's,#OUTPUT_FILENAME#,$(NRF52_SOFTDEVICE),' $(CONTIKI_CPU)/flash.jlink > $@
	
softdevice.flash: softdevice.jlink
	@echo Flashing: $(notdir $(NRF52_SOFTDEVICE))
	$(JLINK) $(JLINK_OPTS) -CommanderScript $^

erase:
	$(JLINK) $(JLINK_OPTS) -CommanderScript $(CONTIKI_CPU)/erase.jlink

.PHONY: softdevice.jlink