Files
VolvoRTI/Arduino/LIN_to_IR/README.md
T

5.7 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
Volume Up (Shutdown) LIN Silent > 5s 7 0x800f0410 Trigger Shutdown (via KeyMapper)

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 0x800f0410 (mapped to KEY_VOLUMEUP) 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 the MCE remote codes 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. KeyMapper Setup

Instead of MacroDroid, KeyMapper is used to intercept the KEY_VOLUMEUP trigger from the direct-wired IR receiver and execute the shutdown command.

To configure KeyMapper completely via command-line:

  • Enable Accessibility Service:
    adb shell settings put secure accessibility_enabled 1
    adb shell settings put secure enabled_accessibility_services io.github.sds100.keymapper/.system.accessibility.MyAccessibilityService
    
  • Grant Do Not Disturb Access (to prevent warnings on volume key mapping):
    adb shell settings put secure enabled_notification_policy_access_packages io.github.sds100.keymapper
    
  • Map Trigger and Action: The preconfigured KeyMapper SQLite database is pushed directly to the device. The Volume Up key is mapped to run the command:
    reboot -p
    

3. Wi-Fi Hotspot Auto-start Setup

To enable the Wi-Fi hotspot (VolvoC70_AndroidAuto with passphrase 123456789) automatically at startup:

  • A boot shell script /system/bin/start_hotspot.sh is defined to wait for boot completion and start the SoftAP.
  • A custom Android init service configuration /system/etc/init/start_hotspot.rc starts it when sys.boot_completed transitions to 1.

Script (/system/bin/start_hotspot.sh):

#!/system/bin/sh
while [ "$(getprop sys.boot_completed)" != "1" ]; do
    sleep 1
done
sleep 5
cmd wifi start-softap VolvoC70_AndroidAuto wpa2 123456789

Init Service (/system/etc/init/start_hotspot.rc):

service start_hotspot /system/bin/sh /system/bin/start_hotspot.sh
    class main
    user root
    group root system wifi
    oneshot
    disabled

on property:sys.boot_completed=1
    start start_hotspot

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.