Synapse PDM is an open-source, automotive power distribution module with mobile data, GPS connectivity, SD card logging, and an on-board IMU.
During my Triumph Spitfire restoration and conversion to EFI, I wanted a better solution to the whole car running on three fuses. Especially given the additional circuits required for all the EFI components, fuel pumps, ignition system and injectors.
This led me to start development of Synapse PDM. Originally a basic unit with six channels that I was going to use along side the existing fuse box. It's now grown to 14 channels which will run all the circuits in the car with a few more nice-to-have features.
I don't believe there is currently an open-source PDM of this size on the market. Much of the inspiration for this project has come from the likes of Haltech, Aim and Link. All of these companies manufacture professional, cutting-edge PDM solutions, packed with features and rugged enough to meet the demands of motorsport.
I see Synapse PDM filling a gap in the market for DIY car enthusiasts that run the likes of Speeduino or RusEFI in their cars who want a fully featured PDM without the professional-level cost.
For discussion and updates, join the Facebook Group, Discord server or see my YouTube channel.
Some features aren't implemented. Check the GitHub repositories for info.
As of 2026, development is ongoing but the hardware is production-ready. Firmware is stable with ongoing feature expansion via updates.
See the GitHub pages for the firmware and configuration utility for progress.
The SynapsePDM firmware repository can be found here.
The Cortex software repository can be found here.
The hardware can be found on OSHWLab, here.
Enclosure CAD can be found here.
I'm actively seeking developers and testers for this project. Please Contact me if you are interested in contributing.
The 4-layer PCB measures 186mm x 160mm. Outer copper needs to be 2oz to effectively dissipate heat. The high-side drivers are fed by threaded terminals for high current capability. Seven drivers along each edge of the board with four layers and thermal vias to dissipate heat. Most of the other connections are made using the 35-way Ampseal connector.
On the board, you'll find a micro SD card socket, SIM card socket, GPS and mobile data U.FL antenna connectors, display header, programming header, external USB-C socket, debug USB-C socket for the SIM7900X module and the usual STM32 boot mode selection headers.
Input power is protected from over voltage (load dump) and reverse polarity.
Inputs are over voltage and under voltage protected as well as being current limited.
The CAN interface is protected from transients.
The connection to VBatt along the top row of drivers (U27) is also used to power the control electronics.
Backup LiPo has been removed from v1.7. This was a decision based on several factors including cost, complexity and thermal considerations.

Dimentions are in millimeters.

I selected the BTS50025-1TEA due to their extremely low on resistance. Worst case being 5mΩ. If we take a maximum single channel steady-state current of 20A and calculate power dissipation (I2R), we see a power dissipation of 2 watts per channel. Thermal resistance given in Infineon's datasheet of 22°C/W yeilds a temperature rise of 44°C. This of course, describes the thermal characteristics a single channel. Multiple adjacent channels at full load will enevitably see a greater temperature rise. They are rated to 150°C operating temperature so should withstand high currents even at relativley high ambient temperatures.
The current carrying traces and the connector are probably the limiting factors in maximum achievable current. The traces are 4mm wide. On 2oz copper, on a 4-layer board with internal ground planes at 20A, that gives a temperature rise of 42°C. 25A on the same trace gives a temperature rise of 70°C which is getting too close in an ambient environment that may be 40°C or more.
Below are some thermal images from my testing. A single channel loaded at 17A (left) and an adjacent pair loaded at 24A (12A each, right). Testing was done on a channel closest to the edge of the board which has the worst case copper area for dissipation. The board was mounted in the 3D printed enclosure with the 5mm aluminium heat spreader attached to the under side of the PCB using thermal tape.
The highest temperature rise was for the single 17A test, that channel saw a 25°C rise.
I have more thermal testing planned to fully load several adjacent channels, but looking at these initial results, I don't see any cause for concern.

In both tests below, the tin plated 35-way PCB header is used (part number 776163-1). The gold plated header is part number 1-776163-1 and is specified on the most recent BOM.
Each test was a single channel loaded to 15.5A and soaked for 10 minutes. First image shown is with tin plated crimp terminals, the second with gold plated terminals.

As you can see, simply by changing the terminal to the gold plated variant, decrease in temperature rise by 5.7°C is obtained.
Below are 4 adjacent channels with gold plated crimp terminals, loaded at 15.5A each and soaked for 10 minutes.

