Пример #1
0
/**
 * Common initialization code for Encoders.
 * This code allocates resources for Encoders and is common to all constructors.
 * @param reverseDirection If true, counts down instead of up (this is all relative)
 * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If 4X is
 * selected, then an encoder FPGA object is used and the returned counts will be 4x the encoder
 * spec'd value since all rising and falling edges are counted. If 1X or 2X are selected then
 * a counter object will be used and the returned value will either exactly match the spec'd count
 * or be double (2x) the spec'd count.
 */
void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType)
{
	m_table = NULL;
	m_encodingType = encodingType;
	tRioStatusCode localStatus = NiFpga_Status_Success;
	switch (encodingType)
	{
		case k4X:
		{
			Resource::CreateResourceObject(&quadEncoders, tEncoder::kNumSystems);
			uint32_t index = quadEncoders->Allocate("4X Encoder");
			if (index == ~0ul)
			{
				CloneError(quadEncoders);
				return;
			}
			if (m_aSource->StatusIsFatal())
			{
				CloneError(m_aSource);
				return;
			}
			if (m_bSource->StatusIsFatal())
			{
				CloneError(m_bSource);
				return;
			}
			m_index = index;
			m_encoder = tEncoder::create(m_index, &localStatus);
			m_encoder->writeConfig_ASource_Module(m_aSource->GetModuleForRouting(), &localStatus);
			m_encoder->writeConfig_ASource_Channel(m_aSource->GetChannelForRouting(), &localStatus);
			m_encoder->writeConfig_ASource_AnalogTrigger(m_aSource->GetAnalogTriggerForRouting(), &localStatus);
			m_encoder->writeConfig_BSource_Module(m_bSource->GetModuleForRouting(), &localStatus);
			m_encoder->writeConfig_BSource_Channel(m_bSource->GetChannelForRouting(), &localStatus);
			m_encoder->writeConfig_BSource_AnalogTrigger(m_bSource->GetAnalogTriggerForRouting(), &localStatus);
			m_encoder->strobeReset(&localStatus);
			m_encoder->writeConfig_Reverse(reverseDirection, &localStatus);
			m_encoder->writeTimerConfig_AverageSize(4, &localStatus);
			m_counter = NULL;
			break;
		}
		case k1X:
		case k2X:
		{
			m_counter = new Counter(m_encodingType, m_aSource, m_bSource, reverseDirection);
			m_index = m_counter->GetIndex();
			break;
		}
	}
	m_distancePerPulse = 1.0;
	m_pidSource = kDistance;
	wpi_setError(localStatus);

	nUsageReporting::report(nUsageReporting::kResourceType_Encoder, m_index, encodingType);
	LiveWindow::GetInstance()->AddSensor("Encoder", m_aSource->GetModuleForRouting(), m_aSource->GetChannelForRouting(), this);
}
Пример #2
0
/**
 * Common initialization code for Encoders.
 * This code allocates resources for Encoders and is common to all constructors.
 *
 * The counter will start counting immediately.
 *
 * @param reverseDirection If true, counts down instead of up (this is all relative)
 * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If 4X is
 * selected, then an encoder FPGA object is used and the returned counts will be 4x the encoder
 * spec'd value since all rising and falling edges are counted. If 1X or 2X are selected then
 * a counter object will be used and the returned value will either exactly match the spec'd count
 * or be double (2x) the spec'd count.
 */
