Advertisement
Guest User

Untitled

a guest
Feb 21st, 2017
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.42 KB | None | 0 0
  1. //Credit to Ownasaurous for constructing/making 90 % this file.
  2. //rcombs from #tasbot was extremely helpful
  3.  
  4. /*
  5. n64_send function is....
  6. Copyright (c) 2009 Andrew Brown
  7. Permission is hereby granted, free of charge, to any person
  8. obtaining a copy of this software and associated documentation
  9. files (the "Software"), to deal in the Software without
  10. restriction, including without limitation the rights to use,
  11. copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. copies of the Software, and to permit persons to whom the
  13. Software is furnished to do so, subject to the following
  14. conditions:
  15. The above copyright notice and this permission notice shall be
  16. included in all copies or substantial portions of the Software.
  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. int pin = 4;
  27. int commandNumber = 0;
  28. int debug = 1;
  29. int commanddebug = 1;
  30.  
  31. inline int port4read()
  32. {
  33. return (PIND >> 4) & 1;
  34. }
  35. inline void port4OutputMode()
  36. {
  37. DDRD = DDRD | B00010000; // force bit/port4 to be 1, which is output mode
  38. }
  39. inline void port4InputMode()
  40. {
  41. DDRD = DDRD & B11101111; // force bit/port4 to be 0, which is input mode
  42. }
  43. inline void port4HIGH()
  44. {
  45. PORTD = PORTD | B00010000; // force bit/port4 to be 1 which is HIGH
  46. }
  47. inline void port4LOW()
  48. {
  49. PORTD = PORTD & B11101111; // force bit/port4 to be 1 which is LOW
  50. }
  51.  
  52. inline void wait1us()
  53. {
  54. asm volatile("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"); // 16 nops = 1 us
  55. }
  56.  
  57.  
  58.  
  59. static unsigned char n64_buffer[33];
  60. #define N64_HIGH DDRD &= ~0x10
  61. #define N64_LOW DDRD |= 0x10
  62. #define N64_INPUT DDRD &= 0xEF
  63. #define N64_OUTPUT DDRD |= 0x10
  64. #define N64_QUERY (PIND & 0x10)
  65.  
  66.  
  67. void setup()
  68. {
  69. noInterrupts();
  70. port4InputMode();
  71. //Serial.begin(9600);
  72. }
  73.  
  74. void loop()
  75. {
  76. unsigned int cmd = readCommand();
  77. wait1us();
  78. //wait1us(); // this one is probably not needd because of readCommand overhead
  79. port4OutputMode();
  80. switch (cmd)
  81. {
  82. case 0x00:
  83. case 0xFF:
  84. // send identity, normal controller
  85. n64_buffer[0] = 0x05;
  86. n64_buffer[1] = 0x00;
  87. n64_buffer[2] = 0x01;
  88.  
  89. n64_send(n64_buffer, 3, 0);
  90. break;
  91. case 0x01:
  92. // send blank controller data
  93. n64_buffer[0] = 0x00;
  94. n64_buffer[1] = 0x00;
  95. n64_buffer[2] = 0x00;
  96. n64_buffer[3] = 0x00;
  97.  
  98. n64_send(n64_buffer, 4, 0);
  99. break;
  100. default:
  101. break;
  102. }
  103. port4InputMode();
  104. }
  105. /**
  106. * Complete copy and paste of gc_send, but with the N64
  107. * pin being manipulated instead.
  108. */
  109. static void n64_send(unsigned char *buffer, char length, bool wide_stop)
  110. {
  111. asm volatile (";Starting N64 Send Routine");
  112. // Send these bytes
  113. char bits;
  114.  
  115. // This routine is very carefully timed by examining the assembly output.
  116. // Do not change any statements, it could throw the timings off
  117. //
  118. // We get 16 cycles per microsecond, which should be plenty, but we need to
  119. // be conservative. Most assembly ops take 1 cycle, but a few take 2
  120. //
  121. // I use manually constructed for-loops out of gotos so I have more control
  122. // over the outputted assembly. I can insert nops where it was impossible
  123. // with a for loop
  124.  
  125. asm volatile (";Starting outer for loop");
  126. outer_loop:
  127. {
  128. asm volatile (";Starting inner for loop");
  129. bits=8;
  130. inner_loop:
  131. {
  132. // Starting a bit, set the line low
  133. asm volatile (";Setting line to low");
  134. N64_LOW; // 1 op, 2 cycles
  135.  
  136. asm volatile (";branching");
  137. if (*buffer >> 7) {
  138. asm volatile (";Bit is a 1");
  139. // 1 bit
  140. // remain low for 1us, then go high for 3us
  141. // nop block 1
  142. asm volatile ("nop\nnop\nnop\nnop\nnop\n");
  143.  
  144. asm volatile (";Setting line to high");
  145. N64_HIGH;
  146.  
  147. // nop block 2
  148. // we'll wait only 2us to sync up with both conditions
  149. // at the bottom of the if statement
  150. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  151. "nop\nnop\nnop\nnop\nnop\n"
  152. "nop\nnop\nnop\nnop\nnop\n"
  153. "nop\nnop\nnop\nnop\nnop\n"
  154. "nop\nnop\nnop\nnop\nnop\n"
  155. "nop\nnop\nnop\nnop\nnop\n"
  156. );
  157.  
  158. } else {
  159. asm volatile (";Bit is a 0");
  160. // 0 bit
  161. // remain low for 3us, then go high for 1us
  162. // nop block 3
  163. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  164. "nop\nnop\nnop\nnop\nnop\n"
  165. "nop\nnop\nnop\nnop\nnop\n"
  166. "nop\nnop\nnop\nnop\nnop\n"
  167. "nop\nnop\nnop\nnop\nnop\n"
  168. "nop\nnop\nnop\nnop\nnop\n"
  169. "nop\nnop\nnop\nnop\nnop\n"
  170. "nop\n");
  171.  
  172. asm volatile (";Setting line to high");
  173. N64_HIGH;
  174.  
  175. // wait for 1us
  176. asm volatile ("; end of conditional branch, need to wait 1us more before next bit");
  177.  
  178. }
  179. // end of the if, the line is high and needs to remain
  180. // high for exactly 16 more cycles, regardless of the previous
  181. // branch path
  182.  
  183. asm volatile (";finishing inner loop body");
  184. --bits;
  185. if (bits != 0) {
  186. // nop block 4
  187. // this block is why a for loop was impossible
  188. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  189. "nop\nnop\nnop\nnop\n");
  190. // rotate bits
  191. asm volatile (";rotating out bits");
  192. *buffer <<= 1;
  193.  
  194. goto inner_loop;
  195. } // fall out of inner loop
  196. }
  197. asm volatile (";continuing outer loop");
  198. // In this case: the inner loop exits and the outer loop iterates,
  199. // there are /exactly/ 16 cycles taken up by the necessary operations.
  200. // So no nops are needed here (that was lucky!)
  201. --length;
  202. if (length != 0) {
  203. ++buffer;
  204. goto outer_loop;
  205. } // fall out of outer loop
  206. }
  207.  
  208. // send a single stop (1) bit
  209. // nop block 5
  210. asm volatile ("nop\nnop\nnop\nnop\n");
  211. N64_LOW;
  212. // wait 1 us, 16 cycles, then raise the line
  213. // take another 3 off for the wide_stop check
  214. // 16-2-3=11
  215. // nop block 6
  216. asm volatile ("nop\nnop\nnop\nnop\nnop\n"
  217. "nop\nnop\nnop\nnop\nnop\n"
  218. "nop\n");
  219. if (wide_stop) {
  220. asm volatile (";another 1us for extra wide stop bit\n"
  221. "nop\nnop\nnop\nnop\nnop\n"
  222. "nop\nnop\nnop\nnop\nnop\n"
  223. "nop\nnop\nnop\nnop\n");
  224. }
  225.  
  226. N64_HIGH;
  227.  
  228. }
  229.  
  230. unsigned int readCommand()
  231. {
  232. unsigned int command = readn64(), bits = 1;
  233. while (true)
  234. {
  235. command = command << 1;
  236. command += readn64();
  237. command &= 0x1FF;
  238. bits++;
  239. if (bits >= 9)
  240. {
  241. if (command == 0x3 || command == 0x1 || command == 0x1FF || command == 0x5 || command == 0x7)
  242. {
  243. command = command >> 1;
  244. if (commanddebug == 1)
  245. {
  246. commandNumber++;
  247. char buff[256];
  248. sprintf(buff,"Command #%d = 0x%02X",commandNumber,command);
  249. Serial.println(buff);
  250. }
  251. return command;
  252. }
  253. }
  254. }
  255. }
  256. unsigned int readn64()
  257. {
  258. while (true)
  259. {
  260. if (N64_QUERY)
  261. break;
  262. }
  263. while (true)
  264. {
  265. if (!N64_QUERY)
  266. break;
  267. }
  268. wait1us();
  269. wait1us();
  270. if (debug == 1)
  271. {
  272. Serial.print("Bit: ");
  273. //Serial.print(port4read());
  274. Serial.println("");
  275. }
  276. return N64_QUERY;
  277. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement