Removed AnalogModule, DigitalModule, and Module from C++

The HAL calls from Analog/DigitalModule are now directly in the classes
that use them.

Change-Id: I1cf879ab2979be903d03ab8282dfe5a5e7ae9443
This commit is contained in:
thomasclark
2014-07-21 16:32:36 -04:00
parent f27e16735f
commit 1a77cea13a
25 changed files with 248 additions and 1082 deletions

View File

@@ -9,7 +9,6 @@
#include "SensorBase.h"
#include "PIDSource.h"
#include "LiveWindow/LiveWindowSendable.h"
#include "AnalogModule.h"
/**
* Analog input class.
@@ -31,8 +30,6 @@ public:
explicit AnalogInput(uint32_t channel);
virtual ~AnalogInput();
AnalogModule *GetModule() { return AnalogModule::GetInstance(1); }
int16_t GetValue();
int32_t GetAverageValue();
@@ -59,6 +56,9 @@ public:
uint32_t GetAccumulatorCount();
void GetAccumulatorOutput(int64_t *value, uint32_t *count);
static void SetSampleRate(float samplesPerSecond);
static float GetSampleRate();
double PIDGet();
void UpdateTable();

View File

@@ -1,52 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008. 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 $(WIND_BASE)/WPILib. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "HAL/HAL.hpp"
#include "Module.h"
/**
* Analog Module class.
* Each module can independently sample its channels at a configurable rate.
* There is a 64-bit hardware accumulator associated with channel 1 on each module.
* The accumulator is attached to the output of the oversample and average engine so that the center
* value can be specified in higher resolution resulting in less error.
*/
class AnalogModule : public Module
{
friend class Module;
public:
static const long kTimebase = 40000000; ///< 40 MHz clock
static const long kDefaultOversampleBits = 0;
static const long kDefaultAverageBits = 7;
static const uint32_t kAnalogInputs = 8;
static constexpr float kDefaultSampleRate = 50000.0;
void SetSampleRate(float samplesPerSecond);
float GetSampleRate();
void SetAverageBits(uint32_t channel, uint32_t bits);
uint32_t GetAverageBits(uint32_t channel);
void SetOversampleBits(uint32_t channel, uint32_t bits);
uint32_t GetOversampleBits(uint32_t channel);
int16_t GetValue(uint32_t channel);
int32_t GetAverageValue(uint32_t channel);
float GetAverageVoltage(uint32_t channel);
float GetVoltage(uint32_t channel);
uint32_t GetLSBWeight(uint32_t channel);
int32_t GetOffset(uint32_t channel);
int32_t VoltsToValue(int32_t channel, float voltage);
static AnalogModule* GetInstance(uint8_t moduleNumber);
protected:
explicit AnalogModule(uint8_t moduleNumber);
virtual ~AnalogModule();
private:
uint8_t m_moduleNumber;
void* m_ports[kAnalogInputs];
};

View File

