blob: ee39d2d6b674b993451e6ac067cc69012f9a523e [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2019 FIRST. All Rights Reserved. */
3/* 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/DMA.h"
9
10#include <array>
11#include <cstddef>
12#include <cstring>
13#include <memory>
14#include <type_traits>
15
16#include "AnalogInternal.h"
17#include "DigitalInternal.h"
18#include "EncoderInternal.h"
19#include "PortsInternal.h"
20#include "hal/AnalogAccumulator.h"
Austin Schuh1e69f942020-11-14 15:06:14 -080021#include "hal/AnalogGyro.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080022#include "hal/AnalogInput.h"
23#include "hal/ChipObject.h"
24#include "hal/Errors.h"
25#include "hal/HALBase.h"
26#include "hal/handles/HandlesInternal.h"
27#include "hal/handles/LimitedHandleResource.h"
28#include "hal/handles/UnlimitedHandleResource.h"
29
30using namespace hal;
31
32static_assert(std::is_standard_layout_v<HAL_DMASample>,
33 "HAL_DMASample must have standard layout");
34
35namespace {
36
37struct DMA {
38 std::unique_ptr<tDMAManager> manager;
39 std::unique_ptr<tDMA> aDMA;
40
41 HAL_DMASample captureStore;
42};
43} // namespace
44
45static constexpr size_t kChannelSize[22] = {2, 2, 4, 4, 2, 2, 4, 4, 3, 3, 2,
46 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
47
48enum DMAOffsetConstants {
49 kEnable_AI0_Low = 0,
50 kEnable_AI0_High = 1,
51 kEnable_AIAveraged0_Low = 2,
52 kEnable_AIAveraged0_High = 3,
53 kEnable_AI1_Low = 4,
54 kEnable_AI1_High = 5,
55 kEnable_AIAveraged1_Low = 6,
56 kEnable_AIAveraged1_High = 7,
57 kEnable_Accumulator0 = 8,
58 kEnable_Accumulator1 = 9,
59 kEnable_DI = 10,
60 kEnable_AnalogTriggers = 11,
61 kEnable_Counters_Low = 12,
62 kEnable_Counters_High = 13,
63 kEnable_CounterTimers_Low = 14,
64 kEnable_CounterTimers_High = 15,
65 kEnable_Encoders_Low = 16,
66 kEnable_Encoders_High = 17,
67 kEnable_EncoderTimers_Low = 18,
68 kEnable_EncoderTimers_High = 19,
69 kEnable_DutyCycle_Low = 20,
70 kEnable_DutyCycle_High = 21,
71};
72
73static hal::LimitedHandleResource<HAL_DMAHandle, DMA, 1, HAL_HandleEnum::DMA>*
74 dmaHandles;
75
76namespace hal {
77namespace init {
78void InitializeDMA() {
79 static hal::LimitedHandleResource<HAL_DMAHandle, DMA, 1, HAL_HandleEnum::DMA>
80 dH;
81 dmaHandles = &dH;
82}
83} // namespace init
84} // namespace hal
85
86extern "C" {
87
88HAL_DMAHandle HAL_InitializeDMA(int32_t* status) {
89 HAL_Handle handle = dmaHandles->Allocate();
90 if (handle == HAL_kInvalidHandle) {
91 *status = NO_AVAILABLE_RESOURCES;
92 return HAL_kInvalidHandle;
93 }
94
95 auto dma = dmaHandles->Get(handle);
96
97 if (!dma) {
98 // Can only happen on thread error
99 *status = HAL_HANDLE_ERROR;
100 return HAL_kInvalidHandle;
101 }
102
103 // Manager does not get created until DMA is started
104 dma->aDMA.reset(tDMA::create(status));
105 if (*status != 0) {
106 dmaHandles->Free(handle);
107 return HAL_kInvalidHandle;
108 }
109
110 dma->aDMA->writeConfig_ExternalClock(false, status);
111 if (*status != 0) {
112 dmaHandles->Free(handle);
113 return HAL_kInvalidHandle;
114 }
115
116 HAL_SetDMARate(handle, 1, status);
117 if (*status != 0) {
118 dmaHandles->Free(handle);
119 return HAL_kInvalidHandle;
120 }
121
122 HAL_SetDMAPause(handle, false, status);
123 return handle;
124}
125
126void HAL_FreeDMA(HAL_DMAHandle handle) {
127 auto dma = dmaHandles->Get(handle);
128 dmaHandles->Free(handle);
129
130 if (!dma) return;
131
132 int32_t status = 0;
133 if (dma->manager) {
134 dma->manager->stop(&status);
135 }
136}
137
138void HAL_SetDMAPause(HAL_DMAHandle handle, HAL_Bool pause, int32_t* status) {
139 auto dma = dmaHandles->Get(handle);
140 if (!dma) {
141 *status = HAL_HANDLE_ERROR;
142 return;
143 }
144
145 dma->aDMA->writeConfig_Pause(pause, status);
146}
147void HAL_SetDMARate(HAL_DMAHandle handle, int32_t cycles, int32_t* status) {
148 auto dma = dmaHandles->Get(handle);
149 if (!dma) {
150 *status = HAL_HANDLE_ERROR;
151 return;
152 }
153
154 if (cycles < 1) {
155 cycles = 1;
156 }
157
158 dma->aDMA->writeRate(static_cast<uint32_t>(cycles), status);
159}
160
161void HAL_AddDMAEncoder(HAL_DMAHandle handle, HAL_EncoderHandle encoderHandle,
162 int32_t* status) {
163 // Detect a counter encoder vs an actual encoder, and use the right DMA calls
164 HAL_FPGAEncoderHandle fpgaEncoderHandle = HAL_kInvalidHandle;
165 HAL_CounterHandle counterHandle = HAL_kInvalidHandle;
166
167 bool validEncoderHandle = hal::GetEncoderBaseHandle(
168 encoderHandle, &fpgaEncoderHandle, &counterHandle);
169
170 if (!validEncoderHandle) {
171 *status = HAL_HANDLE_ERROR;
172 return;
173 }
174
175 if (counterHandle != HAL_kInvalidHandle) {
176 HAL_AddDMACounter(handle, counterHandle, status);
177 return;
178 }
179
180 auto dma = dmaHandles->Get(handle);
181 if (!dma) {
182 *status = HAL_HANDLE_ERROR;
183 return;
184 }
185
186 if (dma->manager) {
187 *status = HAL_INVALID_DMA_ADDITION;
188 return;
189 }
190
191 if (getHandleType(fpgaEncoderHandle) != HAL_HandleEnum::FPGAEncoder) {
192 *status = HAL_HANDLE_ERROR;
193 return;
194 }
195
196 int32_t index = getHandleIndex(fpgaEncoderHandle);
197 if (index < 0) {
198 *status = HAL_HANDLE_ERROR;
199 return;
200 }
201
202 if (index < 4) {
203 dma->aDMA->writeConfig_Enable_Encoders_Low(true, status);
204 } else if (index < 8) {
205 dma->aDMA->writeConfig_Enable_Encoders_High(true, status);
206 } else {
207 *status = NiFpga_Status_InvalidParameter;
208 }
209}
210
211void HAL_AddDMAEncoderPeriod(HAL_DMAHandle handle,
212 HAL_EncoderHandle encoderHandle, int32_t* status) {
213 // Detect a counter encoder vs an actual encoder, and use the right DMA calls
214 HAL_FPGAEncoderHandle fpgaEncoderHandle = HAL_kInvalidHandle;
215 HAL_CounterHandle counterHandle = HAL_kInvalidHandle;
216
217 bool validEncoderHandle = hal::GetEncoderBaseHandle(
218 encoderHandle, &fpgaEncoderHandle, &counterHandle);
219
220 if (!validEncoderHandle) {
221 *status = HAL_HANDLE_ERROR;
222 return;
223 }
224
225 if (counterHandle != HAL_kInvalidHandle) {
226 HAL_AddDMACounterPeriod(handle, counterHandle, status);
227 return;
228 }
229
230 auto dma = dmaHandles->Get(handle);
231 if (!dma) {
232 *status = HAL_HANDLE_ERROR;
233 return;
234 }
235
236 if (dma->manager) {
237 *status = HAL_INVALID_DMA_ADDITION;
238 return;
239 }
240
241 if (getHandleType(fpgaEncoderHandle) != HAL_HandleEnum::FPGAEncoder) {
242 *status = HAL_HANDLE_ERROR;
243 return;
244 }
245
246 int32_t index = getHandleIndex(fpgaEncoderHandle);
247 if (index < 0) {
248 *status = HAL_HANDLE_ERROR;
249 return;
250 }
251
252 if (index < 4) {
253 dma->aDMA->writeConfig_Enable_EncoderTimers_Low(true, status);
254 } else if (index < 8) {
255 dma->aDMA->writeConfig_Enable_EncoderTimers_High(true, status);
256 } else {
257 *status = NiFpga_Status_InvalidParameter;
258 }
259}
260
261void HAL_AddDMACounter(HAL_DMAHandle handle, HAL_CounterHandle counterHandle,
262 int32_t* status) {
263 auto dma = dmaHandles->Get(handle);
264 if (!dma) {
265 *status = HAL_HANDLE_ERROR;
266 return;
267 }
268
269 if (dma->manager) {
270 *status = HAL_INVALID_DMA_ADDITION;
271 return;
272 }
273
274 if (getHandleType(counterHandle) != HAL_HandleEnum::Counter) {
275 *status = HAL_HANDLE_ERROR;
276 return;
277 }
278
279 int32_t index = getHandleIndex(counterHandle);
280 if (index < 0) {
281 *status = HAL_HANDLE_ERROR;
282 return;
283 }
284
285 if (index < 4) {
286 dma->aDMA->writeConfig_Enable_Counters_Low(true, status);
287 } else if (index < 8) {
288 dma->aDMA->writeConfig_Enable_Counters_High(true, status);
289 } else {
290 *status = NiFpga_Status_InvalidParameter;
291 }
292}
293
294void HAL_AddDMACounterPeriod(HAL_DMAHandle handle,
295 HAL_CounterHandle counterHandle, int32_t* status) {
296 auto dma = dmaHandles->Get(handle);
297 if (!dma) {
298 *status = HAL_HANDLE_ERROR;
299 return;
300 }
301
302 if (dma->manager) {
303 *status = HAL_INVALID_DMA_ADDITION;
304 return;
305 }
306
307 if (getHandleType(counterHandle) != HAL_HandleEnum::Counter) {
308 *status = HAL_HANDLE_ERROR;
309 return;
310 }
311
312 int32_t index = getHandleIndex(counterHandle);
313 if (index < 0) {
314 *status = HAL_HANDLE_ERROR;
315 return;
316 }
317
318 if (index < 4) {
319 dma->aDMA->writeConfig_Enable_CounterTimers_Low(true, status);
320 } else if (index < 8) {
321 dma->aDMA->writeConfig_Enable_CounterTimers_High(true, status);
322 } else {
323 *status = NiFpga_Status_InvalidParameter;
324 }
325}
326
327void HAL_AddDMADigitalSource(HAL_DMAHandle handle,
328 HAL_Handle digitalSourceHandle, int32_t* status) {
329 auto dma = dmaHandles->Get(handle);
330 if (!dma) {
331 *status = HAL_HANDLE_ERROR;
332 return;
333 }
334
335 if (dma->manager) {
336 *status = HAL_INVALID_DMA_ADDITION;
337 return;
338 }
339
340 if (isHandleType(digitalSourceHandle, HAL_HandleEnum::AnalogTrigger)) {
341 dma->aDMA->writeConfig_Enable_AnalogTriggers(true, status);
342 } else if (isHandleType(digitalSourceHandle, HAL_HandleEnum::DIO)) {
343 dma->aDMA->writeConfig_Enable_DI(true, status);
344 } else {
345 *status = NiFpga_Status_InvalidParameter;
346 }
347}
348
349void HAL_AddDMAAnalogInput(HAL_DMAHandle handle,
350 HAL_AnalogInputHandle aInHandle, int32_t* status) {
351 auto dma = dmaHandles->Get(handle);
352 if (!dma) {
353 *status = HAL_HANDLE_ERROR;
354 return;
355 }
356
357 if (dma->manager) {
358 *status = HAL_INVALID_DMA_ADDITION;
359 return;
360 }
361
362 if (getHandleType(aInHandle) != HAL_HandleEnum::AnalogInput) {
363 *status = HAL_HANDLE_ERROR;
364 return;
365 }
366
367 int32_t index = getHandleIndex(aInHandle);
368 if (index < 0) {
369 *status = HAL_HANDLE_ERROR;
370 return;
371 }
372
373 if (index < 4) {
374 dma->aDMA->writeConfig_Enable_AI0_Low(true, status);
375 } else if (index < 8) {
376 dma->aDMA->writeConfig_Enable_AI0_High(true, status);
377 } else {
378 *status = NiFpga_Status_InvalidParameter;
379 }
380}
381
382void HAL_AddDMADutyCycle(HAL_DMAHandle handle,
383 HAL_DutyCycleHandle dutyCycleHandle, int32_t* status) {
384 auto dma = dmaHandles->Get(handle);
385 if (!dma) {
386 *status = HAL_HANDLE_ERROR;
387 return;
388 }
389
390 if (dma->manager) {
391 *status = HAL_INVALID_DMA_ADDITION;
392 return;
393 }
394
395 if (getHandleType(dutyCycleHandle) != HAL_HandleEnum::DutyCycle) {
396 *status = HAL_HANDLE_ERROR;
397 return;
398 }
399
400 int32_t index = getHandleIndex(dutyCycleHandle);
401 if (index < 0) {
402 *status = HAL_HANDLE_ERROR;
403 return;
404 }
405
406 if (index < 4) {
407 dma->aDMA->writeConfig_Enable_DutyCycle_Low(true, status);
408 } else if (index < 8) {
409 dma->aDMA->writeConfig_Enable_DutyCycle_High(true, status);
410 } else {
411 *status = NiFpga_Status_InvalidParameter;
412 }
413}
414
415void HAL_AddDMAAveragedAnalogInput(HAL_DMAHandle handle,
416 HAL_AnalogInputHandle aInHandle,
417 int32_t* status) {
418 auto dma = dmaHandles->Get(handle);
419 if (!dma) {
420 *status = HAL_HANDLE_ERROR;
421 return;
422 }
423
424 if (dma->manager) {
425 *status = HAL_INVALID_DMA_ADDITION;
426 return;
427 }
428
429 if (getHandleType(aInHandle) != HAL_HandleEnum::AnalogInput) {
430 *status = HAL_HANDLE_ERROR;
431 return;
432 }
433
434 int32_t index = getHandleIndex(aInHandle);
435 if (index < 0) {
436 *status = HAL_HANDLE_ERROR;
437 return;
438 }
439
440 if (index < 4) {
441 dma->aDMA->writeConfig_Enable_AIAveraged0_Low(true, status);
442 } else if (index < 8) {
443 dma->aDMA->writeConfig_Enable_AIAveraged0_High(true, status);
444 } else {
445 *status = NiFpga_Status_InvalidParameter;
446 }
447}
448
449void HAL_AddDMAAnalogAccumulator(HAL_DMAHandle handle,
450 HAL_AnalogInputHandle aInHandle,
451 int32_t* status) {
452 auto dma = dmaHandles->Get(handle);
453 if (!dma) {
454 *status = HAL_HANDLE_ERROR;
455 return;
456 }
457
458 if (dma->manager) {
459 *status = HAL_INVALID_DMA_ADDITION;
460 return;
461 }
462
463 if (!HAL_IsAccumulatorChannel(aInHandle, status)) {
464 *status = HAL_INVALID_ACCUMULATOR_CHANNEL;
465 return;
466 }
467
468 int32_t index = getHandleIndex(aInHandle);
469 if (index < 0) {
470 *status = HAL_HANDLE_ERROR;
471 return;
472 }
473
474 if (index == 0) {
475 dma->aDMA->writeConfig_Enable_Accumulator0(true, status);
476 } else if (index == 1) {
477 dma->aDMA->writeConfig_Enable_Accumulator1(true, status);
478 } else {
479 *status = NiFpga_Status_InvalidParameter;
480 }
481}
482
483void HAL_SetDMAExternalTrigger(HAL_DMAHandle handle,
484 HAL_Handle digitalSourceHandle,
485 HAL_AnalogTriggerType analogTriggerType,
486 HAL_Bool rising, HAL_Bool falling,
487 int32_t* status) {
488 auto dma = dmaHandles->Get(handle);
489 if (!dma) {
490 *status = HAL_HANDLE_ERROR;
491 return;
492 }
493
494 if (dma->manager) {
495 *status = HAL_INVALID_DMA_ADDITION;
496 return;
497 }
498
499 int index = 0;
500 auto triggerChannels = dma->captureStore.triggerChannels;
501 do {
502 if (((triggerChannels >> index) & 0x1) == 0) {
503 break;
504 }
505 index++;
506 } while (index < 8);
507
508 if (index == 8) {
509 *status = NO_AVAILABLE_RESOURCES;
510 return;
511 }
512
513 dma->captureStore.triggerChannels |= (1 << index);
514
515 auto channelIndex = index;
516
517 auto isExternalClock = dma->aDMA->readConfig_ExternalClock(status);
518 if (*status == 0 && !isExternalClock) {
519 dma->aDMA->writeConfig_ExternalClock(true, status);
520 if (*status != 0) return;
521 } else if (*status != 0) {
522 return;
523 }
524
525 uint8_t pin = 0;
526 uint8_t module = 0;
527 bool analogTrigger = false;
528 bool success = remapDigitalSource(digitalSourceHandle, analogTriggerType, pin,
529 module, analogTrigger);
530
531 if (!success) {
532 *status = PARAMETER_OUT_OF_RANGE;
533 return;
534 }
535
536 tDMA::tExternalTriggers newTrigger;
537 newTrigger.FallingEdge = falling;
538 newTrigger.RisingEdge = rising;
539 newTrigger.ExternalClockSource_AnalogTrigger = analogTrigger;
540 newTrigger.ExternalClockSource_Channel = pin;
541 newTrigger.ExternalClockSource_Module = module;
542
543 dma->aDMA->writeExternalTriggers(channelIndex / 4, channelIndex % 4,
544 newTrigger, status);
545}
546
547void HAL_StartDMA(HAL_DMAHandle handle, int32_t queueDepth, int32_t* status) {
548 auto dma = dmaHandles->Get(handle);
549 if (!dma) {
550 *status = HAL_HANDLE_ERROR;
551 return;
552 }
553
554 if (dma->manager) {
555 *status = INCOMPATIBLE_STATE;
556 return;
557 }
558
559 tDMA::tConfig config = dma->aDMA->readConfig(status);
560 if (*status != 0) return;
561
562 {
563 size_t accum_size = 0;
564#define SET_SIZE(bit) \
565 if (config.bit) { \
566 dma->captureStore.channelOffsets[k##bit] = accum_size; \
567 accum_size += kChannelSize[k##bit]; \
568 } else { \
569 dma->captureStore.channelOffsets[k##bit] = -1; \
570 }
571 SET_SIZE(Enable_AI0_Low);
572 SET_SIZE(Enable_AI0_High);
573 SET_SIZE(Enable_AIAveraged0_Low);
574 SET_SIZE(Enable_AIAveraged0_High);
575 SET_SIZE(Enable_AI1_Low);
576 SET_SIZE(Enable_AI1_High);
577 SET_SIZE(Enable_AIAveraged1_Low);
578 SET_SIZE(Enable_AIAveraged1_High);
579 SET_SIZE(Enable_Accumulator0);
580 SET_SIZE(Enable_Accumulator1);
581 SET_SIZE(Enable_DI);
582 SET_SIZE(Enable_AnalogTriggers);
583 SET_SIZE(Enable_Counters_Low);
584 SET_SIZE(Enable_Counters_High);
585 SET_SIZE(Enable_CounterTimers_Low);
586 SET_SIZE(Enable_CounterTimers_High);
587 SET_SIZE(Enable_Encoders_Low);
588 SET_SIZE(Enable_Encoders_High);
589 SET_SIZE(Enable_EncoderTimers_Low);
590 SET_SIZE(Enable_EncoderTimers_High);
591 SET_SIZE(Enable_DutyCycle_Low);
592 SET_SIZE(Enable_DutyCycle_High);
593#undef SET_SIZE
594 dma->captureStore.captureSize = accum_size + 1;
595 }
596
597 dma->manager = std::make_unique<tDMAManager>(
598 g_DMA_index, queueDepth * dma->captureStore.captureSize, status);
599 if (*status != 0) {
600 return;
601 }
602
603 dma->manager->start(status);
604 dma->manager->stop(status);
605 dma->manager->start(status);
606}
607
608void HAL_StopDMA(HAL_DMAHandle handle, int32_t* status) {
609 auto dma = dmaHandles->Get(handle);
610 if (!dma) {
611 *status = HAL_HANDLE_ERROR;
612 return;
613 }
614
615 if (dma->manager) {
616 dma->manager->stop(status);
617 dma->manager = nullptr;
618 }
619}
620
621void* HAL_GetDMADirectPointer(HAL_DMAHandle handle) {
622 auto dma = dmaHandles->Get(handle);
623 return dma.get();
624}
625
626enum HAL_DMAReadStatus HAL_ReadDMADirect(void* dmaPointer,
627 HAL_DMASample* dmaSample,
628 int32_t timeoutMs,
629 int32_t* remainingOut,
630 int32_t* status) {
631 DMA* dma = static_cast<DMA*>(dmaPointer);
632 *remainingOut = 0;
633 size_t remainingBytes = 0;
634
635 if (!dma->manager) {
636 *status = INCOMPATIBLE_STATE;
637 return HAL_DMA_ERROR;
638 }
639
640 dma->manager->read(dmaSample->readBuffer, dma->captureStore.captureSize,
641 timeoutMs, &remainingBytes, status);
642
643 *remainingOut = remainingBytes / dma->captureStore.captureSize;
644
645 if (*status == 0) {
646 uint32_t lower_sample =
647 dmaSample->readBuffer[dma->captureStore.captureSize - 1];
648 dmaSample->timeStamp = HAL_ExpandFPGATime(lower_sample, status);
649 if (*status != 0) {
650 return HAL_DMA_ERROR;
651 }
652 dmaSample->triggerChannels = dma->captureStore.triggerChannels;
653 dmaSample->captureSize = dma->captureStore.captureSize;
654 std::memcpy(dmaSample->channelOffsets, dma->captureStore.channelOffsets,
655 sizeof(dmaSample->channelOffsets));
656 return HAL_DMA_OK;
657 } else if (*status == NiFpga_Status_FifoTimeout) {
658 *status = 0;
659 return HAL_DMA_TIMEOUT;
660 } else {
661 return HAL_DMA_ERROR;
662 }
663}
664
665enum HAL_DMAReadStatus HAL_ReadDMA(HAL_DMAHandle handle,
666 HAL_DMASample* dmaSample, int32_t timeoutMs,
667 int32_t* remainingOut, int32_t* status) {
668 auto dma = dmaHandles->Get(handle);
669 if (!dma) {
670 *status = HAL_HANDLE_ERROR;
671 return HAL_DMA_ERROR;
672 }
673
674 return HAL_ReadDMADirect(dma.get(), dmaSample, timeoutMs, remainingOut,
675 status);
676}
677
678static uint32_t ReadDMAValue(const HAL_DMASample& dma, int valueType, int index,
679 int32_t* status) {
680 auto offset = dma.channelOffsets[valueType];
681 if (offset == -1) {
682 *status = NiFpga_Status_ResourceNotFound;
683 return 0;
684 }
685 return dma.readBuffer[offset + index];
686}
687
688uint64_t HAL_GetDMASampleTime(const HAL_DMASample* dmaSample, int32_t* status) {
689 return dmaSample->timeStamp;
690}
691
692int32_t HAL_GetDMASampleEncoderRaw(const HAL_DMASample* dmaSample,
693 HAL_EncoderHandle encoderHandle,
694 int32_t* status) {
695 HAL_FPGAEncoderHandle fpgaEncoderHandle = 0;
696 HAL_CounterHandle counterHandle = 0;
697 bool validEncoderHandle = hal::GetEncoderBaseHandle(
698 encoderHandle, &fpgaEncoderHandle, &counterHandle);
699
700 if (!validEncoderHandle) {
701 *status = HAL_HANDLE_ERROR;
702 return -1;
703 }
704
705 if (counterHandle != HAL_kInvalidHandle) {
706 return HAL_GetDMASampleCounter(dmaSample, counterHandle, status);
707 }
708
709 if (getHandleType(fpgaEncoderHandle) != HAL_HandleEnum::FPGAEncoder) {
710 *status = HAL_HANDLE_ERROR;
711 return -1;
712 }
713
714 int32_t index = getHandleIndex(fpgaEncoderHandle);
715 if (index < 0) {
716 *status = HAL_HANDLE_ERROR;
717 return -1;
718 }
719
720 uint32_t dmaWord = 0;
721 *status = 0;
722 if (index < 4) {
723 dmaWord = ReadDMAValue(*dmaSample, kEnable_Encoders_Low, index, status);
724 } else if (index < 8) {
725 dmaWord =
726 ReadDMAValue(*dmaSample, kEnable_Encoders_High, index - 4, status);
727 } else {
728 *status = NiFpga_Status_ResourceNotFound;
729 }
730 if (*status != 0) {
731 return -1;
732 }
733
734 return static_cast<int32_t>(dmaWord) >> 1;
735}
736
737int32_t HAL_GetDMASampleEncoderPeriodRaw(const HAL_DMASample* dmaSample,
738 HAL_EncoderHandle encoderHandle,
739 int32_t* status) {
740 HAL_FPGAEncoderHandle fpgaEncoderHandle = 0;
741 HAL_CounterHandle counterHandle = 0;
742 bool validEncoderHandle = hal::GetEncoderBaseHandle(
743 encoderHandle, &fpgaEncoderHandle, &counterHandle);
744
745 if (!validEncoderHandle) {
746 *status = HAL_HANDLE_ERROR;
747 return -1;
748 }
749
750 if (counterHandle != HAL_kInvalidHandle) {
751 return HAL_GetDMASampleCounterPeriod(dmaSample, counterHandle, status);
752 }
753
754 if (getHandleType(fpgaEncoderHandle) != HAL_HandleEnum::FPGAEncoder) {
755 *status = HAL_HANDLE_ERROR;
756 return -1;
757 }
758
759 int32_t index = getHandleIndex(fpgaEncoderHandle);
760 if (index < 0) {
761 *status = HAL_HANDLE_ERROR;
762 return -1;
763 }
764
765 uint32_t dmaWord = 0;
766 *status = 0;
767 if (index < 4) {
768 dmaWord =
769 ReadDMAValue(*dmaSample, kEnable_EncoderTimers_Low, index, status);
770 } else if (index < 8) {
771 dmaWord =
772 ReadDMAValue(*dmaSample, kEnable_EncoderTimers_High, index - 4, status);
773 } else {
774 *status = NiFpga_Status_ResourceNotFound;
775 }
776 if (*status != 0) {
777 return -1;
778 }
779
780 return static_cast<int32_t>(dmaWord) & 0x7FFFFF;
781}
782
783int32_t HAL_GetDMASampleCounter(const HAL_DMASample* dmaSample,
784 HAL_CounterHandle counterHandle,
785 int32_t* status) {
786 if (getHandleType(counterHandle) != HAL_HandleEnum::Counter) {
787 *status = HAL_HANDLE_ERROR;
788 return -1;
789 }
790
791 int32_t index = getHandleIndex(counterHandle);
792 if (index < 0) {
793 *status = HAL_HANDLE_ERROR;
794 return -1;
795 }
796
797 uint32_t dmaWord = 0;
798 *status = 0;
799 if (index < 4) {
800 dmaWord = ReadDMAValue(*dmaSample, kEnable_Counters_Low, index, status);
801 } else if (index < 8) {
802 dmaWord =
803 ReadDMAValue(*dmaSample, kEnable_Counters_High, index - 4, status);
804 } else {
805 *status = NiFpga_Status_ResourceNotFound;
806 }
807 if (*status != 0) {
808 return -1;
809 }
810
811 return static_cast<int32_t>(dmaWord) >> 1;
812}
813
814int32_t HAL_GetDMASampleCounterPeriod(const HAL_DMASample* dmaSample,
815 HAL_CounterHandle counterHandle,
816 int32_t* status) {
817 if (getHandleType(counterHandle) != HAL_HandleEnum::Counter) {
818 *status = HAL_HANDLE_ERROR;
819 return -1;
820 }
821
822 int32_t index = getHandleIndex(counterHandle);
823 if (index < 0) {
824 *status = HAL_HANDLE_ERROR;
825 return -1;
826 }
827
828 uint32_t dmaWord = 0;
829 *status = 0;
830 if (index < 4) {
831 dmaWord =
832 ReadDMAValue(*dmaSample, kEnable_CounterTimers_Low, index, status);
833 } else if (index < 8) {
834 dmaWord =
835 ReadDMAValue(*dmaSample, kEnable_CounterTimers_High, index - 4, status);
836 } else {
837 *status = NiFpga_Status_ResourceNotFound;
838 }
839 if (*status != 0) {
840 return -1;
841 }
842
843 return static_cast<int32_t>(dmaWord) & 0x7FFFFF;
844}
845
846HAL_Bool HAL_GetDMASampleDigitalSource(const HAL_DMASample* dmaSample,
847 HAL_Handle dSourceHandle,
848 int32_t* status) {
849 HAL_HandleEnum handleType = getHandleType(dSourceHandle);
850 int32_t index = getHandleIndex(dSourceHandle);
851
852 *status = 0;
853 if (handleType == HAL_HandleEnum::DIO) {
854 auto readVal = ReadDMAValue(*dmaSample, kEnable_DI, 0, status);
855 if (*status == 0) {
856 if (index < kNumDigitalHeaders) {
857 return (readVal >> index) & 0x1;
858 } else {
859 return (readVal >> (index + 6)) & 0x1;
860 }
861 }
862 } else if (handleType == HAL_HandleEnum::AnalogTrigger) {
863 auto readVal = ReadDMAValue(*dmaSample, kEnable_AnalogTriggers, 0, status);
864 if (*status == 0) {
865 return (readVal >> index) & 0x1;
866 }
867 } else {
868 *status = NiFpga_Status_InvalidParameter;
869 }
870 return false;
871}
872int32_t HAL_GetDMASampleAnalogInputRaw(const HAL_DMASample* dmaSample,
873 HAL_AnalogInputHandle aInHandle,
874 int32_t* status) {
875 if (getHandleType(aInHandle) != HAL_HandleEnum::AnalogInput) {
876 *status = HAL_HANDLE_ERROR;
877 return 0xFFFFFFFF;
878 }
879
880 int32_t index = getHandleIndex(aInHandle);
881 if (index < 0) {
882 *status = HAL_HANDLE_ERROR;
883 return 0xFFFFFFFF;
884 }
885
886 uint32_t dmaWord = 0;
887 if (index < 4) {
888 dmaWord = ReadDMAValue(*dmaSample, kEnable_AI0_Low, index / 2, status);
889 } else if (index < 8) {
890 dmaWord =
891 ReadDMAValue(*dmaSample, kEnable_AI0_High, (index - 4) / 2, status);
892 } else {
893 *status = NiFpga_Status_ResourceNotFound;
894 }
895 if (*status != 0) {
896 return 0xFFFFFFFF;
897 }
898
899 if (index % 2) {
900 return (dmaWord >> 16) & 0xffff;
901 } else {
902 return dmaWord & 0xffff;
903 }
904}
905
906int32_t HAL_GetDMASampleAveragedAnalogInputRaw(const HAL_DMASample* dmaSample,
907 HAL_AnalogInputHandle aInHandle,
908 int32_t* status) {
909 if (getHandleType(aInHandle) != HAL_HandleEnum::AnalogInput) {
910 *status = HAL_HANDLE_ERROR;
911 return 0xFFFFFFFF;
912 }
913
914 int32_t index = getHandleIndex(aInHandle);
915 if (index < 0) {
916 *status = HAL_HANDLE_ERROR;
917 return 0xFFFFFFFF;
918 }
919
920 uint32_t dmaWord = 0;
921 if (index < 4) {
922 dmaWord = ReadDMAValue(*dmaSample, kEnable_AIAveraged0_Low, index, status);
923 } else if (index < 8) {
924 dmaWord =
925 ReadDMAValue(*dmaSample, kEnable_AIAveraged0_High, index - 4, status);
926 } else {
927 *status = NiFpga_Status_ResourceNotFound;
928 }
929 if (*status != 0) {
930 return 0xFFFFFFFF;
931 }
932
933 return dmaWord;
934}
935
936void HAL_GetDMASampleAnalogAccumulator(const HAL_DMASample* dmaSample,
937 HAL_AnalogInputHandle aInHandle,
938 int64_t* count, int64_t* value,
939 int32_t* status) {
940 if (!HAL_IsAccumulatorChannel(aInHandle, status)) {
941 *status = HAL_INVALID_ACCUMULATOR_CHANNEL;
942 return;
943 }
944
945 int32_t index = getHandleIndex(aInHandle);
946 if (index < 0) {
947 *status = HAL_HANDLE_ERROR;
948 return;
949 }
950
951 uint32_t dmaWord = 0;
952 uint32_t dmaValue1 = 0;
953 uint32_t dmaValue2 = 0;
954 if (index == 0) {
955 dmaWord = ReadDMAValue(*dmaSample, kEnable_Accumulator0, index, status);
956 dmaValue1 =
957 ReadDMAValue(*dmaSample, kEnable_Accumulator0, index + 1, status);
958 dmaValue2 =
959 ReadDMAValue(*dmaSample, kEnable_Accumulator0, index + 2, status);
960 } else if (index == 1) {
961 dmaWord = ReadDMAValue(*dmaSample, kEnable_Accumulator1, index - 1, status);
962 dmaValue1 = ReadDMAValue(*dmaSample, kEnable_Accumulator0, index, status);
963 dmaValue2 =
964 ReadDMAValue(*dmaSample, kEnable_Accumulator0, index + 1, status);
965 } else {
966 *status = NiFpga_Status_ResourceNotFound;
967 }
968 if (*status != 0) {
969 return;
970 }
971
972 *count = dmaWord;
973
974 *value = static_cast<int64_t>(dmaValue1) << 32 | dmaValue2;
975}
976
977int32_t HAL_GetDMASampleDutyCycleOutputRaw(const HAL_DMASample* dmaSample,
978 HAL_DutyCycleHandle dutyCycleHandle,
979 int32_t* status) {
980 if (getHandleType(dutyCycleHandle) != HAL_HandleEnum::DutyCycle) {
981 *status = HAL_HANDLE_ERROR;
982 return -1;
983 }
984
985 int32_t index = getHandleIndex(dutyCycleHandle);
986 if (index < 0) {
987 *status = HAL_HANDLE_ERROR;
988 return -1;
989 }
990
991 uint32_t dmaWord = 0;
992 *status = 0;
993 if (index < 4) {
994 dmaWord = ReadDMAValue(*dmaSample, kEnable_DutyCycle_Low, index, status);
995 } else if (index < 8) {
996 dmaWord =
997 ReadDMAValue(*dmaSample, kEnable_DutyCycle_High, index - 4, status);
998 } else {
999 *status = NiFpga_Status_ResourceNotFound;
1000 }
1001 if (*status != 0) {
1002 return -1;
1003 }
1004 return dmaWord;
1005}
1006} // extern "C"