void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType)
{
	m_table = NULL;
	m_encodingType = encodingType;
	m_index = 0;
	switch (encodingType)
	{
		case k4X:
		{
			m_encodingScale = 4;
			if (m_aSource->StatusIsFatal())
			{
				CloneError(m_aSource);
				return;
			}
			if (m_bSource->StatusIsFatal())
			{
				CloneError(m_bSource);
				return;
			}
			int32_t status = 0;
			m_encoder =  initializeEncoder(m_aSource->GetModuleForRouting(), m_aSource->GetChannelForRouting(),
										   m_aSource->GetAnalogTriggerForRouting(),
										   m_bSource->GetModuleForRouting(), m_bSource->GetChannelForRouting(),
										   m_bSource->GetAnalogTriggerForRouting(),
										   reverseDirection, &m_index, &status);
			  wpi_setErrorWithContext(status, getHALErrorMessage(status));
			m_counter = NULL;
			SetMaxPeriod(.5);
			break;
		}
		case k1X:
		case k2X:
		{
			m_encodingScale = encodingType == k1X ? 1 : 2;
			m_counter = new Counter(m_encodingType, m_aSource, m_bSource, reverseDirection);
			m_index = m_counter->GetFPGAIndex();
			break;
		}
		default:
			wpi_setErrorWithContext(-1, "Invalid encodingType argument");
			break;
	}
	m_distancePerPulse = 1.0;
	m_pidSource = kDistance;

	HALReport(HALUsageReporting::kResourceType_Encoder, m_index, encodingType);
	LiveWindow::GetInstance()->AddSensor("Encoder", m_aSource->GetChannelForRouting(), this);
}
Пример #3
0
/**
 * Set the source object that causes the counter to count up.
 * Set the up counting DigitalSource.
 */
void xCounter::SetUpSource(DigitalSource *source)
{
	if (StatusIsFatal()) return;
	if (m_allocatedUpSource)
	{
		delete m_upSource;
		m_upSource = NULL;
		m_allocatedUpSource = false;
	}
	m_upSource = source;
	if (m_upSource->StatusIsFatal())
	{
		CloneError(m_upSource);
	}
	else
	{
		tRioStatusCode localStatus = NiFpga_Status_Success;
		m_counter->writeConfig_UpSource_Module(source->GetModuleForRouting(), &localStatus);
		m_counter->writeConfig_UpSource_Channel(source->GetChannelForRouting(), &localStatus);
		m_counter->writeConfig_UpSource_AnalogTrigger(source->GetAnalogTriggerForRouting(), &localStatus);
	
		if(m_counter->readConfig_Mode(&localStatus) == kTwoPulse ||
				m_counter->readConfig_Mode(&localStatus) == kExternalDirection)
		{
			SetUpSourceEdge(true, false);
		}
		m_counter->strobeReset(&localStatus);
		wpi_setError(localStatus);
	}
}
Пример #4
0
/**
 * Set the source object that causes the counter to count down.
 * Set the down counting DigitalSource.
 */
void xCounter::SetDownSource(DigitalSource *source)
{
	if (StatusIsFatal()) return;
	if (m_allocatedDownSource)
	{
		delete m_downSource;
		m_downSource = NULL;
		m_allocatedDownSource = false;
	}
	m_downSource = source;
	if (m_downSource->StatusIsFatal())
	{
		CloneError(m_downSource);
	}
	else
	{
		tRioStatusCode localStatus = NiFpga_Status_Success;
		unsigned char mode = m_counter->readConfig_Mode(&localStatus);
		if (mode != kTwoPulse && mode != kExternalDirection)
		{
			wpi_setWPIErrorWithContext(ParameterOutOfRange, "Counter only supports DownSource in TwoPulse and ExternalDirection modes.");
			return;
		}
		m_counter->writeConfig_DownSource_Module(source->GetModuleForRouting(), &localStatus);
		m_counter->writeConfig_DownSource_Channel(source->GetChannelForRouting(), &localStatus);
		m_counter->writeConfig_DownSource_AnalogTrigger(source->GetAnalogTriggerForRouting(), &localStatus);
	
		SetDownSourceEdge(true, false);
		m_counter->strobeReset(&localStatus);
		wpi_setError(localStatus);
	}
}
Пример #5
0
/**
 * Constructor.
 *
 * @param moduleNumber The CAN ID of the PCM the solenoid is attached to
 * @param channel The channel on the PCM to control (0..7).
 */
Solenoid::Solenoid(uint8_t moduleNumber, uint32_t channel)
    : SolenoidBase(moduleNumber), m_channel(channel) {
  std::stringstream buf;
  if (!CheckSolenoidModule(m_moduleNumber)) {
    buf << "Solenoid Module " << m_moduleNumber;
    wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf.str());
    return;
  }
  if (!CheckSolenoidChannel(m_channel)) {
    buf << "Solenoid Module " << m_channel;
    wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str());
    return;
  }
  Resource::CreateResourceObject(m_allocated, m_maxModules * m_maxPorts);
  buf << "Solenoid " << m_channel << " (Module: " << m_moduleNumber << ")";
  if (m_allocated->Allocate(m_moduleNumber * kSolenoidChannels + m_channel,
                            buf.str()) ==
      std::numeric_limits<uint32_t>::max()) {
    CloneError(*m_allocated);
    return;
  }

