Android Auto and CarPlay Cluster Integration for Porsche mh2p / PCM5 and mhi2 / PCM4

Bridge Android Auto and CarPlay navigation from Porsche PCM5 / VW / Audi MH2P and MHI2 / PCM4 to the instrument cluster display. CarPlay cluster rendering now live.

Android Auto
CarPlay1
CarPlay2
CarPlay3

Overview

Turns the digital instrument cluster on Porsche PCM5 / VW / Audi MH2P into a proper second navigation display driven by your phone — both Android Auto and CarPlay. Live map view, turn-by-turn arrows on the physical dial, seamless handoff back to native Porsche navigation when the phone disconnects.

✅ Status: Stable release — CarPlay cluster rendering now live alongside Android Auto.

What it does

Features

🚗

CarPlay Cluster Nav

Apple Maps, Google Maps, Waze — iPhone navigation renders on the digital cluster in real time. Turn arrows on the physical dial too.

📱

Android Auto Cluster Nav

Live Android Auto navigation view on the cluster — Google Maps, Waze, and every other AA-compatible nav app.

🗺️

Full Turn-by-Turn

Turn arrows, distance, road names, roundabouts, highway exits, lane guidance — everything from your phone rendered on the cluster arrow display.

🔄

Native Maps Handoff

When the phone disconnects, the built-in Porsche navigation reclaims the cluster automatically. No reboot, no menu-diving.

🖥️

HMI-Independent

You can leave the centre display on native infotainment and the cluster keeps showing phone nav underneath. HMI-off / HMI-on transitions no longer kill the mirror.

🌍

Auto Unit Detection

Automatic km/mi and LHD/RHD detection via platform services with JSON country fallback. Supports 60+ countries.

🔧

JSON Configuration

Runtime-configurable logging, heartbeat, units, and more via JSON. Override via USB/SD without reinstall.

📊

Comprehensive Logging

Detailed dual-timestamp logs with optional privacy hashing and external USB/SD output for support and debugging.

🚙

Multi-Car Config

Per-car overrides for Cayenne, 911, Panamera, Macan, Audi A7. Bargraph mode and cluster behaviour auto-detected per variant.

Supported vehicles

Model years 2019–2021. Firmware range 9xxx–28xx. Other firmwares can be enabled on request; the OEM/firmware gate is tunable in the installer.

ModelHead unitStatus
Cayenne (9Y0)PCM5 / MH2PSupported
MacanPCM5 / MH2PSupported
PanameraPCM5 / MH2PSupported
992.1 (911)PCM5 / MH2PSupported
718 (Cayman / Boxster)MHI2 / PCM4AA and CarPlay working (not released)

Support continued development

This software is developed and maintained in my spare time, and made available completely free of charge. If you find it useful, please consider supporting further development and testing.

Support this project on Ko-fi ↓ Download latest release
Donations are optional. The software is free.

Stable — CarPlay cluster rendering + AA reliability rewrite LATEST

CarPlay nav in the cluster is live for the first time. Android Auto black-screen-on-connect race fixed. Session stability across park/drive cycles. HMI-independent operation. Native maps handoff on disconnect. Turn-by-turn fixes across both platforms.

718 (MHI2/PCM4) port IN PROGRESS

Android Auto working. CarPlay next.

Installation

Based on MH2p Mod Kit

⚠️ Warning: This modifies files on your PCM5 / MH2P unit. Only proceed if you understand the risks. Uninstall is reversible.

Prerequisites

Steps

  1. Download the latest release
  2. Format the SD card as FAT32
  3. Extract the ZIP to the root of the SD card.

    The SD card should look like this:

    SD card directory structure
    Using a Mac? Additional steps are required: Video guide · macOS text guide
  4. Start the vehicle
  5. Insert the SD card
  6. Within a few seconds, the head unit will reboot
  7. The update installs automatically
  8. When done, a prompt says "Please remove update media"
  9. Remove the SD card from the vehicle
  10. Head unit reboots into normal mode with the mod installed

Uninstall

Architecture

ClusterIntegration bridges the Android Auto DSI event stream and the CarPlay RGI event stream to the Porsche instrument cluster BAP navigation protocol, plus a second video stream from the phone that is decoded on the head unit and composited to the cluster's dedicated video surface.

Data Flow

Phone (Android Auto or CarPlay)
        ↓
    Nav events (DSI / RGI)      +    H.264 video stream
        ↓                                    ↓
ClusterIntegration               Cluster daemon
    ├─ event → BAP maneuver          ├─ NvMedia H.264 decode
    ├─ heartbeat (every 2s)          ├─ YV12 → RGBA
    └─ CombiBAPServiceNavi           └─ Cluster video window
        ↓                                    ↓
Instrument Cluster (arrow dial + video display)

