Skyward boardcore
Loading...
Searching...
No Matches
PinObserver.cpp
Go to the documentation of this file.
1/* Copyright (c) 2018-2022 Skyward Experimental Rocketry
2 * Authors: Luca Erbetta, Alberto Nidasio, Niccolò Betto
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "PinObserver.h"
24
25namespace Boardcore
26{
27
28bool PinObserver::registerPinCallback(miosix::GpioPin pin, PinCallback callback,
29 uint32_t detectionThreshold,
30 bool reverted)
31{
32 // Try to insert the callback
33 auto result =
34 callbacks.insert({pin, PinEntry{
35 .config =
37 .callback = std::move(callback),
38 .threshold = detectionThreshold,
39 .reverted = reverted,
40 },
41 .data =
42 PinData{
43 .periodCount = 0,
44 .lastTransitionTs = TimePoint{},
45 .lastStateChangeTs = TimePoint{},
46 // Broken on cppcheck 2.7
47 // cppcheck-suppress internalAstError
48 .lastState = pin.value() != reverted,
49 .changesCount = 0,
50 },
51 }});
52
53 // Check if the insertion took place
54 if (!result.second)
55 return false;
56
57 auto taskId =
58 scheduler.addTask([this, pin] { periodicPinValueCheck(pin); },
59 pollInterval, TaskScheduler::Policy::RECOVER);
60
61 // Check if the task was added successfully
62 if (!taskId)
63 {
64 callbacks.erase(pin);
65 return false;
66 }
67
68 return true;
69}
70
71PinData PinObserver::getPinData(miosix::GpioPin pin)
72{
73 auto pinEntry = callbacks.find(pin);
74 if (pinEntry == callbacks.end())
75 return PinData{};
76
77 return pinEntry->second.data;
78}
79
80void PinObserver::resetPinChangesCount(miosix::GpioPin pin)
81{
82 auto pinEntry = callbacks.find(pin);
83 if (pinEntry == callbacks.end())
84 return;
85
86 pinEntry->second.data.changesCount = 0;
87}
88
89void PinObserver::periodicPinValueCheck(miosix::GpioPin pin)
90{
91 auto pinEntry = callbacks.find(pin);
92
93 // Make sure the pin informations are still present
94 if (pinEntry == callbacks.end())
95 return;
96
97 // Retrieve the pin information
98 auto& pinConfig = pinEntry->second.config;
99 auto& pinData = pinEntry->second.data;
100 auto& count = pinData.periodCount;
101
102 // Read the current pin status
103 const bool newState = pin.value() != pinConfig.reverted;
104
105 // Are we in a transition?
106 if (pinData.lastState != newState)
107 {
108 // Register the current state change
109 count++;
110
111 // If the count reaches the threshold, then the change is confirmed and
112 // we can trigger the event
113 if (count >= pinConfig.threshold)
114 {
115 count = 0; // Reset the counter
116 pinData.changesCount++; // Register the change
117
118 // Update the state
119 pinData.lastStateChangeTs = Clock::now();
120 pinData.lastState = newState;
121
122 // Execute the callback
123 pinConfig.callback(newState ? PinTransition::RISING_EDGE
125 pinData);
126 }
127 }
128 else
129 {
130 // Update the last transition timestamp as the time it was still in the
131 // previous state. Once a transition happens this won't be updated and
132 // will contain the last time the pin was in the previous state
133 pinData.lastTransitionTs = Clock::now();
134
135 // If the value is still the same as before, the counter is reset to 0
136 count = 0;
137 }
138}
139
140} // namespace Boardcore
std::function< void(PinTransition transition, const PinData &data)> PinCallback
Callback function type for pin transitions.
Definition PinObserver.h:89
Clock::time_point TimePoint
Definition PinObserver.h:58
void resetPinChangesCount(miosix::GpioPin pin)
Resets the changes counter for the specified pin.
bool registerPinCallback(miosix::GpioPin pin, PinCallback callback, uint32_t detectionThreshold=1, bool reverted=false)
PinData getPinData(miosix::GpioPin pin)
Returns the information for the specified pin.
@ RECOVER
Prioritize the number of executions over the period.
size_t addTask(function_t function, uint32_t periodMs, Policy policy=Policy::RECOVER, int64_t startTick=Kernel::getOldTick())
Add a millisecond-period task function to the scheduler with an auto generated ID.
Driver for the VN100S IMU.
PinTransition
Pin transition.
Definition PinObserver.h:39
@ FALLING_EDGE
The pin goes from high to low.
@ RISING_EDGE
The pin goes from low to high.
PinObserver::PinCallback callback
The callback function.
Definition PinObserver.h:96