#if FULL_WPILIB
  LiveWindow::GetInstance()->AddActuator("Solenoid", m_moduleNumber, m_channel,
                                         this);
#endif
  HALReport(HALUsageReporting::kResourceType_Solenoid, m_channel,
            m_moduleNumber);
}
Пример #6
0
/**
 * Construct an analog input.
 *
 * @param channel The channel number on the roboRIO to represent. 0-3 are
 * on-board 4-7 are on the MXP port.
 */
AnalogInput::AnalogInput(uint32_t channel) {
    std::stringstream buf;
    buf << "Analog Input " << channel;
    Resource::CreateResourceObject(inputs, kAnalogInputs);

    if (!checkAnalogInputChannel(channel)) {
        wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str());
        return;
    }

    if (inputs->Allocate(channel, buf.str()) ==
            std::numeric_limits<uint32_t>::max()) {
        CloneError(*inputs);
        return;
    }

    m_channel = channel;

    void *port = getPort(channel);
    int32_t status = 0;
    m_port = initializeAnalogInputPort(port, &status);
    wpi_setErrorWithContext(status, getHALErrorMessage(status));

    LiveWindow::GetInstance()->AddSensor("AnalogInput", channel, this);
    HALReport(HALUsageReporting::kResourceType_AnalogChannel, channel);
}
Пример #7
0
/**
 * Common function to implement constructor behavior.
 */
void Solenoid::InitSolenoid()
{
	m_table = NULL;
	char buf[64];
	if (!CheckSolenoidModule(m_moduleNumber))
	{
		snprintf(buf, 64, "Solenoid Module %d", m_moduleNumber);
		wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf);
		return;
	}
	if (!CheckSolenoidChannel(m_channel))
	{
		snprintf(buf, 64, "Solenoid Channel %d", m_channel);
		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
		return;
	}
	Resource::CreateResourceObject(&m_allocated, tSolenoid::kNumDO7_0Elements * kSolenoidChannels);

	snprintf(buf, 64, "Solenoid %d (Module: %d)", m_channel, m_moduleNumber);
	if (m_allocated->Allocate((m_moduleNumber - 1) * kSolenoidChannels + m_channel - 1, buf) == ~0ul)
	{
		CloneError(m_allocated);
		return;
	}

	LiveWindow::GetInstance()->AddActuator("Solenoid", m_moduleNumber, m_channel, this);
	nUsageReporting::report(nUsageReporting::kResourceType_Solenoid, m_channel, m_moduleNumber - 1);
}
Пример #8
0
/**
 * Initialize PWMs given an module and channel.
 * 
 * This method is private and is the common path for all the constructors for creating PWM
 * instances. Checks module and channel value ranges and allocates the appropriate channel.
 * The allocation is only done to help users ensure that they don't double assign channels.
 */
void PWM::InitPWM(UINT8 moduleNumber, UINT32 channel)
{
	char buf[64];
	Resource::CreateResourceObject(&allocated, tDIO::kNumSystems * kPwmChannels);
	if (!CheckPWMModule(moduleNumber))
	{
		snprintf(buf, 64, "Digital Module %d", moduleNumber);
		wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf);
		return;
	}
	if (!CheckPWMChannel(channel))
	{
		snprintf(buf, 64, "PWM Channel %d", channel);
		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
		return;
	}

	snprintf(buf, 64, "PWM %d (Module: %d)", channel, moduleNumber);
	if (allocated->Allocate((moduleNumber - 1) * kPwmChannels + channel - 1, buf) == ~0ul)
	{
		CloneError(allocated);
		return;
	}
	m_channel = channel;
	m_module = DigitalModule::GetInstance(moduleNumber);
	m_module->SetPWM(m_channel, kPwmDisabled);
	m_eliminateDeadband = false;

	nUsageReporting::report(nUsageReporting::kResourceType_PWM, channel, moduleNumber - 1);
}
Пример #9
0
/**
 * Common initialization code for Encoders.
 * This code allocates resources for Encoders and is common to all constructors.
 * @param reverseDirection If true, counts down instead of up (this is all relative)
 * @param encodingType either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If 4X is
 * selected, then an encoder FPGA object is used and the returned counts will be 4x the encoder
 * spec'd value since all rising and falling edges are counted. If 1X or 2X are selected then
 * a counter object will be used and the returned value will either exactly match the spec'd count
 * or be double (2x) the spec'd count.
 */
