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 identifier 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 * Get the name of the simulated device. 111 * 112 * @return the name 113 */ 114 public String getName() { 115 return SimDeviceJNI.getSimDeviceName(m_handle); 116 } 117 118 /** 119 * Creates a value on the simulated device. 120 * 121 * <p>Returns null if not in simulation. 122 * 123 * @param name value name 124 * @param direction input/output/bidir (from perspective of user code) 125 * @param initialValue initial value 126 * @return simulated value object 127 */ 128 public SimValue createValue(String name, Direction direction, HALValue initialValue) { 129 int handle = SimDeviceJNI.createSimValue(m_handle, name, direction.m_value, initialValue); 130 if (handle <= 0) { 131 return null; 132 } 133 return new SimValue(handle); 134 } 135 136 /** 137 * Creates an int value on the simulated device. 138 * 139 * <p>Returns null if not in simulation. 140 * 141 * @param name value name 142 * @param direction input/output/bidir (from perspective of user code) 143 * @param initialValue initial value 144 * @return simulated double value object 145 */ 146 public SimInt createInt(String name, Direction direction, int initialValue) { 147 int handle = SimDeviceJNI.createSimValueInt(m_handle, name, direction.m_value, initialValue); 148 if (handle <= 0) { 149 return null; 150 } 151 return new SimInt(handle); 152 } 153 154 /** 155 * Creates a long value on the simulated device. 156 * 157 * <p>Returns null if not in simulation. 158 * 159 * @param name value name 160 * @param direction input/output/bidir (from perspective of user code) 161 * @param initialValue initial value 162 * @return simulated double value object 163 */ 164 public SimLong createLong(String name, Direction direction, long initialValue) { 165 int handle = SimDeviceJNI.createSimValueLong(m_handle, name, direction.m_value, initialValue); 166 if (handle <= 0) { 167 return null; 168 } 169 return new SimLong(handle); 170 } 171 172 /** 173 * Creates a double value on the simulated device. 174 * 175 * <p>Returns null if not in simulation. 176 * 177 * @param name value name 178 * @param direction input/output/bidir (from perspective of user code) 179 * @param initialValue initial value 180 * @return simulated double value object 181 */ 182 public SimDouble createDouble(String name, Direction direction, double initialValue) { 183 int handle = SimDeviceJNI.createSimValueDouble(m_handle, name, direction.m_value, initialValue); 184 if (handle <= 0) { 185 return null; 186 } 187 return new SimDouble(handle); 188 } 189 190 /** 191 * Creates an enumerated value on the simulated device. 192 * 193 * <p>Enumerated values are always in the range 0 to numOptions-1. 194 * 195 * <p>Returns null if not in simulation. 196 * 197 * @param name value name 198 * @param direction input/output/bidir (from perspective of user code) 199 * @param options array of option descriptions 200 * @param initialValue initial value (selection) 201 * @return simulated enum value object 202 */ 203 public SimEnum createEnum(String name, Direction direction, String[] options, int initialValue) { 204 int handle = 205 SimDeviceJNI.createSimValueEnum(m_handle, name, direction.m_value, options, initialValue); 206 if (handle <= 0) { 207 return null; 208 } 209 return new SimEnum(handle); 210 } 211 212 /** 213 * Creates an enumerated value on the simulated device with double values. 214 * 215 * <p>Enumerated values are always in the range 0 to numOptions-1. 216 * 217 * <p>Returns null if not in simulation. 218 * 219 * @param name value name 220 * @param direction input/output/bidir (from perspective of user code) 221 * @param options array of option descriptions 222 * @param optionValues array of option values (must be the same size as options) 223 * @param initialValue initial value (selection) 224 * @return simulated enum value object 225 */ 226 public SimEnum createEnumDouble( 227 String name, Direction direction, String[] options, double[] optionValues, int initialValue) { 228 int handle = 229 SimDeviceJNI.createSimValueEnumDouble( 230 m_handle, name, direction.m_value, options, optionValues, initialValue); 231 if (handle <= 0) { 232 return null; 233 } 234 return new SimEnum(handle); 235 } 236 237 /** 238 * Creates a boolean value on the simulated device. 239 * 240 * <p>Returns null if not in simulation. 241 * 242 * @param name value name 243 * @param direction input/output/bidir (from perspective of user code) 244 * @param initialValue initial value 245 * @return simulated boolean value object 246 */ 247 public SimBoolean createBoolean(String name, Direction direction, boolean initialValue) { 248 int handle = 249 SimDeviceJNI.createSimValueBoolean(m_handle, name, direction.m_value, initialValue); 250 if (handle <= 0) { 251 return null; 252 } 253 return new SimBoolean(handle); 254 } 255 256 private final int m_handle; 257}