blob: a34eb9316ddbb04155d299f8eeab60729aa6f1d2 [file] [log] [blame]
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. 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/Analog.hpp"
#include "HAL/cpp/priority_mutex.h"
#include "HAL/Port.h"
#include "HAL/HAL.hpp"
#include "ChipObject.h"
#include "HAL/cpp/Resource.hpp"
#include "FRC_NetworkCommunication/AICalibration.h"
#include "FRC_NetworkCommunication/LoadOut.h"
static const long kTimebase = 40000000; ///< 40 MHz clock
static const long kDefaultOversampleBits = 0;
static const long kDefaultAverageBits = 7;
static const float kDefaultSampleRate = 50000.0;
static const uint32_t kAnalogInputPins = 8;
static const uint32_t kAnalogOutputPins = 2;
static const uint32_t kAccumulatorNumChannels = 2;
static const uint32_t kAccumulatorChannels[] = {0, 1};
struct AnalogPort {
Port port;
tAccumulator *accumulator;
};
static bool analogSampleRateSet = false;
static priority_recursive_mutex analogRegisterWindowMutex;
static tAI* analogInputSystem = NULL;
static tAO* analogOutputSystem = NULL;
static uint32_t analogNumChannelsToActivate = 0;
extern "C" {
// Utility methods defined below.
static uint32_t getAnalogNumActiveChannels(int32_t *status);
static uint32_t getAnalogNumChannelsToActivate(int32_t *status);
static void setAnalogNumChannelsToActivate(uint32_t channels);
static bool analogSystemInitialized = false;
/**
* Initialize the analog System.
*/
void initializeAnalog(int32_t *status) {
std::lock_guard<priority_recursive_mutex> sync(analogRegisterWindowMutex);
if (analogSystemInitialized) return;
analogInputSystem = tAI::create(status);
analogOutputSystem = tAO::create(status);
setAnalogNumChannelsToActivate(kAnalogInputPins);
setAnalogSampleRate(kDefaultSampleRate, status);
analogSystemInitialized = true;
}
/**
* Initialize the analog input port using the given port object.
*/
void* initializeAnalogInputPort(void* port_pointer, int32_t *status) {
initializeAnalog(status);
Port* port = (Port*) port_pointer;
// Initialize port structure
AnalogPort* analog_port = new AnalogPort();
analog_port->port = *port;
if (isAccumulatorChannel(analog_port, status)) {
analog_port->accumulator = tAccumulator::create(port->pin, status);
} else analog_port->accumulator = NULL;
// Set default configuration
analogInputSystem->writeScanList(port->pin, port->pin, status);
setAnalogAverageBits(analog_port, kDefaultAverageBits, status);
setAnalogOversampleBits(analog_port, kDefaultOversampleBits, status);
return analog_port;
}
void freeAnalogInputPort(void* analog_port_pointer) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
if (!port) return;
delete port->accumulator;
delete port;
}
/**
* Initialize the analog output port using the given port object.
*/
void* initializeAnalogOutputPort(void* port_pointer, int32_t *status) {
initializeAnalog(status);
Port* port = (Port*) port_pointer;
// Initialize port structure
AnalogPort* analog_port = new AnalogPort();
analog_port->port = *port;
analog_port->accumulator = NULL;
return analog_port;
}
void freeAnalogOutputPort(void* analog_port_pointer) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
if (!port) return;
delete port->accumulator;
delete port;
}
/**
* Check that the analog module number is valid.
*
* @return Analog module is valid and present
*/
bool checkAnalogModule(uint8_t module) {
return module == 1;
}
/**
* Check that the analog output channel number is value.
* Verify that the analog channel number is one of the legal channel numbers. Channel numbers
* are 0-based.
*
* @return Analog channel is valid
*/
bool checkAnalogInputChannel(uint32_t pin) {
if (pin < kAnalogInputPins)
return true;
return false;
}
/**
* Check that the analog output channel number is value.
* Verify that the analog channel number is one of the legal channel numbers. Channel numbers
* are 0-based.
*
* @return Analog channel is valid
*/
bool checkAnalogOutputChannel(uint32_t pin) {
if (pin < kAnalogOutputPins)
return true;
return false;
}
void setAnalogOutput(void* analog_port_pointer, double voltage, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
uint16_t rawValue = (uint16_t)(voltage / 5.0 * 0x1000);
if(voltage < 0.0) rawValue = 0;
else if(voltage > 5.0) rawValue = 0x1000;
analogOutputSystem->writeMXP(port->port.pin, rawValue, status);
}
double getAnalogOutput(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
uint16_t rawValue = analogOutputSystem->readMXP(port->port.pin, status);
return rawValue * 5.0 / 0x1000;
}
/**
* Set the sample rate.
*
* This is a global setting for the Athena and effects all channels.
*
* @param samplesPerSecond The number of samples per channel per second.
*/
void setAnalogSampleRate(double samplesPerSecond, int32_t *status) {
// TODO: This will change when variable size scan lists are implemented.
// TODO: Need float comparison with epsilon.
//wpi_assert(!sampleRateSet || GetSampleRate() == samplesPerSecond);
analogSampleRateSet = true;
// Compute the convert rate
uint32_t ticksPerSample = (uint32_t)((float)kTimebase / samplesPerSecond);
uint32_t ticksPerConversion = ticksPerSample / getAnalogNumChannelsToActivate(status);
// ticksPerConversion must be at least 80
if (ticksPerConversion < 80) {
if ((*status) >= 0) *status = SAMPLE_RATE_TOO_HIGH;
ticksPerConversion = 80;
}
// Atomically set the scan size and the convert rate so that the sample rate is constant
tAI::tConfig config;
config.ScanSize = getAnalogNumChannelsToActivate(status);
config.ConvertRate = ticksPerConversion;
analogInputSystem->writeConfig(config, status);
// Indicate that the scan size has been commited to hardware.
setAnalogNumChannelsToActivate(0);
}
/**
* Get the current sample rate.
*
* This assumes one entry in the scan list.
* This is a global setting for the Athena and effects all channels.
*
* @return Sample rate.
*/
float getAnalogSampleRate(int32_t *status) {
uint32_t ticksPerConversion = analogInputSystem->readLoopTiming(status);
uint32_t ticksPerSample = ticksPerConversion * getAnalogNumActiveChannels(status);
return (float)kTimebase / (float)ticksPerSample;
}
/**
* Set the number of averaging bits.
*
* 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.
* The averaging is done automatically in the FPGA.
*
* @param analog_port_pointer Pointer to the analog port to configure.
* @param bits Number of bits to average.
*/
void setAnalogAverageBits(void* analog_port_pointer, uint32_t bits, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
analogInputSystem->writeAverageBits(port->port.pin, bits, status);
}
/**
* Get the number of averaging bits.
*
* This gets the number of averaging bits from the FPGA. The actual number of averaged samples is 2**bits.
* The averaging is done automatically in the FPGA.
*
* @param analog_port_pointer Pointer to the analog port to use.
* @return Bits to average.
*/
uint32_t getAnalogAverageBits(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
uint32_t result = analogInputSystem->readAverageBits(port->port.pin, status);
return result;
}
/**
* Set the number of oversample bits.
*
* This sets the number of oversample bits. The actual number of oversampled 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.
*
* @param analog_port_pointer Pointer to the analog port to use.
* @param bits Number of bits to oversample.
*/
void setAnalogOversampleBits(void* analog_port_pointer, uint32_t bits, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
analogInputSystem->writeOversampleBits(port->port.pin, bits, status);
}
/**
* Get the number of oversample bits.
*
* This gets the number of oversample bits from the FPGA. The actual number of oversampled values is
* 2**bits. The oversampling is done automatically in the FPGA.
*
* @param analog_port_pointer Pointer to the analog port to use.
* @return Bits to oversample.
*/
uint32_t getAnalogOversampleBits(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
uint32_t result = analogInputSystem->readOversampleBits(port->port.pin, status);
return result;
}
/**
* Get a sample straight from the channel on this module.
*
* The sample is a 12-bit value representing the 0V to 5V range of the A/D converter in the module.
* The units are in A/D converter codes. Use GetVoltage() to get the analog value in calibrated units.
*
* @param analog_port_pointer Pointer to the analog port to use.
* @return A sample straight from the channel on this module.
*/
int16_t getAnalogValue(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
int16_t value;
if (!checkAnalogInputChannel(port->port.pin)) {
return 0;
}
tAI::tReadSelect readSelect;
readSelect.Channel = port->port.pin;
readSelect.Averaged = false;
{
std::lock_guard<priority_recursive_mutex> sync(analogRegisterWindowMutex);
analogInputSystem->writeReadSelect(readSelect, status);
analogInputSystem->strobeLatchOutput(status);
value = (int16_t) analogInputSystem->readOutput(status);
}
return value;
}
/**
* Get a sample from the output of the oversample and average engine for the channel.
*
* The sample is 12-bit + the value configured in SetOversampleBits().
* 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**(OversamplBits + AverageBits) samples
* have been acquired from the module on this channel.
* Use GetAverageVoltage() to get the analog value in calibrated units.
*
* @param analog_port_pointer Pointer to the analog port to use.
* @return A sample from the oversample and average engine for the channel.
*/
int32_t getAnalogAverageValue(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
int32_t value;
if (!checkAnalogInputChannel(port->port.pin)) {
return 0;
}
tAI::tReadSelect readSelect;
readSelect.Channel = port->port.pin;
readSelect.Averaged = true;
{
std::lock_guard<priority_recursive_mutex> sync(analogRegisterWindowMutex);
analogInputSystem->writeReadSelect(readSelect, status);
analogInputSystem->strobeLatchOutput(status);
value = (int32_t) analogInputSystem->readOutput(status);
}
return value;
}
/**
* Get a scaled sample straight from the channel on this module.
*
* The value is scaled to units of Volts using the calibrated scaling data from GetLSBWeight() and GetOffset().
*
* @param analog_port_pointer Pointer to the analog port to use.
* @return A scaled sample straight from the channel on this module.
*/
float getAnalogVoltage(void* analog_port_pointer, int32_t *status) {
int16_t value = getAnalogValue(analog_port_pointer, status);
uint32_t LSBWeight = getAnalogLSBWeight(analog_port_pointer, status);
int32_t offset = getAnalogOffset(analog_port_pointer, status);
float voltage = LSBWeight * 1.0e-9 * value - offset * 1.0e-9;
return voltage;
}
/**
* Get a scaled sample from the output of the oversample and average engine for the channel.
*
* 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.
*
* @param analog_port_pointer Pointer to the analog port to use.
* @return A scaled sample from the output of the oversample and average engine for the channel.
*/
float getAnalogAverageVoltage(void* analog_port_pointer, int32_t *status) {
int32_t value = getAnalogAverageValue(analog_port_pointer, status);
uint32_t LSBWeight = getAnalogLSBWeight(analog_port_pointer, status);
int32_t offset = getAnalogOffset(analog_port_pointer, status);
uint32_t oversampleBits = getAnalogOversampleBits(analog_port_pointer, status);
float voltage = ((LSBWeight * 1.0e-9 * value) / (float)(1 << oversampleBits)) - offset * 1.0e-9;
return voltage;
}
/**
* Convert a voltage to a raw value for a specified channel.
*
* This process depends on the calibration of each channel, so the channel
* must be specified.
*
* @todo This assumes raw values. Oversampling not supported as is.
*
* @param analog_port_pointer Pointer to the analog port to use.
* @param voltage The voltage to convert.
* @return The raw value for the channel.
*/
int32_t getAnalogVoltsToValue(void* analog_port_pointer, double voltage, int32_t *status) {
if (voltage > 5.0) {
voltage = 5.0;
*status = VOLTAGE_OUT_OF_RANGE;
}
if (voltage < 0.0) {
voltage = 0.0;
*status = VOLTAGE_OUT_OF_RANGE;
}
uint32_t LSBWeight = getAnalogLSBWeight(analog_port_pointer, status);
int32_t offset = getAnalogOffset(analog_port_pointer, status);
int32_t value = (int32_t) ((voltage + offset * 1.0e-9) / (LSBWeight * 1.0e-9));
return value;
}
/**
* Get the factory scaling least significant bit weight constant.
* The least significant bit weight constant for the channel that was calibrated in
* manufacturing and stored in an eeprom in the module.
*
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
*
* @param analog_port_pointer Pointer to the analog port to use.
* @return Least significant bit weight.
*/
uint32_t getAnalogLSBWeight(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
uint32_t lsbWeight = FRC_NetworkCommunication_nAICalibration_getLSBWeight(0, port->port.pin, status); // XXX: aiSystemIndex == 0?
return lsbWeight;
}
/**
* Get the factory scaling offset constant.
* The offset constant for the channel that was calibrated in manufacturing and stored
* in an eeprom in the module.
*
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
*
* @param analog_port_pointer Pointer to the analog port to use.
* @return Offset constant.
*/
int32_t getAnalogOffset(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
int32_t offset = FRC_NetworkCommunication_nAICalibration_getOffset(0, port->port.pin, status); // XXX: aiSystemIndex == 0?
return offset;
}
/**
* Return the number of channels on the module in use.
*
* @return Active channels.
*/
static uint32_t getAnalogNumActiveChannels(int32_t *status) {
uint32_t scanSize = analogInputSystem->readConfig_ScanSize(status);
if (scanSize == 0)
return 8;
return scanSize;
}
/**
* Get the number of active channels.
*
* This is an internal function to allow the atomic update of both the
* number of active channels and the sample rate.
*
* When the number of channels changes, use the new value. Otherwise,
* return the curent value.
*
* @return Value to write to the active channels field.
*/
static uint32_t getAnalogNumChannelsToActivate(int32_t *status) {
if(analogNumChannelsToActivate == 0) return getAnalogNumActiveChannels(status);
return analogNumChannelsToActivate;
}
/**
* Set the number of active channels.
*
* Store the number of active channels to set. Don't actually commit to hardware
* until SetSampleRate().
*
* @param channels Number of active channels.
*/
static void setAnalogNumChannelsToActivate(uint32_t channels) {
analogNumChannelsToActivate = channels;
}
//// Accumulator Stuff
/**
* Is the channel attached to an accumulator.
*
* @return The analog channel is attached to an accumulator.
*/
bool isAccumulatorChannel(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
for (uint32_t i=0; i < kAccumulatorNumChannels; i++) {
if (port->port.pin == kAccumulatorChannels[i]) return true;
}
return false;
}
/**
* Initialize the accumulator.
*/
void initAccumulator(void* analog_port_pointer, int32_t *status) {
setAccumulatorCenter(analog_port_pointer, 0, status);
resetAccumulator(analog_port_pointer, status);
}
/**
* Resets the accumulator to the initial value.
*/
void resetAccumulator(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
if (port->accumulator == NULL) {
*status = NULL_PARAMETER;
return;
}
port->accumulator->strobeReset(status);
}
/**
* Set the center value of the accumulator.
*
* The center value is subtracted from each A/D value before it is added to the accumulator. This
* is used for the center value of devices like gyros and accelerometers to make integration work
* and to take the device offset into account when integrating.
*
* This center value is based on the output of the oversampled and averaged source from channel 1.
* Because of this, any non-zero oversample bits will affect the size of the value for this field.
*/
void setAccumulatorCenter(void* analog_port_pointer, int32_t center, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
if (port->accumulator == NULL) {
*status = NULL_PARAMETER;
return;
}
port->accumulator->writeCenter(center, status);
}
/**
* Set the accumulator's deadband.
*/
void setAccumulatorDeadband(void* analog_port_pointer, int32_t deadband, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
if (port->accumulator == NULL) {
*status = NULL_PARAMETER;
return;
}
port->accumulator->writeDeadband(deadband, status);
}
/**
* Read the accumulated value.
*
* Read the value that has been accumulating on channel 1.
* The accumulator is attached after the oversample and average engine.
*
* @return The 64-bit value accumulated since the last Reset().
*/
int64_t getAccumulatorValue(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
if (port->accumulator == NULL) {
*status = NULL_PARAMETER;
return 0;
}
int64_t value = port->accumulator->readOutput_Value(status);
return value;
}
/**
* Read the number of accumulated values.
*
* Read the count of the accumulated values since the accumulator was last Reset().
*
* @return The number of times samples from the channel were accumulated.
*/
uint32_t getAccumulatorCount(void* analog_port_pointer, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
if (port->accumulator == NULL) {
*status = NULL_PARAMETER;
return 0;
}
return port->accumulator->readOutput_Count(status);
}
/**
* Read the accumulated value and the number of accumulated values atomically.
*
* This function reads the value and count from the FPGA atomically.
* This can be used for averaging.
*
* @param value Pointer to the 64-bit accumulated output.
* @param count Pointer to the number of accumulation cycles.
*/
void getAccumulatorOutput(void* analog_port_pointer, int64_t *value, uint32_t *count, int32_t *status) {
AnalogPort* port = (AnalogPort*) analog_port_pointer;
if (port->accumulator == NULL) {
*status = NULL_PARAMETER;
return;
}
if (value == NULL || count == NULL) {
*status = NULL_PARAMETER;
return;
}
tAccumulator::tOutput output = port->accumulator->readOutput(status);
*value = output.Value;
*count = output.Count;
}
struct trigger_t {
tAnalogTrigger* trigger;
AnalogPort* port;
uint32_t index;
};
typedef struct trigger_t AnalogTrigger;
static hal::Resource *triggers = NULL;
void* initializeAnalogTrigger(void* port_pointer, uint32_t *index, int32_t *status) {
Port* port = (Port*) port_pointer;
hal::Resource::CreateResourceObject(&triggers, tAnalogTrigger::kNumSystems);
AnalogTrigger* trigger = new AnalogTrigger();
trigger->port = (AnalogPort*) initializeAnalogInputPort(port, status);
trigger->index = triggers->Allocate("Analog Trigger");
*index = trigger->index;
// TODO: if (index == ~0ul) { CloneError(triggers); return; }
trigger->trigger = tAnalogTrigger::create(trigger->index, status);
trigger->trigger->writeSourceSelect_Channel(port->pin, status);
return trigger;
}
void cleanAnalogTrigger(void* analog_trigger_pointer, int32_t *status) {
AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
if (!trigger) return;
triggers->Free(trigger->index);
delete trigger->trigger;
freeAnalogInputPort(trigger->port);
delete trigger;
}
void setAnalogTriggerLimitsRaw(void* analog_trigger_pointer, int32_t lower, int32_t upper, int32_t *status) {
AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
if (lower > upper) {
*status = ANALOG_TRIGGER_LIMIT_ORDER_ERROR;
}
trigger->trigger->writeLowerLimit(lower, status);
trigger->trigger->writeUpperLimit(upper, status);
}
/**
* Set the upper and lower limits of the analog trigger.
* The limits are given as floating point voltage values.
*/
void setAnalogTriggerLimitsVoltage(void* analog_trigger_pointer, double lower, double upper, int32_t *status) {
AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
if (lower > upper) {
*status = ANALOG_TRIGGER_LIMIT_ORDER_ERROR;
}
// TODO: This depends on the averaged setting. Only raw values will work as is.
trigger->trigger->writeLowerLimit(getAnalogVoltsToValue(trigger->port, lower, status), status);
trigger->trigger->writeUpperLimit(getAnalogVoltsToValue(trigger->port, upper, status), status);
}
/**
* Configure the analog trigger to use the averaged vs. raw values.
* If the value is true, then the averaged value is selected for the analog trigger, otherwise
* the immediate value is used.
*/
void setAnalogTriggerAveraged(void* analog_trigger_pointer, bool useAveragedValue, int32_t *status) {
AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
if (trigger->trigger->readSourceSelect_Filter(status) != 0) {
*status = INCOMPATIBLE_STATE;
// TODO: wpi_setWPIErrorWithContext(IncompatibleMode, "Hardware does not support average and filtering at the same time.");
}
trigger->trigger->writeSourceSelect_Averaged(useAveragedValue, status);
}
/**
* Configure the analog trigger to use a filtered value.
* The analog trigger will operate with a 3 point average rejection filter. This is designed to
* help with 360 degree pot applications for the period where the pot crosses through zero.
*/
void setAnalogTriggerFiltered(void* analog_trigger_pointer, bool useFilteredValue, int32_t *status) {
AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
if (trigger->trigger->readSourceSelect_Averaged(status) != 0) {
*status = INCOMPATIBLE_STATE;
// TODO: wpi_setWPIErrorWithContext(IncompatibleMode, "Hardware does not support average and filtering at the same time.");
}
trigger->trigger->writeSourceSelect_Filter(useFilteredValue, status);
}
/**
* Return the InWindow output of the analog trigger.
* True if the analog input is between the upper and lower limits.
* @return The InWindow output of the analog trigger.
*/
bool getAnalogTriggerInWindow(void* analog_trigger_pointer, int32_t *status) {
AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
return trigger->trigger->readOutput_InHysteresis(trigger->index, status) != 0;
}
/**
* Return the TriggerState output of the analog trigger.
* True if above upper limit.
* False if below lower limit.
* If in Hysteresis, maintain previous state.
* @return The TriggerState output of the analog trigger.
*/
bool getAnalogTriggerTriggerState(void* analog_trigger_pointer, int32_t *status) {
AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
return trigger->trigger->readOutput_OverLimit(trigger->index, status) != 0;
}
/**
* Get the state of the analog trigger output.
* @return The state of the analog trigger output.
*/
bool getAnalogTriggerOutput(void* analog_trigger_pointer, AnalogTriggerType type, int32_t *status) {
AnalogTrigger* trigger = (AnalogTrigger*) analog_trigger_pointer;
bool result = false;
switch(type) {
case kInWindow:
result = trigger->trigger->readOutput_InHysteresis(trigger->index, status);
break; // XXX: Backport
case kState:
result = trigger->trigger->readOutput_OverLimit(trigger->index, status);
break; // XXX: Backport
case kRisingPulse:
case kFallingPulse:
*status = ANALOG_TRIGGER_PULSE_OUTPUT_ERROR;
return false;
}
return result;
}
//// Float JNA Hack
// Float
int getAnalogSampleRateIntHack(int32_t *status) {
return floatToInt(getAnalogSampleRate(status));
}
int getAnalogVoltageIntHack(void* analog_port_pointer, int32_t *status) {
return floatToInt(getAnalogVoltage(analog_port_pointer, status));
}
int getAnalogAverageVoltageIntHack(void* analog_port_pointer, int32_t *status) {
return floatToInt(getAnalogAverageVoltage(analog_port_pointer, status));
}
// Doubles
void setAnalogSampleRateIntHack(int samplesPerSecond, int32_t *status) {
setAnalogSampleRate(intToFloat(samplesPerSecond), status);
}
int32_t getAnalogVoltsToValueIntHack(void* analog_port_pointer, int voltage, int32_t *status) {
return getAnalogVoltsToValue(analog_port_pointer, intToFloat(voltage), status);
}
void setAnalogTriggerLimitsVoltageIntHack(void* analog_trigger_pointer, int lower, int upper, int32_t *status) {
setAnalogTriggerLimitsVoltage(analog_trigger_pointer, intToFloat(lower), intToFloat(upper), status);
}
} // extern "C"