← AXO-013

Circuit review & bench-test guide

AXO-013 — analog joystick carrier PMOD module

Design-stage — board not yet fabricated

Document purpose#

This document explains the axo-013-joystick module at component level and turns the design evidence into a practical manual-review and bench-test plan. It is based on generate_design.py, README.md, and reports/erc.rpt.

This board has never been fabricated or assembled. The schematic is ERC clean (0/0, see reports/erc.rpt) and the netlist has been reviewed, but the PCB layout has not been started — there are no gerbers, no renders, and no physical board. Every number here is a design target or a datasheet expectation to verify, not a proven result. Layout-dependent items (RC/decoupling placement, thumbstick socket clearance from the PMOD clip zone) cannot be reviewed yet and are flagged below.

This is a carrier: it does not contain the joystick. A common 5-pin XY thumbstick breakout (KY-023 class) plugs into socket J2. Because clone breakouts disagree on pin order, Section 4A is a mandatory plug-in-pin-order-verification-before-power gate.

1. What the board does#

AXO-013 digitizes a two-axis analog thumbstick plus its click switch and presents them to a PMOD host over SPI. The stick is mechanically two 10 kΩ potentiometers whose wipers (VRx, VRy) swing rail-to-rail as the stick moves, plus a normally-open switch (SW) that closes to GND when the stick is pressed. A Microchip MCP3202 dual-channel 12-bit SPI SAR ADC digitizes X on CH0 and Y on CH1; the click switch reaches the host as a plain active-low GPIO on PMOD pin 8. Each wiper passes a 1 kΩ + 10 nF RC (fc ≈ 16 kHz) that both filters wiper-scratch noise and acts as the SAR sample-cap charge reservoir.

It teaches SPI ADC transactions, dead-zone/centering math in fabric, and feeds later projects (Pong with the VGA module axo-007, robot teleop with the actuator line). It does not interpret the stick — center offset, dead zone, and axis inversion are all host/HDL responsibilities.

Functional block diagram#

PMOD plug J1 (2x6)
  6/12: 3V3 ──┬────────────┬───────────┬────────────┐
              C4 1uF     C3 100nF    R6 10k       (VDD/VREF U1 pin 8)
              (bulk)     (VDD/VREF)  (~CS PU)
  1: CS_N ───────────────────────────┴──────────────> U1 ~CS (pin 1)
  2: MOSI ──────────────────────────────────────────> U1 DIN (pin 5)
  4: SCK  ──────────────────────────────────────────> U1 CLK (pin 7)
  3: MISO <── R5 100R ── ADC_DOUT ──────────────────── U1 DOUT (pin 6)
  8: JOY_SW <── R4 100R ── SW_RAW ──┬── R3 10k ── 3V3
                                    └────────────────< J2.5 SW (to GND when pressed)

  J2 thumbstick socket (1x5): 1 VCC(3V3) 2 GND 3 VRx 4 VRy 5 SW
    VRx ── R1 1k ──┬── U1 CH0 (pin 2)      C1 10nF ── GND
                   └── JOY_X
    VRy ── R2 1k ──┬── U1 CH1 (pin 3)      C2 10nF ── GND
                   └── JOY_Y
  5/11: GND ──────────────────────────────── U1 VSS (pin 4)

2. Safety and scope boundaries#

