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 a port handle for a specific channel and module.
195   *
196   * <p>This is expected to be used for PCMs, as the roboRIO does not work with modules anymore.
197   *
198   * <p>The created handle does not need to be freed.
199   *
200   * @param module the module number
201   * @param channel the channel number
202   * @return the created port
203   * @see "HAL_GetPortWithModule"
204   */
205  public static native int getPortWithModule(byte module, byte channel);
206
207  /**
208   * Gets a port handle for a specific channel.
209   *
210   * <p>The created handle does not need to be freed.
211   *
212   * @param channel the channel number
213   * @return the created port
214   * @see "HAL_GetPort"
215   */
216  public static native int getPort(byte channel);
217
218  /**
219   * Report the usage of a resource of interest.
220   *
221   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
222   * char*)</code>
223   *
224   * @param resource one of the values in the tResourceType above.
225   * @param instanceNumber an index that identifies the resource instance.
226   * @see "HAL_Report"
227   */
228  public static void report(int resource, int instanceNumber) {
229    report(resource, instanceNumber, 0, "");
230  }
231
232  /**
233   * Report the usage of a resource of interest.
234   *
235   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
236   * char*)</code>
237   *
238   * @param resource one of the values in the tResourceType above.
239   * @param instanceNumber an index that identifies the resource instance.
240   * @param context an optional additional context number for some cases (such as module number).
241   *     Set to 0 to omit.
242   * @see "HAL_Report"
243   */
244  public static void report(int resource, int instanceNumber, int context) {
245    report(resource, instanceNumber, context, "");
246  }
247
248  /**
249   * Report the usage of a resource of interest.
250   *
251   * <p>Original signature: <code>uint32_t report(tResourceType, uint8_t, uint8_t, const
252   * char*)</code>
253   *
254   * @param resource one of the values in the tResourceType above.
255   * @param instanceNumber an index that identifies the resource instance.
256   * @param context an optional additional context number for some cases (such as module number).
257   *     Set to 0 to omit.
258   * @param feature a string to be included describing features in use on a specific resource.
259   *     Setting the same resource more than once allows you to change the feature string.
260   * @return the index of the added value in NetComm
261   * @see "HAL_Report"
262   */
263  public static int report(int resource, int instanceNumber, int context, String feature) {
264    return DriverStationJNI.report(resource, instanceNumber, context, feature);
265  }
266
267  private HAL() {}
268}