/** * Execute a read transaction with the device. * * <p>Read bytes from a device. Most I2C devices will auto-increment the register pointer * internally allowing you to read 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. * @param buffer A buffer to store the data read from the device. Must be created using * ByteBuffer.allocateDirect(). * @return Transfer Aborted... false for success, true for aborted. */ public boolean read(int registerAddress, int count, ByteBuffer buffer) { if (count < 1) { throw new BoundaryException("Value must be at least 1, " + count + " given"); } if (!buffer.isDirect()) { throw new IllegalArgumentException("must be a direct buffer"); } if (buffer.capacity() < count) { throw new IllegalArgumentException("buffer is too small, must be at least " + count); } ByteBuffer dataToSendBuffer = ByteBuffer.allocateDirect(1); dataToSendBuffer.put(0, (byte) registerAddress); return transaction(dataToSendBuffer, 1, buffer, count); }
/** * Execute a read only transaction with the device. * * <p>Read bytes from a device. This method does not write any data to prompt the device. * * @param buffer A pointer to the array of bytes to store the data read from the device. * @param count The number of bytes to read in the transaction. * @return Transfer Aborted... false for success, true for aborted. */ public boolean readOnly(byte[] buffer, int count) { if (count < 1) { throw new BoundaryException("Value must be at least 1, " + count + " given"); } if (buffer == null) { throw new NullPointerException("Null return buffer was given"); } ByteBuffer dataReceivedBuffer = ByteBuffer.allocateDirect(count); int retVal = I2CJNI.i2CRead((byte) m_port.value, (byte) m_deviceAddress, dataReceivedBuffer, (byte) count); dataReceivedBuffer.get(buffer); return retVal < count; }
/** * Execute a read only transaction with the device. * * <p>Read bytes from a device. This method does not write any data to prompt the device. * * @param buffer A pointer to the array of bytes to store the data read from the device. Must be * created using ByteBuffer.allocateDirect(). * @param count The number of bytes to read in the transaction. * @return Transfer Aborted... false for success, true for aborted. */ public boolean readOnly(ByteBuffer buffer, int count) { if (count < 1) { throw new BoundaryException("Value must be at least 1, " + count + " given"); } if (!buffer.isDirect()) { throw new IllegalArgumentException("must be a direct buffer"); } if (buffer.capacity() < count) { throw new IllegalArgumentException("buffer is too small, must be at least " + count); } return I2CJNI.i2CRead((byte) m_port.value, (byte) m_deviceAddress, buffer, (byte) count) < count; }
/** * Execute a read transaction with the device. * * Read bytes from a device. Most I2C devices will auto-increment the * register pointer internally allowing you to read 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. * @param buffer A buffer to store the data read from the device. Must be * created using ByteBuffer.allocateDirect(). * @return Transfer Aborted... false for success, true for aborted. */ public boolean read(int registerAddress, int count, ByteBuffer buffer) { if (count < 1) { throw new BoundaryException("Value must be at least 1, " + count + " given"); } if (!buffer.isDirect()) throw new IllegalArgumentException("must be a direct buffer"); if (buffer.capacity() < count) throw new IllegalArgumentException("buffer is too small, must be at least " + count); ByteBuffer dataToSendBuffer = ByteBuffer.allocateDirect(1); dataToSendBuffer.put(0, (byte) registerAddress); return transaction(dataToSendBuffer, 1, buffer, count); }
/** * Execute a read only transaction with the device. * * Read bytes from a device. This method does not write any data to prompt * the device. * * @param buffer A pointer to the array of bytes to store the data read from * the device. * @param count The number of bytes to read in the transaction. * @return Transfer Aborted... false for success, true for aborted. */ public boolean readOnly(byte[] buffer, int count) { if (count < 1) { throw new BoundaryException("Value must be at least 1, " + count + " given"); } if (buffer == null) { throw new NullPointerException("Null return buffer was given"); } ByteBuffer dataReceivedBuffer = ByteBuffer.allocateDirect(count); int retVal = I2CJNI.i2CRead((byte) m_port.getValue(), (byte) m_deviceAddress, dataReceivedBuffer, (byte) count); dataReceivedBuffer.get(buffer); return retVal < 0; }
/** * Set the analog output voltage. * * AO1 is pin 11 on the top connector (P2). * AO2 is pin 12 on the top connector (P2). * AO1 is the reference voltage for the 2 analog comparators on DIO15 and DIO16. * * The output range is 0V to 4V, however due to the supply voltage don't expect more than about 3V. * Current supply capability is only 100uA. * * @param channel The analog output channel on the DS IO. [1,2] * @param value The voltage to output on the channel. */ public void setAnalogOut(int channel, double value) throws EnhancedIOException { BoundaryException.assertWithinBounds(channel, 1, 2); if (!m_outputValid) { throw new EnhancedIOException("Enhanced IO Missing"); } if (value < 0.0) { value = 0.0; } if (value > kAnalogOutputReference) { value = kAnalogOutputReference; } if (value > kAnalogOutputReference) { value = kAnalogOutputReference; } synchronized (m_outputDataSemaphore) { m_outputData.data.dac[channel - 1] = (byte) (value / kAnalogOutputReference * kAnalogOutputResolution); } }
/** * Set the state of an LED on the IO board. * * @param channel The LED channel to set. [1,8] * @param value True to turn the LED on. */ public void setLED(int channel, boolean value) throws EnhancedIOException { BoundaryException.assertWithinBounds(channel, 1, 8); if (!m_outputValid) { throw new EnhancedIOException("Enhanced IO Missing"); } byte leds; synchronized (m_outputDataSemaphore) { leds = m_outputData.data.leds; leds &= ~(1 << (channel - 1)); if (value) { leds |= 1 << (channel - 1); } m_outputData.data.leds = leds; } }
/** * Set the state of a DIO line that is configured for digital output. * * @param channel The DIO channel to set. [1,16] * @param value The state to set the selected channel to. */ public void setDigitalOutput(int channel, boolean value) throws EnhancedIOException { BoundaryException.assertWithinBounds(channel, 1, 16); if (!m_outputValid) { throw new EnhancedIOException("Enhanced IO Missing"); } short digital; synchronized (m_outputDataSemaphore) { if ((m_outputData.data.digital_oe & (1 << (channel - 1))) != 0) { digital = m_outputData.data.digital; digital &= ~(1 << (channel - 1)); if (value) { digital |= 1 << (channel - 1); } m_outputData.data.digital = digital; } else { System.err.println("Line not configured for output"); } } }
/** * Set the state to output on a Fixed High Current Digital Output line. * * FixedDO1 is pin 5 on the top connector (P2). * FixedDO2 is pin 3 on the top connector (P2). * * The FixedDO lines always output 0V and 3.3V regardless of J1 and J4. * They can source 4mA and can sink 25mA. Because of this, they are expected to be used * in an active low configuration, such as connecting to the cathode of a bright LED. * Because they are expected to be active low, they default to true. * * @param channel The FixedDO channel to set. * @param value The state to set the FixedDO. */ public void setFixedDigitalOutput(int channel, boolean value) throws EnhancedIOException { BoundaryException.assertWithinBounds(channel, 1, 2); if (!m_outputValid) { throw new EnhancedIOException("Enhanced IO Missing"); } byte digital; synchronized (m_outputDataSemaphore) { digital = m_outputData.data.fixed_digital_out; digital &= ~(1 << (channel - 1)); if (value) { digital |= 1 << (channel - 1); } m_outputData.data.fixed_digital_out = digital; } }
/** * Sets the maximum and minimum values expected from the input. * * @param minimumInput the minimum value expected from the input * @param maximumInput the maximum value expected from the output */ public void setInputRange(double minimumInput, double maximumInput) { if (minimumInput > maximumInput) { throw new BoundaryException("Lower bound is greater than upper bound"); } m_minimumInput = minimumInput; m_maximumInput = maximumInput; setSetpoint(m_setpoint); }
/** * Sets the minimum and maximum values to write. * * @param minimumOutput the minimum value to write to the output * @param maximumOutput the maximum value to write to the output */ public void setOutputRange(double minimumOutput, double maximumOutput) { if (minimumOutput > maximumOutput) { throw new BoundaryException("Lower bound is greater than upper bound"); } m_minimumOutput = minimumOutput; m_maximumOutput = maximumOutput; }
/** * Sets the maximum and minimum values expected from the input and setpoint. * * @param minimumInput the minimum value expected from the input * @param maximumInput the maximum value expected from the input */ public synchronized void setInputRange(double minimumInput, double maximumInput) { if (minimumInput > maximumInput) { throw new BoundaryException("Lower bound is greater than upper bound"); } m_minimumInput = minimumInput; m_maximumInput = maximumInput; setSetpoint(m_setpoint); }
/** * Sets the minimum and maximum values to write. * * @param minimumOutput the minimum percentage to write to the output * @param maximumOutput the maximum percentage to write to the output */ public synchronized void setOutputRange(double minimumOutput, double maximumOutput) { if (minimumOutput > maximumOutput) { throw new BoundaryException("Lower bound is greater than upper bound"); } m_minimumOutput = minimumOutput; m_maximumOutput = maximumOutput; }
/** * Set which parameter of the encoder you are using as a process control variable. The counter * class supports the rate and distance parameters. * * @param pidSource An enum to select the parameter. */ public void setPIDSourceType(PIDSourceType pidSource) { if (pidSource == null) { throw new NullPointerException("PID Source Parameter given was null"); } BoundaryException.assertWithinBounds(pidSource.value, 0, 1); m_pidSource = pidSource; }
/** * Execute a read transaction with the device. * * <p>Read bytes from a device. Most I2C devices will auto-increment the register pointer * internally allowing you to read 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. * @param buffer A pointer to the array of bytes to store the data read from the device. * @return Transfer Aborted... false for success, true for aborted. */ public boolean read(int registerAddress, int count, byte[] buffer) { if (count < 1) { throw new BoundaryException("Value must be at least 1, " + count + " given"); } if (buffer == null) { throw new NullPointerException("Null return buffer was given"); } byte[] registerAddressArray = new byte[1]; registerAddressArray[0] = (byte) registerAddress; return transaction(registerAddressArray, registerAddressArray.length, buffer, count); }
/** * Set which parameter of the encoder you are using as a process control * variable. The counter class supports the rate and distance parameters. * * @param pidSource An enum to select the parameter. */ public void setPIDSourceType(PIDSourceType pidSource) { if (pidSource == null) { throw new NullPointerException("PID Source Parameter given was null"); } BoundaryException.assertWithinBounds(pidSource.value, 0, 1); m_pidSource = pidSource; }
/** * Execute a read transaction with the device. * * Read bytes from a device. Most I2C devices will auto-increment the * register pointer internally allowing you to read 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. * @param buffer A pointer to the array of bytes to store the data read from * the device. * @return Transfer Aborted... false for success, true for aborted. */ public boolean read(int registerAddress, int count, byte[] buffer) { if (count < 1) { throw new BoundaryException("Value must be at least 1, " + count + " given"); } if (buffer == null) { throw new NullPointerException("Null return buffer was given"); } byte[] registerAddressArray = new byte[1]; registerAddressArray[0] = (byte) registerAddress; return transaction(registerAddressArray, registerAddressArray.length, buffer, count); }
/** * Execute a read only transaction with the device. * * Read bytes from a device. This method does not write any data to prompt * the device. * * @param buffer A pointer to the array of bytes to store the data read from * the device. Must be created using ByteBuffer.allocateDirect(). * @param count The number of bytes to read in the transaction. * @return Transfer Aborted... false for success, true for aborted. */ public boolean readOnly(ByteBuffer buffer, int count) { if (count < 1) { throw new BoundaryException("Value must be at least 1, " + count + " given"); } if (!buffer.isDirect()) throw new IllegalArgumentException("must be a direct buffer"); if (buffer.capacity() < count) throw new IllegalArgumentException("buffer is too small, must be at least " + count); return I2CJNI.i2CRead((byte) m_port.getValue(), (byte) m_deviceAddress, buffer, (byte) count) < 0; }
/** * Execute a read only transaction with the device. * <p/> * Read 1 to 7 bytes from a device. This method does not write any data to prompt * the device. * * @param buffer A pointer to the array of bytes to store the data read from * the device. * @param count The number of bytes to read in the transaction. [1..7] * @return Transfer Aborted... false for success, true for aborted. */ public boolean readOnly(byte[] buffer, int count) { BoundaryException.assertWithinBounds(count, 1, 7); if (buffer == null) { throw new NullPointerException("Null return buffer was given"); } ByteBuffer dataReceivedBuffer = ByteBuffer.allocateDirect(count); int retVal = 0; dataReceivedBuffer.get(buffer); return retVal < 0; }
/** * Set the upper and lower limits of the analog trigger. * The limits are given in ADC codes. If oversampling is used, the units must be scaled * appropriately. * @param lower the lower raw limit * @param upper the upper raw limit */ public void setLimitsRaw(final int lower, final int upper) { if (lower > upper) { throw new BoundaryException("Lower bound is greater than upper"); } m_trigger.writeLowerLimit(lower); m_trigger.writeUpperLimit(upper); }
/** * Set the upper and lower limits of the analog trigger. * The limits are given as floating point voltage values. * @param lower the lower voltage limit * @param upper the upper voltage limit */ public void setLimitsVoltage(double lower, double upper) { if (lower > upper) { throw new BoundaryException("Lower bound is greater than upper bound"); } // TODO: This depends on the averaged setting. Only raw values will work as is. m_trigger.writeLowerLimit(m_analogModule.voltsToValue(m_channel, lower)); m_trigger.writeUpperLimit(m_analogModule.voltsToValue(m_channel, upper)); }
/** * Sets the maximum and minimum values expected from the input. * * @param minimumInput the minimum percentage expected from the input * @param maximumInput the maximum percentage expected from the output */ public synchronized void setInputRange(double minimumInput, double maximumInput) { if (minimumInput > maximumInput) { throw new BoundaryException("Lower bound is greater than upper bound"); } m_minimumInput = minimumInput; m_maximumInput = maximumInput; setSetpoint(m_setpoint); }
/** * Set 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. * @param samplesToAverage The number of samples to average from 1 to 127. */ public void setSamplesToAverage(int samplesToAverage) { BoundaryException.assertWithinBounds(samplesToAverage, 1, 127); switch (m_encodingType.value) { case EncodingType.k4X_val: m_encoder.writeTimerConfig_AverageSize(samplesToAverage); break; case EncodingType.k1X_val: case EncodingType.k2X_val: m_counter.setSamplesToAverage(samplesToAverage); } }
/** * Query an analog input channel on the DS IO in ratiometric form. * * @param channel The channel number to read. [1,8] * @return The analog input percentage for the channel. */ public double getAnalogInRatio(int channel) throws EnhancedIOException { BoundaryException.assertWithinBounds(channel, 1, 8); if (!m_inputValid) { throw new EnhancedIOException("Enhanced IO Missing"); } synchronized (m_inputDataSemaphore) { return m_inputData.data.analog[channel - 1] / kAnalogInputResolution; } }
/** * Query the voltage currently being output. * * AO1 is pin 11 on the top connector (P2). * AO2 is pin 12 on the top connector (P2). * * @param channel The analog output channel on the DS IO. [1,2] * @return The voltage being output on the channel. */ public double getAnalogOut(int channel) throws EnhancedIOException { BoundaryException.assertWithinBounds(channel, 1, 2); if (!m_outputValid) { throw new EnhancedIOException("Enhanced IO Missing"); } synchronized (m_outputDataSemaphore) { int tempData = m_outputData.data.dac[channel - 1]; tempData = tempData < 0 ? tempData + 256 : tempData; return tempData * kAnalogOutputReference / kAnalogOutputResolution; } }
/** * Get the current configuration for a DIO line. * * This has the side effect of forcing the Driver Station to switch to Enhanced mode if it's not when called. * If Enhanced mode is not enabled when this is called, it will return kUnknown. * * @param channel The DIO channel config to get. [1,16] * @return The configured mode for the DIO line. */ public tDigitalConfig getDigitalConfig(int channel) throws EnhancedIOException { BoundaryException.assertWithinBounds(channel, 1, 16); if (!m_outputValid) { m_requestEnhancedEnable = true; throw new EnhancedIOException("Enhanced IO Missing"); } synchronized (m_outputDataSemaphore) { if ((channel >= 1) && (channel <= 4)) { if ((m_outputData.data.pwm_enable & (1 << (channel - 1))) != 0) { return tDigitalConfig.kPWM; } } if ((channel >= 15) && (channel <= 16)) { if ((m_outputData.data.comparator_enable & (1 << (channel - 15))) != 0) { return tDigitalConfig.kAnalogComparator; } } if ((m_outputData.data.digital_oe & (1 << (channel - 1))) != 0) { return tDigitalConfig.kOutput; } if ((m_outputData.data.digital_pe & (1 << (channel - 1))) == 0) { return tDigitalConfig.kInputFloating; } if ((m_outputData.data.digital & (1 << (channel - 1))) != 0) { return tDigitalConfig.kInputPullUp; } else { return tDigitalConfig.kInputPullDown; } } }
/** * Get the state being output on a fixed digital output. * * @param channel The FixedDO line to get. [1,2] * @return The state of the FixedDO line. */ public boolean getFixedDigitalOutput(int channel) throws EnhancedIOException { BoundaryException.assertWithinBounds(channel, 1, 2); if (!m_outputValid) { throw new EnhancedIOException("Enhanced IO Missing"); } synchronized (m_outputDataSemaphore) { return ((m_outputData.data.fixed_digital_out >> (channel - 1)) & 1) != 0; } }
/** * Reset the position of an encoder to 0. * * This simply stores an offset locally. It does not reset the hardware counter on the IO board. * If you use this method with Index enabled, you may get unexpected results. * * @param encoderNumber The quadrature encoder to reset. [1,2] */ public void resetEncoder(int encoderNumber) throws EnhancedIOException { BoundaryException.assertWithinBounds(encoderNumber, 1, 2); if (!m_inputValid) { throw new EnhancedIOException("Enhanced IO Missing"); } synchronized (m_inputDataSemaphore) { m_encoderOffsets[encoderNumber - 1] = m_inputData.data.quad[encoderNumber - 1]; } }
/** * Get the current configuration of a quadrature encoder index channel. * * This has the side effect of forcing the Driver Station to switch to Enhanced mode if it's not when called. * If Enhanced mode is not enabled when this is called, it will return false. * * @param encoderNumber The quadrature encoder. [1,2] * @return Is the index channel of the encoder enabled. */ public boolean getEncoderIndexEnable(int encoderNumber) throws EnhancedIOException { BoundaryException.assertWithinBounds(encoderNumber, 1, 2); if (!m_outputValid) { m_requestEnhancedEnable = true; throw new EnhancedIOException("Enhanced IO Missing"); } synchronized (m_outputDataSemaphore) { return ((m_outputData.data.quad_index_enable >> (encoderNumber - 1)) & 1) != 0; } }
/** * Get the percent duty-cycle that the PWM generator channel is configured to output. * * @param channel The DIO line's PWM generator to get the duty-cycle from. [1,4] * @return The percent duty-cycle being output (if the DIO line is configured for PWM). [0.0,1.0] */ public double getPWMOutput(int channel) throws EnhancedIOException { BoundaryException.assertWithinBounds(channel, 1, 4); if (!m_outputValid) { throw new EnhancedIOException("Enhanced IO Missing"); } synchronized (m_outputDataSemaphore) { int tempCompare = m_outputData.data.pwm_compare[channel - 1] & 0xFFFF; int tempPeriod = m_outputData.data.pwm_period[(channel - 1) >> 1] & 0xFFFF; return (double) tempCompare / (double) tempPeriod; } }
/** * Set the percent duty-cycle to output on a PWM enabled DIO line. * * DIO1 through DIO4 have the ability to output a PWM signal. The period of the * signal can be configured in pairs using SetPWMPeriod(). * * @param channel The DIO line's PWM generator to set. [1,4] * @param value The percent duty-cycle to output from the PWM generator. [0.0,1.0] */ public void setPWMOutput(int channel, double value) throws EnhancedIOException { BoundaryException.assertWithinBounds(channel, 1, 4); if (!m_outputValid) { throw new EnhancedIOException("Enhanced IO Missing"); } if (value > 1.0) { value = 1.0; } else if (value < 0.0) { value = 0.0; } synchronized (m_outputDataSemaphore) { m_outputData.data.pwm_compare[channel - 1] = (short) (value * (double) m_outputData.data.pwm_period[(channel - 1) >> 1]); } }
/** * Set the upper and lower boundaries * @param lower The lower limit * @param upper The upper limit */ public void set(final int lower, final int upper) { if (lower > upper) { throw new BoundaryException("Lower boundary is greater than upper"); } this.lower = lower; this.upper = upper; write(); }