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