Makefile 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. # OpenPuck developer convenience targets.
  2. # Pin to clang-format 18 to match CI; output differs between versions, so a
  3. # mismatch would make CI reject locally-formatted code. Resolve the binary in
  4. # order of preference: the apt-style versioned name (CI / Linux), the Homebrew
  5. # llvm@18 keg (macOS), then a bare clang-format as a last resort. Override with
  6. # `make format CLANG_FORMAT=/path/to/clang-format` if yours lives elsewhere.
  7. CLANG_FORMAT ?= $(shell command -v clang-format-18 \
  8. || ([ -x /opt/homebrew/opt/llvm@18/bin/clang-format ] && echo /opt/homebrew/opt/llvm@18/bin/clang-format) \
  9. || ([ -x /usr/local/opt/llvm@18/bin/clang-format ] && echo /usr/local/opt/llvm@18/bin/clang-format) \
  10. || command -v clang-format)
  11. # All hand-written C/C++ sources. Generated headers (git_version.h) are
  12. # gitignored and excluded here so formatting never touches them.
  13. FORMAT_FILES := $(shell find OpenPuck ReversePuckFirmware puck_sniffer pairtui \
  14. \( -name '*.c' -o -name '*.cpp' -o -name '*.h' -o -name '*.hpp' -o -name '*.ino' \) \
  15. -not -name 'git_version.h')
  16. # --- firmware build ---------------------------------------------------------
  17. # The OpenPuck firmware needs two TinyUSB config values that differ from the Adafruit nRF52 core defaults:
  18. # CFG_TUD_HID=4 -- four HID interfaces (Steam mode exposes four puck slots); core default is 2.
  19. # CFG_TUD_TASK_QUEUE_SZ=64 -- deeper usbd event queue; the default 16 deadlocks the loop task under comms
  20. # load -> watchdog reset (see OpenPuck.ino + docs/BUILD_AND_DEPLOY.md).
  21. # CFG_TUD_VENDOR_TX_BUFSIZE=256 -- the WebUSB status blob is ~118 B; the core default 64 can't hold it whole,
  22. # so the panel send (which drops rather than blocks when the FIFO is full) could
  23. # never fit a frame -> blank panel. Sized to hold a full blob with headroom.
  24. # They're baked in here so a normal build is just `make build` -- no need to remember the flags. Override any
  25. # on the command line, e.g. make build CFG_TUD_HID=6 CFG_TUD_TASK_QUEUE_SZ=128
  26. # or add your own defines: make build EXTRA_FLAGS="-DOPK_LOG=1"
  27. FQBN ?= adafruit:nrf52:feather52840
  28. CFG_TUD_HID ?= 4
  29. # Deep so a loop()-context sendReport never blocks on a full usbd event queue (the watchdog path). Sends run
  30. # from loop() now (usbTxPump) for stable RF timing, so this depth is what keeps that block from happening.
  31. CFG_TUD_TASK_QUEUE_SZ ?= 512
  32. # Must hold a whole WebUSB status blob (~118 B) so the drop-on-full panel send can fit one; core default 64 is
  33. # too small and would silently drop every frame (blank panel / stale mappings).
  34. CFG_TUD_VENDOR_TX_BUFSIZE ?= 256
  35. EXTRA_FLAGS ?=
  36. # {build.flags.usb} is expanded by arduino-cli (VID/PID/strings); pass it through verbatim.
  37. USB_EXTRA_FLAGS = -DNRF52840_XXAA {build.flags.usb} -DCFG_TUD_HID=$(CFG_TUD_HID) -DCFG_TUD_TASK_QUEUE_SZ=$(CFG_TUD_TASK_QUEUE_SZ) -DCFG_TUD_VENDOR_TX_BUFSIZE=$(CFG_TUD_VENDOR_TX_BUFSIZE) $(EXTRA_FLAGS)
  38. # Low-frequency clock source for the SoftDevice (BLE controllers feature). The feather52840 variant hardcodes
  39. # USE_LFXO (32.768 kHz crystal), but the Pro Micro / SuperMini nRF52840 CLONES this firmware runs on have NO
  40. # crystal -- with LFXO the SoftDevice's Bluefruit.begin() fails (BLE_ST_FAILED). variant_lfrc/ is a verbatim
  41. # copy of the express variant with ONLY the LF clock flipped to the internal RC oscillator (250 ppm, well
  42. # within BLE tolerance and what these boards already run their LFCLK on in bare-metal mode); the pin map / USB
  43. # identity are otherwise identical. A compile-time #error in ble_host.cpp guards against this override being
  44. # dropped (which would silently re-break BLE). Set LF_VARIANT_PATH= empty to fall back to the stock LFXO
  45. # variant if you build for a genuine crystal board without BLE.
  46. LF_VARIANT_PATH ?= $(CURDIR)/variant_lfrc
  47. VARIANT_PROP = $(if $(LF_VARIANT_PATH),--build-property "build.variant.path=$(LF_VARIANT_PATH)",)
  48. # `flash`/`deploy` take the serial port as a REQUIRED POSITIONAL arg: `make flash /dev/cu.usbmodem1101`.
  49. # (No auto-detect -- uploading to a guessed serial port risks writing to the wrong device. List with
  50. # `arduino-cli board list`.) FLASH_PORT = whatever goal isn't one of our real targets; the catch-all rule at
  51. # the bottom swallows it so make doesn't try to build the port path as a target.
  52. FLASH_PORT := $(filter-out format format-check check build build-recovery flash deploy,$(MAKECMDGOALS))
  53. UPLOAD = arduino-cli upload -b $(FQBN) -p "$(FLASH_PORT)" OpenPuck
  54. .PHONY: format format-check check build build-recovery flash deploy
  55. ## Compile the firmware with the required USB flags baked in. Override CFG_TUD_HID / CFG_TUD_TASK_QUEUE_SZ /
  56. ## EXTRA_FLAGS / FQBN as make variables if needed.
  57. build:
  58. arduino-cli compile -b $(FQBN) --build-property "build.extra_flags=$(USB_EXTRA_FLAGS)" $(VARIANT_PROP) OpenPuck
  59. ## One-time factory-reset recovery image (wipes persistent storage once on first boot). See §6 of the build doc.
  60. build-recovery:
  61. $(MAKE) build EXTRA_FLAGS="$(EXTRA_FLAGS) -DOPK_FACTORY_RESET=1"
  62. ## Upload the most recent build. Usage: make flash <port> e.g. make flash /dev/cu.usbmodem1101
  63. ## The board may need DFU/bootloader mode first (double-tap RST): puck (Steam/Lizard) mode drops the CDC port
  64. ## so arduino-cli can't auto-reset it -- see docs/BUILD_AND_DEPLOY.md.
  65. flash:
  66. @[ -n "$(FLASH_PORT)" ] || { echo "usage: make flash <port> e.g. make flash /dev/cu.usbmodem1101 (list ports: arduino-cli board list)"; exit 1; }
  67. $(UPLOAD)
  68. ## Build then upload in one step. Usage: make deploy <port> (same build overrides as `build`).
  69. deploy:
  70. @[ -n "$(FLASH_PORT)" ] || { echo "usage: make deploy <port> e.g. make deploy /dev/cu.usbmodem1101"; exit 1; }
  71. $(MAKE) build
  72. $(UPLOAD)
  73. # Swallow the positional <port> arg so make doesn't error trying to build it as a target. Scoped to things
  74. # that look like a serial port (so a real typo like `make buld` still errors instead of silently no-op'ing).
  75. /dev/% COM% tty% cu.%:
  76. @:
  77. ## Reformat all C/C++ sources in place using the Linux kernel style.
  78. format:
  79. $(CLANG_FORMAT) -i $(FORMAT_FILES)
  80. ## Verify all C/C++ sources are formatted; exit non-zero if any differ.
  81. ## Used by CI to reject unformatted code.
  82. format-check:
  83. $(CLANG_FORMAT) --dry-run --Werror $(FORMAT_FILES)
  84. ## Everything CI gates on.
  85. check: format-check