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 007/** 008 * A wrapper around a simulator device handle. 009 * 010 * <p>Teams: if you are using this class, you are likely confusing it for {@link 011 * edu.wpi.first.wpilibj.simulation.SimDeviceSim}. 012 * 013 * <p>Vendors: This class should be used from inside the device class to define the 014 * properties/fields of the device. Use {@link #create} to get a SimDevice object, then use {@link 015 * #createDouble(String, Direction, double)} or similar to define the device's fields. See {@link 016 * edu.wpi.first.wpilibj.ADXRS450_Gyro} for an example implementation. 017 */ 018public class SimDevice implements AutoCloseable { 019 public enum Direction { 020 kInput(SimDeviceJNI.kInput), 021 kOutput(SimDeviceJNI.kOutput), 022 kBidir(SimDeviceJNI.kBidir); 023 024 public final int m_value; 025 026 Direction(int value) { 027 m_value = value; 028 } 029 } 030 031 /** 032 * Creates a simulated device. 033 * 034 * <p>The device name must be unique. Returns null if the device name already exists. If multiple 035 * instances of the same device are desired, recommend appending the instance/unique identifer in 036 * brackets to the base name, e.g. "device[1]". 037 * 038 * <p>null is returned if not in simulation. 039 * 040 * @param name device name 041 * @return simulated device object 042 */ 043 public static SimDevice create(String name) { 044 int handle = SimDeviceJNI.createSimDevice(name); 045 if (handle <= 0) { 046 return null; 047 } 048 return new SimDevice(handle); 049 } 050 051 /** 052 * Creates a simulated device. 053 * 054 * <p>The device name must be unique. Returns null if the device name already exists. This is a 055 * convenience method that appends index in brackets to the device name, e.g. passing index=1 056 * results in "device[1]" for the device name. 057 * 058 * <p>null is returned if not in simulation. 059 * 060 * @param name device name 061 * @param index device index number to append to name 062 * @return simulated device object 063 */ 064 public static SimDevice create(String name, int index) { 065 return create(name + "[" + index + "]"); 066 } 067 068 /** 069 * Creates a simulated device. 070 * 071 * <p>The device name must be unique. Returns null if the device name already exists. This is a 072 * convenience method that appends index and channel in brackets to the device name, e.g. passing 073 * index=1 and channel=2 results in "device[1,2]" for the device name. 074 * 075 * <p>null is returned if not in simulation. 076 * 077 * @param name device name 078 * @param index device index number to append to name 079 * @param channel device channel number to append to name 080 * @return simulated device object 081 */ 082 public static SimDevice create(String name, int index, int channel) { 083 return create(name + "[" + index + "," + channel + "]"); 084 } 085 086 /** 087 * Wraps a simulated device handle as returned by SimDeviceJNI.createSimDevice(). 088 * 089 * @param handle simulated device handle 090 */ 091 public SimDevice(int handle) { 092 m_handle = handle; 093 } 094 095 @Override 096 public void close() { 097 SimDeviceJNI.freeSimDevice(m_handle); 098 } 099 100 /** 101 * Get the internal device handle. 102 * 103 * @return internal handle 104 */ 105 public int getNativeHandle() { 106 return m_handle; 107 } 108 109 /** 110 * Creates a value on the simulated device. 111 * 112 * <p>Returns null if not in simulation. 113 * 114 * @param name value name 115 * @param readonly if the value should not be written from simulation side 116 * @param initialValue initial value 117 * @return simulated value object 118 * @deprecated Use direction function instead 119 */ 120 @Deprecated 121 public SimValue createValue(String name, boolean readonly, HALValue initialValue) { 122 return createValue(name, readonly ? Direction.kOutput : Direction.kInput, initialValue); 123 } 124 125 /** 126 * Creates a value on the simulated device. 127 * 128 * <p>Returns null if not in simulation. 129 * 130 * @param name value name 131 * @param direction input/output/bidir (from perspective of user code) 132 * @param initialValue initial value 133 * @return simulated value object 134 */ 135 public SimValue createValue(String name, Direction direction, HALValue initialValue) { 136 int handle = SimDeviceJNI.createSimValue(m_handle, name, direction.m_value, initialValue); 137 if (handle <= 0) { 138 return null; 139 } 140 return new SimValue(handle); 141 } 142 143 /** 144 * Creates an int value on the simulated device. 145 * 146 * <p>Returns null if not in simulation. 147 * 148 * @param name value name 149 * @param direction input/output/bidir (from perspective of user code) 150 * @param initialValue initial value 151 * @return simulated double value object 152 */ 153 public SimInt createInt(String name, Direction direction, int initialValue) { 154 int handle = SimDeviceJNI.createSimValueInt(m_handle, name, direction.m_value, initialValue); 155 if (handle <= 0) { 156 return null; 157 } 158 return new SimInt(handle); 159 } 160 161 /** 162 * Creates a long value on the simulated device. 163 * 164 * <p>Returns null if not in simulation. 165 * 166 * @param name value name 167 * @param direction input/output/bidir (from perspective of user code) 168 * @param initialValue initial value 169 * @return simulated double value object 170 */ 171 public SimLong createLong(String name, Direction direction, long initialValue) { 172 int handle = SimDeviceJNI.createSimValueLong(m_handle, name, direction.m_value, initialValue); 173 if (handle <= 0) { 174 return null; 175 } 176 return new SimLong(handle); 177 } 178 179 /** 180 * Creates a double value on the simulated device. 181 * 182 * <p>Returns null if not in simulation. 183 * 184 * @param name value name 185 * @param readonly if the value should not be written from simulation side 186 * @param initialValue initial value 187 * @return simulated double value object 188 * @deprecated Use direction function instead 189 */ 190 @Deprecated 191 public SimDouble createDouble(String name, boolean readonly, double initialValue) { 192 return createDouble(name, readonly ? Direction.kOutput : Direction.kInput, initialValue); 193 } 194 195 /** 196 * Creates a double value on the simulated device. 197 * 198 * <p>Returns null if not in simulation. 199 * 200 * @param name value name 201 * @param direction input/output/bidir (from perspective of user code) 202 * @param initialValue initial value 203 * @return simulated double value object 204 */ 205 public SimDouble createDouble(String name, Direction direction, double initialValue) { 206 int handle = SimDeviceJNI.createSimValueDouble(m_handle, name, direction.m_value, initialValue); 207 if (handle <= 0) { 208 return null; 209 } 210 return new SimDouble(handle); 211 } 212 213 /** 214 * Creates an enumerated value on the simulated device. 215 * 216 * <p>Enumerated values are always in the range 0 to numOptions-1. 217 * 218 * <p>Returns null if not in simulation. 219 * 220 * @param name value name 221 * @param readonly if the value should not be written from simulation side 222 * @param options array of option descriptions 223 * @param initialValue initial value (selection) 224 * @return simulated enum value object 225 * @deprecated Use direction function instead 226 */ 227 @Deprecated 228 public SimEnum createEnum(String name, boolean readonly, String[] options, int initialValue) { 229 return createEnum(name, readonly ? Direction.kOutput : Direction.kInput, options, initialValue); 230 } 231 232 /** 233 * Creates an enumerated value on the simulated device. 234 * 235 * <p>Enumerated values are always in the range 0 to numOptions-1. 236 * 237 * <p>Returns null if not in simulation. 238 * 239 * @param name value name 240 * @param direction input/output/bidir (from perspective of user code) 241 * @param options array of option descriptions 242 * @param initialValue initial value (selection) 243 * @return simulated enum value object 244 */ 245 public SimEnum createEnum(String name, Direction direction, String[] options, int initialValue) { 246 int handle = 247 SimDeviceJNI.createSimValueEnum(m_handle, name, direction.m_value, options, initialValue); 248 if (handle <= 0) { 249 return null; 250 } 251 return new SimEnum(handle); 252 } 253 254 /** 255 * Creates an enumerated value on the simulated device with double values. 256 * 257 * <p>Enumerated values are always in the range 0 to numOptions-1. 258 * 259 * <p>Returns null if not in simulation. 260 * 261 * @param name value name 262 * @param direction input/output/bidir (from perspective of user code) 263 * @param options array of option descriptions 264 * @param optionValues array of option values (must be the same size as options) 265 * @param initialValue initial value (selection) 266 * @return simulated enum value object 267 */ 268 public SimEnum createEnumDouble( 269 String name, Direction direction, String[] options, double[] optionValues, int initialValue) { 270 int handle = 271 SimDeviceJNI.createSimValueEnumDouble( 272 m_handle, name, direction.m_value, options, optionValues, initialValue); 273 if (handle <= 0) { 274 return null; 275 } 276 return new SimEnum(handle); 277 } 278 279 /** 280 * Creates a boolean value on the simulated device. 281 * 282 * <p>Returns null if not in simulation. 283 * 284 * @param name value name 285 * @param readonly if the value should not be written from simulation side 286 * @param initialValue initial value 287 * @return simulated boolean value object 288 * @deprecated Use direction function instead 289 */ 290 @Deprecated 291 public SimBoolean createBoolean(String name, boolean readonly, boolean initialValue) { 292 return createBoolean(name, readonly ? Direction.kOutput : Direction.kInput, initialValue); 293 } 294 295 /** 296 * Creates a boolean value on the simulated device. 297 * 298 * <p>Returns null if not in simulation. 299 * 300 * @param name value name 301 * @param direction input/output/bidir (from perspective of user code) 302 * @param initialValue initial value 303 * @return simulated boolean value object 304 */ 305 public SimBoolean createBoolean(String name, Direction direction, boolean initialValue) { 306 int handle = 307 SimDeviceJNI.createSimValueBoolean(m_handle, name, direction.m_value, initialValue); 308 if (handle <= 0) { 309 return null; 310 } 311 return new SimBoolean(handle); 312 } 313 314 private final int m_handle; 315}