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}