Advertisement
SlaskPrask

ESS arduino code, n64 to gc

Mar 23rd, 2018
583
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.65 KB | None | 0 0
  1. //Code written by Zas & Slask, Modified from both Andrew Brown & Moltov codes
  2.  
  3. /*
  4. Copyright (c) 2009 Andrew Brown
  5. Permission is hereby granted, free of charge, to any person
  6. obtaining a copy of this software and associated documentation
  7. files (the "Software"), to deal in the Software without
  8. restriction, including without limitation the rights to use,
  9. copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the
  11. Software is furnished to do so, subject to the following
  12. conditions:
  13.  
  14. The above copyright notice and this permission notice shall be
  15. included in all copies or substantial portions of the Software.
  16.  
  17. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  19. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  24. OTHER DEALINGS IN THE SOFTWARE.
  25. */
  26.  
  27. /*
  28. Copyright (c) 2018 Pontus Johansson & Zas_
  29.  
  30. Permission is hereby granted, free of charge, to any person
  31. obtaining a copy of this software and associated documentation
  32. files (the "Software"), to deal in the Software without
  33. restriction, including without limitation the rights to use,
  34. copy, modify, merge, publish, distribute, sublicense, and/or sell
  35. copies of the Software, and to permit persons to whom the
  36. Software is furnished to do so, subject to the following
  37. conditions:
  38.  
  39. The above copyright notice and this permission notice shall be
  40. included in all copies or substantial portions of the Software.
  41.  
  42. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  43. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  44. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  45. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  46. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  47. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  48. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  49. OTHER DEALINGS IN THE SOFTWARE.
  50. */
  51.  
  52. /* user controls */
  53. //comment to disable
  54. #define ENABLE_SERIAL //ZAS USES THIS, Used for Boards without HID capability for Input Display(N64C3)
  55. #define ENABLE_JOYSTICK //SLASK USES THIS, Used for ATmega32u4 Boards or similar for Gamepad Support
  56.  
  57. //console input pin
  58. #define GC_PIN 3
  59. #define GC_HIGH DDRD &= ~0x01
  60. #define GC_LOW DDRD |= 0x01
  61. #define GC_QUERY (PIND & 0x01)
  62.  
  63. //controller input pin
  64. #define N64_PIN 5
  65. #define N64_HIGH DDRC &= ~0x40
  66. #define N64_LOW DDRC |= 0x40
  67. #define N64_QUERY (PINC & 0x40)
  68.  
  69. /******************/
  70.  
  71. #ifdef ENABLE_JOYSTICK
  72. #include <HID-Project.h>
  73. #include <HID-Settings.h>
  74. #endif
  75.  
  76. #include "crc_table.h" //can be found at https://github.com/brownan/Gamecube-N64-Controller/blob/master/crc_table.h
  77.  
  78. #define SERIAL_SYNC (4)
  79. int serialTiming = 0;
  80.  
  81. unsigned char gc_Buffer[33];
  82.  
  83. bool needCommand = false;
  84.  
  85. char gc_Raw_Dump[281];
  86. unsigned char gc_Command;
  87. void get_GC_Command();
  88. void gc_Send(unsigned char *buffer, char length, bool wide_stop);
  89.  
  90. #define ABS(A)((A)<0?(-A):(A))
  91. #define SIGN(A)((A)==0?(0):((A)<0?(-1):(1)))
  92.  
  93. #define OOTess (23)
  94. #define OOTwalk (39)
  95. #define OOTrun (57)
  96. #define INPUTrange (64)
  97.  
  98. #define ESSstart (8)
  99. #define ESSend (27)
  100. #define OUTPUTrange (75)
  101.  
  102. struct state {
  103. char stick_x;
  104. char stick_y;
  105. // bits: 0, 0, 0, start, y, x, b, a
  106. unsigned char data1;
  107. // bits: 1, L, R, Z, Dup, Ddown, Dright, Dleft
  108. unsigned char data2;
  109. } N64_status;
  110. char N64_raw_dump[33]; // 1 received bit per byte
  111.  
  112. void setup() {
  113. #ifdef ENABLE_SERIAL
  114. Serial.begin(9600);
  115. #endif
  116.  
  117. #ifdef ENABLE_JOYSTICK
  118. //pinMode(17, OUTPUT); //Used to check usb status
  119. Gamepad.begin();
  120. #endif
  121.  
  122. //init gc buffer
  123. memset(gc_Buffer, 0, sizeof(gc_Buffer));
  124.  
  125. digitalWrite(GC_PIN, LOW);
  126. pinMode(GC_PIN, INPUT);
  127.  
  128. digitalWrite(N64_PIN, LOW);
  129. pinMode(N64_PIN, INPUT);
  130. }
  131.  
  132. void loop() {//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  133. if (needCommand == false) {
  134. getN64();
  135. translate_raw_data();
  136. #ifdef ENABLE_SERIAL
  137.  
  138. #ifndef ENABLE_JOYSTICK
  139. if (serialTiming >= SERIAL_SYNC) {
  140. print_N64_status();
  141. serialTiming = 0;
  142. } else {
  143. serialTiming++;
  144. }
  145. #endif
  146. #endif
  147.  
  148. #ifdef ENABLE_JOYSTICK
  149. if (USBSTA >> VBUS & 1)//Checks if power is coming through USB
  150. {
  151. //digitalWrite(17, LOW);
  152. if (serialTiming >= SERIAL_SYNC)
  153. {
  154. #ifdef ENABLE_SERIAL
  155. print_N64_status();
  156. #endif
  157.  
  158. update_joystick();
  159. Gamepad.write();
  160. serialTiming = 0;
  161. }
  162. else
  163. {
  164. serialTiming++;
  165. }
  166. }
  167. #endif
  168.  
  169. N64_status.stick_x = essMod(N64_status.stick_x);
  170. N64_status.stick_y = essMod(N64_status.stick_y);
  171. N64toGC();
  172.  
  173. noInterrupts();
  174. get_GC_Command(0);
  175. }
  176.  
  177. if (needCommand == true) {
  178. needCommand = false;
  179. }
  180.  
  181. switch (gc_Command) {
  182. case 0x00:
  183. case 0xff:
  184. //ID what controller you are using, return 0x090000
  185. gc_Buffer[0] = 0x29;
  186. gc_Buffer[1] = 0x00;
  187. gc_Buffer[2] = 0x20;
  188.  
  189. gc_Buffer[3] = 0x00;
  190.  
  191. gc_Send(gc_Buffer, 3, 0);
  192. needCommand = true;
  193.  
  194. get_GC_Command(0);
  195.  
  196. //Serial.println("ID command:");
  197. //Serial.println(gc_Command, HEX);
  198. break;
  199. case 0x40:
  200. //Return the data input from the classic controller
  201. gc_Send(gc_Buffer, 8, 0);
  202. get_GC_Command(1);
  203. //Serial.println("Input Request command:");
  204. //Serial.println(gc_Command, HEX);
  205. break;
  206. case 0x41:
  207. case 0x42:
  208. //
  209. gc_Buffer[0] = 0x00;
  210. gc_Buffer[1] = 0x80;
  211. gc_Buffer[2] = 0x80;
  212. gc_Buffer[3] = 0x80;
  213. gc_Buffer[4] = 0x80;
  214. gc_Buffer[5] = 0x80;
  215. gc_Buffer[6] = 0x00;
  216. gc_Buffer[7] = 0x00;
  217. gc_Buffer[8] = 0x02;
  218. gc_Buffer[9] = 0x02;
  219. gc_Send(gc_Buffer, 10, 0);
  220. //Serial.println("Origin command:");
  221. //Serial.println(gc_Command, HEX);
  222. break;
  223.  
  224. default:
  225. //
  226. //Serial.println("Error, unknown command from console.");
  227. //Serial.println(gc_Command, HEX);
  228. break;
  229. }
  230.  
  231. interrupts();
  232. }
  233.  
  234. int essMod(float v)
  235. {
  236. if (v > 128)
  237. {
  238. v -= 256;
  239. }
  240.  
  241. float amount = ABS(v);
  242. float sign = SIGN(v);
  243.  
  244. if (amount >= ESSstart) {
  245. if (amount < ESSend) {
  246. //ess
  247. amount = (OOTess + (amount - ESSstart) * (OOTwalk - OOTess) / (ESSend - ESSstart)) * sign;
  248. } else {
  249. amount = (OOTwalk + (amount - ESSend) * (INPUTrange - OOTwalk) / (OUTPUTrange - ESSend)) * sign;
  250. }
  251. } else {
  252. //less
  253. amount = (amount * OOTess / ESSstart) * sign;
  254. }
  255. return amount < 0 ? amount + 256 : amount;
  256. }
  257.  
  258. void N64_send(unsigned char *buffer, char length)
  259. {
  260. // Send these bytes
  261. char bits;
  262.  
  263. bool bit;
  264.  
  265. // This routine is very carefully timed by examining the assembly output.
  266. // Do not change any statements, it could throw the timings off
  267. //
  268. // We get 16 cycles per microsecond, which should be plenty, but we need to
  269. // be conservative. Most assembly ops take 1 cycle, but a few take 2
  270. //
  271. // I use manually constructed for-loops out of gotos so I have more control
  272. // over the outputted assembly. I can insert nops where it was impossible
  273. // with a for loop
  274.  
  275. asm volatile (";Starting outer for loop");
  276. outer_loop:
  277. {
  278. asm volatile (";Starting inner for loop");
  279. bits = 8;
  280. inner_loop:
  281. {
  282. // Starting a bit, set the line low
  283. asm volatile (";Setting line to low");
  284. N64_LOW; // 1 op, 2 cycles
  285.  
  286. asm volatile (";branching");
  287. if (*buffer >> 7) {
  288. asm volatile (";Bit is a 1");
  289. // 1 bit
  290. // remain low for 1us, then go high for 3us
  291. // nop block 1
  292. asm volatile ("nop\nnop\nnop\nnop\nnop\n");
  293.  
  294. asm volatile (";Setting line to high");
  295. N64_HIGH;
  296.  
  297. // nop block 2
  298. // we'll wait only 2us to sync up with both conditions
  299. // at the bottom of the if statement
  300. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  301. "nop\nnop\nnop\nnop\nnop\n"
  302. "nop\nnop\nnop\nnop\nnop\n"
  303. "nop\nnop\nnop\nnop\nnop\n"
  304. "nop\nnop\nnop\nnop\nnop\n"
  305. "nop\nnop\nnop\nnop\nnop\n"
  306. );
  307.  
  308. } else {
  309. asm volatile (";Bit is a 0");
  310. // 0 bit
  311. // remain low for 3us, then go high for 1us
  312. // nop block 3
  313. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  314. "nop\nnop\nnop\nnop\nnop\n"
  315. "nop\nnop\nnop\nnop\nnop\n"
  316. "nop\nnop\nnop\nnop\nnop\n"
  317. "nop\nnop\nnop\nnop\nnop\n"
  318. "nop\nnop\nnop\nnop\nnop\n"
  319. "nop\nnop\nnop\nnop\nnop\n"
  320. "nop\n");
  321.  
  322. asm volatile (";Setting line to high");
  323. N64_HIGH;
  324.  
  325. // wait for 1us
  326. asm volatile ("; end of conditional branch, need to wait 1us more before next bit");
  327.  
  328. }
  329. // end of the if, the line is high and needs to remain
  330. // high for exactly 16 more cycles, regardless of the previous
  331. // branch path
  332.  
  333. asm volatile (";finishing inner loop body");
  334. --bits;
  335. if (bits != 0) {
  336. // nop block 4
  337. // this block is why a for loop was impossible
  338. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  339. "nop\nnop\nnop\nnop\n");
  340. // rotate bits
  341. asm volatile (";rotating out bits");
  342. *buffer <<= 1;
  343.  
  344. goto inner_loop;
  345. } // fall out of inner loop
  346. }
  347. asm volatile (";continuing outer loop");
  348. // In this case: the inner loop exits and the outer loop iterates,
  349. // there are /exactly/ 16 cycles taken up by the necessary operations.
  350. // So no nops are needed here (that was lucky!)
  351. --length;
  352. if (length != 0) {
  353. ++buffer;
  354. goto outer_loop;
  355. } // fall out of outer loop
  356. }
  357.  
  358. // send a single stop (1) bit
  359. // nop block 5
  360. asm volatile ("nop\nnop\nnop\nnop\n");
  361. N64_LOW;
  362. // wait 1 us, 16 cycles, then raise the line
  363. // 16-2=14
  364. // nop block 6
  365. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  366. "nop\nnop\nnop\nnop\nnop\n"
  367. "nop\nnop\nnop\nnop\n");
  368. N64_HIGH;
  369.  
  370. }
  371.  
  372. void N64_get()
  373. {
  374. // listen for the expected 8 bytes of data back from the controller and
  375. // blast it out to the N64_raw_dump array, one bit per byte for extra speed.
  376. // Afterwards, call translate_raw_data() to interpret the raw data and pack
  377. // it into the N64_status struct.
  378. asm volatile (";Starting to listen");
  379. unsigned char timeout;
  380. char bitcount = 32;
  381. char *bitbin = N64_raw_dump;
  382.  
  383. // Again, using gotos here to make the assembly more predictable and
  384. // optimization easier (please don't kill me)
  385. read_loop:
  386. timeout = 0x3f;
  387. // wait for line to go low
  388. while (N64_QUERY) {
  389. if (!--timeout)
  390. return;
  391. }
  392. // wait approx 2us and poll the line
  393. asm volatile (
  394. "nop\nnop\nnop\nnop\nnop\n"
  395. "nop\nnop\nnop\nnop\nnop\n"
  396. "nop\nnop\nnop\nnop\nnop\n"
  397. "nop\nnop\nnop\nnop\nnop\n"
  398. "nop\nnop\nnop\nnop\nnop\n"
  399. "nop\nnop\nnop\nnop\nnop\n"
  400. );
  401. *bitbin = N64_QUERY;
  402. ++bitbin;
  403. --bitcount;
  404. if (bitcount == 0)
  405. return;
  406.  
  407. // wait for line to go high again
  408. // it may already be high, so this should just drop through
  409. timeout = 0x3f;
  410. while (!N64_QUERY) {
  411. if (!--timeout)
  412. return;
  413. }
  414. goto read_loop;
  415.  
  416. }
  417.  
  418. #ifdef ENABLE_SERIAL
  419. void print_N64_status()
  420. {
  421. char out[30];
  422. sprintf(out, "%i%i%i%i%i%i%i%i%i%i%i%i%i%i %i %i",
  423. N64_status.data1&16?1:0,
  424. N64_status.data1&32?1:0,
  425. N64_status.data1&64?1:0,
  426. N64_status.data1&128?1:0,
  427. N64_status.data2&32?1:0,
  428. N64_status.data2&16?1:0,
  429. N64_status.data2&0x08?1:0,
  430. N64_status.data2&0x04?1:0,
  431. N64_status.data2&0x01?1:0,
  432. N64_status.data2&0x02?1:0,
  433. N64_status.data1&0x08?1:0,
  434. N64_status.data1&0x04?1:0,
  435. N64_status.data1&0x01?1:0,
  436. N64_status.data1&0x02?1:0,
  437. N64_status.stick_x,
  438. N64_status.stick_y);
  439. Serial.println(out);
  440. }
  441. #endif ENABLE_SERIAL
  442.  
  443. void translate_raw_data()
  444. {
  445. memset(&N64_status, 0, sizeof(N64_status));
  446. for (int i = 0; i < 8; i++) {
  447. N64_status.data1 |= N64_raw_dump[i] ? (0x80 >> i) : 0;
  448. N64_status.data2 |= N64_raw_dump[8 + i] ? (0x80 >> i) : 0;
  449. N64_status.stick_x |= N64_raw_dump[16 + i] ? (0x80 >> i) : 0;
  450. N64_status.stick_y |= N64_raw_dump[24 + i] ? (0x80 >> i) : 0;
  451. }
  452. }
  453.  
  454. void N64toGC()
  455. {
  456. gc_Buffer[0] = gc_Buffer[1] = 0;//no buttons
  457. gc_Buffer[1] |= 1 << 7;//dummy
  458.  
  459. gc_Buffer[4] = 128;//c stick centered
  460. gc_Buffer[5] = 128 + (N64_status.data2 & 32 ? -127 : 0) + (N64_status.data2 & 0x08 ? 127 : 0);//l, c up -> c stick down, c stick up
  461. gc_Buffer[0] |= (N64_status.data1 & 16 ? 1 : 0) << 4;//start -> start
  462. gc_Buffer[1] |= (N64_status.data1 & 32 ? 1 : 0) << 6;//z -> l
  463. gc_Buffer[0] |= (N64_status.data1 & 64 ? 1 : 0) << 1;//b -> b
  464. gc_Buffer[0] |= (N64_status.data1 & 128 ? 1 : 0) << 0;//a -> a
  465. gc_Buffer[1] |= (N64_status.data2 & 16 ? 1 : 0) << 5;//r -> r
  466. gc_Buffer[1] |= (N64_status.data2 & 0x04 ? 1 : 0) << 4;//c down -> z
  467. gc_Buffer[0] |= (N64_status.data2 & 0x01 ? 1 : 0) << 2;//c right -> x
  468. gc_Buffer[0] |= (N64_status.data2 & 0x02 ? 1 : 0) << 3;//c left -> y
  469. gc_Buffer[1] |= (N64_status.data1 & 0x08 ? 1 : 0) << 3;//up -> up
  470. gc_Buffer[1] |= (N64_status.data1 & 0x04 ? 1 : 0) << 2;//down -> down
  471. gc_Buffer[1] |= (N64_status.data1 & 0x01 ? 1 : 0) << 1;//right -> right
  472. gc_Buffer[1] |= (N64_status.data1 & 0x02 ? 1 : 0) << 0;//left -> left
  473. gc_Buffer[2] = (N64_status.stick_x + 128);//stick x -> stick x
  474. gc_Buffer[3] = (N64_status.stick_y + 128);//stick y -> stick z
  475. }
  476.  
  477. void getN64()
  478. {
  479. unsigned char command[] = {0x01};
  480. unsigned char command2[] = {0x01};
  481. // don't want interrupts getting in the way
  482. noInterrupts();
  483. // send those 3 bytes
  484. N64_send(command, 1);
  485. // read in data and dump it to N64_raw_dump
  486. N64_get();
  487. interrupts();
  488. }
  489.  
  490. void gc_Send(unsigned char *buffer, char length, bool wide_stop)
  491. {
  492. asm volatile (";Starting GC Send Routine");
  493. // Send these bytes
  494. char bits;
  495.  
  496. bool bit;
  497.  
  498. // This routine is very carefully timed by examining the assembly output.
  499. // Do not change any statements, it could throw the timings off
  500. //
  501. // We get 16 cycles per microsecond, which should be plenty, but we need to
  502. // be conservative. Most assembly ops take 1 cycle, but a few take 2
  503. //
  504. // I use manually constructed for-loops out of gotos so I have more control
  505. // over the outputted assembly. I can insert nops where it was impossible
  506. // with a for loop
  507.  
  508. asm volatile (";Starting outer for loop");
  509. outer_loop:
  510. {
  511. asm volatile (";Starting inner for loop");
  512. bits = 8;
  513. inner_loop:
  514. {
  515. // Starting a bit, set the line low
  516. asm volatile (";Setting line to low");
  517. GC_LOW; // 1 op, 2 cycles
  518.  
  519. asm volatile (";branching");
  520. if (*buffer >> 7) {
  521. asm volatile (";Bit is a 1");
  522. // 1 bit
  523. // remain low for 1us, then go high for 3us
  524. // nop block 1
  525. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  526. "nop\nnop\nnop\n");
  527.  
  528. asm volatile (";Setting line to high");
  529. GC_HIGH;
  530.  
  531. // nop block 2
  532. // we'll wait only 2us to sync up with both conditions
  533. // at the bottom of the if statement
  534. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  535. "nop\nnop\nnop\nnop\nnop\n"
  536. "nop\nnop\nnop\nnop\nnop\n"
  537. "nop\nnop\nnop\nnop\nnop\n"
  538. "nop\nnop\nnop\nnop\nnop\n"
  539. "nop\nnop\nnop\nnop\nnop\n"
  540. "nop\nnop\nnop\nnop\n"
  541. "nop\nnop\nnop\nnop\n"
  542. );
  543.  
  544. } else {
  545. asm volatile (";Bit is a 0");
  546. // 0 bit
  547. // remain low for 3us, then go high for 1us
  548. // nop block 3
  549. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  550. "nop\nnop\nnop\nnop\nnop\n"
  551. "nop\nnop\nnop\nnop\nnop\n"
  552. "nop\nnop\nnop\nnop\nnop\n"
  553. "nop\nnop\nnop\nnop\nnop\n"
  554. "nop\nnop\nnop\nnop\nnop\n"
  555. "nop\nnop\nnop\nnop\nnop\n"
  556. "nop\n"
  557. "nop\nnop\nnop\nnop\n"
  558. "nop\nnop\nnop\nnop\n"
  559. "nop\nnop\nnop\n");
  560.  
  561. asm volatile (";Setting line to high");
  562. GC_HIGH;
  563.  
  564. // wait for 1us
  565. asm volatile ("; end of conditional branch, need to wait 1us more before next bit");
  566.  
  567. }
  568. // end of the if, the line is high and needs to remain
  569. // high for exactly 16 more cycles, regardless of the previous
  570. // branch path
  571.  
  572. asm volatile (";finishing inner loop body");
  573. --bits;
  574. if (bits != 0) {
  575. // nop block 4
  576. // this block is why a for loop was impossible
  577. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  578. "nop\nnop\nnop\nnop\n");
  579. // rotate bits
  580. asm volatile (";rotating out bits");
  581. *buffer <<= 1;
  582.  
  583. goto inner_loop;
  584. } // fall out of inner loop
  585.  
  586. }
  587. asm volatile (";continuing outer loop");
  588. asm volatile ("nop\nnop\nnop\nnop\n");
  589. // In this case: the inner loop exits and the outer loop iterates,
  590. // there are /exactly/ 16 cycles taken up by the necessary operations.
  591. // So no nops are needed here (that was lucky!)
  592. --length;
  593. if (length != 0) {
  594. asm volatile ("nop\nnop\nnop\nnop\n");
  595. ++buffer;
  596. goto outer_loop;
  597. } // fall out of outer loop
  598. }
  599.  
  600. // send a single stop (1) bit
  601. // nop block 5
  602. asm volatile ("nop\nnop\nnop\nnop\n"
  603. "nop\nnop\nnop\nnop\n");
  604. GC_LOW;
  605. // wait 1 us, 16 cycles, then raise the line
  606. // take another 3 off for the wide_stop check
  607. // 16-2-3=11
  608. // nop block 6
  609. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  610. "nop\nnop\nnop\nnop\nnop\n"
  611. "nop\n"
  612. "nop\nnop\nnop\nnop\n");
  613. if (wide_stop) {
  614. asm volatile (";another 1us for extra wide stop bit\n"
  615. "nop\nnop\nnop\nnop\nnop\n"
  616. "nop\nnop\nnop\nnop\nnop\n"
  617. "nop\nnop\nnop\nnop\n"
  618. "nop\nnop\nnop\nnop\n");
  619. }
  620.  
  621. GC_HIGH;
  622. }
  623.  
  624. void get_GC_Command(int ms) {
  625. gc_Command = 0x00;
  626. int bitcount;
  627. char *bitbin = gc_Raw_Dump;
  628. int idle_wait;
  629. int test = 2500;
  630.  
  631.  
  632.  
  633. func_top:
  634. gc_Command = 0;
  635.  
  636. bitcount = 8;
  637.  
  638. if (ms > 0) {
  639. while (test > 0) {
  640. if (!GC_QUERY) {
  641. needCommand = true;
  642. goto read_jump;
  643. }
  644. test--;
  645. }
  646. if (needCommand == false) {
  647. return;
  648. }
  649.  
  650. }
  651.  
  652. // wait to make sure the line is idle before
  653. // we begin listening
  654. if (needCommand == false) {
  655. for (idle_wait = 32; idle_wait > 0; --idle_wait) {
  656. if (!GC_QUERY) {
  657. idle_wait = 32;
  658. }
  659. }
  660. }
  661.  
  662. read_loop:
  663. // wait for the line to go low
  664. while (GC_QUERY) {}
  665. read_jump:
  666. // wait approx 2.5us and poll the line
  667. asm volatile (
  668. "nop\nnop\nnop\nnop\nnop\n"
  669. "nop\nnop\nnop\nnop\nnop\n"
  670. "nop\nnop\nnop\nnop\nnop\n"
  671. "nop\nnop\nnop\nnop\nnop\n"
  672. "nop\nnop\nnop\nnop\nnop\n"
  673. "nop\nnop\nnop\nnop\nnop\n"
  674. "nop\nnop\nnop\nnop\nnop\n"
  675. "nop\nnop\nnop\n"
  676. );
  677. if (GC_QUERY)
  678. gc_Command |= 0x01;
  679.  
  680. --bitcount;
  681. if (bitcount == 0)
  682. goto read_more;
  683.  
  684. gc_Command <<= 1;
  685.  
  686. // wait for line to go high again
  687. // I don't want this to execute if the loop is exiting, so
  688. // I couldn't use a traditional for-loop
  689. while (!GC_QUERY) {}
  690. goto read_loop;
  691.  
  692. read_more:
  693. if (gc_Command == 0x40) {
  694. bitcount = 1;
  695. } else {
  696. bitcount = 1;
  697. }
  698.  
  699. // make sure the line is high. Hopefully we didn't already
  700. // miss the high-to-low transition
  701. while (!GC_QUERY) {}
  702. read_loop2:
  703. for (idle_wait = 12; idle_wait > 0; --idle_wait) {
  704. if (!GC_QUERY) {
  705. idle_wait = 12;
  706. }
  707. }
  708. return;
  709. // wait for the line to go low
  710. while (GC_QUERY) {}
  711.  
  712. // wait approx 2.5us and poll the line
  713. asm volatile (
  714. "nop\nnop\nnop\nnop\nnop\n"
  715. "nop\nnop\nnop\nnop\nnop\n"
  716. "nop\nnop\nnop\nnop\nnop\n"
  717. "nop\nnop\nnop\nnop\nnop\n"
  718. "nop\nnop\nnop\nnop\nnop\n"
  719. "nop\nnop\nnop\nnop\nnop\n"
  720. "nop\nnop\nnop\nnop\nnop\n"
  721. "nop\nnop\nnop\n"
  722. );
  723. if (GC_QUERY) {
  724. //gc_Command |= 0x01;
  725. //goto bit_test;
  726. }
  727.  
  728. --bitcount;
  729. if (bitcount == 0) {
  730. //wait for the line to go high
  731. while (!GC_QUERY) {}
  732. return;
  733. }
  734. gc_Command <<= 1;
  735.  
  736. // wait for line to go high again
  737. while (!GC_QUERY) {}
  738. goto read_loop2;
  739.  
  740. bit_test:
  741.  
  742. if (!GC_QUERY) {
  743. //Serial.println(bitcount);
  744. gc_Command = 0xEE;
  745. return;
  746. }
  747. test--;
  748. if (test > 0) {
  749. goto bit_test;
  750. }
  751. return;
  752. }
  753.  
  754. #ifdef ENABLE_JOYSTICK
  755. void update_joystick()
  756. {
  757. int i;
  758.  
  759. signed char jx=0,jy=0;
  760. jx|=(unsigned char)N64_status.stick_x;
  761. jy|=(unsigned char)N64_status.stick_y;
  762. float JX=jx;
  763. float JY=-jy;
  764. Gamepad.xAxis(4096 * 4 + JX);
  765. Gamepad.yAxis(4096 * 4 + JY);
  766.  
  767. for(i=0;i<8;i++)
  768. {
  769. if (N64_raw_dump[i])
  770. Gamepad.press(i+1);
  771. else
  772. Gamepad.release(i+1);
  773. }
  774.  
  775. for(i=0;i<6;i++)
  776. {
  777. if (N64_raw_dump[10+i])
  778. Gamepad.press(i+9);
  779. else
  780. Gamepad.release(i+9);
  781. }
  782.  
  783.  
  784. unsigned char pov_byte=N64_status.data1&0x0F;
  785. int pov=-1;
  786. switch (pov_byte)
  787. {
  788. default: //Centered
  789. pov=0;
  790. break;
  791. case 1: //RIGHT
  792. pov=3;
  793. break;
  794. case 2: //LEFT
  795. pov=7;
  796. break;
  797. case 4: //DOWN
  798. pov=5;
  799. break;
  800. case 8: //UP
  801. pov=1;
  802. break;
  803. case 10: //UP-LEFT
  804. pov=8;
  805. break;
  806. case 6: //DOWN-LEFT
  807. pov=6;
  808. break;
  809. case 9: //UP-RIGHT
  810. pov=2;
  811. break;
  812. case 5: //DOWN-RIGHT
  813. pov=4;
  814. break;
  815. }
  816. Gamepad.dPad1(pov);
  817.  
  818. }
  819. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement