#   Zerocat Chipflasher --- Flash free firmware, kick the Management Engine.
#
#   Copyright (C) 2020, 2021, 2022, 2023, 2024, 2025  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
#   =============
#
#
#   Brief
#   -----
#
#
#   Build the chipflasher’s new firmware: `kick2`


#   Workaround for GNU Make < 4.3
#   =============================
#
#   Finalize commands within a $(shell) function with semicolon, e.g.:
#
#           $(shell echo;)


# Shell
SHELL                         := /bin/sh


# White Space
EMPTY                         :=
SPACE                         := $(EMPTY) $(EMPTY)
COMMA                         := ,
M5                            := xxxxx
TAB1                          := $(SPACE)$(SPACE)$(SPACE)$(SPACE)
TOKEN_DISABLE                 := $(EMPTY)"'~ \# "$(EMPTY)
TOKEN_ENABLE                  := $(EMPTY)"\# \t "$(EMPTY)


# Root Paths
ROOT_DOC                      := ../../doc/
ROOT_FW2_DOC                  := ../../firmware2/doc/
ROOT_FW2_SRC                  := ../../firmware2/src/


# Utilities
CP                            := $(shell command -v cp;)
CP_FLAGS                      :=
$(if $(strip $(CP)),,         $(error Cannot find cp utility))

MV                            := $(shell command -v mv;)
MV_FLAGS                      :=
$(if $(strip $(MV)),,         $(error Cannot find mv utility))

RM                            := $(shell command -v rm;)
RM_FLAGS                      := -f
$(if $(strip $(RM)),,         $(error Cannot find rm utility))

CAT                           := $(shell command -v cat;)
CAT_FLAGS                     :=
$(if $(strip $(CAT)),,        $(error Cannot find cat utility))

CUT                           := $(shell command -v cut;)
CUT_FLAGS                     := -d' '
$(if $(strip $(CUT)),,        $(error Cannot find cut utility))

GIT                           := $(shell command -v git;)
GIT_FLAGS                     :=
$(if $(strip $(GIT)),,        $(error Cannot find git utility))

SED                           := $(shell command -v sed;)
SED_FLAGS                     := -E
$(if $(strip $(SED)),,        $(error Cannot find sed utility))

SET                           := $(shell command -v set;)
SET_FLAGS                     := -f
$(if $(strip $(SET)),,        $(error Cannot find set utility))

DATE                          := $(shell command -v date;)
DATE_FLAGS                    := -R
$(if $(strip $(DATE)),,       $(error Cannot find date utility))

ECHO                          := $(shell command -v echo;)
ECHO_FLAGS                    :=
$(if $(strip $(ECHO)),,       $(error Cannot find echo utility))

LESS                          := $(shell command -v less;)
LESS_FLAGS                    := -e -N
$(if $(strip $(LESS)),,       $(error Cannot find less utility))

MKTEMP                        := $(shell command -v mktemp;)
MKTEMP_FLAGS                  :=
$(if $(strip $(MKTEMP)),,     $(error Cannot find mktemp utility))

OPENSPIN                      := $(shell command -v openspin;)
OPENSPIN_FLAGS                :=
$(if $(strip $(OPENSPIN)),,   $(error Cannot find openspin utility))


# Files
PTR_FAVICON                   := $(ROOT_FW2_DOC)favicon
SPIN_KICK2                    := kick2.spin
SOURCES_SPIN                  := $(strip\
	$(addprefix $(ROOT_FW2_SRC),$(notdir $(shell\
		$(OPENSPIN) $(OPENSPIN_FLAGS)\
			-f\
				$(SPIN_KICK2)\
	;)))\
)
SPIN_PCB                      := PCB.spin
SPIN_MENU                     := menu.spin
SPIN_SERPROG                  := serprog.spin
KICK2                         := $(subst .spin,,$(SPIN_KICK2))
BOARD_CONFIG                  := $(ROOT_FW2_START)board.cfg


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