void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType)
{
    m_encodingType = encodingType;
    tRioStatusCode localStatus = NiFpga_Status_Success;
    UINT32 index; // declared out here because gcc doesn't like it declared in there
    switch (encodingType)
    {
    case k4X:
        Resource::CreateResourceObject(&quadEncoders, tEncoder::kNumSystems);
        index = quadEncoders->Allocate("4X Encoder");
        if (index == ~0ul)
        {
            CloneError(quadEncoders);
            return;
        }
        if (m_aSource->StatusIsFatal())
        {
            CloneError(m_aSource);
            return;
        }
        if (m_bSource->StatusIsFatal())
        {
            CloneError(m_bSource);
            return;
        }
        m_index = index;
        m_encoder = tEncoder::create(m_index, &localStatus);
        m_encoder->writeConfig_ASource_Module(m_aSource->GetModuleForRouting(), &localStatus);
        m_encoder->writeConfig_ASource_Channel(m_aSource->GetChannelForRouting(), &localStatus);
        m_encoder->writeConfig_ASource_AnalogTrigger(m_aSource->GetAnalogTriggerForRouting(), &localStatus);
        m_encoder->writeConfig_BSource_Module(m_bSource->GetModuleForRouting(), &localStatus);
        m_encoder->writeConfig_BSource_Channel(m_bSource->GetChannelForRouting(), &localStatus);
        m_encoder->writeConfig_BSource_AnalogTrigger(m_bSource->GetAnalogTriggerForRouting(), &localStatus);
        m_encoder->strobeReset(&localStatus);
        m_encoder->writeConfig_Reverse(reverseDirection, &localStatus);
        m_encoder->writeTimerConfig_AverageSize(4, &localStatus);
        m_counter = NULL;
        break;
    case k1X:
    case k2X:
        m_counter = new Counter(m_encodingType, m_aSource, m_bSource, reverseDirection);
        break;
    }
    m_distancePerPulse = 1.0;
    m_pidSource = kDistance;
    wpi_setError(localStatus);
}
Пример #10
0
/**
 * Common function to implement constructor behavior.
 */
void DoubleSolenoid::InitSolenoid()
{
    char buf[64];
    if (!CheckSolenoidModule(m_moduleNumber))
    {
	snprintf(buf, 64, "Solenoid Module %lu", m_moduleNumber);
	wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf);
	return;
    }
    if (!CheckSolenoidChannel(m_forwardChannel))
    {
	snprintf(buf, 64, "Solenoid Channel %lu", m_forwardChannel);
	wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
	return;
    }
    if (!CheckSolenoidChannel(m_reverseChannel))
    {
	snprintf(buf, 64, "Solenoid Channel %lu", m_reverseChannel);
	wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
	return;
    }
    Resource::CreateResourceObject(&m_allocated, tSolenoid::kNumDO7_0Elements * kSolenoidChannels);

    snprintf(buf, 64, "Solenoid %lu (Module %lu)", m_forwardChannel, m_moduleNumber);
    if (m_allocated->Allocate((m_moduleNumber - 1) * kSolenoidChannels + m_forwardChannel - 1, buf) == ~0ul)
    {
	CloneError(m_allocated);
	return;
    }
    snprintf(buf, 64, "Solenoid %lu (Module %lu)", m_reverseChannel, m_moduleNumber);
    if (m_allocated->Allocate((m_moduleNumber - 1) * kSolenoidChannels + m_reverseChannel - 1, buf) == ~0ul)
    {
	CloneError(m_allocated);
	return;
    }
    m_forwardMask = 1 << (m_forwardChannel - 1);
    m_reverseMask = 1 << (m_reverseChannel - 1);

    nUsageReporting::report(nUsageReporting::kResourceType_Solenoid, m_forwardChannel, m_moduleNumber - 1);
    nUsageReporting::report(nUsageReporting::kResourceType_Solenoid, m_reverseChannel, m_moduleNumber - 1);

    LiveWindow::GetInstance()->AddActuator("Double Solenoid", m_moduleNumber, m_forwardChannel, this);
}
Пример #11
0
/**
 * Relay constructor given a channel.
 *
 * This code initializes the relay and reserves all resources that need to be
 * locked. Initially the relay is set to both lines at 0v.
 * @param channel The channel number (0-3).
 * @param direction The direction that the Relay object will control.
 */
