#   Zerocat Chipflasher --- Flash free firmware, kick the Management Engine.
#
#   Copyright (C) 2016  kai <kmx@posteo.net>
#   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
#   =============
#
#
#   FIXME: Those steps missing:
#
#   * propeller-load -s cmm/libfdserial.elf
#   * propeller-elf-objdump -h cmm/libfdserial.elf
#
#
#   Usage
#   -----
#
#
#       $ make help


# Shell
SHELL                         := /bin/sh


# White Space
EMPTY                         :=
SPACE                         := $(EMPTY) $(EMPTY)
COMMA                         := ,
M5                            := ccccc
TAB1                          := $(SPACE)$(SPACE)$(SPACE)$(SPACE)


# Titles
MAKEFILE_TITLE                := Upload ‘kick’ to chip flasher’s RAM or EEPROM
PROJECT_TITLE                 := Zerocat Chipflasher
PROJECT_BRIEF                 := Flash free firmware to BIOS chips, kick the Management Engine.


# Root Paths
ROOT_DOC                      := ../../doc/
ROOT_HOST_START               := ../../host/start/
ROOT_FW1_SRC                  := ../src/
ROOT_FW1_START                := $(EMPTY)


# Tools
CP                            := cp
TOOLS := $(CP)
RM                            := rm
TOOLS += $(RM)
CAT                           := cat
TOOLS += $(CAT)
GIT                           := git
TOOLS += $(GIT)
SED                           := sed
TOOLS += $(SED)
SET                           := set
TOOLS += $(SET)
ECHO                          := echo
TOOLS += $(ECHO)
SLEEP                         := sleep
TOOLS += $(SLEEP)
PROPLOAD                      := propeller-load
TOOLS += $(PROPLOAD)


# Tool Flags
CP_FLAGS                      :=
RM_FLAGS                      := -f
CAT_FLAGS                     :=
GIT_FLAGS                     :=
SED_FLAGS                     := -E
SET_FLAGS                     := -f
ECHO_FLAGS                    :=
SLEEP_FLAGS                   :=
PROPLOAD_FLAGS                := -i -v -v -v -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
KICK_LMM_ELF                  := $(ROOT_FW1_SRC)kick.lmm.elf
KICK_CMM_ELF                  := $(ROOT_FW1_SRC)kick.cmm.elf
BOARD_CFG_TMPL                := $(ROOT_FW1_START)board.cfg.tmpl
BOARD_CFG                     := $(subst .tmpl,,$(BOARD_CFG_TMPL))
PORT_CFG_TMPL                 := $(ROOT_FW1_START)port.cfg.tmpl
PORT_CFG                      := $(subst .tmpl,,$(PORT_CFG_TMPL))


# Settings
DELAY_KICK_RAM                := 3s


# Tinned Cans: GET_TTY_PORT
define GET_TTY_PORT
$(strip\
	$(shell\
		$(SED) $(SED_FLAGS)\
			-e '/^(tty_port|TTY_PORT)/!d; s/^.*=[\t ]*//g;'\
				$(PORT_CFG);\
	)\
)
endef
# Tinned Cans: SET_TTY_PORT ($@ points to port device name)
define SET_TTY_PORT
$(strip\
	$(SED) $(SED_FLAGS)\
		-i -e '/^(tty_port|TTY_PORT)/!d;' -e's,=.*,= /dev/$@,g;'\
			$(PORT_CFG);\
)
endef
# Tinned Cans: GET_TTY_BAUDRATE
define GET_TTY_BAUDRATE
$(strip\
	$(shell\
		$(SED) $(SED_FLAGS)\
			-e '/^baudrate:/!d; s/^.*\:[\t ]*//;'\
				$(BOARD_CFG);\
	)\
)
endef
# Tinned Cans: SET_TTY_BAUDRATE ($@ points to rate)
define SET_TTY_BAUDRATE
$(strip\
	$(SED) $(SED_FLAGS)\
		-i\
		-e 's/^baudrate/#baudrate/;'\
		-e's/^(\#)($(subst config-,baudrate: ,$(@)))$$/\2/;'\
			$(BOARD_CFG)\
)
endef
# Tinned Cans: SET_RESET_LINE ($@ points to signal)
define SET_RESET_LINE
$(strip\
	$(SED) $(SED_FLAGS)\
		-i\
		-e 's/^(reset|RESET)/#reset/;'\
		-e 's/(\#)($(subst use-,reset: ,$(@)))$$/\2/;'\
			$(BOARD_CFG)\
)
endef


# Suffixes, to be checked for old fashioned suffix rules
.SUFFIXES :


# Intermediate Targets
#~ .INTERMEDIATE :


# Secondary Targets, enable empty list for debugging
#~ .SECONDARY :


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


