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 org.wpilib.hardware.hal; 006 007import java.util.ArrayList; 008import java.util.List; 009 010/** 011 * JNI Wrapper for Hardware Abstraction Layer (HAL). 012 * 013 * @see "wpi/hal/HALBase.h" 014 * @see "wpi/hal/Main.h" 015 */ 016public final class HAL extends JNIWrapper { 017 /** 018 * Call this to start up HAL. This is required for robot programs. 019 * 020 * <p>This must be called before any other HAL functions. Failure to do so will result in 021 * undefined behavior, and likely segmentation faults. This means that any statically initialized 022 * variables in a program MUST call this function in their constructors if they want to use other 023 * HAL calls. 024 * 025 * <p>The common parameters are 500 for timeout and 0 for mode. 026 * 027 * <p>This function is safe to call from any thread, and as many times as you wish. It internally 028 * guards from any reentrancy. 029 * 030 * <p>The applicable modes are: 0: Try to kill an existing HAL from another program, if not 031 * successful, error. 1: Force kill a HAL from another program. 2: Just warn if another hal exists 032 * and cannot be killed. Will likely result in undefined behavior. 033 * 034 * @param timeout the initialization timeout (ms) 035 * @param mode the initialization mode (see remarks) 036 * @return true if initialization was successful, otherwise false. 037 * @see "HAL_Initialize" 038 */ 039 public static native boolean initialize(int timeout, int mode); 040 041 /** 042 * Call this to shut down HAL. 043 * 044 * <p>This must be called at termination of the robot program to avoid potential segmentation 045 * faults with simulation extensions at exit. 046 * 047 * @see "HAL_Shutdown" 048 */ 049 public static native void shutdown(); 050 051 /** 052 * Returns true if HAL_SetMain() has been called. 053 * 054 * @return True if HAL_SetMain() has been called, false otherwise. 055 * @see "HAL_HasMain" 056 */ 057 public static native boolean hasMain(); 058 059 /** 060 * Runs the main function provided to HAL_SetMain(). 061 * 062 * <p>If HAL_SetMain() has not been called, simply sleeps until exitMain() is called. 063 * 064 * @see "HAL_RunMain" 065 */ 066 public static native void runMain(); 067 068 /** 069 * Causes HAL_RunMain() to exit. 070 * 071 * <p>If HAL_SetMain() has been called, this calls the exit function provided to that function. 072 * 073 * @see "HAL_ExitMain" 074 */ 075 public static native void exitMain(); 076 077 /** Terminates the executable (at the native level). Does nothing in simulation. */ 078 public static native void terminate(); 079 080 private static native void simPeriodicBeforeNative(); 081 082 private static final List<Runnable> s_simPeriodicBefore = new ArrayList<>(); 083 084 /** A callback to be run by IterativeRobotBase prior to the user's simulationPeriodic code. */ 085 public static final 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 /** A callback to be run by IterativeRobotBase after the user's simulationPeriodic code. */ 132 public static final class SimPeriodicAfterCallback implements AutoCloseable { 133 private SimPeriodicAfterCallback(Runnable r) { 134 m_run = r; 135 } 136 137 @Override 138 public void close() { 139 synchronized (s_simPeriodicAfter) { 140 s_simPeriodicAfter.remove(m_run); 141 } 142 } 143 144 private final Runnable m_run; 145 } 146 147 /** 148 * Registers a callback to be run by IterativeRobotBase after the user's simulationPeriodic code. 149 * 150 * @param r runnable 151 * @return Callback object (must be retained for callback to stay active). 152 */ 153 public static SimPeriodicAfterCallback registerSimPeriodicAfterCallback(Runnable r) { 154 synchronized (s_simPeriodicAfter) { 155 s_simPeriodicAfter.add(r); 156 } 157 return new SimPeriodicAfterCallback(r); 158 } 159 160 /** 161 * Runs SimPeriodicAfter callbacks. IterativeRobotBase calls this after the user's 162 * simulationPeriodic code. 163 */ 164 public static void simPeriodicAfter() { 165 simPeriodicAfterNative(); 166 synchronized (s_simPeriodicAfter) { 167 for (Runnable r : s_simPeriodicAfter) { 168 r.run(); 169 } 170 } 171 } 172 173 /** 174 * Gets if the system is in a browned out state. 175 * 176 * @return true if the system is in a low voltage brown out, false otherwise 177 * @see "HAL_GetBrownedOut" 178 */ 179 public static native boolean getBrownedOut(); 180 181 /** 182 * Gets if the system outputs are currently active. 183 * 184 * @return true if the system outputs are active, false if disabled 185 * @see "HAL_GetSystemActive" 186 */ 187 public static native boolean getSystemActive(); 188 189 /** 190 * Gets the current state of the Robot Signal Light (RSL). 191 * 192 * @return The current state of the RSL- true if on, false if off 193 * @see "HAL_GetRSLState" 194 */ 195 public static native boolean getRSLState(); 196 197 /** 198 * Gets the number of times the system has been disabled due to communication errors with the 199 * Driver Station. 200 * 201 * @return number of disables due to communication errors. 202 */ 203 public static native int getCommsDisableCount(); 204 205 /** 206 * Gets if the system time is valid. 207 * 208 * @return True if the system time is valid, false otherwise 209 * @see "HAL_GetSystemTimeValid" 210 */ 211 public static native boolean getSystemTimeValid(); 212 213 /** 214 * Reports usage of a resource of interest. Repeated calls for the same resource name replace the 215 * previous report. 216 * 217 * @param resource the used resource name 218 * @param data arbitrary associated data string 219 */ 220 public static void reportUsage(String resource, String data) { 221 UsageReportingJNI.report(resource, data); 222 } 223 224 /** 225 * Reports usage of a resource of interest. Repeated calls for the same resource name replace the 226 * previous report. 227 * 228 * @param resource the used resource name 229 * @param instanceNumber an index that identifies the resource instance 230 * @param data arbitrary associated data string 231 */ 232 public static void reportUsage(String resource, int instanceNumber, String data) { 233 reportUsage(resource + "[" + instanceNumber + "]", data); 234 } 235 236 private HAL() {} 237}