Relay::Relay(uint32_t channel, Relay::Direction direction)
    : m_channel(channel), m_direction(direction) {
  std::stringstream buf;
  Resource::CreateResourceObject(relayChannels,
                                 dio_kNumSystems * kRelayChannels * 2);
  if (!SensorBase::CheckRelayChannel(m_channel)) {
    buf << "Relay Channel " << m_channel;
    wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str());
    return;
  }

  if (m_direction == kBothDirections || m_direction == kForwardOnly) {
    buf << "Forward Relay " << m_channel;
    if (relayChannels->Allocate(m_channel * 2, buf.str()) == ~0ul) {
      CloneError(*relayChannels);
      return;
    }

    HALReport(HALUsageReporting::kResourceType_Relay, m_channel);
  }
  if (m_direction == kBothDirections || m_direction == kReverseOnly) {
    buf << "Reverse Relay " << m_channel;
    if (relayChannels->Allocate(m_channel * 2 + 1, buf.str()) == ~0ul) {
      CloneError(*relayChannels);
      return;
    }

    HALReport(HALUsageReporting::kResourceType_Relay, m_channel + 128);
  }

  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);
}
Пример #12
0
/**
 * @brief Constructor.
 */
PCVideoServer::PCVideoServer()
	: m_serverTask("PCVideoServer", (FUNCPTR)s_ServerTask)
	, m_newImageSem (NULL)
	, m_stopServer (false)
{
	AxisCamera &cam = AxisCamera::GetInstance();
	m_newImageSem = cam.GetNewImageSem();
	if (!cam.StatusIsFatal())
	{
		StartServerTask();
	}
	else
	{
		CloneError(&cam);
	}
}
Пример #13
0
/**
* Request one of the 8 interrupts synchronously on this digital input.
* Request interrupts in synchronous mode where the user program will have to
* explicitly
* wait for the interrupt to occur using WaitForInterrupt.
* The default is interrupt on rising edges only.
*/
void InterruptableSensorBase::RequestInterrupts() {
  if (StatusIsFatal()) return;
  uint32_t index = m_interrupts->Allocate("Sync Interrupt");
  if (index == std::numeric_limits<uint32_t>::max()) {
    CloneError(*m_interrupts);
    return;
  }
  m_interruptIndex = index;

  AllocateInterrupts(true);

  int32_t status = 0;
  requestInterrupts(m_interrupt, GetModuleForRouting(), GetChannelForRouting(),
                    GetAnalogTriggerForRouting(), &status);
  wpi_setErrorWithContext(status, getHALErrorMessage(status));
  SetUpSourceEdge(true, false);
}
Пример #14
0
/**
 * Initialize an analog trigger from a slot and channel.
 * This is the common code for the two constructors that use a slot and channel.
 */
void AnalogTrigger::InitTrigger(UINT8 moduleNumber, UINT32 channel)
{
	Resource::CreateResourceObject(&triggers, tAnalogTrigger::kNumSystems);
	UINT32 index = triggers->Allocate("Analog Trigger");
	if (index == ~0ul)
	{
		CloneError(triggers);
		return;
	}
	m_index = (UINT8)index;
	m_channel = channel;
	m_analogModule = AnalogModule::GetInstance(moduleNumber);

	tRioStatusCode localStatus = NiFpga_Status_Success;
	m_trigger = tAnalogTrigger::create(m_index, &localStatus);
	m_trigger->writeSourceSelect_Channel(m_channel - 1, &localStatus);
	m_trigger->writeSourceSelect_Module(moduleNumber - 1, &localStatus);
	wpi_setError(localStatus);
}
Пример #15
0
/**
 * Create an instance of a counter object.
 * This creates a ChipObject counter and initializes status variables appropriately
 */
