Developer manual

The board in detail

The product page covers what P1LOT One does. This page covers how. What it drives, what it reads, what it refuses to do, and what it can be used for outside a game.

What you can plug into it

One 12 V input, one USB-C socket to the computer, and one connector that carries everything else. Nothing on that connector runs off USB. The 12 V supply feeds all of it.

  • Two CAN connectionsThis is what talks to car modules. Today that means instrument clusters, gear selectors and rotary controllers, and the list grows as each one is decoded. Two connections, so you can run everything on one or give a dashboard a set to itself. The rate matches what you connected rather than being fixed in the hardware.
  • One LIN connectionThe other kind of car bus, and the one a steering wheel's button block speaks. It is a master. The board asks and the module answers, so nothing appears on it until the board is looking. One branch, because that is what a wheel needs and there is nothing else on the rig that wants one.
  • Switched power out12 V for whatever you connected and 5 V for smaller accessories, both switched by the board and both protected against a short. This is what powers the dashboard, so there is no second supply on the desk.
  • USB-C to the computerOne cable and nothing to install. The PC sees a serial port and two controllers, on the board's own identity, so its buttons never collide with your wheel's.
  • Two analog inputsAnything that moves a wiper along a track: a pedal, a throttle body, a handbrake lever, a stick, a plain potentiometer. They arrive at the PC as two gamepad axes, so a game reads them in its own settings with nothing else in the path. Each one is calibrated by holding the control where you want an end and pressing a button, setting the resting end, the far end and, for a two-way control, the centre. Nothing is typed in volts, and a pot wired the other way round needs no rewiring. A stick gets the whole axis, centre at rest with one way negative and the other positive, rather than half of it.
  • A gauge and a shift lightTwo signal outputs drive servo gauges straight from telemetry, and an LED strip output runs as a shift light off the revs. Both run on the board, with no host code beyond the telemetry you are already sending. What we do not sell is the gauge or the strip itself. Those are different products with their own approvals. The pins are in the map below.
The exact numbers
Processor
STM32G474CEU6, 512 K flashUpdated over USB from a signed file. An interrupted update leaves the working firmware in place.
Power in
12 V DC, 3 A, barrel jackReverse-protected. This is the only power source for anything on the DB15. USB powers the processor and nothing else.
USB
USB-C, data onlyEnumerates as one virtual COM port and two controllers, a game pad and a second one for the automotive controls. All three are always present, on the board's own identity.
CAN
2 × classic CANTwo independent pairs, and each runs at the rate the devices on it use. A pair with nothing chosen on it stays quiet, so a rig you are half way through building cannot put frames anywhere. Two pairs is what lets parts from two different marques share one connector. A message id means whatever the maker who defined it says it means, so each maker's parts get a pair to themselves.
LIN
1 × master19 200 baud, set by the driver of whatever is on the line rather than typed in. The rate belongs to the module, as its identifiers do, so there is nothing here to get wrong. The transceiver is powered by the firmware rather than always live. This is the steering-wheel block's bus, the one branch on the connector that is not a CAN pair, and a LIN slave says nothing until it is asked, so the part exists only while the board is polling it.
Analog inputs
2 × 0…5 V, 100 Hz hardware scanRead continuously in hardware and referenced to a measured internal reference rather than a nominal supply, so the reading does not drift with the rail. Each one can be CALIBRATED: hold the control at each end and press, so the board takes the reading it is looking at. Then say whether that travel is a pedal, which rests at one end, or a stick, which rests in the middle and reads negative one way and positive the other. A stick can also be given a deadband, because a rest position is a few millivolts wide and it wanders. Which way round the pot is wired does not matter: if the voltage falls as the control moves, take the resting end anyway and the travel runs that way. Nothing has to be typed and nothing is assumed about the pot.
Signal outputs
2 × servo, or plain PWMEither channel can be mapped to a telemetry value on the board, so a gauge needle works with no host code. Both pins are modulated either way. What differs is what the far end reads. As a servo the pulse width is the signal, 50 Hz and 500 to 3500 µs, which is what a hobby servo and most aftermarket movements expect. As PWM the duty is the signal, for a movement driven through an RC filter and an amplifier, and the frame wants to be short so the filter can keep up. The frame is settable from 200 µs to 65 500 µs and both channels share it, because one timer drives them. The gauge itself is a different product with its own approvals. The output is here and it works.
Serial LED
1 × WS2812 chain, up to 32Driven as a shift light from the revs, with no host code beyond the telemetry you are already sending. Tell the board how long the strip is and it does the rest.
Switched 12 V
DB15 pins 11 and 12High-side switch with current sense. Over 2.5 A, or a fault report from the switch, drops the rail for 5 s. Three trips in a row latch it off until something explicitly asks for it again. A single reading decides it, nothing is averaged, and the rail is only judged once it is up, so start-up inrush does not trip it.
Switched 5 V
DB15 pin 13, ≤ 1.8 AThrough an eFuse. A trip is retried three times, two seconds apart to let it cool, and held off after that until something asks again.
Internal measurements
Reference, die temperature, VBATOn the same 100 Hz scan as the external inputs, readable over the protocol and from the console.

