/** * Lab 3 * To develop a simple stopwatch that measures time intervals between * button presses. * * On pressing the START pseudo-button (GP15), * the stopwatch will begin, * and the elapsed time will be displayed every second on * the Serial Monitor (or equivalent). * * Releasing the START pseudo-button will stop the timer and * reset the elapsed time to zero. * * The START pseudo-button must incorporate a debouncing algorithm. * */ #include #include "pico/stdlib.h" #include "hardware/gpio.h" #define PSEUDO_BTN 15 // GPIO 15 is the pseudo-button #define DELAY_US 1000000 // 1-second delay for repeating timer #define DEBOUNCE_US 100 // 100us debounce delay u_int64_t time = 0; // Elapsed time u_int prev_state = 0; // Previous state of pseudo-button struct repeating_timer timer; // Repeating timer /** * Callback function for repeating timer * This function will print the elapsed time every second as required by the * lab specification. * @param t The timer that triggered the callback * @return True to keep the timer running, false to stop it */ bool elapsed_time_callback (struct repeating_timer *t) { time++; // Print elapsed time every second printf("Elapsed Time: %llus\n", time); return true; } /** * Debounce callback function to check if the current state * is equal to the previous state. * @param id The alarm ID * @param new_event The previous state of the pseudo-button * @return True if the current state is equal to the previous state */ int64_t debounce_callback(alarm_id_t id, void *new_event) { printf("Debounce Callback\n"); return (prev_state == *(uint32_t *)new_event); } /** * Interrupt callback function for pseudo-button (pull-up) * This function will start the timer on button press (falling edge) * and stop the timer on button release. (rising edge) * @param gpio The GPIO pin that triggered the interrupt * @param events The type of interrupt that triggered the callback */ void gpio_callback (uint gpio, uint32_t events) { // Debounce algorithm prev_state = prev_state == 0 ? events : prev_state; // Create an alarm that will trigger after 10ms add_alarm_in_us( DEBOUNCE_US, debounce_callback, &events, false ); // Start timer on button press if (gpio == PSEUDO_BTN && events == GPIO_IRQ_EDGE_FALL) { printf("\n====================================\n"); printf("Timer Started\n"); printf("====================================\n"); add_repeating_timer_us( DELAY_US, elapsed_time_callback, NULL, &timer ); } // Stop timer on button release if (gpio == PSEUDO_BTN && events == GPIO_IRQ_EDGE_RISE) { cancel_repeating_timer(&timer); // Print elapsed time and reset printf("\n====================================\n"); printf("Timer Stopped\n"); printf("====================================\n"); printf("Final Elapsed Time: %llus\n", time); printf("====================================\n"); time = 0; } } /** * Initialize the pseudo-button (pull-up) * The pseudo-button is connected to GPIO 15 and is configured as * an input with a pull-up resistor. * The interrupt is configured to trigger on both rising and * falling edges. */ static void btn_init () { gpio_init(PSEUDO_BTN); gpio_set_dir(PSEUDO_BTN, GPIO_IN); gpio_set_pulls(PSEUDO_BTN, true, false); gpio_set_irq_enabled_with_callback( PSEUDO_BTN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback ); } int main () { stdio_init_all(); btn_init(); while (true) { tight_loop_contents(); } }