PROJECT_DIR ?= .
MLEK_EXAMPLES_ROOT ?= /opt/cmsis-mlek-examples
MLEK_PROJECT_SRC ?= $(MLEK_EXAMPLES_ROOT)/Alif/AppKit_D3/MLEK_Video
SOLUTION ?= mlek_video.csolution.yml
CONTEXT ?= app.Release-Live_Stream+AE722F80F55D5LS-U55-256
DOCKER_IMAGE ?= alif:appkit-e7-build
DOCKERFILE ?= tools/alif_appkit_e7_build.Dockerfile
JOBS ?= 4
CMSIS_PACK_ROOT ?= /opt/cmsis-packs
GCC_TOOLCHAIN_14_3_1 ?= /opt/arm_compiler/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi/bin
SETOOLS_ROOT ?= /opt/alif-setools/app-release-exec-linux
ALIF_SETOOLS_URL ?= https://alifsemi.com/download/APFW0002
ALIF_PART ?= E7 (AE722F80F55D5LS) - 5.5 MRAM / 13.5 SRAM
ALIF_REVISION ?= B4
ALIF_IMAGE_NAME ?= aidge_m55_hp_app.bin
ALIF_TOC_CONFIG ?= aidge_m55_hp_app.json
ALIF_COMPORT ?= /dev/ttyACM0
ALIF_TARGET ?= ae722f80f55d5ls
ALIF_MRAM_ADDRESS ?= 0x80200000
ALIF_PACK ?= AlifSemiconductor.Ensemble.2.0.0.pack

.PHONY: build build_image_docker build_export_docker flash_setools flash_setools_docker flash_pyocd flash_jlink get_pack clean_alif

build:

ifdef USE_DOCKER
	@docker image inspect $(DOCKER_IMAGE) >/dev/null 2>&1 || $(MAKE) build_image_docker
	@$(MAKE) build_export_docker JOBS=$(JOBS)
else
	@echo "Building Alif AppKit E7 template project"
	chmod -R u+rwX board app mlek_video.csolution.yml
	python3 -c "from pathlib import Path; files=[Path('$(SOLUTION)'), Path('app/app.cproject.yml'), Path('board/AppKit-E7_M55_HP/Board_HP.clayer.yml')]; repl={'  compiler: AC6':'  compiler: GCC','      board: AppKit-E7-AIML:Gen 2\n':'','ARM::CMSIS@^6.2.0-0':'ARM::CMSIS@6.2.0','ARM::CMSIS-DSP@^1.16.0':'ARM::CMSIS-DSP@1.16.2','ARM::CMSIS-NN@^7.0.0':'ARM::CMSIS-NN@7.0.0','ARM::CMSIS-RTX@^5.9.0':'ARM::CMSIS-RTX@5.9.0','ARM::CMSIS-Compiler@^2.1.0':'ARM::CMSIS-Compiler@2.1.0','ARM::CMSIS-Driver@^2.8.0':'ARM::CMSIS-Driver@2.8.0','ARM::ethos-u-core-driver@^1.24.8':'ARM::ethos-u-core-driver@1.26.2','ARM::ethos-u-core-driver@^1.25.2':'ARM::ethos-u-core-driver@1.26.2','ARM::ethos-u-core-driver@1.25.2':'ARM::ethos-u-core-driver@1.26.2','ARM::ml-embedded-eval-kit-uc-api@^24.8.0':'ARM::ml-embedded-eval-kit-uc-api@24.8.0','tensorflow::flatbuffers@^1.25.2':'tensorflow::flatbuffers@1.25.2','tensorflow::gemmlowp@^1.25.2':'tensorflow::gemmlowp@1.25.2','tensorflow::kissfft@^1.25.2':'tensorflow::kissfft@1.25.2','tensorflow::ruy@^1.25.2':'tensorflow::ruy@1.25.2','tensorflow::tensorflow-lite-micro@^1.25.2':'tensorflow::tensorflow-lite-micro@1.25.2'}; [p.write_text(__import__('functools').reduce(lambda s, kv: s.replace(*kv), repl.items(), p.read_text())) for p in files]"
	python3 tools/patch_cproject.py
	CMSIS_PACK_ROOT="$(CMSIS_PACK_ROOT)" GCC_TOOLCHAIN_14_3_1="$(GCC_TOOLCHAIN_14_3_1)" csolution convert -s $(SOLUTION) -c $(CONTEXT)
	CMSIS_PACK_ROOT="$(CMSIS_PACK_ROOT)" GCC_TOOLCHAIN_14_3_1="$(GCC_TOOLCHAIN_14_3_1)" cbuild $(SOLUTION) -c $(CONTEXT) --rebuild --generator "Unix Makefiles" -j $(JOBS)
	find out -name "*.elf" | while read -r elf; do \
		$(GCC_TOOLCHAIN_14_3_1)/arm-none-eabi-objcopy -O binary "$$elf" "$$(dirname "$$elf")/mram.bin"; \
	done
endif

