blob: ee39d2d6b674b993451e6ac067cc69012f9a523e [file] [log] [blame]
/*----------------------------------------------------------------------------*/
/* 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"