blob: d2158ca02081aa4f28ea20cb6b31488dea860a5c [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/*----------------------------------------------------------------------------*/
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -08002/* Copyright (c) 2008-2019 FIRST. All Rights Reserved. */
Brian Silverman41cdd3e2019-01-19 19:48:58 -08003/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "frc/Counter.h"
9
10#include <utility>
11
James Kuszmaul4b81d302019-12-14 20:53:14 -080012#include <hal/Counter.h>
13#include <hal/FRCUsageReporting.h>
Brian Silverman41cdd3e2019-01-19 19:48:58 -080014
15#include "frc/AnalogTrigger.h"
16#include "frc/DigitalInput.h"
17#include "frc/WPIErrors.h"
18#include "frc/smartdashboard/SendableBuilder.h"
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080019#include "frc/smartdashboard/SendableRegistry.h"
Brian Silverman41cdd3e2019-01-19 19:48:58 -080020
21using namespace frc;
22
23Counter::Counter(Mode mode) {
24 int32_t status = 0;
25 m_counter = HAL_InitializeCounter((HAL_Counter_Mode)mode, &m_index, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -080026 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080027
James Kuszmaul4b81d302019-12-14 20:53:14 -080028 SetMaxPeriod(0.5);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080029
James Kuszmaul4b81d302019-12-14 20:53:14 -080030 HAL_Report(HALUsageReporting::kResourceType_Counter, m_index + 1, mode + 1);
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080031 SendableRegistry::GetInstance().AddLW(this, "Counter", m_index);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080032}
33
34Counter::Counter(int channel) : Counter(kTwoPulse) {
35 SetUpSource(channel);
36 ClearDownSource();
37}
38
39Counter::Counter(DigitalSource* source) : Counter(kTwoPulse) {
40 SetUpSource(source);
41 ClearDownSource();
42}
43
44Counter::Counter(std::shared_ptr<DigitalSource> source) : Counter(kTwoPulse) {
45 SetUpSource(source);
46 ClearDownSource();
47}
48
49Counter::Counter(const AnalogTrigger& trigger) : Counter(kTwoPulse) {
50 SetUpSource(trigger.CreateOutput(AnalogTriggerType::kState));
51 ClearDownSource();
52}
53
54Counter::Counter(EncodingType encodingType, DigitalSource* upSource,
55 DigitalSource* downSource, bool inverted)
56 : Counter(encodingType,
57 std::shared_ptr<DigitalSource>(upSource,
58 NullDeleter<DigitalSource>()),
59 std::shared_ptr<DigitalSource>(downSource,
60 NullDeleter<DigitalSource>()),
61 inverted) {}
62
63Counter::Counter(EncodingType encodingType,
64 std::shared_ptr<DigitalSource> upSource,
65 std::shared_ptr<DigitalSource> downSource, bool inverted)
66 : Counter(kExternalDirection) {
67 if (encodingType != k1X && encodingType != k2X) {
68 wpi_setWPIErrorWithContext(
69 ParameterOutOfRange,
70 "Counter only supports 1X and 2X quadrature decoding.");
71 return;
72 }
73 SetUpSource(upSource);
74 SetDownSource(downSource);
75 int32_t status = 0;
76
77 if (encodingType == k1X) {
78 SetUpSourceEdge(true, false);
79 HAL_SetCounterAverageSize(m_counter, 1, &status);
80 } else {
81 SetUpSourceEdge(true, true);
82 HAL_SetCounterAverageSize(m_counter, 2, &status);
83 }
84
James Kuszmaul4b81d302019-12-14 20:53:14 -080085 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080086 SetDownSourceEdge(inverted, true);
87}
88
89Counter::~Counter() {
90 SetUpdateWhenEmpty(true);
91
92 int32_t status = 0;
93 HAL_FreeCounter(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -080094 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080095}
96
97void Counter::SetUpSource(int channel) {
98 if (StatusIsFatal()) return;
99 SetUpSource(std::make_shared<DigitalInput>(channel));
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -0800100 SendableRegistry::GetInstance().AddChild(this, m_upSource.get());
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800101}
102
103void Counter::SetUpSource(AnalogTrigger* analogTrigger,
104 AnalogTriggerType triggerType) {
105 SetUpSource(std::shared_ptr<AnalogTrigger>(analogTrigger,
106 NullDeleter<AnalogTrigger>()),
107 triggerType);
108}
109
110void Counter::SetUpSource(std::shared_ptr<AnalogTrigger> analogTrigger,
111 AnalogTriggerType triggerType) {
112 if (StatusIsFatal()) return;
113 SetUpSource(analogTrigger->CreateOutput(triggerType));
114}
115
116void Counter::SetUpSource(DigitalSource* source) {
117 SetUpSource(
118 std::shared_ptr<DigitalSource>(source, NullDeleter<DigitalSource>()));
119}
120
121void Counter::SetUpSource(std::shared_ptr<DigitalSource> source) {
122 if (StatusIsFatal()) return;
123 m_upSource = source;
124 if (m_upSource->StatusIsFatal()) {
125 CloneError(*m_upSource);
126 } else {
127 int32_t status = 0;
128 HAL_SetCounterUpSource(
129 m_counter, source->GetPortHandleForRouting(),
130 (HAL_AnalogTriggerType)source->GetAnalogTriggerTypeForRouting(),
131 &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800132 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800133 }
134}
135
136void Counter::SetUpSource(DigitalSource& source) {
137 SetUpSource(
138 std::shared_ptr<DigitalSource>(&source, NullDeleter<DigitalSource>()));
139}
140
141void Counter::SetUpSourceEdge(bool risingEdge, bool fallingEdge) {
142 if (StatusIsFatal()) return;
143 if (m_upSource == nullptr) {
144 wpi_setWPIErrorWithContext(
145 NullParameter,
146 "Must set non-nullptr UpSource before setting UpSourceEdge");
147 }
148 int32_t status = 0;
149 HAL_SetCounterUpSourceEdge(m_counter, risingEdge, fallingEdge, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800150 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800151}
152
153void Counter::ClearUpSource() {
154 if (StatusIsFatal()) return;
155 m_upSource.reset();
156 int32_t status = 0;
157 HAL_ClearCounterUpSource(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800158 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800159}
160
161void Counter::SetDownSource(int channel) {
162 if (StatusIsFatal()) return;
163 SetDownSource(std::make_shared<DigitalInput>(channel));
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -0800164 SendableRegistry::GetInstance().AddChild(this, m_downSource.get());
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800165}
166
167void Counter::SetDownSource(AnalogTrigger* analogTrigger,
168 AnalogTriggerType triggerType) {
169 SetDownSource(std::shared_ptr<AnalogTrigger>(analogTrigger,
170 NullDeleter<AnalogTrigger>()),
171 triggerType);
172}
173
174void Counter::SetDownSource(std::shared_ptr<AnalogTrigger> analogTrigger,
175 AnalogTriggerType triggerType) {
176 if (StatusIsFatal()) return;
177 SetDownSource(analogTrigger->CreateOutput(triggerType));
178}
179
180void Counter::SetDownSource(DigitalSource* source) {
181 SetDownSource(
182 std::shared_ptr<DigitalSource>(source, NullDeleter<DigitalSource>()));
183}
184
185void Counter::SetDownSource(DigitalSource& source) {
186 SetDownSource(
187 std::shared_ptr<DigitalSource>(&source, NullDeleter<DigitalSource>()));
188}
189
190void Counter::SetDownSource(std::shared_ptr<DigitalSource> source) {
191 if (StatusIsFatal()) return;
192 m_downSource = source;
193 if (m_downSource->StatusIsFatal()) {
194 CloneError(*m_downSource);
195 } else {
196 int32_t status = 0;
197 HAL_SetCounterDownSource(
198 m_counter, source->GetPortHandleForRouting(),
199 (HAL_AnalogTriggerType)source->GetAnalogTriggerTypeForRouting(),
200 &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800201 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800202 }
203}
204
205void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge) {
206 if (StatusIsFatal()) return;
207 if (m_downSource == nullptr) {
208 wpi_setWPIErrorWithContext(
209 NullParameter,
210 "Must set non-nullptr DownSource before setting DownSourceEdge");
211 }
212 int32_t status = 0;
213 HAL_SetCounterDownSourceEdge(m_counter, risingEdge, fallingEdge, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800214 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800215}
216
217void Counter::ClearDownSource() {
218 if (StatusIsFatal()) return;
219 m_downSource.reset();
220 int32_t status = 0;
221 HAL_ClearCounterDownSource(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800222 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800223}
224
225void Counter::SetUpDownCounterMode() {
226 if (StatusIsFatal()) return;
227 int32_t status = 0;
228 HAL_SetCounterUpDownMode(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800229 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800230}
231
232void Counter::SetExternalDirectionMode() {
233 if (StatusIsFatal()) return;
234 int32_t status = 0;
235 HAL_SetCounterExternalDirectionMode(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800236 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800237}
238
239void Counter::SetSemiPeriodMode(bool highSemiPeriod) {
240 if (StatusIsFatal()) return;
241 int32_t status = 0;
242 HAL_SetCounterSemiPeriodMode(m_counter, highSemiPeriod, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800243 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800244}
245
246void Counter::SetPulseLengthMode(double threshold) {
247 if (StatusIsFatal()) return;
248 int32_t status = 0;
249 HAL_SetCounterPulseLengthMode(m_counter, threshold, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800250 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800251}
252
253void Counter::SetReverseDirection(bool reverseDirection) {
254 if (StatusIsFatal()) return;
255 int32_t status = 0;
256 HAL_SetCounterReverseDirection(m_counter, reverseDirection, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800257 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800258}
259
260void Counter::SetSamplesToAverage(int samplesToAverage) {
261 if (samplesToAverage < 1 || samplesToAverage > 127) {
262 wpi_setWPIErrorWithContext(
263 ParameterOutOfRange,
264 "Average counter values must be between 1 and 127");
265 }
266 int32_t status = 0;
267 HAL_SetCounterSamplesToAverage(m_counter, samplesToAverage, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800268 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800269}
270
271int Counter::GetSamplesToAverage() const {
272 int32_t status = 0;
273 int samples = HAL_GetCounterSamplesToAverage(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800274 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800275 return samples;
276}
277
278int Counter::GetFPGAIndex() const { return m_index; }
279
280int Counter::Get() const {
281 if (StatusIsFatal()) return 0;
282 int32_t status = 0;
283 int value = HAL_GetCounter(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800284 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800285 return value;
286}
287
288void Counter::Reset() {
289 if (StatusIsFatal()) return;
290 int32_t status = 0;
291 HAL_ResetCounter(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800292 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800293}
294
295double Counter::GetPeriod() const {
296 if (StatusIsFatal()) return 0.0;
297 int32_t status = 0;
298 double value = HAL_GetCounterPeriod(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800299 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800300 return value;
301}
302
303void Counter::SetMaxPeriod(double maxPeriod) {
304 if (StatusIsFatal()) return;
305 int32_t status = 0;
306 HAL_SetCounterMaxPeriod(m_counter, maxPeriod, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800307 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800308}
309
310void Counter::SetUpdateWhenEmpty(bool enabled) {
311 if (StatusIsFatal()) return;
312 int32_t status = 0;
313 HAL_SetCounterUpdateWhenEmpty(m_counter, enabled, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800314 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800315}
316
317bool Counter::GetStopped() const {
318 if (StatusIsFatal()) return false;
319 int32_t status = 0;
320 bool value = HAL_GetCounterStopped(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800321 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800322 return value;
323}
324
325bool Counter::GetDirection() const {
326 if (StatusIsFatal()) return false;
327 int32_t status = 0;
328 bool value = HAL_GetCounterDirection(m_counter, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800329 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800330 return value;
331}
332
333void Counter::InitSendable(SendableBuilder& builder) {
334 builder.SetSmartDashboardType("Counter");
335 builder.AddDoubleProperty("Value", [=]() { return Get(); }, nullptr);
336}