Which pin is which

It is a VGA-style connector, chosen because the cable and the hoods are sold everywhere and cost nothing. The dashboard hangs on CAN 2, which is the bus the firmware selects by default; CAN 1 is the second one, free for whatever you put beside it. Everything else on the connector is there for whatever you add next: a shifter, a real steering wheel, a pedal, a strip of LEDs.

FEMALE PORT TOWARD YOU — PINS MIRRORED55 — CAN 2 low, green44 — LIN, dark blue33 — CAN 1 high, cyan / white22 — Signal out 2, violet / white11 — Analog in 2, yellow / white1010 — CAN 2 high, green / orange99 — CAN 1 low, cyan88 — Serial LED, grey77 — Signal out 1, violet66 — Analog in 1, yellow1515 — Ground, brown1414 — Ground, brown1313 — +5 V fused, orange1212 — +12 V switched, red1111 — +12 V switched, red

The colours are the wires. Both halves of a pair share a base colour. Solid is low, striped is high, and the two CAN pairs are twisted. CAN 2 is green and green/orange because that is what the cluster bus is in the car, and ground is brown for the same reason.

  • 1Analog in 2yellow / white
  • 2Signal out 2violet / white
  • 3CAN 1 highcyan / white · twisted with its CAN 1 partner
  • 4LINdark blue
  • 5CAN 2 lowgreen · twisted with its CAN 2 partner
  • 6Analog in 1yellow
  • 7Signal out 1violet
  • 8Serial LEDgrey
  • 9CAN 1 lowcyan · twisted with its CAN 1 partner
  • 10CAN 2 highgreen / orange · twisted with its CAN 2 partner
  • 11+12 V switchedred
  • 12+12 V switchedred
  • 13+5 V fusedorange
  • 14Groundbrown
  • 15Groundbrown

Every pin, with what it expects

  • 1ADC 2 in0…5 V at the connector, halved by a 1 k / 1 k divider. Not 12 V tolerantyellow / white
  • 2Signal out 2servo: 50 Hz frame, 500–3500 µs · PWM: the duty, on a frame you setviolet / white
  • 3CAN 1 highthe Porsche panel's pair by defaultcyan / white
  • 4LINmaster, 19 200 baud. The steering-wheel block runs heredark blue
  • 5CAN 2 lowthe BMW parts' pair by defaultgreen
  • 6ADC 1 in0…5 V at the connector, halved by a 1 k / 1 k divider. Not 12 V tolerantyellow
  • 7Signal out 1servo: 50 Hz frame, 500–3500 µs · PWM: the duty, on a frame you setviolet
  • 8Serial LEDWS2812, up to 32grey
  • 9CAN 1 lowthe Porsche panel's pair by defaultcyan
  • 10CAN 2 highthe BMW parts' pair by defaultgreen / orange
  • 11+12 V switchedhigh-side switch, current sensedred
  • 12+12 V switchedsame rail as pin 11red
  • 13+5 V fusedeFuse, ≤ 1.8 A, retried three times then held offorange
  • 14GNDbrown
  • 15GNDbrown

