#   Zerocat Chipflasher --- Flash free firmware, kick the Management Engine.
#
#   Copyright (C) 2015, 2016  kai <kmx@posteo.net>
#   Copyright (C) 2015, 2016  tomás zerolo <tomás@tuxteam.de>
#   Copyright (C) 2016, 2017, 2018, 2020, 2021, 2022, 2023, 2024, 2026  Kai Mertens <kmx@posteo.net>
#
#   This file is part of Zerocat Chipflasher.
#
#   Zerocat Chipflasher is free software: you can redistribute it and/or
#   modify it under the terms of the GNU General Public License as
#   published by the Free Software Foundation, either version 3 of the
#   License, or (at your option) any later version.
#
#   Zerocat Chipflasher is distributed in the hope that it will be
#   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
#   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#   General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with Zerocat Chipflasher.
#   If not, see <http://www.gnu.org/licenses/>.


#   Documentation
#   =============
#
#
#   Diagnostic Pragmas
#   ------------------
#
#
#   NOTE Propeller code allows some non ANSI standard format specifiers,
#   i.e. "%b" for binary representation of an integer.
#   That will produce warnings according to -Wformat and -Wformat-extra-args.
#
#   You can temporarily disable these warnings in your source code:
#
#       [...]
#       #pragma GCC diagnostic push
#       #pragma GCC diagnostic ignored "-Wall"
#       #pragma GCC diagnostic ignored "-Wformat-extra-args"
#       //your code goes here, i.e.:
#       //printi("binary number: %08b", x);
#       #pragma GCC diagnostic pop
#       [...]
#
#   Please compare to:
#   https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas)
#
#
#   Usage
#   -----
#
#
#       $ make help
#
#
#   FIXME
#   -----
#
#
#   A patern rule would be nice. But where to stick the -lm -lfdserial and so on?
#   NOTE lib order matters (-lfoo -lbar). And $^ must go before libs.


# Shell
SHELL                         := /bin/sh


# White Space
EMPTY                         :=
SPACE                         := $(EMPTY) $(EMPTY)
COMMA                         := ,
M5                            := uuuuu
TAB1                          := $(SPACE)$(SPACE)$(SPACE)$(SPACE)
TOKEN_DISABLE                 := $(EMPTY)"\/\/\# \t "$(EMPTY)
TOKEN_ENABLE                  := $(EMPTY)"\# \t "$(EMPTY)


# Titles
MAKEFILE_TITLE                := Build ‘kick’, the first firmware
PROJECT_TITLE                 := Zerocat Chipflasher
PROJECT_BRIEF                 := Flash free firmware, kick the Management Engine.


# Root Paths
ROOT                          := ../../
ROOT_DOC                      := ../../doc/
ROOT_FW1_SRC                  := ../../firmware1/src/
PARALLAX_REMOTE               := https://github.com/
PARALLAX_REPO                 := parallaxinc/Simple-Libraries
PARALLAX_REPO_VERSION         := c4f9a3e273002ec5e6f8b1d1ab95c14cb1823e82


# Tools
CD                            := cd
TOOLS := $(CD)
CP                            := cp
TOOLS += $(CP)
RM                            := rm
TOOLS += $(RM)
MV                            := mv
TOOLS += $(MV)
CAT                           := cat
TOOLS += $(CAT)
GIT                           := git
TOOLS += $(GIT)
SED                           := sed
TOOLS += $(SED)
SET                           := set
TOOLS += $(SET)
ECHO                          := echo
TOOLS += $(ECHO)
READ                          := read
TOOLS += $(READ)
MKDIR                         := mkdir
TOOLS += $(MKDIR)
MKTEMP                        := mktemp
TOOLS += $(MKTEMP)
PROPELFGCC                    := propeller-elf-gcc
TOOLS += $(PROPELFGCC)


