001/*----------------------------------------------------------------------------*/
002/* Copyright (c) FIRST 2008-2012. All Rights Reserved.                        */
003/* Open Source Software - may be modified and shared by FRC teams. The code   */
004/* must be accompanied by the FIRST BSD license file in the root directory of */
005/* the project.                                                               */
006/*----------------------------------------------------------------------------*/
007package edu.wpi.first.wpilibj;
008
009import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType;
010import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary;
011import edu.wpi.first.wpilibj.communication.UsageReporting;
012
013/**
014 * Handle input from standard Joysticks connected to the Driver Station.
015 * This class handles standard input that comes from the Driver Station. Each time a value is requested
016 * the most recent value is returned. There is a single class instance for each joystick and the mapping
017 * of ports to hardware buttons depends on the code in the driver station.
018 */
019public class Joystick extends GenericHID {
020
021    static final byte kDefaultXAxis = 0;
022    static final byte kDefaultYAxis = 1;
023    static final byte kDefaultZAxis = 2;
024    static final byte kDefaultTwistAxis = 2;
025    static final byte kDefaultThrottleAxis = 3;
026    static final int kDefaultTriggerButton = 1;
027    static final int kDefaultTopButton = 2;
028
029    /**
030     * Represents an analog axis on a joystick.
031     */
032    public static class AxisType {
033
034        /**
035         * The integer value representing this enumeration
036         */
037        public final int value;
038        static final int kX_val = 0;
039        static final int kY_val = 1;
040        static final int kZ_val = 2;
041        static final int kTwist_val = 3;
042        static final int kThrottle_val = 4;
043        static final int kNumAxis_val = 5;
044        /**
045         * axis: x-axis
046         */
047        public static final AxisType kX = new AxisType(kX_val);
048        /**
049         * axis: y-axis
050         */
051        public static final AxisType kY = new AxisType(kY_val);
052        /**
053         * axis: z-axis
054         */
055        public static final AxisType kZ = new AxisType(kZ_val);
056        /**
057         * axis: twist
058         */
059        public static final AxisType kTwist = new AxisType(kTwist_val);
060        /**
061         * axis: throttle
062         */
063        public static final AxisType kThrottle = new AxisType(kThrottle_val);
064        /**
065         * axis: number of axis
066         */
067        public static final AxisType kNumAxis = new AxisType(kNumAxis_val);
068
069        private AxisType(int value) {
070            this.value = value;
071        }
072    }
073
074    /**
075     * Represents a digital button on the JoyStick
076     */
077    public static class ButtonType {
078
079        /**
080         * The integer value representing this enumeration
081         */
082        public final int value;
083        static final int kTrigger_val = 0;
084        static final int kTop_val = 1;
085        static final int kNumButton_val = 2;
086        /**
087         * button: trigger
088         */
089        public static final ButtonType kTrigger = new ButtonType((kTrigger_val));
090        /**
091         * button: top button
092         */
093        public static final ButtonType kTop = new ButtonType(kTop_val);
094        /**
095         * button: num button types
096         */
097        public static final ButtonType kNumButton = new ButtonType((kNumButton_val));
098
099        private ButtonType(int value) {
100            this.value = value;
101        }
102    }
103    
104    
105    /**
106     * Represents a rumble output on the JoyStick
107     */
108    public static class RumbleType {
109
110        /**
111         * The integer value representing this enumeration
112         */
113        public final int value;
114        static final int kLeftRumble_val = 0;
115        static final int kRightRumble_val = 1;
116        /**
117         * Left Rumble
118         */
119        public static final RumbleType kLeftRumble = new RumbleType((kLeftRumble_val));
120        /**
121         * Right Rumble
122         */
123        public static final RumbleType kRightRumble = new RumbleType(kRightRumble_val);
124
125        private RumbleType(int value) {
126            this.value = value;
127        }
128    }
129    
130    private DriverStation m_ds;
131    private final int m_port;
132    private final byte[] m_axes;
133    private final byte[] m_buttons;
134    private int m_outputs;
135    private short m_leftRumble;
136    private short m_rightRumble;
137
138    /**
139     * Construct an instance of a joystick.
140     * The joystick index is the usb port on the drivers station.
141     *
142     * @param port The port on the driver station that the joystick is plugged into.
143     */
144    public Joystick(final int port) {
145        this(port, AxisType.kNumAxis.value, ButtonType.kNumButton.value);
146
147        m_axes[AxisType.kX.value] = kDefaultXAxis;
148        m_axes[AxisType.kY.value] = kDefaultYAxis;
149        m_axes[AxisType.kZ.value] = kDefaultZAxis;
150        m_axes[AxisType.kTwist.value] = kDefaultTwistAxis;
151        m_axes[AxisType.kThrottle.value] = kDefaultThrottleAxis;
152
153        m_buttons[ButtonType.kTrigger.value] = kDefaultTriggerButton;
154        m_buttons[ButtonType.kTop.value] = kDefaultTopButton;
155
156        UsageReporting.report(tResourceType.kResourceType_Joystick, port);
157    }
158
159    /**
160     * Protected version of the constructor to be called by sub-classes.
161     *
162     * This constructor allows the subclass to configure the number of constants
163     * for axes and buttons.
164     *
165     * @param port The port on the driver station that the joystick is plugged into.
166     * @param numAxisTypes The number of axis types in the enum.
167     * @param numButtonTypes The number of button types in the enum.
168     */
169    protected Joystick(int port, int numAxisTypes, int numButtonTypes) {
170        m_ds = DriverStation.getInstance();
171        m_axes = new byte[numAxisTypes];
172        m_buttons = new byte[numButtonTypes];
173        m_port = port;
174    }
175
176    /**
177     * Get the X value of the joystick.
178     * This depends on the mapping of the joystick connected to the current port.
179     *
180     * @param hand Unused
181     * @return The X value of the joystick.
182     */
183    public double getX(Hand hand) {
184        return getRawAxis(m_axes[AxisType.kX.value]);
185    }
186
187    /**
188     * Get the Y value of the joystick.
189     * This depends on the mapping of the joystick connected to the current port.
190     *
191     * @param hand Unused
192     * @return The Y value of the joystick.
193     */
194    public double getY(Hand hand) {
195        return getRawAxis(m_axes[AxisType.kY.value]);
196    }
197
198    /**
199     * Get the Z value of the joystick.
200     * This depends on the mapping of the joystick connected to the current port.
201     *
202     * @param hand Unused
203     * @return The Z value of the joystick.
204     */
205    public double getZ(Hand hand) {
206        return getRawAxis(m_axes[AxisType.kZ.value]);
207    }
208
209    /**
210     * Get the twist value of the current joystick.
211     * This depends on the mapping of the joystick connected to the current port.
212     *
213     * @return The Twist value of the joystick.
214     */
215    public double getTwist() {
216        return getRawAxis(m_axes[AxisType.kTwist.value]);
217    }
218
219    /**
220     * Get the throttle value of the current joystick.
221     * This depends on the mapping of the joystick connected to the current port.
222     *
223     * @return The Throttle value of the joystick.
224     */
225    public double getThrottle() {
226        return getRawAxis(m_axes[AxisType.kThrottle.value]);
227    }
228
229    /**
230     * Get the value of the axis.
231     *
232     * @param axis The axis to read, starting at 0.
233     * @return The value of the axis.
234     */
235    public double getRawAxis(final int axis) {
236        return m_ds.getStickAxis(m_port, axis);
237    }
238
239    /**
240     * For the current joystick, return the axis determined by the argument.
241     *
242     * This is for cases where the joystick axis is returned programatically, otherwise one of the
243     * previous functions would be preferable (for example getX()).
244     *
245     * @param axis The axis to read.
246     * @return The value of the axis.
247     */
248    public double getAxis(final AxisType axis) {
249        switch (axis.value) {
250        case AxisType.kX_val:
251            return getX();
252        case AxisType.kY_val:
253            return getY();
254        case AxisType.kZ_val:
255            return getZ();
256        case AxisType.kTwist_val:
257            return getTwist();
258        case AxisType.kThrottle_val:
259            return getThrottle();
260        default:
261            return 0.0;
262        }
263    }
264
265    /**
266    * For the current joystick, return the number of axis
267    */
268    public int getAxisCount(){
269        return m_ds.getStickAxisCount(m_port);
270    }
271
272    /**
273     * Read the state of the trigger on the joystick.
274     *
275     * Look up which button has been assigned to the trigger and read its state.
276     *
277     * @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
278     * @return The state of the trigger.
279     */
280    public boolean getTrigger(Hand hand) {
281        return getRawButton(m_buttons[ButtonType.kTrigger.value]);
282    }
283
284    /**
285     * Read the state of the top button on the joystick.
286     *
287     * Look up which button has been assigned to the top and read its state.
288     *
289     * @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
290     * @return The state of the top button.
291     */
292    public boolean getTop(Hand hand) {
293        return getRawButton(m_buttons[ButtonType.kTop.value]);
294    }
295
296    /**
297     * This is not supported for the Joystick.
298     * This method is only here to complete the GenericHID interface.
299     *
300     * @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
301     * @return The state of the bumper (always false)
302     */
303    public boolean getBumper(Hand hand) {
304        return false;
305    }
306
307    /**
308     * Get the button value (starting at button 1)
309     *
310     * The appropriate button is returned as a boolean value.
311     *
312     * @param button The button number to be read (starting at 1).
313     * @return The state of the button.
314     */
315    public boolean getRawButton(final int button) {
316        return m_ds.getStickButton(m_port, (byte)button);
317    }
318
319    /**
320    * For the current joystick, return the number of buttons
321    */
322    public int getButtonCount(){
323        return m_ds.getStickButtonCount(m_port);
324    }
325
326    /**
327     * Get the state of a POV on the joystick.
328     *
329         * @param pov The index of the POV to read (starting at 0)
330     * @return the angle of the POV in degrees, or -1 if the POV is not pressed.
331     */
332    public int getPOV(int pov) {
333        return m_ds.getStickPOV(m_port, pov);
334    }
335
336    /**
337    * For the current joystick, return the number of POVs
338    */
339    public int getPOVCount(){
340        return m_ds.getStickPOVCount(m_port);
341    }
342
343    /**
344     * Get buttons based on an enumerated type.
345     *
346     * The button type will be looked up in the list of buttons and then read.
347     *
348     * @param button The type of button to read.
349     * @return The state of the button.
350     */
351    public boolean getButton(ButtonType button) {
352        switch (button.value) {
353        case ButtonType.kTrigger_val:
354            return getTrigger();
355        case ButtonType.kTop_val:
356            return getTop();
357        default:
358            return false;
359        }
360    }
361
362    /**
363     * Get the magnitude of the direction vector formed by the joystick's
364     * current position relative to its origin
365     *
366     * @return The magnitude of the direction vector
367     */
368    public double getMagnitude() {
369        return Math.sqrt(Math.pow(getX(), 2) + Math.pow(getY(), 2));
370    }
371
372    /**
373     * Get the direction of the vector formed by the joystick and its origin
374     * in radians
375     *
376     * @return The direction of the vector in radians
377     */
378    public double getDirectionRadians() {
379        return Math.atan2(getX(), -getY());
380    }
381
382    /**
383     * Get the direction of the vector formed by the joystick and its origin
384     * in degrees
385     *
386     * uses acos(-1) to represent Pi due to absence of readily accessable Pi
387     * constant in C++
388     *
389     * @return The direction of the vector in degrees
390     */
391    public double getDirectionDegrees() {
392        return Math.toDegrees(getDirectionRadians());
393    }
394
395    /**
396     * Get the channel currently associated with the specified axis.
397     *
398     * @param axis The axis to look up the channel for.
399     * @return The channel fr the axis.
400     */
401    public int getAxisChannel(AxisType axis) {
402        return m_axes[axis.value];
403    }
404
405    /**
406     * Set the channel associated with a specified axis.
407     *
408     * @param axis The axis to set the channel for.
409     * @param channel The channel to set the axis to.
410     */
411    public void setAxisChannel(AxisType axis, int channel) {
412        m_axes[axis.value] = (byte) channel;
413    }
414    
415    /**
416     * Set the rumble output for the joystick. The DS currently supports 2 rumble values,
417     * left rumble and right rumble
418     * @param type Which rumble value to set
419     * @param value The normalized value (0 to 1) to set the rumble to
420     */
421    public void setRumble(RumbleType type, float value) {
422        if (value < 0)
423            value = 0;
424        else if (value > 1)
425            value = 1;
426        if (type.value == RumbleType.kLeftRumble_val)
427            m_leftRumble = (short)(value*65535);
428        else
429            m_rightRumble = (short)(value*65535);
430        FRCNetworkCommunicationsLibrary.HALSetJoystickOutputs((byte)m_port, m_outputs, m_leftRumble, m_rightRumble);
431    }
432
433    /**
434     * Set a single HID output value for the joystick.
435     * @param outputNumber The index of the output to set (1-32)
436     * @param value The value to set the output to
437     */
438        
439    public void setOutput(int outputNumber, boolean value) {
440        m_outputs = (m_outputs & ~(1 << (outputNumber-1))) | ((value?1:0) << (outputNumber-1));
441        FRCNetworkCommunicationsLibrary.HALSetJoystickOutputs((byte)m_port, m_outputs, m_leftRumble, m_rightRumble);
442    }
443
444    /**
445     * Set all HID output values for the joystick.
446     * @param value The 32 bit output value (1 bit for each output)
447     */
448    public void setOutputs(int value) {
449        m_outputs = value;
450        FRCNetworkCommunicationsLibrary.HALSetJoystickOutputs((byte)m_port, m_outputs, m_leftRumble, m_rightRumble);
451    }
452}