# Settings
MAKEFILE_TITLE                := Build ‘kick2’, the second firmware, and provide compiled documentation output.
PROJECT_TITLE                 := Zerocat Chipflasher
PROJECT_BRIEF                 := Flash free firmware to BIOS chips, kick the Management Engine.
PROJECT_REPO                  := git://zerocat.org/zerocat/projects/chipflasher.git
TTY_BAUDRATE                  = $(strip\
	$(shell\
		$(SED) $(SED_FLAGS)\
			-e '/^baudrate:/!d; s/^.*\: //;'\
				$(BOARD_CONFIG)\
	;)\
)
KICK2_INTERFACE               := $(strip\
	$(shell\
		ifc=$$(\
			$(SED) $(SED_FLAGS)\
				-e '/^\#[ \t]*define[ \t]*_CFG/!d; s/^.*_CFG_//;'\
					$(SPIN_KICK2)\
		)\
		&& if [ -z "$$ifc" ]\
			; then\
				$(ECHO) $(ECHO_FLAGS) nointerface\
			; else\
				$(ECHO) $(ECHO_FLAGS) $$ifc\
			; fi\
	;)\
)


# HTML: NAVBAR
define NAVBAR
$(strip\
	$(ECHO) $(ECHO_FLAGS)    "    <div class=\"navbar-container\">" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "      <a id=\"$${id}\"></a>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "      <div class=\"navbar\">" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "        <div>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "          <a href=\"$(ROOT_FW2_DOC)index.html\"><button type=\"button\">Back</button></a>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "          <div>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "          </div>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "        </div>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "      </div>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    </div>" >> $@\
)
endef


# Remove corrupted files
.DELETE_ON_ERROR :


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


# Intermediate Targets
#~ .INTERMEDIATE :


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


# Phony Targets
.PHONY :\
	all\
	\
	hello\
	help\
	symbols\
	review\
	files\
	tree\
	docs\
	show-config\
	\
	html\
	\
	config-connect\
	config-flashrom\
	config-terminal\
	config-nointerface\
	\
	config-RS232_230400\
	config-RS232_115200\
	config-RS232_57600\
	config-RS232_38400\
	\
	config-SPIPWRON_ONESHOT\
	config-SPIPWRON_PULSES\
	config-SPIPWRON_DIPSW\
	\
	config-SPIPWR_AUTO\
	config-SPIPWR_STATIC\
	config-SPIPWROFF_DIPSW\
	\
	config-SPIMODE_0\
	config-SPIMODE_3\
	config-SPIMODE_DIPSW\
	\
	config-SPICLK_100\
	config-SPICLK_75\
	config-SPICLK_50\
	config-SPICLK_25\
	config-SPICLK_DIPSW
	\
	clean-config
	clean-docs\
	clean


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


# Tinned Cans: ...
include $(ROOT_DOC)tinned-cans.mk


# Goals
#   all: greet and build the firmware
all : hello $(KICK2).eeprom $(KICK2)
	@$(HEADLINE)\
	&& $(DONE);

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

#   display help information
help : hello
	@$(HEADLINE)\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "List of Goals"\
	&& $(ECHO) $(ECHO_FLAGS) "============="\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Default Goal"\
	&& $(ECHO) $(ECHO_FLAGS) "------------"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "all"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)same as $(KICK2), with greeter"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Help Options"\
	&& $(ECHO) $(ECHO_FLAGS) "------------"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "hello"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)greeter, provided with all, clean and help"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "help"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)display this help information"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "doc"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)dump doc output mode"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "tree"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)list project’s object tree"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "files"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)list spin files in use"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "symbol"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)dump PUB & CON symbol information"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "review"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)review dumped doc output"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "show-config"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)display current configuration"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Configure"\
	&& $(ECHO) $(ECHO_FLAGS) "---------"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "### Main Interface Options"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-connect"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)enable interface to ‘connect’ utility (default)"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-flashrom"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)enable interface to ‘flashrom’"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-terminal"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)enable interface to ‘terminal’ (reduced set of menu keys)"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-nointerface"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)disable any interface"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "### Secondary Interface Options"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-RS232_230400"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use a fast baudrate"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-RS232_115200"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use a standard baudrate (default)"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-RS232_57600"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use a medium baudrate"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-RS232_38400"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use a slow baudrate"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPIMODE_3"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use SPI Mode 3"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPIMODE_0"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use SPI Mode 0"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPIMODE_DIPSW"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use SPI Mode according to DIP Switch (default)"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPIPWR_AUTO"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to remove Vcc_SPI as needed"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPIPWR_STATIC"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to remove Vcc_SPI at end of program"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPIPWROFF_DIPSW"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to remove Vcc_SPI according to DIP Switch (default)"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPIPWRON_ONESHOT"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use one SPI Power-up Pulse"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPIPWRON_PULSES"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to repeat a SPI Power-up Pulse"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPIPWRON_DIPSW"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use SPI Power-up Pulses according to DIP Switch (default)"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPICLK_100"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use 100% SPI clock driver strength"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPICLK_75"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use 75% SPI clock driver strength"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPICLK_50"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use 50% SPI clock driver strength"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPICLK_25"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use 25% SPI clock driver strength"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "config-SPICLK_DIPSW"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)configure interface to use SPI clock driver strength according to DIP Switch (default)"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Compile"\
	&& $(ECHO) $(ECHO_FLAGS) "-------"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "html"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)generate html documentation"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "$(KICK2)"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)build the firmware, provide ‘$(KICK2)’ and ‘$(KICK2).eeprom’"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "Clean Options"\
	&& $(ECHO) $(ECHO_FLAGS) "-------------"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "clean-config"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)reset configuration"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "clean-doc"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)remove generated documentation files"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(ECHO) $(ECHO_FLAGS) "clean"\
	&& $(ECHO) $(ECHO_FLAGS) "$(TAB1)make folders clean"\
	&& $(ECHO) $(ECHO_FLAGS) ""\
	&& $(DONE);

