blob: 862b4392805869f6d9fd601f512c3b67a89945f4 [file] [log] [blame]
/*----------------------------------------------------------------------------*/
/* 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 "DigitalSource.h"
#include "Resource.h"
#include "WPIErrors.h"
Resource *interruptsResource = NULL;
DigitalSource::DigitalSource()
{
Resource::CreateResourceObject(&interruptsResource, tInterrupt::kNumSystems);
}
/**
* DigitalSource destructor.
*/
DigitalSource::~DigitalSource()
{
if (m_manager != NULL)
{
delete m_manager;
delete m_interrupt;
interruptsResource->Free(m_interruptIndex, this);
}
}
/**
* Request interrupts asynchronously on this digital input.
* @param handler The address of the interrupt handler function of type tInterruptHandler that
* will be called whenever there is an interrupt on the digitial input port.
* Request interrupts in synchronus mode where the user program interrupt handler will be
* called when an interrupt occurs.
* The default is interrupt on rising edges only.
*/
void DigitalSource::RequestInterrupts(tInterruptHandler handler, void *param)
{
if (StatusIsFatal()) return;
UINT32 index = interruptsResource->Allocate("Async Interrupt", this);
if (index == ~0ul)
{
return;
}
m_interruptIndex = index;
// Creates a manager too
AllocateInterrupts(false);
tRioStatusCode localStatus = NiFpga_Status_Success;
m_interrupt->writeConfig_WaitForAck(false, &localStatus);
m_interrupt->writeConfig_Source_AnalogTrigger(GetAnalogTriggerForRouting(), &localStatus);
m_interrupt->writeConfig_Source_Channel(GetChannelForRouting(), &localStatus);
m_interrupt->writeConfig_Source_Module(GetModuleForRouting(), &localStatus);
SetUpSourceEdge(true, false);
m_manager->registerHandler(handler, param, &localStatus);
wpi_setError(localStatus);
}
/**
* Request interrupts synchronously on this digital input.
* Request interrupts in synchronus mode where the user program will have to explicitly
* wait for the interrupt to occur.
* The default is interrupt on rising edges only.
*/
void DigitalSource::RequestInterrupts()
{
if (StatusIsFatal()) return;
UINT32 index = interruptsResource->Allocate("Sync Interrupt", this);
if (index == ~0ul)
{
return;
}
m_interruptIndex = index;
AllocateInterrupts(true);
tRioStatusCode localStatus = NiFpga_Status_Success;
m_interrupt->writeConfig_Source_AnalogTrigger(GetAnalogTriggerForRouting(), &localStatus);
m_interrupt->writeConfig_Source_Channel(GetChannelForRouting(), &localStatus);
m_interrupt->writeConfig_Source_Module(GetModuleForRouting(), &localStatus);
SetUpSourceEdge(true, false);
wpi_setError(localStatus);
}
void DigitalSource::SetUpSourceEdge(bool risingEdge, bool fallingEdge)
{
if (StatusIsFatal()) return;
if (m_interrupt == NULL)
{
wpi_setWPIErrorWithContext(NullParameter, "You must call RequestInterrupts before SetUpSourceEdge");
return;
}
tRioStatusCode localStatus = NiFpga_Status_Success;
if (m_interrupt != NULL)
{
m_interrupt->writeConfig_RisingEdge(risingEdge, &localStatus);
m_interrupt->writeConfig_FallingEdge(fallingEdge, &localStatus);
}
wpi_setError(localStatus);
}