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