Add DMA support to HAL and WPILibC (#2080)

This commit is contained in:
Thad House
2019-11-14 22:52:34 -08:00
committed by Peter Johnson
parent 8280b7e3af
commit 82b2170feb
22 changed files with 1672 additions and 2 deletions

View File

@@ -0,0 +1,115 @@
/*----------------------------------------------------------------------------*/
/* 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 "frc/DMA.h"
#include <frc/AnalogInput.h>
#include <frc/Counter.h>
#include <frc/DigitalSource.h>
#include <frc/DutyCycle.h>
#include <frc/Encoder.h>
#include <hal/DMA.h>
#include <hal/HALBase.h>
using namespace frc;
DMA::DMA() {
int32_t status = 0;
dmaHandle = HAL_InitializeDMA(&status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
DMA::~DMA() { HAL_FreeDMA(dmaHandle); }
void DMA::SetPause(bool pause) {
int32_t status = 0;
HAL_SetDMAPause(dmaHandle, pause, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::SetRate(int cycles) {
int32_t status = 0;
HAL_SetDMARate(dmaHandle, cycles, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::AddEncoder(const Encoder* encoder) {
int32_t status = 0;
HAL_AddDMAEncoder(dmaHandle, encoder->m_encoder, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::AddEncoderPeriod(const Encoder* encoder) {
int32_t status = 0;
HAL_AddDMAEncoderPeriod(dmaHandle, encoder->m_encoder, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::AddCounter(const Counter* counter) {
int32_t status = 0;
HAL_AddDMACounter(dmaHandle, counter->m_counter, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::AddCounterPeriod(const Counter* counter) {
int32_t status = 0;
HAL_AddDMACounterPeriod(dmaHandle, counter->m_counter, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::AddDigitalSource(const DigitalSource* digitalSource) {
int32_t status = 0;
HAL_AddDMADigitalSource(dmaHandle, digitalSource->GetPortHandleForRouting(),
&status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::AddDutyCycle(const DutyCycle* dutyCycle) {
int32_t status = 0;
HAL_AddDMADutyCycle(dmaHandle, dutyCycle->m_handle, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::AddAnalogInput(const AnalogInput* analogInput) {
int32_t status = 0;
HAL_AddDMAAnalogInput(dmaHandle, analogInput->m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::AddAveragedAnalogInput(const AnalogInput* analogInput) {
int32_t status = 0;
HAL_AddDMAAveragedAnalogInput(dmaHandle, analogInput->m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::AddAnalogAccumulator(const AnalogInput* analogInput) {
int32_t status = 0;
HAL_AddDMAAnalogAccumulator(dmaHandle, analogInput->m_port, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::SetExternalTrigger(DigitalSource* source, bool rising, bool falling) {
int32_t status = 0;
HAL_SetDMAExternalTrigger(dmaHandle, source->GetPortHandleForRouting(),
static_cast<HAL_AnalogTriggerType>(
source->GetAnalogTriggerTypeForRouting()),
rising, falling, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::StartDMA(int queueDepth) {
int32_t status = 0;
HAL_StartDMA(dmaHandle, queueDepth, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void DMA::StopDMA() {
int32_t status = 0;
HAL_StopDMA(dmaHandle, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}

View File

@@ -19,6 +19,8 @@
namespace frc {
class SendableBuilder;
class DMA;
class DMASample;
/**
* Analog input class.
@@ -38,6 +40,8 @@ class AnalogInput : public ErrorBase,
public SendableHelper<AnalogInput> {
friend class AnalogTrigger;
friend class AnalogGyro;
friend class DMA;
friend class DMASample;
public:
static constexpr int kAccumulatorModuleNumber = 1;

View File

@@ -21,6 +21,8 @@ namespace frc {
class DigitalGlitchFilter;
class SendableBuilder;
class DMA;
class DMASample;
/**
* Class for counting the number of ticks on a digital input channel.
@@ -36,6 +38,9 @@ class Counter : public ErrorBase,
public CounterBase,
public Sendable,
public SendableHelper<Counter> {
friend class DMA;
friend class DMASample;
public:
enum Mode {
kTwoPulse = 0,

View File

@@ -0,0 +1,57 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <hal/Types.h>
#include "frc/ErrorBase.h"
namespace frc {
class Encoder;
class Counter;
class DigitalSource;
class DutyCycle;
class AnalogInput;
class DMASample;
class DMA : public ErrorBase {
friend class DMASample;
public:
DMA();
~DMA() override;
DMA& operator=(DMA&& other) = default;
DMA(DMA&& other) = default;
void SetPause(bool pause);
void SetRate(int cycles);
void AddEncoder(const Encoder* encoder);
void AddEncoderPeriod(const Encoder* encoder);
void AddCounter(const Counter* counter);
void AddCounterPeriod(const Counter* counter);
void AddDigitalSource(const DigitalSource* digitalSource);
void AddDutyCycle(const DutyCycle* digitalSource);
void AddAnalogInput(const AnalogInput* analogInput);
void AddAveragedAnalogInput(const AnalogInput* analogInput);
void AddAnalogAccumulator(const AnalogInput* analogInput);
void SetExternalTrigger(DigitalSource* source, bool rising, bool falling);
void StartDMA(int queueDepth);
void StopDMA();
private:
hal::Handle<HAL_DMAHandle> dmaHandle;
};
} // namespace frc

View File

@@ -0,0 +1,108 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
#pragma once
#include <hal/AnalogInput.h>
#include <hal/DMA.h>
#include <units/units.h>
#include "frc/AnalogInput.h"
#include "frc/Counter.h"
#include "frc/DMA.h"
#include "frc/DutyCycle.h"
#include "frc/Encoder.h"
namespace frc {
class DMASample : public HAL_DMASample {
public:
HAL_DMAReadStatus Update(const DMA* dma, units::second_t timeout,
int32_t* remaining, int32_t* status) {
units::millisecond_t ms = timeout;
auto timeoutMs = ms.to<int32_t>();
return HAL_ReadDMA(dma->dmaHandle, this, timeoutMs, remaining, status);
}
uint64_t GetTime() const { return timeStamp; }
units::second_t GetTimeStamp() const {
return units::second_t{static_cast<double>(GetTime()) * 1.0e-6};
}
int32_t GetEncoderRaw(const Encoder* encoder, int32_t* status) const {
return HAL_GetDMASampleEncoderRaw(this, encoder->m_encoder, status);
}
double GetEncoderDistance(const Encoder* encoder, int32_t* status) const {
double val = GetEncoderRaw(encoder, status);
val *= encoder->DecodingScaleFactor();
val *= encoder->GetDistancePerPulse();
return val;
}
int32_t GetEncoderPeriodRaw(const Encoder* encoder, int32_t* status) const {
return HAL_GetDMASampleEncoderPeriodRaw(this, encoder->m_encoder, status);
}
int32_t GetCounter(const Counter* counter, int32_t* status) const {
return HAL_GetDMASampleCounter(this, counter->m_counter, status);
}
int32_t GetCounterPeriod(const Counter* counter, int32_t* status) const {
return HAL_GetDMASampleCounterPeriod(this, counter->m_counter, status);
}
bool GetDigitalSource(const DigitalSource* digitalSource,
int32_t* status) const {
return HAL_GetDMASampleDigitalSource(
this, digitalSource->GetPortHandleForRouting(), status);
}
int32_t GetAnalogInputRaw(const AnalogInput* analogInput,
int32_t* status) const {
return HAL_GetDMASampleAnalogInputRaw(this, analogInput->m_port, status);
}
double GetAnalogInputVoltage(const AnalogInput* analogInput,
int32_t* status) {
return HAL_GetAnalogValueToVolts(
analogInput->m_port, GetAnalogInputRaw(analogInput, status), status);
}
int32_t GetAveragedAnalogInputRaw(const AnalogInput* analogInput,
int32_t* status) const {
return HAL_GetDMASampleAveragedAnalogInputRaw(this, analogInput->m_port,
status);
}
double GetAveragedAnalogInputVoltage(const AnalogInput* analogInput,
int32_t* status) {
return HAL_GetAnalogValueToVolts(
analogInput->m_port, GetAveragedAnalogInputRaw(analogInput, status),
status);
}
void GetAnalogAccumulator(const AnalogInput* analogInput, int64_t* count,
int64_t* value, int32_t* status) const {
return HAL_GetDMASampleAnalogAccumulator(this, analogInput->m_port, count,
value, status);
}
int32_t GetDutyCycleOutputRaw(const DutyCycle* dutyCycle,
int32_t* status) const {
return HAL_GetDMASampleDutyCycleOutputRaw(this, dutyCycle->m_handle,
status);
}
double GetDutyCycleOutput(const DutyCycle* dutyCycle, int32_t* status) {
return GetDutyCycleOutputRaw(dutyCycle, status) /
static_cast<double>(dutyCycle->GetOutputScaleFactor());
}
};
static_assert(std::is_pod_v<frc::DMASample>, "DMA Sample MUST Be POD");
} // namespace frc

View File

@@ -18,6 +18,8 @@
namespace frc {
class DigitalSource;
class AnalogTrigger;
class DMA;
class DMASample;
/**
* Class to read a duty cycle PWM input.
@@ -34,6 +36,8 @@ class DutyCycle : public ErrorBase,
public Sendable,
public SendableHelper<DutyCycle> {
friend class AnalogTrigger;
friend class DMA;
friend class DMASample;
public:
/**

View File

@@ -23,6 +23,8 @@ namespace frc {
class DigitalSource;
class DigitalGlitchFilter;
class SendableBuilder;
class DMA;
class DMASample;
/**
* Class to read quad encoders.
@@ -44,6 +46,9 @@ class Encoder : public ErrorBase,
public PIDSource,
public Sendable,
public SendableHelper<Encoder> {
friend class DMA;
friend class DMASample;
public:
enum IndexingType {
kResetWhileHigh,