

Carrier
One board that turns the Pi 4 + 7" screen into a complete car radio replacement. It bolts onto the Pi like a HAT, plugs into the truck's radio harness, and does everything the factory radio did plus what the Pi needs:
- Size
- 164.9 × 102 mm
- Copper layers
- 4
- Thickness
- 1.6 mm
- Parts
- 171
- Nets
- 117
- Pads
- 583
- Tracks, vias
- 1,630, 319
- Pours
- 31
- Routed
- Yes
- KiCad
- KiCad 10.0 (file 20260206)
- Created
- 20 Jul 2026
- Updated
- 29 Oct 2026
Overview
Carrier is an open-source printed circuit board by AJXD2, from the AJXD2/carplay-project repository on GitHub. It is a 4-layer board of 164.9 × 102 mm with 171 parts on 117 nets, routed with 1,630 tracks and 319 vias.
It is built around the ADS1115IDGSR, LM61460AFSQRJRRQ1 and PCM1808QPWRQ1, with the TAS6424EQDKQRQ1, CAT24C32WI-GT3 and DS3231SN#T&R among its other parts. Its parts include 75 capacitors, 46 resistors, 10 diodes, 9 inductors and 8 ICs.
Main components
12ADS1115IDGSR
VSSOP-10-40℃~+125℃ 16 1LSB 2 2.048V 2V~5.5V 500nA 860Hz 8Hz、16Hz、32Hz、64Hz、128Hz、250Hz、475Hz、860Hz Built-in Built-in I2C Sigma-Delta Support Yes VSSOP-10 Analog to Digital Converters (ADC) ROHSTexas InstrumentsAnalog To Digital Converters (ADC)LM61460AFSQRJRRQ1
VQFN-14-HR(3.5x4)-40℃~+150℃@(TJ) 1 1V~34.2V 200kHz~2.2MHz 3V~36V 6A 7uA Adjustable Buck Built-in Light load efficient mode、Operating status indication、Frequency synchronization、Built-in LDO regulator、EMI optimization (spread spectrum) Step-down type Yes VQFN-14-HR(3.5x4) DC-DC Converters ROHSTexas InstrumentsDC-DC ConvertersPCM1808QPWRQ1
TSSOP-14-40℃~+125℃ 1uA、150uA 2 2.7V~3.6V、4.5V~5.5V 24 96000Hz Audio Analog-to-Digital Converter Built-in TSSOP-14 ADCs/DACs - Special Purpose ROHSTexas InstrumentsADCs/DACs - Special PurposeTAS6424EQDKQRQ1
HSSOP-56-40℃~+125℃ -80dB 0.009% 4-Channel 4.5V~26.4V 75Wx4@4Ω 86% Class D Enable/shutdown function、Overvoltage protection HSSOP-56 Audio Amplifiers ROHSTexas InstrumentsAudio AmplifiersCAT24C32WI-GT3
SOIC-8-40℃~+85℃ 0.4us、0.9us、3.5us 1,000,000 cycles 1.7V~5.5V 100 years 1MHz 2mA 32Kbit 5ms 5uA Hardware write protection function、Noise suppression function、Built-in power-on reset (POR) I2C SOIC-8 EEPROM ROHSonsemiEEPROMDS3231SN#T&R
SOIC-16-300mil-40℃~+85℃ 0.84uA 2.3V~5.5V 200uA Built-in I2C Temperature compensation、Programmable clock output、Alarm function Yes SOIC-16-300mil Real Time Clocks ROHSMaxim Integrated (Analog Devices)Real Time ClocksLM74800QDRRRQ1
SON-12(3x3)-40℃~+125℃ 2.6A 3V~65V Ideal Diode Over Voltage Protection SON-12(3x3) Power Distribution Switches ROHSTexas InstrumentsPower Distribution SwitchesTLV75533PDBVR-MS
SOT-23-5SOT-23-5 Voltage Regulators - Linear, Low Drop Out (LDO) Regulators ROHSMSKSEMIUncategorisedCC0603KRX7R9BB104
0603100nF 50V X7R ±10% 0603 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHSYAGEOMultilayer Ceramic Capacitors MLCC - SMD/SMTCL21B105KBFNNNE
08051uF 50V X7R ±10% 0805 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHSSamsung Electro-MechanicsMultilayer Ceramic Capacitors MLCC - SMD/SMTMHCI06030-3R3M-R8
SMD,7.3x6.6mm12A 3.3uH 35mΩ 6A Magnetic Shielded Inductor ±20% SMD,7.3x6.6mm Power Inductors ROHSChilisin ElectronicsPower InductorsCL31B106KBHNNNE
120610uF 50V X7R ±10% 1206 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHSSamsung Electro-MechanicsMultilayer Ceramic Capacitors MLCC - SMD/SMT
README
hardware/carrier/README.mdCarrier board (2007 4Runner head unit)
One board that turns the Pi 4 + 7" screen into a complete car radio replacement. It bolts onto the Pi like a HAT, plugs into the truck's radio harness, and does everything the factory radio did plus what the Pi needs:
- survives car power (reverse battery, load dump, cranking) and switches itself fully off with the key (a few µA left on the battery)
- powers the Pi, the screen and the fans (5 V, 6 A)
- drives the four stock speakers from the Pi's digital audio (no USB DAC, no ground-loop hum)
- reads the steering-wheel buttons (learn mode, any wheel)
- senses key, headlights (night mode) and reverse
- keeps the clock running with the power off
- runs two fans, and tells the Pi what it is at boot (HAT ID EEPROM)
Software for it lives in launcher/board/.
Status
| Stage | State |
|---|---|
| Schematic | Done. ERC 0 errors / 0 warnings. |
| Parts list (BOM) | Done. 148 fitted parts, every one with an LCSC number, stock checked at JLCPCB. |
| Placement | Done for the nominal Pi position. DRC: no overlaps or clearance errors. |
| Routing | Done. 0 unrouted, 0 DRC errors, schematic parity 0. |
| Silkscreen tidy | Done (10 cosmetic silkscreen warnings left). |
| Pi position on the screen | Measured on the real screen and confirmed with a printed fit test (see Mechanical). |
| Software | Installed and running in the truck (launcher/board/install.sh, carrierd); 21 tests on simulated hardware. |
| Simulation + assembly check | Done 2026-09-29: SPICE on every analog block, pinouts and land patterns against datasheets, placement file against JLC's footprints (VERIFICATION.md). |
| Housing | Designed (tools/housing.py): PETG shell + fan lid, clearance-checked against the board, Pi and screen, and checked that each part can go in. First shell printed as a dash and screen fit test; its lid screw blocks stopped the board going in, now moved. Shell and lid to be reprinted. |
| Ordering | Rev A built (2 boards). Board 2 in the truck since 2026-10-28; board 1 has dead audio clocks (X1 or U8 joint, to rework). Bring-up log and in-truck results: BRINGUP.md. |
How it works, block by block
The schematic (carrier.kicad_sch, one A2 sheet, PDF in out/carrier.pdf)
is split into boxed sections. The same section names tag every part
(hidden Section field) so the board layout can find each block.
| Section | Parts | What it does |
|---|---|---|
| Harness | J1, Molex Micro-Fit 3.0 2x10 vertical | Truck wiring in; plug faces the firewall |
| Input protection | LM74800-Q1 + 2x BUK7Y4R8-60E + SMBJ33CA | Reverse-battery block, cuts off above 34.3 V (32.6-36.0 V worst case; load dump), slow soft start (~2.5 V/ms). Its enable (SYS_EN) is the board's master switch |
| 5 V buck | LM61460-Q1, 4.7 µH | 5 V / 6 A at 400 kHz for Pi, screen (through GPIO pins 2/4 and the display's pogo pins), fans. Turns on at 6.0 V, off at 4.3 V, so it rides through cranking |
| 3.3 V | TLV75533 | Amp logic, ADC, RTC, EEPROM, clocks |
| Power hold + sensing | diodes, RC, 3x MMBT3904 | SYS_EN = key OR the Pi's hold line. Key/lights/reverse become active-low 3.3 V inputs |
| Amplifier | TAS6424E-Q1 | 4 x BTL, about 25 W/ch into 4 Ω at 14.4 V, 2.1 MHz switching, I2C controlled (0x6A) |
| Output filters | 8x 3.3 µH + 1 µF + 1 nF | Reconstruction filter per speaker leg (TI reference values) |
| Audio clocks | 12.288 MHz oscillator + PCM1808-Q1 | The board is the audio clock master (see decisions) |
| Mic input | 3.5 mm jack J4 (PJ-320D) into the PCM1808 | Electret car mic for calls and Siri: bias from 3.3 V, ESD and RF filtering at the jack, the PCM1808's ADC sends it to the Pi on GPIO20. Mic on the tip; ring and sleeve grounded |
| Status LEDs | 3 red 0603 (D8-D10), tagged 12V / 5V / PI | Which power stage is alive: protected 12 V, the 5 V rail, and the Pi holding the board on |
| Steering wheel + battery ADC | ADS1115 (0x48) | Two ladder inputs (1k pull-ups, ESD, RC filter), battery voltage on AIN2 |
| RTC + ID EEPROM | DS3231SN + CR2032 (0x68), CAT24C32 (0x50) | Clock through power-off; HAT ID per the Raspberry Pi HAT design guide |
| Pi | J2, 2x20 socket on the underside | Mates with the Pi's header |
| Fans | 2x 4-pin headers, 2N7002 each | PWM from the Pi, inverted by the FET; tach readback |
| Debug + mounting | UART header (not fitted), H1-H6 | Pi holes isolated per HAT spec; H5/H6 are grounded M3 holes beside the amp (heatsink strap or ground wire) |
Design decisions and why
- Class-D amp fed digitally (I2S). The old setup went through a USB sound card; digital audio straight to the amp removes that and the ground-loop path. The TAS6424E-Q1 is automotive (AEC-Q100), survives 40 V load dump, and was the only in-stock 4-channel part with digital input at JLCPCB.
- The board is the audio clock master. The Pi's PCM block carries only two channels, and the TAS6424 needs a real master clock (128-512 x the sample rate) outside TDM mode. So a 12.288 MHz oscillator drives the amp's MCLK directly and a PCM1808-Q1 in master mode (MD1 = MD0 = high, strapped, no software) divides it to the bit clock (64 fs) and frame clock (48 kHz). All three come from one crystal and cannot drift apart. The Pi runs its I2S port as a clock consumer. Consequences: audio is fixed at 48 kHz (PulseAudio resamples), and the rear speakers play the same stereo as the front (SDIN1 and SDIN2 share the data); the fader and balance use the amp's per-channel volume. The CS2100 clock chip originally planned was dropped: JLC only stocks the -10 to 70 °C grade.
- One master switch. The LM74800's enable turns the whole board off.
SYS_EN is the OR of the key (with a 4.7-10 s RC grace period so a crank
before the Pi boots does not cut power, even when the key goes straight to
START) and the Pi's own hold line (GPIO26). The Pi decides when to power
off: key off for 8 s, then it shuts down cleanly, drops the hold line, and
the board switches off 3-5 s later (3 uA standby after 7-12 s). A hung Pi
is reset by its watchdog, which also drops the hold line. Times are from
tools/sim.pyover part tolerances. - Steering wheel by learn mode. Toyota wheels are resistor ladders on two wires. Instead of hard-coding resistor values, the software asks for each button once and remembers what it reads. It refuses two buttons it cannot tell apart.
- Harness as one latching plug. Every truck wire ends in one Micro-Fit plug (like a PC's ATX connector) that clicks into the board. 8.5 A per contact; 12 V and ground use several pins each.
- Heatsink copied from TI's evaluation board. The amp's thermal pad is
on top of the chip. TI's EVM uses a custom 20 x 41.4 mm finned heatsink
screwed down with M3 screws and Arctic Silver paste; ours is the same
footprint with fins sized for CNC machining (
tools/heatsink.py). Its feet sit on grounded pads, which grounds the heatsink as TI requires. Rev A skips the CNC part on cost and uses a stock 20 x 20 x 10 mm heatsink instead; see "Amp heatsink" under the shopping list for what that needs. - Part choices for car conditions. Every IC is rated to at least 85 °C. Caps upstream of the 35 V cutoff are 100 V (the TVS can clamp to 53 V), the rest of the 12 V side is 50 V X7R. Speaker-filter 1 nF caps are C0G. Boot caps are 0603 (fit the amp's 0.635 mm pin pitch; datasheet asks for X7R ≥ 16 V, these are 50 V).
- Fans fail safe. The PWM FET's gate pull-down leaves the fans at full speed whenever the Pi is not driving them.
Full calculations (divider values, time constants, cut-off voltages) are written as notes on the schematic next to each circuit.
Mechanical
Display: Hosyond 7" DSI, 164.9 x 102.0 mm, 12.25 mm thick per the
manufacturer's drawing (datasheets/hosyond/). The board uses the same
outline. Its own four mounting holes sit 5 mm in from each corner (154.89 x
91.92 mm apart), each with a 4 mm threaded M2.5 pillar: the housing screws
onto those before the Pi and board go on (the board sits 12.6 mm above the
pillar tops, clear of the screw heads).
Where the Pi sits on the screen. First estimated from Hosyond's product photo (the Pi's 58 x 49 mm hole pattern set the scale), then measured on the real screen on 2026-09-24 with a printed fit plate and calipers, Pi board edge to screen edge:
| Pi edge | To the screen edge |
|---|---|
| Ports side (USB/Ethernet) | 36.65 mm |
| Display ribbon side | 43.40 mm |
| GPIO side | 15.35 mm |
| USB-C / HDMI side | 31.45 mm |
The sums (165.05 x 102.80, all values rounded down) match the 165 x 103 screen. Left/right differed from the photo estimate by 1.35 mm, up/down by under 0.2 mm. The plate's screw holes, header window and port notch all lined up.
| Viewed from the back, from the display's top-left corner | mm |
|---|---|
| Upper Pi holes | x 60.15 and 118.15, y 35.1 |
| Lower Pi holes | x 60.15 and 118.15, y 84.1 |
| Pi outline | x 36.65 to 121.65, y 31.6 to 87.6 |
| Orientation | rotated 180°: GPIO header at the bottom, USB/Ethernet toward the right of the screen as seen from the front |
The manufacturer's drawing then confirmed the Pi holes at 60.36 / 118.36 mm from the screen's left edge and 35.19 / 84.19 mm from its top (within 0.2 mm of the measurements), and set the final outline.
How the correction is applied: the board is referenced to the Pi, so the
Pi, every part, the notch and the cable slot stay where they are and only
the outer outline moves (OUTLINE_SHIFT in tools/place.py). All copper was
routed at least 3 mm from the outer edges for exactly this; with the final
outline the edge margin is 2.5 mm.
Board shape. The Pi is mid-screen, so its USB/Ethernet block (13.5 mm tall Ethernet jack, board sits 11 mm above the Pi) is ~30 mm in from the display's edge. The board has a notch from the port block to the left edge (back view): the jacks clear it and cables can reach them. A slot next to the Pi's DSI connector clears the display ribbon (HAT spec position).
Stack-up (from the screen's glass, toward the firewall):
| Layer | z (mm) | Source |
|---|---|---|
| Display module | 0 to 8.25 | Hosyond drawing |
| Its rear parts and pillars (corner and Pi) | 8.25 to 12.25 | Hosyond drawing (12.25 total); check with calipers |
| Pi 4 board | 12.25 to 13.85 | Pi spec |
| Header base + socket | 13.85 to 26.85 | 2.5 + 8.5 mm, HAT standard (11 mm M2.5 standoffs), plus a 1 mm nylon spacer on the Pi (the stack was loose without it) and a 1 mm nylon washer under the carrier ("Pi standoffs" below); the header pins go 4 mm into the socket instead of 6 |
| Carrier board | 26.85 to 28.45 | 1.6 mm |
| Tallest parts on it | to ~41 | 470 µF cap 12.5 mm, harness plug + mated housing |
| Amp heatsink | to 41.0 | 20 x 20 x 10 mm stock heatsink on the 2.33 mm chip + tape |
| Fans (in the housing lid) | 44 to 54 | Noctua NF-A4x10, 3 mm above the heatsink |
| Housing lid | 54 to 56.4 | tools/housing.py |
Board stack 165 x 103 x ~41 mm; in its housing 176.7 x 106.2 x 56.4 mm,
sized to slide through the Metra 95-8210 dash kit's double DIN opening. The heatsink, the 470 µF cap and the
harness plug all end at about the same height. (The CNC heatsink in mech/
is cut to the same 10 mm height, so it fits without moving the lid.)
Fit test before ordering: tools/fit_plate.py writes
mech/fit_plate.stl, a 1.6 mm plate with the board's exact outline, notch,
cable slot, Pi and heatsink holes and a window for the Pi header. Print it
text side up, mount it on the Pi with the 11 mm standoffs, and check the
edges against the screen and the holes against the standoffs.
Housing. tools/housing.py builds a two-part PETG housing from the same
numbers as the board (place.py, part positions read from
carrier.kicad_pcb) and checks it against the board, Pi, heatsink and screen
where they sit, and along the way in: the screen from the front, the Pi and
the board straight in from the open back, and a screwdriver down onto each
pillar screw. It also checks the shell and lid against the Metra 95-8210 trim
panel's opening (about 177.8 x 108.0 mm, ruler-measured; KIT_OPENING) with
0.5 mm to spare on each side (exit 1 on any clash, blocked path or misfit):
- Shell (
mech/housing_shell.stl): walls 0.5 mm outside the screen outline, with a skirt down flush with the glass front: 2.4 mm at the sides, 1.6 mm top and bottom (the screen is 102.0 mm tall against the kit's ~108 mm opening). The right wall (driver side, seen from the back) is 6.0 mm thicker, taking the kit opening's spare width. Corner tabs sit on the screen's four pillars (2.9 mm holes, M2.5 x 6 screws). A ledge under the board's top edge either side of J1 (x 90 to 145, stopping 1 mm short of J1's pins) takes the push when the harness goes in: open item 5. Vent slots below the board (Pi level) and above it, an opening in the left wall for the USB cables (CarPlay dongle), and a hole in the right wall for the mic plug (12 mm counterbore through the thick wall). Four M3 heat-set inserts hold the lid, all outside the board's path in (it has only 0.5 mm to the walls): two go straight down into the top of the thick right wall (y 20 and 82), two sit in 7 x 7 x 8 mm blocks on the left wall inside the Pi's port notch (y 35 and 84), where the board has no edge. All four are kept off the corners so a screwdriver reaches the pillar screws. The kit's own side brackets hold the housing in the dash: three more M3 heat-set inserts, pressed in from outside at the old bracket pads' positions (y 25 and 77, 34 mm from the glass). Two go into the thick right wall; on the left only the lower one, in a block inside the port notch (the upper one would sit in the board's way in). The mic plug's hole may sit behind the kit's right bracket: cut the bracket if so. - Lid (
mech/housing_lid.stl): both fans hang under it, blowing in. Fan 1 sits over the amp heatsink (the airflow the stock heatsink needs); fan 2 sits over the Pi's port notch, so its air goes down past the jacks, under the board across the Pi, and out of the low vents. Grilles over both, an opening the harness plug passes through (and its latch can be pressed through), and two ribs either side of J1 that stop 0.2 mm above the board so pulling the plug can't lift it. A lip locates it inside the shell. - Fit ring (
mech/housing_fit_ring.stl): the bottom 17 mm of the shell, about a fifth of the plastic. Print it first and check the skirt fit and the four pillar screws.
Exhaust (slots + USB opening) is 2.0x the open area of the two fan grilles.
Print in PETG, 0.16 mm layers, 6 walls (every wall comes out solid), 30% gyroid, textured PEI: the shell on its front rim (screen side down, 5 mm outer brim), the lid on its outer face. The lid needs no supports. The shell needs them only under the four corner tabs: each is a 10 mm corner overhang held by two walls, and its underside is the face that sits on the pillar. Paint support enforcers on those four undersides (tree); auto supports miss some of them. With an AMS, use PLA for the support interface and accept Bambu Studio's suggested settings (0 mm top Z distance, interlaced rectilinear): PLA does not bond to PETG, so the tab undersides come out flat. PETG-only supports need 0.2 mm top Z distance instead. The STEP files are in the assembly frame, for importing into other CAD.
Onshape: the same parts are rebuilt feature by feature in the private
document "CarPlay Head Unit Housing"
(https://cad.onshape.com/documents/92519b2e7fb9667b3fe711ef), with a fan
part, a reference part studio (screen, pillars, Pi, HAT standoffs, board with
its notch and slot, heatsink, J1) and a "Head unit assembly" fastening it all
together. It is behind housing.py now: no thick right wall, no mic
counterbore, and the old lid screw blocks. Those features sit at fixed
coordinates and are not linked to each other, so housing.py stays the master:
change sizes there, check them with its clearance check, then redo the
affected features in Onshape.
Hardware: 4x M2.5 x 6 (shell to pillars), 4x M3 x 5.7 heat-set inserts + 4x M3 x 8 countersunk (lid), 3x M3 x 5.7 heat-set inserts + M3 screws (kit brackets), the screws in the Noctua box through the lid into the fans (or M3 x 16 + nuts).
Assembly: press the four lid inserts in from the back (about 240 °C for PETG), screw the shell to the screen, fit the Pi, then drop the board straight in from the back onto its standoffs (its top edge rests on the ledge), plug the fans into the board, and close the lid. Gap check on the bench: the board should sit on the ledge with no rocking and the ribs just touching it.
PETG starts to soften around 75 to 80 °C. If it sags in a summer dash, reprint the same files in ASA.
3D model: tools/assembly.py builds display + Pi 4 + board + stock
heatsink + housing + fans (mech/assembly.step, mech/assembly.stl;
generated, not committed). Review images: out/3d/*.png via
tools/render3d.py; housing_cut_j1.png and housing_cut_fan1.png are
sections through the J1 clamp and through fan 1 and the heatsink.
Wiring the truck
The truck has three plugs behind the radio: a 10-pin (power, front
speakers, illumination) and a 6-pin (rear speakers), both yellowish, plus
a white 20-pin that carries the steering-wheel wires. The Klintotour Toyota
adapter mates with all three; nothing on the truck gets cut. Cut the 16-pin
Android plug off the adapter's far end and crimp its wires into the
Micro-Fit plug (diagram: tools/harness_diagram.py, writes
out/harness.png).
The adapter's 16-pin end uses the usual Android colour code: the EIA power and speaker colours, brown and brown/white for the wheel, and a loose pink lead tagged BACK for reverse. Wire positions inside that 16-pin shell vary between makers, so go by colour. On the Toyota side the wheel is 20-pin #7 (SW1: seek, volume), #8 (SW2: mode, phone, voice) and #6 (its ground, which the adapter joins to black). Only non-JBL trucks: the adapter does not work with the JBL amplifier.
To build the plug: solder each wire to a pre-crimped Micro-Fit lead, heat-shrink it, and push the pin into its numbered hole until it clicks. Pin n sits directly above pin n+10. Use both +12 V pins and at least two grounds: loud music peaks at 10 to 12 A, more than one Micro-Fit contact is rated for. The speaker order (FR, FL, RR, RL) is not a typo: it matches the amp's output order on the board, so the four speaker tracks run straight to the plug without crossing.
| Pin | Signal | Adapter wire |
|---|---|---|
| 1, 11 | +12 V constant | Yellow |
| 2, 12, 19 | Ground | Black |
| 7 | Key / accessory | Red |
| 17 | Headlights on (illumination) | Orange |
| 10 | Reverse (+12 V in reverse) | Pink, tagged BACK; splice to the reverse-light feed |
| 8 | Steering wheel 1 (seek, volume) | Brown (KEY1) |
| 18 | Steering wheel 2 (mode) | Brown/white (KEY2) |
| 9 | Steering wheel ground | Leave empty (the adapter grounds the wheel through black) |
| 3 / 13 | Front right + / − | Gray / gray-black |
| 4 / 14 | Front left + / − | White / white-black |
| 5 / 15 | Rear right + / − | Purple / purple-black |
| 6 / 16 | Rear left + / − | Green / green-black |
| 20 | Not used |
Blue (antenna / amp turn-on) and anything else on the 16-pin are not used: cap them. Before the first plug-in, check with a meter that +12 V (1, 11) has no continuity to ground (2, 12, 19), and confirm KEY1 / KEY2: adapter in the truck, key off, ohms from brown and from brown/white to black; the reading changes as the wheel buttons are pressed. Earlier measurements on the purple SWC wire: seek+ ~0 Ω, seek− 331 Ω, vol+ 100 Ω, vol− "3.111" (unit unclear). Learn mode makes the exact values irrelevant.
Pi GPIO map
| Header pin | BCM | Net | Use |
|---|---|---|---|
| 2, 4 | 5V | +5V | Board powers the Pi (and the screen through its pogo pins) |
| 1, 17 | 3V3 | (unused) | The board makes its own 3.3 V |
| 3, 5 | GPIO2/3 | I2C_SDA/SCL | Amp 0x6A, ADC 0x48, RTC 0x68 (Pi has 1.8k pull-ups) |
| 27, 28 | ID_SD/SC | ID_SDA/SCL | HAT EEPROM 0x50 (3.9k pull-ups on the board) |
| 12 | GPIO18 | I2S_BCLK | Bit clock, input (board is master) |
| 35 | GPIO19 | I2S_FSYNC | Frame clock, input |
| 40 | GPIO21 | I2S_DOUT | Audio data to the amp |
| 32, 33 | GPIO12/13 | FAN1/2_PWM | Hardware PWM, 25 kHz, inverted |
| 36, 7 | GPIO16/4 | FAN1/2_TACH | Tach, 2 pulses/rev |
| 11 | GPIO17 | ~ACC_ON | Key on (active low) |
| 13 | GPIO27 | ~LIGHTS_ON | Headlights (active low, may be PWM-dimmed) |
| 38 | GPIO20 | I2S_DIN | Mic audio from the PCM1808, input |
| 26 | GPIO7 | ~REVERSE | Reverse gear (active low) |
| 37 | GPIO26 | PI_HOLD | Keeps the board powered while high |
| 15, 16 | GPIO22/23 | ~AMP_STBY/~AMP_MUTE | Amp control |
| 18, 22 | GPIO24/25 | ~AMP_FAULT/~AMP_WARN | Amp status (open drain) |
| 31 | GPIO6 | ~ADC_ALERT | ADC ready (unused by software for now) |
| 29 | GPIO5 | ~RTC_INT | RTC alarm |
| 8, 10 | GPIO14/15 | UART_TX/RX | Debug header (not fitted) |
Shopping list (besides the board)
From DigiKey (genuine Molex; Amazon does not carry the 20-way housing):
| Qty | Part | Link |
|---|---|---|
| 2 | Micro-Fit 3.0 2x10 plug housing, Molex 43025-2000 | DigiKey |
| 25 | Micro-Fit pre-crimped lead, socket + 300 mm 18 AWG, Molex 2147611124 | DigiKey |
| opt. | Micro-Fit extraction tool, Molex 11-03-0043 (the Amazon "11-03-0044" tools are Mini-Fit Jr, wrong size) | DigiKey |
From Amazon:
| Qty | Part | Link |
|---|---|---|
| 1 | Klintotour Toyota adapter (for the white steering-wheel plug) | B0FBRNCNPD |
| 1 | CR2032 | B07G7KRQQ5 |
| 1 | M2.5 standoffs, 11 mm body + 6 mm thread | B07KM27KC6 |
| 2 | Noctua NF-A4x10 5V PWM (each includes an extension cable) | B07DXS86G7 |
| 1 | Posi-Tap 18-24 AWG | B01HSBYX3I |
| 1 | 18 AWG wire (reverse run), stranded pure copper (not CCA: copper-clad aluminium); splice solid core to a stranded tail before any pin or Posi-Tap | B07D74RGVM |
| 1 | Heat-shrink assortment | B01MFA3OFA |
| 1 | 20 x 20 x 10 mm aluminium heatsinks with thermal tape (one goes on the amp) | |
| 1 pack | M2.5 nylon washers (see "Pi standoffs" below) | |
| 1 | Car microphone, 3.5 mm plug, plain 2-wire electret (head-unit type, not USB or a TRRS headset) | |
| opt. | 4-pin PWM fan extensions | B0CNLDNZB2 |
Amp heatsink (rev A). The CNC heatsink in mech/ (copied from TI's EVM)
was dropped on cost. Rev A uses one stock 20 x 20 x 10 mm heatsink centred on
U7. Parts in that area are at most 1.8 mm tall against the 2.33 mm chip, so it
sits flat. Anything up to 41 x 20 mm fits (long side along the chip); past
20 mm the other way it hits the speaker inductors. Three conditions:
- A fan must blow across it. In still air with tape, loud music would reach the amp's 160 °C shutdown; with airflow it stays around 100-120 °C, and the software cuts 6 dB on the amp's warning.
- Hold it mechanically. Tape alone can let go in a hot dash and leave a loose aluminium block on the board. Use thermal epoxy instead, or a metal strap across the fins on long M3 screws through H5/H6 (they sit just outside a 20 mm heatsink).
- Ground it. TI requires the heatsink on GND and the tape insulates. A short wire from a fin to H5 or H6 (GND pads; screw + ring terminal), or the metal strap, does it.
Pi standoffs. Signal tracks pass under the metal at two Pi holes: at H1, I2S_FSYNC (top) and ~AMP_MUTE / I2C_SDA (bottom); at H4, +3V3 (top). The Pi's holes are grounded, so a standoff or screw head that wears through the mask would short them. Put a nylon washer on both faces of the board at all four holes (1 mm, the same on every hole so the board sits level; the housing assumes 1 mm under the board). Fix in rev B: keep copper 3 mm from the Pi hole centres.
Order options: 4 layers, 1 oz inner copper (the default is 0.5 oz; the
+12V_PROT and +5V planes on In2 carry up to ~12 A peak at full volume); ENIG
suits the 0.5 mm WSON/VQFN parts better than HASL. J2 is on the underside, so
the assembler may ask to confirm assembly on both sides. In
JLC's placement preview, check the parts whose footprints JLC draws
differently from KiCad (tools/jlc_cpl.py already corrects the placement
file for them): BT1 with its + contact on the square pad, J1's latch and the fan headers'
ramps on the side the silkscreen shows, pin-1 dots on Q1-Q7 and U2-U7, and
Q1/Q2 and L1 sitting centred on their pads (JLC's LFPAK56 pads differ from
ours; JLC has no footprint for L1 to check against).
Files
| Path | What |
|---|---|
carrier.kicad_sch / .kicad_pcb / .kicad_pro | KiCad 10 project (generated, see below) |
lib/carrier.kicad_sym, lib/carrier.pretty/ | Custom symbols and footprints |
lib/ref/ | EasyEDA/JLC reference symbols and footprints used to check pinouts |
datasheets/ | Every datasheet used, plus the HAT mechanical drawing and TI's EVM guide |
mech/heatsink.step, .stl | CNC heatsink (not used on rev A; stock heatsink instead) |
mech/housing_*.stl, .step | Printed housing: shell, lid, fit ring |
tools/ | Generators and checks (below) |
out/ | Renders, PDF, BOM, reports (generated, not committed) |
Regenerating everything
The schematic and board are produced by scripts, not edited by hand, so
every value and position is reviewable in one place. KiCad runs as a
Flatpak; kicad-cli is a wrapper in ~/.local/bin. The Python virtualenv
.venv holds easyeda2kicad, cadquery and matplotlib.
cd hardware/carrier
python3 tools/make_symbols.py # lib/carrier.kicad_sym
python3 tools/gen_sch.py # carrier.kicad_sch (part numbers included)
python3 tools/render.py # out/sch/full.png, plus crops: render.py name x1 y1 x2 y2
kicad-cli sch erc -o out/erc.rpt carrier.kicad_sch
kicad-cli sch export pdf -o out/carrier.pdf carrier.kicad_sch
kicad-cli sch export bom --fields 'Value,Reference,Footprint,LCSC,MPN,Manufacturer,${QUANTITY},${DNP}' \
--labels 'Comment,Designator,Footprint,LCSC,MPN,Manufacturer,Qty,DNP' \
--group-by 'Value,Footprint,LCSC,${DNP}' --exclude-dnp -o out/bom_jlcpcb.csv carrier.kicad_sch
tools/build_board.sh # placement, planes, hand routes, Freerouting, finish, DRC (~20 min)
tools/build_board.sh noauto # stop before the autorouter
flatpak run --command=python3 org.kicad.KiCad tools/dump_pcb.py # then:
.venv/bin/python tools/view_pcb.py NAME [x0 y0 x1 y1] [--nets TEXT] [--labels] # out/pcb/NAME.png
.venv/bin/python tools/fit_plate.py # mech/fit_plate.stl
.venv/bin/python tools/heatsink.py # mech/heatsink.step/.stl
kicad-cli pcb export step --subst-models --force -o mech/carrier_board.step carrier.kicad_pcb
.venv/bin/python tools/housing.py # mech/housing_*.stl/.step + clearance check
.venv/bin/python tools/assembly.py # mech/assembly.step/.stl
.venv/bin/python tools/render3d.py # out/3d/*.png
tools/jlc_export.sh # fab/: Gerbers + drill zip, BOM, CPL
flatpak run --command=python3 org.kicad.KiCad tools/check_cpl.py --dump # then:
.venv/bin/python tools/check_cpl.py # CPL vs JLC's footprints, exit 1 on a mismatch
.venv/bin/python tools/sim.py # SPICE testbenches, out/sim/*.png, exit 1 on a failed checkWhat each script owns:
make_symbols.py: custom symbols (TAS6424, LM61460, LM74800, DS3231, PCM1808, harness, Pi header). Pin numbers and names were checked against datasheets / EasyEDA each time a symbol was rearranged.gen_sch.py+schlib.py: the schematic. Each section is a function placed at an anchor;PARTSmaps (value, footprint) to MPN / manufacturer / LCSC. Part UUIDs are derived from references, so reruns are byte-identical and the board stays linked to the schematic.gen_pcb.py+place.py: board outline, 4-layer stackup, JLC design rules, net classes and placement.place.pyholds the Pi position, the notch/slot geometry and every block's layout, with parts found by Section field and nets.route.py: everything that carries current or needs care, locked so the autorouter works around it. In1 is solid GND; In2 is split into +12V_PROT (protection, amp, buck input) and +5V (buck output, Pi, LDO, clocks, fans). Top-layer pours for the battery path, VMID, buck VIN/PGND/SW and output, amp PVDD and the Pi's 5 V pins. Hand-routed amp outputs (P legs on top, M legs dropped to the bottom under the coils) and speaker lanes (1 mm, nested so none cross). Every GND pad gets its own via to In1, and +5V/+12V pads over their In2 region likewise. The LM74800's 0.5 mm pins and a few tight nets are routed bymaze.py(a small grid router). Nothing copper within 3 mm of the outer edge.autoroute.pyexports to Freerouting (with keepouts guarding the pours) and imports the result;finish.pymaze-routes anything left open.jlc_export.sh+jlc_cpl.py: order files.jlc_cpl.pymoves each part to JLC's footprint origin and adds the rotation JLC's footprint needs (JLC_ROT,JLC_ORIGIN);check_cpl.pyre-derives both from JLC's footprints and checksfab/carrier_cpl.csv.sim.py+ngspice_run.py: SPICE testbenches for the analog blocks, run in KiCad's bundled ngspice. Values are copied fromgen_sch.py(constants at the top ofsim.py); change both together.heatsink.py,housing.py,assembly.py,render3d.py: mechanical.HEATSINK=stock|double|cncpicks the amp heatsink the assembly and the housing check use.heatsink_thermal.py: rough junction temperatures for each heatsink option, swept over the unmeasured fan airflow.assembly.pyowns the stack heights;housing.pytakes them from it. Re-exportmech/carrier_board.stepafter any board change, beforehousing.py(its clearance check uses it).
Verification so far
- ERC: 0 errors, 0 warnings.
- Netlist check: every Pi GPIO lands on its intended net; amp pins, speaker filters and clock nets checked net by net.
- Board: 0 schematic-parity issues; no courtyard overlaps or clearance errors; parts clear of the Pi socket's solder pins by 3 mm; only parts under 2.2 mm under the heatsink.
- BOM: 148 fitted parts, all LCSC numbers present and in stock when chosen (2026-09-22/24).
- Pi socket orientation: pin 1 over the Pi's pin 1, checked by pad position (a mirrored socket would put 5 V on the wrong pins).
- Software: 18 tests on simulated hardware, including the GPIO request
struct compared byte for byte with
<linux/gpio.h>. - SPICE (
tools/sim.py, 37 checks over tolerance corners): power hold, key/lights/reverse inputs, soft start, OV cutoff, buck UVLO and setpoint, speaker filters, steering-wheel and battery ADC, mic bias, fan PWM. - Pinouts of every IC and the land patterns of the LM74800 and LM61460 checked against their datasheets; TAS6424 wiring against TI's fig 10-2.
- Placement file: every part's rotation and centre checked against JLC's
own footprint (
tools/check_cpl.py): 0 mismatches.
Open items
Fit check: done 2026-09-24, the corrected outline (mech/fit_frame.stl) fits the screen, screw holes, header and port notch exactly.- Display thickness and pillar height now come from Hosyond's drawing (8.25 + 4.0 mm). The housing's corner tabs, J1 ledge and lid ribs depend on them: check glass-to-pillar-top (12.25 mm) with calipers, and print the fit ring before the full housing.
Tidy silkscreen; add the harness pin table next to J1: done.Final review: done 2026-10-07 (VERIFICATION.md, third pass). Order the board + assembly; stock heatsink instead of CNC.Enclosure: support the board under J1: done 2026-10-12, the housing's ledge under J1 and the lid ribs above it (tools/housing.py). Not printed yet.- On first power-up: confirm the react-carplay window class used for steering-wheel keys, run learn mode, check amp start-up and fault handling on real hardware, and check the mic capture path (the overlay puts two dummy codecs on one I2S link; set mic gain in software).
Parts
171| Qty | Value | Footprint | References |
|---|---|---|---|
| 18 | 100nF | Capacitor_SMD:C_0603_1608Metric | C6, C7, C10, C11, C13, C14, C15, C18, C19, C22, C26, C29, C31, C33, C67, C69 +2 |
| 17 | 1uF | Capacitor_SMD:C_0603_1608Metric | C20, C21, C27, C28, C37, C38, C39, C40, C43, C44, C45, C46, C47, C48, C49, C50 +1 |
| 14 | 10k | Resistor_SMD:R_0603_1608Metric | R6, R8, R10, R11, R15, R19, R20, R22, R23, R25, R26, R34, R36, R44 |
| 9 | 1nF | Capacitor_SMD:C_0603_1608Metric | C52, C54, C56, C58, C60, C62, C64, C66, C75 |
| 9 | 1uF | Capacitor_SMD:C_0805_2012Metric | C35, C51, C53, C55, C57, C59, C61, C63, C65 |
| 8 | 1k | Resistor_SMD:R_0603_1608Metric | R5, R7, R12, R16, R33, R43, R45, R46 |
| 8 | 3.3uH | Inductor_SMD:L_Chilisin_BMRx00060630 | L2, L3, L4, L5, L6, L7, L8, L9 |
| 5 | 100k | Resistor_SMD:R_0603_1608Metric | R17, R27, R31, R35, R37 |
| 5 | 10uF | Capacitor_SMD:C_1206_3216Metric | C16, C17, C30, C32, C34 |
| 4 | 10uF | Capacitor_SMD:C_0805_2012Metric | C68, C70, C72, C73 |
| 4 | 33R | Resistor_SMD:R_0603_1608Metric | R38, R39, R40, R41 |
| 4 | Pi | MountingHole:MountingHole_2.7mm_M2.5 | H1, H2, H3, H4 |
| 3 | 100nF | Capacitor_SMD:C_0805_2012Metric | C1, C2, C4 |
| 3 | 47k | Resistor_SMD:R_0603_1608Metric | R18, R21, R24 |
| 3 | 47uF | Capacitor_SMD:C_1210_3225Metric | C12, C24, C25 |
| 3 | H15VND3B | Diode_SMD:D_SOD-323 | D2, D3, D7 |
| 3 | MMBT3904 | Package_TO_SOT_SMD:SOT-23 | Q3, Q4, Q5 |
| 3 | RED | LED_SMD:LED_0603_1608Metric | D8, D9, D10 |
| 2 | 0R | Resistor_SMD:R_0603_1608Metric | R9, R30 |
| 2 | 1N4148W | Diode_SMD:D_SOD-123 | D4, D5 |
| 2 | 2.2uF | Capacitor_SMD:C_0805_2012Metric | C41, C42 |
| 2 | 2N7002 | Package_TO_SOT_SMD:SOT-23 | Q6, Q7 |
| 2 | 3.9k | Resistor_SMD:R_0603_1608Metric | R13, R14 |
| 2 | BUK7Y4R8-60E | Package_TO_SOT_SMD:LFPAK56 | Q1, Q2 |
| 2 | Heatsink | MountingHole:MountingHole_3.2mm_M3_Pad_Via | H5, H6 |
| 1 | 100R | Resistor_SMD:R_0603_1608Metric | R1 |
| 1 | 10nF | Capacitor_SMD:C_0603_1608Metric | C8 |
| 1 | 12.288MHz | Oscillator:Oscillator_SMD_Abracon_ASE-4Pin_3.2x2.5mm | X1 |
| 1 | 2.2k | Resistor_SMD:R_0603_1608Metric | R42 |
| 1 | 220nF | Capacitor_SMD:C_0603_1608Metric | C5 |
| 1 | 22nF | Capacitor_SMD:C_0805_2012Metric | C3 |
| 1 | 22pF | Capacitor_SMD:C_0603_1608Metric | C23 |
| 1 | 24.9k | Resistor_SMD:R_0603_1608Metric | R32 |
| 1 | 26.7k | Resistor_SMD:R_0603_1608Metric | R28 |
| 1 | 3.74k | Resistor_SMD:R_0603_1608Metric | R4 |
| 1 | 33.2k | Resistor_SMD:R_0603_1608Metric | R29 |
| 1 | 4.7uH | Inductor_SMD:L_APV_APH0840 | L1 |
| 1 | 470uF | Capacitor_SMD:CP_Elec_10x12.5 | C36 |
| 1 | 5.11k | Resistor_SMD:R_0603_1608Metric | R3 |
| 1 | 95.3k | Resistor_SMD:R_0603_1608Metric | R2 |
| 1 | ADS1115IDGS | Package_SO:TSSOP-10_3x3mm_P0.5mm | U2 |
| 1 | BZT52C15 | Diode_SMD:D_SOD-123 | D6 |
| 1 | CAT24C32 | Package_SO:SOIC-8_3.9x4.9mm_P1.27mm | U4 |
| 1 | CR2032 | Battery:BatteryHolder_MYOUNG_BS-07-A1BJ001_CR2032 | BT1 |
| 1 | DS3231SN | Package_SO:SOIC-16W_7.5x10.3mm_P1.27mm | U3 |
| 1 | EEPROM_WP | Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm | JP1 |
| 1 | FAN1 | Connector:FanPinHeader_1x04_P2.54mm_Vertical | M1 |
| 1 | FAN2 | Connector:FanPinHeader_1x04_P2.54mm_Vertical | M2 |
| 1 | Harness_4Runner | Connector_Molex:Molex_Micro-Fit_3.0_43045-2012_2x10_P3.00mm_Vertical | J1 |
| 1 | LM61460-Q1 | carrier:TI_RJR0014A_VQFN-HR-14_3.5x4mm | U5 |
| 1 | LM74800-Q1 | Package_SON:WSON-12-1EP_3x3mm_P0.5mm_EP1.5x2.5mm | U1 |
| 1 | MIC | Connector_Audio:Jack_3.5mm_PJ320D_Horizontal | J4 |
| 1 | PCM1808-Q1 | Package_SO:TSSOP-14_4.4x5mm_P0.65mm | U8 |
| 1 | Pi 4 GPIO | Connector_PinSocket_2.54mm:PinSocket_2x20_P2.54mm_Vertical | J2 |
| 1 | SMBJ33CA | Diode_SMD:D_SMB | D1 |
| 1 | TAS6424E-Q1 | Package_SO:SSOP-56_7.5x18.5mm_P0.635mm | U7 |
| 1 | TLV75533PDBV | Package_TO_SOT_SMD:SOT-23-5 | U6 |
| 1 | UART | Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical | J3 |
| 1 | WP | TestPoint:TestPoint_Pad_D1.5mm | TP1 |
Questions
How big is the Carrier PCB?
It measures 164.9 × 102 mm and has 4 copper layers, 1.6 mm thick.
What parts does the Carrier use?
171 parts, built around the ADS1115IDGSR, LM61460AFSQRJRRQ1, PCM1808QPWRQ1 and TAS6424EQDKQRQ1. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
Where can I download the Carrier KiCad files?
From the AJXD2/carplay-project repository on GitHub, at the commit this page was made from: the board is hardware/carrier/carrier.kicad_pcb and its schematic hardware/carrier/carrier.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Can I use the Carrier design in my own project?
Its repository states no licence, so its author keeps all rights: ask AJXD2 before reusing the design.
Similar boards
- 4 layers170 × 101 mm

- 4 layers65 × 56 mm

- 2 layers145 × 60.3 mm

Mkulima hardware
Kazenzi/The-robotic-farmer
Click the Youtube Thumbnail below for a youtube demo video:
147 parts1MIT - 4 layers52.9 × 79.6 mm

PCB Pere V1
CaptainDJMax/2627_Projet3AMSC_Index_Stellaire
Ceci est notre projet sur l'index stellaire
93 partsMIT - 2 layers170 × 120 mm

Motor pid
gallicchio/motor-pid
The motor-position feedback loop of Learning the Art of Electronics (Hayes & Horowitz), Lab 10L, as a 170 x 120 mm printed circuit board whose silkscreen is the schematic.
110 parts - 4 layers191.5 × 121.8 mm

Foxhunt1
gx1400/kicad_foxhunt_batterytest
Custom amateur radio fox hunt (hidden transmitter) controller, aimed at being a flexible, dynamic platform for a wide range of fox-hunt formats — not just a fixed single-mode beacon.
260 parts - 4 layers41.2 × 49.9 mm

- 4 layers150 × 40 mm

Linklite v2
WeasalCrafter/linklite-v2
Programming and KiCad files for LinkLite v2: a modular lighting system with wireless control and syncing.
116 partsMIT