daily pastebin goal
76%
SHARE
TWEET

Waffle

a guest Jan 10th, 2010 717 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * Nintendo 64 Controller to Arduino sketch
  3.  * By Waffle (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?action=viewprofile;username=Waffle)
  4.  * See this Arduino forum thread for info: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1261980415
  5.  *
  6.  * Connect N64 controller +3.3V line to Arduino 3.3V line
  7.  * Connect N64 controller ground line to Arduino ground
  8.  * Connect N64 controller data line to an Arduino I/O pin with a 1K pull-up resistor to 3.3V line
  9.  *
  10.  * Set Arduino pin used for data line in the follow three #defines:
  11.  * Example for Arduino pin 9: N64_DATA_DDR = DDRB, N64_DATA_PIN = PINB, N64_DATA_PIN_NO = PINB1
  12.  */
  13.  
  14. #define N64_DATA_DDR    DDRB
  15. #define N64_DATA_PIN    PINB
  16. #define N64_DATA_PIN_NO PINB1
  17.  
  18. #include <util/delay.h>
  19.  
  20. /* based off the 'N64/Gamecube controller to USB adapter' by Raphaël Assénat (http://www.raphnet.net/electronique/gc_n64_usb/index_en.php)
  21.  * modifications/improvements:
  22.  * - adjusted timing for 16 MHz
  23.  * - support writing variable length data
  24.  * - receive variable length data directly packed into destination buffer
  25.  */
  26. uint8_t n64cmd(uint8_t rxdata[], uint8_t rxlen, uint8_t txdata[], uint8_t txlen) {
  27.         uint8_t num = 0;
  28.         uint8_t oldSREG = SREG;
  29.  
  30.         cli();
  31.         asm volatile(
  32. "nextByte%=:                                            \n"
  33. "                       cpi %[txlen], 0                 \n" // 1
  34. "                       breq done%=                             \n" // 1
  35. "                       dec %[txlen]                    \n" // 1
  36. "                       ld r16, z+                              \n" // 2
  37. "                       ldi r17, 0x80                   \n" // 1
  38. "nextBit%=:                                                     \n"
  39. "                       mov r18, r16                    \n" // 1
  40. "                       and r18, r17                    \n" // 1
  41. "                       breq send0%=                    \n" // 2
  42. "                       nop                                             \n"
  43.  
  44. // 1us low, 1us high
  45. "send1%=:                                                       \n"
  46. "                       sbi %[ddr], %[pinNo]    \n" // 2
  47. "                               nop\nnop\nnop\nnop      \n" // 4
  48. "                               nop\nnop\nnop\nnop      \n" // 4
  49. "                               nop\nnop\nnop\nnop      \n" // 4
  50. "                               nop\nnop                        \n" // 2
  51. "                       cbi %[ddr], %[pinNo]    \n" // 2
  52. "                               ldi r19, 11                     \n"     // 1
  53. "lp1%=:                 dec r19                         \n"     // 1
  54. "                               brne lp1%=                      \n"     // 2
  55. "                       lsr r17                                 \n" // 1
  56. "                       breq nextByte%=                 \n" // 1
  57. "                               nop\nnop\nnop\nnop      \n" // 4
  58. "                               nop                                     \n" // 1
  59. "                       rjmp nextBit%=                  \n" // 2
  60.  
  61. // 3us low, 1us high
  62. "send0%=:       sbi %[ddr], %[pinNo]    \n"     // 2
  63. "                               ldi r19, 15                     \n"     // 1
  64. "lp0%=:                 dec r19                         \n"     // 1
  65. "                               brne lp0%=                      \n"     // 2
  66. "                               nop                                     \n" // 1
  67. "               cbi %[ddr], %[pinNo]    \n" // 2
  68. "                               nop                                     \n" // 1
  69. "                       lsr r17                                 \n" // 1
  70. "                       breq nextByte%=                 \n" // 1
  71. "                               nop\nnop\nnop\nnop      \n" // 4
  72. "                               nop                                     \n" // 1
  73. "                       rjmp nextBit%=                  \n" // 2
  74.  
  75. // finished sending, sync up to the stop bit time
  76. "done%=:                                                        \n"
  77. "                       nop\nnop\nnop\nnop              \n"     // 4
  78. "                       nop\nnop\nnop                   \n" // 3
  79.  
  80. // stop bit
  81. "               sbi %[ddr], %[pinNo]    \n" // 2
  82. "                               nop\nnop\nnop\nnop      \n" // 4
  83. "                               nop\nnop\nnop\nnop      \n" // 4
  84. "                               nop\nnop\nnop\nnop      \n" // 4
  85. "                               nop\nnop                        \n" // 2
  86. "                       cbi %[ddr], %[pinNo]    \n"
  87.  
  88. // stop now if there's nothing to receive
  89. "                       cpi %[rxlen], 0                 \n" // 1
  90. "                       breq end%=                              \n" // 1
  91.  
  92. // receiving
  93. "                       clr r18                                 \n" // 1  current byte
  94. "                       ldi     r17, 0x80                       \n" // 1  current bit
  95. "st%=:                                                          \n"
  96. "                       ldi r16, 0xff                   \n" // 1  setup timeout
  97. "waitFall%=:                                            \n"
  98. "                       dec r16                                 \n" // 1
  99. "                       breq end%=                              \n" // 1
  100. "                       sbic %[pin], %[pinNo]   \n" // 2
  101. "                       rjmp waitFall%=                 \n"
  102.  
  103. // wait about 2us to check the state
  104. "                       nop\nnop\nnop\nnop              \n" // 4
  105. "                       nop\nnop\nnop\nnop              \n" // 4
  106. "                       nop\nnop\nnop\nnop              \n" // 4
  107. "                       nop\nnop\nnop\nnop              \n" // 4
  108. "                       nop\nnop\nnop\nnop              \n" // 4
  109. "                       nop\nnop\nnop\nnop              \n" // 4
  110. "                       nop\nnop\nnop\nnop              \n" // 4
  111.  
  112. "                       sbic %[pin], %[pinNo]   \n" // 2
  113. "                       or r18, r17                             \n"
  114. "                       lsr r17                                 \n" // 1
  115. "                       brne nextRxBit%=                \n" // 2
  116.  
  117. "nextRxByte%=:                                          \n"
  118. "                       st x+, r18                              \n" // 2  store the value
  119. "                       inc %[num]                              \n" // 1  increase number of received bytes
  120. "                       cp %[rxlen], %[num]             \n" // 1  check for finish
  121. "                       breq end%=                              \n" // 1
  122. "                       clr r18                                 \n" // 1
  123. "                       ldi     r17, 0x80                       \n" // 1
  124.  
  125. "nextRxBit%=:                                           \n"
  126. "                       ldi r16, 0xff                   \n" // 1  setup timeout
  127. "waitHigh%=:                                            \n"
  128. "                       dec r16                                 \n" // 1  decrement timeout
  129. "                       breq end%=                              \n" // 1  handle timeout condition
  130. "                       sbis %[pin], %[pinNo]   \n" // 2
  131. "                       rjmp waitHigh%=                 \n"
  132. "                       rjmp st%=                               \n" // 2
  133.  
  134. "end%=:                                                         \n"
  135.                         : [num] "=r"(num)
  136.                         : [ddr] "I"(_SFR_IO_ADDR(N64_DATA_DDR)), [pin] "I"(_SFR_IO_ADDR(N64_DATA_PIN)), [pinNo] "I"(N64_DATA_PIN_NO),
  137.                                 [rxdata] "x"(rxdata), [rxlen] "r"(rxlen),
  138.                                 [txdata] "z"(txdata), [txlen] "r"(txlen), "0"(num)
  139.                         : "r16", "r17", "r18", "r19"
  140.                         );
  141.         SREG = oldSREG;
  142.  
  143.         _delay_us(100); // some commands leave the controller unresponsive for a while
  144.  
  145.         return num;
  146. }
  147.  
  148. struct n64Buttons { // 4 byte struct of the N64 controller data
  149.         uint8_t right : 1;
  150.         uint8_t left : 1;
  151.         uint8_t down : 1;
  152.         uint8_t up : 1;
  153.         uint8_t start : 1;
  154.         uint8_t z : 1;
  155.         uint8_t b : 1;
  156.         uint8_t a : 1;
  157.         uint8_t cRight : 1;
  158.         uint8_t cLeft : 1;
  159.         uint8_t cDown : 1;
  160.         uint8_t cUp : 1;
  161.         uint8_t r : 1;
  162.         uint8_t l : 1;
  163.         uint8_t unknown : 2;
  164.         int8_t x;
  165.         int8_t y;
  166. };
  167.  
  168. n64Buttons prev; // hold last button status for reporting
  169.  
  170. void setup() {
  171.         Serial.begin(9600);
  172. }
  173.  
  174. void loop() {
  175.         // fetch new button status
  176.         n64Buttons btn;
  177.         uint8_t num = n64cmd((uint8_t*)&btn, 4, (uint8_t[]){0x01}, 1);
  178.  
  179.         // check if we got 4 bytes back, if not there must be a connection or controller problem
  180.         if (num != 4) {
  181.                 Serial.println("Controller Error!");
  182.                 delay(1000);
  183.                 return;
  184.         }
  185.  
  186.         // output if a button was just pressed
  187.         if (btn.a && !prev.a)
  188.                 Serial.println('A');
  189.         if (btn.b && !prev.b)
  190.                 Serial.println('B');
  191.         if (btn.z && !prev.z)
  192.                 Serial.println('Z');
  193.         if (btn.start && !prev.start)
  194.                 Serial.println("Start");
  195.         if (btn.up && !prev.up)
  196.                 Serial.println("Up");
  197.         if (btn.down && !prev.down)
  198.                 Serial.println("Down");
  199.         if (btn.left && !prev.left)
  200.                 Serial.println("Left");
  201.         if (btn.right && !prev.right)
  202.                 Serial.println("Right");
  203.         if (btn.l && !prev.l)
  204.                 Serial.println('L');
  205.         if (btn.r && !prev.r)
  206.                 Serial.println('R');
  207.         if (btn.cUp && !prev.cUp)
  208.                 Serial.println("C-Up");
  209.         if (btn.cDown && !prev.cDown)
  210.                 Serial.println("C-Down");
  211.         if (btn.cLeft && !prev.cLeft)
  212.                 Serial.println("C-Left");
  213.         if (btn.cRight && !prev.cRight)
  214.                 Serial.println("C-Right");
  215.  
  216.         // output analog stick values if it has changed
  217.         if (btn.x != prev.x || btn.y != prev.y) {
  218.                 Serial.print("Stick: ");
  219.                 Serial.print(btn.x, DEC);
  220.                 Serial.print(", ");
  221.                 Serial.println(btn.y, DEC);
  222.         }
  223.  
  224.         // set the previous to be the last
  225.         prev = btn;
  226. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top