From 596f06b0cade4b798b80764bc21396d0b4ab60a9 Mon Sep 17 00:00:00 2001 From: lurenaud Date: Sun, 31 May 2026 15:45:25 +0200 Subject: [PATCH] Configure GPIO 16 as power button on Pi and update ATtiny firmware to toggle PA2 on RIGHT+ENTER --- Arduino/LIN_to_IR/LIN_to_IR.cpp | 96 +++++++++++++++++---------------- Raspberry/config.txt | 2 +- 2 files changed, 52 insertions(+), 46 deletions(-) diff --git a/Arduino/LIN_to_IR/LIN_to_IR.cpp b/Arduino/LIN_to_IR/LIN_to_IR.cpp index 0bd050c..32f429e 100644 --- a/Arduino/LIN_to_IR/LIN_to_IR.cpp +++ b/Arduino/LIN_to_IR/LIN_to_IR.cpp @@ -4,6 +4,7 @@ #define IR_ARDUINO_PIN PIN_PA0 // Digital pin 10 #define LED_PIN PIN_PA7 // Digital pin 3 +#define RPI_POWER_PIN PIN_PA2 // GPIO 16 of the RPi is connected to PA2 of the ATtiny #define RX_PIN PIN_PB2 // Digital pin 2 #define TX_PIN PIN_PB0 // Digital pin 0 (Unused dummy pin or LIN TX) @@ -17,34 +18,31 @@ SoftwareSerial LINBusSerial(RX_PIN, TX_PIN); -#if defined(TIM1_COMPA_vect) && !defined(TIMER1_COMPA_vect) - #define TIMER1_COMPA_vect TIM1_COMPA_vect -#endif +void rti_write_byte(uint8_t data) { + // Disable interrupts to ensure precise bit-banging timing + uint8_t oldSREG = SREG; + cli(); -volatile uint16_t rti_tx_buffer = 0xFFFF; -volatile uint8_t rti_tx_bit_count = 0; + // Start bit (LOW) + digitalWrite(RTI_TX_PIN, LOW); + delayMicroseconds(417); // 1 / 2400 baud ≈ 416.67 us -ISR(TIMER1_COMPA_vect) { - if (rti_tx_bit_count > 0) { - uint8_t bit = rti_tx_buffer & 1; - if (bit) { + // 8 Data bits (LSB first) + for (uint8_t i = 0; i < 8; i++) { + if (data & (1 << i)) { digitalWrite(RTI_TX_PIN, HIGH); } else { digitalWrite(RTI_TX_PIN, LOW); } - rti_tx_buffer >>= 1; - rti_tx_bit_count--; + delayMicroseconds(417); } -} -void rti_write_byte(uint8_t data) { - while (rti_tx_bit_count > 0) { - // Wait for the previous byte to finish transmitting - } - noInterrupts(); - rti_tx_buffer = 0x200 | (data << 1); - rti_tx_bit_count = 10; - interrupts(); + // Stop bit (HIGH) + digitalWrite(RTI_TX_PIN, HIGH); + delayMicroseconds(417); + + // Restore interrupts + SREG = oldSREG; } // RC-6 timing constants @@ -153,6 +151,26 @@ uint8_t pending_button = 0; unsigned long pending_button_time = 0; bool button_triggered = false; +// RPi Power control variables and functions +bool power_button_active = false; +unsigned long power_button_start_time = 0; + +void trigger_power_button() { + if (!power_button_active) { + pinMode(RPI_POWER_PIN, OUTPUT); + digitalWrite(RPI_POWER_PIN, LOW); + power_button_active = true; + power_button_start_time = millis(); + } +} + +void update_power_button() { + if (power_button_active && (millis() - power_button_start_time >= 150)) { + pinMode(RPI_POWER_PIN, INPUT); + power_button_active = false; + } +} + void process_button_state(uint8_t active_button) { unsigned long now = millis(); @@ -168,15 +186,7 @@ void process_button_state(uint8_t active_button) { screen_open = !screen_open; rti_byte_index = 0; // Reset byte index to send new sequence immediately } else if (current_button == 9) { - toggle_bit ^= 1; - send_ir_for_button(9, toggle_bit); - last_ir_send_time = now; - } - } else if (current_button == 9) { - // Repeat sleep command if held - if (now - last_ir_send_time >= 250) { - send_ir_for_button(9, toggle_bit); - last_ir_send_time = now; + trigger_power_button(); } } } else { @@ -264,6 +274,9 @@ void setup() { pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); // LED OFF + // Configure RPi power pin (High-Z input initially) + pinMode(RPI_POWER_PIN, INPUT); + // Configure RTI TX pin pinMode(RTI_TX_PIN, OUTPUT); digitalWrite(RTI_TX_PIN, HIGH); // Serial idle is HIGH @@ -277,14 +290,7 @@ void setup() { LINBusSerial.begin(9600); - // Initialize Timer 1 for 2400 Hz CTC interrupts - TCCR1A = 0; - TCCR1B = 0; - TCNT1 = 0; - OCR1A = 3332; // 8,000,000 / (1 * 2400) - 1 - TCCR1B |= (1 << WGM12); // CTC mode - TCCR1B |= (1 << CS10); // Prescaler 1 - TIMSK1 |= (1 << OCIE1A); // Enable interrupt + // No timer initialization needed for bit-banging frame = LinFrame(); last_frame_time = millis(); @@ -293,6 +299,8 @@ void setup() { } void loop() { + update_power_button(); + if (LINBusSerial.available()) { last_lin_activity_time = millis(); if (!is_car_on) { @@ -336,21 +344,19 @@ void loop() { if (now - last_rti_send_time >= 100) { last_rti_send_time = now; - uint8_t byte_to_send = 0; if (screen_open) { + uint8_t byte_to_send = 0; // ON sequence: 0x4C (NTSC), 0x2F (max brightness), 0x83 (execute) if (rti_byte_index == 0) byte_to_send = 0x4C; else if (rti_byte_index == 1) byte_to_send = 0x2F; else byte_to_send = 0x83; + + rti_write_byte(byte_to_send); + rti_byte_index = (rti_byte_index + 1) % 3; } else { - // OFF sequence: 0x46 (OFF), 0x00 (min brightness), 0x83 (execute) - if (rti_byte_index == 0) byte_to_send = 0x46; - else if (rti_byte_index == 1) byte_to_send = 0x00; - else byte_to_send = 0x83; + // Stay completely silent on serial when screen is closed to let it retract/close + rti_byte_index = 0; } - - rti_write_byte(byte_to_send); - rti_byte_index = (rti_byte_index + 1) % 3; } } diff --git a/Raspberry/config.txt b/Raspberry/config.txt index 8871ea5..e1de979 100644 --- a/Raspberry/config.txt +++ b/Raspberry/config.txt @@ -83,7 +83,7 @@ dtparam=i2c_arm=on dtoverlay=gpio-ir,gpio_pin=24 # Keys -#dtoverlay=gpio-key,gpio=21,keycode=116,label="POWER" +dtoverlay=gpio-key,gpio=16,keycode=116,label="POWER" #dtoverlay=gpio-key,gpio=26,keycode=115,label="VOLUME_UP" #dtoverlay=gpio-key,gpio=20,keycode=114,label="VOLUME_DOWN"