refactor(Debounce, Error handling):
Modified: - Debounce Algorithm - Result Printings - Formatting
This commit is contained in:
parent
8b03fa6fcc
commit
3567d6deb3
106
lab_3/lab_3.c
106
lab_3/lab_3.c
|
@ -1,17 +1,31 @@
|
||||||
/**
|
/**
|
||||||
* Lab 3
|
* Lab 3
|
||||||
* To develop a simple stopwatch that measures time intervals between
|
|
||||||
* button presses.
|
|
||||||
*
|
*
|
||||||
* On pressing the START pseudo-button (GP15),
|
* This is my solution to the lab 3 assignment.
|
||||||
* the stopwatch will begin,
|
* There are multiple structs and enums defined in this file.
|
||||||
* 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
|
* time_struct is used to store the start time and current time for
|
||||||
* reset the elapsed time to zero.
|
* time calculations.
|
||||||
*
|
*
|
||||||
* The START pseudo-button must incorporate a debouncing algorithm.
|
* btn_status struct is used to keep track of the number of times the
|
||||||
|
* button is pressed and released. This is used to implement a debounce
|
||||||
|
* algorithm.
|
||||||
|
*
|
||||||
|
* btn_state enum is used to return the states of the button, used to check
|
||||||
|
* for errors and to return the state of the button.
|
||||||
|
*
|
||||||
|
* This firmware will use GPIO 15 as a pseudo-button (pull-up) and
|
||||||
|
* will start a timer on button press (falling edge) and stop the timer
|
||||||
|
* on button release (rising edge).
|
||||||
|
*
|
||||||
|
* The Timer will print the elapsed time every second as required by the
|
||||||
|
* lab specification.
|
||||||
|
*
|
||||||
|
* The DEBOUNCE_US macro is used to set the debounce delay to 20ms, the value
|
||||||
|
* can be refined to get more accurate results.
|
||||||
|
*
|
||||||
|
* This is made more complex with the use of interrupts, timers and a debounce
|
||||||
|
* algorithm.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -21,21 +35,26 @@
|
||||||
|
|
||||||
#define PSEUDO_BTN 15 // GPIO 15 is the pseudo-button
|
#define PSEUDO_BTN 15 // GPIO 15 is the pseudo-button
|
||||||
#define TIMER_US 1000000 // 1-second delay for repeating timer
|
#define TIMER_US 1000000 // 1-second delay for repeating timer
|
||||||
#define DEBOUNCE_US 100 // 100us debounce time
|
#define DEBOUNCE_US 20000 // 20ms debounce delay
|
||||||
|
|
||||||
struct repeating_timer timer; // Repeating timer
|
struct repeating_timer timer; // Repeating timer
|
||||||
u_int64_t time = 0; // Elapsed time
|
|
||||||
|
|
||||||
typedef enum btn_state { // Button state
|
struct time_struct {
|
||||||
PRESSED = 0,
|
uint64_t start_time;
|
||||||
RELEASED = 1
|
uint64_t current_time;
|
||||||
} btn_state_t;
|
} time_struct = {0, 0};
|
||||||
|
|
||||||
struct btn_status { // Button status
|
struct btn_status { // Button status (Used to implement debounce)
|
||||||
uint btn_pressed;
|
uint btn_pressed;
|
||||||
uint btn_released;
|
uint btn_released;
|
||||||
} btn_status = {0, 0};
|
} btn_status = {0, 0};
|
||||||
|
|
||||||
|
typedef enum btn_state { // Button state (Used as return value)
|
||||||
|
PRESSED = 0,
|
||||||
|
RELEASED = 1,
|
||||||
|
ERROR = -1
|
||||||
|
} btn_state_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback function for repeating timer
|
* Callback function for repeating timer
|
||||||
* This function will print the elapsed time every second as required by the
|
* This function will print the elapsed time every second as required by the
|
||||||
|
@ -44,9 +63,14 @@ struct btn_status { // Button status
|
||||||
* @return True to keep the timer running, false to stop it
|
* @return True to keep the timer running, false to stop it
|
||||||
*/
|
*/
|
||||||
bool elapsed_time_callback (struct repeating_timer *t) {
|
bool elapsed_time_callback (struct repeating_timer *t) {
|
||||||
time++;
|
time_struct.start_time = (time_struct.start_time == 0) ?
|
||||||
// Print elapsed time every second
|
time_us_64() : time_struct.start_time;
|
||||||
printf("Elapsed Time: %llus\n", time);
|
|
||||||
|
time_struct.current_time = time_us_64();
|
||||||
|
|
||||||
|
printf("%llus\n",
|
||||||
|
(time_struct.current_time - time_struct.start_time) / 1000000);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +81,13 @@ bool elapsed_time_callback (struct repeating_timer *t) {
|
||||||
* @return The state of the pseudo-button
|
* @return The state of the pseudo-button
|
||||||
*/
|
*/
|
||||||
btn_state_t get_btn_state () {
|
btn_state_t get_btn_state () {
|
||||||
|
if (btn_status.btn_pressed != 0 || btn_status.btn_released != 0)
|
||||||
|
{
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
u_int64_t start_time = time_us_64();
|
u_int64_t start_time = time_us_64();
|
||||||
|
|
||||||
while (time_us_64() - start_time < DEBOUNCE_US)
|
while (time_us_64() - start_time < DEBOUNCE_US)
|
||||||
{
|
{
|
||||||
if (gpio_get(PSEUDO_BTN))
|
if (gpio_get(PSEUDO_BTN))
|
||||||
|
@ -71,7 +101,7 @@ btn_state_t get_btn_state () {
|
||||||
}
|
}
|
||||||
|
|
||||||
btn_state_t state = (btn_status.btn_pressed > btn_status.btn_released) ?
|
btn_state_t state = (btn_status.btn_pressed > btn_status.btn_released) ?
|
||||||
PRESSED : RELEASED;
|
PRESSED : RELEASED;
|
||||||
|
|
||||||
// Reset btn_status
|
// Reset btn_status
|
||||||
btn_status = (struct btn_status) {0, 0};
|
btn_status = (struct btn_status) {0, 0};
|
||||||
|
@ -89,11 +119,15 @@ btn_state_t get_btn_state () {
|
||||||
void gpio_callback (uint gpio, uint32_t events) {
|
void gpio_callback (uint gpio, uint32_t events) {
|
||||||
btn_state_t btn_state = get_btn_state();
|
btn_state_t btn_state = get_btn_state();
|
||||||
|
|
||||||
|
if (btn_state == ERROR)
|
||||||
|
{
|
||||||
|
printf("Error: Button is bouncing\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (events == GPIO_IRQ_EDGE_FALL && btn_state == PRESSED)
|
if (events == GPIO_IRQ_EDGE_FALL && btn_state == PRESSED)
|
||||||
{
|
{
|
||||||
printf("\n====================================\n");
|
|
||||||
printf("Timer Started\n");
|
printf("Timer Started\n");
|
||||||
printf("====================================\n");
|
|
||||||
|
|
||||||
add_repeating_timer_us(
|
add_repeating_timer_us(
|
||||||
TIMER_US,
|
TIMER_US,
|
||||||
|
@ -101,31 +135,29 @@ void gpio_callback (uint gpio, uint32_t events) {
|
||||||
NULL,
|
NULL,
|
||||||
&timer
|
&timer
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (events == GPIO_IRQ_EDGE_RISE && btn_state == RELEASED)
|
if (events == GPIO_IRQ_EDGE_RISE && btn_state == RELEASED)
|
||||||
{
|
{
|
||||||
cancel_repeating_timer(&timer);
|
if (cancel_repeating_timer(&timer))
|
||||||
|
{
|
||||||
// Print elapsed time and reset
|
printf("Timer Stopped\n");
|
||||||
printf("\n====================================\n");
|
printf("Final Elapsed Time: %llus\n",
|
||||||
printf("Timer Stopped\n");
|
(time_struct.current_time - time_struct.start_time) /
|
||||||
printf("====================================\n");
|
1000000);
|
||||||
printf("Final Elapsed Time: %llus\n", time);
|
}
|
||||||
printf("====================================\n");
|
|
||||||
|
|
||||||
time = 0;
|
|
||||||
|
|
||||||
|
time_struct = (struct time_struct) {0, 0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the pseudo-button (pull-up)
|
* Initialize the pseudo-button (pull-up)
|
||||||
* The pseudo-button is connected to GPIO 15 and is configured as
|
* The pseudo-button is connected to GPIO 15 and
|
||||||
* an input with a pull-up resistor.
|
* is configured as an input with a pull-up resistor.
|
||||||
* The interrupt is configured to trigger on both rising and
|
*
|
||||||
* falling edges.
|
* The interrupt is configured to trigger on both
|
||||||
|
* rising and falling edges.
|
||||||
*/
|
*/
|
||||||
static void btn_init () {
|
static void btn_init () {
|
||||||
gpio_init(PSEUDO_BTN);
|
gpio_init(PSEUDO_BTN);
|
||||||
|
|
Loading…
Reference in New Issue