These temperatures are well within the operating temperature of 105°C for the tin plated PCB header and even more so for the gold plated header which is rated to 125°C. The surrounding parts are rated to 125°C or better.
Loading 7 adjacent channels starts to get a bit close to limits. Again, 15.5A each, soaked for 10 minutes. This is quite an extreme scenario, however. 109A of the total system current limit of 150A loaded entirely on one set of drivers and adjacent pins but it does show that some consideration is required to distribute the required load.

The Amphenol connector is rated to 17A per pin and only a certain subset of pins can be loaded according to their datasheet as seen in the derating table below. Use of the gold contacts is also a requirement for these ratings.

It is worth pointing out that this derating table applies to the connector at an ambient operating temperature of about 85°C at which point they are derated from there up to 125°C for the gold plated pins (see chart below). In practice, loading multiple pins at 17A outside of this pattern is probably going to be fine.

Given these limits, I decided to hard-code the firmware with a 17A limit. Channels can be paired for this reason, to allow control of high-current devices.
The main power is supplied via an Amphenol SurLok connector. These robust and IP rated connectors are ideal for this applicaton. The one I fitted can supply 150A with a 35mm2 cable. Cable connector part number SLPPB35BSR, panel socket part number SLPRBBPSR.



| Ampseal pin | Function | Ampseal pin | Function | Ampseal pin | Function |
|---|---|---|---|---|---|
| 1 | Output 3 | 13 | Output 2 | 24 | Output 1 |
| 2 | Output 4 | 14 | Digital in 1 | 25 | Analogue in 1 |
| 3 | Output 5 | 15 | Digital in 2 | 26 | Analogue in 2 |
| 4 | Output 6 | 16 | Digital in 3 | 27 | Analogue in 3 |
| 5 | Output 7 | 17 | Digital in 4 | 28 | Analogue in 4 |
| 6 | CAN L | 18 | Digital in 5 | 29 | Analogue in 5 |
| 7 | CAN H | 19 | Digital in 6 | 30 | Analogue in 6 |
| 8 | Output 8 | 20 | Digital in 7 | 31 | Analogue in 7 |
| 9 | Output 9 | 21 | Digital in 8 | 32 | Analogue in 8 |
| 10 | Output 10 | 22 | Igntion | 33 | 5V Reference |
| 11 | Output 11 | 23 | Output 13 | 34 | Ground |
| 12 | Output 12 | - | - | 35 | Output 14 |
There are two variants of the enclosure. The 3D printed variant caters for 5mm aluminium heat spreaders which can be attached to the underside of the PCB using thermal tape. The full aluminium enclosure is designed so the area beneath the drivers is in contact with the enclosure itself, using thermal interface tape.
Most peripherals are turned off when the PDM goes into sleep mode to save power before the processor goes into sleep mode by means of turning off the switched 5V and 3.3V rails.
The 3.8V SIM module regulator is tuned off via the enable pin in hardware v1.8 onwards.
Current consumption in normal operating (no outputs on) with all peripherals running and GPS fix is ~85mA. Sleep current is about 2.4mA.

The scope trace below shows ignition on (yellow) and an output (blue) where its input is already high on wake. Average time to output high on waking from sleep is 80ms.

