/* * local_control.c * Code related to the local control mode * * Created on: Nov 4, 2025 * Author: sowgro */ #include #include #include #include "GPIO.h" #include "project.h" #include "systick.h" #include "player_actions.h" static int click_count = 0; static uint32_t last_press = 0; static int hold_pending = 0; void handle_press(int pressed); /** * Initialize local control mode (does not enable it) */ void local_control_init() { GPIO_Init(); NVIC_EnableIRQ(EXTI9_5_IRQn); } /** * Logic that should be called constantly from the main loop. */ void local_control_loop() { uint32_t now = systick_get_count(); if (hold_pending) { hold_pending = 0; player_stop(); } if (last_press && now - last_press > 1000) { last_press = 0; switch(click_count) { case 1: if (player_get_state() == PLAYING_STATE) { player_pause(); } else { player_play(); } break; case 2: player_next(); break; } click_count = 0; } } /** * Handles external button press */ void EXTI9_5_IRQHandler() { static int prevStatus = -1; if (~EXTI->PR1 & EXTI_PR1_PIF9) return; EXTI->PR1 |= EXTI_PR1_PIF9; if (project_get_mode() != LOCAL_MODE) return; int status = !!(GPIOA->IDR & GPIO_PIN_9); if (prevStatus == status) return; prevStatus = status; handle_press(status); } /** * Logs button information * @param pressed 1 if the button was just pressed, 0 if the button was just released */ void handle_press(int pressed) { static uint32_t time_down = 0; uint32_t now = systick_get_count(); if (pressed) { time_down = now; } else { putchar(0); // I don't know why but without this it bounces if ((now - time_down) < 1000) { time_down = 0; last_press = now; click_count++; } else { hold_pending = 1; time_down = 0; } } }