Read this before you wire anything to it

The 12 V pins are a switched rail, not a supply you can lean on. The firmware owns them, telemetry brings them up, and a 30-second timer takes them down. Do not power a bench from them and expect it to stay powered.

The two analog inputs expect 0…5 V and are divided for it. The two signal outputs are logic-level, timer-driven pins, not drivers. Anything that needs current needs its own stage. They idle low and pulse high, on a 20 ms frame, so a width of 1500 µs is 1500 µs of pulse at the pin. And the cluster harness that came with your unit belongs to the cluster printed on its label; the warning on the product page explains why that matters more than it sounds.

The status word

Field 15 of the line is 32 bits of hex. Each bit is one event, and the driver decides whether the cluster shows it as a latched warning light or as a rotating message on the text line. Several lights can be lit at once, and messages take their turn.

  • b00x00001Handbrake
  • b10x00002Traction control intervening
  • b20x00004Check engine
  • b30x00008Stability control off
  • b40x00010Low tyre pressure
  • b50x00020Seat belt
  • b60x00040Steering malfunction
  • b70x00080Transmission malfunction
  • b80x00100Brake malfunction
  • b90x00200ABS malfunction
  • b100x00400Speed warning
  • b110x00800Damage to the car
  • b120x01000Engine overheating
  • b130x02000Oil pressure low
  • b140x04000Launch control
  • b150x08000Gearbox over temperature
  • b160x10000Clutch
  • b170x20000Fuel reserve
  • b180x40000Below reserve

Which of those a given cluster can physically show is a property of the cluster, not of the interface. Ask us which is which for the one you have. There are two different answers behind a signal that does nothing: it is not decoded yet, or that dashboard has no such display at all, and no update fixes the second one.

The lights

Field 14 is a bitfield too, and a smaller one. The indicators are in here rather than in a column of their own. They are exterior lamps like the other four, and a separate column meant a line could contradict itself, the lights saying one thing and the indicators another, with nothing to say which the panel should believe. Both bits together is a hazard flash.

  • b00x01Low beam
  • b10x02High beam
  • b20x04Fog
  • b30x08Daytime running / sidelights / parking
  • b40x10Automatic-light switch
  • b50x20Left indicator
  • b60x40Right indicator

The console

Open any terminal on the port and send one line. Every command name is lowercase. The shell takes each one from the identifier it was declared with, so there is no capitalised spelling of any of them to get wrong. help in the shell is always authoritative. This is the current set.

G1VE_ME_CLI
status
Link, both rails, both buses, and what is bound to them
setup
What is on the harness, and what fights what
config
What the board does with it
knob · shifter
The rotary controller and the gear selector: are they answering, and what do their controls mean
wheel
The steering wheel: which control is being held, by name, and a scorecard. Press every one once, stop it, and whatever never answered is listed
map
Who serves what on this rig: one line per job, naming the part that ended up doing it
power
The connector's supply switches: hold the rails up with no game running, and the current amplifier
setup servo · setup pwm · setup led · setup axis
Everything on the connector: what each signal pin follows, the shape those pins make and the frame, how long the LED strip is, and what is on each analog pin, a pedal, a stick or nothing, with the travel it actually has
save
Keep the whole configuration across a reset
dfu · reset
Reboot into the updater, or just reboot
uname [-a] · help
Build and identity, with the authoritative list taken from the board rather than from this page

It used to be eighteen commands. Everything removed only poked a pin. Paint the strip, drive a servo, switch a rail, park a bus in listen-only. A shipping console full of ways to make a rig behave unlike itself is a support case with a keyboard attached. What is left answers the two questions a service call actually asks: what is this rig, and is it working.

setup, what is on the harness

setup
setup <class>
setup <class> <id> can1|can2|def
setup <class> off
setup servo | setup pwm | setup led | setup axis

