INF2004_Labs/lab_3/lab_3.c

136 lines
3.8 KiB
C

/**
* 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 <stdio.h>
#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();
}
}