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