@@ -10,7 +10,6 @@
#include "SensorBase.h"
class AnalogInput;
class AnalogModule;
class AnalogTrigger : public SensorBase
{

View File

@@ -5,8 +5,6 @@
/*----------------------------------------------------------------------------*/
#pragma once
class DigitalModule;
#include "DigitalSource.h"
#include "LiveWindow/LiveWindowSendable.h"
@@ -45,7 +43,6 @@ public:
private:
void InitDigitalInput(uint32_t channel);
uint32_t m_channel;
DigitalModule *m_module;
bool m_lastValue;
ITable *m_table;

View File

@@ -1,66 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008. 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 $(WIND_BASE)/WPILib. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "HAL/HAL.hpp"
#include "Module.h"
class I2C;
const uint32_t kExpectedLoopTiming = 260;
class DigitalModule : public Module
{
friend class I2C;
friend class Module;
protected:
explicit DigitalModule(uint8_t moduleNumber);
virtual ~DigitalModule();
public:
void SetPWM(uint32_t channel, unsigned short value);
unsigned short GetPWM(uint32_t channel);
void SetPWMPeriodScale(uint32_t channel, uint32_t squelchMask);
void SetRelayForward(uint32_t channel, bool on);
void SetRelayReverse(uint32_t channel, bool on);
bool GetRelayForward(uint32_t channel);
uint8_t GetRelayForward();
bool GetRelayReverse(uint32_t channel);
uint8_t GetRelayReverse();
bool AllocateDIO(uint32_t channel, bool input);
void FreeDIO(uint32_t channel);
void SetDIO(uint32_t channel, short value);
bool GetDIO(uint32_t channel);
uint16_t GetDIO();
bool GetDIODirection(uint32_t channel);
uint16_t GetDIODirection();
void Pulse(uint32_t channel, float pulseLength);
bool IsPulsing(uint32_t channel);
bool IsPulsing();
uint32_t AllocateDO_PWM();
void FreeDO_PWM(uint32_t pwmGenerator);
void SetDO_PWMRate(float rate);
void SetDO_PWMDutyCycle(uint32_t pwmGenerator, float dutyCycle);
void SetDO_PWMOutputChannel(uint32_t pwmGenerator, uint32_t channel);
uint16_t GetLoopTiming();
static DigitalModule* GetInstance(uint8_t moduleNumber);
static uint8_t RemapDigitalChannel(uint32_t channel)
{
return 15 - channel;
} // TODO: Need channel validation
static uint8_t UnmapDigitalChannel(uint32_t channel)
{
return 15 - channel;
} // TODO: Need channel validation
private:
uint8_t m_module;
void* m_digital_ports[kDigitalChannels];
void* m_relay_ports[kRelayChannels];
void* m_pwm_ports[kPwmChannels];
};

View File

@@ -9,8 +9,6 @@
#include "LiveWindow/LiveWindowSendable.h"
#include "tables/ITableListener.h"
class DigitalModule;
/**
* Class to write to digital outputs.
* Write values to the digital output channels. Other devices implemented elsewhere will allocate
@@ -51,8 +49,7 @@ private:
void InitDigitalOutput(uint32_t channel);
uint32_t m_channel;
uint32_t m_pwmGenerator;
DigitalModule *m_module;
void *m_pwmGenerator;
ITable *m_table;
};

View File

@@ -7,14 +7,12 @@
#include "SensorBase.h"
class DigitalModule;
/**
* I2C bus interface class.
*
*
* This class is intended to be used by sensor (and other I2C device) drivers.
* It probably should not be used directly.
*
*
*/
class I2C : SensorBase
{

View File

@@ -1,36 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008. 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 $(WIND_BASE)/WPILib. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "SensorBase.h"
#include "NetworkCommunication/LoadOut.h"
#define kMaxModules (nLoadOut::kModuleType_Solenoid * kMaxModuleNumber + (kMaxModuleNumber - 1))
class Module : public SensorBase
{
public:
nLoadOut::tModuleType GetType()
{
return m_moduleType;
}
uint8_t GetNumber()
{
return m_moduleNumber;
}
static Module *GetModule(nLoadOut::tModuleType type, uint8_t number);
protected:
explicit Module(nLoadOut::tModuleType type, uint8_t number);
virtual ~Module();
nLoadOut::tModuleType m_moduleType; ///< The type of module represented.
uint8_t m_moduleNumber; ///< The module index within the module type.
private:
static uint8_t ToIndex(nLoadOut::tModuleType type, uint8_t number);
static Module* m_modules[kMaxModules];
};

View File

@@ -9,8 +9,6 @@
#include "LiveWindow/LiveWindowSendable.h"
#include "tables/ITableListener.h"
class DigitalModule;
/**
* Class implements the PWM generation in the FPGA.
*
@@ -29,7 +27,6 @@ class DigitalModule;
*/
class PWM : public SensorBase, public ITableListener, public LiveWindowSendable
{
friend class DigitalModule;
public:
enum PeriodMultiplier
{
@@ -105,7 +102,6 @@ protected:
private:
void InitPWM(uint32_t channel);
uint32_t m_channel;
DigitalModule *m_module;
int32_t GetMaxPositivePwm()
{
return m_maxPwm;

View File

@@ -10,8 +10,6 @@
#include "LiveWindow/LiveWindowSendable.h"
#include "tables/ITable.h"
class DigitalModule;
/**
* Class for Spike style relay outputs.
* Relays are intended to be connected to spikes or similar relays. The relay channels controls
@@ -59,5 +57,4 @@ private:
uint32_t m_channel;
Direction m_direction;
DigitalModule *m_module;
};

View File

@@ -21,7 +21,7 @@ public:
virtual ~SensorBase();
static void DeleteSingletons();
static uint32_t GetDefaultSolenoidModule()
static uint32_t GetDefaultSolenoidModule()
{
return 0;
}
@@ -44,9 +44,14 @@ public:
static const uint32_t kRelayChannels = 8;
static const uint32_t kPDPChannels = 16;
static const uint32_t kChassisSlots = 8;
protected:
void AddToSingletonList();
static void* m_digital_ports[kDigitalChannels];
static void* m_relay_ports[kRelayChannels];
static void* m_pwm_ports[kPwmChannels];
private:
DISALLOW_COPY_AND_ASSIGN(SensorBase);
static SensorBase *m_singletonList;

View File

@@ -16,7 +16,6 @@
#include "AnalogInput.h"
#include "AnalogOutput.h"
#include "AnalogPotentiometer.h"
#include "AnalogModule.h"
#include "AnalogTrigger.h"
#include "AnalogTriggerOutput.h"
#include "BuiltInAccelerometer.h"
@@ -41,7 +40,6 @@
#include "Counter.h"
#include "Dashboard.h"
#include "DigitalInput.h"
#include "DigitalModule.h"
#include "DigitalOutput.h"
#include "DigitalSource.h"
#include "DoubleSolenoid.h"

View File

@@ -5,7 +5,6 @@
/*----------------------------------------------------------------------------*/
#include "ADXL345_I2C.h"
#include "DigitalModule.h"
//#include "NetworkCommunication/UsageReporting.h"
#include "I2C.h"

View File

@@ -367,6 +367,29 @@ void AnalogInput::GetAccumulatorOutput(int64_t *value, uint32_t *count)
*value += m_accumulatorOffset;
}
/**
* Set the sample rate for all analog channels.
*
* @param samplesPerSecond The number of samples per second.
*/
void AnalogInput::SetSampleRate(float samplesPerSecond)
{
int32_t status = 0;
setAnalogSampleRate(samplesPerSecond, &status);
}
/**
* Get the current sample rate for all channels
*
* @return Sample rate.
*/
float AnalogInput::GetSampleRate()
{
int32_t status = 0;
float sampleRate = getAnalogSampleRate(&status);
return sampleRate;
}
/**
* Get the Average value for the PID Source base object.
*

View File

@@ -1,299 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008. 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 $(WIND_BASE)/WPILib. */
/*----------------------------------------------------------------------------*/
#include "AnalogModule.h"
#include "Timer.h"
#include "WPIErrors.h"
const long AnalogModule::kTimebase; ///< 40 MHz clock
const long AnalogModule::kDefaultOversampleBits;
const long AnalogModule::kDefaultAverageBits;
constexpr float AnalogModule::kDefaultSampleRate;
/**
* Get an instance of an Analog Module.
*
* Singleton analog module creation where a module is allocated on the first use
* and the same module is returned on subsequent uses.
*
* @param moduleNumber The analog module to get (1 or 2).
* @return A pointer to the AnalogModule.
*/
AnalogModule* AnalogModule::GetInstance(uint8_t moduleNumber)
{
if (checkAnalogModule(moduleNumber))
{
return (AnalogModule*)GetModule(nLoadOut::kModuleType_Analog, moduleNumber);
}
// If this wasn't caught before now, make sure we say what's wrong before we crash
char buf[64];
snprintf(buf, 64, "Analog Module %d", moduleNumber);
wpi_setGlobalWPIErrorWithContext(ModuleIndexOutOfRange, buf);
return NULL;
}
/**
* Create a new instance of an analog module.
*
* Create an instance of the analog module object. Initialize all the parameters
* to reasonable values on start.
* Setting a global value on an analog module can be done only once unless subsequent
* values are set the previously set value.
* Analog modules are a singleton, so the constructor is never called outside of this class.
*
* @param moduleNumber The analog module to create (1 or 2).
*/
AnalogModule::AnalogModule(uint8_t moduleNumber)
: Module(nLoadOut::kModuleType_Analog, moduleNumber)
, m_moduleNumber(moduleNumber)
, m_ports()
{
for (uint32_t i = 0; i < kAnalogInputs; i++)
{
void* port = getPortWithModule(moduleNumber, i);
int32_t status = 0;
m_ports[i] = initializeAnalogInputPort(port, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
AddToSingletonList();
}
/**
* Destructor for AnalogModule.
*/
AnalogModule::~AnalogModule()
{
}
/**
* Set the sample rate on the module.
*
* This is a global setting for the module and effects all channels.
*
* @param samplesPerSecond The number of samples per channel per second.
*/
void AnalogModule::SetSampleRate(float samplesPerSecond)
{
int32_t status = 0;
setAnalogSampleRateWithModule(m_moduleNumber, samplesPerSecond, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Get the current sample rate on the module.
*
* This assumes one entry in the scan list.
* This is a global setting for the module and effects all channels.
*
* @return Sample rate.
*/
float AnalogModule::GetSampleRate()
{
int32_t status = 0;
float sampleRate = getAnalogSampleRateWithModule(m_moduleNumber, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return sampleRate;
}
/**
* 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 channel Analog channel to configure.
* @param bits Number of bits to average.
*/
void AnalogModule::SetAverageBits(uint32_t channel, uint32_t bits)
{
int32_t status = 0;
setAnalogAverageBits(m_ports[channel-1], bits, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(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 channel Channel to address.
* @return Bits to average.
*/
uint32_t AnalogModule::GetAverageBits(uint32_t channel)
{
int32_t status = 0;
int32_t averageBits = getAnalogAverageBits(m_ports[channel-1], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return averageBits;
}
/**
* 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 channel Analog channel to configure.
* @param bits Number of bits to oversample.
*/
void AnalogModule::SetOversampleBits(uint32_t channel, uint32_t bits)
{
int32_t status = 0;
setAnalogOversampleBits(m_ports[channel-1], bits, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(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 channel Channel to address.
* @return Bits to oversample.
*/
uint32_t AnalogModule::GetOversampleBits(uint32_t channel)
{
int32_t status = 0;
int32_t oversampleBits = getAnalogOversampleBits(m_ports[channel-1], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return oversampleBits;
}
/**
* Get a sample straight from the channel on this module.
*
* The sample is a 12-bit value representing the -10V to 10V 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.
*
* @return A sample straight from the channel on this module.
*/
int16_t AnalogModule::GetValue(uint32_t channel)
{
int32_t status = 0;
int16_t value = getAnalogValue(m_ports[channel-1], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(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 channel Channel number to read.
* @return A sample from the oversample and average engine for the channel.
*/
int32_t AnalogModule::GetAverageValue(uint32_t channel)
{
int32_t status = 0;
int32_t value = getAnalogAverageValue(m_ports[channel-1], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return value;
}
/**
* 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 channel The channel to convert for.
* @param voltage The voltage to convert.
* @return The raw value for the channel.
*/
int32_t AnalogModule::VoltsToValue(int32_t channel, float voltage)
{
int32_t status = 0;
int32_t value = getAnalogVoltsToValue(m_ports[channel-1], voltage, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(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 channel The channel to read.
* @return A scaled sample straight from the channel on this module.
*/
float AnalogModule::GetVoltage(uint32_t channel)
{
int32_t status = 0;
float voltage = getAnalogVoltage(m_ports[channel-1], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
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 channel The channel to read.
* @return A scaled sample from the output of the oversample and average engine for the channel.
*/
float AnalogModule::GetAverageVoltage(uint32_t channel)
{
int32_t status = 0;
float voltage = getAnalogAverageVoltage(m_ports[channel-1], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return voltage;
}
/**
* 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 channel The channel to get calibration data for.
* @return Least significant bit weight.
*/
uint32_t AnalogModule::GetLSBWeight(uint32_t channel)
{
int32_t status = 0;
int32_t lsbWeight = getAnalogLSBWeight(m_ports[channel-1], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
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 channel The channel to get calibration data for.
* @return Offset constant.
*/
int32_t AnalogModule::GetOffset(uint32_t channel)
{
int32_t status = 0;
int32_t offset = getAnalogOffset(m_ports[channel-1], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return offset;
}

View File

@@ -7,7 +7,6 @@
#include "AnalogTrigger.h"
#include "AnalogInput.h"
#include "AnalogModule.h"
//#include "NetworkCommunication/UsageReporting.h"
#include "Resource.h"
#include "WPIErrors.h"

View File

@@ -5,7 +5,6 @@
/*----------------------------------------------------------------------------*/
#include "DigitalInput.h"
#include "DigitalModule.h"
//#include "NetworkCommunication/UsageReporting.h"
#include "Resource.h"
#include "WPIErrors.h"
@@ -31,8 +30,10 @@ void DigitalInput::InitDigitalInput(uint32_t channel)
return;
}
m_channel = channel;
m_module = DigitalModule::GetInstance(1);
m_module->AllocateDIO(channel, true);
int32_t status = 0;
bool allocated = allocateDIO(m_digital_ports[channel], true, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
HALReport(HALUsageReporting::kResourceType_DigitalInput, channel);
}
@@ -62,7 +63,10 @@ DigitalInput::~DigitalInput()
m_interrupt = NULL;
interruptsResource->Free(m_interruptIndex);
}
m_module->FreeDIO(m_channel);
int32_t status = 0;
freeDIO(m_digital_ports[m_channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/*
@@ -71,8 +75,10 @@ DigitalInput::~DigitalInput()
*/
uint32_t DigitalInput::Get()
{
if (StatusIsFatal()) return 0;
return m_module->GetDIO(m_channel);
int32_t status = 0;
bool value = getDIO(m_digital_ports[m_channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return value;
}
/**
@@ -96,8 +102,7 @@ uint32_t DigitalInput::GetChannelForRouting()
*/
uint32_t DigitalInput::GetModuleForRouting()
{
if (StatusIsFatal()) return 0;
return m_module->GetNumber() - 1;
return 0;
}
/**

View File

@@ -1,413 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008. 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 $(WIND_BASE)/WPILib. */
/*----------------------------------------------------------------------------*/
#include "DigitalModule.h"
#include "I2C.h"
#include "PWM.h"
#include "HAL/cpp/Synchronized.hpp"
#include "WPIErrors.h"
#include <math.h>
/**
* Get an instance of an Digital Module.
* Singleton digital module creation where a module is allocated on the first use
* and the same module is returned on subsequent uses.
*
* @param moduleNumber The digital module to get (1 or 2).
*/
DigitalModule* DigitalModule::GetInstance(uint8_t moduleNumber)
{
if (checkDigitalModule(moduleNumber))
{
return (DigitalModule *)GetModule(nLoadOut::kModuleType_Digital, moduleNumber);
}
// If this wasn't caught before now, make sure we say what's wrong before we crash
char buf[64];
snprintf(buf, 64, "Digital Module %d", moduleNumber);
wpi_setGlobalWPIErrorWithContext(ModuleIndexOutOfRange, buf);
return NULL;
}
/**
* Create a new instance of an digital module.
* Create an instance of the digital module object. Initialize all the parameters
* to reasonable values on start.
* Setting a global value on an digital module can be done only once unless subsequent
* values are set the previously set value.
* Digital modules are a singleton, so the constructor is never called outside of this class.
*
* @param moduleNumber The digital module to create (1 or 2).
*/
DigitalModule::DigitalModule(uint8_t moduleNumber)
: Module(nLoadOut::kModuleType_Digital, moduleNumber)
{
// TODO: Refactor out common logic
m_module = moduleNumber;
for (uint32_t i = 0; i < kDigitalChannels; i++)
{
void* port = getPortWithModule(moduleNumber, i);
int32_t status = 0;
m_digital_ports[i] = initializeDigitalPort(port, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
for (uint32_t i = 0; i < kRelayChannels; i++)
{
void* port = getPortWithModule(moduleNumber, i);
int32_t status = 0;
m_relay_ports[i] = initializeDigitalPort(port, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
for (uint32_t i = 0; i < kPwmChannels; i++)
{
void* port = getPortWithModule(moduleNumber, i);
int32_t status = 0;
m_pwm_ports[i] = initializeDigitalPort(port, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
AddToSingletonList();
}
DigitalModule::~DigitalModule()
{
}
/**
* Set a PWM channel to the desired value. The values range from 0 to 255 and the period is controlled
* by the PWM Period and MinHigh registers.
*
* @param channel The PWM channel to set.
* @param value The PWM value to set.
*/
void DigitalModule::SetPWM(uint32_t channel, unsigned short value)
{
int32_t status = 0;
setPWM(m_pwm_ports[channel], value, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Get a value from a PWM channel.
*
* @param channel The PWM channel to read from.
* @return The raw PWM value.
*/
unsigned short DigitalModule::GetPWM(uint32_t channel)
{
int32_t status = 0;
uint16_t value = getPWM(m_pwm_ports[channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return value;
}
/**
* Set how how often the PWM signal is squelched, thus scaling the period.
*
* @param channel The PWM channel to configure.
* @param squelchMask The 2-bit mask of outputs to squelch.
*/
void DigitalModule::SetPWMPeriodScale(uint32_t channel, uint32_t squelchMask)
{
int32_t status = 0;
setPWMPeriodScale(m_pwm_ports[channel], squelchMask, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Set the state of a relay.
* Set the state of a relay output to be forward. Relays have two outputs and each is
* independently set to 0v or 12v.
*/
void DigitalModule::SetRelayForward(uint32_t channel, bool on)
{
int32_t status = 0;
setRelayForward(m_relay_ports[channel], on, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Set the state of a relay.
* Set the state of a relay output to be reverse. Relays have two outputs and each is
* independently set to 0v or 12v.
*/
void DigitalModule::SetRelayReverse(uint32_t channel, bool on)
{
int32_t status = 0;
setRelayReverse(m_relay_ports[channel], on, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Get the current state of the forward relay channel
*/
bool DigitalModule::GetRelayForward(uint32_t channel)
{
int32_t status = 0;
bool on = getRelayForward(m_relay_ports[channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return on;
}
/**
* Get the current state of all of the forward relay channels on this module.
*/
uint8_t DigitalModule::GetRelayForward()
{
uint8_t value = 0;
for (unsigned int i = 0; i < kRelayChannels; i++) {
value |= GetRelayForward(i) << i;
}
return value;
}
/**
* Get the current state of the reverse relay channel
*/
bool DigitalModule::GetRelayReverse(uint32_t channel)
{
int32_t status = 0;
bool on = getRelayReverse(m_relay_ports[channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return on;
}
/**
* Get the current state of all of the reverse relay channels on this module.
*/
uint8_t DigitalModule::GetRelayReverse()
{
uint8_t value = 0;
for (unsigned int i = 0; i < kRelayChannels; i++) {
value |= GetRelayReverse(i) << i;
}
return value;
}
/**
* Allocate Digital I/O channels.
* Allocate channels so that they are not accidently reused. Also the direction is set at the
* time of the allocation.
*
* @param channel The Digital I/O channel
* @param input If true open as input; if false open as output
* @return Was successfully allocated
*/
bool DigitalModule::AllocateDIO(uint32_t channel, bool input)
{
int32_t status = 0;
bool allocated = allocateDIO(m_digital_ports[channel], input, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return allocated;
}
/**
* Free the resource associated with a digital I/O channel.
*
* @param channel The Digital I/O channel to free
*/
void DigitalModule::FreeDIO(uint32_t channel)
{
int32_t status = 0;
freeDIO(m_digital_ports[channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Write a digital I/O bit to the FPGA.
* Set a single value on a digital I/O channel.
*
* @param channel The Digital I/O channel
* @param value The state to set the digital channel (if it is configured as an output)
*/
void DigitalModule::SetDIO(uint32_t channel, short value)
{
int32_t status = 0;
setDIO(m_digital_ports[channel], value, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Read a digital I/O bit from the FPGA.
* Get a single value from a digital I/O channel.
*
* @param channel The digital I/O channel
* @return The state of the specified channel
*/
bool DigitalModule::GetDIO(uint32_t channel)
{
int32_t status = 0;
bool value = getDIO(m_digital_ports[channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return value;
}
/**
* Read the state of all the Digital I/O lines from the FPGA
* These are not remapped to logical order. They are still in hardware order.
*/
uint16_t DigitalModule::GetDIO()
{
uint16_t value = 0;
for (unsigned int i = 0; i < kDigitalChannels; i++) {
value |= GetDIO(i) << i;
}
return value;
}
/**
* Read the direction of a the Digital I/O lines
* A 1 bit means output and a 0 bit means input.
*
* @param channel The digital I/O channel
* @return The direction of the specified channel
*/
bool DigitalModule::GetDIODirection(uint32_t channel)
{
int32_t status = 0;
bool value = getDIODirection(m_digital_ports[channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return value;
}
/**
* Read the direction of all the Digital I/O lines from the FPGA
* A 1 bit means output and a 0 bit means input.
* These are not remapped to logical order. They are still in hardware order.
*/
uint16_t DigitalModule::GetDIODirection()
{
uint16_t value = 0;
for (unsigned int i = 0; i < kDigitalChannels; i++) {
value |= GetDIODirection(i) << i;
}
return value;
}
/**
* Generate a single pulse.
* Write a pulse to the specified digital output channel. There can only be a single pulse going at any time.
*
* @param channel The Digital Output channel that the pulse should be output on
* @param pulseLength The active length of the pulse (in seconds)
*/
void DigitalModule::Pulse(uint32_t channel, float pulseLength)
{
int32_t status = 0;
pulse(m_digital_ports[channel], pulseLength, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Check a DIO line to see if it is currently generating a pulse.
*
* @return A pulse is in progress
*/
bool DigitalModule::IsPulsing(uint32_t channel)
{
int32_t status = 0;
bool value = isPulsing(m_digital_ports[channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return value;
}
/**
* Check if any DIO line is currently generating a pulse.
*
* @return A pulse on some line is in progress
*/
bool DigitalModule::IsPulsing()
{
int32_t status = 0;
bool value = isAnyPulsing(&status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return value;
}
/**
* Allocate a DO PWM Generator.
* Allocate PWM generators so that they are not accidently reused.
*
* @return PWM Generator refnum
*/
uint32_t DigitalModule::AllocateDO_PWM()
{
int32_t status = 0;
uint32_t value = *((uint32_t*) allocatePWMWithModule(m_module, &status)); // TODO: Hacky
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return value;
}
/**
* Free the resource associated with a DO PWM generator.
*
* @param pwmGenerator The pwmGen to free that was allocated with AllocateDO_PWM()
*/
void DigitalModule::FreeDO_PWM(uint32_t pwmGenerator) // Note: should become void*
{
int32_t status = 0;
void* generator = &pwmGenerator;
freePWMWithModule(m_module, generator, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Change the frequency of the DO PWM generator.
*
* The valid range is from 0.6 Hz to 19 kHz. The frequency resolution is logarithmic.
*
* @param rate The frequency to output all digital output PWM signals on this module.
*/
void DigitalModule::SetDO_PWMRate(float rate)
{
int32_t status = 0;
setPWMRateWithModule(m_module, rate, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Configure which DO channel the PWM siganl is output on
*
* @param pwmGenerator The generator index reserved by AllocateDO_PWM()
* @param channel The Digital Output channel to output on
*/
void DigitalModule::SetDO_PWMOutputChannel(uint32_t pwmGenerator, uint32_t channel) // pwmGenerator should become void*
{
int32_t status = 0;
void* generator = &pwmGenerator;
setPWMOutputChannelWithModule(m_module, generator, channel, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Configure the duty-cycle of the PWM generator
*
* @param pwmGenerator The generator index reserved by AllocateDO_PWM()
* @param dutyCycle The percent duty cycle to output [0..1].
*/
void DigitalModule::SetDO_PWMDutyCycle(uint32_t pwmGenerator, float dutyCycle)
{
int32_t status = 0;
void* generator = &pwmGenerator;
setPWMDutyCycleWithModule(m_module, generator, dutyCycle, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
* Get the loop timing of the Digital Module
*
* @return The loop time
*/
uint16_t DigitalModule::GetLoopTiming()
{
int32_t status = 0;
uint16_t timing = getLoopTimingWithModule(m_module, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return timing;
}

View File

@@ -5,7 +5,6 @@
/*----------------------------------------------------------------------------*/
#include "DigitalOutput.h"
#include "DigitalModule.h"
//#include "NetworkCommunication/UsageReporting.h"
#include "Resource.h"
#include "WPIErrors.h"
@@ -29,9 +28,11 @@ void DigitalOutput::InitDigitalOutput(uint32_t channel)
return;
}
m_channel = channel;
m_pwmGenerator = ~0ul;
m_module = DigitalModule::GetInstance(1);
m_module->AllocateDIO(m_channel, false);
m_pwmGenerator = (void *)~0ul;
int32_t status = 0;
allocateDIO(m_digital_ports[channel], false, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
HALReport(HALUsageReporting::kResourceType_DigitalOutput, channel);
}
@@ -55,7 +56,10 @@ DigitalOutput::~DigitalOutput()
if (StatusIsFatal()) return;
// Disable the PWM in case it was running.
DisablePWM();
m_module->FreeDIO(m_channel);
int32_t status = 0;
freeDIO(m_digital_ports[m_channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
@@ -65,7 +69,10 @@ DigitalOutput::~DigitalOutput()
void DigitalOutput::Set(uint32_t value)
{
if (StatusIsFatal()) return;
m_module->SetDIO(m_channel, value);
int32_t status = 0;
setDIO(m_digital_ports[m_channel], value, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
@@ -85,7 +92,10 @@ uint32_t DigitalOutput::GetChannel()
void DigitalOutput::Pulse(float length)
{
if (StatusIsFatal()) return;
m_module->Pulse(m_channel, length);
int32_t status = 0;
pulse(m_digital_ports[m_channel], length, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
@@ -95,7 +105,11 @@ void DigitalOutput::Pulse(float length)
bool DigitalOutput::IsPulsing()
{
if (StatusIsFatal()) return false;
return m_module->IsPulsing(m_channel);
int32_t status = 0;
bool value = isPulsing(m_digital_ports[m_channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return value;
}
/**
@@ -103,14 +117,17 @@ bool DigitalOutput::IsPulsing()
*
* The valid range is from 0.6 Hz to 19 kHz. The frequency resolution is logarithmic.
*
* There is only one PWM frequency per digital module.
* There is only one PWM frequency for all digital channels.
*
* @param rate The frequency to output all digital output PWM signals on this module.
* @param rate The frequency to output all digital output PWM signals.
*/
void DigitalOutput::SetPWMRate(float rate)
{
if (StatusIsFatal()) return;
m_module->SetDO_PWMRate(rate);
int32_t status = 0;
setPWMRate(rate, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
@@ -127,11 +144,21 @@ void DigitalOutput::SetPWMRate(float rate)
*/
void DigitalOutput::EnablePWM(float initialDutyCycle)
{
if (StatusIsFatal()) return;
if (m_pwmGenerator != ~0ul) return;
m_pwmGenerator = m_module->AllocateDO_PWM();
m_module->SetDO_PWMDutyCycle(m_pwmGenerator, initialDutyCycle);
m_module->SetDO_PWMOutputChannel(m_pwmGenerator, m_channel);
if(m_pwmGenerator != (void *)~0ul) return;
int32_t status = 0;
if(StatusIsFatal()) return;
m_pwmGenerator = allocatePWM(&status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
if(StatusIsFatal()) return;
setPWMDutyCycle(m_pwmGenerator, initialDutyCycle, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
if(StatusIsFatal()) return;
setPWMOutputChannel(m_pwmGenerator, m_channel, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
@@ -142,10 +169,18 @@ void DigitalOutput::EnablePWM(float initialDutyCycle)
void DigitalOutput::DisablePWM()
{
if (StatusIsFatal()) return;
if(m_pwmGenerator == (void *)~0ul) return;
int32_t status = 0;
// Disable the output by routing to a dead bit.
m_module->SetDO_PWMOutputChannel(m_pwmGenerator, kDigitalChannels);
m_module->FreeDO_PWM(m_pwmGenerator);
m_pwmGenerator = ~0ul;
setPWMOutputChannel(m_pwmGenerator, kDigitalChannels, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
freePWM(m_pwmGenerator, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
m_pwmGenerator = (void *)~0ul;
}
/**
@@ -159,7 +194,10 @@ void DigitalOutput::DisablePWM()
void DigitalOutput::UpdateDutyCycle(float dutyCycle)
{
if (StatusIsFatal()) return;
m_module->SetDO_PWMDutyCycle(m_pwmGenerator, dutyCycle);
int32_t status = 0;
setPWMDutyCycle(m_pwmGenerator, dutyCycle, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
@@ -167,7 +205,7 @@ void DigitalOutput::UpdateDutyCycle(float dutyCycle)
*/
uint32_t DigitalOutput::GetChannelForRouting()
{
return DigitalModule::RemapDigitalChannel(GetChannel() - 1);
return GetChannel();
}
/**
@@ -175,8 +213,7 @@ uint32_t DigitalOutput::GetChannelForRouting()
*/
uint32_t DigitalOutput::GetModuleForRouting()
{
if (StatusIsFatal()) return 0;
return m_module->GetNumber() - 1;
return 0;
}
/**

View File

@@ -6,7 +6,6 @@
#include "Gyro.h"
#include "AnalogInput.h"
#include "AnalogModule.h"
//#include "NetworkCommunication/UsageReporting.h"
#include "Timer.h"
#include "WPIErrors.h"
@@ -46,7 +45,7 @@ void Gyro::InitGyro()
m_analog->SetOversampleBits(kOversampleBits);
float sampleRate = kSamplesPerSecond *
(1 << (kAverageBits + kOversampleBits));
m_analog->GetModule()->SetSampleRate(sampleRate);
m_analog->SetSampleRate(sampleRate);
Wait(1.0);
m_analog->InitAccumulator();
@@ -148,7 +147,7 @@ float Gyro::GetAngle( void )
int64_t value = rawValue - (int64_t)((float)count * m_offset);
double scaledValue = value * 1e-9 * (double)m_analog->GetLSBWeight() * (double)(1 << m_analog->GetAverageBits()) /
(m_analog->GetModule()->GetSampleRate() * m_voltsPerDegreePerSecond);
(m_analog->GetSampleRate() * m_voltsPerDegreePerSecond);
return (float)scaledValue;
}

View File

@@ -5,14 +5,13 @@
/*----------------------------------------------------------------------------*/
#include "I2C.h"
#include "DigitalModule.h"
//#include "NetworkCommunication/UsageReporting.h"
#include "HAL/Digital.hpp"
#include "WPIErrors.h"
/**
* Constructor.
*
*
* @param Port The I2C port to which the device is connected.
* @param deviceAddress The address of the device on the I2C bus.
*/
@@ -37,9 +36,9 @@ I2C::~I2C()
/**
* Generic transaction.
*
*
* This is a lower-level interface to the I2C hardware giving you more control over each transaction.
*
*
* @param dataToSend Buffer of data to send as part of the transaction.
* @param sendSize Number of bytes to send as part of the transaction. [0..6]
* @param dataReceived Buffer to read data into.
@@ -68,10 +67,10 @@ bool I2C::Transaction(uint8_t *dataToSend, uint8_t sendSize, uint8_t *dataReceiv
/**
* Attempt to address a device on the I2C bus.
*
*
* This allows you to figure out if there is a device on the I2C bus that
* responds to the address specified in the constructor.
*
*
* @return Transfer Aborted... false for success, true for aborted.
*/
bool I2C::AddressOnly()
@@ -83,10 +82,10 @@ bool I2C::AddressOnly()
/**
* Execute a write transaction with the device.
*
*
* Write a single byte to a register on a device and wait until the
* transaction is complete.
*
*
* @param registerAddress The address of the register on the device to be written.
* @param data The byte to write to the register on the device.
* @return Transfer Aborted... false for success, true for aborted.
@@ -120,12 +119,12 @@ bool I2C::WriteBulk(uint8_t* data, uint8_t count)
/**
* Execute a read transaction with the device.
*
*
* Read 1 to 7 bytes from a device.
* Most I2C devices will auto-increment the register pointer internally
* allowing you to read up to 7 consecutive registers on a device in a
* single transaction.
*
*
* @param registerAddress The register to read first in the transaction.
* @param count The number of bytes to read in the transaction. [1..7]
* @param buffer A pointer to the array of bytes to store the data read from the device.
@@ -180,9 +179,9 @@ bool I2C::ReadOnly(uint8_t count, uint8_t *buffer)
/**
* Send a broadcast write to all devices on the I2C bus.
*
*
* This is not currently implemented!
*
*
* @param registerAddress The register to write on all devices on the bus.
* @param data The value to write to the devices.
*/
@@ -192,13 +191,13 @@ void I2C::Broadcast(uint8_t registerAddress, uint8_t data)
/**
* Verify that a device's registers contain expected values.
*
*
* Most devices will have a set of registers that contain a known value that
* can be used to identify them. This allows an I2C device driver to easily
* verify that the device contains the expected value.
*
*
* @pre The device must support and be configured to use register auto-increment.
*
*
* @param registerAddress The base register to start reading from the device.
* @param count The size of the field to be verified.
* @param expected A buffer containing the values expected from the device.
@@ -220,4 +219,3 @@ bool I2C::VerifySensor(uint8_t registerAddress, uint8_t count, const uint8_t *ex
}
return true;
}

View File

@@ -1,76 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008. 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 $(WIND_BASE)/WPILib. */
/*----------------------------------------------------------------------------*/
#include "Module.h"
#include "AnalogModule.h"
#include "DigitalModule.h"
//#include "SolenoidModule.h"
Module* Module::m_modules[kMaxModules] = {NULL};
/**
* Constructor.
*
* @param type The type of module represented.
* @param number The module index within the module type.
*/
Module::Module(nLoadOut::tModuleType type, uint8_t number)
: m_moduleType (type)
, m_moduleNumber (number)
{
m_modules[ToIndex(type, number)] = this;
}
/**
* Destructor.
*/
Module::~Module()
{
}
/**
* Static module singleton factory.
*
* @param type The type of module represented.
* @param number The module index within the module type.
*/
Module* Module::GetModule(nLoadOut::tModuleType type, uint8_t number)
{
if (m_modules[ToIndex(type, number)] == NULL)
{
switch(type)
{
case nLoadOut::kModuleType_Analog:
new AnalogModule(number);
break;
case nLoadOut::kModuleType_Digital:
new DigitalModule(number);
break;
/*
case nLoadOut::kModuleType_Solenoid:
new SolenoidModule(number);
break;
*/
default:
return NULL;
}
}
return m_modules[ToIndex(type, number)];
}
/**
* Create an index into the m_modules array based on type and number
*
* @param type The type of module represented.
* @param number The module index within the module type.
* @return The index into m_modules.
*/
uint8_t Module::ToIndex(nLoadOut::tModuleType type, uint8_t number)
{
if (number == 0 || number > kMaxModuleNumber) return 0;
if (type < nLoadOut::kModuleType_Analog || type > nLoadOut::kModuleType_Solenoid) return 0;
return (type * kMaxModuleNumber) + (number - 1);
}

View File

@@ -6,7 +6,6 @@
#include "PWM.h"
#include "DigitalModule.h"
//#include "NetworkCommunication/UsageReporting.h"
#include "Resource.h"
#include "Utility.h"
@@ -44,9 +43,13 @@ void PWM::InitPWM(uint32_t channel)
CloneError(allocated);
return;
}
m_channel = channel;
m_module = DigitalModule::GetInstance(1);
m_module->SetPWM(m_channel, kPwmDisabled);
int32_t status = 0;
setPWM(m_pwm_ports[m_channel], kPwmDisabled, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
m_eliminateDeadband = false;
HALReport(HALUsageReporting::kResourceType_PWM, channel);
@@ -58,7 +61,6 @@ void PWM::InitPWM(uint32_t channel)
* @param channel The PWM channel.
*/
PWM::PWM(uint32_t channel)
: m_module(NULL)
{
InitPWM(channel);
}
@@ -70,11 +72,11 @@ PWM::PWM(uint32_t channel)
*/
PWM::~PWM()
{
if (m_module)
{
m_module->SetPWM(m_channel, kPwmDisabled);
allocated->Free(m_channel);
}
int32_t status = 0;
setPWM(m_pwm_ports[m_channel], kPwmDisabled, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
allocated->Free(m_channel);
}
/**
@@ -123,15 +125,17 @@ void PWM::SetBounds(int32_t max, int32_t deadbandMax, int32_t center, int32_t de
void PWM::SetBounds(double max, double deadbandMax, double center, double deadbandMin, double min)
{
// calculate the loop time in milliseconds
double loopTime = m_module->GetLoopTiming()/(kSystemClockTicksPerMicrosecond*1e3);
int32_t status = 0;
double loopTime = getLoopTiming(&status)/(kSystemClockTicksPerMicrosecond*1e3);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
if (StatusIsFatal()) return;
m_maxPwm = (int32_t)((max-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
m_deadbandMaxPwm = (int32_t)((deadbandMax-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
m_centerPwm = (int32_t)((center-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
m_deadbandMinPwm = (int32_t)((deadbandMin-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
m_minPwm = (int32_t)((min-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
// printf("Calculated m_minPwm: %d min: %lf loopTime: %lf defaultStepsDown: %d\n", m_minPwm, min, loopTime, kDefaultPwmStepsDown);
m_maxPwm = (int32_t)((max-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
m_deadbandMaxPwm = (int32_t)((deadbandMax-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
m_centerPwm = (int32_t)((center-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
m_deadbandMinPwm = (int32_t)((deadbandMin-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
m_minPwm = (int32_t)((min-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
}
/**
@@ -298,7 +302,10 @@ float PWM::GetSpeed()
void PWM::SetRaw(unsigned short value)
{
if (StatusIsFatal()) return;
m_module->SetPWM(m_channel, value);
int32_t status = 0;
setPWM(m_pwm_ports[m_channel], value, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
@@ -311,7 +318,12 @@ void PWM::SetRaw(unsigned short value)
unsigned short PWM::GetRaw()
{
if (StatusIsFatal()) return 0;
return m_module->GetPWM(m_channel);
int32_t status = 0;
unsigned short value = getPWM(m_pwm_ports[m_channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return value;
}
/**
@@ -322,20 +334,25 @@ unsigned short PWM::GetRaw()
void PWM::SetPeriodMultiplier(PeriodMultiplier mult)
{
if (StatusIsFatal()) return;
int32_t status = 0;
switch(mult)
{
case kPeriodMultiplier_4X:
m_module->SetPWMPeriodScale(m_channel, 3); // Squelch 3 out of 4 outputs
setPWMPeriodScale(m_pwm_ports[m_channel], 3, &status); // Squelch 3 out of 4 outputs
break;
case kPeriodMultiplier_2X:
m_module->SetPWMPeriodScale(m_channel, 1); // Squelch 1 out of 2 outputs
setPWMPeriodScale(m_pwm_ports[m_channel], 1, &status); // Squelch 1 out of 2 outputs
break;
case kPeriodMultiplier_1X:
m_module->SetPWMPeriodScale(m_channel, 0); // Don't squelch any outputs
setPWMPeriodScale(m_pwm_ports[m_channel], 0, &status); // Don't squelch any outputs
break;
default:
wpi_assert(false);
}
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}

View File

@@ -1,12 +1,11 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
/*----------------------------------------------------------------------------*/
#include "Relay.h"
#include "DigitalModule.h"
//#include "NetworkCommunication/UsageReporting.h"
#include "Resource.h"
#include "WPIErrors.h"
@@ -54,9 +53,12 @@ void Relay::InitRelay()
HALReport(HALUsageReporting::kResourceType_Relay, m_channel + 128);
}
m_module = DigitalModule::GetInstance(1);
m_module->SetRelayForward(m_channel, false);
m_module->SetRelayReverse(m_channel, false);
int32_t status = 0;
setRelayForward(m_relay_ports[m_channel], false, &status);
setRelayReverse(m_relay_ports[m_channel], false, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
LiveWindow::GetInstance()->AddActuator("Relay", 1, m_channel, this);
}
@@ -78,8 +80,11 @@ Relay::Relay(uint32_t channel, Relay::Direction direction)
*/
Relay::~Relay()
{
m_module->SetRelayForward(m_channel, false);
m_module->SetRelayReverse(m_channel, false);
int32_t status = 0;
setRelayForward(m_relay_ports[m_channel], false, &status);
setRelayReverse(m_relay_ports[m_channel], false, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
if (m_direction == kBothDirections || m_direction == kForwardOnly)
{
@@ -97,37 +102,40 @@ Relay::~Relay()
* Valid values depend on which directions of the relay are controlled by the object.
*
* When set to kBothDirections, the relay can be any of the four states:
* 0v-0v, 0v-12v, 12v-0v, 12v-12v
* 0v-0v, 0v-12v, 12v-0v, 12v-12v
*
* When set to kForwardOnly or kReverseOnly, you can specify the constant for the
* direction or you can simply specify kOff and kOn. Using only kOff and kOn is
* recommended.
* direction or you can simply specify kOff and kOn. Using only kOff and kOn is
* recommended.
*
* @param value The state to set the relay.
*/
void Relay::Set(Relay::Value value)
{
if (StatusIsFatal()) return;
int32_t status = 0;
switch (value)
{
case kOff:
if (m_direction == kBothDirections || m_direction == kForwardOnly)
{
m_module->SetRelayForward(m_channel, false);
setRelayForward(m_relay_ports[m_channel], false, &status);
}
if (m_direction == kBothDirections || m_direction == kReverseOnly)
{
m_module->SetRelayReverse(m_channel, false);
setRelayReverse(m_relay_ports[m_channel], false, &status);
}
break;
case kOn:
if (m_direction == kBothDirections || m_direction == kForwardOnly)
{
m_module->SetRelayForward(m_channel, true);
setRelayForward(m_relay_ports[m_channel], true, &status);
}
if (m_direction == kBothDirections || m_direction == kReverseOnly)
{
m_module->SetRelayReverse(m_channel, true);
setRelayReverse(m_relay_ports[m_channel], true, &status);
}
break;
case kForward:
@@ -138,11 +146,11 @@ void Relay::Set(Relay::Value value)
}
if (m_direction == kBothDirections || m_direction == kForwardOnly)
{
m_module->SetRelayForward(m_channel, true);
setRelayForward(m_relay_ports[m_channel], true, &status);
}
if (m_direction == kBothDirections)
{
m_module->SetRelayReverse(m_channel, false);
setRelayReverse(m_relay_ports[m_channel], false, &status);
}
break;
case kReverse:
@@ -153,14 +161,16 @@ void Relay::Set(Relay::Value value)
}
if (m_direction == kBothDirections)
{
m_module->SetRelayForward(m_channel, false);
setRelayForward(m_relay_ports[m_channel], false, &status);
}
if (m_direction == kBothDirections || m_direction == kReverseOnly)
{
m_module->SetRelayReverse(m_channel, true);
setRelayReverse(m_relay_ports[m_channel], true, &status);
}
break;
}
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**
@@ -174,27 +184,31 @@ void Relay::Set(Relay::Value value)
* @return The current state of the relay as a Relay::Value
*/
Relay::Value Relay::Get() {
if(m_module->GetRelayForward(m_channel)) {
if(m_module->GetRelayReverse(m_channel)) {
return kOn;
} else {
if(m_direction == kForwardOnly) {
return kOn;
} else {
return kForward;
}
}
} else {
if(m_module->GetRelayReverse(m_channel)) {
if(m_direction == kReverseOnly) {
return kOn;
} else {
return kReverse;
}
} else {
return kOff;
}
}
int32_t status;
if(getRelayForward(m_relay_ports[m_channel], &status)) {
if(getRelayReverse(m_relay_ports[m_channel], &status)) {
return kOn;
} else {
if(m_direction == kForwardOnly) {
return kOn;
} else {
return kForward;
}
}
} else {
if(getRelayReverse(m_relay_ports[m_channel], &status)) {
if(m_direction == kReverseOnly) {
return kOn;
} else {
return kReverse;
}
} else {
return kOff;
}
}
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
void Relay::ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew) {

View File

@@ -19,11 +19,41 @@ const uint32_t SensorBase::kPDPChannels;
const uint32_t SensorBase::kChassisSlots;
SensorBase *SensorBase::m_singletonList = NULL;
static bool portsInitialized = false;
void* SensorBase::m_digital_ports[kDigitalChannels];
void* SensorBase::m_relay_ports[kRelayChannels];
void* SensorBase::m_pwm_ports[kPwmChannels];
/**
* Creates an instance of the sensor base and gets an FPGA handle
*/
SensorBase::SensorBase()
{
if(!portsInitialized) {
for (uint32_t i = 0; i < kDigitalChannels; i++)
{
void* port = getPort(i);
int32_t status = 0;
m_digital_ports[i] = initializeDigitalPort(port, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
for (uint32_t i = 0; i < kRelayChannels; i++)
{
void* port = getPort(i);
int32_t status = 0;
m_relay_ports[i] = initializeDigitalPort(port, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
for (uint32_t i = 0; i < kPwmChannels; i++)
{
void* port = getPort(i);
int32_t status = 0;
m_pwm_ports[i] = initializeDigitalPort(port, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
}
/**
@@ -141,9 +171,9 @@ bool SensorBase::CheckAnalogInput(uint32_t channel)
*/
bool SensorBase::CheckAnalogOutput(uint32_t channel)
{
if (channel < kAnalogOutputs)
return true;
return false;
if (channel < kAnalogOutputs)
return true;
return false;
}
/**