diff --git a/Arduino/LIN_to_IR/LIN_to_IR.cpp b/Arduino/LIN_to_IR/LIN_to_IR.cpp index bfbae71..b3fd158 100644 --- a/Arduino/LIN_to_IR/LIN_to_IR.cpp +++ b/Arduino/LIN_to_IR/LIN_to_IR.cpp @@ -85,6 +85,7 @@ uint32_t get_mce_code(uint8_t button) { case 4: return 0x800f0421; // RIGHT case 5: return 0x800f0422; // ENTER / OK case 6: return 0x800f0423; // BACK + case 7: return 0x800f046f; // F12 (Shutdown) default: return 0; } } @@ -105,6 +106,8 @@ unsigned long last_frame_time = 0; uint8_t current_button = 0; uint8_t toggle_bit = 0; unsigned long last_ir_send_time = 0; +unsigned long last_lin_activity_time = 0; +bool is_car_on = false; void process_button_state(uint8_t active_button) { unsigned long now = millis(); @@ -179,10 +182,15 @@ void setup() { LINBusSerial.begin(9600); frame = LinFrame(); last_frame_time = millis(); + last_lin_activity_time = millis(); } void loop() { if (LINBusSerial.available()) { + last_lin_activity_time = millis(); + if (!is_car_on) { + is_car_on = true; + } b = LINBusSerial.read(); n = frame.num_bytes(); @@ -201,4 +209,13 @@ void loop() { if (millis() - last_frame_time > 200) { current_button = 0; } + + // Car off detection: if no LIN activity for 5 seconds, send F12 to trigger shutdown + if (is_car_on && (millis() - last_lin_activity_time > 5000)) { + is_car_on = false; + for (int i = 0; i < 3; i++) { + send_ir_for_button(7, i & 1); + delay(100); + } + } } diff --git a/Arduino/LIN_to_IR/README.md b/Arduino/LIN_to_IR/README.md index 10aaf4d..904403a 100644 --- a/Arduino/LIN_to_IR/README.md +++ b/Arduino/LIN_to_IR/README.md @@ -27,9 +27,45 @@ The Steering Wheel Module (SWM) sends frames on LIN ID `0x20` with the navigatio | **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: + ```bash + /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**) + ```bash + /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**) + ```bash + reboot -p + ``` + ## Protocol and Timing - **Protocol**: RC-6 Mode 6A (MCE). @@ -46,3 +82,4 @@ The Steering Wheel Module (SWM) sends frames on LIN ID `0x20` with the navigatio 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. + diff --git a/Raspberry/rc-rc6-mce.toml b/Raspberry/rc-rc6-mce.toml new file mode 100644 index 0000000..7e5ec74 --- /dev/null +++ b/Raspberry/rc-rc6-mce.toml @@ -0,0 +1,11 @@ +[[protocols]] +name = "rc-rc6-mce" +protocol = "rc-6" +[protocols.scancodes] +0x800f041e = "KEY_UP" +0x800f041f = "KEY_DOWN" +0x800f0420 = "KEY_LEFT" +0x800f0421 = "KEY_RIGHT" +0x800f0422 = "KEY_OK" +0x800f0423 = "KEY_EXIT" +0x800f046f = "KEY_F12"