# Tool Flags
CD_FLAGS                      :=
CP_FLAGS                      :=
RM_FLAGS                      := -f
MV_FLAGS                      :=
CAT_FLAGS                     :=
GIT_FLAGS                     :=
SED_FLAGS                     := -E
SET_FLAGS                     := -f
ECHO_FLAGS                    :=
READ_FLAGS                    :=
MKDIR_FLAGS                   :=
MKTEMP_FLAGS                  :=
PROPELFGCC_SYSROOT            := $(strip\
	--sysroot=$(PARALLAX_REPO)/\
)
PROPELFGCC_INCLUDES           := $(strip\
	-I .\
	-I =Learn/Simple\ Libraries/TextDevices/libsimpletext\
	-I =Learn/Simple\ Libraries/Utility/libsimpletools\
	-I =Learn/Simple\ Libraries/Protocol/libsimplei2c\
)
PROPELFGCC_LIBDIRS_lmm        := $(strip\
	-L .\
	-L =Learn/Simple\ Libraries/TextDevices/libsimpletext/lmm\
	-L =Learn/Simple\ Libraries/Utility/libsimpletools/lmm\
	-L =Learn/Simple\ Libraries/Protocol/libsimplei2c/lmm\
)
PROPELFGCC_LIBDIRS_cmm        := $(strip\
	-L .\
	-L =Learn/Simple\ Libraries/TextDevices/libsimpletext/cmm\
	-L =Learn/Simple\ Libraries/Utility/libsimpletools/cmm\
	-L =Learn/Simple\ Libraries/Protocol/libsimplei2c/cmm\
)
PROPELFGCC_LIBS               := $(strip\
	-lsimpletext\
	-lsimpletools\
	-lsimplei2c\
)
PROPELFGCC_FLAGS              = $(strip\
	$(PROPELFGCC_SYSROOT)\
	$(PROPELFGCC_INCLUDES)\
	$(PROPELFGCC_LIBDIRS_$*)\
	-Os -Wall -Wmissing-prototypes -m32bit-doubles -fno-exceptions -std=c99 -m$*\
)


# Tool Check
CHECK=$(if $(strip $(shell command -v $(TOOL))),,$(error $(TOOL) -- No such tool))
$(foreach TOOL,$(TOOLS),$(CHECK))


# Project Numbers
include $(ROOT_DOC)project-numbers.mk