The classes are cluster, knob and shifter, and a rig has one of each at most. Bare, it prints a row per class, showing what is chosen and on which pair. Given a class, it lists everything this firmware can drive there.

There is no on. Naming a device is choosing it. A thing you have just picked and placed, which is then also switched off, is a state that exists only to be wondered at later. And nothing is assumed. A board out of the box drives no dashboard, no knob, no lever, no strip and no gauge, because it cannot see what is on the other end of the connector and guessing means a rig that does something nobody asked for on its first power-up.

config, what the board does with it

config
config <group>
config <group> <name>
config <group> <name> <value>

Every value is a WORD out of a list the setting will show you, never a number. A rig configured by numbers cannot be read back by the person who owns it, and every number in a console is one more thing somebody has to be told.

A setting can belong to a PART rather than to the board, and the three gearbox ones do. They mean nothing on a rig with no gear selector on it. configprints the owner in brackets beside such a setting and the row over the protocol carries it as its last field, so a tool draws it under the part instead of on a settings page. Everything else here is the board’s own and is true of a bare board.

controls mode default · game
Default hands each control to the first job on the rig that can use it, in the order dashboard menus, volume, mute, track, play/pause. Whatever nothing takes reaches your game. Game switches every one of those off, so all of it arrives at the title, which is what a binding dialog needs. The controls switch it themselves, and this is the stored value
gearbox mode hold · pulse
Whether an emulated gear is a state the button holds, or a press. Hold is right for a game that reads the button as a state. Pulse is for one that only ever watches for events and would otherwise see a selection once and never again. Belongs to the gear selector’s driver, and is only offered while one is fitted
gearbox sync none · neutral · all
How much of the game's own gear the lever's gearbox takes. None is the lever alone. Neutral believes a Neutral the game keeps insisting on. Under either, the number is the lever's as well, so pushing into Drive gives first, as it does in the car. All hands the readout to the game instead, and the lever stays worth binding as buttons. Belongs to the gear selector’s driver, and is only offered while one is fitted
gearbox timeout 1s · 2s · 3s · 5s
How long the game must insist on neutral before it is taken. Only consulted under sync neutral. Belongs to the gear selector’s driver, and is only offered while one is fitted
led brightness off · low · medium · high · full
The status light on the board itself, not a strip on the connector. Turn it down if the board sits where you can see it while you drive. A fault ignores this and lights anyway, because a board turned down to nothing would report a problem by looking exactly like a board with no power. The values are an ORDER rather than a set, which is the one thing the protocol marks about a setting so a tool can draw it as a slider
power mode default · eco
How soon the rig switches itself off with nothing driving it. The rails always follow the game. They come up on the first telemetry line and go down after the last, and this is only how long the board waits
board rev auto · 1.0 · 1.1
Which hardware this is. Service only, and it is flagged as such over the protocol so a tool can keep it out of the way. Naming the wrong revision changes which way a pin is driven, so a board that is physically fine stops working and nothing says why. Auto reads it from the provision record and is the answer

save, and what survives

Nothing saves itself. A change takes effect at once and is gone on the next reset until you type save, which writes the whole configuration in one go: what is on the harness, the gauge mappings, what the controls do, the gamepad and the rails. There used to be five separate saves, one hanging off whichever command changed a value, and a person who moved a device, picked a dashboard and set the pointer gain had to remember which three owed one. Configuration is one thing to a person, so it is one command.

Each store reports on its own line, because a single "saved" over five writes hides the one that failed. A failed flash write is exactly what you need to know before powering down. What is saved lives in a part of flash the updater does not touch, so it survives both a power cycle and a firmware update. reset is what applies a saved setup change, because a device binds its hardware once, at boot.

What it will not tell you

No frame identifiers, no decoded payload bytes, no last-frame dumps. Whoever holds a unit can open this console, so everything it prints is published, and the ids and payload layouts are the part of this product that took a bench and months to find. Counters are named for what they count, which is also the better diagnostic. You want to know whether a device is talking, not on which id.

Gauges the board drives by itself

