Configure GPIO 16 as power button on Pi and update ATtiny firmware to toggle PA2 on RIGHT+ENTER
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user