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}