blob: 8e91c82f2322e86115ea2cd1ab375806cc375fde [file] [log] [blame]
Parker Schuhd3b7a8872018-02-19 16:42:27 -08001/*----------------------------------------------------------------------------*/
James Kuszmaul41fa78a2019-12-14 20:53:14 -08002/* Copyright (c) 2008-2019 FIRST. All Rights Reserved. */
Parker Schuhd3b7a8872018-02-19 16:42:27 -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 "frc971/wpilib/ahal/Counter.h"
9
Austin Schuhf6b94632019-02-02 22:11:27 -080010#include "hal/HAL.h"
Parker Schuhd3b7a8872018-02-19 16:42:27 -080011#include "frc971/wpilib/ahal/AnalogTrigger.h"
James Kuszmaul41fa78a2019-12-14 20:53:14 -080012#include "frc971/wpilib/ahal/Base.h"
Parker Schuhd3b7a8872018-02-19 16:42:27 -080013#include "frc971/wpilib/ahal/DigitalInput.h"
14#include "frc971/wpilib/ahal/WPIErrors.h"
15
16using namespace frc;
17
Parker Schuhd3b7a8872018-02-19 16:42:27 -080018Counter::Counter(Mode mode) {
19 int32_t status = 0;
20 m_counter = HAL_InitializeCounter((HAL_Counter_Mode)mode, &m_index, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -080021 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -080022 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080023
James Kuszmaul41fa78a2019-12-14 20:53:14 -080024 SetMaxPeriod(0.5);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080025
James Kuszmaul41fa78a2019-12-14 20:53:14 -080026 HAL_Report(HALUsageReporting::kResourceType_Counter, m_index + 1, mode + 1);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080027}
28
Parker Schuhd3b7a8872018-02-19 16:42:27 -080029Counter::Counter(int channel) : Counter(kTwoPulse) {
30 SetUpSource(channel);
31 ClearDownSource();
32}
33
James Kuszmaul41fa78a2019-12-14 20:53:14 -080034Counter::Counter(DigitalSource* source) : Counter(kTwoPulse) {
35 SetUpSource(source);
36 ClearDownSource();
37}
38
39Counter::Counter(std::shared_ptr<DigitalSource> source) : Counter(kTwoPulse) {
40 SetUpSource(source);
41 ClearDownSource();
42}
43
44Counter::Counter(const AnalogTrigger& trigger) : Counter(kTwoPulse) {
Parker Schuhd3b7a8872018-02-19 16:42:27 -080045 SetUpSource(trigger.CreateOutput(AnalogTriggerType::kState));
46 ClearDownSource();
47}
48
James Kuszmaul41fa78a2019-12-14 20:53:14 -080049Counter::Counter(EncodingType encodingType, DigitalSource* upSource,
50 DigitalSource* downSource, bool inverted)
51 : Counter(encodingType,
52 std::shared_ptr<DigitalSource>(upSource,
53 NullDeleter<DigitalSource>()),
Parker Schuhd3b7a8872018-02-19 16:42:27 -080054 std::shared_ptr<DigitalSource>(downSource,
55 NullDeleter<DigitalSource>()),
56 inverted) {}
57
Parker Schuhd3b7a8872018-02-19 16:42:27 -080058Counter::Counter(EncodingType encodingType,
59 std::shared_ptr<DigitalSource> upSource,
60 std::shared_ptr<DigitalSource> downSource, bool inverted)
61 : Counter(kExternalDirection) {
62 if (encodingType != k1X && encodingType != k2X) {
63 wpi_setWPIErrorWithContext(
64 ParameterOutOfRange,
65 "Counter only supports 1X and 2X quadrature decoding.");
66 return;
67 }
68 SetUpSource(upSource);
69 SetDownSource(downSource);
70 int32_t status = 0;
71
72 if (encodingType == k1X) {
73 SetUpSourceEdge(true, false);
74 HAL_SetCounterAverageSize(m_counter, 1, &status);
75 } else {
76 SetUpSourceEdge(true, true);
77 HAL_SetCounterAverageSize(m_counter, 2, &status);
78 }
79
James Kuszmaul41fa78a2019-12-14 20:53:14 -080080 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -080081 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080082 SetDownSourceEdge(inverted, true);
83}
84
Parker Schuhd3b7a8872018-02-19 16:42:27 -080085Counter::~Counter() {
86 SetUpdateWhenEmpty(true);
87
88 int32_t status = 0;
89 HAL_FreeCounter(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -080090 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -080091 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080092}
93
Parker Schuhd3b7a8872018-02-19 16:42:27 -080094void Counter::SetUpSource(int channel) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -080095 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -080096 SetUpSource(std::make_shared<DigitalInput>(channel));
97}
98
James Kuszmaul41fa78a2019-12-14 20:53:14 -080099void Counter::SetUpSource(AnalogTrigger* analogTrigger,
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800100 AnalogTriggerType triggerType) {
101 SetUpSource(std::shared_ptr<AnalogTrigger>(analogTrigger,
102 NullDeleter<AnalogTrigger>()),
103 triggerType);
104}
105
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800106void Counter::SetUpSource(std::shared_ptr<AnalogTrigger> analogTrigger,
107 AnalogTriggerType triggerType) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800108 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800109 SetUpSource(analogTrigger->CreateOutput(triggerType));
110}
111
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800112void Counter::SetUpSource(DigitalSource* source) {
113 SetUpSource(
114 std::shared_ptr<DigitalSource>(source, NullDeleter<DigitalSource>()));
115}
116
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800117void Counter::SetUpSource(std::shared_ptr<DigitalSource> source) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800118 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800119 m_upSource = source;
120 int32_t status = 0;
121 HAL_SetCounterUpSource(
122 m_counter, source->GetPortHandleForRouting(),
123 (HAL_AnalogTriggerType)source->GetAnalogTriggerTypeForRouting(), &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800124 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800125 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800126}
127
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800128void Counter::SetUpSource(DigitalSource& source) {
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800129 SetUpSource(
130 std::shared_ptr<DigitalSource>(&source, NullDeleter<DigitalSource>()));
131}
132
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800133void Counter::SetUpSourceEdge(bool risingEdge, bool fallingEdge) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800134 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800135 if (m_upSource == nullptr) {
136 wpi_setWPIErrorWithContext(
137 NullParameter,
138 "Must set non-nullptr UpSource before setting UpSourceEdge");
139 }
140 int32_t status = 0;
141 HAL_SetCounterUpSourceEdge(m_counter, risingEdge, fallingEdge, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800142 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800143 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800144}
145
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800146void Counter::ClearUpSource() {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800147 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800148 m_upSource.reset();
149 int32_t status = 0;
150 HAL_ClearCounterUpSource(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800151 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800152 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800153}
154
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800155void Counter::SetDownSource(int channel) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800156 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800157 SetDownSource(std::make_shared<DigitalInput>(channel));
158}
159
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800160void Counter::SetDownSource(AnalogTrigger* analogTrigger,
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800161 AnalogTriggerType triggerType) {
162 SetDownSource(std::shared_ptr<AnalogTrigger>(analogTrigger,
163 NullDeleter<AnalogTrigger>()),
164 triggerType);
165}
166
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800167void Counter::SetDownSource(std::shared_ptr<AnalogTrigger> analogTrigger,
168 AnalogTriggerType triggerType) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800169 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800170 SetDownSource(analogTrigger->CreateOutput(triggerType));
171}
172
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800173void Counter::SetDownSource(DigitalSource* source) {
174 SetDownSource(
175 std::shared_ptr<DigitalSource>(source, NullDeleter<DigitalSource>()));
176}
177
178void Counter::SetDownSource(DigitalSource& source) {
179 SetDownSource(
180 std::shared_ptr<DigitalSource>(&source, NullDeleter<DigitalSource>()));
181}
182
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800183void Counter::SetDownSource(std::shared_ptr<DigitalSource> source) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800184 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800185 m_downSource = source;
186 int32_t status = 0;
187 HAL_SetCounterDownSource(
188 m_counter, source->GetPortHandleForRouting(),
189 (HAL_AnalogTriggerType)source->GetAnalogTriggerTypeForRouting(), &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800190 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800191 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800192}
193
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800194void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800195 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800196 if (m_downSource == nullptr) {
197 wpi_setWPIErrorWithContext(
198 NullParameter,
199 "Must set non-nullptr DownSource before setting DownSourceEdge");
200 }
201 int32_t status = 0;
202 HAL_SetCounterDownSourceEdge(m_counter, risingEdge, fallingEdge, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800203 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800204 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800205}
206
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800207void Counter::ClearDownSource() {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800208 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800209 m_downSource.reset();
210 int32_t status = 0;
211 HAL_ClearCounterDownSource(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800212 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800213 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800214}
215
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800216void Counter::SetUpDownCounterMode() {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800217 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800218 int32_t status = 0;
219 HAL_SetCounterUpDownMode(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800220 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800221 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800222}
223
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800224void Counter::SetExternalDirectionMode() {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800225 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800226 int32_t status = 0;
227 HAL_SetCounterExternalDirectionMode(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800228 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800229 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800230}
231
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800232void Counter::SetSemiPeriodMode(bool highSemiPeriod) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800233 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800234 int32_t status = 0;
235 HAL_SetCounterSemiPeriodMode(m_counter, highSemiPeriod, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800236 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800237 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800238}
239
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800240void Counter::SetPulseLengthMode(double threshold) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800241 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800242 int32_t status = 0;
243 HAL_SetCounterPulseLengthMode(m_counter, threshold, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800244 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800245 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800246}
247
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800248void Counter::SetReverseDirection(bool reverseDirection) {
249 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800250 int32_t status = 0;
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800251 HAL_SetCounterReverseDirection(m_counter, reverseDirection, &status);
252 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800253 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800254}
255
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800256void Counter::SetSamplesToAverage(int samplesToAverage) {
257 if (samplesToAverage < 1 || samplesToAverage > 127) {
258 wpi_setWPIErrorWithContext(
259 ParameterOutOfRange,
260 "Average counter values must be between 1 and 127");
261 }
262 int32_t status = 0;
263 HAL_SetCounterSamplesToAverage(m_counter, samplesToAverage, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800264 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800265 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800266}
267
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800268int Counter::GetSamplesToAverage() const {
269 int32_t status = 0;
270 int samples = HAL_GetCounterSamplesToAverage(m_counter, &status);
271 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800272 HAL_CHECK_STATUS(status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800273 return samples;
274}
275
276int Counter::GetFPGAIndex() const { return m_index; }
277
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800278int Counter::Get() const {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800279 if (StatusIsFatal()) return 0;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800280 int32_t status = 0;
281 int value = HAL_GetCounter(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800282 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800283 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800284 return value;
285}
286
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800287void Counter::Reset() {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800288 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800289 int32_t status = 0;
290 HAL_ResetCounter(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800291 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800292 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800293}
294
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800295double Counter::GetPeriod() const {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800296 if (StatusIsFatal()) return 0.0;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800297 int32_t status = 0;
298 double value = HAL_GetCounterPeriod(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800299 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800300 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800301 return value;
302}
303
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800304void Counter::SetMaxPeriod(double maxPeriod) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800305 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800306 int32_t status = 0;
307 HAL_SetCounterMaxPeriod(m_counter, maxPeriod, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800308 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800309 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800310}
311
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800312void Counter::SetUpdateWhenEmpty(bool enabled) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800313 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800314 int32_t status = 0;
315 HAL_SetCounterUpdateWhenEmpty(m_counter, enabled, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800316 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800317 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800318}
319
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800320bool Counter::GetStopped() const {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800321 if (StatusIsFatal()) return false;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800322 int32_t status = 0;
323 bool value = HAL_GetCounterStopped(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800324 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800325 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800326 return value;
327}
328
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800329bool Counter::GetDirection() const {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800330 if (StatusIsFatal()) return false;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800331 int32_t status = 0;
332 bool value = HAL_GetCounterDirection(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800333 wpi_setHALError(status);
James Kuszmauleb9f6fb2022-02-27 21:04:00 -0800334 HAL_CHECK_STATUS(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800335 return value;
336}