blob: 81e2c619e66fd45f9a88990101669cf7764559ea [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);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080022
James Kuszmaul41fa78a2019-12-14 20:53:14 -080023 SetMaxPeriod(0.5);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080024
James Kuszmaul41fa78a2019-12-14 20:53:14 -080025 HAL_Report(HALUsageReporting::kResourceType_Counter, m_index + 1, mode + 1);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080026}
27
Parker Schuhd3b7a8872018-02-19 16:42:27 -080028Counter::Counter(int channel) : Counter(kTwoPulse) {
29 SetUpSource(channel);
30 ClearDownSource();
31}
32
James Kuszmaul41fa78a2019-12-14 20:53:14 -080033Counter::Counter(DigitalSource* source) : Counter(kTwoPulse) {
34 SetUpSource(source);
35 ClearDownSource();
36}
37
38Counter::Counter(std::shared_ptr<DigitalSource> source) : Counter(kTwoPulse) {
39 SetUpSource(source);
40 ClearDownSource();
41}
42
43Counter::Counter(const AnalogTrigger& trigger) : Counter(kTwoPulse) {
Parker Schuhd3b7a8872018-02-19 16:42:27 -080044 SetUpSource(trigger.CreateOutput(AnalogTriggerType::kState));
45 ClearDownSource();
46}
47
James Kuszmaul41fa78a2019-12-14 20:53:14 -080048Counter::Counter(EncodingType encodingType, DigitalSource* upSource,
49 DigitalSource* downSource, bool inverted)
50 : Counter(encodingType,
51 std::shared_ptr<DigitalSource>(upSource,
52 NullDeleter<DigitalSource>()),
Parker Schuhd3b7a8872018-02-19 16:42:27 -080053 std::shared_ptr<DigitalSource>(downSource,
54 NullDeleter<DigitalSource>()),
55 inverted) {}
56
Parker Schuhd3b7a8872018-02-19 16:42:27 -080057Counter::Counter(EncodingType encodingType,
58 std::shared_ptr<DigitalSource> upSource,
59 std::shared_ptr<DigitalSource> downSource, bool inverted)
60 : Counter(kExternalDirection) {
61 if (encodingType != k1X && encodingType != k2X) {
62 wpi_setWPIErrorWithContext(
63 ParameterOutOfRange,
64 "Counter only supports 1X and 2X quadrature decoding.");
65 return;
66 }
67 SetUpSource(upSource);
68 SetDownSource(downSource);
69 int32_t status = 0;
70
71 if (encodingType == k1X) {
72 SetUpSourceEdge(true, false);
73 HAL_SetCounterAverageSize(m_counter, 1, &status);
74 } else {
75 SetUpSourceEdge(true, true);
76 HAL_SetCounterAverageSize(m_counter, 2, &status);
77 }
78
James Kuszmaul41fa78a2019-12-14 20:53:14 -080079 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080080 SetDownSourceEdge(inverted, true);
81}
82
Parker Schuhd3b7a8872018-02-19 16:42:27 -080083Counter::~Counter() {
84 SetUpdateWhenEmpty(true);
85
86 int32_t status = 0;
87 HAL_FreeCounter(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -080088 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -080089}
90
Parker Schuhd3b7a8872018-02-19 16:42:27 -080091void Counter::SetUpSource(int channel) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -080092 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -080093 SetUpSource(std::make_shared<DigitalInput>(channel));
94}
95
James Kuszmaul41fa78a2019-12-14 20:53:14 -080096void Counter::SetUpSource(AnalogTrigger* analogTrigger,
Parker Schuhd3b7a8872018-02-19 16:42:27 -080097 AnalogTriggerType triggerType) {
98 SetUpSource(std::shared_ptr<AnalogTrigger>(analogTrigger,
99 NullDeleter<AnalogTrigger>()),
100 triggerType);
101}
102
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800103void Counter::SetUpSource(std::shared_ptr<AnalogTrigger> analogTrigger,
104 AnalogTriggerType triggerType) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800105 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800106 SetUpSource(analogTrigger->CreateOutput(triggerType));
107}
108
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800109void Counter::SetUpSource(DigitalSource* source) {
110 SetUpSource(
111 std::shared_ptr<DigitalSource>(source, NullDeleter<DigitalSource>()));
112}
113
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800114void Counter::SetUpSource(std::shared_ptr<DigitalSource> source) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800115 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800116 m_upSource = source;
117 int32_t status = 0;
118 HAL_SetCounterUpSource(
119 m_counter, source->GetPortHandleForRouting(),
120 (HAL_AnalogTriggerType)source->GetAnalogTriggerTypeForRouting(), &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800121 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800122}
123
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800124void Counter::SetUpSource(DigitalSource& source) {
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800125 SetUpSource(
126 std::shared_ptr<DigitalSource>(&source, NullDeleter<DigitalSource>()));
127}
128
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800129void Counter::SetUpSourceEdge(bool risingEdge, bool fallingEdge) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800130 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800131 if (m_upSource == nullptr) {
132 wpi_setWPIErrorWithContext(
133 NullParameter,
134 "Must set non-nullptr UpSource before setting UpSourceEdge");
135 }
136 int32_t status = 0;
137 HAL_SetCounterUpSourceEdge(m_counter, risingEdge, fallingEdge, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800138 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800139}
140
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800141void Counter::ClearUpSource() {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800142 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800143 m_upSource.reset();
144 int32_t status = 0;
145 HAL_ClearCounterUpSource(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800146 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800147}
148
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800149void Counter::SetDownSource(int channel) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800150 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800151 SetDownSource(std::make_shared<DigitalInput>(channel));
152}
153
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800154void Counter::SetDownSource(AnalogTrigger* analogTrigger,
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800155 AnalogTriggerType triggerType) {
156 SetDownSource(std::shared_ptr<AnalogTrigger>(analogTrigger,
157 NullDeleter<AnalogTrigger>()),
158 triggerType);
159}
160
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800161void Counter::SetDownSource(std::shared_ptr<AnalogTrigger> analogTrigger,
162 AnalogTriggerType triggerType) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800163 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800164 SetDownSource(analogTrigger->CreateOutput(triggerType));
165}
166
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800167void Counter::SetDownSource(DigitalSource* source) {
168 SetDownSource(
169 std::shared_ptr<DigitalSource>(source, NullDeleter<DigitalSource>()));
170}
171
172void Counter::SetDownSource(DigitalSource& source) {
173 SetDownSource(
174 std::shared_ptr<DigitalSource>(&source, NullDeleter<DigitalSource>()));
175}
176
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800177void Counter::SetDownSource(std::shared_ptr<DigitalSource> source) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800178 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800179 m_downSource = source;
180 int32_t status = 0;
181 HAL_SetCounterDownSource(
182 m_counter, source->GetPortHandleForRouting(),
183 (HAL_AnalogTriggerType)source->GetAnalogTriggerTypeForRouting(), &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800184 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800185}
186
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800187void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800188 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800189 if (m_downSource == nullptr) {
190 wpi_setWPIErrorWithContext(
191 NullParameter,
192 "Must set non-nullptr DownSource before setting DownSourceEdge");
193 }
194 int32_t status = 0;
195 HAL_SetCounterDownSourceEdge(m_counter, risingEdge, fallingEdge, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800196 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800197}
198
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800199void Counter::ClearDownSource() {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800200 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800201 m_downSource.reset();
202 int32_t status = 0;
203 HAL_ClearCounterDownSource(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800204 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800205}
206
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800207void Counter::SetUpDownCounterMode() {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800208 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800209 int32_t status = 0;
210 HAL_SetCounterUpDownMode(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800211 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800212}
213
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800214void Counter::SetExternalDirectionMode() {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800215 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800216 int32_t status = 0;
217 HAL_SetCounterExternalDirectionMode(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800218 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800219}
220
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800221void Counter::SetSemiPeriodMode(bool highSemiPeriod) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800222 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800223 int32_t status = 0;
224 HAL_SetCounterSemiPeriodMode(m_counter, highSemiPeriod, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800225 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800226}
227
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800228void Counter::SetPulseLengthMode(double threshold) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800229 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800230 int32_t status = 0;
231 HAL_SetCounterPulseLengthMode(m_counter, threshold, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800232 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800233}
234
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800235void Counter::SetReverseDirection(bool reverseDirection) {
236 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800237 int32_t status = 0;
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800238 HAL_SetCounterReverseDirection(m_counter, reverseDirection, &status);
239 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800240}
241
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800242void Counter::SetSamplesToAverage(int samplesToAverage) {
243 if (samplesToAverage < 1 || samplesToAverage > 127) {
244 wpi_setWPIErrorWithContext(
245 ParameterOutOfRange,
246 "Average counter values must be between 1 and 127");
247 }
248 int32_t status = 0;
249 HAL_SetCounterSamplesToAverage(m_counter, samplesToAverage, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800250 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800251}
252
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800253int Counter::GetSamplesToAverage() const {
254 int32_t status = 0;
255 int samples = HAL_GetCounterSamplesToAverage(m_counter, &status);
256 wpi_setHALError(status);
257 return samples;
258}
259
260int Counter::GetFPGAIndex() const { return m_index; }
261
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800262int Counter::Get() const {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800263 if (StatusIsFatal()) return 0;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800264 int32_t status = 0;
265 int value = HAL_GetCounter(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800266 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800267 return value;
268}
269
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800270void Counter::Reset() {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800271 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800272 int32_t status = 0;
273 HAL_ResetCounter(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800274 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800275}
276
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800277double Counter::GetPeriod() const {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800278 if (StatusIsFatal()) return 0.0;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800279 int32_t status = 0;
280 double value = HAL_GetCounterPeriod(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800281 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800282 return value;
283}
284
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800285void Counter::SetMaxPeriod(double maxPeriod) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800286 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800287 int32_t status = 0;
288 HAL_SetCounterMaxPeriod(m_counter, maxPeriod, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800289 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800290}
291
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800292void Counter::SetUpdateWhenEmpty(bool enabled) {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800293 if (StatusIsFatal()) return;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800294 int32_t status = 0;
295 HAL_SetCounterUpdateWhenEmpty(m_counter, enabled, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800296 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800297}
298
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800299bool Counter::GetStopped() const {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800300 if (StatusIsFatal()) return false;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800301 int32_t status = 0;
302 bool value = HAL_GetCounterStopped(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800303 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800304 return value;
305}
306
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800307bool Counter::GetDirection() const {
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800308 if (StatusIsFatal()) return false;
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800309 int32_t status = 0;
310 bool value = HAL_GetCounterDirection(m_counter, &status);
James Kuszmaul41fa78a2019-12-14 20:53:14 -0800311 wpi_setHALError(status);
Parker Schuhd3b7a8872018-02-19 16:42:27 -0800312 return value;
313}