#include "ui.h" #include #include "hx8357d.h" #include "main.h" #include "stm32h7a3xx.h" #include "stm32h7xx_hal.h" #include "stm32h7xx_hal_gpio.h" #include "tx_api.h" #include "vehicle.h" #include "leds.h" #define DRS_BUTTON_IDX (6) #define DRS_PRESS_WAIT_CYCLES (10) static int drs_press_buf_cycles = 0; void ui_thread_entry(ULONG _) { GPIO_TypeDef *button_ports[NUM_BUTTONS] = {BTN1_GPIO_Port, BTN2_GPIO_Port, BTN3_GPIO_Port, BTN4_GPIO_Port, BTN5_GPIO_Port, BTN6_GPIO_Port, SW_DRS_GPIO_Port}; uint16_t button_pins[NUM_BUTTONS] = {BTN1_Pin, BTN2_Pin, BTN3_Pin, BTN4_Pin, BTN5_Pin, BTN6_Pin, SW_DRS_Pin}; GPIO_PinState button_states[NUM_BUTTONS] = {GPIO_PIN_RESET}; uint32_t button_press_times[NUM_BUTTONS] = {HAL_GetTick()}; while (1) { int press_event = -1; for (int i = 0; i < NUM_BUTTONS; i++) { GPIO_PinState state = HAL_GPIO_ReadPin(button_ports[i], button_pins[i]); if (state != button_states[i]) { uint32_t now = HAL_GetTick(); if (state == GPIO_PIN_SET && now - button_press_times[i] >= BUTTON_MIN_INTERVAL) { // Button press event! press_event = i; button_press_times[i] = now; ButtonMessage msg = {.kind = UMK_BTN_PRESSED, .number = i}; tx_queue_send(&gui_button_queue, &msg, TX_NO_WAIT); } button_states[i] = state; } } // FIXME: The right button doesn't work :( // if ((press_event == 1 || press_event == 2) && button_states[1] && // button_states[2]) { if (press_event == 1 && button_states[1]) { tx_event_flags_set(&gui_update_events, GUI_UPDATE_NEXT_SCREEN, TX_OR); } if (button_states[DRS_BUTTON_IDX] == GPIO_PIN_SET) { // Set leftmost led to blue to indicate DRS activation drs_press_buf_cycles = DRS_PRESS_WAIT_CYCLES; led_set(0, 0, 0, 255); } if (drs_press_buf_cycles < 0) { // Assume no longer active, turn off led_set(0, 0, 0, 0); } else if (drs_press_buf_cycles >= 0) { drs_press_buf_cycles--; } vehicle_broadcast_buttons(button_states); // Release so other threads can get scheduled tx_thread_sleep(1); } } void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { // This gets called when an edge on one of the encoder pins is detected. static GPIO_PinState last_state[NUM_ENCS * 2] = {GPIO_PIN_RESET}; if (GPIO_Pin == ENC2B_Pin) { // ENC2A and ENC2B share an interrupt line, so the HAL calls this callback // once with each pin. Since we already handled the interrupt once for // ENC2A, we can just ignore it now. } uint16_t pin_a, pin_b; int idx_a, idx_b; ButtonMessage msg; if (GPIO_Pin == ENC1A_Pin || GPIO_Pin == ENC1B_Pin) { pin_a = ENC1A_Pin; pin_b = ENC1B_Pin; idx_a = 0; idx_b = 1; msg.number = 0; } else { pin_a = ENC2A_Pin; pin_b = ENC2B_Pin; idx_a = 2; idx_b = 3; msg.number = 1; } // All encoder pins are on port E GPIO_PinState state_a = HAL_GPIO_ReadPin(GPIOE, pin_a); GPIO_PinState state_b = HAL_GPIO_ReadPin(GPIOE, pin_b); int a_changed = state_a != last_state[idx_a]; int b_changed = state_b != last_state[idx_b]; last_state[idx_a] = state_a; last_state[idx_b] = state_b; if (state_a == GPIO_PIN_SET && state_b == GPIO_PIN_SET) { // Second rising edge, direction depends on which pin changed last if (a_changed && b_changed) { // This shouldn't happen. Ignore this event. return; } else if (a_changed) { msg.kind = UMK_ENC_CCW; } else if (b_changed) { msg.kind = UMK_ENC_CW; } else { // This shouldn't happen. Ignore this event. return; } tx_queue_send(&gui_button_queue, &msg, TX_NO_WAIT); } }