找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1717|回复: 0
打印 上一主题 下一主题
收起左侧

分享一份关于arduino的ps2的库

[复制链接]
跳转到指定楼层
楼主
ID:620239 发表于 2020-7-16 09:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include "PS2X_lib.h"
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <stdint.h>
  5. #include <avr/io.h>
  6. #if ARDUINO > 22
  7.   #include "Arduino.h"
  8. #else
  9.   #include "WProgram.h"
  10.   #include "pins_arduino.h"
  11. #endif

  12. static byte enter_config[]={0x01,0x43,0x00,0x01,0x00};
  13. static byte set_mode[]={0x01,0x44,0x00,0x01,0x03,0x00,0x00,0x00,0x00};
  14. static byte set_bytes_large[]={0x01,0x4F,0x00,0xFF,0xFF,0x03,0x00,0x00,0x00};
  15. static byte exit_config[]={0x01,0x43,0x00,0x00,0x5A,0x5A,0x5A,0x5A,0x5A};
  16. static byte enable_rumble[]={0x01,0x4D,0x00,0x00,0x01};
  17. static byte type_read[]={0x01,0x45,0x00,0x5A,0x5A,0x5A,0x5A,0x5A,0x5A};

  18. /****************************************************************************************/
  19. boolean PS2X::NewButtonState() {
  20.   return ((last_buttons ^ buttons) > 0);
  21. }

  22. /****************************************************************************************/
  23. boolean PS2X::NewButtonState(unsigned int button) {
  24.   return (((last_buttons ^ buttons) & button) > 0);
  25. }

  26. /****************************************************************************************/
  27. boolean PS2X::ButtonPressed(unsigned int button) {
  28.   return(NewButtonState(button) & Button(button));
  29. }

  30. /****************************************************************************************/
  31. boolean PS2X::ButtonReleased(unsigned int button) {
  32.   return((NewButtonState(button)) & ((~last_buttons & button) > 0));
  33. }

  34. /****************************************************************************************/
  35. boolean PS2X::Button(uint16_t button) {
  36.   return ((~buttons & button) > 0);
  37. }

  38. /****************************************************************************************/
  39. unsigned int PS2X::ButtonDataByte() {
  40.    return (~buttons);
  41. }

  42. /****************************************************************************************/
  43. byte PS2X::Analog(byte button) {
  44.    return PS2data[button];
  45. }

  46. /****************************************************************************************/
  47. unsigned char PS2X::_gamepad_shiftinout (char byte) {
  48.    unsigned char tmp = 0;
  49.    for(unsigned char i=0;i<8;i++) {
  50.       if(CHK(byte,i)) CMD_SET();
  51.       else CMD_CLR();
  52.           
  53.       CLK_CLR();
  54.       delayMicroseconds(CTRL_CLK);

  55.       //if(DAT_CHK()) SET(tmp,i);
  56.       if(DAT_CHK()) bitSet(tmp,i);

  57.       CLK_SET();
  58. #if CTRL_CLK_HIGH
  59.       delayMicroseconds(CTRL_CLK_HIGH);
  60. #endif
  61.    }
  62.    CMD_SET();
  63.    delayMicroseconds(CTRL_BYTE_DELAY);
  64.    return tmp;
  65. }

  66. /****************************************************************************************/
  67. void PS2X::read_gamepad() {
  68.    read_gamepad(false, 0x00);
  69. }

  70. /****************************************************************************************/
  71. boolean PS2X::read_gamepad(boolean motor1, byte motor2) {
  72.    double temp = millis() - last_read;

  73.    if (temp > 1500) //waited to long
  74.       reconfig_gamepad();

  75.    if(temp < read_delay)  //waited too short
  76.       delay(read_delay - temp);

  77.    if(motor2 != 0x00)
  78.       motor2 = map(motor2,0,255,0x40,0xFF); //noting below 40 will make it spin

  79.    char dword[9] = {0x01,0x42,0,motor1,motor2,0,0,0,0};
  80.    byte dword2[12] = {0,0,0,0,0,0,0,0,0,0,0,0};

  81.    // Try a few times to get valid data...
  82.    for (byte RetryCnt = 0; RetryCnt < 5; RetryCnt++) {
  83.       CMD_SET();
  84.       CLK_SET();
  85.       ATT_CLR(); // low enable joystick

  86.       delayMicroseconds(CTRL_BYTE_DELAY);
  87.       //Send the command to send button and joystick data;
  88.       for (int i = 0; i<9; i++) {
  89.          PS2data[i] = _gamepad_shiftinout(dword[i]);
  90.       }

  91.       if(PS2data[1] == 0x79) {  //if controller is in full data return mode, get the rest of data
  92.          for (int i = 0; i<12; i++) {
  93.             PS2data[i+9] = _gamepad_shiftinout(dword2[i]);
  94.          }
  95.       }

  96.       ATT_SET(); // HI disable joystick
  97.       // Check to see if we received valid data or not.  
  98.           // We should be in analog mode for our data to be valid (analog == 0x7_)
  99.       if ((PS2data[1] & 0xf0) == 0x70)
  100.          break;

  101.       // If we got to here, we are not in analog mode, try to recover...
  102.       reconfig_gamepad(); // try to get back into Analog mode.
  103.       delay(read_delay);
  104.    }

  105.    // If we get here and still not in analog mode (=0x7_), try increasing the read_delay...
  106.    if ((PS2data[1] & 0xf0) != 0x70) {
  107.       if (read_delay < 10)
  108.          read_delay++;   // see if this helps out...
  109.    }

  110. #ifdef PS2X_COM_DEBUG
  111.    Serial.println("OUT:IN");
  112.    for(int i=0; i<9; i++){
  113.       Serial.print(dword[i], HEX);
  114.       Serial.print(":");
  115.       Serial.print(PS2data[i], HEX);
  116.       Serial.print(" ");
  117.    }
  118.    for (int i = 0; i<12; i++) {
  119.       Serial.print(dword2[i], HEX);
  120.       Serial.print(":");
  121.       Serial.print(PS2data[i+9], HEX);
  122.       Serial.print(" ");
  123.    }
  124.    Serial.println("");
  125. #endif

  126.    last_buttons = buttons; //store the previous buttons states

  127. #if defined(__AVR__)
  128.    buttons = *(uint16_t*)(PS2data+3);   //store as one value for multiple functions
  129. #else
  130.    buttons =  (uint16_t)(PS2data[4] << 8) + PS2data[3];   //store as one value for multiple functions
  131. #endif
  132.    last_read = millis();
  133.    return ((PS2data[1] & 0xf0) == 0x70);  // 1 = OK = analog mode - 0 = NOK
  134. }

  135. /****************************************************************************************/
  136. byte PS2X::config_gamepad(uint8_t clk, uint8_t cmd, uint8_t att, uint8_t dat) {
  137.    return config_gamepad(clk, cmd, att, dat, false, false);
  138. }

  139. /****************************************************************************************/
  140. byte PS2X::config_gamepad(uint8_t clk, uint8_t cmd, uint8_t att, uint8_t dat, bool pressures, bool rumble) {

  141.   byte temp[sizeof(type_read)];

  142. #ifdef __AVR__
  143.   _clk_mask = digitalPinToBitMask(clk);
  144.   _clk_oreg = portOutputRegister(digitalPinToPort(clk));
  145.   _cmd_mask = digitalPinToBitMask(cmd);
  146.   _cmd_oreg = portOutputRegister(digitalPinToPort(cmd));
  147.   _att_mask = digitalPinToBitMask(att);
  148.   _att_oreg = portOutputRegister(digitalPinToPort(att));
  149.   _dat_mask = digitalPinToBitMask(dat);
  150.   _dat_ireg = portInputRegister(digitalPinToPort(dat));
  151. #else
  152.   uint32_t            lport;                   // Port number for this pin
  153.   _clk_mask = digitalPinToBitMask(clk);
  154.   lport = digitalPinToPort(clk);
  155.   _clk_lport_set = portOutputRegister(lport) + 2;
  156.   _clk_lport_clr = portOutputRegister(lport) + 1;

  157.   _cmd_mask = digitalPinToBitMask(cmd);
  158.   lport = digitalPinToPort(cmd);
  159.   _cmd_lport_set = portOutputRegister(lport) + 2;
  160.   _cmd_lport_clr = portOutputRegister(lport) + 1;

  161.   _att_mask = digitalPinToBitMask(att);
  162.   lport = digitalPinToPort(att);
  163.   _att_lport_set = portOutputRegister(lport) + 2;
  164.   _att_lport_clr = portOutputRegister(lport) + 1;

  165.   _dat_mask = digitalPinToBitMask(dat);
  166.   _dat_lport = portInputRegister(digitalPinToPort(dat));
  167. #endif

  168.   pinMode(clk, OUTPUT); //configure ports
  169.   pinMode(att, OUTPUT);
  170.   pinMode(cmd, OUTPUT);
  171.   pinMode(dat, INPUT);

  172. #if defined(__AVR__)
  173.   digitalWrite(dat, HIGH); //enable pull-up
  174. #endif

  175.   CMD_SET(); // SET(*_cmd_oreg,_cmd_mask);
  176.   CLK_SET();

  177.   //new error checking. First, read gamepad a few times to see if it's talking
  178.   read_gamepad();
  179.   read_gamepad();

  180.   //see if it talked - see if mode came back.
  181.   //If still anything but 41, 73 or 79, then it's not talking
  182.   if(PS2data[1] != 0x41 && PS2data[1] != 0x73 && PS2data[1] != 0x79){
  183. #ifdef PS2X_DEBUG
  184.     Serial.println("Controller mode not matched or no controller found");
  185.     Serial.print("Expected 0x41, 0x73 or 0x79, but got ");
  186.     Serial.println(PS2data[1], HEX);
  187. #endif
  188.     return 1; //return error code 1
  189.   }

  190.   //try setting mode, increasing delays if need be.
  191.   read_delay = 1;

  192.   for(int y = 0; y <= 10; y++) {
  193.     sendCommandString(enter_config, sizeof(enter_config)); //start config run

  194.     //read type
  195.     delayMicroseconds(CTRL_BYTE_DELAY);

  196.     CMD_SET();
  197.     CLK_SET();
  198.     ATT_CLR(); // low enable joystick

  199.     delayMicroseconds(CTRL_BYTE_DELAY);

  200.     for (int i = 0; i<9; i++) {
  201.       temp[i] = _gamepad_shiftinout(type_read[i]);
  202.     }

  203.     ATT_SET(); // HI disable joystick

  204.     controller_type = temp[3];

  205.     sendCommandString(set_mode, sizeof(set_mode));
  206.     if(rumble){ sendCommandString(enable_rumble, sizeof(enable_rumble)); en_Rumble = true; }
  207.     if(pressures){ sendCommandString(set_bytes_large, sizeof(set_bytes_large)); en_Pressures = true; }
  208.     sendCommandString(exit_config, sizeof(exit_config));

  209.     read_gamepad();

  210.     if(pressures){
  211.       if(PS2data[1] == 0x79)
  212.         break;
  213.       if(PS2data[1] == 0x73)
  214.         return 3;
  215.     }

  216.     if(PS2data[1] == 0x73)
  217.       break;

  218.     if(y == 10){
  219. #ifdef PS2X_DEBUG
  220.       Serial.println("Controller not accepting commands");
  221.       Serial.print("mode stil set at");
  222.       Serial.println(PS2data[1], HEX);
  223. #endif
  224.       return 2; //exit function with error
  225.     }
  226.     read_delay += 1; //add 1ms to read_delay
  227.   }
  228.   return 0; //no error if here
  229. }

  230. /****************************************************************************************/
  231. void PS2X::sendCommandString(byte string[], byte len) {
  232. #ifdef PS2X_COM_DEBUG
  233.   byte temp[len];
  234.   ATT_CLR(); // low enable joystick
  235.   delayMicroseconds(CTRL_BYTE_DELAY);

  236.   for (int y=0; y < len; y++)
  237.     temp[y] = _gamepad_shiftinout(string[y]);

  238.   ATT_SET(); //high disable joystick
  239.   delay(read_delay); //wait a few

  240.   Serial.println("OUT:IN Configure");
  241.   for(int i=0; i<len; i++) {
  242.     Serial.print(string[i], HEX);
  243.     Serial.print(":");
  244.     Serial.print(temp[i], HEX);
  245.     Serial.print(" ");
  246.   }
  247.   Serial.println("");
  248. #else
  249.   ATT_CLR(); // low enable joystick
  250.   for (int y=0; y < len; y++)
  251.     _gamepad_shiftinout(string[y]);
  252.   ATT_SET(); //high disable joystick
  253.   delay(read_delay);                  //wait a few
  254. #endif
  255. }

  256. /****************************************************************************************/
  257. byte PS2X::readType() {
  258. /*
  259.   byte temp[sizeof(type_read)];

  260.   sendCommandString(enter_config, sizeof(enter_config));

  261.   delayMicroseconds(CTRL_BYTE_DELAY);

  262.   CMD_SET();
  263.   CLK_SET();
  264.   ATT_CLR(); // low enable joystick

  265.   delayMicroseconds(CTRL_BYTE_DELAY);

  266.   for (int i = 0; i<9; i++) {
  267.     temp[i] = _gamepad_shiftinout(type_read[i]);
  268.   }

  269.   sendCommandString(exit_config, sizeof(exit_config));

  270.   if(temp[3] == 0x03)
  271.     return 1;
  272.   else if(temp[3] == 0x01)
  273.     return 2;

  274.   return 0;
  275. */

  276.   if(controller_type == 0x03)
  277.     return 1;
  278.   else if(controller_type == 0x01)
  279.     return 2;
  280.   else if(controller_type == 0x0C)  
  281.     return 3;  //2.4G Wireless Dual Shock PS2 Game Controller
  282.        
  283.   return 0;
  284. }

  285. /****************************************************************************************/
  286. void PS2X::enableRumble() {
  287.   sendCommandString(enter_config, sizeof(enter_config));
  288.   sendCommandString(enable_rumble, sizeof(enable_rumble));
  289.   sendCommandString(exit_config, sizeof(exit_config));
  290.   en_Rumble = true;
  291. }

  292. /****************************************************************************************/
  293. bool PS2X::enablePressures() {
  294.   sendCommandString(enter_config, sizeof(enter_config));
  295.   sendCommandString(set_bytes_large, sizeof(set_bytes_large));
  296.   sendCommandString(exit_config, sizeof(exit_config));

  297.   read_gamepad();
  298.   read_gamepad();

  299.   if(PS2data[1] != 0x79)
  300.     return false;

  301.   en_Pressures = true;
  302.     return true;
  303. }

  304. /****************************************************************************************/
  305. void PS2X::reconfig_gamepad(){
  306.   sendCommandString(enter_config, sizeof(enter_config));
  307.   sendCommandString(set_mode, sizeof(set_mode));
  308.   if (en_Rumble)
  309.     sendCommandString(enable_rumble, sizeof(enable_rumble));
  310.   if (en_Pressures)
  311.     sendCommandString(set_bytes_large, sizeof(set_bytes_large));
  312.   sendCommandString(exit_config, sizeof(exit_config));
  313. }

  314. /****************************************************************************************/
  315. #ifdef __AVR__
  316. inline void  PS2X::CLK_SET(void) {
  317.   register uint8_t old_sreg = SREG;
  318.   cli();
  319.   *_clk_oreg |= _clk_mask;
  320.   SREG = old_sreg;
  321. }

  322. inline void  PS2X::CLK_CLR(void) {
  323.   register uint8_t old_sreg = SREG;
  324.   cli();
  325.   *_clk_oreg &= ~_clk_mask;
  326.   SREG = old_sreg;
  327. }

  328. inline void  PS2X::CMD_SET(void) {
  329.   register uint8_t old_sreg = SREG;
  330.   cli();
  331.   *_cmd_oreg |= _cmd_mask; // SET(*_cmd_oreg,_cmd_mask);
  332.   SREG = old_sreg;
  333. }

  334. inline void  PS2X::CMD_CLR(void) {
  335.   register uint8_t old_sreg = SREG;
  336.   cli();
  337.   *_cmd_oreg &= ~_cmd_mask; // SET(*_cmd_oreg,_cmd_mask);
  338.   SREG = old_sreg;
  339. }

  340. ……………………

  341. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码


PS2X_lib.zip

5.83 KB, 下载次数: 7, 下载积分: 黑币 -5

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表