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/UsageReporting.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 /** A callback to be run by IterativeRobotBase prior to the user's simulationPeriodic code. */ 086 public static final class SimPeriodicBeforeCallback implements AutoCloseable { 087 private SimPeriodicBeforeCallback(Runnable r) { 088 m_run = r; 089 } 090 091 @Override 092 public void close() { 093 synchronized (s_simPeriodicBefore) { 094 s_simPeriodicBefore.remove(m_run); 095 } 096 } 097 098 private final Runnable m_run; 099 } 100 101 /** 102 * Registers a callback to be run by IterativeRobotBase prior to the user's simulationPeriodic 103 * code. 104 * 105 * @param r runnable 106 * @return Callback object (must be retained for callback to stay active). 107 */ 108 public static SimPeriodicBeforeCallback registerSimPeriodicBeforeCallback(Runnable r) { 109 synchronized (s_simPeriodicBefore) { 110 s_simPeriodicBefore.add(r); 111 } 112 return new SimPeriodicBeforeCallback(r); 113 } 114 115 /** 116 * Runs SimPeriodicBefore callbacks. IterativeRobotBase calls this prior to the user's 117 * simulationPeriodic code. 118 */ 119 public static void simPeriodicBefore() { 120 simPeriodicBeforeNative(); 121 synchronized (s_simPeriodicBefore) { 122 for (Runnable r : s_simPeriodicBefore) { 123 r.run(); 124 } 125 } 126 } 127 128 private static native void simPeriodicAfterNative(); 129 130 private static final List<Runnable> s_simPeriodicAfter = new ArrayList<>(); 131 132 /** A callback to be run by IterativeRobotBase after the user's simulationPeriodic code. */ 133 public static final class SimPeriodicAfterCallback implements AutoCloseable { 134 private SimPeriodicAfterCallback(Runnable r) { 135 m_run = r; 136 } 137 138 @Override 139 public void close() { 140 synchronized (s_simPeriodicAfter) { 141 s_simPeriodicAfter.remove(m_run); 142 } 143 } 144 145 private final Runnable m_run; 146 } 147 148 /** 149 * Registers a callback to be run by IterativeRobotBase after the user's simulationPeriodic code. 150 * 151 * @param r runnable 152 * @return Callback object (must be retained for callback to stay active). 153 */ 154 public static SimPeriodicAfterCallback registerSimPeriodicAfterCallback(Runnable r) { 155 synchronized (s_simPeriodicAfter) { 156 s_simPeriodicAfter.add(r); 157 } 158 return new SimPeriodicAfterCallback(r); 159 } 160 161 /** 162 * Runs SimPeriodicAfter callbacks. IterativeRobotBase calls this after the user's 163 * simulationPeriodic code. 164 */ 165 public static void simPeriodicAfter() { 166 simPeriodicAfterNative(); 167 synchronized (s_simPeriodicAfter) { 168 for (Runnable r : s_simPeriodicAfter) { 169 r.run(); 170 } 171 } 172 } 173 174 /** 175 * Gets if the system is in a browned out state. 176 * 177 * @return true if the system is in a low voltage brown out, false otherwise 178 * @see "HAL_GetBrownedOut" 179 */ 180 public static native boolean getBrownedOut(); 181 182 /** 183 * Gets if the system outputs are currently active. 184 * 185 * @return true if the system outputs are active, false if disabled 186 * @see "HAL_GetSystemActive" 187 */ 188 public static native boolean getSystemActive(); 189 190 /** 191 * Gets the current state of the Robot Signal Light (RSL). 192 * 193 * @return The current state of the RSL- true if on, false if off 194 * @see "HAL_GetRSLState" 195 */ 196 public static native boolean getRSLState(); 197 198 /** 199 * Gets the number of times the system has been disabled due to communication errors with the 200 * Driver Station. 201 * 202 * @return number of disables due to communication errors. 203 */ 204 public static native int getCommsDisableCount(); 205 206 /** 207 * Gets if the system time is valid. 208 * 209 * @return True if the system time is valid, false otherwise 210 * @see "HAL_GetSystemTimeValid" 211 */ 212 public static native boolean getSystemTimeValid(); 213 214 /** 215 * Reports usage of a resource of interest. Repeated calls for the same resource name replace the 216 * previous report. 217 * 218 * @param resource the used resource name 219 * @param data arbitrary associated data string 220 * @return a handle 221 */ 222 public static int reportUsage(String resource, String data) { 223 return UsageReportingJNI.report(resource, data); 224 } 225 226 /** 227 * Reports usage of a resource of interest. Repeated calls for the same resource name replace the 228 * previous report. 229 * 230 * @param resource the used resource name 231 * @param instanceNumber an index that identifies the resource instance 232 * @param data arbitrary associated data string 233 * @return a handle 234 */ 235 public static int reportUsage(String resource, int instanceNumber, String data) { 236 return reportUsage(resource + "[" + instanceNumber + "]", data); 237 } 238 239 private HAL() {} 240}