There are two signal outputs and only two. Channel 0 on pin 7 and channel 1 on pin 2. Either can be mapped to a telemetry value on the board, so a needle works with no host code beyond the telemetry you are already sending. Give it a source and, optionally, your own input range and your own on-time range. Swapping the ends of that range reverses the sweep, and the ends are signed, so a boost gauge reading below atmosphere maps from a negative number.

setup servo <ch> <src> [in_min in_max] [us_min us_max]
setup pwm <group> servo|pwm <frame µs>
save

The SHAPE is separate, and it belongs to the group rather than to the channel, because one timer drives both pins and a timer has one frame for everything on it. As a servo that frame is 20 ms and the pulse may be anywhere from 500 to 3 500 µs. As PWM the duty is the signal and the frame wants to be short enough for the filter behind it to keep up. A channel with no range of its own gets 1 000 to 2 000 µs, which is what most gauges want. Off, nothing drives it at all.

rpm
Defaults to 0…7000rev/min
speed
Defaults to 0…300km/h
coolant
Defaults to 40…130°C
fuel
Defaults to 0…100%
oil
Defaults to 40…150°C
oilp
Defaults to 0…50tenths of a bar
boost
Defaults to −100…300hundredths of a bar, negative is vacuum
off
Defaults to —nothing drives the channel

Pulse defaults to 1000…2000 µs, and a mapped channel accepts anything from 500 to 3500 µs, wider than the nominal servo frame, because a gauge movement often needs the extra travel to reach the end of its own dial. Zero is refused. At the pin it releases the line rather than driving to it, so a mapping ending there goes limp instead of reading empty. While a channel is off it keeps its pulse pair, is not held to those bounds, and the host drives it directly. Going offline parks every mapped needle at its low end.

Outside a game

Most of what the board does has nothing to do with telemetry. All of it is on the unit you buy, running the P1LOT firmware. These are what the hardware is capable of rather than a separate toolkit.

  • On every unit

    A diagnostic with no computer at all

    Unplug USB, leave the 12 V supply connected, and hold the button on the board for three seconds. The dashboard wakes, both needles cross their whole scale together, hold at the top, drop back to zero, and the ignition switches itself off. About fifteen seconds. It separates a hardware fault from a host-side one in a single gesture, which is otherwise three emails. The same hold with USB connected opens the firmware updater instead.

  • On every unit

    A dashboard, a knob, a gear lever and a wheel block, all at once

    There are two sets of bus wires on the connector plus the LIN line, so you can run everything together on one pair, or give the dashboard a pair to itself if it wants one. You tell the board what you plugged in. `setup cluster`, `setup knob`, `setup shifter`, `setup wheel`, and it drives them. Nothing is assumed. A board out of the box drives nothing until you say what is there.

  • On every unit

    Driven by something that is not a game

    The board takes one line of plain text per update, so it does not have to be a game sending it. A test rig, a replayed log, a script of your own, or a build server proving a dashboard still works. Anything that can open a serial port can move the needles.

The rules that will bite you

Every one of these has cost somebody an afternoon, which is why they are listed rather than left in the source.

  • Keep sendingAt least 2 Hz. Six tenths of a second of silence is stale and the panel holds its last picture. Five seconds is offline, which walks the cluster down and parks everything.
  • The rails are requestsThey come up when telemetry arrives and drop 30 seconds after it stops. They are supervised, so a fault can take one down under you. Read the state back rather than assuming.
  • The 5 V fault flag pulsesIt is an edge, not a level. Polling it once and seeing zero tells you nothing. The verdict is the rail staying off.
  • Ignore columns you do not knowBoth lines grow to the right and never in the middle. Split on the semicolon and read the columns you need. A reader that insists on an exact count breaks on the next firmware.
  • Nothing saves itselfChange a setting and it takes effect at once, and is gone on the next reset unless you type save. What is saved then survives both a power cycle and a firmware update.

Questions

Why is there only one COM port?

Because two identical-looking ports with nothing to say which is which is a support case waiting to happen. The console is not a second device, it is a mode of the only one. Send G1VE_ME_CLI on its own line and the shell takes the port; send any line starting with P1 and telemetry takes it back. SimHub sends one on every update, so the link recovers by itself the moment a host starts talking. Nothing is stored, and closing the port ends the session too.