void Counter::InitCounter(Mode mode)
{
	Resource::CreateResourceObject(&counters, tCounter::kNumSystems);
	UINT32 index = counters->Allocate("Counter");
	if (index == ~0ul)
	{
		CloneError(counters);
		return;
	}
	m_index = index;
	tRioStatusCode localStatus = NiFpga_Status_Success;
	m_counter = tCounter::create(m_index, &localStatus);
	m_counter->writeConfig_Mode(mode, &localStatus);
	m_upSource = NULL;
	m_downSource = NULL;
	m_allocatedUpSource = false;
	m_allocatedDownSource = false;
	m_counter->writeTimerConfig_AverageSize(1, &localStatus);
	wpi_setError(localStatus);
}
Пример #16
0
/**
* Request one of the 8 interrupts asynchronously on this digital input.
* Request interrupts in asynchronous mode where the user's interrupt handler
* will be
* called when the interrupt fires. Users that want control over the thread
* priority
* should use the synchronous method with their own spawned thread.
* The default is interrupt on rising edges only.
*/
void InterruptableSensorBase::RequestInterrupts(
    InterruptHandlerFunction handler, void *param) {
  if (StatusIsFatal()) return;
  uint32_t index = m_interrupts->Allocate("Async Interrupt");
  if (index == std::numeric_limits<uint32_t>::max()) {
    CloneError(*m_interrupts);
    return;
  }
  m_interruptIndex = index;

  // Creates a manager too
  AllocateInterrupts(false);

  int32_t status = 0;
  requestInterrupts(m_interrupt, GetModuleForRouting(), GetChannelForRouting(),
                    GetAnalogTriggerForRouting(), &status);
  SetUpSourceEdge(true, false);
  attachInterruptHandler(m_interrupt, handler, param, &status);
  wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
Пример #17
0
/**
 * 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 DigitalInput::RequestInterrupts()
{
	if (StatusIsFatal()) return;
	uint32_t index = interruptsResource->Allocate("Sync Interrupt");
	if (index == ~0ul)
	{
		CloneError(interruptsResource);
		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);
}
Пример #18
0
/**
 * Common initialization.
 */
void AnalogChannel::InitChannel(UINT8 moduleNumber, UINT32 channel)
{
	char buf[64];
	Resource::CreateResourceObject(&channels, kAnalogModules * kAnalogChannels);
	if (!CheckAnalogModule(moduleNumber))
	{
		snprintf(buf, 64, "Analog Module %d", moduleNumber);
		wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf);
		return;
	}
	if (!CheckAnalogChannel(channel))
	{
		snprintf(buf, 64, "Analog Channel %d", channel);
		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf);
		return;
	}

	snprintf(buf, 64, "Analog Input %d (Module: %d)", channel, moduleNumber);
	if (channels->Allocate((moduleNumber - 1) * kAnalogChannels + channel - 1, buf) == ~0ul)
	{
		CloneError(channels);
		return;
	}
	m_channel = channel;
	m_module = AnalogModule::GetInstance(moduleNumber);
	if (IsAccumulatorChannel())
	{
		tRioStatusCode localStatus = NiFpga_Status_Success;
		m_accumulator = tAccumulator::create(channel - 1, &localStatus);
		wpi_setError(localStatus);
		m_accumulatorOffset=0;
	}
	else
	{
		m_accumulator = NULL;
	}
	LiveWindow::GetInstance()->AddActuator("AnalogChannel",channel, GetModuleNumber(), this);
	nUsageReporting::report(nUsageReporting::kResourceType_AnalogChannel, channel, GetModuleNumber() - 1);
}
Пример #19
0
/**
 * 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 DigitalInput::RequestInterrupts(tInterruptHandler handler, void *param)
{
	if (StatusIsFatal()) return;
	uint32_t index = interruptsResource->Allocate("Async Interrupt");
	if (index == ~0ul)
	{
		CloneError(interruptsResource);
		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);
}