cmake_minimum_required(VERSION 3.15.3)

# Verbose output (optional)
set(CMAKE_VERBOSE_MAKEFILE ON)

# Toolchain must be set before project()
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/cmake/arm-none-eabi-gcc.cmake)
include(${CMAKE_TOOLCHAIN_FILE})

# Project setup
project(bmd380_central
    VERSION 1.0.0
    LANGUAGES C ASM
)
set(EXECUTABLE ${PROJECT_NAME}.elf)
set(NRF_SDK_DIR ${CMAKE_SOURCE_DIR}/../bmd380_sdk)
#set(LINKER_FILE ${CMAKE_SOURCE_DIR}/linkscripts/nRF52840_XXAA_s140.lds)
set(LINKER_FILE ${CMAKE_SOURCE_DIR}/linkscripts/nRF52840_XXAA_S140_reserve.lds)
set(LINKER_DIR ${CMAKE_SOURCE_DIR}/linkscripts)
set(NRF_SDK_LINKER_DIR ${NRF_SDK_DIR}/modules/nrfx/mdk)
set(SD_LINKER_DIR ${CMAKE_SOURCE_DIR}/SoftdeviceLibraries/hard)


set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
# Define the build type
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Debug")
endif()

message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}")

set(COMMON_COMPILE_OPT
    -mcpu=cortex-m4
    -mfpu=fpv4-sp-d16 
    -mfloat-abi=hard
    -mthumb
    -fdata-sections
    -ffunction-sections
    -Wall
    -Os
    -g3
    -std=gnu99
    -Wno-unused-variable
    -Wno-pointer-sign
    -Wno-array-bounds
)

set(COMMON_COMPILE_DEF
    -DDEBUG=1
    -DNRF52840_XXAA
    -DS140_reserve
    -DCONFIG_GPIO_AS_PINRESET 
    -DRESETHNRF_DFU_SETTINGS_VERSION=2
    -DNRF_SD_BLE_API_VERSION=7
    -D__STACK_SIZE=1024
    -D__HEAP_SIZE=1024
    -DARM_MATH_CM4
    -DSOFTDEVICE_PRESENT
    -DUSE_APP_CONFIG
)

set(COMMON_COMPILE_INC
    ${ARM_TOOLCHAIN_DIR}/../arm-none-eabi/include
    ${CMAKE_SOURCE_DIR}/app
    ${NRF_SDK_DIR}/components/ble/ble_db_discovery
    ${NRF_SDK_DIR}/components/ble/ble_services/ble_dis
    ${NRF_SDK_DIR}/components/ble/ble_services/ble_dis_c
    ${NRF_SDK_DIR}/components/ble/common/
    ${NRF_SDK_DIR}/components/ble/nrf_ble_gatt
    ${NRF_SDK_DIR}/components/ble/nrf_ble_gq
    ${NRF_SDK_DIR}/components/ble/nrf_ble_scan
    ${NRF_SDK_DIR}/components/libraries/atomic
    ${NRF_SDK_DIR}/components/libraries/atomic_flags
    ${NRF_SDK_DIR}/components/libraries/balloc
    ${NRF_SDK_DIR}/components/libraries/delay
    ${NRF_SDK_DIR}/components/libraries/experimental_section_vars
    ${NRF_SDK_DIR}/components/libraries/log
    ${NRF_SDK_DIR}/components/libraries/log/src
    ${NRF_SDK_DIR}/components/libraries/memobj
    ${NRF_SDK_DIR}/components/libraries/queue
    ${NRF_SDK_DIR}/components/libraries/ringbuf
    ${NRF_SDK_DIR}/components/libraries/strerror
    ${NRF_SDK_DIR}/components/libraries/util
    ${NRF_SDK_DIR}/components/softdevice/common
    ${NRF_SDK_DIR}/components/softdevice/mbr/headers
    ${NRF_SDK_DIR}/components/softdevice/s140/headers
    ${NRF_SDK_DIR}/components/toolchain/cmsis/include
    ${NRF_SDK_DIR}/external/fprintf
    ${NRF_SDK_DIR}/external/freertos/portable/CMSIS/nrf52
    ${NRF_SDK_DIR}/external/freertos/portable/GCC/nrf52
    ${NRF_SDK_DIR}/external/freertos/source/include
    ${NRF_SDK_DIR}/external/segger_rtt
    ${NRF_SDK_DIR}/integration/nrfx
    ${NRF_SDK_DIR}/integration/nrfx/legacy
    ${NRF_SDK_DIR}/modules/nrfx
    ${NRF_SDK_DIR}/modules/nrfx/drivers/include
    ${NRF_SDK_DIR}/modules/nrfx/hal
    ${NRF_SDK_DIR}/modules/nrfx/mdk   
)

# ==========================
# Prj Configuration
# ==========================
add_library(prj_config INTERFACE)
target_include_directories(prj_config INTERFACE ${COMMON_COMPILE_INC})
target_compile_definitions(prj_config INTERFACE ${COMMON_COMPILE_DEF})
target_compile_options(prj_config INTERFACE ${COMMON_COMPILE_OPT})

# ====================================================
# Add FreeRTOS kernel and portable layer
# Add application source files as an OBJECT library
# Add board support package (BSP) source files as an OBJECT library
# ====================================================
add_subdirectory(app)
include(cmake/freertos.cmake)