show-config : $(filter %$(SPIN_KICK2) %$(SPIN_PCB),$(SOURCES_SPIN))
	@$(HEADLINE)\
	&& for i in $^\
		; do\
			$(CAT) $(CAT_FLAGS) $${i}\
			| $(SED) $(SED_FLAGS)\
				-e'/^#.*define/!d;' -\
		; done\
	&& $(DONE);

config-RS232_230400 : $(filter %$(SPIN_PCB),$(SOURCES_SPIN))
	@$(HEADLINE)\
	&& for i in $^\
		; do\
			$(SED) $(SED_FLAGS)\
				--in-place\
				-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_RS232_.*)/"$(TOKEN_DISABLE)"\2/;"\
				-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_RS232_$(subst config-RS232_,,$@))/"$(TOKEN_ENABLE)"\2/;"\
					$$i\
		; done\
	&& $(DONE);

config-RS232_115200 : $(filter %$(SPIN_PCB),$(SOURCES_SPIN))
	@$(HEADLINE)\
	&& for i in $^\
		; do\
			$(SED) $(SED_FLAGS)\
				--in-place\
				-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_RS232_.*)/"$(TOKEN_DISABLE)"\2/;"\
				-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_RS232_$(subst config-RS232_,,$@))/"$(TOKEN_ENABLE)"\2/;"\
					$$i\
		; done\
	&& $(DONE);

config-RS232_57600 : $(filter %$(SPIN_PCB),$(SOURCES_SPIN))
	@$(HEADLINE)\
	&& for i in $^\
		; do\
			$(SED) $(SED_FLAGS)\
				--in-place\
				-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_RS232_.*)/"$(TOKEN_DISABLE)"\2/;"\
				-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_RS232_$(subst config-RS232_,,$@))/"$(TOKEN_ENABLE)"\2/;"\
					$$i\
		; done\
	&& $(DONE);

config-RS232_38400 : $(filter %$(SPIN_PCB),$(SOURCES_SPIN))
	@$(HEADLINE)\
	&& for i in $^\
		; do\
			$(SED) $(SED_FLAGS)\
				--in-place\
				-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_RS232_.*)/"$(TOKEN_DISABLE)"\2/;"\
				-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_RS232_$(subst config-RS232_,,$@))/"$(TOKEN_ENABLE)"\2/;"\
					$$i\
		; done\
	&& $(DONE);

config-SPICLK_100 : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_75)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_50)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_25)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_DIPSW)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPICLK_100)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

config-SPICLK_75 : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_100)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_50)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_25)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_DIPSW)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPICLK_75)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

config-SPICLK_50 : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_100)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_75)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_25)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_DIPSW)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPICLK_50)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

config-SPICLK_25 : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_100)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_75)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_50)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_DIPSW)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPICLK_25)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

