# Copyright 2021 John-Mark Gurney.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#

.if $(.OBJDIR) == $(.CURDIR)
.error Need to set MAKEOBJDIR.
.endif

PLATFORM != uname -s

.if $(PLATFORM) == "Darwin"
SOEXT=dylib
.else
.error Unsupported platform: $(PLATFORM)
.endif

PROGS = lora.gw lora.irr

SRCS.lora.gw = main.c
SRCS.lora.gw+= $(SRCS.NODE151)

SRCS.lora.irr = irr_main.c
SRCS.lora.irr+= comms.c
SRCS.lora.irr+= strobe_rng_init.c
SRCS.lora.irr+= $(STROBE_SRCS)
SRCS.lora.irr+= $(SRCS.NODE151)

CFLAGS+= -I$(.CURDIR)
CFLAGS+= -g
#CFLAGS+= -DNDEBUG
CFLAGS+= -I$(.OBJDIR)	# for shared_key.h

WITH_STROBE=yes

WITH_SX1276=yes

WITH_NODE151=yes

WITH_USB_CDC=yes

.include <mk/boards.mk>

CFLAGS+= -Werror -Wall

LIBSYOTE_TEST_SRCS= comms.c strobe.c x25519.c
LIBSYOTE_TEST_OBJS= $(LIBSYOTE_TEST_SRCS:C/.c$/.no/)

LIBSYOTE_TEST = libsyote_test.$(SOEXT)
$(LIBSYOTE_TEST): $(LIBSYOTE_TEST_OBJS)
	$(CC) -shared -o $@ $(.ALLSRC)

DEPENDS = .test_deps

# Temporarily disabled as OpenOCD can't program EEPROM on the STM32L1.
# This could be used to add the data to flash.
rng_save.c: Makefile
	( echo '#include <strobe_rng_init.h>'; \
	  echo 'const rng_word_t rng_save[roundup(32, sizeof(rng_word_t)) / sizeof(rng_word_t)] __attribute__ ((section (".eeprom"))) = {'; \
	  dd if=/dev/random bs=32 count=1 | hexdump -e '4/4 " %3u," "\n"'; \
	  echo '};' \
	  ) > $@ || (rm $@ && false)

.test_deps: $(LIBSYOTE_TEST_SRCS)
	$(CC) $(CFLAGS) $(.ALLSRC) -MM | sed -e 's/\.o:/\.no:/' > $@ || (rm -f $@ && false)

.PHONY: runtests
runtests: Makefile syote_comms.py lora.py loraserv.py multicast.py $(LIBSYOTE_TEST) $(LIBSYOTE_TEST_SRCS)
	ls $(.ALLSRC) | entr sh -c '(cd $(.CURDIR) && $(MAKE) $(.MAKEFLAGS) $(LIBSYOTE_TEST)) && ((PYTHONPATH="$(.CURDIR)" python3 -m coverage run -m unittest lora multicast loraserv syote_comms && coverage report --omit=$(.CURDIR)/p/\* -m -i) 2>&1 | head -n 30)'

.if empty(IRR_KEY) && exists($(.CURDIR)/.irr_key)
IRR_KEY!= cat $(.CURDIR)/.irr_key
.endif

.PHONY: irrigation_key
irrigation_key:
	@LANG=C tr -c -d a-zA-Z0-9 < /dev/urandom | dd bs=1 of=$(.CURDIR)/.irr_key count=32 2>/dev/null
	@echo 'Irrgation key created and put into .irr_key.'

# make this a phony target so it's always run
# dependancies will only be made when it's updated
.PHONY: $(.OBJDIR)/shared_key.h
$(.OBJDIR)/shared_key.h:
	@if [ "$(IRR_KEY)" = "" ]; then echo 'Must provide IRR_KEY make variable or have a non-empty file ".irr_key".'; false; fi

	@echo 'static uint8_t shared_key[] = {' $$(python3 -c 'import sys; print(", ".join(str(x) for x in sys.argv[1].encode("utf-8")))' $(IRR_KEY) ) "};" > shared_key.h.tmp
	@echo 'static struct pktbuf shared_key_buf = (struct pktbuf){ .pkt = shared_key, .pktlen = sizeof shared_key, };' >> shared_key.h.tmp

	(cmp shared_key.h.tmp shared_key.h >/dev/null 2>&1 && rm shared_key.h.tmp) || mv shared_key.h.tmp shared_key.h

# hard coded dependancy for when "make depend" has not been run.
irr_main.o: $(.OBJDIR)/shared_key.h

.include <mk/mu.progs.mk>

########################################################
#  External Source Code                                #
########################################################

STROBE_NAME = strobe
STROBE_REPO = https://git.code.sf.net/p/strobe/code
STROBE_BRANCH = master

LORAMAC_NAME = loramac
LORAMAC_REPO = https://github.com/Lora-net/LoRaMac-node.git
LORAMAC_BRANCH = master

.for module in STROBE LORAMAC
.PHONY: init-$($(module)_NAME)
init-$($(module)_NAME):
	git subtree add -P $($(module)_NAME) --squash $($(module)_REPO) $($(module)_BRANCH)

.PHONY: update-$($(module)_NAME)
update-$($(module)_NAME):
	git subtree pull -P $($(module)_NAME) --squash $($(module)_REPO) $($(module)_BRANCH)
.endfor

########################################################
#  Diagrams                                            #
########################################################

# imported from fbsdembdev
#
# Uses Graph Easy to convert to ASCII art:
# https://github.com/ironcamel/Graph-Easy

.SUFFIXES: .getxt .diag .html

.getxt.diag: box.sh
	graph-easy < $< | sh $(.CURDIR)/box.sh > $@

.diag.html:
	(cat $<; echo; echo '<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js" charset="utf-8"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js" charset="utf-8"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>') > $@

DIAG?=diag
test-diag:
	ls $(.CURDIR)/box.sh $(.CURDIR)/$(DIAG).getxt $(.CURDIR)/Makefile | entr sh -c 'cd $(.CURDIR) && $(MAKE) $(.MAKEFLAGS) $(DIAG).diag && cat $(.OBJDIR)/$(DIAG).diag'