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