PS2X_lib.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. #include "PS2X_lib.h"
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <stdint.h>
  5. #ifdef __AVR__
  6. #include <avr/io.h>
  7. #endif
  8. #if ARDUINO > 22
  9. #include "Arduino.h"
  10. #else
  11. #include "WProgram.h"
  12. #include "pins_arduino.h"
  13. #endif
  14. static byte enter_config[]={0x01,0x43,0x00,0x01,0x00};
  15. static byte set_mode[]={0x01,0x44,0x00,0x01,0x03,0x00,0x00,0x00,0x00};
  16. static byte set_bytes_large[]={0x01,0x4F,0x00,0xFF,0xFF,0x03,0x00,0x00,0x00};
  17. static byte exit_config[]={0x01,0x43,0x00,0x00,0x5A,0x5A,0x5A,0x5A,0x5A};
  18. static byte enable_rumble[]={0x01,0x4D,0x00,0x00,0x01};
  19. static byte type_read[]={0x01,0x45,0x00,0x5A,0x5A,0x5A,0x5A,0x5A,0x5A};
  20. /****************************************************************************************/
  21. boolean PS2X::NewButtonState() {
  22. return ((last_buttons ^ buttons) > 0);
  23. }
  24. /****************************************************************************************/
  25. boolean PS2X::NewButtonState(unsigned int button) {
  26. return (((last_buttons ^ buttons) & button) > 0);
  27. }
  28. /****************************************************************************************/
  29. boolean PS2X::ButtonPressed(unsigned int button) {
  30. return(NewButtonState(button) & Button(button));
  31. }
  32. /****************************************************************************************/
  33. boolean PS2X::ButtonReleased(unsigned int button) {
  34. return((NewButtonState(button)) & ((~last_buttons & button) > 0));
  35. }
  36. /****************************************************************************************/
  37. boolean PS2X::Button(uint16_t button) {
  38. return ((~buttons & button) > 0);
  39. }
  40. /****************************************************************************************/
  41. unsigned int PS2X::ButtonDataByte() {
  42. return (~buttons);
  43. }
  44. /****************************************************************************************/
  45. byte PS2X::Analog(byte button) {
  46. return PS2data[button];
  47. }
  48. /****************************************************************************************/
  49. unsigned char PS2X::_gamepad_shiftinout (char byte) {
  50. unsigned char tmp = 0;
  51. for(unsigned char i=0;i<8;i++) {
  52. if(CHK(byte,i)) CMD_SET();
  53. else CMD_CLR();
  54. CLK_CLR();
  55. delayMicroseconds(CTRL_CLK);
  56. //if(DAT_CHK()) SET(tmp,i);
  57. if(DAT_CHK()) bitSet(tmp,i);
  58. CLK_SET();
  59. #if CTRL_CLK_HIGH
  60. delayMicroseconds(CTRL_CLK_HIGH);
  61. #endif
  62. }
  63. CMD_SET();
  64. delayMicroseconds(CTRL_BYTE_DELAY);
  65. return tmp;
  66. }
  67. /****************************************************************************************/
  68. void PS2X::read_gamepad() {
  69. read_gamepad(false, 0x00);
  70. }
  71. /****************************************************************************************/
  72. boolean PS2X::read_gamepad(boolean motor1, byte motor2) {
  73. double temp = millis() - last_read;
  74. if (temp > 1500) //waited to long
  75. reconfig_gamepad();
  76. if(temp < read_delay) //waited too short
  77. delay(read_delay - temp);
  78. if(motor2 != 0x00)
  79. motor2 = map(motor2,0,255,0x40,0xFF); //noting below 40 will make it spin
  80. byte dword[9] = {0x01,0x42,0,motor1,motor2,0,0,0,0};
  81. byte dword2[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
  82. // Try a few times to get valid data...
  83. for (byte RetryCnt = 0; RetryCnt < 5; RetryCnt++) {
  84. CMD_SET();
  85. CLK_SET();
  86. ATT_CLR(); // low enable joystick
  87. delayMicroseconds(CTRL_BYTE_DELAY);
  88. //Send the command to send button and joystick data;
  89. for (int i = 0; i<9; i++) {
  90. PS2data[i] = _gamepad_shiftinout(dword[i]);
  91. }
  92. if(PS2data[1] == 0x79) { //if controller is in full data return mode, get the rest of data
  93. for (int i = 0; i<12; i++) {
  94. PS2data[i+9] = _gamepad_shiftinout(dword2[i]);
  95. }
  96. }
  97. ATT_SET(); // HI disable joystick
  98. // Check to see if we received valid data or not.
  99. // We should be in analog mode for our data to be valid (analog == 0x7_)
  100. if ((PS2data[1] & 0xf0) == 0x70)
  101. break;
  102. // If we got to here, we are not in analog mode, try to recover...
  103. reconfig_gamepad(); // try to get back into Analog mode.
  104. delay(read_delay);
  105. }
  106. // If we get here and still not in analog mode (=0x7_), try increasing the read_delay...
  107. if ((PS2data[1] & 0xf0) != 0x70) {
  108. if (read_delay < 10)
  109. read_delay++; // see if this helps out...
  110. }
  111. #ifdef PS2X_COM_DEBUG
  112. Serial.print("OUT:IN ");
  113. for(int i=0; i<9; i++){
  114. Serial.print(dword[i], HEX);
  115. Serial.print(":");
  116. Serial.print(PS2data[i], HEX);
  117. Serial.print(" ");
  118. }
  119. for (int i = 0; i<12; i++) {
  120. Serial.print(dword2[i], HEX);
  121. Serial.print(":");
  122. Serial.print(PS2data[i+9], HEX);
  123. Serial.print(" ");
  124. }
  125. Serial.println("");
  126. #endif
  127. last_buttons = buttons; //store the previous buttons states
  128. #if defined(__AVR__)
  129. buttons = *(uint16_t*)(PS2data+3); //store as one value for multiple functions
  130. #else
  131. buttons = (uint16_t)(PS2data[4] << 8) + PS2data[3]; //store as one value for multiple functions
  132. #endif
  133. last_read = millis();
  134. return ((PS2data[1] & 0xf0) == 0x70); // 1 = OK = analog mode - 0 = NOK
  135. }
  136. /****************************************************************************************/
  137. byte PS2X::config_gamepad(uint8_t clk, uint8_t cmd, uint8_t att, uint8_t dat) {
  138. return config_gamepad(clk, cmd, att, dat, false, false);
  139. }
  140. /****************************************************************************************/
  141. byte PS2X::config_gamepad(uint8_t clk, uint8_t cmd, uint8_t att, uint8_t dat, bool pressures, bool rumble) {
  142. byte temp[sizeof(type_read)];
  143. #ifdef __AVR__
  144. _clk_mask = digitalPinToBitMask(clk);
  145. _clk_oreg = portOutputRegister(digitalPinToPort(clk));
  146. _cmd_mask = digitalPinToBitMask(cmd);
  147. _cmd_oreg = portOutputRegister(digitalPinToPort(cmd));
  148. _att_mask = digitalPinToBitMask(att);
  149. _att_oreg = portOutputRegister(digitalPinToPort(att));
  150. _dat_mask = digitalPinToBitMask(dat);
  151. _dat_ireg = portInputRegister(digitalPinToPort(dat));
  152. #else
  153. #if defined(ESP8266) || defined(ESP32)
  154. _clk_pin = clk;
  155. _cmd_pin = cmd;
  156. _att_pin = att;
  157. _dat_pin = dat;
  158. #else
  159. uint32_t lport; // Port number for this pin
  160. _clk_mask = digitalPinToBitMask(clk);
  161. lport = digitalPinToPort(clk);
  162. _clk_lport_set = portOutputRegister(lport) + 2;
  163. _clk_lport_clr = portOutputRegister(lport) + 1;
  164. _cmd_mask = digitalPinToBitMask(cmd);
  165. lport = digitalPinToPort(cmd);
  166. _cmd_lport_set = portOutputRegister(lport) + 2;
  167. _cmd_lport_clr = portOutputRegister(lport) + 1;
  168. _att_mask = digitalPinToBitMask(att);
  169. lport = digitalPinToPort(att);
  170. _att_lport_set = portOutputRegister(lport) + 2;
  171. _att_lport_clr = portOutputRegister(lport) + 1;
  172. _dat_mask = digitalPinToBitMask(dat);
  173. _dat_lport = portInputRegister(digitalPinToPort(dat));
  174. #endif
  175. #endif
  176. pinMode(clk, OUTPUT); //configure ports
  177. pinMode(att, OUTPUT);
  178. pinMode(cmd, OUTPUT);
  179. #if defined(ESP8266) || defined(ESP32)
  180. pinMode(dat, INPUT_PULLUP); // enable pull-up
  181. #else
  182. pinMode(dat, INPUT);
  183. #endif
  184. #if defined(__AVR__)
  185. digitalWrite(dat, HIGH); //enable pull-up
  186. #endif
  187. CMD_SET(); // SET(*_cmd_oreg,_cmd_mask);
  188. CLK_SET();
  189. //new error checking. First, read gamepad a few times to see if it's talking
  190. read_gamepad();
  191. read_gamepad();
  192. //see if it talked - see if mode came back.
  193. //If still anything but 41, 73 or 79, then it's not talking
  194. if(PS2data[1] != 0x41 && PS2data[1] != 0x42 && PS2data[1] != 0x73 && PS2data[1] != 0x79){
  195. #ifdef PS2X_DEBUG
  196. Serial.println("Controller mode not matched or no controller found");
  197. Serial.print("Expected 0x41, 0x42, 0x73 or 0x79, but got ");
  198. Serial.println(PS2data[1], HEX);
  199. #endif
  200. return 1; //return error code 1
  201. }
  202. //try setting mode, increasing delays if need be.
  203. read_delay = 1;
  204. for(int y = 0; y <= 10; y++) {
  205. sendCommandString(enter_config, sizeof(enter_config)); //start config run
  206. //read type
  207. delayMicroseconds(CTRL_BYTE_DELAY);
  208. CMD_SET();
  209. CLK_SET();
  210. ATT_CLR(); // low enable joystick
  211. delayMicroseconds(CTRL_BYTE_DELAY);
  212. for (int i = 0; i<9; i++) {
  213. temp[i] = _gamepad_shiftinout(type_read[i]);
  214. }
  215. ATT_SET(); // HI disable joystick
  216. controller_type = temp[3];
  217. sendCommandString(set_mode, sizeof(set_mode));
  218. if(rumble){ sendCommandString(enable_rumble, sizeof(enable_rumble)); en_Rumble = true; }
  219. if(pressures){ sendCommandString(set_bytes_large, sizeof(set_bytes_large)); en_Pressures = true; }
  220. sendCommandString(exit_config, sizeof(exit_config));
  221. read_gamepad();
  222. if(pressures){
  223. if(PS2data[1] == 0x79)
  224. break;
  225. if(PS2data[1] == 0x73)
  226. return 3;
  227. }
  228. if(PS2data[1] == 0x73)
  229. break;
  230. if(y == 10){
  231. #ifdef PS2X_DEBUG
  232. Serial.println("Controller not accepting commands");
  233. Serial.print("mode still set at");
  234. Serial.println(PS2data[1], HEX);
  235. #endif
  236. return 2; //exit function with error
  237. }
  238. read_delay += 1; //add 1ms to read_delay
  239. }
  240. return 0; //no error if here
  241. }
  242. /****************************************************************************************/
  243. void PS2X::sendCommandString(byte string[], byte len) {
  244. #ifdef PS2X_COM_DEBUG
  245. byte temp[len];
  246. ATT_CLR(); // low enable joystick
  247. delayMicroseconds(CTRL_BYTE_DELAY);
  248. for (int y=0; y < len; y++)
  249. temp[y] = _gamepad_shiftinout(string[y]);
  250. ATT_SET(); //high disable joystick
  251. delay(read_delay); //wait a few
  252. Serial.println("OUT:IN Configure");
  253. for(int i=0; i<len; i++) {
  254. Serial.print(string[i], HEX);
  255. Serial.print(":");
  256. Serial.print(temp[i], HEX);
  257. Serial.print(" ");
  258. }
  259. Serial.println("");
  260. #else
  261. ATT_CLR(); // low enable joystick
  262. delayMicroseconds(CTRL_BYTE_DELAY);
  263. for (int y=0; y < len; y++)
  264. _gamepad_shiftinout(string[y]);
  265. ATT_SET(); //high disable joystick
  266. delay(read_delay); //wait a few
  267. #endif
  268. }
  269. /****************************************************************************************/
  270. byte PS2X::readType() {
  271. /*
  272. byte temp[sizeof(type_read)];
  273. sendCommandString(enter_config, sizeof(enter_config));
  274. delayMicroseconds(CTRL_BYTE_DELAY);
  275. CMD_SET();
  276. CLK_SET();
  277. ATT_CLR(); // low enable joystick
  278. delayMicroseconds(CTRL_BYTE_DELAY);
  279. for (int i = 0; i<9; i++) {
  280. temp[i] = _gamepad_shiftinout(type_read[i]);
  281. }
  282. sendCommandString(exit_config, sizeof(exit_config));
  283. if(temp[3] == 0x03)
  284. return 1;
  285. else if(temp[3] == 0x01)
  286. return 2;
  287. return 0;
  288. */
  289. Serial.print("Controller_type: ");
  290. Serial.println(controller_type, HEX);
  291. if(controller_type == 0x03)
  292. return 1;
  293. else if(controller_type == 0x01 && PS2data[1] == 0x42)
  294. return 4;
  295. else if(controller_type == 0x01 && PS2data[1] != 0x42)
  296. return 2;
  297. else if(controller_type == 0x0C)
  298. return 3; //2.4G Wireless Dual Shock PS2 Game Controller
  299. return 0;
  300. }
  301. /****************************************************************************************/
  302. void PS2X::enableRumble() {
  303. sendCommandString(enter_config, sizeof(enter_config));
  304. sendCommandString(enable_rumble, sizeof(enable_rumble));
  305. sendCommandString(exit_config, sizeof(exit_config));
  306. en_Rumble = true;
  307. }
  308. /****************************************************************************************/
  309. bool PS2X::enablePressures() {
  310. sendCommandString(enter_config, sizeof(enter_config));
  311. sendCommandString(set_bytes_large, sizeof(set_bytes_large));
  312. sendCommandString(exit_config, sizeof(exit_config));
  313. read_gamepad();
  314. read_gamepad();
  315. if(PS2data[1] != 0x79)
  316. return false;
  317. en_Pressures = true;
  318. return true;
  319. }
  320. /****************************************************************************************/
  321. void PS2X::reconfig_gamepad(){
  322. sendCommandString(enter_config, sizeof(enter_config));
  323. sendCommandString(set_mode, sizeof(set_mode));
  324. if (en_Rumble)
  325. sendCommandString(enable_rumble, sizeof(enable_rumble));
  326. if (en_Pressures)
  327. sendCommandString(set_bytes_large, sizeof(set_bytes_large));
  328. sendCommandString(exit_config, sizeof(exit_config));
  329. }
  330. /****************************************************************************************/
  331. #ifdef __AVR__
  332. inline void PS2X::CLK_SET(void) {
  333. register uint8_t old_sreg = SREG;
  334. cli();
  335. *_clk_oreg |= _clk_mask;
  336. SREG = old_sreg;
  337. }
  338. inline void PS2X::CLK_CLR(void) {
  339. register uint8_t old_sreg = SREG;
  340. cli();
  341. *_clk_oreg &= ~_clk_mask;
  342. SREG = old_sreg;
  343. }
  344. inline void PS2X::CMD_SET(void) {
  345. register uint8_t old_sreg = SREG;
  346. cli();
  347. *_cmd_oreg |= _cmd_mask; // SET(*_cmd_oreg,_cmd_mask);
  348. SREG = old_sreg;
  349. }
  350. inline void PS2X::CMD_CLR(void) {
  351. register uint8_t old_sreg = SREG;
  352. cli();
  353. *_cmd_oreg &= ~_cmd_mask; // SET(*_cmd_oreg,_cmd_mask);
  354. SREG = old_sreg;
  355. }
  356. inline void PS2X::ATT_SET(void) {
  357. register uint8_t old_sreg = SREG;
  358. cli();
  359. *_att_oreg |= _att_mask ;
  360. SREG = old_sreg;
  361. }
  362. inline void PS2X::ATT_CLR(void) {
  363. register uint8_t old_sreg = SREG;
  364. cli();
  365. *_att_oreg &= ~_att_mask;
  366. SREG = old_sreg;
  367. }
  368. inline bool PS2X::DAT_CHK(void) {
  369. return (*_dat_ireg & _dat_mask) ? true : false;
  370. }
  371. #else
  372. #if defined(ESP8266) || defined(ESP32)
  373. // Let's just use digitalWrite() on ESP8266.
  374. inline void PS2X::CLK_SET(void) {
  375. digitalWrite(_clk_pin, HIGH);
  376. }
  377. inline void PS2X::CLK_CLR(void) {
  378. digitalWrite(_clk_pin, LOW);
  379. }
  380. inline void PS2X::CMD_SET(void) {
  381. digitalWrite(_cmd_pin, HIGH);
  382. }
  383. inline void PS2X::CMD_CLR(void) {
  384. digitalWrite(_cmd_pin, LOW);
  385. }
  386. inline void PS2X::ATT_SET(void) {
  387. digitalWrite(_att_pin, HIGH);
  388. }
  389. inline void PS2X::ATT_CLR(void) {
  390. digitalWrite(_att_pin, LOW);
  391. }
  392. inline bool PS2X::DAT_CHK(void) {
  393. return digitalRead(_dat_pin) ? true : false;
  394. }
  395. #else
  396. // On pic32, use the set/clr registers to make them atomic...
  397. inline void PS2X::CLK_SET(void) {
  398. *_clk_lport_set |= _clk_mask;
  399. }
  400. inline void PS2X::CLK_CLR(void) {
  401. *_clk_lport_clr |= _clk_mask;
  402. }
  403. inline void PS2X::CMD_SET(void) {
  404. *_cmd_lport_set |= _cmd_mask;
  405. }
  406. inline void PS2X::CMD_CLR(void) {
  407. *_cmd_lport_clr |= _cmd_mask;
  408. }
  409. inline void PS2X::ATT_SET(void) {
  410. *_att_lport_set |= _att_mask;
  411. }
  412. inline void PS2X::ATT_CLR(void) {
  413. *_att_lport_clr |= _att_mask;
  414. }
  415. inline bool PS2X::DAT_CHK(void) {
  416. return (*_dat_lport & _dat_mask) ? true : false;
  417. }
  418. #endif
  419. #endif