Rename our allwpilib (which is now 2020) to not have 2019 in the name

Change-Id: I3c07f85ed32ab8b97db765a9b43f2a6ce7da964a
diff --git a/hal/src/main/native/athena/DMA.cpp b/hal/src/main/native/athena/DMA.cpp
new file mode 100644
index 0000000..19c3068
--- /dev/null
+++ b/hal/src/main/native/athena/DMA.cpp
@@ -0,0 +1,1006 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2019 FIRST. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#include "hal/DMA.h"
+
+#include <array>
+#include <cstddef>
+#include <cstring>
+#include <memory>
+#include <type_traits>
+
+#include "AnalogInternal.h"
+#include "DigitalInternal.h"
+#include "EncoderInternal.h"
+#include "PortsInternal.h"
+#include "hal/AnalogAccumulator.h"
+//#include "hal/AnalogGyro.h"
+#include "hal/AnalogInput.h"
+#include "hal/ChipObject.h"
+#include "hal/Errors.h"
+#include "hal/HALBase.h"
+#include "hal/handles/HandlesInternal.h"
+#include "hal/handles/LimitedHandleResource.h"
+#include "hal/handles/UnlimitedHandleResource.h"
+
+using namespace hal;
+
+static_assert(std::is_standard_layout_v<HAL_DMASample>,
+              "HAL_DMASample must have standard layout");
+
+namespace {
+
+struct DMA {
+  std::unique_ptr<tDMAManager> manager;
+  std::unique_ptr<tDMA> aDMA;
+
+  HAL_DMASample captureStore;
+};
+}  // namespace
+
+static constexpr size_t kChannelSize[22] = {2, 2, 4, 4, 2, 2, 4, 4, 3, 3, 2,
+                                            1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
+
+enum DMAOffsetConstants {
+  kEnable_AI0_Low = 0,
+  kEnable_AI0_High = 1,
+  kEnable_AIAveraged0_Low = 2,
+  kEnable_AIAveraged0_High = 3,
+  kEnable_AI1_Low = 4,
+  kEnable_AI1_High = 5,
+  kEnable_AIAveraged1_Low = 6,
+  kEnable_AIAveraged1_High = 7,
+  kEnable_Accumulator0 = 8,
+  kEnable_Accumulator1 = 9,
+  kEnable_DI = 10,
+  kEnable_AnalogTriggers = 11,
+  kEnable_Counters_Low = 12,
+  kEnable_Counters_High = 13,
+  kEnable_CounterTimers_Low = 14,
+  kEnable_CounterTimers_High = 15,
+  kEnable_Encoders_Low = 16,
+  kEnable_Encoders_High = 17,
+  kEnable_EncoderTimers_Low = 18,
+  kEnable_EncoderTimers_High = 19,
+  kEnable_DutyCycle_Low = 20,
+  kEnable_DutyCycle_High = 21,
+};
+
+static hal::LimitedHandleResource<HAL_DMAHandle, DMA, 1, HAL_HandleEnum::DMA>*
+    dmaHandles;
+
+namespace hal {
+namespace init {
+void InitializeDMA() {
+  static hal::LimitedHandleResource<HAL_DMAHandle, DMA, 1, HAL_HandleEnum::DMA>
+      dH;
+  dmaHandles = &dH;
+}
+}  // namespace init
+}  // namespace hal
+
+extern "C" {
+
+HAL_DMAHandle HAL_InitializeDMA(int32_t* status) {
+  HAL_Handle handle = dmaHandles->Allocate();
+  if (handle == HAL_kInvalidHandle) {
+    *status = NO_AVAILABLE_RESOURCES;
+    return HAL_kInvalidHandle;
+  }
+
+  auto dma = dmaHandles->Get(handle);
+
+  if (!dma) {
+    // Can only happen on thread error
+    *status = HAL_HANDLE_ERROR;
+    return HAL_kInvalidHandle;
+  }
+
+  // Manager does not get created until DMA is started
+  dma->aDMA.reset(tDMA::create(status));
+  if (*status != 0) {
+    dmaHandles->Free(handle);
+    return HAL_kInvalidHandle;
+  }
+
+  dma->aDMA->writeConfig_ExternalClock(false, status);
+  if (*status != 0) {
+    dmaHandles->Free(handle);
+    return HAL_kInvalidHandle;
+  }
+
+  HAL_SetDMARate(handle, 1, status);
+  if (*status != 0) {
+    dmaHandles->Free(handle);
+    return HAL_kInvalidHandle;
+  }
+
+  HAL_SetDMAPause(handle, false, status);
+  return handle;
+}
+
+void HAL_FreeDMA(HAL_DMAHandle handle) {
+  auto dma = dmaHandles->Get(handle);
+  dmaHandles->Free(handle);
+
+  if (!dma) return;
+
+  int32_t status = 0;
+  if (dma->manager) {
+    dma->manager->stop(&status);
+  }
+}
+
+void HAL_SetDMAPause(HAL_DMAHandle handle, HAL_Bool pause, int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  dma->aDMA->writeConfig_Pause(pause, status);
+}
+void HAL_SetDMARate(HAL_DMAHandle handle, int32_t cycles, int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (cycles < 1) {
+    cycles = 1;
+  }
+
+  dma->aDMA->writeRate(static_cast<uint32_t>(cycles), status);
+}
+
+void HAL_AddDMAEncoder(HAL_DMAHandle handle, HAL_EncoderHandle encoderHandle,
+                       int32_t* status) {
+  // Detect a counter encoder vs an actual encoder, and use the right DMA calls
+  HAL_FPGAEncoderHandle fpgaEncoderHandle = HAL_kInvalidHandle;
+  HAL_CounterHandle counterHandle = HAL_kInvalidHandle;
+
+  bool validEncoderHandle = hal::GetEncoderBaseHandle(
+      encoderHandle, &fpgaEncoderHandle, &counterHandle);
+
+  if (!validEncoderHandle) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (counterHandle != HAL_kInvalidHandle) {
+    HAL_AddDMACounter(handle, counterHandle, status);
+    return;
+  }
+
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = HAL_INVALID_DMA_ADDITION;
+    return;
+  }
+
+  if (getHandleType(fpgaEncoderHandle) != HAL_HandleEnum::FPGAEncoder) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  int32_t index = getHandleIndex(fpgaEncoderHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (index < 4) {
+    dma->aDMA->writeConfig_Enable_Encoders_Low(true, status);
+  } else if (index < 8) {
+    dma->aDMA->writeConfig_Enable_Encoders_High(true, status);
+  } else {
+    *status = NiFpga_Status_InvalidParameter;
+  }
+}
+
+void HAL_AddDMAEncoderPeriod(HAL_DMAHandle handle,
+                             HAL_EncoderHandle encoderHandle, int32_t* status) {
+  // Detect a counter encoder vs an actual encoder, and use the right DMA calls
+  HAL_FPGAEncoderHandle fpgaEncoderHandle = HAL_kInvalidHandle;
+  HAL_CounterHandle counterHandle = HAL_kInvalidHandle;
+
+  bool validEncoderHandle = hal::GetEncoderBaseHandle(
+      encoderHandle, &fpgaEncoderHandle, &counterHandle);
+
+  if (!validEncoderHandle) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (counterHandle != HAL_kInvalidHandle) {
+    HAL_AddDMACounterPeriod(handle, counterHandle, status);
+    return;
+  }
+
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = HAL_INVALID_DMA_ADDITION;
+    return;
+  }
+
+  if (getHandleType(fpgaEncoderHandle) != HAL_HandleEnum::FPGAEncoder) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  int32_t index = getHandleIndex(fpgaEncoderHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (index < 4) {
+    dma->aDMA->writeConfig_Enable_EncoderTimers_Low(true, status);
+  } else if (index < 8) {
+    dma->aDMA->writeConfig_Enable_EncoderTimers_High(true, status);
+  } else {
+    *status = NiFpga_Status_InvalidParameter;
+  }
+}
+
+void HAL_AddDMACounter(HAL_DMAHandle handle, HAL_CounterHandle counterHandle,
+                       int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = HAL_INVALID_DMA_ADDITION;
+    return;
+  }
+
+  if (getHandleType(counterHandle) != HAL_HandleEnum::Counter) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  int32_t index = getHandleIndex(counterHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (index < 4) {
+    dma->aDMA->writeConfig_Enable_Counters_Low(true, status);
+  } else if (index < 8) {
+    dma->aDMA->writeConfig_Enable_Counters_High(true, status);
+  } else {
+    *status = NiFpga_Status_InvalidParameter;
+  }
+}
+
+void HAL_AddDMACounterPeriod(HAL_DMAHandle handle,
+                             HAL_CounterHandle counterHandle, int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = HAL_INVALID_DMA_ADDITION;
+    return;
+  }
+
+  if (getHandleType(counterHandle) != HAL_HandleEnum::Counter) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  int32_t index = getHandleIndex(counterHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (index < 4) {
+    dma->aDMA->writeConfig_Enable_CounterTimers_Low(true, status);
+  } else if (index < 8) {
+    dma->aDMA->writeConfig_Enable_CounterTimers_High(true, status);
+  } else {
+    *status = NiFpga_Status_InvalidParameter;
+  }
+}
+
+void HAL_AddDMADigitalSource(HAL_DMAHandle handle,
+                             HAL_Handle digitalSourceHandle, int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = HAL_INVALID_DMA_ADDITION;
+    return;
+  }
+
+  if (isHandleType(digitalSourceHandle, HAL_HandleEnum::AnalogTrigger)) {
+    dma->aDMA->writeConfig_Enable_AnalogTriggers(true, status);
+  } else if (isHandleType(digitalSourceHandle, HAL_HandleEnum::DIO)) {
+    dma->aDMA->writeConfig_Enable_DI(true, status);
+  } else {
+    *status = NiFpga_Status_InvalidParameter;
+  }
+}
+
+void HAL_AddDMAAnalogInput(HAL_DMAHandle handle,
+                           HAL_AnalogInputHandle aInHandle, int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = HAL_INVALID_DMA_ADDITION;
+    return;
+  }
+
+  if (getHandleType(aInHandle) != HAL_HandleEnum::AnalogInput) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  int32_t index = getHandleIndex(aInHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (index < 4) {
+    dma->aDMA->writeConfig_Enable_AI0_Low(true, status);
+  } else if (index < 8) {
+    dma->aDMA->writeConfig_Enable_AI0_High(true, status);
+  } else {
+    *status = NiFpga_Status_InvalidParameter;
+  }
+}
+
+void HAL_AddDMADutyCycle(HAL_DMAHandle handle,
+                         HAL_DutyCycleHandle dutyCycleHandle, int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = HAL_INVALID_DMA_ADDITION;
+    return;
+  }
+
+  if (getHandleType(dutyCycleHandle) != HAL_HandleEnum::DutyCycle) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  int32_t index = getHandleIndex(dutyCycleHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (index < 4) {
+    dma->aDMA->writeConfig_Enable_DutyCycle_Low(true, status);
+  } else if (index < 8) {
+    dma->aDMA->writeConfig_Enable_DutyCycle_High(true, status);
+  } else {
+    *status = NiFpga_Status_InvalidParameter;
+  }
+}
+
+void HAL_AddDMAAveragedAnalogInput(HAL_DMAHandle handle,
+                                   HAL_AnalogInputHandle aInHandle,
+                                   int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = HAL_INVALID_DMA_ADDITION;
+    return;
+  }
+
+  if (getHandleType(aInHandle) != HAL_HandleEnum::AnalogInput) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  int32_t index = getHandleIndex(aInHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (index < 4) {
+    dma->aDMA->writeConfig_Enable_AIAveraged0_Low(true, status);
+  } else if (index < 8) {
+    dma->aDMA->writeConfig_Enable_AIAveraged0_High(true, status);
+  } else {
+    *status = NiFpga_Status_InvalidParameter;
+  }
+}
+
+void HAL_AddDMAAnalogAccumulator(HAL_DMAHandle handle,
+                                 HAL_AnalogInputHandle aInHandle,
+                                 int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = HAL_INVALID_DMA_ADDITION;
+    return;
+  }
+
+  if (!HAL_IsAccumulatorChannel(aInHandle, status)) {
+    *status = HAL_INVALID_ACCUMULATOR_CHANNEL;
+    return;
+  }
+
+  int32_t index = getHandleIndex(aInHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (index == 0) {
+    dma->aDMA->writeConfig_Enable_Accumulator0(true, status);
+  } else if (index == 1) {
+    dma->aDMA->writeConfig_Enable_Accumulator1(true, status);
+  } else {
+    *status = NiFpga_Status_InvalidParameter;
+  }
+}
+
+void HAL_SetDMAExternalTrigger(HAL_DMAHandle handle,
+                               HAL_Handle digitalSourceHandle,
+                               HAL_AnalogTriggerType analogTriggerType,
+                               HAL_Bool rising, HAL_Bool falling,
+                               int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = HAL_INVALID_DMA_ADDITION;
+    return;
+  }
+
+  int index = 0;
+  auto triggerChannels = dma->captureStore.triggerChannels;
+  do {
+    if (((triggerChannels >> index) & 0x1) == 0) {
+      break;
+    }
+    index++;
+  } while (index < 8);
+
+  if (index == 8) {
+    *status = NO_AVAILABLE_RESOURCES;
+    return;
+  }
+
+  dma->captureStore.triggerChannels |= (1 << index);
+
+  auto channelIndex = index;
+
+  auto isExternalClock = dma->aDMA->readConfig_ExternalClock(status);
+  if (*status == 0 && !isExternalClock) {
+    dma->aDMA->writeConfig_ExternalClock(true, status);
+    if (*status != 0) return;
+  } else if (*status != 0) {
+    return;
+  }
+
+  uint8_t pin = 0;
+  uint8_t module = 0;
+  bool analogTrigger = false;
+  bool success = remapDigitalSource(digitalSourceHandle, analogTriggerType, pin,
+                                    module, analogTrigger);
+
+  if (!success) {
+    *status = PARAMETER_OUT_OF_RANGE;
+    return;
+  }
+
+  tDMA::tExternalTriggers newTrigger;
+  newTrigger.FallingEdge = falling;
+  newTrigger.RisingEdge = rising;
+  newTrigger.ExternalClockSource_AnalogTrigger = analogTrigger;
+  newTrigger.ExternalClockSource_Channel = pin;
+  newTrigger.ExternalClockSource_Module = module;
+
+  dma->aDMA->writeExternalTriggers(channelIndex / 4, channelIndex % 4,
+                                   newTrigger, status);
+}
+
+void HAL_StartDMA(HAL_DMAHandle handle, int32_t queueDepth, int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    *status = INCOMPATIBLE_STATE;
+    return;
+  }
+
+  tDMA::tConfig config = dma->aDMA->readConfig(status);
+  if (*status != 0) return;
+
+  {
+    size_t accum_size = 0;
+#define SET_SIZE(bit)                                      \
+  if (config.bit) {                                        \
+    dma->captureStore.channelOffsets[k##bit] = accum_size; \
+    accum_size += kChannelSize[k##bit];                    \
+  } else {                                                 \
+    dma->captureStore.channelOffsets[k##bit] = -1;         \
+  }
+    SET_SIZE(Enable_AI0_Low);
+    SET_SIZE(Enable_AI0_High);
+    SET_SIZE(Enable_AIAveraged0_Low);
+    SET_SIZE(Enable_AIAveraged0_High);
+    SET_SIZE(Enable_AI1_Low);
+    SET_SIZE(Enable_AI1_High);
+    SET_SIZE(Enable_AIAveraged1_Low);
+    SET_SIZE(Enable_AIAveraged1_High);
+    SET_SIZE(Enable_Accumulator0);
+    SET_SIZE(Enable_Accumulator1);
+    SET_SIZE(Enable_DI);
+    SET_SIZE(Enable_AnalogTriggers);
+    SET_SIZE(Enable_Counters_Low);
+    SET_SIZE(Enable_Counters_High);
+    SET_SIZE(Enable_CounterTimers_Low);
+    SET_SIZE(Enable_CounterTimers_High);
+    SET_SIZE(Enable_Encoders_Low);
+    SET_SIZE(Enable_Encoders_High);
+    SET_SIZE(Enable_EncoderTimers_Low);
+    SET_SIZE(Enable_EncoderTimers_High);
+    SET_SIZE(Enable_DutyCycle_Low);
+    SET_SIZE(Enable_DutyCycle_High);
+#undef SET_SIZE
+    dma->captureStore.captureSize = accum_size + 1;
+  }
+
+  dma->manager = std::make_unique<tDMAManager>(
+      g_DMA_index, queueDepth * dma->captureStore.captureSize, status);
+  if (*status != 0) {
+    return;
+  }
+
+  dma->manager->start(status);
+  dma->manager->stop(status);
+  dma->manager->start(status);
+}
+
+void HAL_StopDMA(HAL_DMAHandle handle, int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  if (dma->manager) {
+    dma->manager->stop(status);
+    dma->manager = nullptr;
+  }
+}
+
+void* HAL_GetDMADirectPointer(HAL_DMAHandle handle) {
+  auto dma = dmaHandles->Get(handle);
+  return dma.get();
+}
+
+enum HAL_DMAReadStatus HAL_ReadDMADirect(void* dmaPointer,
+                                         HAL_DMASample* dmaSample,
+                                         int32_t timeoutMs,
+                                         int32_t* remainingOut,
+                                         int32_t* status) {
+  DMA* dma = static_cast<DMA*>(dmaPointer);
+  *remainingOut = 0;
+  size_t remainingBytes = 0;
+
+  if (!dma->manager) {
+    *status = INCOMPATIBLE_STATE;
+    return HAL_DMA_ERROR;
+  }
+
+  dma->manager->read(dmaSample->readBuffer, dma->captureStore.captureSize,
+                     timeoutMs, &remainingBytes, status);
+
+  *remainingOut = remainingBytes / dma->captureStore.captureSize;
+
+  if (*status == 0) {
+    uint32_t lower_sample =
+        dmaSample->readBuffer[dma->captureStore.captureSize - 1];
+    dmaSample->timeStamp = HAL_ExpandFPGATime(lower_sample, status);
+    if (*status != 0) {
+      return HAL_DMA_ERROR;
+    }
+    dmaSample->triggerChannels = dma->captureStore.triggerChannels;
+    dmaSample->captureSize = dma->captureStore.captureSize;
+    std::memcpy(dmaSample->channelOffsets, dma->captureStore.channelOffsets,
+                sizeof(dmaSample->channelOffsets));
+    return HAL_DMA_OK;
+  } else if (*status == NiFpga_Status_FifoTimeout) {
+    *status = 0;
+    return HAL_DMA_TIMEOUT;
+  } else {
+    return HAL_DMA_ERROR;
+  }
+}
+
+enum HAL_DMAReadStatus HAL_ReadDMA(HAL_DMAHandle handle,
+                                   HAL_DMASample* dmaSample, int32_t timeoutMs,
+                                   int32_t* remainingOut, int32_t* status) {
+  auto dma = dmaHandles->Get(handle);
+  if (!dma) {
+    *status = HAL_HANDLE_ERROR;
+    return HAL_DMA_ERROR;
+  }
+
+  return HAL_ReadDMADirect(dma.get(), dmaSample, timeoutMs, remainingOut,
+                           status);
+}
+
+static uint32_t ReadDMAValue(const HAL_DMASample& dma, int valueType, int index,
+                             int32_t* status) {
+  auto offset = dma.channelOffsets[valueType];
+  if (offset == -1) {
+    *status = NiFpga_Status_ResourceNotFound;
+    return 0;
+  }
+  return dma.readBuffer[offset + index];
+}
+
+uint64_t HAL_GetDMASampleTime(const HAL_DMASample* dmaSample, int32_t* status) {
+  return dmaSample->timeStamp;
+}
+
+int32_t HAL_GetDMASampleEncoderRaw(const HAL_DMASample* dmaSample,
+                                   HAL_EncoderHandle encoderHandle,
+                                   int32_t* status) {
+  HAL_FPGAEncoderHandle fpgaEncoderHandle = 0;
+  HAL_CounterHandle counterHandle = 0;
+  bool validEncoderHandle = hal::GetEncoderBaseHandle(
+      encoderHandle, &fpgaEncoderHandle, &counterHandle);
+
+  if (!validEncoderHandle) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  if (counterHandle != HAL_kInvalidHandle) {
+    return HAL_GetDMASampleCounter(dmaSample, counterHandle, status);
+  }
+
+  if (getHandleType(fpgaEncoderHandle) != HAL_HandleEnum::FPGAEncoder) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  int32_t index = getHandleIndex(fpgaEncoderHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  uint32_t dmaWord = 0;
+  *status = 0;
+  if (index < 4) {
+    dmaWord = ReadDMAValue(*dmaSample, kEnable_Encoders_Low, index, status);
+  } else if (index < 8) {
+    dmaWord =
+        ReadDMAValue(*dmaSample, kEnable_Encoders_High, index - 4, status);
+  } else {
+    *status = NiFpga_Status_ResourceNotFound;
+  }
+  if (*status != 0) {
+    return -1;
+  }
+
+  return static_cast<int32_t>(dmaWord) >> 1;
+}
+
+int32_t HAL_GetDMASampleEncoderPeriodRaw(const HAL_DMASample* dmaSample,
+                                         HAL_EncoderHandle encoderHandle,
+                                         int32_t* status) {
+  HAL_FPGAEncoderHandle fpgaEncoderHandle = 0;
+  HAL_CounterHandle counterHandle = 0;
+  bool validEncoderHandle = hal::GetEncoderBaseHandle(
+      encoderHandle, &fpgaEncoderHandle, &counterHandle);
+
+  if (!validEncoderHandle) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  if (counterHandle != HAL_kInvalidHandle) {
+    return HAL_GetDMASampleCounterPeriod(dmaSample, counterHandle, status);
+  }
+
+  if (getHandleType(fpgaEncoderHandle) != HAL_HandleEnum::FPGAEncoder) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  int32_t index = getHandleIndex(fpgaEncoderHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  uint32_t dmaWord = 0;
+  *status = 0;
+  if (index < 4) {
+    dmaWord =
+        ReadDMAValue(*dmaSample, kEnable_EncoderTimers_Low, index, status);
+  } else if (index < 8) {
+    dmaWord =
+        ReadDMAValue(*dmaSample, kEnable_EncoderTimers_High, index - 4, status);
+  } else {
+    *status = NiFpga_Status_ResourceNotFound;
+  }
+  if (*status != 0) {
+    return -1;
+  }
+
+  return static_cast<int32_t>(dmaWord) & 0x7FFFFF;
+}
+
+int32_t HAL_GetDMASampleCounter(const HAL_DMASample* dmaSample,
+                                HAL_CounterHandle counterHandle,
+                                int32_t* status) {
+  if (getHandleType(counterHandle) != HAL_HandleEnum::Counter) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  int32_t index = getHandleIndex(counterHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  uint32_t dmaWord = 0;
+  *status = 0;
+  if (index < 4) {
+    dmaWord = ReadDMAValue(*dmaSample, kEnable_Counters_Low, index, status);
+  } else if (index < 8) {
+    dmaWord =
+        ReadDMAValue(*dmaSample, kEnable_Counters_High, index - 4, status);
+  } else {
+    *status = NiFpga_Status_ResourceNotFound;
+  }
+  if (*status != 0) {
+    return -1;
+  }
+
+  return static_cast<int32_t>(dmaWord) >> 1;
+}
+
+int32_t HAL_GetDMASampleCounterPeriod(const HAL_DMASample* dmaSample,
+                                      HAL_CounterHandle counterHandle,
+                                      int32_t* status) {
+  if (getHandleType(counterHandle) != HAL_HandleEnum::Counter) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  int32_t index = getHandleIndex(counterHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  uint32_t dmaWord = 0;
+  *status = 0;
+  if (index < 4) {
+    dmaWord =
+        ReadDMAValue(*dmaSample, kEnable_CounterTimers_Low, index, status);
+  } else if (index < 8) {
+    dmaWord =
+        ReadDMAValue(*dmaSample, kEnable_CounterTimers_High, index - 4, status);
+  } else {
+    *status = NiFpga_Status_ResourceNotFound;
+  }
+  if (*status != 0) {
+    return -1;
+  }
+
+  return static_cast<int32_t>(dmaWord) & 0x7FFFFF;
+}
+
+HAL_Bool HAL_GetDMASampleDigitalSource(const HAL_DMASample* dmaSample,
+                                       HAL_Handle dSourceHandle,
+                                       int32_t* status) {
+  HAL_HandleEnum handleType = getHandleType(dSourceHandle);
+  int32_t index = getHandleIndex(dSourceHandle);
+
+  *status = 0;
+  if (handleType == HAL_HandleEnum::DIO) {
+    auto readVal = ReadDMAValue(*dmaSample, kEnable_DI, 0, status);
+    if (*status == 0) {
+      if (index < kNumDigitalHeaders) {
+        return (readVal >> index) & 0x1;
+      } else {
+        return (readVal >> (index + 6)) & 0x1;
+      }
+    }
+  } else if (handleType == HAL_HandleEnum::AnalogTrigger) {
+    auto readVal = ReadDMAValue(*dmaSample, kEnable_AnalogTriggers, 0, status);
+    if (*status == 0) {
+      return (readVal >> index) & 0x1;
+    }
+  } else {
+    *status = NiFpga_Status_InvalidParameter;
+  }
+  return false;
+}
+int32_t HAL_GetDMASampleAnalogInputRaw(const HAL_DMASample* dmaSample,
+                                       HAL_AnalogInputHandle aInHandle,
+                                       int32_t* status) {
+  if (getHandleType(aInHandle) != HAL_HandleEnum::AnalogInput) {
+    *status = HAL_HANDLE_ERROR;
+    return 0xFFFFFFFF;
+  }
+
+  int32_t index = getHandleIndex(aInHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return 0xFFFFFFFF;
+  }
+
+  uint32_t dmaWord = 0;
+  if (index < 4) {
+    dmaWord = ReadDMAValue(*dmaSample, kEnable_AI0_Low, index / 2, status);
+  } else if (index < 8) {
+    dmaWord =
+        ReadDMAValue(*dmaSample, kEnable_AI0_High, (index - 4) / 2, status);
+  } else {
+    *status = NiFpga_Status_ResourceNotFound;
+  }
+  if (*status != 0) {
+    return 0xFFFFFFFF;
+  }
+
+  if (index % 2) {
+    return (dmaWord >> 16) & 0xffff;
+  } else {
+    return dmaWord & 0xffff;
+  }
+}
+
+int32_t HAL_GetDMASampleAveragedAnalogInputRaw(const HAL_DMASample* dmaSample,
+                                               HAL_AnalogInputHandle aInHandle,
+                                               int32_t* status) {
+  if (getHandleType(aInHandle) != HAL_HandleEnum::AnalogInput) {
+    *status = HAL_HANDLE_ERROR;
+    return 0xFFFFFFFF;
+  }
+
+  int32_t index = getHandleIndex(aInHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return 0xFFFFFFFF;
+  }
+
+  uint32_t dmaWord = 0;
+  if (index < 4) {
+    dmaWord = ReadDMAValue(*dmaSample, kEnable_AIAveraged0_Low, index, status);
+  } else if (index < 8) {
+    dmaWord =
+        ReadDMAValue(*dmaSample, kEnable_AIAveraged0_High, index - 4, status);
+  } else {
+    *status = NiFpga_Status_ResourceNotFound;
+  }
+  if (*status != 0) {
+    return 0xFFFFFFFF;
+  }
+
+  return dmaWord;
+}
+
+void HAL_GetDMASampleAnalogAccumulator(const HAL_DMASample* dmaSample,
+                                       HAL_AnalogInputHandle aInHandle,
+                                       int64_t* count, int64_t* value,
+                                       int32_t* status) {
+  if (!HAL_IsAccumulatorChannel(aInHandle, status)) {
+    *status = HAL_INVALID_ACCUMULATOR_CHANNEL;
+    return;
+  }
+
+  int32_t index = getHandleIndex(aInHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return;
+  }
+
+  uint32_t dmaWord = 0;
+  uint32_t dmaValue1 = 0;
+  uint32_t dmaValue2 = 0;
+  if (index == 0) {
+    dmaWord = ReadDMAValue(*dmaSample, kEnable_Accumulator0, index, status);
+    dmaValue1 =
+        ReadDMAValue(*dmaSample, kEnable_Accumulator0, index + 1, status);
+    dmaValue2 =
+        ReadDMAValue(*dmaSample, kEnable_Accumulator0, index + 2, status);
+  } else if (index == 1) {
+    dmaWord = ReadDMAValue(*dmaSample, kEnable_Accumulator1, index - 1, status);
+    dmaValue1 = ReadDMAValue(*dmaSample, kEnable_Accumulator0, index, status);
+    dmaValue2 =
+        ReadDMAValue(*dmaSample, kEnable_Accumulator0, index + 1, status);
+  } else {
+    *status = NiFpga_Status_ResourceNotFound;
+  }
+  if (*status != 0) {
+    return;
+  }
+
+  *count = dmaWord;
+
+  *value = static_cast<int64_t>(dmaValue1) << 32 | dmaValue2;
+}
+
+int32_t HAL_GetDMASampleDutyCycleOutputRaw(const HAL_DMASample* dmaSample,
+                                           HAL_DutyCycleHandle dutyCycleHandle,
+                                           int32_t* status) {
+  if (getHandleType(dutyCycleHandle) != HAL_HandleEnum::DutyCycle) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  int32_t index = getHandleIndex(dutyCycleHandle);
+  if (index < 0) {
+    *status = HAL_HANDLE_ERROR;
+    return -1;
+  }
+
+  uint32_t dmaWord = 0;
+  *status = 0;
+  if (index < 4) {
+    dmaWord = ReadDMAValue(*dmaSample, kEnable_DutyCycle_Low, index, status);
+  } else if (index < 8) {
+    dmaWord =
+        ReadDMAValue(*dmaSample, kEnable_DutyCycle_High, index - 4, status);
+  } else {
+    *status = NiFpga_Status_ResourceNotFound;
+  }
+  if (*status != 0) {
+    return -1;
+  }
+  return dmaWord;
+}
+}  // extern "C"