build_image_docker:
	docker build \
		--build-arg ALIF_SETOOLS_URL="$(ALIF_SETOOLS_URL)" \
		-t $(DOCKER_IMAGE) \
		-f $(DOCKERFILE) tools

build_export_docker:
	docker run --rm \
		--user "$$(id -u):$$(id -g)" \
		-v "$$(pwd)":/workspace \
		-w /workspace \
		$(DOCKER_IMAGE) \
		make build JOBS=$(JOBS)

flash_setools:
	test -x "$(SETOOLS_ROOT)/app-gen-toc"
	test -x "$(SETOOLS_ROOT)/app-write-mram"
	mkdir -p "$(SETOOLS_ROOT)/build/images" "$(SETOOLS_ROOT)/build/config" "$(SETOOLS_ROOT)/build/logs"
	cp "$$(find . -name 'mram.bin' -print -quit)" "$(SETOOLS_ROOT)/build/images/$(ALIF_IMAGE_NAME)"
	python3 -c "import json; from pathlib import Path; p=Path('$(SETOOLS_ROOT)/build/config/$(ALIF_TOC_CONFIG)'); p.write_text(json.dumps({'HP_Image': {'binary': '$(ALIF_IMAGE_NAME)', 'version': '1.0.0', 'mramAddress': '0x80200000', 'cpu_id': 'M55_HP', 'flags': ['boot'], 'signed': False}, 'DEVICE': {'disabled': False, 'binary': 'app-device-config.json', 'version': '0.5.00', 'signed': True}}, indent=2) + '\n')"
	if [ -f "$(SETOOLS_ROOT)/utils/global-cfg.db" ]; then \
		sed -i 's|"Revision": "[^"]*"|"Revision": "$(ALIF_REVISION)"|g' "$(SETOOLS_ROOT)/utils/global-cfg.db"; \
		sed -i 's|"Part#": "[^"]*"|"Part#": "$(ALIF_PART)"|g' "$(SETOOLS_ROOT)/utils/global-cfg.db"; \
	fi
	-cd "$(SETOOLS_ROOT)" && ./tools-config -p "$(ALIF_PART)"
	-cd "$(SETOOLS_ROOT)" && ./tools-config -r "$(ALIF_REVISION)"
	cd "$(SETOOLS_ROOT)" && ./app-gen-toc -f "build/config/$(ALIF_TOC_CONFIG)"
	for i in 1 2 3; do \
		echo "Flashing attempt $$i/3..."; \
		if cd "$(SETOOLS_ROOT)" && ./app-write-mram -p -c "$(ALIF_COMPORT)"; then \
			echo "Flashing succeeded!"; \
			exit 0; \
		fi; \
		echo "Flashing failed, retrying in 2 seconds..."; \
		sleep 2; \
	done; \
	echo "Flashing failed after 3 attempts!"; \
	exit 1

flash_setools_docker:
	docker run --rm \
		--privileged \
		-v /dev:/dev \
		-v "$$(pwd)":/workspace \
		-w /workspace \
		$(DOCKER_IMAGE) \
		make flash_setools ALIF_COMPORT=$(ALIF_COMPORT)

get_pack:
	@if [ ! -f "$(ALIF_PACK)" ]; then \
		echo "Copying Alif CMSIS pack from Docker image..."; \
		docker run --rm -v "$$(pwd)":/workspace $(DOCKER_IMAGE) cp /opt/cmsis-packs/.Download/AlifSemiconductor.Ensemble.2.0.0.pack /workspace/$(ALIF_PACK); \
	fi

flash_pyocd: get_pack
	@mram_bin=$$(find . -name "mram.bin" -print -quit); \
	if [ -z "$$mram_bin" ]; then \
		echo "Error: mram.bin not found! Please build the project first."; \
		exit 1; \
	fi; \
	echo "Flashing $$mram_bin to $(ALIF_TARGET) at $(ALIF_MRAM_ADDRESS) using pyocd..."; \
	pyocd load -t $(ALIF_TARGET) -a $(ALIF_MRAM_ADDRESS) --pack $(ALIF_PACK) "$$mram_bin"

flash_jlink:
	@mram_bin=$$(find . -name "mram.bin" -print -quit); \
	if [ -z "$$mram_bin" ]; then \
		echo "Error: mram.bin not found! Please build the project first."; \
		exit 1; \
	fi; \
	echo "Generating J-Link flash script..."; \
	echo "r" > flash.jlink; \
	echo "h" >> flash.jlink; \
	echo "loadbin $$mram_bin, $(ALIF_MRAM_ADDRESS)" >> flash.jlink; \
	echo "r" >> flash.jlink; \
	echo "g" >> flash.jlink; \
	echo "q" >> flash.jlink; \
	echo "Flashing $$mram_bin to $(ALIF_TARGET) at $(ALIF_MRAM_ADDRESS) using JLinkExe..."; \
	JLinkExe -device $(ALIF_TARGET) -if SWD -speed 4000 -autoconnect 1 -CommandFile flash.jlink; \
	rm -f flash.jlink

clean_alif:
	rm -rf out tmp *.cbuild*.yml app/*.cprj app/RTE $(ALIF_PACK)
