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.FRCNetComm.tResourceType;
008import edu.wpi.first.hal.HAL;
009import edu.wpi.first.wpilibj.event.BooleanEvent;
010import edu.wpi.first.wpilibj.event.EventLoop;
011
012/**
013 * Handle input from PS4 controllers connected to the Driver Station.
014 *
015 * <p>This class handles PS4 input that comes from the Driver Station. Each time a value is
016 * requested the most recent value is returned. There is a single class instance for each controller
017 * and the mapping of ports to hardware buttons depends on the code in the Driver Station.
018 *
019 * <p>Only first party controllers from Sony are guaranteed to have the correct mapping, and only
020 * through the official NI DS. Sim is not guaranteed to have the same mapping, as well as any 3rd
021 * party controllers.
022 */
023public class PS4Controller extends GenericHID {
024  /**
025   * Construct an instance of a device.
026   *
027   * @param port The port index on the Driver Station that the device is plugged into.
028   */
029  public PS4Controller(int port) {
030    super(port);
031
032    HAL.report(tResourceType.kResourceType_PS4Controller, port + 1);
033  }
034
035  /** Represents a digital button on a PS4Controller. */
036  public enum Button {
037    /** Square button. */
038    kSquare(1),
039    /** X button. */
040    kCross(2),
041    /** Circle button. */
042    kCircle(3),
043    /** Triangle button. */
044    kTriangle(4),
045    /** Left Trigger 1 button. */
046    kL1(5),
047    /** Right Trigger 1 button. */
048    kR1(6),
049    /** Left Trigger 2 button. */
050    kL2(7),
051    /** Right Trigger 2 button. */
052    kR2(8),
053    /** Share button. */
054    kShare(9),
055    /** Option button. */
056    kOptions(10),
057    /** Left stick button. */
058    kL3(11),
059    /** Right stick button. */
060    kR3(12),
061    /** PlayStation button. */
062    kPS(13),
063    /** Touchpad click button. */
064    kTouchpad(14);
065
066    /** Button value. */
067    public final int value;
068
069    Button(int index) {
070      this.value = index;
071    }
072
073    /**
074     * Get the human-friendly name of the button, matching the relevant methods. This is done by
075     * stripping the leading `k`, and if not the touchpad append `Button`.
076     *
077     * <p>Primarily used for automated unit tests.
078     *
079     * @return the human-friendly name of the button.
080     */
081    @Override
082    public String toString() {
083      var name = this.name().substring(1); // Remove leading `k`
084      if (this == kTouchpad) {
085        return name;
086      }
087      return name + "Button";
088    }
089  }
090
091  /** Represents an axis on a PS4Controller. */
092  public enum Axis {
093    /** Left X axis. */
094    kLeftX(0),
095    /** Left Y axis. */
096    kLeftY(1),
097    /** Right X axis. */
098    kRightX(2),
099    /** Right Y axis. */
100    kRightY(5),
101    /** Left Trigger 2. */
102    kL2(3),
103    /** Right Trigger 2. */
104    kR2(4);
105
106    /** Axis value. */
107    public final int value;
108
109    Axis(int index) {
110      value = index;
111    }
112
113    /**
114     * Get the human-friendly name of the axis, matching the relevant methods. This is done by
115     * stripping the leading `k`, and if one of L2/R2 append `Axis`.
116     *
117     * <p>Primarily used for automated unit tests.
118     *
119     * @return the human-friendly name of the axis.
120     */
121    @Override
122    public String toString() {
123      var name = this.name().substring(1); // Remove leading `k`
124      if (name.endsWith("2")) {
125        return name + "Axis";
126      }
127      return name;
128    }
129  }
130
131  /**
132   * Get the X axis value of left side of the controller.
133   *
134   * @return the axis value.
135   */
136  public double getLeftX() {
137    return getRawAxis(Axis.kLeftX.value);
138  }
139
140  /**
141   * Get the X axis value of right side of the controller.
142   *
143   * @return the axis value.
144   */
145  public double getRightX() {
146    return getRawAxis(Axis.kRightX.value);
147  }
148
149  /**
150   * Get the Y axis value of left side of the controller.
151   *
152   * @return the axis value.
153   */
154  public double getLeftY() {
155    return getRawAxis(Axis.kLeftY.value);
156  }
157
158  /**
159   * Get the Y axis value of right side of the controller.
160   *
161   * @return the axis value.
162   */
163  public double getRightY() {
164    return getRawAxis(Axis.kRightY.value);
165  }
166
167  /**
168   * Get the L2 axis value of the controller. Note that this axis is bound to the range of [0, 1] as
169   * opposed to the usual [-1, 1].
170   *
171   * @return the axis value.
172   */
173  public double getL2Axis() {
174    return getRawAxis(Axis.kL2.value);
175  }
176
177  /**
178   * Get the R2 axis value of the controller. Note that this axis is bound to the range of [0, 1] as
179   * opposed to the usual [-1, 1].
180   *
181   * @return the axis value.
182   */
183  public double getR2Axis() {
184    return getRawAxis(Axis.kR2.value);
185  }
186
187  /**
188   * Read the value of the left trigger button on the controller.
189   *
190   * @return The state of the button.
191   */
192  public boolean getL2Button() {
193    return getRawButton(Button.kL2.value);
194  }
195
196  /**
197   * Read the value of the right trigger button on the controller.
198   *
199   * @return The state of the button.
200   */
201  public boolean getR2Button() {
202    return getRawButton(Button.kR2.value);
203  }
204
205  /**
206   * Whether the L2 button was pressed since the last check.
207   *
208   * @return Whether the button was pressed since the last check.
209   */
210  public boolean getL2ButtonPressed() {
211    return getRawButtonPressed(Button.kL2.value);
212  }
213
214  /**
215   * Whether the R2 button was pressed since the last check.
216   *
217   * @return Whether the button was pressed since the last check.
218   */
219  public boolean getR2ButtonPressed() {
220    return getRawButtonPressed(Button.kR2.value);
221  }
222
223  /**
224   * Whether the L2 button was released since the last check.
225   *
226   * @return Whether the button was released since the last check.
227   */
228  public boolean getL2ButtonReleased() {
229    return getRawButtonReleased(Button.kL2.value);
230  }
231
232  /**
233   * Whether the R2 button was released since the last check.
234   *
235   * @return Whether the button was released since the last check.
236   */
237  public boolean getR2ButtonReleased() {
238    return getRawButtonReleased(Button.kR2.value);
239  }
240
241  /**
242   * Constructs an event instance around the L2 button's digital signal.
243   *
244   * @param loop the event loop instance to attach the event to.
245   * @return an event instance representing the L2 button's digital signal attached to the given
246   *     loop.
247   */
248  @SuppressWarnings("MethodName")
249  public BooleanEvent L2(EventLoop loop) {
250    return new BooleanEvent(loop, this::getL2Button);
251  }
252
253  /**
254   * Constructs an event instance around the R2 button's digital signal.
255   *
256   * @param loop the event loop instance to attach the event to.
257   * @return an event instance representing the R2 button's digital signal attached to the given
258   *     loop.
259   */
260  @SuppressWarnings("MethodName")
261  public BooleanEvent R2(EventLoop loop) {
262    return new BooleanEvent(loop, this::getR2Button);
263  }
264
265  /**
266   * Read the value of the L1 button on the controller.
267   *
268   * @return The state of the button.
269   */
270  public boolean getL1Button() {
271    return getRawButton(Button.kL1.value);
272  }
273
274  /**
275   * Read the value of the R1 button on the controller.
276   *
277   * @return The state of the button.
278   */
279  public boolean getR1Button() {
280    return getRawButton(Button.kR1.value);
281  }
282
283  /**
284   * Whether the L1 button was pressed since the last check.
285   *
286   * @return Whether the button was pressed since the last check.
287   */
288  public boolean getL1ButtonPressed() {
289    return getRawButtonPressed(Button.kL1.value);
290  }
291
292  /**
293   * Whether the R1 button was pressed since the last check.
294   *
295   * @return Whether the button was pressed since the last check.
296   */
297  public boolean getR1ButtonPressed() {
298    return getRawButtonPressed(Button.kR1.value);
299  }
300
301  /**
302   * Whether the L1 button was released since the last check.
303   *
304   * @return Whether the button was released since the last check.
305   */
306  public boolean getL1ButtonReleased() {
307    return getRawButtonReleased(Button.kL1.value);
308  }
309
310  /**
311   * Whether the R1 button was released since the last check.
312   *
313   * @return Whether the button was released since the last check.
314   */
315  public boolean getR1ButtonReleased() {
316    return getRawButtonReleased(Button.kR1.value);
317  }
318
319  /**
320   * Constructs an event instance around the L1 button's digital signal.
321   *
322   * @param loop the event loop instance to attach the event to.
323   * @return an event instance representing the L1 button's digital signal attached to the given
324   *     loop.
325   */
326  @SuppressWarnings("MethodName")
327  public BooleanEvent L1(EventLoop loop) {
328    return new BooleanEvent(loop, this::getL1Button);
329  }
330
331  /**
332   * Constructs an event instance around the R1 button's digital signal.
333   *
334   * @param loop the event loop instance to attach the event to.
335   * @return an event instance representing the R1 button's digital signal attached to the given
336   *     loop.
337   */
338  @SuppressWarnings("MethodName")
339  public BooleanEvent R1(EventLoop loop) {
340    return new BooleanEvent(loop, this::getR1Button);
341  }
342
343  /**
344   * Read the value of the L3 button (pressing the left analog stick) on the controller.
345   *
346   * @return The state of the button.
347   */
348  public boolean getL3Button() {
349    return getRawButton(Button.kL3.value);
350  }
351
352  /**
353   * Read the value of the R3 button (pressing the right analog stick) on the controller.
354   *
355   * @return The state of the button.
356   */
357  public boolean getR3Button() {
358    return getRawButton(Button.kR3.value);
359  }
360
361  /**
362   * Whether the L3 (left stick) button was pressed since the last check.
363   *
364   * @return Whether the button was pressed since the last check.
365   */
366  public boolean getL3ButtonPressed() {
367    return getRawButtonPressed(Button.kL3.value);
368  }
369
370  /**
371   * Whether the R3 (right stick) button was pressed since the last check.
372   *
373   * @return Whether the button was pressed since the last check.
374   */
375  public boolean getR3ButtonPressed() {
376    return getRawButtonPressed(Button.kR3.value);
377  }
378
379  /**
380   * Whether the L3 (left stick) button was released since the last check.
381   *
382   * @return Whether the button was released since the last check.
383   */
384  public boolean getL3ButtonReleased() {
385    return getRawButtonReleased(Button.kL3.value);
386  }
387
388  /**
389   * Whether the R3 (right stick) button was released since the last check.
390   *
391   * @return Whether the button was released since the last check.
392   */
393  public boolean getR3ButtonReleased() {
394    return getRawButtonReleased(Button.kR3.value);
395  }
396
397  /**
398   * Constructs an event instance around the L3 button's digital signal.
399   *
400   * @param loop the event loop instance to attach the event to.
401   * @return an event instance representing the L3 button's digital signal attached to the given
402   *     loop.
403   */
404  @SuppressWarnings("MethodName")
405  public BooleanEvent L3(EventLoop loop) {
406    return new BooleanEvent(loop, this::getL3Button);
407  }
408
409  /**
410   * Constructs an event instance around the R3 button's digital signal.
411   *
412   * @param loop the event loop instance to attach the event to.
413   * @return an event instance representing the R3 button's digital signal attached to the given
414   *     loop.
415   */
416  @SuppressWarnings("MethodName")
417  public BooleanEvent R3(EventLoop loop) {
418    return new BooleanEvent(loop, this::getR3Button);
419  }
420
421  /**
422   * Read the value of the Square button on the controller.
423   *
424   * @return The state of the button.
425   */
426  public boolean getSquareButton() {
427    return getRawButton(Button.kSquare.value);
428  }
429
430  /**
431   * Whether the Square button was pressed since the last check.
432   *
433   * @return Whether the button was pressed since the last check.
434   */
435  public boolean getSquareButtonPressed() {
436    return getRawButtonPressed(Button.kSquare.value);
437  }
438
439  /**
440   * Whether the Square button was released since the last check.
441   *
442   * @return Whether the button was released since the last check.
443   */
444  public boolean getSquareButtonReleased() {
445    return getRawButtonReleased(Button.kSquare.value);
446  }
447
448  /**
449   * Constructs an event instance around the square button's digital signal.
450   *
451   * @param loop the event loop instance to attach the event to.
452   * @return an event instance representing the square button's digital signal attached to the given
453   *     loop.
454   */
455  public BooleanEvent square(EventLoop loop) {
456    return new BooleanEvent(loop, this::getSquareButton);
457  }
458
459  /**
460   * Read the value of the Cross button on the controller.
461   *
462   * @return The state of the button.
463   */
464  public boolean getCrossButton() {
465    return getRawButton(Button.kCross.value);
466  }
467
468  /**
469   * Whether the Cross button was pressed since the last check.
470   *
471   * @return Whether the button was pressed since the last check.
472   */
473  public boolean getCrossButtonPressed() {
474    return getRawButtonPressed(Button.kCross.value);
475  }
476
477  /**
478   * Whether the Cross button was released since the last check.
479   *
480   * @return Whether the button was released since the last check.
481   */
482  public boolean getCrossButtonReleased() {
483    return getRawButtonReleased(Button.kCross.value);
484  }
485
486  /**
487   * Constructs an event instance around the cross button's digital signal.
488   *
489   * @param loop the event loop instance to attach the event to.
490   * @return an event instance representing the cross button's digital signal attached to the given
491   *     loop.
492   */
493  public BooleanEvent cross(EventLoop loop) {
494    return new BooleanEvent(loop, this::getCrossButton);
495  }
496
497  /**
498   * Read the value of the Triangle button on the controller.
499   *
500   * @return The state of the button.
501   */
502  public boolean getTriangleButton() {
503    return getRawButton(Button.kTriangle.value);
504  }
505
506  /**
507   * Whether the Triangle button was pressed since the last check.
508   *
509   * @return Whether the button was pressed since the last check.
510   */
511  public boolean getTriangleButtonPressed() {
512    return getRawButtonPressed(Button.kTriangle.value);
513  }
514
515  /**
516   * Whether the Triangle button was released since the last check.
517   *
518   * @return Whether the button was released since the last check.
519   */
520  public boolean getTriangleButtonReleased() {
521    return getRawButtonReleased(Button.kTriangle.value);
522  }
523
524  /**
525   * Constructs an event instance around the triangle button's digital signal.
526   *
527   * @param loop the event loop instance to attach the event to.
528   * @return an event instance representing the triangle button's digital signal attached to the
529   *     given loop.
530   */
531  public BooleanEvent triangle(EventLoop loop) {
532    return new BooleanEvent(loop, this::getTriangleButton);
533  }
534
535  /**
536   * Read the value of the Circle button on the controller.
537   *
538   * @return The state of the button.
539   */
540  public boolean getCircleButton() {
541    return getRawButton(Button.kCircle.value);
542  }
543
544  /**
545   * Whether the Circle button was pressed since the last check.
546   *
547   * @return Whether the button was pressed since the last check.
548   */
549  public boolean getCircleButtonPressed() {
550    return getRawButtonPressed(Button.kCircle.value);
551  }
552
553  /**
554   * Whether the Circle button was released since the last check.
555   *
556   * @return Whether the button was released since the last check.
557   */
558  public boolean getCircleButtonReleased() {
559    return getRawButtonReleased(Button.kCircle.value);
560  }
561
562  /**
563   * Constructs an event instance around the circle button's digital signal.
564   *
565   * @param loop the event loop instance to attach the event to.
566   * @return an event instance representing the circle button's digital signal attached to the given
567   *     loop.
568   */
569  public BooleanEvent circle(EventLoop loop) {
570    return new BooleanEvent(loop, this::getCircleButton);
571  }
572
573  /**
574   * Read the value of the share button on the controller.
575   *
576   * @return The state of the button.
577   */
578  public boolean getShareButton() {
579    return getRawButton(Button.kShare.value);
580  }
581
582  /**
583   * Whether the share button was pressed since the last check.
584   *
585   * @return Whether the button was pressed since the last check.
586   */
587  public boolean getShareButtonPressed() {
588    return getRawButtonPressed(Button.kShare.value);
589  }
590
591  /**
592   * Whether the share button was released since the last check.
593   *
594   * @return Whether the button was released since the last check.
595   */
596  public boolean getShareButtonReleased() {
597    return getRawButtonReleased(Button.kShare.value);
598  }
599
600  /**
601   * Constructs an event instance around the share button's digital signal.
602   *
603   * @param loop the event loop instance to attach the event to.
604   * @return an event instance representing the share button's digital signal attached to the given
605   *     loop.
606   */
607  @SuppressWarnings("MethodName")
608  public BooleanEvent share(EventLoop loop) {
609    return new BooleanEvent(loop, this::getShareButton);
610  }
611
612  /**
613   * Read the value of the PS button on the controller.
614   *
615   * @return The state of the button.
616   */
617  public boolean getPSButton() {
618    return getRawButton(Button.kPS.value);
619  }
620
621  /**
622   * Whether the PS button was pressed since the last check.
623   *
624   * @return Whether the button was pressed since the last check.
625   */
626  public boolean getPSButtonPressed() {
627    return getRawButtonPressed(Button.kPS.value);
628  }
629
630  /**
631   * Whether the PS button was released since the last check.
632   *
633   * @return Whether the button was released since the last check.
634   */
635  public boolean getPSButtonReleased() {
636    return getRawButtonReleased(Button.kPS.value);
637  }
638
639  /**
640   * Constructs an event instance around the PS button's digital signal.
641   *
642   * @param loop the event loop instance to attach the event to.
643   * @return an event instance representing the PS button's digital signal attached to the given
644   *     loop.
645   */
646  @SuppressWarnings("MethodName")
647  public BooleanEvent PS(EventLoop loop) {
648    return new BooleanEvent(loop, this::getPSButton);
649  }
650
651  /**
652   * Read the value of the options button on the controller.
653   *
654   * @return The state of the button.
655   */
656  public boolean getOptionsButton() {
657    return getRawButton(Button.kOptions.value);
658  }
659
660  /**
661   * Whether the options button was pressed since the last check.
662   *
663   * @return Whether the button was pressed since the last check.
664   */
665  public boolean getOptionsButtonPressed() {
666    return getRawButtonPressed(Button.kOptions.value);
667  }
668
669  /**
670   * Whether the options button was released since the last check.
671   *
672   * @return Whether the button was released since the last check.
673   */
674  public boolean getOptionsButtonReleased() {
675    return getRawButtonReleased(Button.kOptions.value);
676  }
677
678  /**
679   * Constructs an event instance around the options button's digital signal.
680   *
681   * @param loop the event loop instance to attach the event to.
682   * @return an event instance representing the options button's digital signal attached to the
683   *     given loop.
684   */
685  public BooleanEvent options(EventLoop loop) {
686    return new BooleanEvent(loop, this::getOptionsButton);
687  }
688
689  /**
690   * Read the value of the touchpad on the controller.
691   *
692   * @return The state of the touchpad.
693   */
694  public boolean getTouchpad() {
695    return getRawButton(Button.kTouchpad.value);
696  }
697
698  /**
699   * Whether the touchpad was pressed since the last check.
700   *
701   * @return Whether the touchpad was pressed since the last check.
702   */
703  public boolean getTouchpadPressed() {
704    return getRawButtonPressed(Button.kTouchpad.value);
705  }
706
707  /**
708   * Whether the touchpad was released since the last check.
709   *
710   * @return Whether the touchpad was released since the last check.
711   */
712  public boolean getTouchpadReleased() {
713    return getRawButtonReleased(Button.kTouchpad.value);
714  }
715
716  /**
717   * Constructs an event instance around the touchpad's digital signal.
718   *
719   * @param loop the event loop instance to attach the event to.
720   * @return an event instance representing the touchpad's digital signal attached to the given
721   *     loop.
722   */
723  public BooleanEvent touchpad(EventLoop loop) {
724    return new BooleanEvent(loop, this::getTouchpad);
725  }
726}