cmake_minimum_required(VERSION 3.22)

set(SRC_ROOT ${CMAKE_SOURCE_DIR}/../../../../../src/)
set(COMMON ${SRC_ROOT}/common)
set(UPDATE ${SRC_ROOT}/cyclone_boot)
set(THIRD_PARTY ${CMAKE_SOURCE_DIR}/../../../../../third_party)
set(HAL_DRIVERS ${THIRD_PARTY}/st/drivers/stm32f4xx_hal_driver/src)
set(BSP ${THIRD_PARTY}/st/boards/stm32f4xx_nucleo_144)
set(TOOLS ${CMAKE_SOURCE_DIR}/../../../../../tools)

set(CMAKE_C_STANDARD 11)
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()

# Set the project name
set(CMAKE_PROJECT_NAME blinky)

# Enable compile command to ease indexing with e.g. clangd
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)

# Core project settings
project(${CMAKE_PROJECT_NAME})
message("Build type: " ${CMAKE_BUILD_TYPE})

# Enable CMake support for ASM and C languages
enable_language(C ASM)

# Create an executable object type
add_executable(${CMAKE_PROJECT_NAME})

message(STATUS "C flags DEBUG: ${CMAKE_C_FLAGS_DEBUG}")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

add_executable(app_blinky
        ${COMMON}/cpu_endian.c
        ${COMMON}/date_time.c
        ${COMMON}/path.c
        ${COMMON}/resource_manager.c
        ${COMMON}/str.c
        ${COMMON}/os_port_none.c

        ${BSP}/stm32f4xx_nucleo_144.c

        ${UPDATE}/core/mailbox.c

        ${HAL_DRIVERS}/stm32f4xx_hal.c
        ${HAL_DRIVERS}/stm32f4xx_hal_adc.c
        ${HAL_DRIVERS}/stm32f4xx_hal_adc_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_can.c
        ${HAL_DRIVERS}/stm32f4xx_hal_cec.c
        ${HAL_DRIVERS}/stm32f4xx_hal_cortex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_crc.c
        ${HAL_DRIVERS}/stm32f4xx_hal_cryp.c
        ${HAL_DRIVERS}/stm32f4xx_hal_cryp_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_dac.c
        ${HAL_DRIVERS}/stm32f4xx_hal_dac_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_dcmi.c
        ${HAL_DRIVERS}/stm32f4xx_hal_dcmi_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_dfsdm.c
        ${HAL_DRIVERS}/stm32f4xx_hal_dma.c
        ${HAL_DRIVERS}/stm32f4xx_hal_dma_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_dma2d.c
        ${HAL_DRIVERS}/stm32f4xx_hal_dsi.c
        ${HAL_DRIVERS}/stm32f4xx_hal_eth.c
        ${HAL_DRIVERS}/stm32f4xx_hal_flash.c
        ${HAL_DRIVERS}/stm32f4xx_hal_flash_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_flash_ramfunc.c
        ${HAL_DRIVERS}/stm32f4xx_hal_fmpi2c.c
        ${HAL_DRIVERS}/stm32f4xx_hal_fmpi2c_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_gpio.c
        ${HAL_DRIVERS}/stm32f4xx_hal_hash.c
        ${HAL_DRIVERS}/stm32f4xx_hal_hash_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_hcd.c
        ${HAL_DRIVERS}/stm32f4xx_hal_i2c.c
        ${HAL_DRIVERS}/stm32f4xx_hal_i2c_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_i2s.c
        ${HAL_DRIVERS}/stm32f4xx_hal_i2s_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_irda.c
        ${HAL_DRIVERS}/stm32f4xx_hal_iwdg.c
        ${HAL_DRIVERS}/stm32f4xx_hal_lptim.c
        ${HAL_DRIVERS}/stm32f4xx_hal_ltdc.c
        ${HAL_DRIVERS}/stm32f4xx_hal_ltdc_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_nand.c
        ${HAL_DRIVERS}/stm32f4xx_hal_nor.c
        ${HAL_DRIVERS}/stm32f4xx_hal_pccard.c
        ${HAL_DRIVERS}/stm32f4xx_hal_pcd.c
        ${HAL_DRIVERS}/stm32f4xx_hal_pcd_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_pwr.c
        ${HAL_DRIVERS}/stm32f4xx_hal_pwr_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_qspi.c
        ${HAL_DRIVERS}/stm32f4xx_hal_rcc.c
        ${HAL_DRIVERS}/stm32f4xx_hal_rcc_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_rng.c
        ${HAL_DRIVERS}/stm32f4xx_hal_rtc.c
        ${HAL_DRIVERS}/stm32f4xx_hal_rtc_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_sai.c
        ${HAL_DRIVERS}/stm32f4xx_hal_sai_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_sd.c
        ${HAL_DRIVERS}/stm32f4xx_hal_sdram.c
        ${HAL_DRIVERS}/stm32f4xx_hal_smartcard.c
        ${HAL_DRIVERS}/stm32f4xx_hal_spdifrx.c
        ${HAL_DRIVERS}/stm32f4xx_hal_spi.c
        ${HAL_DRIVERS}/stm32f4xx_hal_sram.c
        ${HAL_DRIVERS}/stm32f4xx_hal_tim.c
        ${HAL_DRIVERS}/stm32f4xx_hal_tim_ex.c
        ${HAL_DRIVERS}/stm32f4xx_hal_uart.c
        ${HAL_DRIVERS}/stm32f4xx_hal_usart.c
        ${HAL_DRIVERS}/stm32f4xx_hal_wwdg.c
        ${HAL_DRIVERS}/stm32f4xx_ll_fmc.c
        ${HAL_DRIVERS}/stm32f4xx_ll_fsmc.c
        ${HAL_DRIVERS}/stm32f4xx_ll_sdmmc.c
        ${HAL_DRIVERS}/stm32f4xx_ll_usb.c

        ${CMAKE_SOURCE_DIR}/src/debug.c
        ${CMAKE_SOURCE_DIR}/src/main.c
        ${CMAKE_SOURCE_DIR}/src/system_stm32f4xx.c
        ${CMAKE_SOURCE_DIR}/src/stm32f4xx_it.c
        ${CMAKE_SOURCE_DIR}/cmake/startup_stm32f439xx.s
        ${CMAKE_SOURCE_DIR}/cmake/syscalls.c
)

