[platformio] ; Default program only. Select another with the Pixi tasks or ; `python tools/pio_task.py build --example examples/... --env ...` rather than ; editing this line -- builds are kept in per-example directories so switching ; does not invalidate a cache. src_dir = examples/RP2040SelfTest lib_dir = src default_envs = mouse_joystick [common_env_data] build_flags = -Isrc ; Both bus libraries. `lib_ldf_mode = off` means nothing is discovered by ; scanning includes, so a library that is not named here is simply not on the ; include path -- the symptom is `Wire.h: No such file or directory` from a ; library that plainly includes it. DAC80501 supports either transport and so ; needs both, even on a board that only wires up one. lib_deps_builtin = SPI Wire ; symlink:// rather than a bare path. A bare local path makes PlatformIO COPY ; the directory into .pio/libdeps/ and it does not refresh the copy when the ; source changes -- not on a rebuild, and not on `-t clean` either. Edits to ; src/MouseJoystickBoard/*.cpp then silently do not get compiled, and the build ; succeeds while testing old code. symlink:// links instead of copying. lib_deps_local = symlink://src/MouseJoystickBoard symlink://src/DAC80501 symlink://src/ADS8689 ; The TMC5130A/TMC5160A driver library, pinned to a tag so a build is ; reproducible. Stage 3 uses it for the ramp generator, the encoder scaler and ; the reference-switch homing; stages 1 and 2 do not use it at all, and stage 2 ; deliberately proves the SPI bus with raw datagrams first so that this library ; is never the second unknown in a first-contact test. ; ; Pinned to a tag so a build is reproducible. Stage 3 needs >= 4.1.0 for two ; things 4.0.3 could not express: ; ; * `DriverParameters::withSenseVoltageMode()` -- the TMC5130A's ; CHOPCONF.vsense, a factor of 1.8 in coil current on this board's 0.15 ohm ; shunts, and unreachable through the 4.0.3 API. ; * `EncoderParameters::withMicrostepsPerPulse(mode, scaled)` -- one signed ; value for the encoder scaling, so a reversed encoder does not need the ; 16.16 fixed-point split composed by hand. ; ; Swap in `symlink:///path/to/TMC51X0` to build against ; a local working copy. Do NOT use a bare path -- see the note above about ; PlatformIO copying rather than linking. lib_deps_external = ; 4.2.0 (2026-10-06): one buffer transfer per datagram and the pipelined ; `readMany()` that MotionSetup::snapshot() uses. Measured on pcb v1.0 ; unit A with a logic analyser; see the PCB bring-up log. https://github.com/janelia-arduino/TMC51X0.git#4.2.0 [env] lib_ldf_mode = off ; Defines MJ_FW_VERSION from `git describe` for `ID`'s `fw` field; see ; src/FirmwareVersion.hpp. extra_scripts = pre:tools/git_version.py build_flags = ${common_env_data.build_flags} monitor_echo = yes monitor_eol = LF monitor_filters = send_on_enter colorize monitor_speed = 115200 lib_deps = ${common_env_data.lib_deps_builtin} ${common_env_data.lib_deps_local} ${common_env_data.lib_deps_external} ; ----------------------------------------------------------------------------- ; mouse-joystick-pcb ; ----------------------------------------------------------------------------- ; A custom RP2040 board, not a Pico: 12 MHz crystal, W25Q128JVPIQ 16 MiB QSPI ; flash, no LED, no SWD header, no RUN connection. `generic` is the right board ; definition because it makes no assumptions this board does not meet -- but see ; the pin-mapping traps documented in src/BoardPins.hpp. [env:mouse_joystick] platform = https://github.com/janelia-arduino/platform-raspberrypi.git board = generic framework = arduino board_build.core = earlephilhower upload_protocol = picotool ; 16 MiB. `generic` already declares this; stating it means a future board ; definition change cannot silently shrink the flash map underneath us. The ; self test probes for address aliasing to confirm the part matches. board_upload.maximum_size = 16777216 board_build.filesystem_size = 0m ; The quad-lane stage 2 matched to the W25Q128JV, the default since 2026-10-06. ; Until then every build used the universal single-lane 0x03 stage 2, kept ; from the first article "until stage 1 passes": it fetches every XIP cache ; miss with a command and address per word, and on the link build's code size ; that cost the 1 kHz sampler most of its budget (a `RELEASED` tick 758 us ; median against 346 on this stage 2; PCB bring-up log, "the tick budget ; attributed on the bus and on the pin"). This stage 2 sets the flash's ; quad-enable bit itself (non-volatile) and the generic one still boots a ; board afterwards; env:mouse_joystick_safeflash keeps the generic one for a ; first-article board whose flash is not yet proven. board_build.arduino.earlephilhower.boot2_source = boot2_w25q128jvxq_4_padded_checksum.S ; Two of these boards serve one rig, so the USB strings matter for telling them ; apart. The flash unique id printed by the self test is the actual serial. board_build.arduino.earlephilhower.usb_manufacturer = Janelia Research Campus board_build.arduino.earlephilhower.usb_product = mouse-joystick-pcb ; MJ_BOARD_REV 0 is pcb tags v0.1 and v0.2 ONLY -- the boards sent for assembly ; as rev 0. Their RP2040 pad-to-net maps are byte-identical to each other, and ; differ from v0.3 only in GP10/GP11/GP13, which they leave unrouted and which ; v0.3 routes to the angle-output DAC. No connected pin moves, so the only ; firmware-visible difference is which pads count as spare. ; ; DO NOT BUILD THIS ENV FOR A v0.3 OR v1.0 BOARD. v0.3 is MJ_BOARD_REV 1 and ; v1.0 is MJ_BOARD_REV 2; see the envs below. Building rev 0 against v0.3 ; makes the spare-pad test drive internal pull-ups and pull-downs onto the ; DAC's SPI bus and its chip select; against v1.0 it drives them onto the ; torque ADC bus, the I2C pair and the brake fault line (all behind the open ; bus switch, so no damage, but every strap and fault check reads the wrong ; pins). build_flags = ${common_env_data.build_flags} -DMOUSE_JOYSTICK_PCB=1 -DMJ_BOARD_REV=0 ; Same board on the universal single-lane 0x03 stage 2: boots regardless of ; the flash's quad-enable bit, for a first-article board before its flash is ; proven. Slow XIP (see env:mouse_joystick); not for delivery. [env:mouse_joystick_safeflash] extends = env:mouse_joystick board_build.arduino.earlephilhower.boot2_source = boot2_generic_03h_4_padded_checksum.S ; MJ_BOARD_REV 1: pcb tag v0.3 ONLY (boards 4 and the other v0.3 units). ; GP10/GP11/GP13 carry the angle-output DAC on SPI1 and must not be pulled ; around by the spare-pad test. ; ; THIS IS THE ENV TO BUILD FOR A v0.3 BOARD. The name says "rev1" rather than ; "v0.3", which reads as if no fabricated board matches it. One does. Read off ; the v0.3 kicad_pcb, footprint U501: pad 13 = GP10 = /mcu/DAC_SPI_SCK_, ; pad 14 = GP11 = /mcu/DAC_SPI_COPI_, pad 16 = GP13 = /mcu/~{DAC_CS_}. ; Confirmed on board E4654C159F171E34, stage 1 passed 2026-09-09. ; ; NOT FOR A v1.0 BOARD. pcb HEAD has been v1.0 since 2026-09-21 and is rev 2: ; on it GP13 is ~{BRAKE_FAULT}, an input driven by the brake block, so a rev 1 ; build that closes the bus and drives the DAC chip select shorts two outputs. [env:mouse_joystick_rev1] extends = env:mouse_joystick build_flags = ${common_env_data.build_flags} -DMOUSE_JOYSTICK_PCB=1 -DMJ_BOARD_REV=1 ; MJ_BOARD_REV 2: pcb v1.0, the boards ordered from the 2026-09-21 fabrication ; package (board file unchanged from commit d5ae4b0 through HEAD; no v1.0 tag ; at the time of writing). Read off the kicad_pcb, footprint U601 -- the RP2040 ; moved into the combined MCU block and U501 is now the 36 V switch. Both DACs ; are on I2C0 (GP16/GP17, angle 0x48, brake 0x49), the torque ADC is on SPI1 ; (GP10/GP11/GP12, CONVST GP15), ~{BRAKE_FAULT} is GP13, TQ_CAL_EN is GP18, ; LATCH is GP24, ~{HV_FAULT} moved to GP23, GP27/GP29 are the brake and angle ; monitors, and the instrument port is Digital-50 with no enable. The I2C ; transport is selected by the revision itself; MJ_DAC_I2C is not needed and ; MJ_DAC_I2C=0 is refused. Confirmed on hardware 2026-10-05, unit E4654C159F274534: ; stage 1 (20 checks), stage 2 (direct LATCH-GPIO power-up), A3 (I2C DAC), A6. ; ; The old env:mouse_joystick_rev1_i2c (rev 1 pins with an I2C DAC) described a ; board that never existed and was removed on 2026-10-04. [env:mouse_joystick_rev2] extends = env:mouse_joystick build_flags = ${common_env_data.build_flags} -DMOUSE_JOYSTICK_PCB=1 -DMJ_BOARD_REV=2 ; ----------------------------------------------------------------------------- ; QP/C++ link application (examples/PyControlLinkQp): the stage-4 protocol ; inside one active object, QS trace on FW_TRIG1. qp-arduino comes from its ; released tag on GitHub (since 2026-10-04; before the release it was the ; sibling checkout ../qp-arduino, linked with symlink://). PlatformIO clones ; the tag once into .pio/libdeps and refreshes it only when the pin changes, ; which is the right behaviour for a released dependency. See the example ; README for what each build is for. ; ----------------------------------------------------------------------------- [qp_env_data] build_flags = lib_deps = ${common_env_data.lib_deps_builtin} ${common_env_data.lib_deps_local} ${common_env_data.lib_deps_external} https://github.com/QuantumLeaps/qp-arduino.git#v7.3.4 ; Delivery configuration, rev 0: TmcMotion over the TMC5130A, pyControl on ; UART0, QS trace on FW_TRIG1 (observation record set). Untested on hardware ; with the rail up as of 2026-10-01; TmcMotion's own first run is still owed. [env:mouse_joystick_qp] extends = env:mouse_joystick build_flags = ${common_env_data.build_flags} ${qp_env_data.build_flags} -DMOUSE_JOYSTICK_PCB=1 -DMJ_BOARD_REV=0 -DQS_ON lib_deps = ${qp_env_data.lib_deps} ; Same for rev 1 (pcb v0.3 and later). [env:mouse_joystick_qp_rev1] extends = env:mouse_joystick_qp build_flags = ${common_env_data.build_flags} ${qp_env_data.build_flags} -DMOUSE_JOYSTICK_PCB=1 -DMJ_BOARD_REV=1 -DQS_ON ; Rev 2 (pcb v1.0): TmcMotion, UART0, trace on FW_TRIG1 (Digital-50 DIG1), ; the angle DAC on I2C0. Ran on v1.0 unit E4654C159F274534 on 2026-10-05 (as ; the _usb variant below, phases a-e); the brake and ; torque blocks are not driven by this build yet (caps lacks brake/torque). [env:mouse_joystick_qp_rev2] extends = env:mouse_joystick_qp build_flags = ${common_env_data.build_flags} ${qp_env_data.build_flags} -DMOUSE_JOYSTICK_PCB=1 -DMJ_BOARD_REV=2 -DQS_ON ; Rev 2 bench build, as mouse_joystick_qp_rev1_usb for a v1.0 board: protocol ; over USB CDC, trace on FW_TRIG1, tick probe on the UART0 TX pad (RJ-45 ; unplugged), TICK handler level on FW_TRIG0. First rail-up runs on v1.0. [env:mouse_joystick_qp_rev2_usb] extends = env:mouse_joystick_qp build_flags = ${common_env_data.build_flags} ${qp_env_data.build_flags} -DMOUSE_JOYSTICK_PCB=1 -DMJ_BOARD_REV=2 -DQS_ON -DMJ_LINK_USB=1 -DMJ_TICK_PROBE=1 -DMJ_TICK_LEVEL=1 ; Bisect build for board 4 (2026-10-02): the real TmcMotion with the rev 0 ; pad map (no DAC path at all), protocol over USB CDC, trace on FW_TRIG1, tick ; probe. Safe on a v0.3 board: rev 0 and rev 1 share every pin the rail-up ; path touches; the difference is only the three DAC pads, which rev 0 leaves ; as inputs. If this build survives hv on and rev1_usb does not, the DAC path ; is the culprit. [env:mouse_joystick_qp_rev0_usb] extends = env:mouse_joystick_qp build_flags = ${common_env_data.build_flags} ${qp_env_data.build_flags} -DMOUSE_JOYSTICK_PCB=1 -DMJ_BOARD_REV=0 -DQS_ON -DMJ_LINK_USB=1 -DMJ_TICK_PROBE=1 -DMJ_TICK_LEVEL=1 ; Rail-up bench build for board 4 (pcb v0.3, serial E4654C159F171E34) without ; a pyControl host: TmcMotion over the TMC5130A, the angle DAC on SPI1 (the ; v0.3 strap), protocol over USB CDC, QS on FW_TRIG1, tick probe on the UART0 ; TX pad (the RJ-45 is unplugged for this). IRUN stays at the bring-up value ; in AppConfig.hpp / motionConfig(). Prepared 2026-10-02; compiled, not flashed. [env:mouse_joystick_qp_rev1_usb] extends = env:mouse_joystick_qp build_flags = ${common_env_data.build_flags} ${qp_env_data.build_flags} -DMOUSE_JOYSTICK_PCB=1 -DMJ_BOARD_REV=1 -DQS_ON -DMJ_LINK_USB=1 -DMJ_TICK_PROBE=1 -DMJ_TICK_LEVEL=1 ; Bench build for a board with no 36 V and no pyControl host (the qp-arduino ; fixture): SimulatedMotion, protocol over USB CDC, tick probe on the unused ; UART0 TX pad. Drive it with qp-arduino-example/tools/link_pilot.py. [env:mouse_joystick_qp_sim_usb] extends = env:mouse_joystick_qp build_flags = ${common_env_data.build_flags} ${qp_env_data.build_flags} -DMOUSE_JOYSTICK_PCB=1 -DMJ_BOARD_REV=0 -DQS_ON -DMJ_SIM_MOTION=1 -DMJ_LINK_USB=1 -DMJ_TICK_PROBE=1 -DMJ_TICK_LEVEL=1 ; ----------------------------------------------------------------------------- ; Host tests ; ----------------------------------------------------------------------------- ; Only the Arduino-free arithmetic is testable here: src/Conversions.hpp and ; src/DAC80501Registers.hpp. Both are plain headers reached through -Isrc, which ; is why they are headers and not part of a library -- a library would drag in ; Arduino.h and stop building natively. Everything else on this board needs the ; board. [env:native] platform = native test_build_src = no test_framework = unity test_filter = native/* build_flags = -Isrc lib_deps = throwtheswitch/Unity@^2.6.1