4.5 KiB
Volvo LIN-to-IR Controller (ATtiny84)
This project implements the production firmware for the ATtiny84 to interface a Volvo V50 Steering Wheel Module (SWM) LIN bus with a Raspberry Pi running LineageOS (Android).
It decodes steering wheel navigation buttons from the vehicle's LIN bus and translates them into bit-banged RC-6 Mode 6A (MCE) remote control commands sent over a direct wire connection.
Pin Configurations (ATtiny84)
| ATtiny84 Pin | Digital Pin (Arduino) | Function | Description |
|---|---|---|---|
| PA0 | 10 |
IR Output | Direct-wired to Raspberry Pi GPIO 24 |
| PB2 | 2 |
LIN RX | SoftwareSerial RX from MCP2004 RXD |
| PB0 | 0 |
LIN TX | SoftwareSerial TX (Unused dummy) |
| PB1 | 1 |
LIN FAULT/TXE | MCP2004 Fault Detect / Transmit Enable |
| PB3 | 11 |
LIN CS | MCP2004 Chip Select (Active High) |
| PA7 | 3 |
Debug LED | Flash on command transmission |
Key Mapping
The Steering Wheel Module (SWM) sends frames on LIN ID 0x20 with the navigation key statuses. The firmware decodes these and maps them to the following Microsoft MCE remote scancodes:
| Button | LIN Frame Trigger | Active Button Code | MCE Scancode | Action on LineageOS |
|---|---|---|---|---|
| UP | d0 & 0x01 |
1 |
0x800f041e |
Navigate Up |
| DOWN | d0 & 0x02 |
2 |
0x800f041f |
Navigate Down |
| LEFT | d0 & 0x04 |
3 |
0x800f0420 |
Navigate Left |
| RIGHT | d0 & 0x08 |
4 |
0x800f0421 |
Navigate Right |
| ENTER | d1 & 0x08 |
5 |
0x800f0422 |
Select / OK |
| BACK | d1 & 0x01 |
6 |
0x800f0423 |
Back / Exit |
| F12 (Shutdown) | LIN Silent > 5s | 7 |
0x800f046f |
Trigger Shutdown (via MacroDroid) |
Note: In previous revisions, ENTER and BACK were reversed. This has been corrected so that pressing ENTER maps to 0x800f0422 and BACK maps to 0x800f0423.
Car-Off (Shutdown) Detection
To automatically power off the Raspberry Pi when the car is turned off:
- Activity Monitor: The ATtiny monitors LIN bus activity. The Central Electronic Module (CEM) continuously polls the LIN bus when the ignition is on.
- Timeout: If no LIN serial data is received for 5 seconds, the ATtiny assumes the car is off.
- Shutdown Signal: It transitions the car status to "off" and sends the MCE code
0x800f046f(mapped toKEY_F12) 3 times to ensure transmission reliability. - State Protection: It will not send the shutdown command again until the car is turned back on and LIN traffic resumes (which sets
is_car_onback totrue).
Raspberry Pi Configuration
1. Keymap Setup
Remap scancode 0x800f046f to KEY_F12 on the Raspberry Pi:
- The custom TOML configuration is saved at
/data/rc-rc6-mce.tomlon the Pi. - To apply it dynamically:
/vendor/bin/ir-keytable -w /data/rc-rc6-mce.toml
2. MacroDroid Persistence & Trigger
Configure two macros in MacroDroid to manage keymap loading and shutdown:
-
Macro 1: Load Keymap on Boot
- Trigger: Device Boot
- Action: Run Shell Command (Check Run as Root)
/vendor/bin/ir-keytable -w /data/rc-rc6-mce.toml
-
Macro 2: Shutdown on F12
- Trigger: Media / Key Pressed -> Select F12
- Action: Run Shell Command (Check Run as Root)
reboot -p
Protocol and Timing
- Protocol: RC-6 Mode 6A (MCE).
- Time Unit (1T):
444us. - Modulation: None. Timing is bit-banged directly since the output pin is wired directly to the Pi's IR receiver GPIO (which expects demodulated active-low signals).
- Idle (Space):
HIGH(3.3V). - Active Pulse (Mark):
LOW(0V). - Toggle Bit: Alternates state on each new button press, but remains constant for repeated holds.
- Repeat Interval: Holds trigger repeat IR commands sent every
250ms.
Software Architecture
- SoftwareSerial Interrupt Isolation:
Since SoftwareSerial RX interrupts consume about 1ms per byte, they will disrupt the precise microsecond-level timing of bit-banged IR frames. To avoid this, interrupts are disabled (
noInterrupts()) during the 37ms window of IR transmission and re-enabled (interrupts()) immediately afterward. - Release detection:
The SWM continuously transmits frames on the LIN bus. If no button frames are detected or a frame with all 0s is received, the current active button resets to idle. A timeout of
200msensures that if the LIN bus goes quiet, button repeats cease immediately.