# Phony Targets
.PHONY:\
	default\
	\
	hello\
	help\
	\
	ttyS0\
	ttyS1\
	ttyS2\
	ttyS3\
	ttyUSB0\
	ttyUSB1\
	ttyUSB2\
	ttyUSB3\
	\
	use-DTR\
	use-RTS\
	\
	config-115200\
	config-57600\
	config-38400\
	\
	upload-RAM\
	upload-RAM-terminal\
	upload-EEPROM\
	\
	delay\
	reset\
	\
	show-config\
	\
	clean-config\
	clean


# Targets
#   default: same as kick-RAM-terminal, with greeter
default : hello upload-RAM-terminal
	@$(HEADLINE)\
	&& $(DONE);

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

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

ttyS0 ttyS1 ttyS2 ttyS3 ttyUSB0 ttyUSB1 ttyUSB2 ttyUSB3 : $(PORT_CFG)
	@$(HEADLINE)\
	&& if [ -e /dev/$(@) ]\
	; then\
		$$($(SET_TTY_PORT))\
	; else\
		$(ECHO) $(ECHO_FLAGS) "No such file: /dev/$(@)"\
	; fi\
	&& $(DONE);

use-DTR use-RTS : $(BOARD_CFG)
	@$(HEADLINE)\
	&& $$($(SET_RESET_LINE))\
	&& $(DONE);

config-115200 config-57600 config-38400 : $(BOARD_CFG)
	@$(HEADLINE)\
	&& $$($(SET_TTY_BAUDRATE))\
	&& $(DONE);

#   send kick to RAM and run
upload-RAM : $(KICK_LMM_ELF) $(BOARD_CFG) $(PORT_CFG)
	@$(HEADLINE)\
	&& $(PROPLOAD) $(PROPLOAD_FLAGS)\
		-p $(GET_TTY_PORT)\
		-b $(basename $(BOARD_CFG)):RAMstart\
		-r\
			$(<)\
	&& $(DONE);

#   send kick to RAM, run and start a propeller-terminal
upload-RAM-terminal : $(KICK_LMM_ELF) $(BOARD_CFG) $(PORT_CFG)
	@$(HEADLINE)\
	&& $(PROPLOAD) $(PROPLOAD_FLAGS)\
		-p $(GET_TTY_PORT)\
		-b $(basename $(BOARD_CFG)):terminal\
		-r -t -q\
			$(<)\
	&& $(DONE);

#   send kick to EEPROM, don't run
upload-EEPROM : $(KICK_LMM_ELF) $(BOARD_CFG) $(PORT_CFG)
	@$(HEADLINE)\
	&& $(PROPLOAD) $(PROPLOAD_FLAGS)\
		-p $(GET_TTY_PORT)\
		-b $(basename $(BOARD_CFG)):default\
		-e\
			$(<)\
	&& $(DONE);

#   delay utility invocation
delay :
	@$(HEADLINE)\
	&& $(ECHO) $(ECHO_FLAGS) "Granting ‘kick’ some seconds to get started ..."\
	&& $(SLEEP) $(SLEEP_FLAGS)\
		$(DELAY_KICK_RAM)\
	&& $(ECHO) $(ECHO_FLAGS) "... done."\
	&& $(DONE);

#   reset chipflasher device, trigger once
reset : $(BOARD_CFG) $(PORT_CFG)
	@$(HEADLINE)\
	&& $(PROPLOAD) $(PROPLOAD_FLAGS)\
		-p $(GET_TTY_PORT)\
		-b $(basename $(BOARD_CFG))\
		-o -r\
	&& $(DONE);

#   cp port.cfg.tml, device /dev/ttyS0 is added as dependency for it is the default value for tty_port
$(PORT_CFG) : $(PORT_CFG_TMPL) /dev/ttyS0
	@$(HEADLINE)\
	&& $(CP) $(CP_FLAGS) $< $@\
	&& $(DONE);

$(BOARD_CFG) : $(BOARD_CFG_TMPL)
	@$(HEADLINE)\
	&& $(CP) $(CP_FLAGS) $< $@\
	&& $(DONE);

show-config : $(BOARD_CFG) $(PORT_CFG)
	@$(HEADLINE)\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Process \`$(<)':"\
	&& $(SED) $(SED_FLAGS) -e '/^baudrate/!d;' -e's,^,* ,;' $(BOARD_CFG)\
	&& $(SED) $(SED_FLAGS) -e '/^reset/!d;' -e's,^,* ,;' $(BOARD_CFG)\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Process \`$(word 2, $^)':"\
	&& $(SED) $(SED_FLAGS) -e '/^tty_port/!d;' -e's,^,* ,;' $(PORT_CFG)\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(DONE);

clean-config : config-115200
	@$(HEADLINE)\
	&& $(DONE);

clean :
	@$(HEADLINE)\
	&& $(RM) $(RM_FLAGS)\
		$(BOARD_CFG)\
		$(PORT_CFG)\
	&& $(DONE);