Checking inputs and raising outputs are some of the first functions called when the system wakes. Other functions such as updating the display come after this.
The firmware is written using PlatformIO and the STM32 Arduino core targetting the STM32F446ZET6. Functions are called at different intervals depending on priority.
Outputs are configured as either digital or PWM. PWM frequency is fixed at 200Hz. This is a limitation of the Infineon HSD but is high enough frequency to run brightness control for lighting, speed control or to allow for soft-starting accessories. PWM control is acheived through DMA register manipulation. This allows for accurate timing with minimal CPU load.
Digital inputs are quite basic, they are just configured as active high or active low. No pull-ups or pull-downs are configured. External resistors should be used if required.
Analogue inputs have several configurable properties. Internal pull-up or pull-down resistors can be configured, the input can behave as a digital input or an analogue input. In analogue mode, the input can be purely passive and accept an analogue signal. As an active analogue input, a pull up can be enabled to effectively create a resistive divider with an NTC thermistor for example. Analogue inputs can be configured as thresholds for a digital output, or scaled for PWM outputs. Analogue signals are read in the range of 0 to 5V. Inputs are 12V tolerant.
Outputs have several protection features.
Under current is the lower current thrshold for open-circuit detection. Should an output be active but the current is below this threshold, the output will be disabled with an open-circuit fault.
Over current threshold is used for detecting over current and short circuit events. Exceeding this value will either trigger retries if they are configured, or an over current fault, disabling the channel.
Inrush delay can be configured up to 2 seconds. This looks to the configured inrush current limit for the configured duration to determine a fault condition. This is inteded for use with accessories such as cooling fans that will draw many times their steady-state current at power on. The maximum inrush current threshold for a single channel is 50 amps. Beyond this, channels will need to be paired.
Soft start can be configured up to 5 seconds. This uses PWM to ramp up the duty for the configured channel over the configured period. For a digital channel, this ramp concludes at 100% duty, For a PWM channel, this ramp concludes at that channel's configured PWM duty at the time of enable.
Retry attempts can also be configured. The retry interval is approximately 150ms. This allows the PDM to make several attempts at activating an output with an over current fault before the number of retries is reached and the output is disabled a fault.
Outputs can be grouped simply by assigning the same input to multiple channels. The current limits applied to each channel can therefore be summed for the total output current available. Generally current sharing is reasonable between channels, but thermal factors prevent them from current from being distributed completely evenly. Expect to see some channels bearing more current than others and adjust limits accordingly.
Bear in mind that if one channel in a group fails, the rest of the channels in that group will try and take the load. So long as limits are set appropriately, those channels will correctly fault also. The PDM will protect iteself, it's the wiring you need to consider.
Faults are reset the next time the associated input transitions from inactive to active.
The display shows an error code in the format "EXXXX". This is a 16-bit hex value. See the table below for individual bit stats or this page for decoding errors.
| Bit position | Fault |
|---|---|
| 0 | Over current (system level) |
| 1 | Over temperature |
| 2 | Under voltage |
| 3 | EEPROM CRC check failed |
| 4 | SD card error |
| 5 | PC comms checksum error |
| 6 | GPS error or no fix if enabled |
Data logging is always enabled as long as the date and time are set. All channel and sytem parameters are logged at 10Hz. 10 log files are retained and store one hour of data in each file. Filenames are in the format, YYYY-MM-DD_HH-MM-SS.csv which represents the date and time the file was created.
Multiple runs of the vehicle will potentially be stored in one file if they are under an hour. This ensures that there is always 10 hours of logged activity across 10 files.
Date and time are obtained from GPS.
The CPU shuts off all uneccessary peripherals & power rails and enters sleep mode when the ignition input goes low. Only the CPU itself and the IMU are kept powered during sleep. Testing shows a sleep current of approximately 2.4mA.
The system exits sleep mode either by interrupt from the IMU (vehicle movement) or via the ignition input.
In sleep the IMU is armed to trigger an interrupt on any movement. This wakes the processor. A configurable timeout is set in system options. Wakes during this period are ignored. This is to account for occupants moving in the car after igntion off, doors closing etc. Upon waking after this period has elapsed, the system checks the ignition input state amd monitors movement for the configured period of time. If no movement or ignition is detected in that time, the system goes back to sleep. If movement persists, other actions can be taken such as reporting to a web service with GPS co-ordinates.
Currently there is no implementation for telemetry reporting or a security system as such. I envisage using something like ThingsBoard to implement telemetry & GPS tracking using MQQT. Security could be done by securing the PDM via an encrypted CAN message from a CAN based NFC module or similar.
Below is a comprehensive specification for the CAN messages and their IDs. Message IDs are shown here as firmware defaults, these are configurable through Cortex.
I recommend using Kvaser CAN database editor which is free. Download the CAN database for Synapse PDM, here or find the latest DBC file in the SynapsePDM firmware repository.
Configuration changes over CAN are checked for differences with stored EEPROM parameters, if there is a change, a timer is set. If no more configuration changes occur within 5 seconds or ignition off (whichever comes soonest), the controller saves those changes to EEPROM. This prevents multiple unnecessary writes to EEPROM.
Direction: PDM → ECU | DLC: 8 bytes | Cycle Time: 100ms
Provides real-time system status information including power, temperature, and error conditions.
| Signal | Bit Position | Length | Unit | Range | Type | Notes |
|---|---|---|---|---|---|---|
| AliveCounter | 0-7 | 8 bits | — | 0-255 | Unsigned | Increments every status message, automatically overflows |
| SystemCurrentLimit | 8-23 | 16 bits | Amps × 10 | 0-65535 | Unsigned | System-wide current limitation threshold |
| SystemTemp | 24-31 | 8 bits | Celsius | 0-255 | Unsigned | PDM internal temperature |
| ECUVoltage | 32-39 | 8 bits | Volts × 10 | 0-255 | Unsigned | Battery voltage (Vbatt) |
| SystemCurrent | 40-47 | 8 bits | Amps × 10 | 0-255 | Unsigned | Total system current draw |
| ErrorFlags | 48-63 | 16 bits | — | 0 | Unsigned | Error condition flags |
Byte Layout:
Byte 0: [AliveCounter]
Byte 1-2: [SystemCurrentLimit]
Byte 3: [SystemTemp]
Byte 4: [ECUVoltage]
Byte 5: [SystemCurrent]
Byte 6-7: [ErrorFlags]
Direction: PDM → ECU | DLC: 8 bytes | Cycle Time: 100ms
Configuration status and system mode information.
| Signal | Bit Position | Length | Unit | Range | Values | Notes |
|---|---|---|---|---|---|---|
| AliveCounter | 0-7 | 8 bits | — | 0-255 | — | Increments per frame, automatically overflows |
| SpeedUnits | 8-15 | 8 bits | — | 0-1 | 0=Metric, 1=Imperial | Configured speed display units |
| DistanceUnits | 16-23 | 8 bits | — | 0-1 | 0=Metric, 1=Imperial | Configured distance display units |
| AllowData | 24-31 | 8 bits | — | 0-1 | 0=False, 1=True | Data logging permission |
| AllowGPS | 32-39 | 8 bits | — | 0-1 | 0=False, 1=True | GPS feature enabled |
| AllowMotionDetect | 40-47 | 8 bits | — | 0-1 | 0=False, 1=True | Motion detection enabled |
| MotionDeadTime | 48-55 | 8 bits | Minutes | 0-255 | — | Delay before motion detection triggers |
Byte Layout:
Byte 0: [AliveCounter]
Byte 1: [SpeedUnits]
Byte 2: [DistanceUnits]
Byte 3: [AllowData]
Byte 4: [AllowGPS]
Byte 5: [AllowMotionDetect]
Byte 6: [MotionDeadTime]
Byte 7: Reserved
Direction: ECU → PDM | DLC: 8 bytes
Request detailed status for a specific channel.
| Signal | Bit Position | Length | Unit | Range | Notes |
|---|---|---|---|---|---|
| ChannelNumber | 0-7 | 8 bits | — | 1-14 | Which channel to query |
| RESERVED | 8-63 | 56 bits | — | 0 | Unused bytes |
Direction: PDM → ECU | DLC: 8 bytes
Basic channel status including type, current, and current limits.
| Signal | Bit Position | Length | Unit | Range | Values | Notes |
|---|---|---|---|---|---|---|
| FrameIndex | 0-7 | 8 bits | — | 0 | — | Indicates Frame 0 |
| ChannelType | 8-15 | 8 bits | — | 0-5 | 0=Digital, 1=DigitalPWM, 2=AnalogueThreshold, 3=AnalogueScaled, 4=CANDigital, 5=CANPWM | Channel configuration type |
| Enabled | 16-23 | 8 bits | — | 0-1 | 0=OutputOff, 1=OutputOn | Current output state |
| ChannelName | 24-39 | 16 bits | — | 0 | — | 5-bit letters encoded in 2 bytes |
| ChannelCurrent | 40-47 | 8 bits | Amps × 10 | 0-255 | — | Current flowing through channel |
| CurrentLimitLow | 48-55 | 8 bits | Amps × 10 | 0-255 | — | Low current threshold |
| CurrenLimitHigh | 56-63 | 8 bits | Amps × 10 | 0-255 | — | High current threshold |
Direction: PDM → ECU | DLC: 8 bytes
Channel timing and behavior configuration status.
| Signal | Bit Position | Length | Unit | Range | Notes |
|---|---|---|---|---|---|
| FrameIndex | 0-7 | 8 bits | — | 0 | Indicates Frame 1 |
| RetryCount | 8-15 | 8 bits | — | 0 | Retry attempts after fault |
| InrushDelay | 16-47 | 32 bits | Milliseconds | 0 | Startup current limiting delay |
| ActiveHigh | 48-55 | 8 bits | — | 0 | Output polarity (0=Low, 1=High) |
| RunOn | 56-63 | 8 bits | — | 0 | Keep-alive behavior flag |
Direction: PDM → ECU | DLC: 8 bytes
Extended timing parameters.
| Signal | Bit Position | Length | Unit | Range | Notes |
|---|---|---|---|---|---|
| FrameIndex | 0-7 | 8 bits | — | 0 | Indicates Frame 2 |
| RunOnTime | 8-39 | 32 bits | Milliseconds | 0 | Duration to keep output on after disable |
Direction: ECU → PDM | DLC: 8 bytes
Basic channel control: enable/disable and PWM duty cycle.
| Signal | Bit Position | Length | Unit | Range | Notes |
|---|---|---|---|---|---|
| ChannelNumber | 0-7 | 8 bits | — | 1-14 | Target channel |
| Enabled | 8-15 | 8 bits | Bool | 0-1 | Output enable flag (latched in PDM, only one message needed to change state) |
| PWM | 16-23 | 8 bits | Percent | 0-100 | Duty cycle (ignored unless channel is CAN PWM type) |
Description: Basic channel control message for enabling/disabling outputs and setting PWM duty cycle on supported channel types.
Direction: ECU → PDM | DLC: 8 bytes
Channel type and threshold configuration.
| Signal | Bit Position | Length | Unit | Range | Values | Notes |
|---|---|---|---|---|---|---|
| ChannelNumber | 0-7 | 8 bits | — | 1-14 | — | Target channel |
| ChannelType | 8-15 | 8 bits | — | 0-5 | 0=Digital, 1=DigitalPWM, 2=AnalogueThreshold, 3=AnalogueScaled, 4=CANDigital, 5=CANPWM | Channel type selection |
| ChannelName | 16-31 | 16 bits | — | 0 | — | 5-bit letters in 2 bytes |
| CurrentThresholdLow | 24-31 | 8 bits | Amps × 10 | 0-170 | — | Low current fault threshold |
| CurrentThresholdHigh | 32-39 | 8 bits | Amps × 10 | 0-170 | — | High current fault threshold |
| RetryCount | 40-47 | 8 bits | — | 0-10 | — | Number of retry attempts |
| InrushLimit | 48-55 | 8 bits | — | 0-50 | — | Inrush current limit |
| WriteBitMask | 56-63 | 8 bits | — | 0-63 | — | Bitmask for which parameters to save (LSB=ChannelType, MSB=InrushLimit) |
WriteBitMask Details: Only parameters marked as true in this bitmask are observed and saved to EEPROM.
Bit 0: Channel Type
Bit 1: Channel name
Bit 2: Low current fault threshold
Bit 3: High current fault threshold
Bit 4: Retry Count
Bit 5: Inrush limit
Bits 6-7: Reserved
Direction: ECU → PDM | DLC: 8 bytes
Channel timing configuration (inrush delay and run-on behavior).
| Signal | Bit Position | Length | Unit | Range | Notes |
|---|---|---|---|---|---|
| ChannelNumber | 0-7 | 8 bits | — | 0-14 | Target channel |
| InrushDelay | 8-39 | 32 bits | Milliseconds | 0 | Current limit delay during startup |
| ActiveHigh | 40-47 | 8 bits | — | 0 | Output polarity (0=ActiveLow, 1=ActiveHigh) |
| RunOn | 48-55 | 8 bits | — | 0 | Keep-alive mode flag |
| WriteBitMask | 56-63 | 8 bits | — | 0-7 | Bitmask for which parameters to save (LSB=InrushDelay, MSB=RunOn) |
WriteBitMask Details: Only parameters marked as true are observed and saved to EEPROM.
Bit 0: Inrush Delay
Bit 1: Active high
Bit 2: Run On
Bits 3-7: Reserved
Direction: ECU → PDM | DLC: 8 bytes
Extended timing: run-on duration.
| Signal | Bit Position | Length | Unit | Range | Notes |
|---|---|---|---|---|---|
| ChannelNumber | 0-7 | 8 bits | — | 0 | Target channel |
| RunOnTime | 8-39 | 32 bits | Milliseconds | 0 | Duration to keep output on after disable |
| SoftStart | 40-47 | 8 bits | - | 1 | Soft start enable flag |
| SoftStartTime | 48-55 | 8 bits | Seconds | 5 | Soft start time |
| WriteBitMask | 56-63 | 8 bits | — | 0-1 | Bitmask for which parameters to save (LSB=RunOnTime, MSB=SoftStartTime, bits 3-7 reserved) |
WriteBitMask Details: Only parameters marked as true are observed and saved to EEPROM.
Bit 0: Run On Time
Bit 1: Soft start
Bit 2: Soft start time
Bits 3-7: Reserved for future signals
Direction: ECU → PDM | DLC: 8 bytes
System-wide configuration parameters.
| Signal | Bit Position | Length | Unit | Range | Values | Notes |
|---|---|---|---|---|---|---|
| SystemCurrentLimit | 0-7 | 8 bits | Amps | 0-150 | — | Maximum system output current |
| SpeedUnits | 8-15 | 8 bits | — | 0-1 | 0=Metric, 1=Imperial | Display units for speed |
| DistanceUnits | 16-23 | 8 bits | — | 0-1 | 0=Metric, 1=Imperial | Display units for distance |
| AllowData | 24-31 | 8 bits | — | 0 | 0=False, 1=True | Data logging permission |
| AllowGPS | 32-39 | 8 bits | — | 0 | 0=False, 1=True | GPS feature enable |
| AllowMotionDetect | 40-47 | 8 bits | — | 0 | 0=False, 1=True | Motion detection enable |
| MotionDeadTIme | 48-55 | 8 bits | Minutes | 0-255 | — | Delay before motion triggers |
| WriteBitMask | 56-63 | 8 bits | — | 0-255 | — | Bitmask for parameter persistence (LSB=SystemCurrentLimit, MSB=MotionDeadTime) |
WriteBitMask Details: Only parameters marked as true are observed and saved to EEPROM.
Bit 0: System Current Limit
Bit 1: Speed Units
Bit 2: Distance Units
Bit 3: Allow Data
Bit 4: Allow GPS
Bit 5: Allow Motion Detect
Bit 6: Motion Dead Time
Bit 7: Reserved
| Message ID | Name | Direction | Signals | Purpose |
|---|---|---|---|---|
| 0x700 (1792) | ChannelStatusRequest | ECU → PDM | 2 | Query channel status |
| 0x701 (1793) | ChannelStatusResponse | PDM → ECU | Multi-frame | Return channel details |
| 0x720 (1824) | SystemStatus1 | PDM → ECU | 6 | System power & temperature |
| 0x721 (1825) | SystemStatus2 | PDM → ECU | 7 | System configuration state |
| 0x730 (1840) | SystemConfig | ECU → PDM | 8 | Configure system parameters |
| 0x740 (1856) | ChannelConfigF0 | ECU → PDM | 3 | Basic channel control |
| 0x741 (1857) | ChannelConfigF1 | ECU → PDM | 8 | Channel type & thresholds |
| 0x742 (1858) | ChannelConfigF2 | ECU → PDM | 5 | Channel timing config |
| 0x743 (1859) | ChannelConfigF3 | ECU → PDM | 5 | Channel run-on duration & soft start |
Configuration messages (ChannelConfigF0-F3, SystemConfig) use bitmasks to specify which parameters should be persisted to the PDM's EEPROM. Always set the appropriate bits for parameters you intend to modify—unmarked parameters will be ignored.
The AliveCounter signal in SystemStatus messages increments with each transmission and automatically wraps around. Use this for:
Current measurements are transmitted as Amps × 10. For example, a signal value of 25 represents 2.5 Amps.
Valid channel numbers are 1-14 (system reserves channel 0). Always validate before sending control messages.
Written in AvaloniaUI for C#.NET, Cortex is the configuration utility for SynapsePDM which uses the USB interface/virtual COM port of the STM32.
The utility allows you to connect and configure the controller.

SynapsePDM hardware is licensed under CERN-OHL-S v2. SynapsePDM firmware and the Cortex application are licensed under the GNU GPL 3.0.
This device is intended for MOTORSPORT, OFF-ROAD, AND EXPERIMENTAL USE ONLY.
DO NOT use this device in any vehicle operated on public roads.
This product is experimental, unverified, and may contain defects. By using this product, you assume all risks. The authors and contributors disclaim all warranties and are not liable for any damages arising from use of this product.
Please download and read the full disclaimer.