target_include_directories(app_blinky PUBLIC
        ${COMMON}
        ${UPDATE}
        ${CMAKE_SOURCE_DIR}/src
        ${THIRD_PARTY}/cmsis/include
        ${THIRD_PARTY}/st/devices/stm32f4xx
        ${THIRD_PARTY}/st/drivers/stm32f4xx_hal_driver/inc
        ${THIRD_PARTY}/st/drivers/stm32f4xx_hal_driver/
        ${BSP}
)

target_compile_definitions(app_blinky PUBLIC
        STM32F439xx
        USE_HAL_DRIVER
        USE_STM32F4XX_NUCLEO_144
        $<$<CONFIG:Debug>:DEBUG>
)

# Add the map file to the list of files to be removed with 'clean' target
set_target_properties(app_blinky PROPERTIES ADDITIONAL_CLEAN_FILES app_blinky.map)

# Convert .elf to .bin
add_custom_command(TARGET app_blinky POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -O binary
        ${CMAKE_CURRENT_BINARY_DIR}/app_blinky.elf
        ${CMAKE_CURRENT_BINARY_DIR}/app_blinky.bin
        COMMENT "Generating binary file from ELF"
)

# Copy the generated .bin file to ../
set(VERSION_HEADER "${CMAKE_SOURCE_DIR}/src/version.h")
# Read the contents of the header
file(READ "${VERSION_HEADER}" VERSION_HEADER_CONTENT)
# Extract the version string from e.g., #define APP_VERSION "1.0.0"
string(REGEX MATCH "#define APP_VERSION_STRING \"([0-9\\.]+)\"" _ UNUSED ${VERSION_HEADER_CONTENT})
set(APP_VERSION_RAW "${CMAKE_MATCH_1}")
string(REPLACE "." "_" APP_VERSION "${APP_VERSION_RAW}")

configure_file(${VERSION_HEADER} ${CMAKE_CURRENT_BINARY_DIR}/version.h COPYONLY)

message("Detected application version: ${APP_VERSION_RAW}")
add_custom_command(TARGET app_blinky POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy
        ${CMAKE_CURRENT_BINARY_DIR}/app_blinky.bin
        ${CMAKE_CURRENT_SOURCE_DIR}/../app_blinky_${APP_VERSION}.bin
        COMMENT "Copying iap_demo.bin to parent directory"
)

add_custom_command(TARGET app_blinky POST_BUILD
        COMMAND ${TOOLS}/ImageBuilder/bin/image_builder_linux
        --input ${CMAKE_CURRENT_SOURCE_DIR}/../app_blinky_${APP_VERSION}.bin
        --output ${CMAKE_CURRENT_SOURCE_DIR}/../app_blinky_${APP_VERSION}.img.bin
        --vtor-align

        COMMAND ${TOOLS}/ImageBuilder/bin/image_builder_linux
        --input ${CMAKE_CURRENT_SOURCE_DIR}/../app_blinky_${APP_VERSION}.bin
        --output ${CMAKE_CURRENT_SOURCE_DIR}/../app_blinky_${APP_VERSION}_update.img
        --integrity-algo sha256
        --vtor-align

        COMMENT "Generating app_blinky images using ImageBuilder"
)
