Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
153 lines (127 loc) · 4.79 KB
/
Copy pathMakefile
File metadata and controls
153 lines (127 loc) · 4.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# UIFlow2 / MicroPython workflow for the M5Stack Cardputer-ADV.
#
# There is no official UIFlow2 CLI — M5Burner is a GUI and the Web IDE is a
# browser. It doesn't matter: UIFlow2 firmware is MicroPython, so mpremote is
# the CLI, and `mpremote run` sends tracebacks back to stdout. That is the whole
# point of this Makefile: `make check` runs the code on real hardware and reads
# the result back, so a change can be verified without a human watching.
VENV := .venv
BIN := $(VENV)/bin
PY := $(BIN)/python3
MPREMOTE := $(BIN)/mpremote
MPYCROSS := $(BIN)/mpy-cross
ESPTOOL := $(BIN)/esptool
# The port is discovered, not hardcoded: any USB monitor or dock also shows up
# as /dev/cu.usbmodem*, so we match on the M5Stack manufacturer string.
# Override with `make check PORT=/dev/cu.usbmodemXXXX` if you have two boards.
PORT ?= $(shell MPREMOTE=$(MPREMOTE) sh tools/find-port.sh)
DEV = $(MPREMOTE) connect $(PORT)
APP := app.py
SOURCES := $(APP) selftest.py
LIBS := $(wildcard lib/*.py)
BLOBS := $(wildcard lib/*.bin) # the PCM kit; see tools/build_kit.py
.DEFAULT_GOAL := help
# ---------------------------------------------------------------- the loop
## check: compile, upload, run the self-test on hardware, read the result back
.PHONY: check
check: compile push
@echo "==> running selftest.py on $(PORT)"
@$(DEV) run selftest.py
## compile: MicroPython syntax check — catches more than ast.parse, needs no board
.PHONY: compile
compile:
@for f in $(SOURCES) $(LIBS); do \
printf '==> mpy-cross %s\n' "$$f"; \
$(MPYCROSS) "$$f" -o /dev/null || exit 1; \
done
## push: copy app.py and lib/ to the device without making it the boot program
# lib/*.py land NEXT TO main.py, not in a lib/ subdirectory. The device's
# sys.path is ['', '.frozen', '/lib', '/system', '/flash/libs'] — note there is
# no /flash/lib, so a lib/ subdir would upload fine and then fail to import.
# '' is the working directory, which is /flash. Hence the flat copy.
.PHONY: push
push:
@echo "==> uploading to $(PORT)"
@$(DEV) fs cp $(APP) :app.py
@for f in $(LIBS) $(BLOBS); do $(DEV) fs cp "$$f" ":$$(basename $$f)"; done
## run: run app.py live on the device — tracebacks come back here, Ctrl-C stops it
.PHONY: run
run:
@echo "==> running $(APP) on $(PORT) (Ctrl-C to stop)"
@$(DEV) run $(APP)
## deploy: install as main.py so the app starts on power-up, then reboot
.PHONY: deploy
deploy: compile
@echo "==> installing $(APP) as main.py on $(PORT)"
@$(DEV) fs cp $(APP) :main.py
@for f in $(LIBS) $(BLOBS); do $(DEV) fs cp "$$f" ":$$(basename $$f)"; done
@$(DEV) reset
@echo "==> deployed; board is rebooting into $(APP)"
## undeploy: remove main.py so the board boots back to the UIFlow2 menu
.PHONY: undeploy
undeploy:
@$(DEV) fs rm :main.py || true
@$(DEV) reset
# ---------------------------------------------------------------- inspection
## shots: render every screen to sim/shots/ on the host, then look at them
.PHONY: shots
shots:
@$(PY) sim/shoot.py 3
## kit: rebuild lib/opcp_kit.bin from lib/opcp_synth.py (run after tuning sounds)
.PHONY: kit
kit:
@$(PY) tools/build_kit.py
## audio: render the kit to WAVs on the host, old vs new, then listen
.PHONY: audio
audio:
@$(PY) sim/render_audio.py
## metrics: re-dump font metrics from the board (needed after a firmware update)
.PHONY: metrics
metrics:
@$(DEV) run sim/dump_metrics.py > sim/metrics.json
@echo "==> sim/metrics.json refreshed ($$(wc -c < sim/metrics.json) bytes)"
## probe: dump the M5 API surface this board actually has — check before calling
.PHONY: probe
probe:
@$(DEV) run tools/probe.py
## api: list attributes of one object, e.g. `make api OBJ=M5.Lcd`
.PHONY: api
api:
@test -n "$(OBJ)" || { echo "usage: make api OBJ=M5.Lcd"; exit 1; }
@$(DEV) exec "import M5; M5.begin(); print(sorted(x for x in dir($(OBJ)) if not x.startswith('_')))"
## ls: list the device filesystem (/flash is the working dir and boot dir)
.PHONY: ls
ls:
@$(DEV) fs ls :/flash
## mem: report free heap on the device
.PHONY: mem
mem:
@$(DEV) exec "import gc; gc.collect(); print('free', gc.mem_free(), 'alloc', gc.mem_alloc())"
## repl: open an interactive REPL (Ctrl-] to exit)
.PHONY: repl
repl:
@$(DEV) repl
## reset: reboot the board
.PHONY: reset
reset:
@$(DEV) reset
## port: show which serial port was detected
.PHONY: port
port:
@echo $(PORT)
@$(MPREMOTE) devs | grep -i m5stack || true
# ---------------------------------------------------------------- setup
## venv: create the local toolchain (mpremote, mpy-cross, esptool)
.PHONY: venv
venv:
python3 -m venv $(VENV)
$(BIN)/pip install --upgrade pip
$(BIN)/pip install mpremote mpy-cross esptool pillow
## help: list targets
.PHONY: help
help:
@echo "UIFlow2 / Cardputer-ADV"
@echo
@grep -E '^## ' $(MAKEFILE_LIST) | sed 's/^## / make /' | sed 's/: /\t/' | expand -t 18
@echo
@echo " port: $(PORT)"