aboutsummaryrefslogtreecommitdiffstats
path: root/buttons.cpp
blob: 589619cd07e696b78de0c9445f0abe03a22a956d (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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <stdio.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.

// SDL2 TODO: Implement button support
#ifndef SDL2_BUILD
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());
}

#else // SDL2_BUILD
// this function will have to be called by SDL2 on keyboard/button press
// gpio: button pressed
// events: 0 is when button released and 1 is when button pressed
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 1:
                    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 0:
                    if (gpio != BUTTON_HOME) // For simplicity's sake
                        app_mgr::app_btnreleased(g_s.foreground_app, gpio, delta_since_press);
                    break;
            }

        }

        if (events == 1)
            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
    // std::cout << to_ms_since_boot(get_absolute_time());
    return to_ms_since_boot(get_absolute_time())-g_s.button_last_pressed_time;
}
void init_buttons() {}
#endif