/** * 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 AnalogModule::GetValue(UINT32 channel) { INT16 value; CheckAnalogChannel(channel); tAI::tReadSelect readSelect; readSelect.Channel = channel - 1; readSelect.Module = m_moduleNumber - 1; readSelect.Averaged = false; tRioStatusCode localStatus = NiFpga_Status_Success; { Synchronized sync(m_registerWindowSemaphore); m_module->writeReadSelect(readSelect, &localStatus); m_module->strobeLatchOutput(&localStatus); value = (INT16) m_module->readOutput(&localStatus); } wpi_setError(localStatus); return value; }
/** * 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) { if (pwmGenerator == ~0ul) return; tRioStatusCode localStatus = NiFpga_Status_Success; switch(pwmGenerator) { case 0: m_fpgaDIO->writeDO_PWMConfig_OutputSelect_0(RemapDigitalChannel(channel - 1), &localStatus); break; case 1: m_fpgaDIO->writeDO_PWMConfig_OutputSelect_1(RemapDigitalChannel(channel - 1), &localStatus); break; case 2: m_fpgaDIO->writeDO_PWMConfig_OutputSelect_2(RemapDigitalChannel(channel - 1), &localStatus); break; case 3: m_fpgaDIO->writeDO_PWMConfig_OutputSelect_3(RemapDigitalChannel(channel - 1), &localStatus); break; } wpi_setError(localStatus); }
/** * Create an instance of a counter object. * This creates a ChipObject counter and initializes status variables appropriately */ void xCounter::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); nUsageReporting::report(nUsageReporting::kResourceType_Counter, index, mode); }
/** * 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); }
/** * 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) { if (value != 0 && value != 1) { wpi_setWPIError(NonBinaryDigitalValue); if (value != 0) value = 1; } tRioStatusCode localStatus = NiFpga_Status_Success; { Synchronized sync(m_digitalSemaphore); uint16_t currentDIO = m_fpgaDIO->readDO(&localStatus); if(value == 0) { currentDIO = currentDIO & ~(1 << RemapDigitalChannel(channel - 1)); } else if (value == 1) { currentDIO = currentDIO | (1 << RemapDigitalChannel(channel - 1)); } m_fpgaDIO->writeDO(currentDIO, &localStatus); } wpi_setError(localStatus); }
/** * 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) { char buf[64]; sprintf(buf, "DIO %u (Module %d)", channel, m_moduleNumber); if (DIOChannels->Allocate(kDigitalChannels * (m_moduleNumber - 1) + channel - 1, buf) == ~0ul) return false; tRioStatusCode localStatus = NiFpga_Status_Success; { Synchronized sync(m_digitalSemaphore); uint32_t bitToSet = 1 << (RemapDigitalChannel(channel - 1)); uint32_t outputEnable = m_fpgaDIO->readOutputEnable(&localStatus); uint32_t outputEnableValue; if (input) { outputEnableValue = outputEnable & (~bitToSet); // clear the bit for read } else { outputEnableValue = outputEnable | bitToSet; // set the bit for write } m_fpgaDIO->writeOutputEnable(outputEnableValue, &localStatus); } wpi_setError(localStatus); return true; }
/** * 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); }
/** * Create an instance of a Serial Port class. * * @param baudRate The baud rate to configure the serial port. The cRIO-9074 supports up to 230400 Baud. * @param dataBits The number of data bits per transfer. Valid values are between 5 and 8 bits. * @param parity Select the type of parity checking to use. * @param stopBits The number of stop bits to use as defined by the enum StopBits. */ SerialPort::SerialPort(uint32_t baudRate, uint8_t dataBits, SerialPort::Parity parity, SerialPort::StopBits stopBits) : m_resourceManagerHandle (0) , m_portHandle (0) , m_consoleModeEnabled (false) { ViStatus localStatus = VI_SUCCESS; localStatus = viOpenDefaultRM((ViSession*)&m_resourceManagerHandle); wpi_setError(localStatus); localStatus = viOpen(m_resourceManagerHandle, const_cast<char*>("ASRL1::INSTR"), VI_NULL, VI_NULL, (ViSession*)&m_portHandle); wpi_setError(localStatus); if (localStatus != 0) { m_consoleModeEnabled = true; return; } localStatus = viSetAttribute(m_portHandle, VI_ATTR_ASRL_BAUD, baudRate); wpi_setError(localStatus); localStatus = viSetAttribute(m_portHandle, VI_ATTR_ASRL_DATA_BITS, dataBits); wpi_setError(localStatus); localStatus = viSetAttribute(m_portHandle, VI_ATTR_ASRL_PARITY, parity); wpi_setError(localStatus); localStatus = viSetAttribute(m_portHandle, VI_ATTR_ASRL_STOP_BITS, stopBits); wpi_setError(localStatus); // Set the default timeout to 5 seconds. SetTimeout(5.0f); // Don't wait until the buffer is full to transmit. SetWriteBufferMode(kFlushOnAccess); EnableTermination(); //viInstallHandler(m_portHandle, VI_EVENT_IO_COMPLETION, ioCompleteHandler, this); //viEnableEvent(m_portHandle, VI_EVENT_IO_COMPLETION, VI_HNDLR, VI_NULL); nUsageReporting::report(nUsageReporting::kResourceType_SerialPort, 0); }
/** * 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 channel, UINT32 bits) { tRioStatusCode localStatus = NiFpga_Status_Success; m_module->writeOversampleBits(channel - 1, bits, &localStatus); wpi_setError(localStatus); }
/** * Configure how many seconds your watchdog can be neglected before it starves to death. * * @param expiration The number of seconds before starvation following a meal (watchdog starves if it doesn't eat this often). */ void Watchdog::SetExpiration(double expiration) { tRioStatusCode localStatus = NiFpga_Status_Success; m_fpgaWatchDog->writeExpiration((UINT32)(expiration * (kSystemClockTicksPerMicrosecond * 1e6)), &localStatus); wpi_setError(localStatus); }
/** * Put the watchdog out of its misery. * * Don't wait for your dying robot to starve when there is a problem. * Kill it quickly, cleanly, and humanely. */ void Watchdog::Kill() { tRioStatusCode localStatus = NiFpga_Status_Success; m_fpgaWatchDog->strobeKill(&localStatus); wpi_setError(localStatus); }
/** * Enable or disable the watchdog timer. * * When enabled, you must keep feeding the watchdog timer to * keep the watchdog active, and hence the dangerous parts * (motor outputs, etc.) can keep functioning. * When disabled, the watchdog is immortal and will remain active * even without being fed. It will also ignore any kill commands * while disabled. * * @param enabled Enable or disable the watchdog. */ void Watchdog::SetEnabled(bool enabled) { tRioStatusCode localStatus = NiFpga_Status_Success; m_fpgaWatchDog->writeImmortal(!enabled, &localStatus); wpi_setError(localStatus); }
/** * Get the Samples to Average which specifies the number of samples of the timer to * average when calculating the period. Perform averaging to account for * mechanical imperfections or as oversampling to increase resolution. * @return SamplesToAverage The number of samples being averaged (from 1 to 127) */ int Counter::GetSamplesToAverage() { tRioStatusCode localStatus = NiFpga_Status_Success; return m_counter->readTimerConfig_AverageSize(&localStatus); wpi_setError(localStatus); }
/** * 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) { tRioStatusCode localStatus = NiFpga_Status_Success; m_module->writeAverageBits(channel - 1, bits, &localStatus); wpi_setError(localStatus); }
/** * Empty the receive FIFO. */ void SPI::ClearReceivedData() { tRioStatusCode localStatus = NiFpga_Status_Success; m_spi->strobeClearReceivedData(&localStatus); wpi_setError(localStatus); }
/** * Stop any transfer in progress and empty the transmit FIFO. */ void SPI::Reset() { tRioStatusCode localStatus = NiFpga_Status_Success; m_spi->strobeReset(&localStatus); wpi_setError(localStatus); }