001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.wpilibj;
006
007import static edu.wpi.first.units.Units.Amps;
008import static edu.wpi.first.units.Units.Celsius;
009import static edu.wpi.first.units.Units.Microseconds;
010import static edu.wpi.first.units.Units.Volts;
011
012import edu.wpi.first.hal.HAL;
013import edu.wpi.first.hal.HALUtil;
014import edu.wpi.first.hal.LEDJNI;
015import edu.wpi.first.hal.PowerJNI;
016import edu.wpi.first.hal.can.CANJNI;
017import edu.wpi.first.hal.can.CANStatus;
018import edu.wpi.first.units.measure.Current;
019import edu.wpi.first.units.measure.Temperature;
020import edu.wpi.first.units.measure.Time;
021import edu.wpi.first.units.measure.Voltage;
022import java.util.function.LongSupplier;
023
024/** Contains functions for roboRIO functionality. */
025public final class RobotController {
026  private static LongSupplier m_timeSource = RobotController::getFPGATime;
027
028  private RobotController() {
029    throw new UnsupportedOperationException("This is a utility class!");
030  }
031
032  /**
033   * Return the FPGA Version number. For now, expect this to be the current year.
034   *
035   * @return FPGA Version number.
036   */
037  public static int getFPGAVersion() {
038    return HALUtil.getFPGAVersion();
039  }
040
041  /**
042   * Return the FPGA Revision number. The format of the revision is 3 numbers. The 12 most
043   * significant bits are the Major Revision. the next 8 bits are the Minor Revision. The 12 least
044   * significant bits are the Build Number.
045   *
046   * @return FPGA Revision number.
047   */
048  public static long getFPGARevision() {
049    return HALUtil.getFPGARevision();
050  }
051
052  /**
053   * Return the serial number of the roboRIO.
054   *
055   * @return The serial number of the roboRIO.
056   */
057  public static String getSerialNumber() {
058    return HALUtil.getSerialNumber();
059  }
060
061  /**
062   * Return the comments from the roboRIO web interface.
063   *
064   * <p>The comments string is cached after the first call to this function on the RoboRIO - restart
065   * the robot code to reload the comments string after changing it in the web interface.
066   *
067   * @return the comments from the roboRIO web interface.
068   */
069  public static String getComments() {
070    return HALUtil.getComments();
071  }
072
073  /**
074   * Returns the team number configured for the robot controller.
075   *
076   * @return team number, or 0 if not found.
077   */
078  public static int getTeamNumber() {
079    return HALUtil.getTeamNumber();
080  }
081
082  /**
083   * Sets a new source to provide the clock time in microseconds. Changing this affects the return
084   * value of {@code getTime} in Java.
085   *
086   * @param supplier Function to return the time in microseconds.
087   */
088  public static void setTimeSource(LongSupplier supplier) {
089    m_timeSource = supplier;
090  }
091
092  /**
093   * Read the microsecond timestamp. By default, the time is based on the FPGA hardware clock in
094   * microseconds since the FPGA started. However, the return value of this method may be modified
095   * to use any time base, including non-monotonic and non-continuous time bases.
096   *
097   * @return The current time in microseconds.
098   */
099  public static long getTime() {
100    return m_timeSource.getAsLong();
101  }
102
103  /**
104   * Read the microsecond timestamp. By default, the time is based on the FPGA hardware clock in
105   * microseconds since the FPGA started. However, the return value of this method may be modified
106   * to use any time base, including non-monotonic and non-continuous time bases.
107   *
108   * @return The current time in a measure.
109   */
110  public static Time getMeasureTime() {
111    return Microseconds.of(m_timeSource.getAsLong());
112  }
113
114  /**
115   * Read the microsecond timer from the FPGA.
116   *
117   * @return The current time in microseconds according to the FPGA.
118   */
119  public static long getFPGATime() {
120    return HALUtil.getFPGATime();
121  }
122
123  /**
124   * Read the microsecond timer in a measure from the FPGA.
125   *
126   * @return The current time according to the FPGA in a measure.
127   */
128  public static Time getMeasureFPGATime() {
129    return Microseconds.of(HALUtil.getFPGATime());
130  }
131
132  /**
133   * Get the state of the "USER" button on the roboRIO.
134   *
135   * <p>Warning: the User Button is used to stop user programs from automatically loading if it is
136   * held for more then 5 seconds. Because of this, it's not recommended to be used by teams for any
137   * other purpose.
138   *
139   * @return true if the button is currently pressed down
140   */
141  public static boolean getUserButton() {
142    return HALUtil.getFPGAButton();
143  }
144
145  /**
146   * Read the battery voltage.
147   *
148   * @return The battery voltage in Volts.
149   */
150  public static double getBatteryVoltage() {
151    return PowerJNI.getVinVoltage();
152  }
153
154  /**
155   * Read the battery voltage in a measure.
156   *
157   * @return The battery voltage in a measure.
158   */
159  public static Voltage getMeasureBatteryVoltage() {
160    return Volts.of(PowerJNI.getVinVoltage());
161  }
162
163  /**
164   * Gets a value indicating whether the FPGA outputs are enabled. The outputs may be disabled if
165   * the robot is disabled or e-stopped, the watchdog has expired, or if the roboRIO browns out.
166   *
167   * @return True if the FPGA outputs are enabled.
168   */
169  public static boolean isSysActive() {
170    return HAL.getSystemActive();
171  }
172
173  /**
174   * Check if the system is browned out.
175   *
176   * @return True if the system is browned out
177   */
178  public static boolean isBrownedOut() {
179    return HAL.getBrownedOut();
180  }
181
182  /**
183   * Gets the number of times the system has been disabled due to communication errors with the
184   * Driver Station.
185   *
186   * @return number of disables due to communication errors.
187   */
188  public static int getCommsDisableCount() {
189    return HAL.getCommsDisableCount();
190  }
191
192  /**
193   * Gets the current state of the Robot Signal Light (RSL).
194   *
195   * @return The current state of the RSL- true if on, false if off
196   */
197  public static boolean getRSLState() {
198    return HAL.getRSLState();
199  }
200
201  /**
202   * Gets if the system time is valid.
203   *
204   * @return True if the system time is valid, false otherwise
205   */
206  public static boolean isSystemTimeValid() {
207    return HAL.getSystemTimeValid();
208  }
209
210  /**
211   * Get the input voltage to the robot controller.
212   *
213   * @return The controller input voltage value in Volts
214   */
215  public static double getInputVoltage() {
216    return PowerJNI.getVinVoltage();
217  }
218
219  /**
220   * Get the input voltage to the robot controller in a measure.
221   *
222   * @return The controller input voltage value in a measure.
223   */
224  public static Voltage getMeasureInputVoltage() {
225    return Volts.of(PowerJNI.getVinVoltage());
226  }
227
228  /**
229   * Get the input current to the robot controller.
230   *
231   * @return The controller input current value in Amps
232   */
233  public static double getInputCurrent() {
234    return PowerJNI.getVinCurrent();
235  }
236
237  /**
238   * Get the input current to the robot controller in a measure.
239   *
240   * @return The controller input current value in a measure.
241   */
242  public static Current getMeasureInputCurrent() {
243    return Amps.of(PowerJNI.getVinCurrent());
244  }
245
246  /**
247   * Get the voltage of the 3.3V rail.
248   *
249   * @return The controller 3.3V rail voltage value in Volts
250   */
251  public static double getVoltage3V3() {
252    return PowerJNI.getUserVoltage3V3();
253  }
254
255  /**
256   * Get the voltage in a measure of the 3.3V rail.
257   *
258   * @return The controller 3.3V rail voltage value in a measure.
259   */
260  public static Voltage getMeasureVoltage3V3() {
261    return Volts.of(PowerJNI.getUserVoltage3V3());
262  }
263
264  /**
265   * Get the current output of the 3.3V rail.
266   *
267   * @return The controller 3.3V rail output current value in Amps
268   */
269  public static double getCurrent3V3() {
270    return PowerJNI.getUserCurrent3V3();
271  }
272
273  /**
274   * Get the current output in a measure of the 3.3V rail.
275   *
276   * @return The controller 3.3V rail output current value in a measure.
277   */
278  public static Current getMeasureCurrent3V3() {
279    return Amps.of(PowerJNI.getUserCurrent3V3());
280  }
281
282  /**
283   * Enables or disables the 3.3V rail.
284   *
285   * @param enabled whether to enable the 3.3V rail.
286   */
287  public static void setEnabled3V3(boolean enabled) {
288    PowerJNI.setUserEnabled3V3(enabled);
289  }
290
291  /**
292   * Get the enabled state of the 3.3V rail. The rail may be disabled due to a controller brownout,
293   * a short circuit on the rail, or controller over-voltage.
294   *
295   * @return The controller 3.3V rail enabled value
296   */
297  public static boolean getEnabled3V3() {
298    return PowerJNI.getUserActive3V3();
299  }
300
301  /**
302   * Get the count of the total current faults on the 3.3V rail since the code started.
303   *
304   * @return The number of faults
305   */
306  public static int getFaultCount3V3() {
307    return PowerJNI.getUserCurrentFaults3V3();
308  }
309
310  /**
311   * Get the voltage of the 5V rail.
312   *
313   * @return The controller 5V rail voltage value in Volts
314   */
315  public static double getVoltage5V() {
316    return PowerJNI.getUserVoltage5V();
317  }
318
319  /**
320   * Get the voltage in a measure of the 5V rail.
321   *
322   * @return The controller 5V rail voltage value in a measure.
323   */
324  public static Voltage getMeasureVoltage5V() {
325    return Volts.of(PowerJNI.getUserVoltage5V());
326  }
327
328  /**
329   * Get the current output of the 5V rail.
330   *
331   * @return The controller 5V rail output current value in Amps
332   */
333  public static double getCurrent5V() {
334    return PowerJNI.getUserCurrent5V();
335  }
336
337  /**
338   * Get the current output in a measure of the 5V rail.
339   *
340   * @return The controller 5V rail output current value in a measure.
341   */
342  public static Current getMeasureCurrent5V() {
343    return Amps.of(PowerJNI.getUserCurrent5V());
344  }
345
346  /**
347   * Enables or disables the 5V rail.
348   *
349   * @param enabled whether to enable the 5V rail.
350   */
351  public static void setEnabled5V(boolean enabled) {
352    PowerJNI.setUserEnabled5V(enabled);
353  }
354
355  /**
356   * Get the enabled state of the 5V rail. The rail may be disabled due to a controller brownout, a
357   * short circuit on the rail, or controller over-voltage.
358   *
359   * @return The controller 5V rail enabled value
360   */
361  public static boolean getEnabled5V() {
362    return PowerJNI.getUserActive5V();
363  }
364
365  /**
366   * Get the count of the total current faults on the 5V rail since the code started.
367   *
368   * @return The number of faults
369   */
370  public static int getFaultCount5V() {
371    return PowerJNI.getUserCurrentFaults5V();
372  }
373
374  /**
375   * Get the voltage of the 6V rail.
376   *
377   * @return The controller 6V rail voltage value in Volts
378   */
379  public static double getVoltage6V() {
380    return PowerJNI.getUserVoltage6V();
381  }
382
383  /**
384   * Get the voltage in a measure of the 6V rail.
385   *
386   * @return The controller 6V rail voltage value in a measure.
387   */
388  public static Voltage getMeasureVoltage6V() {
389    return Volts.of(PowerJNI.getUserVoltage6V());
390  }
391
392  /**
393   * Get the current output of the 6V rail.
394   *
395   * @return The controller 6V rail output current value in Amps
396   */
397  public static double getCurrent6V() {
398    return PowerJNI.getUserCurrent6V();
399  }
400
401  /**
402   * Get the current output in a measure of the 6V rail.
403   *
404   * @return The controller 6V rail output current value in a measure.
405   */
406  public static Current getMeasureCurrent6V() {
407    return Amps.of(PowerJNI.getUserCurrent6V());
408  }
409
410  /**
411   * Enables or disables the 6V rail.
412   *
413   * @param enabled whether to enable the 6V rail.
414   */
415  public static void setEnabled6V(boolean enabled) {
416    PowerJNI.setUserEnabled6V(enabled);
417  }
418
419  /**
420   * Get the enabled state of the 6V rail. The rail may be disabled due to a controller brownout, a
421   * short circuit on the rail, or controller over-voltage.
422   *
423   * @return The controller 6V rail enabled value
424   */
425  public static boolean getEnabled6V() {
426    return PowerJNI.getUserActive6V();
427  }
428
429  /**
430   * Get the count of the total current faults on the 6V rail since the code started.
431   *
432   * @return The number of faults
433   */
434  public static int getFaultCount6V() {
435    return PowerJNI.getUserCurrentFaults6V();
436  }
437
438  /** Reset the overcurrent fault counters for all user rails to 0. */
439  public static void resetRailFaultCounts() {
440    PowerJNI.resetUserCurrentFaults();
441  }
442
443  /**
444   * Get the current brownout voltage setting.
445   *
446   * @return The brownout voltage
447   */
448  public static double getBrownoutVoltage() {
449    return PowerJNI.getBrownoutVoltage();
450  }
451
452  /**
453   * Get the current brownout voltage setting in a measure.
454   *
455   * @return The brownout voltage in a measure.
456   */
457  public static Voltage getMeasureBrownoutVoltage() {
458    return Volts.of(PowerJNI.getBrownoutVoltage());
459  }
460
461  /**
462   * Set the voltage the roboRIO will brownout and disable all outputs.
463   *
464   * <p>Note that this only does anything on the roboRIO 2. On the roboRIO it is a no-op.
465   *
466   * @param brownoutVoltage The brownout voltage
467   */
468  public static void setBrownoutVoltage(double brownoutVoltage) {
469    PowerJNI.setBrownoutVoltage(brownoutVoltage);
470  }
471
472  /**
473   * Set the voltage in a measure the roboRIO will brownout and disable all outputs.
474   *
475   * <p>Note that this only does anything on the roboRIO 2. On the roboRIO it is a no-op.
476   *
477   * @param brownoutVoltage The brownout voltage in a measure
478   */
479  public static void setBrownoutVoltage(Voltage brownoutVoltage) {
480    PowerJNI.setBrownoutVoltage(brownoutVoltage.baseUnitMagnitude());
481  }
482
483  /**
484   * Get the current CPU temperature in degrees Celsius.
485   *
486   * @return current CPU temperature in degrees Celsius
487   */
488  public static double getCPUTemp() {
489    return PowerJNI.getCPUTemp();
490  }
491
492  /**
493   * Get the current CPU temperature in a measure.
494   *
495   * @return current CPU temperature in a measure.
496   */
497  public static Temperature getMeasureCPUTemp() {
498    return Celsius.of(PowerJNI.getCPUTemp());
499  }
500
501  /** State for the radio led. */
502  public enum RadioLEDState {
503    /** Off. */
504    kOff(LEDJNI.RADIO_LED_STATE_OFF),
505    /** Green. */
506    kGreen(LEDJNI.RADIO_LED_STATE_GREEN),
507    /** Red. */
508    kRed(LEDJNI.RADIO_LED_STATE_RED),
509    /** Orange. */
510    kOrange(LEDJNI.RADIO_LED_STATE_ORANGE);
511
512    /** The native value for this state. */
513    public final int value;
514
515    RadioLEDState(int value) {
516      this.value = value;
517    }
518
519    /**
520     * Gets a state from an int value.
521     *
522     * @param value int value
523     * @return state
524     */
525    public static RadioLEDState fromValue(int value) {
526      return switch (value) {
527        case LEDJNI.RADIO_LED_STATE_OFF -> RadioLEDState.kOff;
528        case LEDJNI.RADIO_LED_STATE_GREEN -> RadioLEDState.kGreen;
529        case LEDJNI.RADIO_LED_STATE_RED -> RadioLEDState.kRed;
530        case LEDJNI.RADIO_LED_STATE_ORANGE -> RadioLEDState.kOrange;
531        default -> RadioLEDState.kOff;
532      };
533    }
534  }
535
536  /**
537   * Set the state of the "Radio" LED. On the RoboRIO, this writes to sysfs, so this function should
538   * not be called multiple times per loop cycle to avoid overruns.
539   *
540   * @param state The state to set the LED to.
541   */
542  public static void setRadioLEDState(RadioLEDState state) {
543    LEDJNI.setRadioLEDState(state.value);
544  }
545
546  /**
547   * Get the state of the "Radio" LED. On the RoboRIO, this reads from sysfs, so this function
548   * should not be called multiple times per loop cycle to avoid overruns.
549   *
550   * @return The state of the LED.
551   */
552  public static RadioLEDState getRadioLEDState() {
553    return RadioLEDState.fromValue(LEDJNI.getRadioLEDState());
554  }
555
556  /**
557   * Get the current status of the CAN bus.
558   *
559   * @return The status of the CAN bus
560   */
561  public static CANStatus getCANStatus() {
562    CANStatus status = new CANStatus();
563    CANJNI.getCANStatus(status);
564    return status;
565  }
566}