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 /** Sim device direction. */ 020 public enum Direction { 021 /** Input direction for simulation devices. */ 022 kInput(SimDeviceJNI.kInput), 023 /** Output direction for simulation devices. */ 024 kOutput(SimDeviceJNI.kOutput), 025 /** Bidirectional direction for simulation devices. */ 026 kBidir(SimDeviceJNI.kBidir); 027 028 public final int m_value; 029 030 Direction(int value) { 031 m_value = value; 032 } 033 } 034 035 /** 036 * Creates a simulated device. 037 * 038 * <p>The device name must be unique. Returns null if the device name already exists. If multiple 039 * instances of the same device are desired, recommend appending the instance/unique identifier in 040 * brackets to the base name, e.g. "device[1]". 041 * 042 * <p>null is returned if not in simulation. 043 * 044 * @param name device name 045 * @return simulated device object 046 */ 047 public static SimDevice create(String name) { 048 int handle = SimDeviceJNI.createSimDevice(name); 049 if (handle <= 0) { 050 return null; 051 } 052 return new SimDevice(handle); 053 } 054 055 /** 056 * Creates a simulated device. 057 * 058 * <p>The device name must be unique. Returns null if the device name already exists. This is a 059 * convenience method that appends index in brackets to the device name, e.g. passing index=1 060 * results in "device[1]" for the device name. 061 * 062 * <p>null is returned if not in simulation. 063 * 064 * @param name device name 065 * @param index device index number to append to name 066 * @return simulated device object 067 */ 068 public static SimDevice create(String name, int index) { 069 return create(name + "[" + index + "]"); 070 } 071 072 /** 073 * Creates a simulated device. 074 * 075 * <p>The device name must be unique. Returns null if the device name already exists. This is a 076 * convenience method that appends index and channel in brackets to the device name, e.g. passing 077 * index=1 and channel=2 results in "device[1,2]" for the device name. 078 * 079 * <p>null is returned if not in simulation. 080 * 081 * @param name device name 082 * @param index device index number to append to name 083 * @param channel device channel number to append to name 084 * @return simulated device object 085 */ 086 public static SimDevice create(String name, int index, int channel) { 087 return create(name + "[" + index + "," + channel + "]"); 088 } 089 090 /** 091 * Wraps a simulated device handle as returned by SimDeviceJNI.createSimDevice(). 092 * 093 * @param handle simulated device handle 094 */ 095 public SimDevice(int handle) { 096 m_handle = handle; 097 } 098 099 @Override 100 public void close() { 101 SimDeviceJNI.freeSimDevice(m_handle); 102 } 103 104 /** 105 * Get the internal device handle. 106 * 107 * @return internal handle 108 */ 109 public int getNativeHandle() { 110 return m_handle; 111 } 112 113 /** 114 * Get the name of the simulated device. 115 * 116 * @return the name 117 */ 118 public String getName() { 119 return SimDeviceJNI.getSimDeviceName(m_handle); 120 } 121 122 /** 123 * Creates a value on the simulated device. 124 * 125 * <p>Returns null if not in simulation. 126 * 127 * @param name value name 128 * @param direction input/output/bidir (from perspective of user code) 129 * @param initialValue initial value 130 * @return simulated value object 131 */ 132 public SimValue createValue(String name, Direction direction, HALValue initialValue) { 133 int handle = SimDeviceJNI.createSimValue(m_handle, name, direction.m_value, initialValue); 134 if (handle <= 0) { 135 return null; 136 } 137 return new SimValue(handle); 138 } 139 140 /** 141 * Creates an int value on the simulated device. 142 * 143 * <p>Returns null if not in simulation. 144 * 145 * @param name value name 146 * @param direction input/output/bidir (from perspective of user code) 147 * @param initialValue initial value 148 * @return simulated double value object 149 */ 150 public SimInt createInt(String name, Direction direction, int initialValue) { 151 int handle = SimDeviceJNI.createSimValueInt(m_handle, name, direction.m_value, initialValue); 152 if (handle <= 0) { 153 return null; 154 } 155 return new SimInt(handle); 156 } 157 158 /** 159 * Creates a long value on the simulated device. 160 * 161 * <p>Returns null if not in simulation. 162 * 163 * @param name value name 164 * @param direction input/output/bidir (from perspective of user code) 165 * @param initialValue initial value 166 * @return simulated double value object 167 */ 168 public SimLong createLong(String name, Direction direction, long initialValue) { 169 int handle = SimDeviceJNI.createSimValueLong(m_handle, name, direction.m_value, initialValue); 170 if (handle <= 0) { 171 return null; 172 } 173 return new SimLong(handle); 174 } 175 176 /** 177 * Creates a double value on the simulated device. 178 * 179 * <p>Returns null if not in simulation. 180 * 181 * @param name value name 182 * @param direction input/output/bidir (from perspective of user code) 183 * @param initialValue initial value 184 * @return simulated double value object 185 */ 186 public SimDouble createDouble(String name, Direction direction, double initialValue) { 187 int handle = SimDeviceJNI.createSimValueDouble(m_handle, name, direction.m_value, initialValue); 188 if (handle <= 0) { 189 return null; 190 } 191 return new SimDouble(handle); 192 } 193 194 /** 195 * Creates an enumerated value on the simulated device. 196 * 197 * <p>Enumerated values are always in the range 0 to numOptions-1. 198 * 199 * <p>Returns null if not in simulation. 200 * 201 * @param name value name 202 * @param direction input/output/bidir (from perspective of user code) 203 * @param options array of option descriptions 204 * @param initialValue initial value (selection) 205 * @return simulated enum value object 206 */ 207 public SimEnum createEnum(String name, Direction direction, String[] options, int initialValue) { 208 int handle = 209 SimDeviceJNI.createSimValueEnum(m_handle, name, direction.m_value, options, initialValue); 210 if (handle <= 0) { 211 return null; 212 } 213 return new SimEnum(handle); 214 } 215 216 /** 217 * Creates an enumerated value on the simulated device with double values. 218 * 219 * <p>Enumerated values are always in the range 0 to numOptions-1. 220 * 221 * <p>Returns null if not in simulation. 222 * 223 * @param name value name 224 * @param direction input/output/bidir (from perspective of user code) 225 * @param options array of option descriptions 226 * @param optionValues array of option values (must be the same size as options) 227 * @param initialValue initial value (selection) 228 * @return simulated enum value object 229 */ 230 public SimEnum createEnumDouble( 231 String name, Direction direction, String[] options, double[] optionValues, int initialValue) { 232 int handle = 233 SimDeviceJNI.createSimValueEnumDouble( 234 m_handle, name, direction.m_value, options, optionValues, initialValue); 235 if (handle <= 0) { 236 return null; 237 } 238 return new SimEnum(handle); 239 } 240 241 /** 242 * Creates a boolean value on the simulated device. 243 * 244 * <p>Returns null if not in simulation. 245 * 246 * @param name value name 247 * @param direction input/output/bidir (from perspective of user code) 248 * @param initialValue initial value 249 * @return simulated boolean value object 250 */ 251 public SimBoolean createBoolean(String name, Direction direction, boolean initialValue) { 252 int handle = 253 SimDeviceJNI.createSimValueBoolean(m_handle, name, direction.m_value, initialValue); 254 if (handle <= 0) { 255 return null; 256 } 257 return new SimBoolean(handle); 258 } 259 260 private final int m_handle; 261}