-
-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathDeviceEvents.h
148 lines (138 loc) · 5.43 KB
/
DeviceEvents.h
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
137
138
139
140
141
142
143
144
145
146
147
148
/*
* Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry).
* This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
*/
#ifndef IOABSTRACTION_DEVICEEVENTS_H
#define IOABSTRACTION_DEVICEEVENTS_H
/**
* @file DeviceEvents.h
* @brief This file contains events that are associated with the device, such as the Analog Device.
*/
#include "TaskManagerIO.h"
#include "PlatformDetermination.h"
#include "AnalogDeviceAbstraction.h"
/**
* An event that triggers when a certain analog condition is reached, based on a made and a threshold. It can either
* poll the analog in pin by setting the poll interval to a small value, or can be interrupt driven by calling the
* `readingAvailable` method from the ISR, you can even use a combination of the two. The `exec` method must be
* implemented by the implementor.
*
* There are three possible combinations:
*
* * ANALOGIN_EXCEEDS - the event is triggered when analog in exceeds threshold.
* * ANALOGIN_BELOW - the event is triggered when analog in is below threshold.
* * ANALOGIN_CHANGE - the event is triggered when analog in changes by more than threshold.
*/
class AnalogInEvent : public BaseEvent {
public:
/**
* Describes the way in which the Analog event should trigger.
*/
enum AnalogEventMode {
/** Trigger the event when it exceeds the threshold */
ANALOGIN_EXCEEDS,
/** Trigger the event when it goes below the threshold */
ANALOGIN_BELOW,
/** Trigger the event when it changes by more than threshold */
ANALOGIN_CHANGE
};
private:
AnalogDevice *analogDevice;
AnalogEventMode mode;
uint32_t pollInterval;
bool latched;
pinid_t analogPin;
protected:
float analogThreshold;
float lastReading;
public:
/**
* Constructs the abstract analog event class. Providing the analog pin to read from and the mode for triggering.
* This constructor allows for use of a reference instead of pointer for analog device
* @param device the analog device as a reference
* @param inputPin the pin to read from
* @param threshold the value at which to trigger the event.
* @param mode_ one of the values in enum AnalogEventMode
* @param pollInterval_ the interval on which taskManager should check if the event needs to trigger
*/
AnalogInEvent(AnalogDevice& device, pinid_t inputPin, float threshold, AnalogEventMode mode_,
uint32_t pollInterval_) : BaseEvent() {
analogThreshold = threshold;
analogPin = inputPin;
lastReading = 0;
pollInterval = pollInterval_;
analogDevice = &device;
latched = false;
mode = mode_;
}
/**
* Constructs the abstract analog event class. Providing the analog pin to read from and the mode for triggering.
* This constructor takes a pointer to the analog device.
* @param device the analog device
* @param inputPin the pin to read from
* @param threshold the value at which to trigger the event.
* @param mode_ one of the values in enum AnalogEventMode
* @param pollInterval_ the interval on which taskManager should check if the event needs to trigger
*/
AnalogInEvent(AnalogDevice *device, pinid_t inputPin, float threshold, AnalogEventMode mode_,
uint32_t pollInterval_) : BaseEvent() {
analogThreshold = threshold;
analogPin = inputPin;
lastReading = 0;
pollInterval = pollInterval_;
analogDevice = device;
latched = false;
mode = mode_;
}
/**
* Change to another polling interval
* @param micros the new polling interval in microseconds
*/
void setPollInterval(uint32_t micros) {
pollInterval = micros;
}
/**
* Implementation of the method that checks the analog reading against the condition for this instance. If the
* condition is met, then it triggers the event, which stays latched until the condition is no longer met, and
* then it is unlatched.
* @return the configured poll interval.
*/
uint32_t timeOfNextCheck() override {
lastReading = analogDevice->getCurrentFloat(analogPin);
auto analogTrigger = isConditionTrue();
if (analogTrigger && !latched) {
setTriggered(true);
latched = true;
}
else if(!analogTrigger && latched) {
latched = false;
}
return pollInterval;
}
/**
* Checks if the condition for the event is met, IE if the analog in value is within the range for the interrupt.
* @return true if the condition is met, otherwise false.
*/
bool isConditionTrue() {
if (mode == ANALOGIN_BELOW) {
return lastReading < analogThreshold;
}
else if(mode == ANALOGIN_EXCEEDS) {
return lastReading > analogThreshold;
}
else {
auto change = abs(analogThreshold - lastReading);
return change > analogThreshold;
}
}
/**
* Non-polling case, change interrupt attached to analog pin.
* We've been notified that a reading available from interrupt, tell taskmanager to run event evaluation now.
* This will cause all events to run a check followed by the trigger if needed. Completely safe to call
* from interrupts and other threads
*/
void readingAvailable() {
taskManager.triggerEvents();
}
};
#endif //IOABSTRACTION_DEVICEEVENTS_H