summaryrefslogtreecommitdiffstats
path: root/buttons.cpp
blob: bc0ba74c29c170add36023b712aed4bf2adbbb4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <stdio.h>
#include "pico/stdlib.h"

#include "buttons.hpp"
#include "globals.hpp"
#include "hal/api.hpp"
#include "app/app_manager.hpp"
// From pico-watch.c:
extern Api app_api;

//const uint BUTTON_PINS[] = {BUTTON_HOME, BUTTON_SELECT, BUTTON_MODE, BUTTON_UP, BUTTON_DOWN};

// Rising edge and falling edge are "inverted" as every button is set to be pulled up. This means that the falling edge is done when the button is pressed and the rising edge when the button is released.

void gpio_interrupt_cb(uint gpio, uint32_t events) {
    auto delta_since_press = time_since_button_press();

    if (delta_since_press > g_s.button_delay_time) {

        if (app_api.m_interpret_button_press) {
            switch (events) {
                case GPIO_IRQ_EDGE_FALL:
                    if (gpio == BUTTON_HOME && (g_s.foreground_app->app_get_attributes().id != 0)) // Home app
                        app_mgr::app_switch_request(0);
                    else
                        app_mgr::app_btnpressed(g_s.foreground_app, gpio, delta_since_press);
                    break;
                
                case GPIO_IRQ_EDGE_RISE:
                    if (gpio != BUTTON_HOME) // For simplicity's sake
                        app_mgr::app_btnreleased(g_s.foreground_app, gpio, delta_since_press);
                    break;
            }
            
        }

        if (events == GPIO_IRQ_EDGE_FALL)
            app_api.button_last_set(gpio);
        g_s.button_last_pressed_time = to_ms_since_boot(get_absolute_time());
    }
}

unsigned long time_since_button_press() {
    // FIXME: This does not correct overflows
    return to_ms_since_boot(get_absolute_time())-g_s.button_last_pressed_time;
}

void init_buttons() {
    gpio_init(BUTTON_HOME);
    gpio_pull_up(BUTTON_HOME);
    gpio_set_irq_enabled_with_callback(BUTTON_HOME, GPIO_IRQ_EDGE_FALL|GPIO_IRQ_EDGE_RISE, true, &gpio_interrupt_cb);
    gpio_init(BUTTON_SELECT);
    gpio_pull_up(BUTTON_SELECT);
    gpio_set_irq_enabled_with_callback(BUTTON_SELECT, GPIO_IRQ_EDGE_FALL|GPIO_IRQ_EDGE_RISE, true, &gpio_interrupt_cb);
    gpio_init(BUTTON_MODE);
    gpio_pull_up(BUTTON_MODE);
    gpio_set_irq_enabled_with_callback(BUTTON_MODE, GPIO_IRQ_EDGE_FALL|GPIO_IRQ_EDGE_RISE, true, &gpio_interrupt_cb);
    gpio_init(BUTTON_DOWN);
    gpio_pull_up(BUTTON_DOWN);
    gpio_set_irq_enabled_with_callback(BUTTON_DOWN, GPIO_IRQ_EDGE_FALL|GPIO_IRQ_EDGE_RISE, true, &gpio_interrupt_cb);
    gpio_init(BUTTON_UP);
    gpio_pull_up(BUTTON_UP);
    gpio_set_irq_enabled_with_callback(BUTTON_UP, GPIO_IRQ_EDGE_FALL|GPIO_IRQ_EDGE_RISE, true, &gpio_interrupt_cb);

    /* For some reason for loop does not work… TODO
    for (int i=0; i < NUMBER_OF_BUTTONS; i++) {
        uint button = BUTTON_PINS[i];
        gpio_init(button);
        gpio_pull_up(button);
        gpio_set_irq_enabled_with_callback(button, GPIO_IRQ_EDGE_FALL , true, &gpio_interrupt_cb);
    }
    */
    g_s.button_last_pressed_time = to_ms_since_boot(get_absolute_time());
}