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 org.wpilib.hardware.hal;
006
007import java.util.ArrayList;
008import java.util.List;
009
010/**
011 * JNI Wrapper for Hardware Abstraction Layer (HAL).
012 *
013 * @see "wpi/hal/HALBase.h"
014 * @see "wpi/hal/Main.h"
015 */
016public final class HAL extends JNIWrapper {
017  /**
018   * Call this to start up HAL. This is required for robot programs.
019   *
020   * <p>This must be called before any other HAL functions. Failure to do so will result in
021   * undefined behavior, and likely segmentation faults. This means that any statically initialized
022   * variables in a program MUST call this function in their constructors if they want to use other
023   * HAL calls.
024   *
025   * <p>The common parameters are 500 for timeout and 0 for mode.
026   *
027   * <p>This function is safe to call from any thread, and as many times as you wish. It internally
028   * guards from any reentrancy.
029   *
030   * <p>The applicable modes are: 0: Try to kill an existing HAL from another program, if not
031   * successful, error. 1: Force kill a HAL from another program. 2: Just warn if another hal exists
032   * and cannot be killed. Will likely result in undefined behavior.
033   *
034   * @param timeout the initialization timeout (ms)
035   * @param mode the initialization mode (see remarks)
036   * @return true if initialization was successful, otherwise false.
037   * @see "HAL_Initialize"
038   */
039  public static native boolean initialize(int timeout, int mode);
040
041  /**
042   * Call this to shut down HAL.
043   *
044   * <p>This must be called at termination of the robot program to avoid potential segmentation
045   * faults with simulation extensions at exit.
046   *
047   * @see "HAL_Shutdown"
048   */
049  public static native void shutdown();
050
051  /**
052   * Returns true if HAL_SetMain() has been called.
053   *
054   * @return True if HAL_SetMain() has been called, false otherwise.
055   * @see "HAL_HasMain"
056   */
057  public static native boolean hasMain();
058
059  /**
060   * Runs the main function provided to HAL_SetMain().
061   *
062   * <p>If HAL_SetMain() has not been called, simply sleeps until exitMain() is called.
063   *
064   * @see "HAL_RunMain"
065   */
066  public static native void runMain();
067
068  /**
069   * Causes HAL_RunMain() to exit.
070   *
071   * <p>If HAL_SetMain() has been called, this calls the exit function provided to that function.
072   *
073   * @see "HAL_ExitMain"
074   */
075  public static native void exitMain();
076
077  /** Terminates the executable (at the native level). Does nothing in simulation. */
078  public static native void terminate();
079
080  private static native void simPeriodicBeforeNative();
081
082  private static final List<Runnable> s_simPeriodicBefore = new ArrayList<>();
083
084  /** A callback to be run by IterativeRobotBase prior to the user's simulationPeriodic code. */
085  public static final class SimPeriodicBeforeCallback implements AutoCloseable {
086    private SimPeriodicBeforeCallback(Runnable r) {
087      m_run = r;
088    }
089
090    @Override
091    public void close() {
092      synchronized (s_simPeriodicBefore) {
093        s_simPeriodicBefore.remove(m_run);
094      }
095    }
096
097    private final Runnable m_run;
098  }
099
100  /**
101   * Registers a callback to be run by IterativeRobotBase prior to the user's simulationPeriodic
102   * code.
103   *
104   * @param r runnable
105   * @return Callback object (must be retained for callback to stay active).
106   */
107  public static SimPeriodicBeforeCallback registerSimPeriodicBeforeCallback(Runnable r) {
108    synchronized (s_simPeriodicBefore) {
109      s_simPeriodicBefore.add(r);
110    }
111    return new SimPeriodicBeforeCallback(r);
112  }
113
114  /**
115   * Runs SimPeriodicBefore callbacks. IterativeRobotBase calls this prior to the user's
116   * simulationPeriodic code.
117   */
118  public static void simPeriodicBefore() {
119    simPeriodicBeforeNative();
120    synchronized (s_simPeriodicBefore) {
121      for (Runnable r : s_simPeriodicBefore) {
122        r.run();
123      }
124    }
125  }
126
127  private static native void simPeriodicAfterNative();
128
129  private static final List<Runnable> s_simPeriodicAfter = new ArrayList<>();
130
131  /** A callback to be run by IterativeRobotBase after the user's simulationPeriodic code. */
132  public static final class SimPeriodicAfterCallback implements AutoCloseable {
133    private SimPeriodicAfterCallback(Runnable r) {
134      m_run = r;
135    }
136
137    @Override
138    public void close() {
139      synchronized (s_simPeriodicAfter) {
140        s_simPeriodicAfter.remove(m_run);
141      }
142    }
143
144    private final Runnable m_run;
145  }
146
147  /**
148   * Registers a callback to be run by IterativeRobotBase after the user's simulationPeriodic code.
149   *
150   * @param r runnable
151   * @return Callback object (must be retained for callback to stay active).
152   */
153  public static SimPeriodicAfterCallback registerSimPeriodicAfterCallback(Runnable r) {
154    synchronized (s_simPeriodicAfter) {
155      s_simPeriodicAfter.add(r);
156    }
157    return new SimPeriodicAfterCallback(r);
158  }
159
160  /**
161   * Runs SimPeriodicAfter callbacks. IterativeRobotBase calls this after the user's
162   * simulationPeriodic code.
163   */
164  public static void simPeriodicAfter() {
165    simPeriodicAfterNative();
166    synchronized (s_simPeriodicAfter) {
167      for (Runnable r : s_simPeriodicAfter) {
168        r.run();
169      }
170    }
171  }
172
173  /**
174   * Gets if the system is in a browned out state.
175   *
176   * @return true if the system is in a low voltage brown out, false otherwise
177   * @see "HAL_GetBrownedOut"
178   */
179  public static native boolean getBrownedOut();
180
181  /**
182   * Gets if the system outputs are currently active.
183   *
184   * @return true if the system outputs are active, false if disabled
185   * @see "HAL_GetSystemActive"
186   */
187  public static native boolean getSystemActive();
188
189  /**
190   * Gets the current state of the Robot Signal Light (RSL).
191   *
192   * @return The current state of the RSL- true if on, false if off
193   * @see "HAL_GetRSLState"
194   */
195  public static native boolean getRSLState();
196
197  /**
198   * Gets the number of times the system has been disabled due to communication errors with the
199   * Driver Station.
200   *
201   * @return number of disables due to communication errors.
202   */
203  public static native int getCommsDisableCount();
204
205  /**
206   * Gets if the system time is valid.
207   *
208   * @return True if the system time is valid, false otherwise
209   * @see "HAL_GetSystemTimeValid"
210   */
211  public static native boolean getSystemTimeValid();
212
213  /**
214   * Reports usage of a resource of interest. Repeated calls for the same resource name replace the
215   * previous report.
216   *
217   * @param resource the used resource name
218   * @param data arbitrary associated data string
219   */
220  public static void reportUsage(String resource, String data) {
221    UsageReportingJNI.report(resource, data);
222  }
223
224  /**
225   * Reports usage of a resource of interest. Repeated calls for the same resource name replace the
226   * previous report.
227   *
228   * @param resource the used resource name
229   * @param instanceNumber an index that identifies the resource instance
230   * @param data arbitrary associated data string
231   */
232  public static void reportUsage(String resource, int instanceNumber, String data) {
233    reportUsage(resource + "[" + instanceNumber + "]", data);
234  }
235
236  private HAL() {}
237}