summaryrefslogtreecommitdiff
path: root/ButtonHandler/ButtonHandler.cpp
blob: 279fc5b5b9128772daa036ff16d5667c14831309 (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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "ButtonHandler.h"

#define signal (int32_t)0xA0

typedef enum {
    b_none = 0,
    b_sw1_fall,
    b_sw1_rise,
    b_sw2_fall,
    b_sw2_rise
} InternalButtonEvent;

InternalButtonEvent event = b_none;
bool check_sw1 = false;

void b_worker(void const* argument) {
    ButtonHandler* b = (ButtonHandler*)argument;
    osEvent e;

    while (true) {
        e = Thread::signal_wait(signal, 250);
        if (e.status == osEventSignal) {
            switch (event) {
                case b_sw1_fall:
                    if (! b->_sw1_running) {
                        check_sw1 = true;
                        b->_sw1_running = true;
                        b->_sw1_timer.reset();
                        b->_sw1_timer.start();
                    }
                    break;
                
                case b_sw1_rise:
                    if (b->_sw1_running) {
                        check_sw1 = false;
                        b->_sw1_running = false;
                        b->_sw1_timer.stop();
                        b->_sw1_time = b->_sw1_timer.read_ms();

                        if (b->_sw1_time > b->_debounce_time) {
                            b->_event = ButtonHandler::sw1_press;
                            osSignalSet(b->_main, buttonSignal);
                        }
                    }
                    break;

                case b_sw2_fall:
                    if (! b->_sw2_running) {
                        b->_sw2_running = true;
                        b->_sw2_timer.reset();
                        b->_sw2_timer.start();
                    }
                    break;

                case b_sw2_rise:
                    if (b->_sw2_running) {
                        b->_sw2_running = false;
                        b->_sw2_timer.stop();
                        b->_sw2_time = b->_sw2_timer.read_ms();

                        if (b->_sw2_time > b->_debounce_time) {
                            b->_event = ButtonHandler::sw2_press;
                            osSignalSet(b->_main, buttonSignal);
                        }
                    }
                    break;

                default:
                    break;
            }
        }

        if (check_sw1) {
            if (b->_sw1_timer.read_ms() > b->_hold_threshold) {
                check_sw1 = false;
                b->_sw1_running = false;
                b->_sw1_timer.stop();
                b->_event = ButtonHandler::sw1_hold;
                osSignalSet(b->_main, buttonSignal);
            }
        }
    }
}

ButtonHandler::ButtonHandler(osThreadId main)
  : _main(main),
    _thread(b_worker, (void*)this),
    _sw1(PA_12),
    _sw2(PA_11),
    _sw1_time(0),
    _sw2_time(0),
    _event(none),
    _debounce_time(20),
    _hold_threshold(500)
{
    // fall handler called on press, rise handler called on release
    _sw1.fall(this, &ButtonHandler::sw1_fall);
    _sw1.rise(this, &ButtonHandler::sw1_rise);
    // need to set mode to PullUp after attaching handlers - default is PullNone (see PinNames.h)
    _sw1.mode(PullUp);

    _sw2.fall(this, &ButtonHandler::sw2_fall);
    _sw2.rise(this, &ButtonHandler::sw2_rise);
    _sw2.mode(PullUp);
}

ButtonHandler::ButtonEvent ButtonHandler::getButtonEvent() {
    ButtonEvent event = _event;
    _event = none;
    return event;
}

void ButtonHandler::sw1_fall() {
    event = b_sw1_fall;
    _thread.signal_set(signal);
    _thread.signal_clr(signal);
}

void ButtonHandler::sw1_rise() {
    event = b_sw1_rise;
    _thread.signal_set(signal);
    _thread.signal_clr(signal);
}

void ButtonHandler::sw2_fall() {
    event = b_sw2_fall;
    _thread.signal_set(signal);
    _thread.signal_clr(signal);
}

void ButtonHandler::sw2_rise() {
    event = b_sw2_rise;
    _thread.signal_set(signal);
    _thread.signal_clr(signal);
}