/*
* Copyright 2014-2016 Cel Skeggs
* Copyright 2015 Jake Springer
*
* This file is part of the CCRE, the Common Chicken Runtime Engine.
*
* The CCRE is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* The CCRE is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the CCRE. If not, see <http://www.gnu.org/licenses/>.
*/
package ccre.frc;
import java.io.IOException;
import ccre.bus.I2CBus;
import ccre.bus.RS232Bus;
import ccre.bus.RS232IO;
import ccre.bus.SPIBus;
import ccre.channel.BooleanInput;
import ccre.channel.BooleanOutput;
import ccre.channel.EventInput;
import ccre.channel.FloatInput;
import ccre.channel.FloatOutput;
import ccre.ctrl.ExtendedMotor;
import ccre.ctrl.ExtendedMotorFailureException;
import ccre.ctrl.Joystick;
import ccre.ctrl.binding.CluckControlBinder;
import ccre.ctrl.binding.ControlBindingCreator;
import ccre.ctrl.binding.ControlBindingDataSource;
import ccre.ctrl.binding.ControlBindingDataSourceBuildable;
import ccre.discrete.DiscreteInput;
import ccre.drivers.ctre.talon.TalonExtendedMotor;
import ccre.instinct.InstinctModule;
import ccre.log.Logger;
import ccre.recording.Recorder;
import ccre.timers.Ticker;
import ccre.verifier.SetupPhase;
/**
* The main class to access the I/O on a roboRIO.
*
* @author skeggsc
*/
public class FRC {
/**
* Signifies that the motor should be directly outputted without negation.
*/
public static final boolean MOTOR_FORWARD = false;
/**
* Signifies that the motor should be outputted after negating the value.
*/
public static final boolean MOTOR_REVERSE = true;
/**
* Signifies that no ramping should be applied to this motor.
*/
public static final float NO_RAMPING = 0.0f;
/**
* The battery power channel.
*/
public static final int POWER_CHANNEL_BATTERY = 0;
/**
* The 3.3V rail power channel.
*/
public static final int POWER_CHANNEL_3V3 = 1;
/**
* The 5V rail power channel.
*/
public static final int POWER_CHANNEL_5V = 2;
/**
* The 6V rail power channel.
*/
public static final int POWER_CHANNEL_6V = 3;
/**
* Two pulse mode for a counter. The default mode, uses one source to count
* up and the other to count down.
*/
public static final int TWO_PULSE_MODE = 0;
/**
* Uses the counter to determine the pulse width of a high pulse (rising
* edge to falling edge) or a low pulse (falling edge to rising edge.)
*
* TODO: implement this fully
*/
public static final int SEMIPERIOD_MODE = 1;
/**
* Pulse length mode for a counter. Uses the pulse width to determine if the
* counter should count up or down.
*/
public static final int PULSE_LENGTH_MODE = 2;
/**
* External direction mode for a counter. Uses one source to count up and
* uses one source to determine direction.
*/
public static final int EXTERNAL_DIRECTION_MODE = 3;
/**
* For unused channels for counters.
*/
public static final int UNUSED = -1;
/**
* The FRCImplementation providing access to the robot.
*/
public static final FRCImplementation impl = FRCImplementationHolder.getImplementation();
/**
* Joystick 1 on the Driver Station.
*/
public static final Joystick joystick1 = impl.getJoystick(1);
/**
* Joystick 2 on the Driver Station.
*/
public static final Joystick joystick2 = impl.getJoystick(2);
/**
* Joystick 3 on the Driver Station.
*/
public static final Joystick joystick3 = impl.getJoystick(3);
/**
* Joystick 4 on the Driver Station.
*/
public static final Joystick joystick4 = impl.getJoystick(4);
/**
* Joystick 5 on the Driver Station.
*/
public static final Joystick joystick5 = impl.getJoystick(5);
/**
* Joystick 6 on the Driver Station.
*/
public static final Joystick joystick6 = impl.getJoystick(6);
/**
* Produced during every mode if the driver station is attached.
*/
public static final EventInput globalPeriodic = impl.getGlobalPeriodic();
/**
* Constant time periodic. Should pulse every 10 ms.
*/
public static final EventInput constantPeriodic = new Ticker("constantPeriodic", 10, false);
/**
* Constant time sensor update event. Should pulse every 20 ms. This should
* be used when you want to poll an on-robot sensor.
*/
public static final EventInput sensorPeriodic = new Ticker("sensorPeriodic", 20, false);
/**
* Produced when the robot enters autonomous mode.
*/
public static final EventInput startAuto = impl.getStartAuto();
/**
* Produced during autonomous mode.
*/
public static final EventInput duringAuto = impl.getDuringAuto();
/**
* Produced when the robot enters teleop mode.
*/
public static final EventInput startTele = impl.getStartTele();
/**
* Produced during teleop mode.
*/
public static final EventInput duringTele = impl.getDuringTele();
/**
* Produced when the robot enters testing mode.
*/
public static final EventInput startTest = impl.getStartTest();
/**
* Produced during testing mode.
*/
public static final EventInput duringTest = impl.getDuringTest();
/**
* Produced when the robot enters disabled mode.
*/
public static final EventInput startDisabled = impl.getStartDisabled();
/**
* Produced while the robot is disabled.
*/
public static final EventInput duringDisabled = impl.getDuringDisabled();
/**
* Create a reference to a Jaguar speed controller on the specified PWM port
* and motor reversal, with a specified ramping rate.
*
* If the ramping rate is zero, then no ramping is applied. Don't use this
* if you don't know what you're doing! Otherwise, the ramping rate is the
* maximum difference allowed per 10 milliseconds (constantPeriodic). (So a
* rate of 0.1f means that you need 200 milliseconds to go from -1.0 to
* 1.0.)
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @param ramping the ramping rate.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput jaguar(int id, boolean negate, float ramping) {
FloatOutput motor = impl.makeMotor(id, FRCImplementation.JAGUAR);
FloatOutput ramped = (negate ? motor.negate() : motor).addRamping(ramping, constantPeriodic);
ramped.setWhen(0.0f, startDisabled);
return ramped;
}
/**
* Create a reference to a Jaguar speed controller on the specified PWM port
* and motor reversal, with a default ramping rate of 0.1, aka 200
* milliseconds to ramp from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput jaguar(int id, boolean negate) {
return jaguar(id, negate, 0.1f);
}
/**
* Create a reference to a Jaguar speed controller on the specified PWM
* port, with a default ramping rate of 0.1, aka 200 milliseconds to ramp
* from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @return the output that will output to the specified motor.
*/
@SetupPhase
public static FloatOutput jaguar(int id) {
return jaguar(id, false, 0.1f);
}
/**
* Create a reference to a Victor speed controller on the specified PWM port
* and motor reversal, with a specified ramping rate.
*
* If the ramping rate is zero, then no ramping is applied. Don't use this
* if you don't know what you're doing! Otherwise, the ramping rate is the
* maximum difference allowed per 10 milliseconds (constantPeriodic). (So a
* rate of 0.1f means that you need 200 milliseconds to go from -1.0 to
* 1.0.)
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @param ramping the ramping rate.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput victor(int id, boolean negate, float ramping) {
FloatOutput motor = impl.makeMotor(id, FRCImplementation.VICTOR);
FloatOutput ramped = (negate ? motor.negate() : motor).addRamping(ramping, constantPeriodic);
ramped.setWhen(0.0f, startDisabled);
return ramped;
}
/**
* Create a reference to a Victor speed controller on the specified PWM port
* and motor reversal, with a default ramping rate of 0.1, aka 200
* milliseconds to ramp from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput victor(int id, boolean negate) {
return victor(id, negate, 0.1f);
}
/**
* Create a reference to a Victor speed controller on the specified PWM
* port, with a default ramping rate of 0.1, aka 200 milliseconds to ramp
* from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @return the output that will output to the specified motor.
*/
@SetupPhase
public static FloatOutput victor(int id) {
return victor(id, false, 0.1f);
}
/**
* Create a reference to a Talon SR speed controller on the specified PWM
* port and motor reversal, with a specified ramping rate.
*
* If the ramping rate is zero, then no ramping is applied. Don't use this
* if you don't know what you're doing! Otherwise, the ramping rate is the
* maximum difference allowed per 10 milliseconds (constantPeriodic). (So a
* rate of 0.1f means that you need 200 milliseconds to go from -1.0 to
* 1.0.)
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @param ramping the ramping rate.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput talon(int id, boolean negate, float ramping) {
FloatOutput motor = impl.makeMotor(id, FRCImplementation.TALON);
FloatOutput ramped = (negate ? motor.negate() : motor).addRamping(ramping, constantPeriodic);
ramped.setWhen(0.0f, startDisabled);
return ramped;
}
/**
* Create a reference to a Talon SR speed controller on the specified PWM
* port and motor reversal, with a default ramping rate of 0.1, aka 200
* milliseconds to ramp from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput talon(int id, boolean negate) {
return talon(id, negate, 0.1f);
}
/**
* Create a reference to a Talon SR speed controller on the specified PWM
* port, with a default ramping rate of 0.1, aka 200 milliseconds to ramp
* from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @return the output that will output to the specified motor.
*/
@SetupPhase
public static FloatOutput talon(int id) {
return talon(id, false, 0.1f);
}
/**
* Create a reference to a Talon SRX speed controller on the specified PWM
* port and motor reversal, with a specified ramping rate.
*
* If the ramping rate is zero, then no ramping is applied. Don't use this
* if you don't know what you're doing! Otherwise, the ramping rate is the
* maximum difference allowed per 10 milliseconds (constantPeriodic). (So a
* rate of 0.1f means that you need 200 milliseconds to go from -1.0 to
* 1.0.)
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @param ramping the ramping rate.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput talonSRX(int id, boolean negate, float ramping) {
FloatOutput motor = impl.makeMotor(id, FRCImplementation.TALONSRX);
FloatOutput ramped = (negate ? motor.negate() : motor).addRamping(ramping, constantPeriodic);
ramped.setWhen(0.0f, startDisabled);
return ramped;
}
/**
* Create a reference to a Talon SRX speed controller on the specified PWM
* port and motor reversal, with a default ramping rate of 0.1, aka 200
* milliseconds to ramp from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput talonSRX(int id, boolean negate) {
return talonSRX(id, negate, 0.1f);
}
/**
* Create a reference to a Talon SRX speed controller on the specified PWM
* port, with a default ramping rate of 0.1, aka 200 milliseconds to ramp
* from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @return the output that will output to the specified motor.
*/
@SetupPhase
public static FloatOutput talonSRX(int id) {
return talonSRX(id, false, 0.1f);
}
/**
* Create a reference to a Victor SP speed controller on the specified PWM
* port and motor reversal, with a specified ramping rate.
*
* If the ramping rate is zero, then no ramping is applied. Don't use this
* if you don't know what you're doing! Otherwise, the ramping rate is the
* maximum difference allowed per 10 milliseconds (constantPeriodic). (So a
* rate of 0.1f means that you need 200 milliseconds to go from -1.0 to
* 1.0.)
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @param ramping the ramping rate.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput victorSP(int id, boolean negate, float ramping) {
FloatOutput motor = impl.makeMotor(id, FRCImplementation.VICTORSP);
FloatOutput ramped = (negate ? motor.negate() : motor).addRamping(ramping, constantPeriodic);
ramped.setWhen(0.0f, startDisabled);
return ramped;
}
/**
* Create a reference to a Victor SP speed controller on the specified PWM
* port and motor reversal, with a default ramping rate of 0.1, aka 200
* milliseconds to ramp from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput victorSP(int id, boolean negate) {
return victorSP(id, negate, 0.1f);
}
/**
* Create a reference to a Victor SP speed controller on the specified PWM
* port, with a default ramping rate of 0.1, aka 200 milliseconds to ramp
* from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @return the output that will output to the specified motor.
*/
@SetupPhase
public static FloatOutput victorSP(int id) {
return victorSP(id, false, 0.1f);
}
/**
* Create a reference to a Spark speed controller on the specified PWM port
* and motor reversal, with a specified ramping rate.
*
* If the ramping rate is zero, then no ramping is applied. Don't use this
* if you don't know what you're doing! Otherwise, the ramping rate is the
* maximum difference allowed per 10 milliseconds (constantPeriodic). (So a
* rate of 0.1f means that you need 200 milliseconds to go from -1.0 to
* 1.0.)
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @param ramping the ramping rate.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput spark(int id, boolean negate, float ramping) {
FloatOutput motor = impl.makeMotor(id, FRCImplementation.SPARK);
FloatOutput ramped = (negate ? motor.negate() : motor).addRamping(ramping, constantPeriodic);
ramped.setWhen(0.0f, startDisabled);
return ramped;
}
/**
* Create a reference to a Spark speed controller on the specified PWM port
* and motor reversal, with a default ramping rate of 0.1, aka 200
* milliseconds to ramp from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput spark(int id, boolean negate) {
return spark(id, negate, 0.1f);
}
/**
* Create a reference to a Spark speed controller on the specified PWM port,
* with a default ramping rate of 0.1, aka 200 milliseconds to ramp from
* stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @return the output that will output to the specified motor.
*/
@SetupPhase
public static FloatOutput spark(int id) {
return spark(id, false, 0.1f);
}
/**
* Create a reference to a SD540 speed controller on the specified PWM port
* and motor reversal, with a specified ramping rate.
*
* If the ramping rate is zero, then no ramping is applied. Don't use this
* if you don't know what you're doing! Otherwise, the ramping rate is the
* maximum difference allowed per 10 milliseconds (constantPeriodic). (So a
* rate of 0.1f means that you need 200 milliseconds to go from -1.0 to
* 1.0.)
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @param ramping the ramping rate.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput sd540(int id, boolean negate, float ramping) {
FloatOutput motor = impl.makeMotor(id, FRCImplementation.SD540);
FloatOutput ramped = (negate ? motor.negate() : motor).addRamping(ramping, constantPeriodic);
ramped.setWhen(0.0f, startDisabled);
return ramped;
}
/**
* Create a reference to a SD540 speed controller on the specified PWM port
* and motor reversal, with a default ramping rate of 0.1, aka 200
* milliseconds to ramp from stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @return the output that will output to the specified motor.
* @see #MOTOR_FORWARD
* @see #MOTOR_REVERSE
*/
@SetupPhase
public static FloatOutput sd540(int id, boolean negate) {
return sd540(id, negate, 0.1f);
}
/**
* Create a reference to a SD540 speed controller on the specified PWM port,
* with a default ramping rate of 0.1, aka 200 milliseconds to ramp from
* stopped to full speed.
*
* @param id the motor port ID, from 1 to 10, inclusive.
* @return the output that will output to the specified motor.
*/
@SetupPhase
public static FloatOutput sd540(int id) {
return sd540(id, false, 0.1f);
}
/**
* Create a reference to a CAN Jaguar speed controller with the specified
* CAN device number. This may, of course, fail, if the Jaguar cannot be
* found.
*
* @param deviceNumber the device number to connect to.
* @return the ExtendedMotor representing this output.
*/
@SetupPhase
public static ExtendedMotor jaguarCAN(int deviceNumber) {
Logger.warning("The CCRE CAN Jaguar functionality is NOT yet complete and is UNTESTED! Use with your own risk.");
return impl.makeCANJaguar(deviceNumber);
}
/**
* Create a reference to a CAN Jaguar speed controller with the specified
* CAN device number. This may, of course, fail, if the Jaguar cannot be
* found.
*
* @param deviceNumber the device number to connect to.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @return the output that will output to the specified motor.
* @throws ExtendedMotorFailureException if control cannot be established.
*/
@SetupPhase
public static FloatOutput jaguarSimpleCAN(int deviceNumber, boolean negate) throws ExtendedMotorFailureException {
return jaguarCAN(deviceNumber).simpleControl(negate);
}
/**
* Create a reference to a CAN Talon speed controller with the specified CAN
* device number. This may, of course, fail, if the Talon cannot be found.
*
* @param deviceNumber the device number to connect to.
* @return the ExtendedMotor representing this output.
*/
@SetupPhase
public static TalonExtendedMotor talonCAN(int deviceNumber) {
return impl.makeCANTalon(deviceNumber);
}
/**
* Create a reference to a CAN Talon speed controller with the specified CAN
* device number. This may, of course, fail, if the Talon cannot be found.
*
* @param deviceNumber the device number to connect to.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @return the output that will output to the specified motor.
* @throws ExtendedMotorFailureException if control cannot be established.
* @deprecated Use {@link #talonCANControl(int, boolean)} instead, which
* doesn't throw ExtendedMotorFailureException
*/
@Deprecated
@SetupPhase
public static FloatOutput talonSimpleCAN(int deviceNumber, boolean negate) throws ExtendedMotorFailureException {
return talonCAN(deviceNumber).simpleControl(negate);
}
/**
* Create a reference to a CAN Talon speed controller with the specified CAN
* device number. This may, of course, fail, if the Talon cannot be found.
*
* @param deviceNumber the device number to connect to.
* @param negate MOTOR_FORWARD if the motor direction should be unmodified,
* MOTOR_REVERSE if the motor direction should be reversed.
* @return the output that will output to the specified motor.
*/
@SetupPhase
public static FloatOutput talonCANControl(int deviceNumber, boolean negate) {
return talonCAN(deviceNumber).simpleControlSafe(negate);
}
/**
* Create a reference to a solenoid on the specified port and the default
* module.
*
* @param id the port of the solenoid.
* @return the output that will control the solenoid.
*/
@SetupPhase
public static BooleanOutput solenoid(int id) {
return impl.makeSolenoid(0, id);
}
/**
* Create a reference to a solenoid on the specified port and module.
*
* @param module the module of the solenoid (PCM on roboRIO)
* @param id the port of the solenoid.
* @return the output that will control the solenoid.
*/
@SetupPhase
public static BooleanOutput solenoid(int module, int id) {
return impl.makeSolenoid(module, id);
}
/**
* Create a reference to a digital output on the specified port.
*
* @param id the port of the digital output.
* @return the output that will control the digital output.
*/
@SetupPhase
public static BooleanOutput digitalOutput(int id) {
return impl.makeDigitalOutput(id);
}
/**
* Get a reference to the analog input that reads the current battery
* voltage, scaled to represent the real battery voltage.
*
* @return The current battery voltage.
*/
@SetupPhase
public static FloatInput batteryVoltage() {
return impl.getBatteryVoltage(sensorPeriodic);
}
/**
* Get a reference to the analog input that reads the current battery
* voltage, scaled to represent the real battery voltage.
*
* @param updateOn when to update the sensor value.
* @return The current battery voltage.
*/
@SetupPhase
public static FloatInput batteryVoltage(EventInput updateOn) {
return impl.getBatteryVoltage(updateOn);
}
/**
* Create a reference to an analog input on the specified port.
*
* @param id the port number.
* @return the analog input, reporting in voltage.
*/
@SetupPhase
public static FloatInput analogInput(int id) {
return impl.makeAnalogInput(id, sensorPeriodic);
}
/**
* Create a reference to an analog input on the specified port.
*
* @param id the port number.
* @param updateOn when to update the sensor value.
* @return the analog input, reporting in voltage.
*/
@SetupPhase
public static FloatInput analogInput(int id, EventInput updateOn) {
return impl.makeAnalogInput(id, updateOn);
}
/**
* Create a reference to an analog input on the specified port with the
* specified number of average bits.
*
* @param id the port number.
* @param averageBits the number of averaging bits.
* @return the analog input, reporting in voltage.
*/
@SetupPhase
public static FloatInput analogInput(int id, int averageBits) {
return impl.makeAnalogInput(id, averageBits, sensorPeriodic);
}
/**
* Create a reference to an analog input on the specified port with the
* specified number of average bits.
*
* @param id the port number.
* @param averageBits the number of averaging bits.
* @param updateOn when to update the sensor value.
* @return the analog input, reporting in voltage.
*/
@SetupPhase
public static FloatInput analogInput(int id, int averageBits, EventInput updateOn) {
return impl.makeAnalogInput(id, averageBits, updateOn);
}
/**
* Create a reference to a digital input on the specified port.
*
* @param id the port number.
* @return the digital input.
*/
@SetupPhase
public static BooleanInput digitalInput(int id) {
return impl.makeDigitalInput(id, sensorPeriodic);
}
/**
* Create a reference to a digital input on the specified port.
*
* @param id the port number.
* @param updateOn when to update the sensor value.
* @return the digital input.
*/
@SetupPhase
public static BooleanInput digitalInput(int id, EventInput updateOn) {
return impl.makeDigitalInput(id, updateOn);
}
/**
* Create a reference to a digital input on the specified port, as a
* BooleanInput that updates by using FPGA interrupts or an equivalent.
* Warning: many systems have a limit on the maximum number of interrupts
* available - use sparingly!
*
* @param id the port number.
* @return the digital input.
*/
@SetupPhase
public static BooleanInput digitalInputByInterrupt(int id) {
return impl.makeDigitalInputByInterrupt(id);
}
/**
* Create a reference to a servo controller for the specified port and
* minimum and maximum values.
*
* @param id the port number.
* @param minInput the value on the output that should correspond to the
* servo's minimum position.
* @param maxInput the value on the output that should correspond to the
* servo's maximum position.
* @return the FloatOutput that controls the servo.
*/
@SetupPhase
public static FloatOutput servo(int id, float minInput, float maxInput) {
return impl.makeServo(id, minInput, maxInput);
}
/**
* Get a boolean input that checks if the robot is currently disabled.
*
* @return the input.
*/
@SetupPhase
public static BooleanInput robotDisabled() {
return impl.getIsDisabled();
}
/**
* Get a boolean input that checks if the robot is currently disabled.
*
* @return the input.
*/
@SetupPhase
public static BooleanInput robotEnabled() {
return impl.getIsDisabled().not();
}
/**
* Gets a boolean input that checks if the robot is currently in autonomous,
* as opposed to teleop and testing.
*
* @return the input.
*/
@SetupPhase
public static BooleanInput inAutonomousMode() {
return impl.getIsAutonomous();
}
/**
* Gets a boolean input that checks if the robot is currently in testing
* mode, as opposed to teleop and autonomous.
*
* @return the input.
*/
@SetupPhase
public static BooleanInput inTestMode() {
return impl.getIsTest();
}
/**
* Gets a boolean input that checks if the robot is currently in teleop
* mode, as opposed to testing and autonomous.
*
* @return the input.
*/
@SetupPhase
public static BooleanInput inTeleopMode() {
return impl.getIsTest().or(impl.getIsAutonomous()).not().andNot(impl.getIsDisabled());
}
/**
* Gets the robot's control mode, as a DiscreteInput.
*
* @return the input for the mode.
*/
@SetupPhase
public static DiscreteInput<FRCMode> getMode() {
return impl.getMode();
}
/**
* Get a boolean input that checks if the robot is currently connected to
* the FMS, as opposed to being off the playing field.
*
* @return the input.
*/
@SetupPhase
public static BooleanInput isOnFMS() {
return impl.getIsFMS();
}
/**
* Activate the compressor on the given pressure switch channel and
* compressor relay channel.
*
* @param pressureSwitchChannel the channel of the pressure switch digital
* input.
* @param compressorRelayChannel the channel of the compressor's relay.
*/
@SetupPhase
public static void compressor(int pressureSwitchChannel, int compressorRelayChannel) {
customCompressor(digitalInput(pressureSwitchChannel), compressorRelayChannel);
}
/**
* Get control of the PCM-attached compressor. This makes sure that the PCM
* compressor is running the closed loop control.
*
* @return a BooleanOutput that can turn closed loop control on and off.
*/
@SetupPhase
public static BooleanOutput compressorPCM() {
return impl.usePCMCompressor();
}
/**
* Reads the current status of the PCM pressure switch.
*
* @return the pressure switch status.
*/
@SetupPhase
public static BooleanInput pressureSwitchPCM() {
return impl.getPCMPressureSwitch(sensorPeriodic);
}
/**
* Reads the current status of the PCM pressure switch.
*
* @param updateOn when to update the sensor value.
* @return the pressure switch status.
*/
@SetupPhase
public static BooleanInput pressureSwitchPCM(EventInput updateOn) {
return impl.getPCMPressureSwitch(updateOn);
}
/**
* Reads the current status of the PCM compressor enable output.
*
* @return the compressor enable output.
*/
@SetupPhase
public static BooleanInput compressorRunningPCM() {
return impl.getPCMCompressorRunning(sensorPeriodic);
}
/**
* Reads the current status of the PCM compressor enable output.
*
* @param updateOn when to update the sensor value.
* @return the compressor enable output.
*/
@SetupPhase
public static BooleanInput compressorRunningPCM(EventInput updateOn) {
return impl.getPCMCompressorRunning(updateOn);
}
/**
* Reads the current draw of the PCM compressor.
*
* @return the current being used by the compressor.
*/
@SetupPhase
public static FloatInput compressorCurrentPCM() {
return impl.getPCMCompressorCurrent(sensorPeriodic);
}
/**
* Reads the current draw of the PCM compressor.
*
* @param updateOn when to update the sensor value.
* @return the current being used by the compressor.
*/
@SetupPhase
public static FloatInput compressorCurrentPCM(EventInput updateOn) {
return impl.getPCMCompressorCurrent(updateOn);
}
/**
* Reads the current draw of the entire PDP.
*
* @return the current being used by the specified channel.
*/
@SetupPhase
public static FloatInput totalCurrentPDP() {
return impl.getPDPTotalCurrent(sensorPeriodic);
}
/**
* Reads the current draw of the entire PDP.
*
* @param updateOn when to update the sensor value.
* @return the current being used by the specified channel.
*/
@SetupPhase
public static FloatInput totalCurrentPDP(EventInput updateOn) {
return impl.getPDPTotalCurrent(updateOn);
}
/**
* Reads the current draw of the specified PDP channel.
*
* @param channel the channel to monitor
* @return the current being used by the specified channel.
*/
@SetupPhase
public static FloatInput channelCurrentPDP(int channel) {
return impl.getPDPChannelCurrent(channel, sensorPeriodic);
}
/**
* Reads the current draw of the specified PDP channel.
*
* @param channel the channel to monitor
* @param updateOn when to update the sensor value.
* @return the current being used by the specified channel.
*/
@SetupPhase
public static FloatInput channelCurrentPDP(int channel, EventInput updateOn) {
return impl.getPDPChannelCurrent(channel, updateOn);
}
/**
* Reads the voltage of the PDP.
*
* @return the voltage being measured by the PDP.
*/
@SetupPhase
public static FloatInput voltagePDP() {
return impl.getPDPVoltage(sensorPeriodic);
}
/**
* Reads the voltage of the PDP.
*
* @param updateOn when to update the sensor value.
* @return the voltage being measured by the PDP.
*/
@SetupPhase
public static FloatInput voltagePDP(EventInput updateOn) {
return impl.getPDPVoltage(updateOn);
}
/**
* Reads the voltage from a specified power reading channel.
*
* @param powerChannel the power channel to read from.
* @return the voltage being measured.
*/
@SetupPhase
public static FloatInput voltageChannel(int powerChannel) {
return impl.getChannelVoltage(powerChannel, sensorPeriodic);
}
/**
* Reads the voltage from a specified power reading channel.
*
* @param powerChannel the power channel to read from.
* @param updateOn when to update the sensor value.
* @return the voltage being measured.
*/
@SetupPhase
public static FloatInput voltageChannel(int powerChannel, EventInput updateOn) {
return impl.getChannelVoltage(powerChannel, updateOn);
}
/**
* Reads the current from a specified power reading channel.
*
* @param powerChannel the power channel to read from.
* @return the current being measured.
*/
@SetupPhase
public static FloatInput currentChannel(int powerChannel) {
return impl.getChannelCurrent(powerChannel, sensorPeriodic);
}
/**
* Reads the current from a specified power reading channel.
*
* @param powerChannel the power channel to read from.
* @param updateOn when to update the sensor value.
* @return the current being measured.
*/
@SetupPhase
public static FloatInput currentChannel(int powerChannel, EventInput updateOn) {
return impl.getChannelCurrent(powerChannel, updateOn);
}
/**
* Checks if the specified power reading channel is enabled.
*
* @param powerChannel the power channel to read from.
* @return if the channel is enabled.
*/
@SetupPhase
public static BooleanInput enabledChannel(int powerChannel) {
return impl.getChannelEnabled(powerChannel, sensorPeriodic);
}
/**
* Checks if the specified power reading channel is enabled.
*
* @param powerChannel the power channel to read from.
* @param updateOn when to update the sensor value.
* @return if the channel is enabled.
*/
@SetupPhase
public static BooleanInput enabledChannel(int powerChannel, EventInput updateOn) {
return impl.getChannelEnabled(powerChannel, updateOn);
}
/**
* Activate the compressor on the given pressure switch input and compressor
* relay channel.
*
* @param shouldDisable should the compressor be turned off.
* @param compressorRelayChannel the channel of the compressor's relay.
*/
@SetupPhase
public static void customCompressor(BooleanInput shouldDisable, int compressorRelayChannel) {
// TODO: do this without an extra Ticker?
shouldDisable.send(relayForward(compressorRelayChannel).invert().limitUpdatesTo(new Ticker("compressor", 500, false)));
}
/**
* Create a reference to an Encoder on the specified ports with the
* specified number of average bits.
*
* @param aChannel The alpha-channel for the encoder.
* @param bChannel The beta-channel for the encoder.
* @param reverse Should the result of the encoder be negated?
* @param resetWhen If provided, the Encoder's value will be reset when this
* event is produced.
* @return the Encoder, reporting encoder ticks.
*/
@SetupPhase
public static FloatInput encoder(int aChannel, int bChannel, boolean reverse, EventInput resetWhen) {
return impl.makeEncoder(aChannel, bChannel, reverse, resetWhen, sensorPeriodic);
}
/**
* Create a reference to an Encoder on the specified ports with the
* specified number of average bits.
*
* @param aChannel The alpha-channel for the encoder.
* @param bChannel The beta-channel for the encoder.
* @param reverse Should the result of the encoder be negated?
* @param resetWhen If provided, the Encoder's value will be reset when this
* event is produced.
* @param updateOn when to update the sensor value.
* @return A FloatInput that represents the count of an encoder
*/
@SetupPhase
public static FloatInput encoder(int aChannel, int bChannel, boolean reverse, EventInput resetWhen, EventInput updateOn) {
// TODO: check arguments; similar issue to Gyro
return impl.makeEncoder(aChannel, bChannel, reverse, resetWhen, updateOn);
}
/**
* Creates a reference to a Counter on the specified ports with the
* specified number of average bits. Will count up as specified by the mode.
*
* @see FRC#EXTERNAL_DIRECTION_MODE
* @see FRC#PULSE_LENGTH_MODE
* @see FRC#SEMIPERIOD_MODE
* @see FRC#TWO_PULSE_MODE
*
* @param upChannel the channel for the counter's side that counts up.
* @param downChannel the channel for the counter's side that counts down.
* @param mode the pulse tracking mode for the counter.
* @param resetWhen If provided, the Counter's value will be reset when this
* event is produced.
* @param updateOn Updates the FloatInput when this event is produced.
* @return A FloatInput that represents the count of a counter
*/
@SetupPhase
public static FloatInput counter(int upChannel, int downChannel, int mode, EventInput resetWhen, EventInput updateOn) {
return impl.makeCounter(upChannel, downChannel, resetWhen, updateOn, mode);
}
/**
* Creates a reference to a Counter on the specified ports with the
* specified number of average bits. Will count as specified by the mode.
*
* @see FRC#EXTERNAL_DIRECTION_MODE
* @see FRC#PULSE_LENGTH_MODE
* @see FRC#SEMIPERIOD_MODE
* @see FRC#TWO_PULSE_MODE
*
* @param upChannel the channel for the counter's side that counts up.
* @param downChannel the channel for the counter's side that counts down.
* @param mode the pulse tracking mode for the counter.
* @param resetWhen If provided, the Counter's value will be reset when this
* event is produced.
* @return A FloatInput that represents the count of a counter
*/
@SetupPhase
public static FloatInput counter(int upChannel, int downChannel, int mode, EventInput resetWhen) {
return impl.makeCounter(upChannel, downChannel, resetWhen, sensorPeriodic, mode);
}
/**
* Creates a reference to a Counter on the specified ports with the
* specified number of average bits. Will count as specified by
* TWO_PULSE_MODE.
*
* @see FRC#TWO_PULSE_MODE
*
* @param upChannel the channel for the counter's side that counts up.
* @param downChannel the channel for the counter's side that counts down.
* @param resetWhen If provided, the Counter's value will be reset when this
* event is produced.
* @param updateOn Updates the FloatInput when this event is produced.
* @return A FloatInput that represents the count of a counter
*/
@SetupPhase
public static FloatInput counter(int upChannel, int downChannel, EventInput resetWhen, EventInput updateOn) {
return impl.makeCounter(upChannel, downChannel, resetWhen, updateOn, TWO_PULSE_MODE);
}
/**
* Creates a reference to a Counter on the specified ports. Will count as
* specified by TWO_PULSE_MODE.
*
* @see FRC#TWO_PULSE_MODE
*
* @param upChannel the channel for the counter's side that counts up.
* @param downChannel the channel for the counter's side that counts down.
* @param resetWhen If provided, the Counter's value will be reset when this
* event is produced.
* @return A FloatInput that represents the count of a counter
*/
@SetupPhase
public static FloatInput counter(int upChannel, int downChannel, EventInput resetWhen) {
return impl.makeCounter(upChannel, downChannel, resetWhen, sensorPeriodic, TWO_PULSE_MODE);
}
/**
* Create a reference to the Forward side of the relay on the specified
* channel - this side can be turned on and off.
*
* @param channel The relay channel.
* @return the output that will modify the forward side of the channel.
*/
@SetupPhase
public static BooleanOutput relayForward(int channel) {
return impl.makeRelayForwardOutput(channel);
}
/**
* Create a reference to the Reverse side of the relay on the specified
* channel - this side can be turned on and off.
*
* @param channel The relay channel.
* @return the output that will modify the reverse side of the channel.
*/
@SetupPhase
public static BooleanOutput relayReverse(int channel) {
return impl.makeRelayReverseOutput(channel);
}
/**
* Create a reference to a Gyro on the specified port with the specified
* sensitivity. This will allow reading the current rotation of the Gyro.
* This also takes an EventInput, and when this is fired, the Gyro will be
* reset.
*
* Increased sensitivity means a smaller output for the same turn.
*
* @param port The Gyro port number.
* @param sensitivity The sensitivity of the Gyro. This is the number of
* volts/degree/second sensitivity of the gyro and is used in calculations
* to allow the code to work with multiple gyros. 0.007 is a good default
* value.
* @param evt When to reset the Gyro.
* @return The reference to the Gyro's current value.
*/
@SetupPhase
public static FloatInput gyro(int port, double sensitivity, EventInput evt) {
return impl.makeGyro(port, sensitivity, evt, sensorPeriodic);
}
/**
* Create a reference to a Gyro on the specified port with the specified
* sensitivity. This will allow reading the current rotation of the Gyro.
* This also takes an EventInput, and when this is fired, the Gyro will be
* reset.
*
* Increased sensitivity means a smaller output for the same turn.
*
* @param port The Gyro port number.
* @param sensitivity The sensitivity of the Gyro. This is the number of
* volts/degree/second sensitivity of the gyro and is used in calculations
* to allow the code to work with multiple gyros. 0.007 is a good default
* value.
* @param evt When to reset the Gyro.
* @param updateOn when to update the sensor value.
* @return The reference to the Gyro's current value.
*/
@SetupPhase
public static FloatInput gyro(int port, double sensitivity, EventInput evt, EventInput updateOn) {
// TODO: Figure out if anything should change about makeGyro's arguments
// now that I got rid of the no-event versions due to argument list
// conflicts.
return impl.makeGyro(port, sensitivity, evt, updateOn);
}
/**
* Register the specified InstinctModule as an autonomous mode. Note that
* registering multiple autonomous modes probably won't work properly.
*
* @param module the InstinctModule to register.
*/
@SetupPhase
public static void registerAutonomous(InstinctModule module) {
module.setShouldBeRunning(robotEnabled().and(inAutonomousMode()));
}
/**
* Opens and configures the onboard serial port on the robot.
*
* @param baudRate the baud rate of the port.
* @param deviceName the name of the device the serial port is connected to
* (used for debugging and the emulator.)
* @return a RS232IO interface to the port.
*/
@SetupPhase
public static RS232IO onboardRS232(int baudRate, String deviceName) {
return impl.makeRS232_Onboard(deviceName).open(baudRate);
}
/**
* Gets a reference to the onboard serial port, without configuring it.
*
* @param deviceName the name of the device the serial port is connected to
* (used for debugging and the emulator.)
* @return a RS232Bus interface to the port.
*/
@SetupPhase
public static RS232Bus onboardRS232(String deviceName) {
return impl.makeRS232_Onboard(deviceName);
}
/**
* Opens and configures the roboRIO's MXP-based serial port.
*
* @param baudRate the baud rate of the port.
* @param deviceName the name of the device the serial port is connected to
* (used for debugging and the emulator.)
* @return a RS232IO interface to the port.
*/
@SetupPhase
public static RS232IO mxpRS232(int baudRate, String deviceName) {
return impl.makeRS232_MXP(deviceName).open(baudRate);
}
/**
* Gets a reference to the roboRIO's MXP-based serial port, without
* configuring it.
*
* @param deviceName the name of the device the serial port is connected to
* (used for debugging and the emulator.)
* @return a RS232Bus interface to the port.
*/
@SetupPhase
public static RS232Bus mxpRS232(String deviceName) {
return impl.makeRS232_MXP(deviceName);
}
/**
* Opens and configures the USB-attached serial port on the roboRIO.
*
* @param baudRate the baud rate of the port.
* @param deviceName the name of the device the serial port is connected to
* (used for debugging and the emulator.)
* @return a RS232IO interface to the port.
*/
@SetupPhase
public static RS232IO usbRS232(int baudRate, String deviceName) {
return impl.makeRS232_USB(deviceName).open(baudRate);
}
/**
* Gets a reference to the USB-attached serial port on the roboRIO, without
* configuring it.
*
* @param deviceName the name of the device the serial port is connected to
* (used for debugging and the emulator.)
* @return a RS232Bus interface to the port.
*/
@SetupPhase
public static RS232Bus usbRS232(String deviceName) {
return impl.makeRS232_USB(deviceName);
}
/**
* Gets a reference to the onboard I2C port on the robot, without
* configuring it.
*
* @param deviceName the name of the device the serial port is connected to
* (used for debugging and the emulator.)
* @return a I2CBus interface to the port.
*/
@SetupPhase
public static I2CBus onboardI2C(String deviceName) {
return impl.makeI2C_Onboard(deviceName);
}
/**
* Gets a reference to the MXP's I2C port on the robot, without configuring
* it.
*
* @param deviceName the name of the device the serial port is connected to
* (used for debugging and the emulator.)
* @return a I2CBus interface to the port.
*/
@SetupPhase
public static I2CBus mxpI2C(String deviceName) {
return impl.makeI2C_MXP(deviceName);
}
/**
* Opens the onboard SPI port on the robot, without configuring it.
*
* @param cs the chip select address of the port, from 1 to 4.
* @param deviceName the name of the device the serial port is connected to
* (used for debugging and the emulator.)
* @return a SPIBus interface to the port.
*/
@SetupPhase
public static SPIBus onboardSPI(int cs, String deviceName) {
return impl.makeSPI_Onboard(cs, deviceName);
}
/**
* Opens the MXP's SPI port on the robot, without configuring it.
*
* @param deviceName the name of the device the serial port is connected to
* (used for debugging and the emulator.)
* @return a SPIBus interface to the port.
*/
@SetupPhase
public static SPIBus mxpSPI(String deviceName) {
return impl.makeSPI_MXP(deviceName);
}
/**
* Get a ControlBindingCreator that the user can bind, over Cluck, to any
* Joystick inputs.
*
* If you're running in the emulator, and bypassEmulation is false, then the
* Emulator will skip over including Joysticks at all and just show you your
* control bindings directly. Much easier to work with!
*
* @param name the name of the module that this creator is for. For example,
* "Drive Code".
* @param bypassEmulation if the emulator shouldn't try to emulate control
* bindings directly.
* @return the ControlBindingCreator that you can make your controls
* available over.
*/
@SetupPhase
public static ControlBindingCreator controlBinding(String name, boolean bypassEmulation) {
if (!bypassEmulation) {
ControlBindingCreator out = impl.tryMakeControlBindingCreator(name);
if (out != null) {
return out;
}
}
return CluckControlBinder.makeCreator(name, controlBindingSource(), impl.getOnInitComplete());
}
/**
* Get a ControlBindingCreator that the user can bind, over Cluck, to any
* Joystick inputs.
*
* If you're running in the emulator, then the Emulator will skip over
* including Joysticks at all and just show you your control bindings
* directly. Much easier to work with!
*
* @param name the name of the module that this creator is for. For example,
* "Drive Code".
* @return the ControlBindingCreator that you can make your controls
* available over.
* @see #controlBinding(String, boolean) if you want to choose whether or
* not the emulator emulates control bindings directly.
*/
@SetupPhase
public static ControlBindingCreator controlBinding(String name) {
return controlBinding(name, false);
}
private static ControlBindingCreator creator;
/**
* Get a ControlBindingCreator that the user can bind, over Cluck, to any
* Joystick inputs.
*
* If you're running in the emulator, then the Emulator will skip over
* including Joysticks at all and just show you your control bindings
* directly. Much easier to work with!
*
* @return the ControlBindingCreator that you can make your controls
* available over.
* @see #controlBinding(String) if you want to change the name of the
* module.
*/
@SetupPhase
public static ControlBindingCreator controlBinding() {
if (creator == null) {
creator = controlBinding("Robot");
}
return creator;
}
private static ControlBindingDataSource builtControlSource;
/**
* Get a ControlBindingDataSource for the six Joysticks.
*
* @return the data source.
* @see #controlBindingSource(String...) if you want to provide your own
* names, or use a different number of Joysticks.
* @see #controlBinding(String) if you just want to bind controls.
*/
@SetupPhase
public static synchronized ControlBindingDataSource controlBindingSource() {
if (builtControlSource == null) {
builtControlSource = controlBindingSource("Joystick 1", "Joystick 2", "Joystick 3", "Joystick 4", "Joystick 5", "Joystick 6");
}
return builtControlSource;
}
/**
* This is similar to {@link #controlBindingSource()} but lets you give
* better names to your Joysticks. For example, you could say
* <code>FRC.getControlBindingDataSource("Drive Joystick", "Copilot Joystick");</code>
*
* @param names the names of the Joysticks to attach to, in order.
* @return the generated control binding source.
*/
@SetupPhase
public static ControlBindingDataSource controlBindingSource(String... names) {
ControlBindingDataSourceBuildable ds = new ControlBindingDataSourceBuildable();
for (int i = 0; i < names.length; i++) {
ds.addJoystick(names[i], impl.getJoystick(i + 1), 12, 6);
}
return ds;
}
private static Recorder rec;
/**
* Gets or creates a recorder that includes recording for modes, period
* events, and battery voltage.
*
* @return the global recorder
*/
@SetupPhase
public static synchronized Recorder getRecorder() {
if (rec == null) {
try {
rec = Recorder.open(true, 8); // TODO: configurable?
} catch (IOException e) {
throw new RuntimeException(e); // TODO: better error handling?
}
rec.recordEventInput(globalPeriodic, "FRC.globalPeriodic");
rec.recordEventInput(constantPeriodic, "FRC.constantPeriodic");
rec.recordEventInput(sensorPeriodic, "FRC.sensorPeriodic");
rec.recordDiscreteInput(getMode(), "Robot Mode");
rec.recordBooleanInput(isOnFMS(), "FRC.isOnFMS()");
FloatOutput voltage = rec.createFloatOutput("Battery Voltage");
// make sure it covers the entire range
voltage.set(13f);
voltage.set(0);
batteryVoltage().send(voltage);
}
return rec;
}
/**
* Calculates a unique identifier for this particular roboRIO, which is
* based on a data source like the MAC address.
*
* @return the roboRIO's unique identifier.
*/
@SetupPhase
public static String getUniqueIdentifier() {
return impl.getUniqueIdentifier();
}
private FRC() {
}
}