shepherdingelectrons

PS2 Arduino radio controller

Jun 11th, 2019
3,515
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.98 KB | None | 0 0
  1. #include <PS2X_lib.h>
  2.  
  3. #include <SPI.h>
  4. #include <Mirf.h>
  5. #include <nRF24L01.h>
  6. #include <MirfHardwareSpiDriver.h>
  7.  
  8. #define PS2_DAT        4
  9. #define PS2_CMD        3
  10. #define PS2_SEL        2
  11. #define PS2_CLK        5
  12.  
  13. #define MY_LED 6
  14. #define SPEAKER 9
  15.  
  16. PS2X ps2x; // create PS2 Controller Class  
  17.  
  18. uint8_t tx_address[5] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7};
  19. uint8_t rx_address[5] = {0xD7, 0xD7, 0xD7, 0xD7, 0xD7};
  20.  
  21. #define toggle_pin(port, pin) port^=(1<<pin)
  22.  
  23. struct radio_packet
  24. {
  25.   uint8_t buttons1;
  26.   uint8_t buttons2;
  27.   uint8_t leftX;
  28.   uint8_t leftY;
  29.   uint8_t rightX;
  30.   uint8_t rightY;
  31. }radioData;
  32.  
  33. enum connection_state {WAITING=0, POOR=1, GOOD=2};
  34.  
  35. void playMelody(void)
  36. {
  37.  
  38.   for (uint8_t i=10;i>0;i--)
  39.   {
  40.   // pin, freq (Hz), duration (ms)
  41.     tone(SPEAKER, 100+(uint16_t)i*50,100);
  42.     delay(100);
  43.   }
  44. }
  45.  
  46. void ConnectedBeep(void) // This function has the potential to block radio calls if we're moving between poor and good
  47. {                       // threshold every second... Can this be made non-blocking?
  48.   for (uint8_t i=0;i<10;i++)
  49.   {
  50.     tone(SPEAKER, 100+(uint16_t)i*50,50);
  51.     delay(50);
  52.   }
  53. }
  54.  
  55. void WaitingBeep(void)
  56. {
  57.   tone(SPEAKER, 100, 200);  
  58. }
  59.  
  60. void LowSignalBeep(void)
  61. {
  62.   tone(SPEAKER, 900,200);
  63. }
  64.  
  65.          
  66. // the setup function runs once when you press reset or power the board
  67. void setup() {
  68.   Serial.begin(115200);
  69.  
  70.   Serial.println("Setup radio...");
  71.  
  72.   Mirf.spi = &MirfHardwareSpi;
  73.   Mirf.init();
  74.   Mirf.payload = sizeof(radio_packet);
  75.   Mirf.channel = 2;
  76.   Mirf.config();
  77.  
  78.   Mirf.configRegister(EN_AA, (1 << ENAA_P0)| (1 << ENAA_P1));
  79.  
  80.   Mirf.setTADDR(tx_address);
  81.   Mirf.setRADDR(rx_address);
  82.  
  83.   Mirf.configRegister(SETUP_RETR, 0b0000 | 0b1111); // MAX auto re-transmit time, max 15 retries (MAX)
  84.    
  85. // Setup PS2 controller:
  86.   uint8_t error=1, pressures=0,rumble=0;
  87.  
  88.   Serial.println("Connecting to PS2 controller...");
  89.   while(error==1)
  90.   {
  91.     error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);
  92.  
  93.   if(error == 0){
  94.     Serial.print("Found Controller, configured successful ");
  95.     Serial.print("pressures = ");
  96.   if (pressures)
  97.     Serial.println("true ");
  98.   else
  99.     Serial.println("false");
  100.   Serial.print("rumble = ");
  101.   if (rumble)
  102.     Serial.println("true)");
  103.   else
  104.     Serial.println("false");
  105.   }  
  106.   else if(error == 1)
  107.     Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");
  108.    
  109.   else if(error == 2)
  110.     Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");
  111.  
  112.   else if(error == 3)
  113.     Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
  114.    
  115.   } // End while
  116.   Serial.println("DONE");
  117.  
  118.   uint8_t type = ps2x.readType();
  119.   switch(type) {
  120.     case 0:
  121.       Serial.print("Unknown Controller type found ");
  122.       break;
  123.     case 1:
  124.       Serial.print("DualShock Controller found ");
  125.       break;
  126.     case 2:
  127.       Serial.print("GuitarHero Controller found ");
  128.       break;
  129.   case 3:
  130.       Serial.print("Wireless Sony DualShock Controller found ");
  131.       break;
  132.    }
  133.  
  134.    pinMode(MY_LED, OUTPUT);
  135.    toggleLED(10, 100);
  136.  
  137.    playMelody();
  138. }
  139.  
  140. void toggleLED(uint8_t flashes, uint8_t spacing)
  141. {
  142.   for (uint8_t i=0; i<flashes; i++)
  143.   {
  144.     digitalWrite(MY_LED,HIGH);
  145.     delay(spacing); // in milliseconds
  146.     digitalWrite(MY_LED,LOW);
  147.     delay(spacing); // in milliseconds
  148.   }
  149. }
  150.  
  151. void flushTx(void)
  152. {
  153.     Mirf.csnLow();                    // Pull down chip select
  154.     Mirf.spi->transfer( FLUSH_TX );     // Write cmd to flush tx fifo
  155.     Mirf.csnHi();                    // Pull up chip select
  156. }
  157.  
  158. // the loop function runs over and over again forever
  159. void loop() {
  160.  
  161.   enum connection_state radio_state;
  162.   long mytime=0;
  163.   uint16_t packets_sent=0;
  164.  
  165.   radio_state = WAITING;
  166.  
  167.   Mirf.flushRx();
  168.   flushTx();
  169.  
  170.   mytime = millis();
  171.  
  172.   while(1)
  173.   {
  174.   ps2x.read_gamepad(false, 0); //read controller and set large motor to spin at 'vibrate' speed
  175.  
  176.   radioData.buttons1 = ps2x.Button(PSB_L1)<<7 | ps2x.Button(PSB_L2)<<6 | ps2x.Button(PSB_R1) << 5 | ps2x.Button(PSB_R2) << 4 | ps2x.Button(PSB_PAD_UP) << 3 | ps2x.Button(PSB_PAD_RIGHT)<<2 | ps2x.Button(PSB_PAD_DOWN)<<1 | ps2x.Button(PSB_PAD_LEFT);
  177.   radioData.buttons2 = ps2x.Button(PSB_CIRCLE)<<7 | ps2x.Button(PSB_CROSS)<<6 | ps2x.Button(PSB_TRIANGLE)<<5 | ps2x.Button(PSB_SQUARE)<<4 | ps2x.Button(PSB_START) << 2 | ps2x.Button(PSB_SELECT)<<1;
  178.   radioData.leftX = ps2x.Analog(PSS_LX);
  179.   radioData.leftY = ps2x.Analog(PSS_LY);
  180.   radioData.rightX = ps2x.Analog(PSS_RX);
  181.   radioData.rightY = ps2x.Analog(PSS_RY);
  182.  
  183.   // Send radio data  
  184.           Mirf.setTADDR(tx_address);
  185.           Mirf.send((uint8_t *)&radioData);
  186.  
  187.           //while(Mirf.issending());
  188.          
  189.           uint8_t status, sending;
  190.           sending=1;
  191.          
  192.           while(sending)
  193.           {
  194.             status=Mirf.getStatus();
  195.             if (status & ((1 << TX_DS)  | (1 << MAX_RT)) ) sending=0;
  196.           }
  197.  
  198.           Mirf.isSending(); // Make a call to this so that powerUpRx is called and handled correctly (could also just call powerUpRx ourselves but this feels safer)
  199.          
  200.          if (status & (1 << TX_DS))
  201.             packets_sent++;
  202.  
  203.          if (millis()-mytime>=1000)
  204.          {
  205.           Serial.print("Packets sent:"); Serial.println(packets_sent);
  206.  
  207.           if (packets_sent==0) {WaitingBeep(); radio_state=WAITING;}
  208.           else if (packets_sent<200) {LowSignalBeep();radio_state=POOR;}
  209.           else if (radio_state!=GOOD) {ConnectedBeep();radio_state=GOOD;}
  210.  
  211.           if (radio_state==GOOD) toggle_pin(PORTD, 6); //pin PD6 - slow flash
  212.           else if (radio_state==WAITING) PORTD |= (1<<6); // set pin high - constant if waiting (plus hear low beep)
  213.           packets_sent=0;
  214.           mytime=millis();
  215.          }
  216.      
  217. } // end while
  218.  
  219. } // end loop
Add Comment
Please, Sign In to add comment