@@ -155,8 +155,8 @@ static const byte exit_config[] = {0x01, 0x43, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5
155155 */
156156static const byte type_read[] = {0x01 , 0x45 , 0x00 , 0x5A , 0x5A , 0x5A , 0x5A , 0x5A , 0x5A };
157157static const byte set_mode[] = {0x01 , 0x44 , 0x00 , /* enabled */ 0x01 , /* locked */ 0x03 , 0x00 , 0x00 , 0x00 , 0x00 };
158+ static const byte enable_rumble[] = {0x01 , 0x4D , 0x00 , /* motor 1 on */ 0x00 , /* motor 2 on*/ 0x01 , 0xff , 0xff , 0xff , 0xff };
158159static const byte set_pressures[] = {0x01 , 0x4F , 0x00 , 0xFF , 0xFF , 0x03 , 0x00 , 0x00 , 0x00 };
159- // ~ static byte enable_rumble[] = {0x01, 0x4D, 0x00, 0x00, 0x01};
160160
161161/* * \brief Poll all buttons
162162 *
@@ -355,6 +355,27 @@ class PsxController {
355355 * True if the #analogButtonData were valid in last call to read()
356356 */
357357 boolean analogButtonDataValid;
358+
359+ /* * \brief Rumble feature enabled or disabled.
360+ *
361+ * True if rumble has been turned on with command 0x4d, false otherwise.
362+ * Rumble must be enabled and 7.5v supplied to pin 3!
363+ */
364+ boolean rumbleEnabled;
365+
366+ /* * \brief requested left motor (motor 1) power.
367+ *
368+ * 0xff for on, 0x00 for off, motor does not support partial activation.
369+ * Rumble must be enabled and 7.5v supplied to pin 3!
370+ */
371+ byte motor1Level;
372+
373+ /* * \brief requested right motor (motor 2) power.
374+ *
375+ * 0x00 to 0xFF -> 0 to 100% power.
376+ * Rumble must be enabled and 7.5v supplied to pin 3!
377+ */
378+ byte motor2Level;
358379
359380 /* * \brief Assert the Attention line
360381 *
@@ -559,6 +580,10 @@ class PsxController {
559580 memset (analogButtonData, 0 , sizeof (analogButtonData));
560581
561582 protocol = PSPROTO_UNKNOWN;
583+
584+ rumbleEnabled = false ;
585+ motor1Level = 0x00 ;
586+ motor2Level = 0x00 ;
562587
563588 // Some disposable readings to let the controller know we are here
564589 for (byte i = 0 ; i < 5 ; ++i) {
@@ -661,6 +686,67 @@ class PsxController {
661686 return ret;
662687 }
663688
689+ /* * \brief Enable (or disable) the vibration capability of the DualShock / DualShock 2
690+ *
691+ * This function enables or disables the rumble feature of the DualShock / DualShock 2 controllers.
692+ * NOTE that this function does nothing on its own - the vibration on/off must be set using
693+ * setRumble() and the controller will begin to vibrate when the read() function is
694+ * next called.
695+ *
696+ * This function will only work if when the controller is in Configuration
697+ * Mode.
698+ *
699+ * \param[in] enabled true to enable both motors, false to disable them.
700+ *
701+ * \return true if we got bytes back. Eventually we should wait for ACK from the controller.
702+ */
703+ boolean enableRumble (bool enabled = true ) {
704+ boolean ret = true ;
705+ byte out[sizeof (enable_rumble)];
706+
707+ memcpy (out, enable_rumble, sizeof (enable_rumble));
708+ out[3 ] = enabled ? 0x00 : 0xff ;
709+ out[4 ] = enabled ? 0x01 : 0xff ;
710+
711+ unsigned long start = millis ();
712+ byte cnt = 0 ;
713+ do {
714+ attention ();
715+ byte *in = autoShift (out, 5 );
716+ noAttention ();
717+
718+ /* The real way to check if the command was successful is to wait for ACK.
719+ * Currently the library doesn't support the pin, so I will just assume success.
720+ */
721+ if (in != nullptr ) {
722+ ++cnt;
723+ }
724+ ret = cnt >= 3 ;
725+
726+ if (!ret) {
727+ delay (COMMAND_RETRY_INTERVAL);
728+ }
729+ } while (!ret && millis () - start <= COMMAND_TIMEOUT);
730+ delay (MODE_SWITCH_DELAY);
731+
732+ rumbleEnabled = true ;
733+ return ret;
734+ }
735+
736+ /* * \brief Set the requested power output of the rumble motors on DualShock / DualShock 2 controllers.
737+ *
738+ * This function sets internal variables that set the requested motor power of the rumble motors.
739+ * NOTE this does nothing if rumble has not been enabled with enableRumble(), rumble motors will
740+ * activate or deactivate to match the arguments of this function with the next call to read()
741+ *
742+ * \param[in] enabled true to activate motor 1, false to deactivate.
743+ * \param[in] requested motor power of motor 2, where 0x00 to 0xFF corresponds to 0 to 100%.
744+ */
745+ void setRumble (bool motor1Active = true , byte motor2Power = 0xff ) {
746+ motor1Level = motor1Active ? 0xff : 0x00 ;
747+ motor2Level = motor2Power;
748+ }
749+
664750 /* * \brief Enable (or disable) analog buttons
665751 *
666752 * This function enables or disables the analog buttons that were introduced
@@ -811,7 +897,17 @@ class PsxController {
811897 analogButtonDataValid = false ;
812898
813899 attention ();
814- byte *in = autoShift (poll, 3 );
900+ byte *in = nullptr ;
901+ if (rumbleEnabled) {
902+ byte out[sizeof (poll)];
903+ memcpy (out, poll, sizeof (poll));
904+ out[3 ] = motor1Level;
905+ out[4 ] = motor2Level;
906+ in = autoShift (out, sizeof (poll));
907+ }
908+ else {
909+ in = autoShift (poll, 3 );
910+ }
815911 noAttention ();
816912
817913 if (in != NULL ) {
0 commit comments