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  private static native void simPeriodicBeforeNative();
079
080  private static final List<Runnable> s_simPeriodicBefore = new ArrayList<>();
081
082  public static class SimPeriodicBeforeCallback implements AutoCloseable {
083    private SimPeriodicBeforeCallback(Runnable r) {
084      m_run = r;
085    }
086
087    @Override
088    public void close() {
089      synchronized (s_simPeriodicBefore) {
090        s_simPeriodicBefore.remove(m_run);
091      }
092    }
093
094    private final Runnable m_run;
095  }
096
097  /**
098   * Registers a callback to be run by IterativeRobotBase prior to the user's simulationPeriodic
099   * code.
100   *
101   * @param r runnable
102   * @return Callback object (must be retained for callback to stay active).
103   */
104  public static SimPeriodicBeforeCallback registerSimPeriodicBeforeCallback(Runnable r) {
105    synchronized (s_simPeriodicBefore) {
106      s_simPeriodicBefore.add(r);
107    }
108    return new SimPeriodicBeforeCallback(r);
109  }
110
111  /**
112   * Runs SimPeriodicBefore callbacks. IterativeRobotBase calls this prior to the user's
113   * simulationPeriodic code.
114   */
115  public static void simPeriodicBefore() {
116    simPeriodicBeforeNative();
117    synchronized (s_simPeriodicBefore) {
118      for (Runnable r : s_simPeriodicBefore) {
119        r.run();
120      }
121    }
122  }
123
124  private static native void simPeriodicAfterNative();
125
126  private static final List<Runnable> s_simPeriodicAfter = new ArrayList<>();
127
128  public static class SimPeriodicAfterCallback implements AutoCloseable {
129    private SimPeriodicAfterCallback(Runnable r) {
130      m_run = r;
131    }
132
133    @Override
134    public void close() {
135      synchronized (s_simPeriodicAfter) {
136        s_simPeriodicAfter.remove(m_run);
137      }
138    }
139
140    private final Runnable m_run;
141  }
142
143  /**
144   * Registers a callback to be run by IterativeRobotBase after the user's simulationPeriodic code.
145   *
146   * @param r runnable
147   * @return Callback object (must be retained for callback to stay active).
148   */
149  public static SimPeriodicAfterCallback registerSimPeriodicAfterCallback(Runnable r) {
150    synchronized (s_simPeriodicAfter) {
151      s_simPeriodicAfter.add(r);
152    }
153    return new SimPeriodicAfterCallback(r);
154  }
155
156  /**
157   * Runs SimPeriodicAfter callbacks. IterativeRobotBase calls this after the user's
158   * simulationPeriodic code.
159   */
160  public static void simPeriodicAfter() {
161    simPeriodicAfterNative();
162    synchronized (s_simPeriodicAfter) {
163      for (Runnable r : s_simPeriodicAfter) {
164        r.run();
165      }
166    }
167  }
168
169  /**
170   * Gets if the system is in a browned out state.
171   *
172   * @return true if the system is in a low voltage brown out, false otherwise
173   * @see "HAL_GetBrownedOut"
174   */
175  public static native boolean getBrownedOut();
176
177  /**
178   * Gets if the system outputs are currently active.
179   *
180   * @return true if the system outputs are active, false if disabled
181   * @see "HAL_GetSystemActive"
182   */
183  public static native boolean getSystemActive();
184
185  /**
186   * Gets the current state of the Robot Signal Light (RSL).
187   *
188   * @return The current state of the RSL- true if on, false if off
189   * @see "HAL_GetRSLState"
190   */
191  public static native boolean getRSLState();
192
193  /**
194   * Gets if the system time is valid.
195   *
196   * @return True if the system time is valid, false otherwise
197   * @see "HAL_GetSystemTimeValid"
198   */
199  public static native boolean getSystemTimeValid();
200
201  /**
202   * Gets a port handle for a specific channel and module.
203   *
204   * <p>This is expected to be used for PCMs, as the roboRIO does not work with modules anymore.
205   *
206   * <p>The created handle does not need to be freed.
207   *
208   * @param module the module number
209   * @param channel the channel number
210   * @return the created port
211   * @see "HAL_GetPortWithModule"
212   */
213  public static native int getPortWithModule(byte module, byte channel);
214
215  /**
216   * Gets a port handle for a specific channel.
217   *
218   * <p>The created handle does not need to be freed.
219   *
220   * @param channel the channel number
221   * @return the created port
222   * @see "HAL_GetPort"
223   */
224  public static native int getPort(byte channel);
225
226  /**
227   * Report the usage of a resource of interest.
228   *
229   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
230   * char*)</code>
231   *
232   * @param resource one of the values in the tResourceType above.
233   * @param instanceNumber an index that identifies the resource instance.
234   * @see "HAL_Report"
235   */
236  public static void report(int resource, int instanceNumber) {
237    report(resource, instanceNumber, 0, "");
238  }
239
240  /**
241   * Report the usage of a resource of interest.
242   *
243   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
244   * char*)</code>
245   *
246   * @param resource one of the values in the tResourceType above.
247   * @param instanceNumber an index that identifies the resource instance.
248   * @param context an optional additional context number for some cases (such as module number).
249   *     Set to 0 to omit.
250   * @see "HAL_Report"
251   */
252  public static void report(int resource, int instanceNumber, int context) {
253    report(resource, instanceNumber, context, "");
254  }
255
256  /**
257   * Report the usage of a resource of interest.
258   *
259   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
260   * char*)</code>
261   *
262   * @param resource one of the values in the tResourceType above.
263   * @param instanceNumber an index that identifies the resource instance.
264   * @param context an optional additional context number for some cases (such as module number).
265   *     Set to 0 to omit.
266   * @param feature a string to be included describing features in use on a specific resource.
267   *     Setting the same resource more than once allows you to change the feature string.
268   * @return the index of the added value in NetComm
269   * @see "HAL_Report"
270   */
271  public static int report(int resource, int instanceNumber, int context, String feature) {
272    return DriverStationJNI.report(resource, instanceNumber, context, feature);
273  }
274
275  private HAL() {}
276}