config-SPICLK_DIPSW : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_100)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_75)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_50)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPICLK_25)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPICLK_DIPSW)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-SPIPWRON_ONESHOT
config-SPIPWRON_ONESHOT : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIPWRON_.*)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPIPWRON_ONESHOT)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-SPIPWRON_PULSES
config-SPIPWRON_PULSES : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIPWRON_.*)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPIPWRON_PULSES)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-SPIPWRON_DIPSW
config-SPIPWRON_DIPSW : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIPWRON_.*)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPIPWRON_DIPSW)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-SPIPWR_AUTO
config-SPIPWR_AUTO : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIPWROFF_.*)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPIPWROFF_AUTO)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-SPIPWR_STATIC
config-SPIPWR_STATIC : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIPWROFF_.*)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPIPWROFF_STATIC)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-SPIPWROFF_DIPSW
config-SPIPWROFF_DIPSW : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIPWROFF_.*)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPIPWROFF_DIPSW)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-SPIMODE_0 – Enable interface to `flashrom` to use SPI Mode 0
config-SPIMODE_0 : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIMODE_3)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIMODE_DIPSW)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPIMODE_0)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-SPIMODE_3 – Enable interface to `flashrom` to use SPI Mode 3
config-SPIMODE_3 : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIMODE_0)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIMODE_DIPSW)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPIMODE_3)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-SPIMODE_DIPSW – Enable interface to `flashrom` to use SPI Modes according to DIP Switch
config-SPIMODE_DIPSW : $(SPIN_PCB)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIMODE_0)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_ENABLE)")(.*define.*_CFG_SPIMODE_3)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_SPIMODE_DIPSW)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   clean configuration
clean-config :\
	config-RS232_115200\
		config-SPIPWRON_DIPSW\
			config-SPIPWROFF_DIPSW\
				config-SPIMODE_DIPSW\
					config-SPICLK_DIPSW\
						config-connect
	@$(HEADLINE)\
	&& $(DONE);

#   build ‘kick2’, the firmware, for RAM
$(KICK2) : $(SOURCES_SPIN)
	@$(HEADLINE)\
	&& tmpfile1=`$(MKTEMP) $(MKTEMP_FLAGS)`\
	&& tmpfile2=`$(MKTEMP) $(MKTEMP_FLAGS)`\
	&& $(CP) $(CP_FLAGS)\
		$(SPIN_MENU) $$tmpfile1\
	&& $(CP) $(CP_FLAGS)\
		$(SPIN_SERPROG) $$tmpfile2\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e 's/<VERSION2>/$(PROJECT_NUMBER)/g;'\
			$(SPIN_MENU)\
			$(SPIN_SERPROG)\
	&& $(OPENSPIN) $(OPENSPIN_FLAGS)\
		-u\
		-b $<\
		-o $@\
	&& $(MV) $(MV_FLAGS)\
		$$tmpfile1 $(SPIN_MENU)\
	&& $(MV) $(MV_FLAGS)\
		$$tmpfile2 $(SPIN_SERPROG)\
	&& $(DONE);

#   build ‘kick2.eeprom’, the firmware for EEPROM
$(KICK2).eeprom : $(SOURCES_SPIN)
	@$(HEADLINE)\
	&& tmpfile1=`$(MKTEMP) $(MKTEMP_FLAGS)`\
	&& tmpfile2=`$(MKTEMP) $(MKTEMP_FLAGS)`\
	&& $(CP) $(CP_FLAGS)\
		$(SPIN_MENU) $$tmpfile1\
	&& $(CP) $(CP_FLAGS)\
		$(SPIN_SERPROG) $$tmpfile2\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e 's/<VERSION2>/$(PROJECT_NUMBER)/g;'\
			$(SPIN_MENU)\
			$(SPIN_SERPROG)\
	&& $(OPENSPIN) $(OPENSPIN_FLAGS)\
		-u\
		-e $<\
		-o $@\
	&& $(MV) $(MV_FLAGS)\
		$$tmpfile1 $(SPIN_MENU)\
	&& $(MV) $(MV_FLAGS)\
		$$tmpfile2 $(SPIN_SERPROG)\
	&& $(DONE);

#   favicon for html output
$(PTR_FAVICON) : $(ROOT_FW2_DOC)Makefile
	@$(HEADLINE)\
	&& $(MAKE)\
		-C $(<D)\
			$(@)\
	&& $(DONE);

%.spin.$(KICK2_INTERFACE).txt : %.spin
	@$(HEADLINE)\
	&& $(OPENSPIN) $(OPENSPIN_FLAGS)\
		-d\
			$<\
				> $@\
	&& $(DONE);