Service Injection

All platform services are injected via setters after construction:

ServicePurpose
CombiBAPServiceNaviBAP cluster output — maneuver, distance, RGStatus, destination
ISysServicesUnit system detection, car clock, car type/variant detection
ICarCoreServicesDrive-side detection via exteriorLight().leftHandTraffic()
StorageMountHandlerRemounts USB/SD R/W for external log writing
ICarStatisticsServiceInjected but not currently used in active code

AA / CarPlay Event → BAP Maneuver Translation

Maps eventCode (1–19) + turnSide + angle + num to a BAP maneuver descriptor.
Direction is a 0–255 byte (0=straight, 64=left/90°, 128=back/180°, 192=right/270°).

Event(s)Translation
event=3–5 (turns)TURN, direction from angle or fallback to turnSide
event=6 (U-turn)UTURN
event=7 (on-ramp)TURN_ON_MAINROAD, direction from turnSide
event=8/10 (off-ramp/merge)EXIT_LEFT or EXIT_RIGHT based on turnSide; side=0 → FOLLOW_STREET
event=9 (fork)FORK_2
event=14 (STRAIGHT/KEEP)num==1 = Waze lane-keep → FOLLOW_STREET; num==0 or num>1 = motorway exit → EXIT_LEFT/RIGHT
event=11–13 (roundabout)ROUNDABOUT_TRS_LEFT/RIGHT.
RHD angle correction: (540−angle)%360;
LHD: (angle+180)%360.
T-junction override: 180° → 0° when exit ≤ 2
event=16/17 (ferry)FERRY
event=19 (destination preview)Sets flag, falls through as FOLLOW_STREET. DESTINATION symbol shown only on event=0 valid=2

Distance Update Pipeline

  1. Throttle check — minimum ms between sends per proximity zone (veryFar=2000ms down to now=100ms).
  2. Maneuver change detection — key = road|eventCode|turnSide. New maneuver resets baseline distance and bypasses throttle for first update.
  3. Distance threshold — minimum change required per zone (100m at veryFar down to 5m at now).
  4. Unit conversion — metric: m below 100m, tenths of km to 19.9km. Imperial: yards below 161m, tenths of miles to 9.9mi.
  5. Bargraph — (1 − distance/maneuverInitialDistance) × 100, clamped 0–100.
  6. Roundabout traversal — force distance/bargraph to 0 during CONTINUE events to suppress erratic display inside roundabouts.

Heartbeat

A daemon timer fires every heartbeatInterval ms (default 2000ms) while navigation is active. It resends the last cached maneuver, distance, bargraph, and destination data to continuously override the cluster's native navigation display.

Bargraph Auto Mode — Car Variant Detection

When bargraphMode="auto", the car type is queried at runtime via sysServices.config().carType():

CarcarClassgenerationResolved mode
Cayenne E353"always"
911 99268"always"
Panamera G262"always"
Macan41"distance"
Unknownanyany"always" (safe default)

Explicit JSON values always override auto-detection.

Logging

Two parallel log files: plain (full road names) and hashed (road names, music metadata replaced with [HASH_nnn] for privacy).
Each entry has a dual timestamp: QNX boot time + real car clock.
When enableExternalLogging=true, logs are written to USB/SD if writable, with automatic fallback to /tmp.

Configuration

The config file cluster_config.json is installed on the head unit. To override without reinstalling, place a file on a USB stick or SD card — the app checks these paths first:

/fs/usb0_0/cluster_config.json
/fs/usb1_0/cluster_config.json
/fs/sda0/cluster_config.json
/fs/sdb0/cluster_config.json

Logging

KeyTypeDefaultDescription
enableFileLoggingbooltrueMaster switch for all file logging.
enableFileHashingboolfalseWrite a second log with road names/music hashed for privacy.
enableExternalLoggingboolfalseWrite logs to USB/SD if present; falls back to logFilePath.
logFilePathstring/tmp/cluster.logPlain log file path.
hashedLogFilePathstring/tmp/cluster_hashed.logHashed log file path.
logFileSizeint (MB)50Max file size before rotation. Range: 1–100.

Features

KeyTypeDefaultDescription
enableRoundaboutLatchingbooltrueCache and hold roundabout exit direction across ENTER→CONTINUE→EXIT events to prevent arrow flickering.
enableHeartbeatbooltruePeriodically resend last maneuver+distance to prevent native nav from overwriting.
heartbeatIntervalint (ms)2000Heartbeat period. Range: 100–10000.
maneuverStateMaskint0Bitmask for updateManeuverState calls.
0 = disabled.
bit0=FOLLOW (>500m), bit1=PREPARE (200–500m), bit2=DISTANCE (50–200m), bit3=CALL_FOR_ACTION (<50m).
Example: 15 = all states.

