Files
VolvoRTI/Arduino/LIN_to_IR

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:

  1. Activity Monitor: The ATtiny monitors LIN bus activity. The Central Electronic Module (CEM) continuously polls the LIN bus when the ignition is on.
  2. Timeout: If no LIN serial data is received for 5 seconds, the ATtiny assumes the car is off.
  3. Shutdown Signal: It transitions the car status to "off" and sends the MCE code 0x800f046f (mapped to KEY_F12) 3 times to ensure transmission reliability.
  4. 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_on back to true).

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.toml on 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

  1. 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.
  2. 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 200ms ensures that if the LIN bus goes quiet, button repeats cease immediately.