/**
 * 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.
 */
DigitalModule::DigitalModule(UINT32 slot)
	: Module(slot)
	, m_fpgaDIO (NULL)
{
	Resource::CreateResourceObject(&DIOChannels, tDIO::kNumSystems * kDigitalChannels);
	m_fpgaDIO = new tDIO(SlotToIndex(m_slot), &status);

	// Make sure that the 9403 IONode has had a chance to initialize before continuing.
	while(m_fpgaDIO->readLoopTiming(&status) == 0) taskDelay(1);
	if (m_fpgaDIO->readLoopTiming(&status) != kExpectedLoopTiming)
	{
		wpi_fatal(LoopTimingError);
		printf("DIO LoopTiming: %d, expecting: %d\n", m_fpgaDIO->readLoopTiming(&status), kExpectedLoopTiming);
	}
	m_fpgaDIO->writePWMConfig_Period(PWM::kDefaultPwmPeriod, &status);
	m_fpgaDIO->writePWMConfig_MinHigh(PWM::kDefaultMinPwmHigh, &status);

	// Ensure that PWM output values are set to OFF
	for (UINT32 pwm_index = 1; pwm_index <= kPwmChannels; pwm_index++)
	{
		SetPWM(pwm_index, PWM::kPwmDisabled);
		SetPWMPeriodScale(pwm_index, 3); // Set all to 4x by default.
	}

	// Turn off all relay outputs.
	m_fpgaDIO->writeSlowValue_RelayFwd(0, &status);
	m_fpgaDIO->writeSlowValue_RelayRev(0, &status);

	// Create a semaphore to protect changes to the relay values
	m_relaySemaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);

	AddToSingletonList();
}
Beispiel #2
0
/**
 * 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 slot The slot in the chassis that the module is plugged into.
 */
AnalogModule::AnalogModule(UINT32 slot)
	: Module(slot)
	, m_module (NULL)
	, m_sampleRateSet (false)
	, m_numChannelsToActivate (0)
{
	status = 0;
	AddToSingletonList();
	m_module = new tAI(SlotToIndex(slot), &status);
	SetNumChannelsToActivate(kAnalogChannels);
	SetSampleRate(kDefaultSampleRate);

	for (UINT32 i = 0; i < kAnalogChannels; i++)
	{
		m_module->writeScanList(i, i, &status);
		SetAverageBits(i + 1, kDefaultAverageBits);
		SetOversampleBits(i + 1, kDefaultOversampleBits);
	}

	if (m_registerWindowSemaphore == NULL)
	{
		// Needs to be global since the protected resource spans both module singletons.
		m_registerWindowSemaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
	}

	wpi_assertCleanStatus(status);
}
Beispiel #3
0
/**
 * Destructor.
 */
Solenoid::~Solenoid()
{
	allocated->Free(SlotToIndex(m_chassisSlot) * kSolenoidChannels + m_channel - 1);
	if (m_refCount == 1)
	{
		delete m_fpgaSolenoidModule;
		m_fpgaSolenoidModule = NULL;
		semDelete(m_semaphore);
		m_semaphore = NULL;
	}
	m_refCount--;
}
Beispiel #4
0
/**
 * Common function to implement constructor behavior.
 */
void Solenoid::InitSolenoid()
{
	Resource::CreateResourceObject(&allocated, tSolenoid::kNumSystems * kSolenoidChannels);
	CheckSolenoidModule(m_chassisSlot);
	CheckSolenoidChannel(m_channel);

	m_refCount++;
	if (m_refCount == 1)
	{
		// Needs to be global since the protected resource spans all Solenoid objects.
		m_semaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
		m_fpgaSolenoidModule = new tSolenoid(&status);
	}

	allocated->Allocate(SlotToIndex(m_chassisSlot) * kSolenoidChannels + m_channel - 1);
	wpi_assertCleanStatus(status);
}
/**
 * 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.
 */
bool DigitalModule::AllocateDIO(UINT32 channel, bool input)
{
	status = 0;
	DIOChannels->Allocate(kDigitalChannels * SlotToIndex(m_slot) + channel - 1);
	UINT32 outputEnable = m_fpgaDIO->readOutputEnable(&status);
	UINT32 bitToSet = 1 << (RemapDigitalChannel(channel - 1));
	UINT32 outputEnableValue;
	if (input)
	{
		outputEnableValue = outputEnable & (~ bitToSet ); // clear the bit for read
	}
	else
	{
		outputEnableValue = outputEnable | bitToSet; // set the bit for write
	}
	m_fpgaDIO->writeOutputEnable(outputEnableValue, &status);
	wpi_assertCleanStatus(status);
	return true;
}
Beispiel #6
0
/**
 * 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 AnalogModule::GetAverageValue(UINT32 channel)
{
	INT32 value;
	CheckAnalogChannel(channel);

	tAI::tReadSelect readSelect;
	readSelect.Channel = channel - 1;
	readSelect.Module = SlotToIndex(m_slot);
	readSelect.Averaged = true;

	{
		Synchronized sync(m_registerWindowSemaphore);
		m_module->writeReadSelect(readSelect, &status);
		m_module->strobeLatchOutput(&status);
		value = m_module->readOutput(&status);
	}

	wpi_assertCleanStatus(status);
	return value;
}
/**
 * Free the resource associated with a digital I/O channel.
 */
void DigitalModule::FreeDIO(UINT32 channel)
{
	DIOChannels->Free(kDigitalChannels * SlotToIndex(m_slot) + channel - 1);
}