#   *.spin.txt.html
#     * remove copyright footers
#     * remove email addresses
%.spin.$(KICK2_INTERFACE).html : %.spin.$(KICK2_INTERFACE).txt $(PTR_FAVICON)
	@$(ECHO) $(ECHO_FLAGS)   "<!DOCTYPE html>" > $@\
	&& $(ECHO) $(ECHO_FLAGS) "<html>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "  <head>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    <meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=3.0, user-scalable=1\">" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    <link rel=\"icon\" type=\"image/png\" href=\"$(PTR_FAVICON)\">" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    <title>$@</title>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    <style type=\"text/css\">" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "      @import url(../doc/stylesheet.css) all;" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    </style>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "  </head>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "  <body>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    <div><br></div>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    <p id=\"doc-reference\">" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "      Documentation for “$(PROJECT_TITLE)” as of $(shell $(DATE) $(DATE_FLAGS);)<br>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "      Repository: $(PROJECT_REPO)<br>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "      Version: $(PROJECT_NUMBER)<br>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "      Branch: $(PROJECT_BRANCH)<br>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    </p>" >> $@\
	&& $(NAVBAR)\
	&& $(ECHO) $(ECHO_FLAGS) "    <h1>$@</h1>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    <pre>" >> $@\
	&& $(CAT) $(CAT_FLAGS)\
		-v\
			$<\
	| $(SED) $(SED_FLAGS)\
		-e 's/<.*@.*\..*>//g; s/\&/\&amp;/g; s/\"/\&quot;/g; s/</\&lt;/g; s/>/\&gt;/g;'\
			-\
				>> $@\
	&& $(ECHO) $(ECHO_FLAGS) "    </pre>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "  </body>" >> $@\
	&& $(ECHO) $(ECHO_FLAGS) "</html>" >> $@\
	&& $(DONE);

#   config-connect – Enable interface to `connect`
config-connect : $(SPIN_KICK2)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_connect)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-flashrom – Enable interface to `flashrom`
config-flashrom : $(SPIN_KICK2)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_flashrom)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-terminal – Enable interface to `terminal`
config-terminal : $(SPIN_KICK2)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_terminal)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   config-nointerface – Disable interface configurations in top object
config-nointerface : $(SPIN_KICK2)
	@$(HEADLINE)\
	&& $(SED) $(SED_FLAGS)\
		--in-place\
		-e "s/^("$(TOKEN_ENABLE)")(.*define)/"$(TOKEN_DISABLE)"\2/;"\
		-e "s/^("$(TOKEN_DISABLE)")(.*define.*_CFG_nointerface)/"$(TOKEN_ENABLE)"\2/;"\
			$<\
	&& $(DONE);

#   docs – dump out doc mode
docs : $(patsubst %.spin,%.spin.$(KICK2_INTERFACE).txt,$(SOURCES_SPIN))

#   html – generate html documentation
html : $(patsubst %.spin,%.spin.$(KICK2_INTERFACE).html,$(SOURCES_SPIN))
	@$(HEADLINE)\
	&& $(DONE);

#   tree – list project’s object tree
tree : $(SPIN_KICK2)
	@$(HEADLINE)\
	&& @$(OPENSPIN) $(OPENSPIN_FLAGS)\
		-t\
			$<\
	&& $(DONE);

#   files – list spin files in use
files : $(SPIN_KICK2)
	@$(HEADLINE)\
	&& $(OPENSPIN) $(OPENSPIN_FLAGS)\
		-f\
			$<\
	&& $(DONE);

#   review – review dumped documentation
review : docs
	@$(HEADLINE)\
	&& for i in $(wildcard ./*.spin.txt)\
		; do\
			$(LESS) $(LESS_FLAGS)\
				$$i\
		; done\
	&& $(DONE);

#   symbols – Dump PUB & CON symbol information
symbols : $(SPIN_KICK2)
	@$(HEADLINE)\
	&& $(OPENSPIN) $(OPENSPIN_FLAGS)\
		-s\
			$<\
	&& $(DONE);

#   clean documentation
clean-docs :
	@$(HEADLINE)\
	&& $(RM) $(RM_FLAGS)\
		-f\
			$(wildcard ./*.binary)\
			$(wildcard ./*.spin.*.txt)\
			$(wildcard ./*.spin.*.html)\
			index.html\
	&& $(DONE);

#   clean
clean : hello clean-docs clean-config
	@$(HEADLINE)\
	&& $(RM) $(RM_FLAGS)\
		-f\
			$(KICK2)\
			$(KICK2).eeprom\
	&& $(DONE);
