Navi: Unterschied zwischen den Versionen

aus Metalab Wiki, dem offenen Zentrum für meta-disziplinäre Magier und technisch-kreative Enthusiasten.
Zur Navigation springenZur Suche springen
 
(37 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 15: Zeile 15:
  
 
* 12 V -> 5 V Anker PowerDrive 2 Auto "Ladegerät" 24W / 4.8A 2-Port USB
 
* 12 V -> 5 V Anker PowerDrive 2 Auto "Ladegerät" 24W / 4.8A 2-Port USB
* [https://www.sparkfun.com/datasheets/GPS/Modules/LS20030~3_datasheet_v1.2.pdf MT3329] GPS Receiver
+
* [https://www.olimex.com/Products/Modules/GPS/MOD-GPS/resources/UBX-G7020_HardwareIntegrationManual_-GPS.G7-HW-10003-_Confidential.pdf U-Blox 7] GPS Receiver
 
* [http://www.atmel.com/images/doc4205.pdf TSS463-AA] VAN Bus Controller
 
* [http://www.atmel.com/images/doc4205.pdf TSS463-AA] VAN Bus Controller
 
* [http://ww1.microchip.com/downloads/en/DeviceDoc/21667f.pdf MCP2551] CAN Line Driver
 
* [http://ww1.microchip.com/downloads/en/DeviceDoc/21667f.pdf MCP2551] CAN Line Driver
Zeile 27: Zeile 27:
  
 
* 12 V -> 5 V Anker Netzteil für Auto: ISO-Stecker, USB
 
* 12 V -> 5 V Anker Netzteil für Auto: ISO-Stecker, USB
* MT3329 GPS Receiver: UART
+
* MT3329 GPS Receiver: UART4
* TSS463-AA VAN Bus Controller: SPI
+
* TSS463-AA VAN Bus Controller: SPI2
 
* MCP2551 CAN Line Driver: UART, aber zwischen TSS463-AA und MCP2551
 
* MCP2551 CAN Line Driver: UART, aber zwischen TSS463-AA und MCP2551
* RDA5807M FM Radio: I²C, Antenne
+
* RDA5807M FM Radio: I²C2, Antenne
 
* TDA7850 4-Kanal-Audio-Verstärker: Cinch, ISO-Stecker
 
* TDA7850 4-Kanal-Audio-Verstärker: Cinch, ISO-Stecker
 
* PT7313E Audio Filter: I²C, Klinke
 
* PT7313E Audio Filter: I²C, Klinke
Zeile 40: Zeile 40:
 
* SPI2: PC19,20,21,22 (on GPIO-1)
 
* SPI2: PC19,20,21,22 (on GPIO-1)
 
* I2C2: PB20, PB21 (on GPIO-1)
 
* I2C2: PB20, PB21 (on GPIO-1)
* ???: PH1..8 mostly missing
 
  
* EINT: PI10..PI13, PI16..PI19 incl. [muxed SPI0, SPI1, UART5, UART6] (on GPIO-2)
+
* maybeEINT: PI17 (pin# 38) (possible: PI10..PI13, PI16..PI19 incl.; prefer: PI16, PI17 [muxed UART2 RTS, CTS]) [muxed SPI0, SPI1, UART5, UART6] (on GPIO-2)
        prefer PI16, PI17 [muxed UART2 RTS, CTS]
 
  
* CAN: PH20, PH21 (on GPIO-3)
+
* CAN: PH20 [pin# 33], PH21 [pin# 35] (on GPIO-3)
 
* PS2: PH12, PH13, PI14, PI15 [muxed with SPI0 CS, SPI1 CS, EINT] (on GPIO-3)
 
* PS2: PH12, PH13, PI14, PI15 [muxed with SPI0 CS, SPI1 CS, EINT] (on GPIO-3)
* maybeEINT: PH0, PH9..PH11, PH14..PH21 incl. [muxed UART3, CSI] (on GPIO-3)
+
* EINT: PH0, PH9..PH11, PH14..PH21 incl. [muxed UART3, CSI] (on GPIO-3) ^^^ best: PH8,9 [pin#11],10,11
        ^^^ best: 8,9,10,11 [but not used!]
 
  
 
* FM In: FMINR, FMINL (on GPIO-4)
 
* FM In: FMINR, FMINL (on GPIO-4)
 
* Line In: LINEINR, LINEINL (on GPIO-4)
 
* Line In: LINEINR, LINEINL (on GPIO-4)
 
* [TV In: TVIN0, TVIN1, TVIN2, TVIN3 (on GPIO-4)]
 
* [TV In: TVIN0, TVIN1, TVIN2, TVIN3 (on GPIO-4)]
 +
 +
* maybe TODO: IR (both CIR and IRDA)
  
 
== Hardware-Fallstricke ==
 
== Hardware-Fallstricke ==
Zeile 61: Zeile 60:
 
* hat möglicherweise eingebauten Verstärker
 
* hat möglicherweise eingebauten Verstärker
 
** Verstärker schwierig zu finden (ist meist außerhalb des Autos)
 
** Verstärker schwierig zu finden (ist meist außerhalb des Autos)
** Phantomspeisung zur Stromversorgung nötig?
+
** Phantomspeisung zur Stromversorgung irgendwo drin?
 
* Buchse? ISO oder DIN? Wahrscheinlich DIN.
 
* Buchse? ISO oder DIN? Wahrscheinlich DIN.
 
* Impedanz? 150 Ω (wahrscheinlich)? 50 Ω (wahrscheinlich nicht)? Antennenanpassung nötig?
 
* Impedanz? 150 Ω (wahrscheinlich)? 50 Ω (wahrscheinlich nicht)? Antennenanpassung nötig?
Zeile 86: Zeile 85:
 
** xgps-Testprogramm
 
** xgps-Testprogramm
  
== Linux 4.4-rc2 ==
+
== Mainline Linux ==
 
* Hardware und Verbindungen müssen im Device-Tree-File eingetragen sein (d.h. eingetragen werden)
 
* Hardware und Verbindungen müssen im Device-Tree-File eingetragen sein (d.h. eingetragen werden)
  
Zeile 100: Zeile 99:
  
 
<pre>
 
<pre>
 +
#include <dt-bindings/pwm/pwm.h>
 +
 
/ {
 
/ {
tss463aa {
+
        pwm_bl: backlight {
compatible = “atmel,tss463aa”;
+
                compatible = "pwm-backlight";
clocks = <&clk_out_a>;
+
                pwms = <&pwm0 0 50000>; /* FIXME settings; FIXME use pwm0_pins_a. */
clock-frequency = <8000000>;
+
                brightness-levels = <0 2 5 7 10 12 15 17 255>; /* FIXME more */
pinctrl-0 = <&clk_out_a_pins_a>;
+
                default-brightness-level = <0>;
pinctrl-names = "default";
+
 
};
+
                pinctrl-names = "default";
 +
                pinctrl-0 = <&bl_enable_pin>;
 +
                enable-gpios = <&pio 7 8 GPIO_ACTIVE_HIGH>; /* FIXME: LCD power: PH8. */
 +
        };
 +
 
 +
        panel: panel {
 +
                compatible = "innolux,at070tn92", "panel-dpi";
 +
                backlight = <&pwm_bl>;
 +
                /* TODO power-supply = <&vdd_pnl_reg> */
 +
                #address-cells = <1>;
 +
                #size-cells = <0>;
 +
                port@0 {
 +
                        reg = <0>;
 +
                        #address-cells = <1>;
 +
                        #size-cells = <0>;
 +
                        panel_input: endpoint {
 +
                                reg = <0>;
 +
                                remote-endpoint = <&tcon0_out_lcd>;
 +
                        };
 +
                };
 +
        };
 +
};
 +
 
 +
&pio {
 +
  ...
 +
        bl_enable_pin: bl_enable_pin@0 {
 +
                pins = "PH8";
 +
                function = "gpio_out";
 +
        };
 +
        lcd_rgb888_pins: lcd-rgb888 {
 +
                pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7",
 +
                        "PD8", "PD9", "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
 +
                        "PD16", "PD17", "PD18", "PD19", "PD20", "PD21", "PD22", "PD23",
 +
                        "PD24", "PD25", "PD26", "PD27";
 +
                function = "lcd0";
 +
        };
 
};
 
};
  
Zeile 114: Zeile 150:
 
pinctrl-0 = <&uart4_pins_a>;
 
pinctrl-0 = <&uart4_pins_a>;
 
status = “okay”;
 
status = “okay”;
 +
};
 +
 +
tss463aa_clock_source: oscillator {
 +
        #clock-cells = <0>;
 +
        compatible = "fixed-clock";
 +
        clock-frequency = <4000000>;
 
};
 
};
  
Zeile 119: Zeile 161:
 
status = “okay”;
 
status = “okay”;
 
pinctrl-names = “default”;
 
pinctrl-names = “default”;
pinctrl-0 = <&spi2_pins_a>;
+
pinctrl-0 = <&spi2_pins_a>, <&spi2_cs0_pins_a>;
 
van0: tss463aa@1 {
 
van0: tss463aa@1 {
 
compatible = “atmel,tss463aa”;
 
compatible = “atmel,tss463aa”;
 
reg = <0>;
 
reg = <0>;
 +
                interrupt-parent = <&pio>;
 +
                interrupts = <8 10 IRQ_TYPE_LEVEL_LOW>; /* PI10 / EINT22 */  /* TODO specify as gpio-in */
 +
                interrupt-names = "activity";
 
spi-max-frequency = <4000000>;
 
spi-max-frequency = <4000000>;
 
spi-cpol;
 
spi-cpol;
 
spi-cpha;
 
spi-cpha;
 +
                clocks = <&tss463aa_clock_source>;
 +
                tss463aa,diagnosis-mode = <0>;
 
};
 
};
 
};
 
};
Zeile 137: Zeile 184:
 
&codec {
 
&codec {
 
status = “okay”;
 
status = “okay”;
 +
};
 +
 +
/* touchscreen */
 +
&rtp {
 +
        allwinner,ts-attached;
 +
        #thermal-sensor-cells = <0>;
 +
        /* sensitive/noisy touch panel */
 +
        allwinner,tp-sensitive-adjust = <0>;
 +
        allwinner,filter-type = <3>;
 +
};
 +
 +
&pwm {
 +
        pinctrl-names = "default";
 +
        pinctrl-0 = <&pwm0_pins_a>, <&pwm1_pins_a>;
 +
        status = "okay";
 +
};
 +
 +
&tcon0 {
 +
        pinctrl-names = "default";
 +
        pinctrl-0 = <&lcd_rgb888_pins>;
 +
        status = "okay";
 +
};
 +
 +
&tcon0_out {
 +
        tcon0_out_lcd: endpoint@0 {
 +
                reg = <0>;
 +
                remote-endpoint = <&panel_input>;
 +
        };
 
};
 
};
 
</pre>
 
</pre>
Zeile 157: Zeile 232:
 
== User-Space ==
 
== User-Space ==
  
* Zugriff auf SPI über spidev
+
* Zugriff auf SPI über spidev (Später: Selbstgeschriebenes CAN-Kernel-Modul)
 
** Linux-Source muss editiert werden., damit /dev/-Datei erscheint
 
** Linux-Source muss editiert werden., damit /dev/-Datei erscheint
 
** es existieren verschiedene Headerfiles für SPI. Vorsicht! linux-headers-Paket im User Space installieren&verwenden, nicht /usr/src/linux/include
 
** es existieren verschiedene Headerfiles für SPI. Vorsicht! linux-headers-Paket im User Space installieren&verwenden, nicht /usr/src/linux/include
Zeile 180: Zeile 255:
 
= TODO =
 
= TODO =
  
* besser: Interrupts im Kernel abarbeiten
+
* SocketCAN-Netzwerkmodul für VAN-Bus: https://github.com/daym/linux/blob/van/drivers/net/can/spi/tss463aa.c
** Vorteil: diese werden auch abgearbeitet wenn das User-Space-Programm gerade kaputt ist und wir stellen so sicher, dass das auslösende Gerät weiterarbeiten kann.
+
 
* noch besser: SocketCAN-Netzwerkmodul für VAN-Bus schreiben
+
= VAN Bus Monitoring Ergebnisse =
** einfachste Vorlage: vcan
+
 
 +
== Participiants (Arbitration IDs) on the Bus (Peugeot 307 XS) ==
 +
 
 +
<pre>
 +
0x4d4/RTR Radio Settings
 +
0x4ec/RTR Track Time
 +
0x4fc/RTR Lights in Instrument Array
 +
0x524/RTR Car Status 2
 +
0x554/RTR RDS Repeater
 +
0x664/RTR Middle Console Buttons
 +
0x824/RTR Speed and RPM
 +
0x8a4/RTR Display
 +
0x8c4/RTR Radio Buttons
 +
0x9c4/RTR Steering Wheel Radio Remote Control Stick
 +
0xe24/RTR VIN
 +
</pre>
 +
 
 +
=== 0x4fc/RTR Lights in Instrument Array ===
 +
 
 +
* Offset 5:
 +
** Mask 0x80: Headlight low
 +
** Mask 0x40: Headlight high
 +
** Mask 0x20: Front fog lights
 +
** Mask 0x10: Rear fog lights
 +
** Mask 0x08: Right turn indicator
 +
** Mask 0x04: Left turn indicator
 +
 
 +
=== 0x664/RTR Middle Console Buttons ===
 +
 
 +
* Offset 0:
 +
** Mask 0x02: Hazard
 +
* Offset 2:
 +
** Mask 0x40: Door lock
 +
** Mask 0x0F: Brightness
 +
* Offset 3:
 +
** Mask 0x02: ESP off
 +
 
 +
=== 0x824/RTR Speed and RPM ===
 +
 
 +
* Offset 0 .. 1: RPM
 +
** X/10 if X != 0xFFFF else None
 +
* Offset 2 .. 3: Speed
 +
** X/100 if X != 0xFFFF else None
 +
* Offset 4 .. 6: Sequence
 +
 
 +
=== 0x8a4/RTR Display ===
 +
 
 +
* Offset 0:
 +
** Mask 0x0F: Backlight intensity
 +
** Mask 0x80: ???
 +
 
 +
=== 0x9c4/RTR Steering Wheel Radio Remote Control Stick ===
 +
 
 +
* Offset 0: "Buttons"
 +
** Mask 0x02: Source (outermost right button)
 +
** Mask 0x04: Decrease volume
 +
** Mask 0x08: Increase volume
 +
** Mask 0x40: Seek- (bottom)
 +
** Mask 0x80: Seek+ (top)
  
 
[[Kategorie:Projekte]]
 
[[Kategorie:Projekte]]

Aktuelle Version vom 6. September 2018, 18:53 Uhr

Ziele

  • Linux-Navigationsgerät fürs Auto bauen mit ausschließlich Free Software.
  • Einarbeiten in UART, SPI, I²C, SPI mit Linux >= 4.4
  • Spaß haben

Hardware, abstrakt

  • Stromversorgung
  • GPS
  • FM-Radio
  • VAN Bus Controller für Display, Tasten etc

Hardware, konkret

Verbindungen

  • 12 V -> 5 V Anker Netzteil für Auto: ISO-Stecker, USB
  • MT3329 GPS Receiver: UART4
  • TSS463-AA VAN Bus Controller: SPI2
  • MCP2551 CAN Line Driver: UART, aber zwischen TSS463-AA und MCP2551
  • RDA5807M FM Radio: I²C2, Antenne
  • TDA7850 4-Kanal-Audio-Verstärker: Cinch, ISO-Stecker
  • PT7313E Audio Filter: I²C, Klinke
  • A20-OLinuXIno-LIME2 Host Computer: Ethernet

A20 Pinout

  • UART4: PG10,PG11 (on GPIO-1)
  • SPI2: PC19,20,21,22 (on GPIO-1)
  • I2C2: PB20, PB21 (on GPIO-1)
  • maybeEINT: PI17 (pin# 38) (possible: PI10..PI13, PI16..PI19 incl.; prefer: PI16, PI17 [muxed UART2 RTS, CTS]) [muxed SPI0, SPI1, UART5, UART6] (on GPIO-2)
  • CAN: PH20 [pin# 33], PH21 [pin# 35] (on GPIO-3)
  • PS2: PH12, PH13, PI14, PI15 [muxed with SPI0 CS, SPI1 CS, EINT] (on GPIO-3)
  • EINT: PH0, PH9..PH11, PH14..PH21 incl. [muxed UART3, CSI] (on GPIO-3) ^^^ best: PH8,9 [pin#11],10,11
  • FM In: FMINR, FMINL (on GPIO-4)
  • Line In: LINEINR, LINEINL (on GPIO-4)
  • [TV In: TVIN0, TVIN1, TVIN2, TVIN3 (on GPIO-4)]
  • maybe TODO: IR (both CIR and IRDA)

Hardware-Fallstricke

FM-Antenne

  • vorhanden am Auto etc
  • hat möglicherweise eingebauten Verstärker
    • Verstärker schwierig zu finden (ist meist außerhalb des Autos)
    • Phantomspeisung zur Stromversorgung irgendwo drin?
  • Buchse? ISO oder DIN? Wahrscheinlich DIN.
  • Impedanz? 150 Ω (wahrscheinlich)? 50 Ω (wahrscheinlich nicht)? Antennenanpassung nötig?

EMI

  • ElectroMagnetic Interference
  • unsere Hardware stellt viele Hochfrequenzstörquellen dar
  • Störung von außen gibt’s vielleicht auch
  • Audioverstärker sollte nicht gestört werden
  • Faradayscher Käfig nötig (1 oder mehr)
    • Filterplatte mit Masse
    • min. 2 Lagen

Ghost in the Machine

  • Pull-Up-Widerstände sind auf den Kommunikationsleitungen notwendig, damit kein Blödsinn gesendet/empfangen wird, wenn ein Gerät ohne Strom ist

Software

Mainline Linux

  • Hardware und Verbindungen müssen im Device-Tree-File eingetragen sein (d.h. eingetragen werden)
  • Device Tree
    • offiziell sollten für Peripherie Device-Tree-Overlays verwendet werden (wird zusätzlich zum Board-Device-Tree-File geladen):
      • Spezialsyntax __overlay__ { … }
      • dtc -@ xxx.dts
      • Linux Command Line: dtoverlay=xxx.dtb beim Booten
      • geht nicht in Debian, weil "/plugin/" unbekannt
    • Hack: Board-File editieren
      • bei unserem Host: sun7i-a20-olinuxino-lime2.dts
      • folgendes hinten anhängen und dann: make dtbs und die entstehende Datei sun7i-a20-olinuxino-lime2.dtb dem Bootvorgang zur Verfügung stellen
#include <dt-bindings/pwm/pwm.h>

/ {
        pwm_bl: backlight {
                compatible = "pwm-backlight";
                pwms = <&pwm0 0 50000>; /* FIXME settings; FIXME use pwm0_pins_a. */
                brightness-levels = <0 2 5 7 10 12 15 17 255>; /* FIXME more */
                default-brightness-level = <0>;

                pinctrl-names = "default";
                pinctrl-0 = <&bl_enable_pin>;
                enable-gpios = <&pio 7 8 GPIO_ACTIVE_HIGH>; /* FIXME: LCD power: PH8. */
        };

        panel: panel {
                compatible = "innolux,at070tn92", "panel-dpi";
                backlight = <&pwm_bl>;
                /* TODO power-supply = <&vdd_pnl_reg> */
                #address-cells = <1>;
                #size-cells = <0>;
                port@0 {
                        reg = <0>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        panel_input: endpoint {
                                reg = <0>;
                                remote-endpoint = <&tcon0_out_lcd>;
                        };
                };
        };
};

&pio {
   ...
        bl_enable_pin: bl_enable_pin@0 {
                pins = "PH8";
                function = "gpio_out";
        };
        lcd_rgb888_pins: lcd-rgb888 {
                pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", 
                        "PD8", "PD9", "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
                        "PD16", "PD17", "PD18", "PD19", "PD20", "PD21", "PD22", "PD23",
                        "PD24", "PD25", "PD26", "PD27";
                function = "lcd0";
        };
};

&uart4 {
	pinctrl-names = “default”;
	pinctrl-0 = <&uart4_pins_a>;
	status = “okay”;
};

tss463aa_clock_source: oscillator {
        #clock-cells = <0>;
        compatible = "fixed-clock";
        clock-frequency = <4000000>;
};

&spi2 {
	status = “okay”;
	pinctrl-names = “default”;
	pinctrl-0 = <&spi2_pins_a>, <&spi2_cs0_pins_a>;
	van0: tss463aa@1 {
		compatible = “atmel,tss463aa”;
		reg = <0>;
                interrupt-parent = <&pio>;
                interrupts = <8 10 IRQ_TYPE_LEVEL_LOW>; /* PI10 / EINT22 */  /* TODO specify as gpio-in */
                interrupt-names = "activity";
		spi-max-frequency = <4000000>;
		spi-cpol;
		spi-cpha;
                clocks = <&tss463aa_clock_source>;
                tss463aa,diagnosis-mode = <0>;
	};
};

&i2c2 {
	pinctrl-names = “default”;
	pinctrl-0 = <&i2c2_pins_a>;
	status = “okay”;
};

&codec {
	status = “okay”;
};

/* touchscreen */
&rtp {
        allwinner,ts-attached;
        #thermal-sensor-cells = <0>;
        /* sensitive/noisy touch panel */
        allwinner,tp-sensitive-adjust = <0>;
        allwinner,filter-type = <3>;
};

&pwm {
        pinctrl-names = "default";
        pinctrl-0 = <&pwm0_pins_a>, <&pwm1_pins_a>;
        status = "okay";
};

&tcon0 {
        pinctrl-names = "default";
        pinctrl-0 = <&lcd_rgb888_pins>;
        status = "okay";
};

&tcon0_out {
        tcon0_out_lcd: endpoint@0 {
                reg = <0>;
                remote-endpoint = <&panel_input>;
        };
};
  • Für spidev in Linux drivers/spi/spidev.c editieren:
    • das Array spidev_dt_ids erweitern um
	{ .compatible = “atmel,tss463aa” },
    • vor dem (existierenden) Sentinel
	{},
    • dann ausführen:
make modules
make modules_install

User-Space

  • Zugriff auf SPI über spidev (Später: Selbstgeschriebenes CAN-Kernel-Modul)
    • Linux-Source muss editiert werden., damit /dev/-Datei erscheint
    • es existieren verschiedene Headerfiles für SPI. Vorsicht! linux-headers-Paket im User Space installieren&verwenden, nicht /usr/src/linux/include
  • Zugriff auf I2C funktioniert auch so
  • Zugriff auf UART funktioniert auch so
  • Interrupts (EINTxx):
    • /sys/class/gpioXXX/edge
    • /sys/class/gpioXXX/uevent
    • poll() oder select() auf errors

http://svn.nomike.com/playground/trunk/Navi/

Softwarekonfiguration

http://www.catb.org/gpsd/gpsd-time-service-howto.html

Linux Kernel:

   CONFIG_PPS=y
   CONFIG_PPS_CLIENT_LDISC=y

TODO

VAN Bus Monitoring Ergebnisse

Participiants (Arbitration IDs) on the Bus (Peugeot 307 XS)

0x4d4/RTR Radio Settings
0x4ec/RTR Track Time
0x4fc/RTR Lights in Instrument Array
0x524/RTR Car Status 2
0x554/RTR RDS Repeater
0x664/RTR Middle Console Buttons
0x824/RTR Speed and RPM
0x8a4/RTR Display
0x8c4/RTR Radio Buttons
0x9c4/RTR Steering Wheel Radio Remote Control Stick
0xe24/RTR VIN

0x4fc/RTR Lights in Instrument Array

  • Offset 5:
    • Mask 0x80: Headlight low
    • Mask 0x40: Headlight high
    • Mask 0x20: Front fog lights
    • Mask 0x10: Rear fog lights
    • Mask 0x08: Right turn indicator
    • Mask 0x04: Left turn indicator

0x664/RTR Middle Console Buttons

  • Offset 0:
    • Mask 0x02: Hazard
  • Offset 2:
    • Mask 0x40: Door lock
    • Mask 0x0F: Brightness
  • Offset 3:
    • Mask 0x02: ESP off

0x824/RTR Speed and RPM

  • Offset 0 .. 1: RPM
    • X/10 if X != 0xFFFF else None
  • Offset 2 .. 3: Speed
    • X/100 if X != 0xFFFF else None
  • Offset 4 .. 6: Sequence

0x8a4/RTR Display

  • Offset 0:
    • Mask 0x0F: Backlight intensity
    • Mask 0x80: ???

0x9c4/RTR Steering Wheel Radio Remote Control Stick

  • Offset 0: "Buttons"
    • Mask 0x02: Source (outermost right button)
    • Mask 0x04: Decrease volume
    • Mask 0x08: Increase volume
    • Mask 0x40: Seek- (bottom)
    • Mask 0x80: Seek+ (top)