cmake_minimum_required(VERSION 3.16)

# Cross-compilation settings
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

project(LSPi_Project C CXX ASM)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)

set(MCU_TYPE GD32F470ZGT6)

# Define MCU for GD32 library
add_definitions(-DGD32F470)

set(CPU_FLAGS "-mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard")
set(COMMON_FLAGS "${CPU_FLAGS} -Wall -Wextra -Wno-unused-parameter -ffunction-sections -fdata-sections -fno-common")
set(CMAKE_C_FLAGS "${COMMON_FLAGS} -std=gnu11")
set(CMAKE_CXX_FLAGS "${COMMON_FLAGS} -std=gnu++14")
set(CMAKE_ASM_FLAGS "${CPU_FLAGS} -x assembler-with-cpp")
set(CMAKE_EXE_LINKER_FLAGS "${CPU_FLAGS} -Wl,--gc-sections -specs=nano.specs -specs=nosys.specs -T${CMAKE_SOURCE_DIR}/libs/thirdparty/GD32F4xx/Ld/Link.ld")

set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)

# Library check macro (from download-lib skill template)
macro(check_required_library lib_name lib_path)
  if(NOT EXISTS ${lib_path})
    message(WARNING "Missing library: ${lib_name}")
    message(STATUS "Please run: download-lib --chip-type gd32 --chip-series GD32F470")
    set(${lib_name}_FOUND FALSE)
  else()
    set(${lib_name}_FOUND TRUE)
    message(STATUS "Found library: ${lib_name}")
  endif()
endmacro()

# Check GD32 library
check_required_library(GD32F4XX_LIB "${CMAKE_SOURCE_DIR}/libs/thirdparty/GD32F4xx")

include_directories(
    app
    app/tasks
    bsp
    config
    drv/adc
    drv/i2c
    drv/spi
    drv/uart
    drv/timer
    drv/exmc
    drv/bus
    drv/gpio
    drv/system
    bsp/device/sdcard
    bsp/device/led
    bsp/device/lcd
    bsp/device/touch
    bsp/device/sdram
    bsp/device/flash
    libs/common
    libs/CMSIS
    libs/thirdparty
)

if(GD32F4XX_LIB_FOUND)
  # Add GD32 library include paths
  include_directories(
    ${CMAKE_SOURCE_DIR}/libs/thirdparty/GD32F4xx/Include
    ${CMAKE_SOURCE_DIR}/libs/thirdparty/GD32F4xx/CMSIS
  )
  message(STATUS "GD32 library include path added")
else()
  message(FATAL_ERROR "GD32F4xx library not found. Cannot continue.")
endif()

# Application sources (both .c and .cpp)
file(GLOB_RECURSE APP_SOURCES
    app/*.cpp
    bsp/*.cpp
    drv/adc/*.cpp
    drv/i2c/*.cpp
    drv/spi/*.cpp
    drv/uart/*.cpp
    drv/timer/*.cpp
    drv/exmc/*.cpp
    drv/bus/*.cpp
    drv/gpio/*.cpp
    drv/system/*.cpp
    bsp/device/sdcard/*.cpp
    bsp/device/led/*.cpp
    bsp/device/lcd/*.cpp
    bsp/device/touch/*.cpp
    bsp/device/sdram/*.cpp
    bsp/device/flash/*.cpp
)



# GD32 standard peripheral library sources
file(GLOB GD32_SOURCES
    ${CMAKE_SOURCE_DIR}/libs/thirdparty/GD32F4xx/Source/*.c
)

# Assembly startup file
set(ASSEMBLY_SOURCES
    ${CMAKE_SOURCE_DIR}/libs/thirdparty/GD32F4xx/Startup/startup_gd32f450_470.S
)

# Combine all sources
set(ALL_SOURCES ${APP_SOURCES} ${GD32_SOURCES} ${ASSEMBLY_SOURCES})

add_executable(${PROJECT_NAME} ${ALL_SOURCES})

target_compile_options(${PROJECT_NAME} PRIVATE -Os)

set_target_properties(${PROJECT_NAME} PROPERTIES
    SUFFIX ".elf"
    OUTPUT_NAME "${PROJECT_NAME}"
)

# Generate .hex and .bin files after linking
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND arm-none-eabi-objcopy -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
    COMMAND arm-none-eabi-objcopy -O binary -S ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
    COMMAND ${CMAKE_COMMAND} -E echo "Generated: ${PROJECT_NAME}.hex ${PROJECT_NAME}.bin"
    COMMENT "Generating .hex and .bin files"
)

# Flash programming option
set(FLASH_TOOL "auto" CACHE STRING "Programming tool to use (openocd, jlink, pyocd, auto)")
set_property(CACHE FLASH_TOOL PROPERTY STRINGS "openocd" "jlink" "pyocd" "auto")

# Custom target for flashing
add_custom_target(flash
    DEPENDS ${PROJECT_NAME}
    COMMAND ${CMAKE_COMMAND} -E echo "Flashing ${PROJECT_NAME}.elf using ${FLASH_TOOL}..."
    COMMAND python ${CMAKE_SOURCE_DIR}/tools/flash.py --tool ${FLASH_TOOL} --elf ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.elf --hex ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.hex --bin ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.bin
    COMMENT "Programming ${PROJECT_NAME} to GD32F470ZGT6"
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)

# Custom target for flashing with OpenOCD directly
add_custom_target(flash-openocd
    DEPENDS ${PROJECT_NAME}
    COMMAND ${CMAKE_COMMAND} -E echo "Flashing ${PROJECT_NAME}.elf with OpenOCD..."
    COMMAND openocd -f ${CMAKE_SOURCE_DIR}/tools/openocd_gd32f470.cfg -c "program_elf ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.elf" -c "shutdown"
    COMMENT "Programming ${PROJECT_NAME} via OpenOCD"
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)