Integrate RTI screen control and button combinations into LIN_to_IR firmware
This commit is contained in:
+124
-24
@@ -10,10 +10,15 @@
|
||||
#define FAULT_PIN PIN_PB1 // Digital pin 1
|
||||
#define CS_PIN PIN_PB3 // Digital pin 11
|
||||
|
||||
#define RTI_RX_PIN PIN_PA4 // Digital pin 6 (Unused/LED COM)
|
||||
#define RTI_TX_PIN PIN_PA5 // Digital pin 5
|
||||
#define MUX_LOGIC_SEL_PIN PIN_PA6 // Digital pin 4
|
||||
|
||||
#define SYN_FIELD 0x55
|
||||
#define SWM_ID 0x20
|
||||
|
||||
SoftwareSerial LINBusSerial(RX_PIN, TX_PIN);
|
||||
SoftwareSerial rtiSerial(RTI_RX_PIN, RTI_TX_PIN);
|
||||
|
||||
// RC-6 timing constants
|
||||
// 1 time unit (1t) = 444us
|
||||
@@ -86,6 +91,7 @@ uint32_t get_mce_code(uint8_t button) {
|
||||
case 5: return 0x800f0422; // ENTER / OK
|
||||
case 6: return 0x800f0423; // BACK
|
||||
case 7: return 0x800f0410; // Volume Up (Shutdown)
|
||||
case 9: return 0x800f0411; // Volume Down (Sleep)
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
@@ -109,33 +115,70 @@ unsigned long last_ir_send_time = 0;
|
||||
unsigned long last_lin_activity_time = 0;
|
||||
bool is_car_on = false;
|
||||
|
||||
// RTI Screen variables
|
||||
bool screen_open = true; // Screen should open at startup
|
||||
unsigned long last_rti_send_time = 0;
|
||||
uint8_t rti_byte_index = 0;
|
||||
|
||||
// Debouncing variables for combinations
|
||||
bool combination_active = false;
|
||||
uint8_t pending_button = 0;
|
||||
unsigned long pending_button_time = 0;
|
||||
bool button_triggered = false;
|
||||
|
||||
void process_button_state(uint8_t active_button) {
|
||||
unsigned long now = millis();
|
||||
|
||||
if (active_button != 0) {
|
||||
if (current_button == 0) {
|
||||
// Button was just pressed!
|
||||
current_button = active_button;
|
||||
toggle_bit ^= 1; // Toggle bit alternates on each new press
|
||||
send_ir_for_button(current_button, toggle_bit);
|
||||
last_ir_send_time = now;
|
||||
} else if (current_button == active_button) {
|
||||
// Button is being held down!
|
||||
// Send repeat code every 250ms
|
||||
if (now - last_ir_send_time >= 250) {
|
||||
send_ir_for_button(current_button, toggle_bit);
|
||||
last_ir_send_time = now;
|
||||
if (active_button >= 8) {
|
||||
// Combinations trigger immediately without delay
|
||||
if (current_button != active_button) {
|
||||
current_button = active_button;
|
||||
pending_button = 0;
|
||||
button_triggered = true;
|
||||
|
||||
if (current_button == 8) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// A different button was pressed!
|
||||
current_button = active_button;
|
||||
toggle_bit ^= 1;
|
||||
send_ir_for_button(current_button, toggle_bit);
|
||||
last_ir_send_time = now;
|
||||
// Single buttons: delay by 80ms to check if a combination is being pressed
|
||||
if (pending_button != active_button) {
|
||||
pending_button = active_button;
|
||||
pending_button_time = now;
|
||||
button_triggered = false;
|
||||
} else if (!button_triggered) {
|
||||
if (now - pending_button_time >= 80) {
|
||||
current_button = active_button;
|
||||
button_triggered = true;
|
||||
toggle_bit ^= 1;
|
||||
send_ir_for_button(current_button, toggle_bit);
|
||||
last_ir_send_time = now;
|
||||
}
|
||||
} else {
|
||||
// Button was already triggered and is being held down
|
||||
if (now - last_ir_send_time >= 250) {
|
||||
send_ir_for_button(current_button, toggle_bit);
|
||||
last_ir_send_time = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Idle state
|
||||
current_button = 0;
|
||||
pending_button = 0;
|
||||
button_triggered = false;
|
||||
}
|
||||
|
||||
last_frame_time = now;
|
||||
@@ -153,14 +196,36 @@ void handle_frame() {
|
||||
uint8_t d0 = frame.get_byte(1);
|
||||
uint8_t d1 = frame.get_byte(2);
|
||||
|
||||
bool enter_pressed = (d1 & 0x08) != 0;
|
||||
bool back_pressed = (d1 & 0x01) != 0;
|
||||
bool right_pressed = (d0 & 0x08) != 0;
|
||||
|
||||
uint8_t active_button = 0;
|
||||
|
||||
if (d0 & 0x01) active_button = 1; // UP
|
||||
else if (d0 & 0x02) active_button = 2; // DOWN
|
||||
else if (d0 & 0x04) active_button = 3; // LEFT
|
||||
else if (d0 & 0x08) active_button = 4; // RIGHT
|
||||
else if (d1 & 0x08) active_button = 5; // ENTER / OK
|
||||
else if (d1 & 0x01) active_button = 6; // BACK
|
||||
if (back_pressed && enter_pressed) {
|
||||
active_button = 8; // Special combination: BACK + ENTER (Toggle Screen)
|
||||
combination_active = true;
|
||||
} else if (right_pressed && enter_pressed) {
|
||||
active_button = 9; // Special combination: RIGHT + ENTER (Sleep Raspberry)
|
||||
combination_active = true;
|
||||
} else if (combination_active) {
|
||||
// A combination was active, but it's no longer detected as a combination.
|
||||
// If any buttons are still pressed, ignore them to prevent false single button triggering.
|
||||
if (enter_pressed || back_pressed || right_pressed || (d0 & 0x01) || (d0 & 0x02) || (d0 & 0x04)) {
|
||||
active_button = 0; // Ignore
|
||||
} else {
|
||||
combination_active = false; // All buttons released, clear flag
|
||||
active_button = 0;
|
||||
}
|
||||
} else {
|
||||
// Normal single button decoding
|
||||
if (d0 & 0x01) active_button = 1; // UP
|
||||
else if (d0 & 0x02) active_button = 2; // DOWN
|
||||
else if (d0 & 0x04) active_button = 3; // LEFT
|
||||
else if (d0 & 0x08) active_button = 4; // RIGHT
|
||||
else if (d1 & 0x08) active_button = 5; // ENTER / OK
|
||||
else if (d1 & 0x01) active_button = 6; // BACK
|
||||
}
|
||||
|
||||
process_button_state(active_button);
|
||||
}
|
||||
@@ -172,6 +237,10 @@ void setup() {
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, LOW); // LED OFF
|
||||
|
||||
// Mux logic select pin
|
||||
pinMode(MUX_LOGIC_SEL_PIN, OUTPUT);
|
||||
digitalWrite(MUX_LOGIC_SEL_PIN, HIGH);
|
||||
|
||||
// Enable MCP2004
|
||||
pinMode(CS_PIN, OUTPUT);
|
||||
digitalWrite(CS_PIN, HIGH);
|
||||
@@ -180,9 +249,12 @@ void setup() {
|
||||
digitalWrite(FAULT_PIN, HIGH);
|
||||
|
||||
LINBusSerial.begin(9600);
|
||||
rtiSerial.begin(2400);
|
||||
|
||||
frame = LinFrame();
|
||||
last_frame_time = millis();
|
||||
last_lin_activity_time = millis();
|
||||
last_rti_send_time = millis();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@@ -190,6 +262,7 @@ void loop() {
|
||||
last_lin_activity_time = millis();
|
||||
if (!is_car_on) {
|
||||
is_car_on = true;
|
||||
screen_open = true; // Automatically open screen when car turns back on
|
||||
}
|
||||
b = LINBusSerial.read();
|
||||
n = frame.num_bytes();
|
||||
@@ -207,15 +280,42 @@ void loop() {
|
||||
|
||||
// Timeout: if no LIN frames received for 200ms, assume no button is pressed
|
||||
if (millis() - last_frame_time > 200) {
|
||||
current_button = 0;
|
||||
if (pending_button == 0) {
|
||||
current_button = 0;
|
||||
button_triggered = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Car off detection: if no LIN activity for 5 seconds, send Volume Up to trigger shutdown
|
||||
if (is_car_on && (millis() - last_lin_activity_time > 5000)) {
|
||||
is_car_on = false;
|
||||
screen_open = false; // Close screen when car is off
|
||||
for (int i = 0; i < 3; i++) {
|
||||
send_ir_for_button(7, i & 1);
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
// Send RTI screen serial command byte every 100ms (non-blocking)
|
||||
unsigned long now = millis();
|
||||
if (now - last_rti_send_time >= 100) {
|
||||
last_rti_send_time = now;
|
||||
|
||||
uint8_t byte_to_send = 0;
|
||||
if (screen_open) {
|
||||
// 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;
|
||||
} 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;
|
||||
}
|
||||
|
||||
rtiSerial.write(byte_to_send);
|
||||
rti_byte_index = (rti_byte_index + 1) % 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user