Units and Display

KeyTypeDefaultDescription
forceImperialboolfalseAlways use miles/yards, ignoring car settings.
forceRHDboolfalseAlways treat vehicle as right-hand drive.
metricUnitThresholdint (m)100Below this, display switches from km to m. Range: 50–5000.
imperialUnitThresholdint (m)161Below this (~0.1 mi), display switches from miles to yards. Range: 50–5000.
destinationDisplayDurationint (ms)5000How long to hold arrival maneuver on screen before clearing. Range: 0–10000.

Bargraph

KeyTypeDefaultDescription
bargraphModestring"auto""auto" — detect car variant at runtime. "always" — send both text and bargraph. "distance" — text only. "dynamic" — bargraph only within dynamicBargraphDistance.
dynamicBargraphDistanceint (m)100In "dynamic" mode: distance below which bargraph replaces text. Range: 10–500.
dynamicBargraphPercentint (%)50In "dynamic" mode: for short maneuvers, switch point as % of initial distance. Range: 10–90.

Dynamic Thresholds

Controls how aggressively distance updates are sent per proximity zone. Each zone has a boundary (upper edge in metres), distance threshold (minimum change to trigger a send), and rateLimit (minimum ms between sends). now has no boundary — catch-all below veryClose.boundary.

ZoneDefault boundaryDefault distanceDefault rateLimit
veryFar5000 m100 m2000 ms
far1000 m50 m500 ms
approaching500 m25 m250 ms
near200 m15 m200 ms
close100 m15 m150 ms
veryClose50 m10 m120 ms
now—5 m100 ms
"dynamicThresholds": {
  "veryFar":    { "boundary": 5000, "distance": 100, "rateLimit": 2000 },
  "far":        { "boundary": 1000, "distance": 50,  "rateLimit": 500  },
  "approaching":{ "boundary": 500,  "distance": 25,  "rateLimit": 250  },
  "near":       { "boundary": 200,  "distance": 15,  "rateLimit": 200  },
  "close":      { "boundary": 100,  "distance": 15,  "rateLimit": 150  },
  "veryClose":  { "boundary": 50,   "distance": 10,  "rateLimit": 120  },
  "now":        {                    "distance": 5,   "rateLimit": 100  }
}

Countries

Country overrides for when locale cannot be detected from platform services. forceImperial and forceRHD override this table entirely.

{ "code": "GB", "name": "United Kingdom", "rhd": true, "imperial": true }
{ "code": "US", "name": "United States",  "rhd": false, "imperial": true }
{ "code": "DE", "name": "Germany",        "rhd": false, "imperial": false }

Scope of the project

Two years of evenings and weekends. Reverse engineering of the QNX Screen API, NvMedia decoder, iAP2 protocol, Android Auto and CarPlay wire protocols, Porsche's BAP cluster protocol, and the composition stack on both PCM5 and MHI2 head units.

Rough labor equivalent at specialist embedded / reverse-engineering contractor rates: $90k–$200k. For an automotive middleware vendor doing this cleanly with docs and full test rig: $250k–$400k. What an OEM would price this at as a factory feature: $500–$2000 per vehicle.

This project is free. None of that value is going anywhere except back into more releases.

If someone is asking you for money for a cluster mod built on this work, they got the underlying code for free too.

Contributing & Troubleshooting

This project is the result of extensive reverse-engineering and testing on MH2P. Contributions welcome via the ModKit Discord.

Troubleshooting / bug reports


Format a FAT32 SD card
Put the SD in the head unit before turning ignition on
Drive → afterwards when you turn ignition off → pull SD card → look in the log for the event that was wrong → match it to the same one in the hashed log (timestamps help)
Share the hashed logs + expected vs actual cluster behaviour on the Discord

Known limitations


RHD and metric/imperial coverage still expanding — report issues
Roundabout accuracy limited by what the phone sends (Waze in particular can lack exit angles)
Data granularity and update rate limit accuracy on very short maneuvers
Some glitches are inherent to Android Auto / CarPlay themselves

Credits

LukaDev: Managing screens in VW/MIB2, CarPlay RGI and GAL hacking, https://github.com/luka-dev/mib2q-carplay-rgi/

One1Blt: Android Auto / VNC to MIB2 rendering, https://github.com/OneB1t/VcMOSTRenderMqb

adi961: Turn-by-turn to VC integration, https://github.com/adi961/mib2-android-auto-vc

LawPaul: MH2P Modkit, https://lawpaul.github.io/MH2p_SD_ModKit_Site

CosminBC: MH2P/MhHI2 Audi/VW paid ofr VC: https://altscreen.mib-helper.com/

litdreams10: general platform knowledge, Android Auto testing

ModKit Discord community: testing, bug reports, cross-car validation