# Files
H_IDENTIFIER_TMPL             := $(ROOT_FW1_SRC)identifier.h.tmpl
H_IDENTIFIER                  := $(ROOT_FW1_SRC)identifier.h
H_PROPPINS_CFG_TMPL           := $(ROOT_FW1_SRC)libkick/proppins.h.cfg.tmpl
H_PROPPINS_CFG                := $(ROOT_FW1_SRC)libkick/proppins.h.cfg
LIBCOMMON                     := $(wildcard libcommon/*)
LIBKICK                       := $(wildcard libkick/*)
LIBPROP                       := $(wildcard libprop/*)
LIBSPI                        := $(wildcard libSPI/*)


# Tinned Cans: HEADER, HEADLINE, DONE
include $(ROOT_DOC)tinned-headers.mk


# Phony Targets
.PHONY :\
	all\
	\
	hello\
	help\
	print-search-dirs\
	\
	setup-lib-parallaxinc\
	\
	config-BOARD_V2_2\
	config-BOARD_V2_0\
	config-BOARD_V1\
	\
	kick\
	\
	show-config\
	\
	remove-lib-parallaxinc\
	clean-config\
	clean-kick\
	clean


# Targets
#   all: same as kick
all : hello kick
	@$(HEADLINE)\
	&& $(DONE);

#   Say hello.
#     provided with all, clean and help
hello :
	@$(HEADER)\
	&& $(DONE);

#   display help information
help : $(ROOT_FW1_SRC)help.txt hello
	@$(HEADLINE)\
	&& $(CAT) $(CAT_FLAGS)\
		$<\
	&& $(DONE);

#   print search directories
print-search-dirs :
	@$(HEADLINE)\
	&& $(PROPELFGCC)\
		-print-search-dirs\
	&& $(DONE);

#   set up parallaxinc repo clone
setup-lib-parallaxinc : $(PARALLAX_REPO)
	@$(HEADLINE)\
	&& $(DONE);

#   clean (remove) parallaxinc folder
remove-lib-parallaxinc :
	@$(HEADLINE)\
	&& $(RM) $(RM_FLAGS) -r\
		$(dir $(PARALLAX_REPO))\
	&& $(DONE);

#   apply configuration to match PCB
config-BOARD_V2_2 config-BOARD_V2_0 config-BOARD_V1 : $(H_PROPPINS_CFG)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_BOARD_V.*)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")($(subst config-,.*define.*_CFG_,$(@)))/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   retrieve Parallax library from GitHub
$(PARALLAX_REPO) :
	@$(HEADLINE)\
	&& $(READ) $(READ_FLAGS)\
		-p 'Ready to start download from ‘$(PARALLAX_REMOTE)’? [yes|no]: '\
			reply\
	&& if [ "$$reply" = 'yes' ]\
		; then\
			$(MKDIR) $(MKDIR_FLAGS)\
				$(dir $@)\
			&& $(CD) $(CD_FLAGS)\
				$(dir $@)\
			&& $(GIT) $(GIT_FLAGS)\
				clone $(PARALLAX_REMOTE)$@.git\
			&& if [ $$? -eq 0 ]\
				; then\
					$(CD) $(CD_FLAGS)\
						$(@F)/\
					&& $(GIT) $(GIT_FLAGS)\
						checkout $(PARALLAX_REPO_VERSION)\
					&& $(CD) $(CD_FLAGS)\
						-\
				; else\
					exit 1\
				; fi\
		; else\
			$(ECHO) $(ECHO_FLAGS) "Download cancelled by user."\
			&& exit 1\
		; fi\
	&& $(DONE);

#   target ‘kick’
kick : kick.lmm.elf
	@$(HEADLINE)\
	&& $(DONE);

#   build kick.lmm.elf and kick.cmm.elf file
#
#     Memory model
#
#     * lmm: stores the program image and variable data in main RAM, fastest execution
#     * cmm: the program image is compiled into a size-optimized form
#     * xmmc: stores program images in external flash memory, an SD card, or EEPROM
#
kick.%.elf : kick.c $(H_IDENTIFIER) $(LIBPROP) $(LIBCOMMON) $(LIBSPI) $(LIBKICK) setup-lib-parallaxinc
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e 's/<VERSION>/$(PROJECT_NUMBER)/;' $(H_IDENTIFIER)\
	&& $(PROPELFGCC) $(PROPELFGCC_FLAGS)\
		$< $(PROPELFGCC_LIBS)\
			-o $@\
	&& $(DONE);

#   header includes config file, which must exist
libkick/proppins.h : $(H_PROPPINS_CFG)
	@$(HEADLINE)\
	&& $(DONE);

#   create config file, if not present
$(H_PROPPINS_CFG) : $(H_PROPPINS_CFG_TMPL)
	@$(HEADLINE)\
	&& $(CP) $(CP_FLAGS) $< $@\
	&& $(DONE);

$(H_IDENTIFIER) : $(H_IDENTIFIER_TMPL)
	@$(HEADLINE)\
	&& $(CP) $(CP_FLAGS) $(<) $(@)\
	&& $(DONE);

#   display kick configuration
show-config : $(H_PROPPINS_CFG)
	@$(HEADLINE)\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Process \`$(word 1, $^)':"\
	&& $(SED) $(SED_FLAGS) -e '/^#[\t ]*define/!d;' $<\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(DONE);

#   clean kick configuration
clean-config : config-BOARD_V2_2
	@$(HEADLINE)\
	&& $(DONE);

#   remove build
clean-kick :
	@$(HEADLINE)\
	&& $(RM) $(RM_FLAGS)\
		kick.lmm.elf\
		kick.cmm.elf\
		$(H_IDENTIFIER)\
	&& $(DONE);

#   clean kick and configuration
clean : hello
	@$(HEADLINE)\
	&& $(RM) $(RM_FLAGS)\
		kick.lmm.elf\
		kick.cmm.elf\
		$(H_PROPPINS_CFG)\
		$(H_IDENTIFIER)\
	&& $(DONE);
