2019-11-14 22:52:34 -08:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
/* 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 "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_pod_v<HAL_DMASample>, "DMA Sample must be POD");
|
|
|
|
|
|
|
|
|
|
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>(
|
2019-11-15 17:32:29 -08:00
|
|
|
g_DMA_index, queueDepth * dma->captureStore.captureSize, status);
|
2019-11-14 22:52:34 -08:00
|
|
|
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"
|