-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDoorbell.cpp
74 lines (53 loc) · 1.9 KB
/
Doorbell.cpp
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 "Doorbell.hpp"
#define DOORBELL_TASK_NAME "Doorbell task"
#define DOORBELL_TASK_STACK_SIZE 4096
#define DOORBELL_TASK_PRIORITY 2
#define DOORBELL_MIN_RING_INTERVAL 5000
namespace DC {
Doorbell::Doorbell(Pin interruptPin)
: interruptPin(interruptPin), requestTaskTerminate(false) {
this->binarySemaphore = xSemaphoreCreateBinary();
xTaskCreate(
taskRoutine,
DOORBELL_TASK_NAME,
DOORBELL_TASK_STACK_SIZE,
(void*)this,
DOORBELL_TASK_PRIORITY | portPRIVILEGE_BIT,
NULL
);
}
Doorbell::~Doorbell() {
this->stop();
this->requestTaskTerminate = true;
vSemaphoreDelete(this->binarySemaphore);
}
void Doorbell::start() {
pinMode(digitalPinToInterrupt(this->interruptPin), INPUT_PULLUP);
attachInterruptArg(this->interruptPin, isr, (void*)this, FALLING);
}
void Doorbell::stop() {
detachInterrupt(this->interruptPin);
}
/*static*/ void IRAM_ATTR Doorbell::isr(void* arg) {
Doorbell* _this = (Doorbell*)arg;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(_this->binarySemaphore, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
/*static*/ void Doorbell::taskRoutine(void* arg) {
Doorbell* _this = (Doorbell*)arg;
unsigned long lastRing = millis();
while(!_this->requestTaskTerminate) {
if (xSemaphoreTake(_this->binarySemaphore, portMAX_DELAY) == pdTRUE) {
unsigned long now = millis();
if (now - lastRing > DOORBELL_MIN_RING_INTERVAL) {
_this->notifyListeners(DoorbellEvent{});
lastRing = now;
}
}
}
vTaskDelete(NULL);
}
}