Can I use the console and stream telemetry at the same time?

No, and that is deliberate. The console owns the byte stream raw, which is what makes it a real terminal. Characters echo as you type, backspace works, the arrow keys walk the history, Tab completes a command. Forwarding only whole lines to it would give you a command slot, not a console. Nobody services a board and drives a lap at the same moment.

I set the 12 V rail on and it turned itself off. Why?

Because the rails follow telemetry rather than a switch. They come up the instant a line arrives and drop together 30 seconds after the last one, once the cluster has been walked down properly. Keep sending and they stay up. Stop, and the rig puts itself to bed. What they are actually doing is in the status line’s flags, which you get by asking for the line with field 21.

The 5 V fault input reads zero, so nothing is wrong. Right?

No. That is the one input you cannot poll. The eFuse answers a short by cycling: limit, overheat, shut down, cool, retry. A single read lands in a gap far more often than not. The board catches the asserting edge in hardware and adds the flag time up. The verdict you want is the 5 V output going off and staying off, which is what the status line shows.

Why does the fuel gauge move slowly when everything else is instant?

Because a real cluster rejects a fuel level that appears out of nowhere. Power on straight into a full tank and the gauge stays dead. The board ramps it instead, in small steps the cluster accepts, so a full sweep takes about two seconds. It also does not park when you go offline, because a parked car does not drain its tank and the cluster computes its range readout from the same filtered value. Until a host states a level at all, the gauge sits at half rather than at empty with a reserve warning.

Why are the gamepad axes centred when nothing is wired to them?

Because each input reaches the processor through the resistor divider that scales 0…5 V down, and that divider holds the pin at zero on its own, so an unconnected input reads a clean zero rather than noise. Zero is one end of an axis, though, which a game will happily let you bind and then act on. Centred is the value that means nothing. The board enumerates the same either way, so nothing has to be re-detected when you do wire something.

Are the analog readings in volts at the connector?

No. They are millivolts at the processor pin, referenced against the chip's own factory-calibrated reference rather than a nominal 3.3 V, so the reading does not drift with the supply. The two DB15 inputs sit behind a 1 k / 1 k divider, a plain halving, so double them for volts at the connector. Everything the board itself reports about a calibration is already at the connector, because that is where a meter goes. The 12 V draw beside them is different again. That one is already converted, and is in milliamps.

That divider is a scale and not a protection. These pins are for the 5 V the connector hands out; 12 V on one of them reaches the processor as 6 V, which is past what it will take, and the damage is to the board rather than to whatever you plugged in. Nothing in the firmware sees it coming or can report it afterwards.

Do my settings survive a firmware update?

Yes, and a power cycle too. What is on the harness, the gauge mappings, what the controls do and the rail defaults live in a part of flash the updater does not touch, so a unit comes back from an update set up the way you left it. Nothing saves itself. Change something and type save before you power down, or it was only for this session.

How much do I have to send, and how often?

At least twice a second. After six tenths of a second of silence the board goes stale and holds the picture it has. After five it goes offline, which walks the cluster down, parks the needles and blanks the strip. You may send every field every time or only the ones that changed. An empty column means keep the last value.

Can I add support for a part you do not drive?

The firmware is built for exactly that, and not only for dashboards: clusters, selectors, controllers and wheel blocks are one registry, because an id, a place on the connector and a lifecycle describe all four. The fourth arriving on LIN rather than on a CAN pair changed a row rather than the registry. A new part is one driver file and one row, and the conflict rules, the console and the saved setup pick it up without being told. What it takes is not the code, it is the decoding. The frames, the counters and the checksums a given part refuses to work without. That is the work, and it is the work we do. Tell us what you have and it goes on the list.

Building something with it?

Tell us what you are wiring to it. The SimHub template is on the downloads page, the protocol reference and its Python mirror come with the board, and your email is answered by the engineers who wrote the firmware.