# ==========================
# Executable Target
# ==========================
add_executable(${EXECUTABLE}
    $<TARGET_OBJECTS:app>
    ${NRF_SDK_DIR}/components/ble/ble_db_discovery/ble_db_discovery.c
    ${NRF_SDK_DIR}/components/ble/ble_services/ble_dis_c/ble_dis_c.c
    ${NRF_SDK_DIR}/components/ble/common/ble_advdata.c
    ${NRF_SDK_DIR}/components/ble/common/ble_conn_params.c
    ${NRF_SDK_DIR}/components/ble/common/ble_conn_state.c
    ${NRF_SDK_DIR}/components/ble/nrf_ble_gatt/nrf_ble_gatt.c
    ${NRF_SDK_DIR}/components/ble/nrf_ble_gq/nrf_ble_gq.c
    ${NRF_SDK_DIR}/components/ble/nrf_ble_scan/nrf_ble_scan.c
    ${NRF_SDK_DIR}/components/libraries/atomic/nrf_atomic.c
    ${NRF_SDK_DIR}/components/libraries/atomic_flags/nrf_atflags.c
    ${NRF_SDK_DIR}/components/libraries/balloc/nrf_balloc.c
    ${NRF_SDK_DIR}/components/libraries/experimental_section_vars/nrf_section_iter.c
    ${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_backend_rtt.c
    ${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_backend_serial.c
    ${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_default_backends.c
    ${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_frontend.c
    ${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_str_formatter.c
    ${NRF_SDK_DIR}/components/libraries/memobj/nrf_memobj.c
    ${NRF_SDK_DIR}/components/libraries/queue/nrf_queue.c
    ${NRF_SDK_DIR}/components/libraries/ringbuf/nrf_ringbuf.c
    ${NRF_SDK_DIR}/components/libraries/strerror/nrf_strerror.c
    ${NRF_SDK_DIR}/components/libraries/util/app_error.c
    ${NRF_SDK_DIR}/components/libraries/util/app_error_handler_gcc.c
    ${NRF_SDK_DIR}/components/libraries/util/app_error_weak.c
    ${NRF_SDK_DIR}/components/libraries/util/app_util_platform.c
    ${NRF_SDK_DIR}/components/softdevice/common/nrf_sdh.c
    ${NRF_SDK_DIR}/components/softdevice/common/nrf_sdh_ble.c
    ${NRF_SDK_DIR}/components/softdevice/common/nrf_sdh_freertos.c
    ${NRF_SDK_DIR}/external/fprintf/nrf_fprintf.c
    ${NRF_SDK_DIR}/external/fprintf/nrf_fprintf_format.c
    ${NRF_SDK_DIR}/external/segger_rtt/SEGGER_RTT.c
    ${NRF_SDK_DIR}/external/segger_rtt/SEGGER_RTT_printf.c
    ${NRF_SDK_DIR}/integration/nrfx/legacy/nrf_drv_clock.c
    ${NRF_SDK_DIR}/modules/nrfx/drivers/src/nrfx_clock.c
    ${NRF_SDK_DIR}/modules/nrfx/mdk/gcc_startup_nrf52840.S
    ${NRF_SDK_DIR}/modules/nrfx/mdk/system_nrf52.c
)

target_include_directories(${EXECUTABLE} PRIVATE ${COMMON_COMPILE_INC})
target_compile_definitions(${EXECUTABLE} PRIVATE ${COMMON_COMPILE_DEF})
target_compile_options(${EXECUTABLE} PRIVATE ${COMMON_COMPILE_OPT})

# ==========================
# Link configuration
# ==========================

# Linker options (linker script and flags)
target_link_options(${EXECUTABLE} PRIVATE
    -T${LINKER_FILE}                 # Linker script
    -L${SD_LINKER_DIR}               # Linker library directory (SoftDevice)
    -L${NRF_SDK_LINKER_DIR}          # Linker library directory (SDK) 
    -L${LINKER_DIR}                  # Linker library directory
    -mcpu=cortex-m4                  # CPU architecture
    -mfpu=fpv4-sp-d16                # Floating-point unit
    -mfloat-abi=hard
    -mthumb
    --specs=nano.specs               # Use nano C library
    --specs=nosys.specs              # Minimal syscall stubs
    -u _printf_float                 # Enable float support in printf
    -lc                              # Link C library
    -lm                              # Link math library
    -Wl,-Map=${PROJECT_NAME}.map,--cref     # Generate memory map file
    -Wl,--gc-sections                       # Remove unused sections
    -Xlinker -print-memory-usage -Xlinker   # Print memory usage after link
)

# Link with logical (target-based) libraries
target_link_libraries(${EXECUTABLE} PRIVATE
    prj_config
    app
    freertos
)

# ==========================
# Post-build Actions
# ==========================
add_custom_command(TARGET ${EXECUTABLE}
    POST_BUILD
    COMMAND ${CMAKE_SIZE} ${EXECUTABLE}
    COMMENT "Print memory usage"
)

add_custom_command(TARGET ${EXECUTABLE}
    POST_BUILD
    COMMAND ${CMAKE_OBJCOPY} -O srec --srec-len=64 ${EXECUTABLE} ${PROJECT_NAME}.s19
    COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE} ${PROJECT_NAME}.hex
    COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE} ${PROJECT_NAME}.bin
    COMMENT "Generate .s19, .hex, and .bin output files"
)