3. Power and signal sequence#

  1. The host (or bench supply) applies 3.3 V to PMOD 6/12 and GND to 5/11. C3/C4 charge; U1 VDD/VREF (pin 8) comes up. VREF = VDD is the design intent so the 12-bit code maps linearly to wiper position.
  2. R6 (10 kΩ) holds ~CS high while the host FPGA is unconfigured, so U1 stays deselected and no accidental conversion starts on a floating chip-select.
  3. The thumbstick's two pots divide 3V3→GND; the wipers sit near mid-rail at physical center and swing toward 3V3 or GND at the extents. R1/C1 and R2/C2 low-pass each wiper (fc ≈ 16 kHz) and present the MCP3202's sample cap a low enough source impedance to settle within the acquisition window.
  4. The click switch SW is open at rest; R3 (10 kΩ) holds SW_RAW at 3V3. Press closes SW to GND, pulling SW_RAW low. R4 (100 Ω) series-protects the module-driven JOY_SW line into PMOD pin 8 (active-low).
  5. On demand the host asserts ~CS low, clocks a config frame on MOSI to select CH0 (X) or CH1 (Y), and reads the 12-bit result MSB-first on MISO (through R5's 100 Ω). One conversion per axis per transaction.

4. Interfaces#

PMOD pin123456789101112
Net~CSMOSIMISOSCKGND3V3NCJOY_SWNCNCGND3V3
RefTypeSignalsIntended use
J1PMOD 2×6 plug (Type 2A SPI)SPI + JOY_SW + powerHost connection
J21×05 pin socket1 VCC 2 GND 3 VRx 4 VRy 5 SWThumbstick breakout carrier

SPI framing (MCP3202): mode 0,0 or 1,1; ≤ ~0.9 MHz at 3.3 V (the part is 100 ksps class; a 12-bit conversion needs ~18 clocks). ~CS low starts each conversion; the host clocks in a 4-bit config (START=1, SGL/DIFF, ODD/SIGN, MSBF=1), the ADC returns a leading null (0) bit then 12 data bits, and ~CS high ends it. Single-ended CH0 = SGL/DIFF 1, ODD/SIGN 0; CH1 = SGL/DIFF 1, ODD/SIGN 1.

No dedicated test points exist; probe at J1, J2, and the R1–R6/C1–C4 pads. (Layout to-do: add probe-friendly pads before fabrication.)

4A. Plug-in pin-order verification BEFORE power (mandatory carrier gate)#

The thumbstick breakout is not on this BOM and clone pinouts vary. Do this before the breakout is ever plugged into a powered board.

  1. Read the breakout's own silkscreen. The J2 map expects, socket pin 1→5: VCC, GND, VRx, VRy, SW. Common clone deviations: VRx/VRy swapped (harmless — just swaps X/Y in software), or GND/VCC swapped or +5V labeled (dangerous — reverses supply into the stick and can feed the wrong rail into the RC nodes).
  2. With the breakout unplugged, DMM continuity/ohms across the breakout itself: VCC↔GND should read the two pots roughly in parallel to the wipers (kΩ scale), never a short. VRx and VRy should each read ~5 kΩ to both VCC and GND at mechanical center and sweep as you move the stick. SW should be open to GND at rest and close when pressed.
  3. Confirm the breakout is a 3.3 V-tolerant resistive stick (it always is — it is passive), and that it has no onboard regulator or logic that assumes 5 V.
  4. Only after the map matches, plug the breakout into J2 with the board unpowered, and re-run Section 9A resistance checks through J2 before applying 3.3 V. A reversed VCC/GND here is the one wiring error that this passive carrier cannot protect against.

5. Component-by-component review#

5.1 ADC and connectors#

Ref.PartFunction and why neededIf absent/openIf shorted, wrong, or misassembled
U1Microchip MCP3202-BI/SN, SOIC-8 dual 12-bit SPI SAR ADCDigitizes both wiper voltages ratiometrically (VREF = VDD); returns 12-bit codes over SPINo conversions; MISO reads all-0/all-1SOIC rotation shorts VDD/VSS; a DIN/DOUT swap yields garbage/no data; VREF pin not at 3V3 breaks the ratiometric mapping
J1Generic 2×6 right-angle PMOD plugHost power + SPI + JOY_SWNo host connectionPin-1/zigzag error puts 3V3 on signal pins; verify against the PMOD spec and a physical socket once a layout exists
J2Generic 1×05 2.54 mm socketThumbstick breakout carrierNo stick input; CH0/CH1 float toward mid-rail through pots-absentReversed VCC/GND (see 4A) mis-powers the stick; VRx/VRy swap only exchanges axes

5.2 Per-axis RC (anti-alias + SAR source impedance)#

Ref.ValueFunctionIf omitted or wrong
R11 kΩ (RC0603FR-071KL)X-wiper series element into CH0Open: CH0 floats/no X reading; ≫1 kΩ: with C1 pushes fc down and slows SAR settling, softening the response
C110 nF 50 V X7RX shunt: fc = 1/(2π·1k·10n) ≈ 15.9 kHz, plus SAR charge reservoirOpen: wiper scratch and SAR kickback appear as X jitter; too large: sluggish X, possible under-settle at fast scan
R21 kΩY-wiper series element into CH1As R1, for Y
C210 nF 50 V X7RY shunt, same fcAs C1, for Y

5.3 Button conditioning, SPI support, decoupling#

Ref.ValueFunctionIf omitted or wrong
R310 kΩStick-click pull-up: SW closes to GND, so SW_RAW idles highOpen: JOY_SW floats — random presses; too small: wasted current, still works
R4100 ΩSeries protection on the module-driven JOY_SW line to PMOD 8Open: no button at host; shorted: works, no miswire protection
R5100 ΩSeries protection on the ADC-driven DOUT→MISO lineOpen: MISO dead (reads 0x00/0xFF); ≫100 Ω: RC into host input pin eats the DOUT-valid budget at high SCLK
R610 kΩ~CS idle pull-up: an unconfigured host cannot start a conversionOpen: ~CS floats before FPGA config — spurious conversions/undefined SPI; too small: host fights it (0.33 mA, negligible)
C3100 nF 16 V X7RMCP3202 VDD/VREF decouplingReference bounce during acquisition degrades LSBs
C41 µF 10 V X7RSupply bulk at the socketMore rail droop under the pot/ADC load; noisier LSBs

Power flags #FLG01 (3V3) and #FLG02 (GND) are ERC source markers, not physical parts. Every schematic reference designator (U1, J1, J2, R1–R6, C1–C4) is covered above. There are no jumpers on this module.

6. Datasheet summary and design interpretation#

Primary reference: Microchip MCP3202 datasheet (21034F). Check the revision before procurement.

Datasheet factValueBoard-specific interpretation
Resolution / channels12-bit, 2-ch (single-ended or 1 pseudo-diff pair)CH0 = X, CH1 = Y, both single-ended vs VSS
ReferenceVREF = VDD tied here (pin 8)Ratiometric: code = 4096·V_wiper/VDD; supply noise cancels since the stick divides the same VDD
Sample rate100 ksps at VDD = 5 V, ~50 ksps at 2.7 V; ~18 clocks/conversionAt 3.3 V keep SCLK ≤ ~0.9 MHz for full accuracy; a joystick needs only kHz-rate scans
SPI frameSTART, SGL/DIFF, ODD/SIGN, MSBF config in; null bit + 12 data outFirst returned bit is a 0 null — a stuck-high first bit means MISO/DOUT trouble
Input modelSwitched sample cap (~20 pF class), needs low source ZThe 1 kΩ series is well within the part's source-impedance tolerance; C1/C2 supply the sample charge
Supply2.7–5.5 V, ~550 µA active, sub-µA standby (CS high powers down)Single 3.3 V rail; CS-high between reads lets it idle

The thumbstick itself: two ~10 kΩ linear pots and an SPST-NO click switch. Center voltage ≈ VDD/2 only if the pot is mechanically centered and linear; real sticks show a center offset and non-symmetric extents that the host must calibrate.

7. Expected values before bench testing#

None of these have been measured — no board exists.

QuantityExpected (design/datasheet)How to measure
3V3-to-GND resistance, unpoweredHigh (kΩ–MΩ scale after caps charge; a few kΩ once J2 stick is fitted, from the two pot end paths)DMM both polarities
~CS-to-3V3 resistance≈10 kΩ (R6)DMM J1 pin 1 → pin 6
JOY_SW-to-3V3 (stick released)≈10 kΩ (R3), through R4 in seriesDMM J1 pin 8 → 3V3
MISO continuity to U1 DOUT≈100 Ω (R5)DMM J1 pin 3 → U1 pin 6
X/Y wiper to CH0/CH1≈1 kΩ (R1/R2)DMM J2.3/J2.4 → U1 pin 2/3
VRx/VRy at mechanical center≈ VDD/2 (≈1.65 V) ± stick offsetDMM at JOY_X/JOY_Y nodes, powered, stick centered
VRx/VRy at extentsswing toward ≈0 V and ≈3.3 V (not always full rail)DMM while holding each extent
Center 12-bit code≈2048 ± offset (hundreds of counts of offset is normal)First SPI reads, stick centered
Extent 12-bit codesapproach 0 and ~4095, asymmetricallySPI reads at each extent
JOY_SW pressedlogic low at PMOD 8Scope/DMM while pressing
Active supply current< 1 mA totalµA/mA meter, standalone supply

The canonical first read: MCP3202 CH0 (X) over SPI#

Exact framing (single-ended CH0, MSBF, mode 0,0; the 3-byte host convention):

Assert ~CS low.
MOSI byte 0: 0x01                 (START bit)
MOSI byte 1: 0xA0                 (SGL/DIFF=1, ODD/SIGN=0 -> CH0, MSBF=1)
MOSI byte 2: 0x00                 (clock out the low data bits)
MISO: byte1 lower bits + byte2 = null bit then D11..D0
X code = ((byte1 & 0x0F) << 8 | byte2) masked to 12 bits
Deassert ~CS.  For CH1 (Y) use byte1 = 0xE0 (ODD/SIGN=1).

A first frame that returns 0x000 or 0xFFF stops bring-up: MISO dead (R5 open, DOUT unsoldered), DIN/DOUT swapped, ~CS never asserted, or the part unpowered. A value stuck near mid-scale that never moves with the stick points at a J2 wiring/pot problem, not the ADC.

8. Manual schematic and assembly review checklist#

Reviewable now:

Assembly items (for the eventual first article — none exists yet):

9. Ordered bench-test procedure#

Stop at the first abnormal result. Record board serial, supply voltage, equipment, SPI clock, and operator. Two host contexts: standalone (current-limited bench supply + SPI adapter, phases B–D) and PMOD host (FPGA/MCU provides 3.3 V, phase E). Standalone first. Complete Section 4A before J2 is populated and powered.

A. Unpowered inspection and resistance tests#

  1. Complete the Section 8 checklist under magnification; complete 4A.
  2. DMM 3V3-to-GND (J1 pin 6 → 5), both polarities: no hard short.
  3. ~CS (pin 1) → 3V3: ≈10 kΩ. JOY_SW (pin 8) → 3V3: ≈10 kΩ (stick released).
  4. MISO (pin 3) → U1 DOUT: ≈100 Ω. MOSI/SCK (pins 2/4) → U1 pins 5/7: ≈0 Ω.
  5. With the stick fitted: VRx/VRy (J2.3/J2.4) → U1 CH0/CH1: ≈1 kΩ; sweep the stick and watch resistance to 3V3/GND change smoothly.

B. Standalone first power#

  1. Bench supply 3.3 V (measure it), current limit 20–50 mA, output off. Wire + to J1 PMOD 6/12, − to 5/11 per the header map.
  2. Power on: no current-limit trip; total draw < 1 mA. Milliamps beyond that mean a solder fault or reversed stick supply.
  3. Verify 3.3 V at C3/C4/U1 pin 8; ~CS idling at 3.3 V through R6; JOY_SW near 3.3 V; VRx/VRy near mid-rail with the stick centered.

C. Standalone SPI bring-up and axis reads#

Use any 3.3 V SPI master, mode 0,0 (or 1,1), start at ~500 kHz, MSB first.

  1. CH0 (X): run the Section 7 frame. Expect a valid 12-bit code near 2048 at center. Capture the first frame regardless of result.
  2. CH1 (Y): byte1 = 0xE0. Same expectation.
  3. Sweep test: move the stick slowly corner to corner and log both codes. Each axis should move monotonically from near 0 to near 4095; note the center code and the two extents per axis (they are usually asymmetric).
  4. Button: read PMOD 8 while pressing the stick — high released, low pressed, clean through R4/R3.

D. Center and extents calibration#

  1. Center: stick released, average ≥ 100 samples per axis → X_center, Y_center. Expect ≈2048 ± offset; hundreds of counts offset is normal.
  2. Extents: hold each of the four mechanical stops, average → X_min, X_max, Y_min, Y_max. Record all four per axis; they bound the usable range.
  3. Dead zone: compute the peak-to-peak jitter at rest (should be a few LSB with the RC filters working); set the host dead zone above it.
  4. Repeat after re-centering; center code should return within noise. These numbers are per-stick and per-assembly — this is calibration data, not a pass/fail spec.

E. PMOD-host context (FPGA/MCU provides 3.3 V)#

  1. Measure the host socket rail: must be 3.3 V. Confirm the host I/O bank voltage.
  2. Plug in with the host unconfigured; verify ~CS reads 3.3 V at the module (R6 vs a floating host pin).
  3. Run the same ladder from the host SPI master (bit-banged or the AruviX HDL SPI+MCP3202 core): CH0/CH1 reads, center/extents, JOY_SW GPIO.
  4. Scope the first host-driven frame and compare with the phase C capture; confirm the leading null bit and 12 data bits.
  5. Demo: dead-zone + centering math in fabric driving Pong (axo-007 VGA) or robot teleop.

F. Release-only tests#

Pot linearity/repeatability characterization, mechanical endurance of the stick, ESD at J1/J2, and temperature behavior belong to a separate qualification plan, gated on a board existing at all.

10. Troubleshooting map#

SymptomFirst measurementsLikely areas
Current-limits at power-on3V3-to-GND resistanceReversed stick VCC/GND (4A), U1 solder bridge, >rating event
Both axes read 0x000/0xFFFScope ~CS/SCK/MOSI/MISO during a frameDIN/DOUT swap, R5 open, ~CS not reaching U1, unpowered
Reads shifted/garbageSCLK edges vs SPI mode; leading null bitWrong mode, bit order, SCLK too fast for 3.3 V
One axis stuck mid-scaleThat axis' wiper voltage at J2 and JOY_X/YPot wiper open, R1/R2 open, J2 wiring, stick fault
Axes swappedWhich stick direction moves which codeVRx/VRy swapped on the breakout (harmless, fix in SW)
Codes inverted (max at rest)VCC/GND at the stickReversed stick supply (4A)
No buttonJOY_SW at U1 side of R4 vs J1 sideR3 open (floats), R4 open, switch fault
Noisy/jittery axesPeak-to-peak at rest; C1/C2 presenceRC missing/wrong, long unshielded stick leads, dead zone too small
Works standalone, dead on hostHost rail and bank voltage, ~CS idleWrong socket voltage, host pin contention

11. Bench record template#

FieldRecord
Board revision / serial
Thumbstick breakout make + verified pin order (4A)
Supply voltage (exact) and current limit
Host or adapter, SPI clock, equipment + calibration
Unpowered resistance results (A.2–A.5)
Active supply current
CH0/CH1 center codes + first-frame capture path
Four extents per axis (X_min/max, Y_min/max)
Rest jitter / chosen dead zone
JOY_SW pressed/released result
Deviations, photos, raw-file paths
Reviewer / date / disposition

12. Review conclusion#

The schematic is a clean minimal MCP3202 carrier: both axes digitized ratiometrically (VREF = VDD), 1 kΩ + 10 nF per wiper for scratch filtering and SAR charge, the click switch pulled up and passed out behind 100 Ω, ~CS defended by a 10 kΩ idle pull-up, and DOUT behind the standard 100 Ω line resistor. The principal risks are that nothing physical exists yet (no layout, no first-article data); the passive carrier's inability to protect against a reversed thumbstick VCC/GND, which makes the Section 4A pin-order gate mandatory; SPI framing discipline (leading null bit, correct config bits); and that center/extents are per-stick calibration data, not board specifications. The bring-up ladder — CH0/CH1 12-bit reads, center capture, four-extent sweep, button GPIO — is exactly what the AruviX SPI+MCP3202 HDL core and its dead-zone/centering math will need to reproduce.