blob: 32416f0d7a943968b3c383501c35da21e3c9939a [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/*----------------------------------------------------------------------------*/
Austin Schuh1e69f942020-11-14 15:06:14 -08002/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */
Brian Silverman8fce7482020-01-05 13:18:21 -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 "hal/Encoder.h"
9
10#include "CounterInternal.h"
11#include "HALInitializer.h"
12#include "PortsInternal.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080013#include "hal/Errors.h"
14#include "hal/handles/HandlesInternal.h"
15#include "hal/handles/LimitedHandleResource.h"
16#include "mockdata/EncoderDataInternal.h"
17
18using namespace hal;
19
20namespace {
21struct Encoder {
22 HAL_Handle nativeHandle;
23 HAL_EncoderEncodingType encodingType;
24 double distancePerPulse;
25 uint8_t index;
26};
27struct Empty {};
28} // namespace
29
30static LimitedHandleResource<HAL_EncoderHandle, Encoder,
31 kNumEncoders + kNumCounters,
32 HAL_HandleEnum::Encoder>* encoderHandles;
33
34static LimitedHandleResource<HAL_FPGAEncoderHandle, Empty, kNumEncoders,
35 HAL_HandleEnum::FPGAEncoder>* fpgaEncoderHandles;
36
37namespace hal {
38namespace init {
39void InitializeEncoder() {
40 static LimitedHandleResource<HAL_FPGAEncoderHandle, Empty, kNumEncoders,
41 HAL_HandleEnum::FPGAEncoder>
42 feH;
43 fpgaEncoderHandles = &feH;
44 static LimitedHandleResource<HAL_EncoderHandle, Encoder,
45 kNumEncoders + kNumCounters,
46 HAL_HandleEnum::Encoder>
47 eH;
48 encoderHandles = &eH;
49}
50} // namespace init
51} // namespace hal
52
53extern "C" {
54HAL_EncoderHandle HAL_InitializeEncoder(
55 HAL_Handle digitalSourceHandleA, HAL_AnalogTriggerType analogTriggerTypeA,
56 HAL_Handle digitalSourceHandleB, HAL_AnalogTriggerType analogTriggerTypeB,
57 HAL_Bool reverseDirection, HAL_EncoderEncodingType encodingType,
58 int32_t* status) {
59 hal::init::CheckInit();
60 HAL_Handle nativeHandle = HAL_kInvalidHandle;
61 if (encodingType == HAL_EncoderEncodingType::HAL_Encoder_k4X) {
62 // k4x, allocate encoder
63 nativeHandle = fpgaEncoderHandles->Allocate();
64 } else {
65 // k2x or k1x, allocate counter
66 nativeHandle = counterHandles->Allocate();
67 }
68 if (nativeHandle == HAL_kInvalidHandle) {
69 *status = NO_AVAILABLE_RESOURCES;
70 return HAL_kInvalidHandle;
71 }
72 auto handle = encoderHandles->Allocate();
73 if (handle == HAL_kInvalidHandle) {
74 *status = NO_AVAILABLE_RESOURCES;
75 return HAL_kInvalidHandle;
76 }
77 auto encoder = encoderHandles->Get(handle);
78 if (encoder == nullptr) { // would only occur on thread issue
79 *status = HAL_HANDLE_ERROR;
80 return HAL_kInvalidHandle;
81 }
82 int16_t index = getHandleIndex(handle);
83 SimEncoderData[index].digitalChannelA = getHandleIndex(digitalSourceHandleA);
84 SimEncoderData[index].digitalChannelB = getHandleIndex(digitalSourceHandleB);
85 SimEncoderData[index].initialized = true;
86 SimEncoderData[index].reverseDirection = reverseDirection;
87 SimEncoderData[index].simDevice = 0;
88 // TODO: Add encoding type to Sim data
89 encoder->index = index;
90 encoder->nativeHandle = nativeHandle;
91 encoder->encodingType = encodingType;
92 encoder->distancePerPulse = 1.0;
93 return handle;
94}
95
96void HAL_FreeEncoder(HAL_EncoderHandle encoderHandle, int32_t* status) {
97 auto encoder = encoderHandles->Get(encoderHandle);
98 encoderHandles->Free(encoderHandle);
99 if (encoder == nullptr) return;
100 if (isHandleType(encoder->nativeHandle, HAL_HandleEnum::FPGAEncoder)) {
101 fpgaEncoderHandles->Free(encoder->nativeHandle);
102 } else if (isHandleType(encoder->nativeHandle, HAL_HandleEnum::Counter)) {
103 counterHandles->Free(encoder->nativeHandle);
104 }
105 SimEncoderData[encoder->index].initialized = false;
106}
107
108void HAL_SetEncoderSimDevice(HAL_EncoderHandle handle,
109 HAL_SimDeviceHandle device) {
110 auto encoder = encoderHandles->Get(handle);
111 if (encoder == nullptr) return;
112 SimEncoderData[encoder->index].simDevice = device;
113}
114
115static inline int EncodingScaleFactor(Encoder* encoder) {
116 switch (encoder->encodingType) {
117 case HAL_Encoder_k1X:
118 return 1;
119 case HAL_Encoder_k2X:
120 return 2;
121 case HAL_Encoder_k4X:
122 return 4;
123 default:
124 return 0;
125 }
126}
127
128static inline double DecodingScaleFactor(Encoder* encoder) {
129 switch (encoder->encodingType) {
130 case HAL_Encoder_k1X:
131 return 1.0;
132 case HAL_Encoder_k2X:
133 return 0.5;
134 case HAL_Encoder_k4X:
135 return 0.25;
136 default:
137 return 0.0;
138 }
139}
140
141int32_t HAL_GetEncoder(HAL_EncoderHandle encoderHandle, int32_t* status) {
142 auto encoder = encoderHandles->Get(encoderHandle);
143 if (encoder == nullptr) {
144 *status = HAL_HANDLE_ERROR;
145 return 0;
146 }
147
148 return SimEncoderData[encoder->index].count;
149}
150int32_t HAL_GetEncoderRaw(HAL_EncoderHandle encoderHandle, int32_t* status) {
151 auto encoder = encoderHandles->Get(encoderHandle);
152 if (encoder == nullptr) {
153 *status = HAL_HANDLE_ERROR;
154 return 0;
155 }
156
157 return SimEncoderData[encoder->index].count /
158 DecodingScaleFactor(encoder.get());
159}
160int32_t HAL_GetEncoderEncodingScale(HAL_EncoderHandle encoderHandle,
161 int32_t* status) {
162 auto encoder = encoderHandles->Get(encoderHandle);
163 if (encoder == nullptr) {
164 *status = HAL_HANDLE_ERROR;
165 return 0;
166 }
167
168 return EncodingScaleFactor(encoder.get());
169}
170void HAL_ResetEncoder(HAL_EncoderHandle encoderHandle, int32_t* status) {
171 auto encoder = encoderHandles->Get(encoderHandle);
172 if (encoder == nullptr) {
173 *status = HAL_HANDLE_ERROR;
174 return;
175 }
176
177 SimEncoderData[encoder->index].count = 0;
178 SimEncoderData[encoder->index].period = std::numeric_limits<double>::max();
179 SimEncoderData[encoder->index].reset = true;
180}
181double HAL_GetEncoderPeriod(HAL_EncoderHandle encoderHandle, int32_t* status) {
182 auto encoder = encoderHandles->Get(encoderHandle);
183 if (encoder == nullptr) {
184 *status = HAL_HANDLE_ERROR;
185 return 0;
186 }
187
188 return SimEncoderData[encoder->index].period;
189}
190void HAL_SetEncoderMaxPeriod(HAL_EncoderHandle encoderHandle, double maxPeriod,
191 int32_t* status) {
192 auto encoder = encoderHandles->Get(encoderHandle);
193 if (encoder == nullptr) {
194 *status = HAL_HANDLE_ERROR;
195 return;
196 }
197
198 SimEncoderData[encoder->index].maxPeriod = maxPeriod;
199}
200HAL_Bool HAL_GetEncoderStopped(HAL_EncoderHandle encoderHandle,
201 int32_t* status) {
202 auto encoder = encoderHandles->Get(encoderHandle);
203 if (encoder == nullptr) {
204 *status = HAL_HANDLE_ERROR;
205 return 0;
206 }
207
208 return SimEncoderData[encoder->index].period >
209 SimEncoderData[encoder->index].maxPeriod;
210}
211HAL_Bool HAL_GetEncoderDirection(HAL_EncoderHandle encoderHandle,
212 int32_t* status) {
213 auto encoder = encoderHandles->Get(encoderHandle);
214 if (encoder == nullptr) {
215 *status = HAL_HANDLE_ERROR;
216 return 0;
217 }
218
219 return SimEncoderData[encoder->index].direction;
220}
221double HAL_GetEncoderDistance(HAL_EncoderHandle encoderHandle,
222 int32_t* status) {
223 auto encoder = encoderHandles->Get(encoderHandle);
224 if (encoder == nullptr) {
225 *status = HAL_HANDLE_ERROR;
226 return 0;
227 }
228
229 return SimEncoderData[encoder->index].count * encoder->distancePerPulse;
230}
231double HAL_GetEncoderRate(HAL_EncoderHandle encoderHandle, int32_t* status) {
232 auto encoder = encoderHandles->Get(encoderHandle);
233 if (encoder == nullptr) {
234 *status = HAL_HANDLE_ERROR;
235 return 0;
236 }
237
238 return encoder->distancePerPulse / SimEncoderData[encoder->index].period;
239}
240void HAL_SetEncoderMinRate(HAL_EncoderHandle encoderHandle, double minRate,
241 int32_t* status) {
242 auto encoder = encoderHandles->Get(encoderHandle);
243 if (encoder == nullptr) {
244 *status = HAL_HANDLE_ERROR;
245 return;
246 }
247
248 if (minRate == 0.0) {
249 *status = PARAMETER_OUT_OF_RANGE;
250 return;
251 }
252
253 SimEncoderData[encoder->index].maxPeriod =
254 encoder->distancePerPulse / minRate;
255}
256void HAL_SetEncoderDistancePerPulse(HAL_EncoderHandle encoderHandle,
257 double distancePerPulse, int32_t* status) {
258 auto encoder = encoderHandles->Get(encoderHandle);
259 if (encoder == nullptr) {
260 *status = HAL_HANDLE_ERROR;
261 return;
262 }
263
264 if (distancePerPulse == 0.0) {
265 *status = PARAMETER_OUT_OF_RANGE;
266 return;
267 }
268 encoder->distancePerPulse = distancePerPulse;
269 SimEncoderData[encoder->index].distancePerPulse = distancePerPulse;
270}
271void HAL_SetEncoderReverseDirection(HAL_EncoderHandle encoderHandle,
272 HAL_Bool reverseDirection,
273 int32_t* status) {
274 auto encoder = encoderHandles->Get(encoderHandle);
275 if (encoder == nullptr) {
276 *status = HAL_HANDLE_ERROR;
277 return;
278 }
279
280 SimEncoderData[encoder->index].reverseDirection = reverseDirection;
281}
282void HAL_SetEncoderSamplesToAverage(HAL_EncoderHandle encoderHandle,
283 int32_t samplesToAverage, int32_t* status) {
284 auto encoder = encoderHandles->Get(encoderHandle);
285 if (encoder == nullptr) {
286 *status = HAL_HANDLE_ERROR;
287 return;
288 }
289
290 SimEncoderData[encoder->index].samplesToAverage = samplesToAverage;
291}
292int32_t HAL_GetEncoderSamplesToAverage(HAL_EncoderHandle encoderHandle,
293 int32_t* status) {
294 auto encoder = encoderHandles->Get(encoderHandle);
295 if (encoder == nullptr) {
296 *status = HAL_HANDLE_ERROR;
297 return 0;
298 }
299
300 return SimEncoderData[encoder->index].samplesToAverage;
301}
302
303void HAL_SetEncoderIndexSource(HAL_EncoderHandle encoderHandle,
304 HAL_Handle digitalSourceHandle,
305 HAL_AnalogTriggerType analogTriggerType,
306 HAL_EncoderIndexingType type, int32_t* status) {
307 // Not implemented yet
308}
309
310int32_t HAL_GetEncoderFPGAIndex(HAL_EncoderHandle encoderHandle,
311 int32_t* status) {
312 auto encoder = encoderHandles->Get(encoderHandle);
313 if (encoder == nullptr) {
314 *status = HAL_HANDLE_ERROR;
315 return 0;
316 }
317
318 return encoder->index;
319}
320
321double HAL_GetEncoderDecodingScaleFactor(HAL_EncoderHandle encoderHandle,
322 int32_t* status) {
323 auto encoder = encoderHandles->Get(encoderHandle);
324 if (encoder == nullptr) {
325 *status = HAL_HANDLE_ERROR;
326 return 0.0;
327 }
328
329 return DecodingScaleFactor(encoder.get());
330}
331
332double HAL_GetEncoderDistancePerPulse(HAL_EncoderHandle encoderHandle,
333 int32_t* status) {
334 auto encoder = encoderHandles->Get(encoderHandle);
335 if (encoder == nullptr) {
336 *status = HAL_HANDLE_ERROR;
337 return 0.0;
338 }
339
340 return encoder->distancePerPulse;
341}
342
343HAL_EncoderEncodingType HAL_GetEncoderEncodingType(
344 HAL_EncoderHandle encoderHandle, int32_t* status) {
345 auto encoder = encoderHandles->Get(encoderHandle);
346 if (encoder == nullptr) {
347 *status = HAL_HANDLE_ERROR;
348 return HAL_Encoder_k4X; // default to k4x
349 }
350
351 return encoder->encodingType;
352}
353} // extern "C"