You've already forked torvalds-GuitarPedal
mirror of
https://github.com/torvalds/GuitarPedal.git
synced 2026-08-14 04:43:53 +00:00
test-bench, test-analog and measure-load all took whatever enumerated first, and test-audio took its card from one enumeration and its MIDI port from another - so with two boards attached it could have measured the audio of one and talked to the other. test-bench and test-analog at least refused to guess and skipped; the other two did not. All four go through pedal.discover() now and take --target (-t for measure-load), which is passed to pedal.find() - already written to refuse ambiguity rather than answer with the first hit. Refusing is still the default: no target and more than one board is a skip, not a guess. The Makefile passes TARGET= through, the same way check-boot already did. This is not hypothetical tidying. Two boards of one revision differ only in their serial, and the run that matters is the one where a suspected board is compared against a known-good one - which is exactly when picking the wrong one is both easy and invisible. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
244 lines
8.9 KiB
Makefile
244 lines
8.9 KiB
Makefile
CC = gcc
|
|
CFLAGS = -Wall -O2 -I.. -I../Firmware -I../build/ \
|
|
-ffast-math -fsingle-precision-constant -Wfloat-conversion
|
|
|
|
visualize: test-fft
|
|
python visualize.py DADGAD.wav
|
|
|
|
test-fft: test-fft.c
|
|
|
|
test-midi-cin: test-midi-cin.c
|
|
|
|
#
|
|
# The effect bench: the pedal's own audio core, built for the host.
|
|
#
|
|
# Everything it needs is generated here rather than taken from
|
|
# ../build, so it does not need the firmware to have been built
|
|
# and never writes into the source tree. The three math tables carry
|
|
# the shift values from CMakeLists.txt; if those move, these
|
|
# have to move with them, and the bench will be measuring a different
|
|
# pedal until they do.
|
|
#
|
|
# The include paths want a word. Three of the four are the top-level
|
|
# directories the bench compiles against - the repository root so that
|
|
# "Audio/x.h" and the generated map's "Effects/y.h" resolve from
|
|
# wherever they are included, ../Firmware for the pedal-side headers the
|
|
# audio core reaches for (status.h, effect-state.h), and ../Audio
|
|
# because the files in there include each other by bare name. The
|
|
# fourth, bench/shim, has to come first: it is how a workstation gets
|
|
# past the things that only exist on an M33.
|
|
#
|
|
BENCH_GEN = bench/gen
|
|
BENCH_HDRS = $(BENCH_GEN)/effect_map.h $(BENCH_GEN)/pow2.h \
|
|
$(BENCH_GEN)/log2.h $(BENCH_GEN)/quarter_sine.h
|
|
BENCH_CFLAGS = -Wall -Wno-unused-function -O2 \
|
|
-ffast-math -fsingle-precision-constant -Wfloat-conversion \
|
|
-DSAMPLES_PER_SEC=48000.0f \
|
|
-Ibench/shim -I$(BENCH_GEN) -I.. -I../Firmware -I../Audio
|
|
|
|
$(BENCH_GEN)/effect_map.h: $(wildcard ../Effects/*.h) \
|
|
../scripts/gen_effects.py
|
|
@mkdir -p $(BENCH_GEN)
|
|
python3 ../scripts/gen_effects.py ../Effects/ \
|
|
$(BENCH_GEN)/effect_map.h $(BENCH_GEN)/effects.js \
|
|
$(BENCH_GEN)/dummy_map.md
|
|
|
|
$(BENCH_GEN)/pow2.h: ../scripts/pow2.py
|
|
@mkdir -p $(BENCH_GEN)
|
|
python3 $< $@ 8
|
|
|
|
$(BENCH_GEN)/log2.h: ../scripts/log2.py
|
|
@mkdir -p $(BENCH_GEN)
|
|
python3 $< $@ 8
|
|
|
|
$(BENCH_GEN)/quarter_sine.h: ../scripts/quarter_sine.py
|
|
@mkdir -p $(BENCH_GEN)
|
|
python3 $< $@ 8
|
|
|
|
bench/bench: bench/bench.c $(BENCH_HDRS) \
|
|
$(wildcard bench/shim/*/*.h bench/shim/*/*/*.h) \
|
|
$(wildcard ../Audio/*.h) ../Firmware/effect-state.h \
|
|
../Firmware/status.h
|
|
$(CC) $(BENCH_CFLAGS) -o $@ $< -lm
|
|
|
|
#
|
|
# The same headers, without the audio path: just the biquad
|
|
# constructors, so a filter can be asked where it landed.
|
|
#
|
|
#
|
|
# All three math tables, not just the sine: Audio/util.h includes pow2.h
|
|
# and log2.h too, and coeff.c reaches util.h through biquad.h. Only the
|
|
# sine was listed, which worked for as long as nobody built this target
|
|
# with an empty gen/ - 'make bench' builds bench/bench first and that
|
|
# generates all three, so the gap stayed hidden.
|
|
#
|
|
bench/coeff: bench/coeff.c $(BENCH_GEN)/quarter_sine.h \
|
|
$(BENCH_GEN)/pow2.h $(BENCH_GEN)/log2.h \
|
|
$(wildcard bench/shim/*/*.h) $(wildcard ../Audio/*.h)
|
|
$(CC) $(BENCH_CFLAGS) -o $@ $< -lm
|
|
|
|
bench: bench/bench bench/coeff
|
|
|
|
#
|
|
# What the bench is for is looking at one effect, which is a
|
|
# conversation and not a target. What belongs in 'check' is only the
|
|
# part that has a right answer: the two controls that say whether the
|
|
# instrument is working at all. A bench that passes these and an effect
|
|
# that then reads strangely is a finding; a bench that fails these makes
|
|
# every other number in the session worthless.
|
|
#
|
|
check-effects: bench/bench
|
|
./test-effects.py
|
|
|
|
#
|
|
# Where every biquad in the pedal actually lands, swept across the range
|
|
# the pots offer. Host arithmetic only, so it needs no hardware and is
|
|
# part of 'check'.
|
|
#
|
|
check-biquad: bench/coeff
|
|
./test-biquad.py
|
|
|
|
#
|
|
# Do the pages in Documentation/effects still describe the effects, and
|
|
# do their charts still draw?
|
|
#
|
|
# Not slow - three seconds for a page, because bench.py parallelises the
|
|
# sweeps and mmdc takes the whole markdown file in one browser start.
|
|
# It is out of 'check' for the other reason: drawing the charts wants
|
|
# node and a headless browser, fetched through npx the first time, and
|
|
# 'check' should stay runnable with nothing but python and a compiler.
|
|
# It says so rather than skipping quietly when it cannot draw them.
|
|
#
|
|
# This is the target to run after changing an effect, which is exactly
|
|
# when a page goes stale - the last analysis was wrong from the moment
|
|
# single_pole_freq() was fixed under it, and nothing said so for a day.
|
|
#
|
|
check-analysis: bench/bench
|
|
./check-analysis.py
|
|
|
|
#
|
|
# The other half of the bench: whether it agrees with a real pedal.
|
|
#
|
|
# Separate from check-effects because it needs hardware, and separate
|
|
# from check-hw because it needs no signal generator - the stimulus is
|
|
# [TESTTONE] and the capture is the pedal's own USB audio, so the path
|
|
# is digital end to end. Skips when there is no pedal plugged in.
|
|
#
|
|
check-bench: bench/bench
|
|
./test-bench.py $(if $(TARGET),--target $(TARGET))
|
|
|
|
#
|
|
# The analog half, which needs a patch cable from the pedal's output
|
|
# back to its own input and nothing else. One board, one cable, so the
|
|
# DAC and the ADC are the same codec on the same clock and there is no
|
|
# drift to chase.
|
|
#
|
|
# Reports and never fails. What it measures is a converter and a cable
|
|
# rather than any code of ours, and 95 is the issue about a bench
|
|
# measurement that carries no record of the bench - so this prints
|
|
# numbers and lets a person decide whether the cable moved.
|
|
#
|
|
check-analog:
|
|
./test-analog.py $(if $(TARGET),--target $(TARGET))
|
|
|
|
#
|
|
# The web app gets checked too, which needs node.
|
|
#
|
|
# Skipped rather than fatal when node isn't installed: it is the only
|
|
# thing here that needs anything beyond a C compiler and python, and
|
|
# 'make check' should still be worth running without it. It says so when
|
|
# it skips, so it can't quietly stop testing anything.
|
|
#
|
|
NODE := $(shell command -v node 2>/dev/null)
|
|
|
|
#
|
|
# The hardware half. Wants a pedal on the USB and a signal generator on
|
|
# its input, so it is a separate target rather than part of 'check' -
|
|
# and it skips rather than fails when there is nothing plugged in, the
|
|
# same bargain the node check makes below.
|
|
#
|
|
# The generator cannot be set from here. --ptp and --freq say what it
|
|
# is set to, and every number that depends on it is reported against
|
|
# what was declared.
|
|
#
|
|
check-hw:
|
|
./test-audio.py --ptp 0.100 --freq 440 $(if $(TARGET),--target $(TARGET))
|
|
|
|
#
|
|
# Separate from check-hw because it reflashes: planting a scene with
|
|
# channel routing in it means a trip through BOOTSEL, since nothing sets
|
|
# that over MIDI yet. It leaves two scenes behind in the save area.
|
|
#
|
|
check-split:
|
|
./test-split.py
|
|
|
|
#
|
|
# Two pedals, patched output to input in both directions, one generating
|
|
# and the other measured. Separate from check-hw because it needs the
|
|
# second board, and because what it is for is different: check-hw asks
|
|
# whether the pedal does the right thing to a signal somebody else
|
|
# provides, and this asks the questions that need the signal to be under
|
|
# the test's control - what the analog link does, how quiet a properly
|
|
# driven input is, and whether the audio survives the pedal's own sysex.
|
|
#
|
|
check-loop:
|
|
./test-loop.py
|
|
|
|
#
|
|
# The hardware MIDI jacks, through a USB-MIDI adapter on the other end.
|
|
#
|
|
# Reports and never fails. The adapter is a cheap CH345 and the path has
|
|
# shown intermittent trouble nobody has pinned down, so wiring it into a
|
|
# gate would only teach us to ignore the gate. What is wanted is the
|
|
# rate: run it, watch the number, and let the data say whether the
|
|
# flakiness is the dongle, the parser, or nothing.
|
|
#
|
|
check-midi:
|
|
./test-midi.py
|
|
|
|
#
|
|
# Cold power cycles on one board, tallied. Needs a hand on the USB plug
|
|
# - there is no switched hub here - so it is as far from 'check' as a
|
|
# target gets, and it takes a --target because cycling the wrong board
|
|
# yields a number indistinguishable from a real one.
|
|
#
|
|
# make check-boot TARGET=7989 JSON=boot-A.json
|
|
#
|
|
TARGET ?=
|
|
JSON ?=
|
|
check-boot:
|
|
./test-boot.py $(if $(TARGET),--target $(TARGET)) \
|
|
$(if $(JSON),--json $(JSON)) $(BOOTARGS)
|
|
|
|
#
|
|
# The same hang, chased unattended through BOOTSEL instead of through the
|
|
# plug. Cheap enough to leave running, and blind to whatever needs a
|
|
# genuinely cold crystal - a clean run here is not a fixed pedal. See
|
|
# the header of test-reboot.py before believing a result either way.
|
|
#
|
|
check-reboot:
|
|
./test-reboot.py $(if $(TARGET),--target $(TARGET)) \
|
|
$(if $(JSON),--json $(JSON)) $(BOOTARGS)
|
|
|
|
check: test-midi-cin bench/coeff
|
|
./test-midi-cin
|
|
./test-biquad.py
|
|
ifeq ($(NODE),)
|
|
@echo "test-webmidi: SKIPPED - no node in PATH"
|
|
else
|
|
@#
|
|
@# effects.js is generated, so generate it - into a temp directory,
|
|
@# because a test has no business writing into the source tree, and
|
|
@# this way it doesn't matter whether the firmware has been built.
|
|
@#
|
|
@t=`mktemp -d` && \
|
|
python3 ../scripts/gen_effects.py ../Effects/ \
|
|
$$t/dummy_map.h $$t/effects.js $$t/dummy_map.md && \
|
|
$(NODE) test-webmidi.js $$t/effects.js; \
|
|
r=$$?; rm -rf $$t; exit $$r
|
|
endif
|
|
|
|
.PHONY: bench check check-analog check-analysis check-bench check-biquad
|
|
.PHONY: check-boot check-effects check-hw check-loop
|
|
.PHONY: check-midi check-reboot check-split
|