2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2016-01-02 03:02:34 -08:00
|
|
|
/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
|
2013-12-15 18:30:16 -05:00
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
2016-01-02 03:02:34 -08:00
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
|
|
|
/* the project. */
|
2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
2014-06-12 18:07:45 -04:00
|
|
|
#include "AnalogInput.h"
|
2016-09-05 13:55:31 -07:00
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
2016-05-25 22:38:11 -07:00
|
|
|
#include "HAL/HAL.h"
|
2016-05-20 17:30:37 -07:00
|
|
|
#include "LiveWindow/LiveWindow.h"
|
2014-07-31 15:46:14 -04:00
|
|
|
#include "Timer.h"
|
2013-12-15 18:30:16 -05:00
|
|
|
#include "WPIErrors.h"
|
|
|
|
|
|
2014-06-12 18:07:45 -04:00
|
|
|
const uint8_t AnalogInput::kAccumulatorModuleNumber;
|
|
|
|
|
const uint32_t AnalogInput::kAccumulatorNumChannels;
|
|
|
|
|
const uint32_t AnalogInput::kAccumulatorChannels[] = {0, 1};
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
2015-06-29 02:43:44 -07:00
|
|
|
* Construct an analog input.
|
|
|
|
|
*
|
|
|
|
|
* @param channel The channel number on the roboRIO to represent. 0-3 are
|
2016-05-20 17:30:37 -07:00
|
|
|
* on-board 4-7 are on the MXP port.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-29 02:43:44 -07:00
|
|
|
AnalogInput::AnalogInput(uint32_t channel) {
|
2015-06-30 15:01:20 -04:00
|
|
|
std::stringstream buf;
|
|
|
|
|
buf << "Analog Input " << channel;
|
2015-06-25 15:07:55 -04:00
|
|
|
|
2016-07-21 23:24:06 -07:00
|
|
|
if (!SensorBase::CheckAnalogInputChannel(channel)) {
|
2015-06-30 15:01:20 -04:00
|
|
|
wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str());
|
2015-06-25 15:07:55 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_channel = channel;
|
|
|
|
|
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_PortHandle port = HAL_GetPort(channel);
|
2015-06-25 15:07:55 -04:00
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
m_port = HAL_InitializeAnalogInputPort(port, &status);
|
2016-06-27 21:32:30 -07:00
|
|
|
if (status != 0) {
|
2016-07-13 20:29:28 -07:00
|
|
|
wpi_setErrorWithContextRange(status, 0, HAL_GetNumAnalogInputs(), channel,
|
|
|
|
|
HAL_GetErrorMessage(status));
|
2016-06-27 21:32:30 -07:00
|
|
|
m_channel = std::numeric_limits<uint32_t>::max();
|
2016-07-09 00:24:26 -07:00
|
|
|
m_port = HAL_kInvalidHandle;
|
2016-06-27 21:32:30 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
|
Revert changes preventing old user code from compiling.
I'm not 100% sure whether we want these, but they are a quick
find and replace to do.
Basically, there are two primary things that we have done
this summer that break existing user code:
-Changing GetInstance() calls to return references instead
of pointers. This forces users to change from doing something
like LiveWindow::GetInstance()->AddSensor() to LiveWindow::GetInstance().AddSensor().
-Making PIDGet() and related calls const, forcing users to change
the function signatures wherever they override them.
The GetInstance() calls don't really matter to me either way,
especially since there are no real ownership issues going on there,
unlike the rest of the smart pointer-related changes.
For the const stuff, it is certainly more correct to mandate that
user PIDGet() functions be const and the such, but at the same time,
I'm not sure that there is any strong need for it, and the errors
generated are not the most helpful. While this wouldn't necessarily
be an issue for more experienced teams or completely new teams (who
don't have any old code to be reusing), it may cause issues for more
average teams who aren't familiar with the intricacies of C++ anything.
Change-Id: I6e7007982069292ea70e6d0fc8ca40203340df1b
2015-07-24 19:19:40 -04:00
|
|
|
LiveWindow::GetInstance()->AddSensor("AnalogInput", channel, this);
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_Report(HALUsageReporting::kResourceType_AnalogChannel, channel);
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Channel destructor.
|
|
|
|
|
*/
|
2015-10-20 10:37:04 -07:00
|
|
|
AnalogInput::~AnalogInput() {
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_FreeAnalogInputPort(m_port);
|
|
|
|
|
m_port = HAL_kInvalidHandle;
|
2015-10-20 10:37:04 -07:00
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
2014-06-13 17:45:10 -04:00
|
|
|
* Get a sample straight from this channel.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* The sample is a 12-bit value representing the 0V to 5V range of the A/D
|
2016-05-20 17:30:37 -07:00
|
|
|
* converter in the module. The units are in A/D converter codes. Use
|
|
|
|
|
* GetVoltage() to get the analog value in calibrated units.
|
|
|
|
|
*
|
2014-06-13 17:45:10 -04:00
|
|
|
* @return A sample straight from this channel.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2016-07-12 10:45:14 -07:00
|
|
|
int32_t AnalogInput::GetValue() const {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (StatusIsFatal()) return 0;
|
|
|
|
|
int32_t status = 0;
|
2016-07-12 10:45:14 -07:00
|
|
|
int32_t value = HAL_GetAnalogValue(m_port, &status);
|
2016-07-09 00:24:26 -07:00
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return value;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2015-06-25 15:07:55 -04:00
|
|
|
* Get a sample from the output of the oversample and average engine for this
|
|
|
|
|
* channel.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2014-12-29 14:09:37 -05:00
|
|
|
* The sample is 12-bit + the bits configured in SetOversampleBits().
|
2015-06-25 15:07:55 -04:00
|
|
|
* The value configured in SetAverageBits() will cause this value to be averaged
|
|
|
|
|
* 2**bits number of samples.
|
|
|
|
|
* This is not a sliding window. The sample will not change until
|
|
|
|
|
* 2**(OversampleBits + AverageBits) samples
|
2013-12-15 18:30:16 -05:00
|
|
|
* have been acquired from the module on this channel.
|
|
|
|
|
* Use GetAverageVoltage() to get the analog value in calibrated units.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return A sample from the oversample and average engine for this channel.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
int32_t AnalogInput::GetAverageValue() const {
|
|
|
|
|
if (StatusIsFatal()) return 0;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t value = HAL_GetAnalogAverageValue(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return value;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-06-13 17:45:10 -04:00
|
|
|
* Get a scaled sample straight from this channel.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* The value is scaled to units of Volts using the calibrated scaling data from
|
|
|
|
|
* GetLSBWeight() and GetOffset().
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2014-06-13 17:45:10 -04:00
|
|
|
* @return A scaled sample straight from this channel.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
float AnalogInput::GetVoltage() const {
|
|
|
|
|
if (StatusIsFatal()) return 0.0f;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
float voltage = HAL_GetAnalogVoltage(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return voltage;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2015-06-25 15:07:55 -04:00
|
|
|
* Get a scaled sample from the output of the oversample and average engine for
|
|
|
|
|
* this channel.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* The value is scaled to units of Volts using the calibrated scaling data from
|
|
|
|
|
* GetLSBWeight() and GetOffset().
|
|
|
|
|
* Using oversampling will cause this value to be higher resolution, but it will
|
|
|
|
|
* update more slowly.
|
|
|
|
|
* Using averaging will cause this value to be more stable, but it will update
|
|
|
|
|
* more slowly.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return A scaled sample from the output of the oversample and average engine
|
|
|
|
|
* for this channel.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
float AnalogInput::GetAverageVoltage() const {
|
|
|
|
|
if (StatusIsFatal()) return 0.0f;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
float voltage = HAL_GetAnalogAverageVoltage(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return voltage;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the factory scaling least significant bit weight constant.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return Least significant bit weight.
|
|
|
|
|
*/
|
2016-07-12 10:45:14 -07:00
|
|
|
int32_t AnalogInput::GetLSBWeight() const {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (StatusIsFatal()) return 0;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t lsbWeight = HAL_GetAnalogLSBWeight(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return lsbWeight;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the factory scaling offset constant.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return Offset constant.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
int32_t AnalogInput::GetOffset() const {
|
|
|
|
|
if (StatusIsFatal()) return 0;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t offset = HAL_GetAnalogOffset(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return offset;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the channel number.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return The channel number.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
uint32_t AnalogInput::GetChannel() const {
|
|
|
|
|
if (StatusIsFatal()) return 0;
|
|
|
|
|
return m_channel;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the number of averaging bits.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* This sets the number of averaging bits. The actual number of averaged samples
|
|
|
|
|
* is 2^bits.
|
|
|
|
|
* Use averaging to improve the stability of your measurement at the expense of
|
|
|
|
|
* sampling rate.
|
2013-12-15 18:30:16 -05:00
|
|
|
* The averaging is done automatically in the FPGA.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @param bits Number of bits of averaging.
|
|
|
|
|
*/
|
2016-07-12 10:45:14 -07:00
|
|
|
void AnalogInput::SetAverageBits(int32_t bits) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (StatusIsFatal()) return;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_SetAnalogAverageBits(m_port, bits, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the number of averaging bits previously configured.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* This gets the number of averaging bits from the FPGA. The actual number of
|
2016-05-20 17:30:37 -07:00
|
|
|
* averaged samples is 2^bits. The averaging is done automatically in the FPGA.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return Number of bits of averaging previously configured.
|
|
|
|
|
*/
|
2016-07-12 10:45:14 -07:00
|
|
|
int32_t AnalogInput::GetAverageBits() const {
|
2015-06-25 15:07:55 -04:00
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t averageBits = HAL_GetAnalogAverageBits(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return averageBits;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the number of oversample bits.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* This sets the number of oversample bits. The actual number of oversampled
|
2016-05-20 17:30:37 -07:00
|
|
|
* values is 2^bits. Use oversampling to improve the resolution of your
|
|
|
|
|
* measurements at the expense of sampling rate. The oversampling is done
|
|
|
|
|
* automatically in the FPGA.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @param bits Number of bits of oversampling.
|
|
|
|
|
*/
|
2016-07-12 10:45:14 -07:00
|
|
|
void AnalogInput::SetOversampleBits(int32_t bits) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (StatusIsFatal()) return;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_SetAnalogOversampleBits(m_port, bits, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the number of oversample bits previously configured.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* This gets the number of oversample bits from the FPGA. The actual number of
|
2016-05-20 17:30:37 -07:00
|
|
|
* oversampled values is 2^bits. The oversampling is done automatically in the
|
|
|
|
|
* FPGA.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return Number of bits of oversampling previously configured.
|
|
|
|
|
*/
|
2016-07-12 10:45:14 -07:00
|
|
|
int32_t AnalogInput::GetOversampleBits() const {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (StatusIsFatal()) return 0;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t oversampleBits = HAL_GetAnalogOversampleBits(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return oversampleBits;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Is the channel attached to an accumulator.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
|
|
|
|
* @return The analog input is attached to an accumulator.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
bool AnalogInput::IsAccumulatorChannel() const {
|
|
|
|
|
if (StatusIsFatal()) return false;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
bool isAccum = HAL_IsAccumulatorChannel(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return isAccum;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize the accumulator.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void AnalogInput::InitAccumulator() {
|
|
|
|
|
if (StatusIsFatal()) return;
|
|
|
|
|
m_accumulatorOffset = 0;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_InitAccumulator(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-12-29 14:09:37 -05:00
|
|
|
* Set an initial value for the accumulator.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* This will be added to all values returned to the user.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @param initialValue The value that the accumulator should start from when
|
2016-05-20 17:30:37 -07:00
|
|
|
* reset.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void AnalogInput::SetAccumulatorInitialValue(int64_t initialValue) {
|
|
|
|
|
if (StatusIsFatal()) return;
|
|
|
|
|
m_accumulatorOffset = initialValue;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Resets the accumulator to the initial value.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void AnalogInput::ResetAccumulator() {
|
|
|
|
|
if (StatusIsFatal()) return;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_ResetAccumulator(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
|
|
|
|
|
if (!StatusIsFatal()) {
|
|
|
|
|
// Wait until the next sample, so the next call to GetAccumulator*()
|
|
|
|
|
// won't have old values.
|
|
|
|
|
const float sampleTime = 1.0f / GetSampleRate();
|
|
|
|
|
const float overSamples = 1 << GetOversampleBits();
|
|
|
|
|
const float averageSamples = 1 << GetAverageBits();
|
|
|
|
|
Wait(sampleTime * overSamples * averageSamples);
|
|
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the center value of the accumulator.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* The center value is subtracted from each A/D value before it is added to the
|
2016-05-20 17:30:37 -07:00
|
|
|
* accumulator. This is used for the center value of devices like gyros and
|
|
|
|
|
* accelerometers to take the device offset into account when integrating.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* This center value is based on the output of the oversampled and averaged
|
2016-05-20 17:30:37 -07:00
|
|
|
* source from the accumulator channel. Because of this, any non-zero
|
|
|
|
|
* oversample bits will affect the size of the value for this field.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void AnalogInput::SetAccumulatorCenter(int32_t center) {
|
|
|
|
|
if (StatusIsFatal()) return;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_SetAccumulatorCenter(m_port, center, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the accumulator's deadband.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void AnalogInput::SetAccumulatorDeadband(int32_t deadband) {
|
|
|
|
|
if (StatusIsFatal()) return;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_SetAccumulatorDeadband(m_port, deadband, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Read the accumulated value.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2014-12-29 14:09:37 -05:00
|
|
|
* Read the value that has been accumulating.
|
2013-12-15 18:30:16 -05:00
|
|
|
* The accumulator is attached after the oversample and average engine.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return The 64-bit value accumulated since the last Reset().
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
int64_t AnalogInput::GetAccumulatorValue() const {
|
|
|
|
|
if (StatusIsFatal()) return 0;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
int64_t value = HAL_GetAccumulatorValue(m_port, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return value + m_accumulatorOffset;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Read the number of accumulated values.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* Read the count of the accumulated values since the accumulator was last
|
|
|
|
|
* Reset().
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return The number of times samples from the channel were accumulated.
|
|
|
|
|
*/
|
2016-07-12 10:45:14 -07:00
|
|
|
int64_t AnalogInput::GetAccumulatorCount() const {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (StatusIsFatal()) return 0;
|
|
|
|
|
int32_t status = 0;
|
2016-07-12 10:45:14 -07:00
|
|
|
int64_t count = HAL_GetAccumulatorCount(m_port, &status);
|
2016-07-09 00:24:26 -07:00
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return count;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Read the accumulated value and the number of accumulated values atomically.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* This function reads the value and count from the FPGA atomically.
|
|
|
|
|
* This can be used for averaging.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
artf4154: Get rid of raw pointers in C++.
This deals with the majority of the user-facing code
in wpilibC++Devices and a substantial portion of it in
wpilibC++. wpilibC++Sim and wpilibC++IntegrationTests
are untouched except where it is necessary to make them
work with the rest of the libraries.
There is still a lot to do in the following areas:
-The HAL (which we may not want to touch at all).
-The I2C, Serial, and SPI interfaces in wpilibC++Devices,
which I haven't gotten around to doing yet.
-Most wpilibC++Devices classes have void* pointers
for interacting with the HAL.
-InterruptableSensorBase passes a void *params for
the interrupt handler.
-I haven't converted all the const char* to std::strings.
-There are plenty of other cases of raw pointers still
existing.
-This doesn't fall directly under raw pointer stuff,
but move syntax and rvalue references could be introduced
in many places.
-I haven't touched vision code.
-The Resource classes conflict (one is in the hal, the other
in wpilibC++). Someone should figure out a more
permanent fix (eg, just renaming them), then doing
what I did (making a new namespace for one of them,
essentially the same as renaming it).
A few other things:
-I created a NullDeleter class which is marked as deprecated.
What this does is it can be passed as the deleter to a
std::shared_ptr so that when you are converting raw pointers
to shared_ptrs the shared_ptr doesn't do any deletion if
someone else owns the raw pointer. This should only be
used in making old raw pointer UIs.
-I had to alter the build.gradle so that it did not
emit errors when deprecated functions called deprecated
functions. Unfortunately, gradle doesn't appear to be
actually printing out gcc warnigns for some reason.
The best way I have found to fix this is to patch
the toolchains (https://bitbucket.org/byteit101/toolchain-builder/pull-request/5/make-gcc-not-throw-warnings-for-nested/diff)
so that a deprecated function calling a deprecated
function is fine but a non-deprecated function calling
a deprecated function will throw a warning (which we
then elevate with -Werror). I believe that clang
deals with this properly, although I have not
tried it myself.
Change-Id: Ib8090c66893576fe73654f4e9d268f9d37be06a2
2015-06-30 15:01:20 -04:00
|
|
|
* @param value Reference to the 64-bit accumulated output.
|
|
|
|
|
* @param count Reference to the number of accumulation cycles.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2016-07-12 10:45:14 -07:00
|
|
|
void AnalogInput::GetAccumulatorOutput(int64_t& value, int64_t& count) const {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (StatusIsFatal()) return;
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_GetAccumulatorOutput(m_port, &value, &count, &status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
artf4154: Get rid of raw pointers in C++.
This deals with the majority of the user-facing code
in wpilibC++Devices and a substantial portion of it in
wpilibC++. wpilibC++Sim and wpilibC++IntegrationTests
are untouched except where it is necessary to make them
work with the rest of the libraries.
There is still a lot to do in the following areas:
-The HAL (which we may not want to touch at all).
-The I2C, Serial, and SPI interfaces in wpilibC++Devices,
which I haven't gotten around to doing yet.
-Most wpilibC++Devices classes have void* pointers
for interacting with the HAL.
-InterruptableSensorBase passes a void *params for
the interrupt handler.
-I haven't converted all the const char* to std::strings.
-There are plenty of other cases of raw pointers still
existing.
-This doesn't fall directly under raw pointer stuff,
but move syntax and rvalue references could be introduced
in many places.
-I haven't touched vision code.
-The Resource classes conflict (one is in the hal, the other
in wpilibC++). Someone should figure out a more
permanent fix (eg, just renaming them), then doing
what I did (making a new namespace for one of them,
essentially the same as renaming it).
A few other things:
-I created a NullDeleter class which is marked as deprecated.
What this does is it can be passed as the deleter to a
std::shared_ptr so that when you are converting raw pointers
to shared_ptrs the shared_ptr doesn't do any deletion if
someone else owns the raw pointer. This should only be
used in making old raw pointer UIs.
-I had to alter the build.gradle so that it did not
emit errors when deprecated functions called deprecated
functions. Unfortunately, gradle doesn't appear to be
actually printing out gcc warnigns for some reason.
The best way I have found to fix this is to patch
the toolchains (https://bitbucket.org/byteit101/toolchain-builder/pull-request/5/make-gcc-not-throw-warnings-for-nested/diff)
so that a deprecated function calling a deprecated
function is fine but a non-deprecated function calling
a deprecated function will throw a warning (which we
then elevate with -Werror). I believe that clang
deals with this properly, although I have not
tried it myself.
Change-Id: Ib8090c66893576fe73654f4e9d268f9d37be06a2
2015-06-30 15:01:20 -04:00
|
|
|
value += m_accumulatorOffset;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2014-07-21 16:32:36 -04:00
|
|
|
/**
|
2014-12-29 14:09:37 -05:00
|
|
|
* Set the sample rate per channel for all analog channels.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2014-12-29 14:09:37 -05:00
|
|
|
* The maximum rate is 500kS/s divided by the number of channels in use.
|
|
|
|
|
* This is 62500 samples/s per channel.
|
2016-05-20 17:30:37 -07:00
|
|
|
*
|
2014-07-21 16:32:36 -04:00
|
|
|
* @param samplesPerSecond The number of samples per second.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
void AnalogInput::SetSampleRate(float samplesPerSecond) {
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_SetAnalogSampleRate(samplesPerSecond, &status);
|
|
|
|
|
wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
|
2014-07-21 16:32:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the current sample rate for all channels
|
|
|
|
|
*
|
|
|
|
|
* @return Sample rate.
|
|
|
|
|
*/
|
2015-06-25 15:07:55 -04:00
|
|
|
float AnalogInput::GetSampleRate() {
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
float sampleRate = HAL_GetAnalogSampleRate(&status);
|
|
|
|
|
wpi_setGlobalErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return sampleRate;
|
2014-07-21 16:32:36 -04:00
|
|
|
}
|
|
|
|
|
|
2013-12-15 18:30:16 -05:00
|
|
|
/**
|
|
|
|
|
* Get the Average value for the PID Source base object.
|
2014-06-12 18:07:45 -04:00
|
|
|
*
|
2013-12-15 18:30:16 -05:00
|
|
|
* @return The average voltage.
|
|
|
|
|
*/
|
Revert changes preventing old user code from compiling.
I'm not 100% sure whether we want these, but they are a quick
find and replace to do.
Basically, there are two primary things that we have done
this summer that break existing user code:
-Changing GetInstance() calls to return references instead
of pointers. This forces users to change from doing something
like LiveWindow::GetInstance()->AddSensor() to LiveWindow::GetInstance().AddSensor().
-Making PIDGet() and related calls const, forcing users to change
the function signatures wherever they override them.
The GetInstance() calls don't really matter to me either way,
especially since there are no real ownership issues going on there,
unlike the rest of the smart pointer-related changes.
For the const stuff, it is certainly more correct to mandate that
user PIDGet() functions be const and the such, but at the same time,
I'm not sure that there is any strong need for it, and the errors
generated are not the most helpful. While this wouldn't necessarily
be an issue for more experienced teams or completely new teams (who
don't have any old code to be reusing), it may cause issues for more
average teams who aren't familiar with the intricacies of C++ anything.
Change-Id: I6e7007982069292ea70e6d0fc8ca40203340df1b
2015-07-24 19:19:40 -04:00
|
|
|
double AnalogInput::PIDGet() {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (StatusIsFatal()) return 0.0;
|
|
|
|
|
return GetAverageVoltage();
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2014-06-12 18:07:45 -04:00
|
|
|
void AnalogInput::UpdateTable() {
|
2015-06-23 04:49:51 -07:00
|
|
|
if (m_table != nullptr) {
|
2015-06-25 15:07:55 -04:00
|
|
|
m_table->PutNumber("Value", GetAverageVoltage());
|
|
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
void AnalogInput::StartLiveWindowMode() {}
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
void AnalogInput::StopLiveWindowMode() {}
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2015-06-19 17:23:54 -07:00
|
|
|
std::string AnalogInput::GetSmartDashboardType() const {
|
2015-06-25 15:07:55 -04:00
|
|
|
return "Analog Input";
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2015-07-29 16:48:04 -04:00
|
|
|
void AnalogInput::InitTable(std::shared_ptr<ITable> subTable) {
|
2015-06-25 15:07:55 -04:00
|
|
|
m_table = subTable;
|
|
|
|
|
UpdateTable();
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2015-07-29 16:48:04 -04:00
|
|
|
std::shared_ptr<ITable> AnalogInput::GetTable() const { return m_table; }
|