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.wpilibj;
006
007import edu.wpi.first.hal.HAL;
008import java.util.HashMap;
009import java.util.Map;
010
011/**
012 * Handle input from standard HID devices connected to the Driver Station.
013 *
014 * <p>This class handles standard input that comes from the Driver Station. Each time a value is
015 * requested the most recent value is returned. There is a single class instance for each device and
016 * the mapping of ports to hardware buttons depends on the code in the Driver Station.
017 */
018public class GenericHID {
019  /** Represents a rumble output on the JoyStick. */
020  public enum RumbleType {
021    kLeftRumble,
022    kRightRumble
023  }
024
025  public enum HIDType {
026    kUnknown(-1),
027    kXInputUnknown(0),
028    kXInputGamepad(1),
029    kXInputWheel(2),
030    kXInputArcadeStick(3),
031    kXInputFlightStick(4),
032    kXInputDancePad(5),
033    kXInputGuitar(6),
034    kXInputGuitar2(7),
035    kXInputDrumKit(8),
036    kXInputGuitar3(11),
037    kXInputArcadePad(19),
038    kHIDJoystick(20),
039    kHIDGamepad(21),
040    kHIDDriving(22),
041    kHIDFlight(23),
042    kHID1stPerson(24);
043
044    public final int value;
045
046    @SuppressWarnings("PMD.UseConcurrentHashMap")
047    private static final Map<Integer, HIDType> map = new HashMap<>();
048
049    HIDType(int value) {
050      this.value = value;
051    }
052
053    static {
054      for (HIDType hidType : HIDType.values()) {
055        map.put(hidType.value, hidType);
056      }
057    }
058
059    public static HIDType of(int value) {
060      return map.get(value);
061    }
062  }
063
064  private final int m_port;
065  private int m_outputs;
066  private short m_leftRumble;
067  private short m_rightRumble;
068
069  /**
070   * Construct an instance of a device.
071   *
072   * @param port The port index on the Driver Station that the device is plugged into.
073   */
074  public GenericHID(int port) {
075    m_port = port;
076  }
077
078  /**
079   * Get the button value (starting at button 1).
080   *
081   * <p>The buttons are returned in a single 16 bit value with one bit representing the state of
082   * each button. The appropriate button is returned as a boolean value.
083   *
084   * <p>This method returns true if the button is being held down at the time that this method is
085   * being called.
086   *
087   * @param button The button number to be read (starting at 1)
088   * @return The state of the button.
089   */
090  public boolean getRawButton(int button) {
091    return DriverStation.getStickButton(m_port, (byte) button);
092  }
093
094  /**
095   * Whether the button was pressed since the last check. Button indexes begin at 1.
096   *
097   * <p>This method returns true if the button went from not pressed to held down since the last
098   * time this method was called. This is useful if you only want to call a function once when you
099   * press the button.
100   *
101   * @param button The button index, beginning at 1.
102   * @return Whether the button was pressed since the last check.
103   */
104  public boolean getRawButtonPressed(int button) {
105    return DriverStation.getStickButtonPressed(m_port, (byte) button);
106  }
107
108  /**
109   * Whether the button was released since the last check. Button indexes begin at 1.
110   *
111   * <p>This method returns true if the button went from held down to not pressed since the last
112   * time this method was called. This is useful if you only want to call a function once when you
113   * release the button.
114   *
115   * @param button The button index, beginning at 1.
116   * @return Whether the button was released since the last check.
117   */
118  public boolean getRawButtonReleased(int button) {
119    return DriverStation.getStickButtonReleased(m_port, button);
120  }
121
122  /**
123   * Get the value of the axis.
124   *
125   * @param axis The axis to read, starting at 0.
126   * @return The value of the axis.
127   */
128  public double getRawAxis(int axis) {
129    return DriverStation.getStickAxis(m_port, axis);
130  }
131
132  /**
133   * Get the angle in degrees of a POV on the HID.
134   *
135   * <p>The POV angles start at 0 in the up direction, and increase clockwise (eg right is 90,
136   * upper-left is 315).
137   *
138   * @param pov The index of the POV to read (starting at 0). Defaults to 0.
139   * @return the angle of the POV in degrees, or -1 if the POV is not pressed.
140   */
141  public int getPOV(int pov) {
142    return DriverStation.getStickPOV(m_port, pov);
143  }
144
145  /**
146   * Get the angle in degrees of the default POV (index 0) on the HID.
147   *
148   * <p>The POV angles start at 0 in the up direction, and increase clockwise (eg right is 90,
149   * upper-left is 315).
150   *
151   * @return the angle of the POV in degrees, or -1 if the POV is not pressed.
152   */
153  public int getPOV() {
154    return getPOV(0);
155  }
156
157  /**
158   * Get the number of axes for the HID.
159   *
160   * @return the number of axis for the current HID
161   */
162  public int getAxisCount() {
163    return DriverStation.getStickAxisCount(m_port);
164  }
165
166  /**
167   * For the current HID, return the number of POVs.
168   *
169   * @return the number of POVs for the current HID
170   */
171  public int getPOVCount() {
172    return DriverStation.getStickPOVCount(m_port);
173  }
174
175  /**
176   * For the current HID, return the number of buttons.
177   *
178   * @return the number of buttons for the current HID
179   */
180  public int getButtonCount() {
181    return DriverStation.getStickButtonCount(m_port);
182  }
183
184  /**
185   * Get if the HID is connected.
186   *
187   * @return true if the HID is connected
188   */
189  public boolean isConnected() {
190    return DriverStation.isJoystickConnected(m_port);
191  }
192
193  /**
194   * Get the type of the HID.
195   *
196   * @return the type of the HID.
197   */
198  public HIDType getType() {
199    return HIDType.of(DriverStation.getJoystickType(m_port));
200  }
201
202  /**
203   * Get the name of the HID.
204   *
205   * @return the name of the HID.
206   */
207  public String getName() {
208    return DriverStation.getJoystickName(m_port);
209  }
210
211  /**
212   * Get the axis type of a joystick axis.
213   *
214   * @param axis The axis to read, starting at 0.
215   * @return the axis type of a joystick axis.
216   */
217  public int getAxisType(int axis) {
218    return DriverStation.getJoystickAxisType(m_port, axis);
219  }
220
221  /**
222   * Get the port number of the HID.
223   *
224   * @return The port number of the HID.
225   */
226  public int getPort() {
227    return m_port;
228  }
229
230  /**
231   * Set a single HID output value for the HID.
232   *
233   * @param outputNumber The index of the output to set (1-32)
234   * @param value The value to set the output to
235   */
236  public void setOutput(int outputNumber, boolean value) {
237    m_outputs = (m_outputs & ~(1 << (outputNumber - 1))) | ((value ? 1 : 0) << (outputNumber - 1));
238    HAL.setJoystickOutputs((byte) m_port, m_outputs, m_leftRumble, m_rightRumble);
239  }
240
241  /**
242   * Set all HID output values for the HID.
243   *
244   * @param value The 32 bit output value (1 bit for each output)
245   */
246  public void setOutputs(int value) {
247    m_outputs = value;
248    HAL.setJoystickOutputs((byte) m_port, m_outputs, m_leftRumble, m_rightRumble);
249  }
250
251  /**
252   * Set the rumble output for the HID. The DS currently supports 2 rumble values, left rumble and
253   * right rumble.
254   *
255   * @param type Which rumble value to set
256   * @param value The normalized value (0 to 1) to set the rumble to
257   */
258  public void setRumble(RumbleType type, double value) {
259    if (value < 0) {
260      value = 0;
261    } else if (value > 1) {
262      value = 1;
263    }
264    if (type == RumbleType.kLeftRumble) {
265      m_leftRumble = (short) (value * 65535);
266    } else {
267      m_rightRumble = (short) (value * 65535);
268    }
269    HAL.setJoystickOutputs((byte) m_port, m_outputs, m_leftRumble, m_rightRumble);
270  }
271}