Guest User

Untitled

a guest
Jun 25th, 2018
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.61 KB | None | 0 0
  1. #include <stdint.h>
  2.  
  3. // GPIO pins used for connected gamepad
  4. #define CLOCK 21
  5. #define LATCH 20
  6. #define DATA 19
  7.  
  8. #define DEVICE_TYPE_AUTO 0
  9. #define DEVICE_TYPE_NES 1
  10. #define DEVICE_TYPE_SNES 2
  11. #define DEVICE_METHOD_JOYSTICK 0
  12. #define DEVICE_METHOD_KEYBOARD 1
  13.  
  14. enum {
  15. NES_BUTTON_A,
  16. NES_BUTTON_B,
  17. NES_BUTTON_SELECT,
  18. NES_BUTTON_START,
  19. NES_DPAD_UP,
  20. NES_DPAD_DOWN,
  21. NES_DPAD_LEFT,
  22. NES_DPAD_RIGHT
  23. } NES_BUTTON_MAP;
  24.  
  25. enum {
  26. SNES_BUTTON_B,
  27. SNES_BUTTON_Y,
  28. SNES_BUTTON_SELECT,
  29. SNES_BUTTON_START,
  30. SNES_DPAD_UP,
  31. SNES_DPAD_DOWN,
  32. SNES_DPAD_LEFT,
  33. SNES_DPAD_RIGHT,
  34. SNES_BUTTON_A,
  35. SNES_BUTTON_X,
  36. SNES_BUTTON_L,
  37. SNES_BUTTON_R,
  38. } SNES_BUTTON_MAP;
  39.  
  40. uint8_t BUTTON_STATE[16];
  41. uint8_t DEVICE_TYPE = DEVICE_TYPE_AUTO; // Device Type (configurable)
  42. uint8_t DEVICE_METHOD = DEVICE_METHOD_JOYSTICK; // Device Method (configurable)
  43.  
  44. const int16_t NES_JOYSTICK_MAP[4][2] = {
  45. {NES_BUTTON_A, 1},
  46. {NES_BUTTON_B, 2},
  47. {NES_BUTTON_SELECT, 7},
  48. {NES_BUTTON_START, 8},
  49. };
  50.  
  51. // NES Keyboard Map (configurable)
  52. const int16_t NES_KEYBOARD_MAP[8][2] = {
  53. {NES_BUTTON_A, KEY_X},
  54. {NES_BUTTON_B, KEY_Z},
  55. {NES_BUTTON_SELECT, KEY_A},
  56. {NES_BUTTON_START, KEY_S},
  57. {NES_DPAD_UP, KEY_UP},
  58. {NES_DPAD_DOWN, KEY_DOWN},
  59. {NES_DPAD_LEFT, KEY_LEFT},
  60. {NES_DPAD_RIGHT, KEY_RIGHT},
  61. };
  62.  
  63. const int16_t SNES_JOYSTICK_MAP[8][2] = {
  64. {SNES_BUTTON_A, 1},
  65. {SNES_BUTTON_B, 2},
  66. {SNES_BUTTON_X, 3},
  67. {SNES_BUTTON_Y, 4},
  68. {SNES_BUTTON_L, 5},
  69. {SNES_BUTTON_R, 6},
  70. {SNES_BUTTON_SELECT, 7},
  71. {SNES_BUTTON_START, 8},
  72. };
  73.  
  74. // SNES Keyboard Map (configurable)
  75. const int16_t SNES_KEYBOARD_MAP[16][2] = {
  76. {SNES_BUTTON_A, KEY_X},
  77. {SNES_BUTTON_B, KEY_Z},
  78. {SNES_BUTTON_X, KEY_D},
  79. {SNES_BUTTON_Y, KEY_F},
  80. {SNES_BUTTON_L, KEY_C},
  81. {SNES_BUTTON_R, KEY_V},
  82. {SNES_BUTTON_SELECT, KEY_A},
  83. {SNES_BUTTON_START, KEY_S},
  84. {SNES_DPAD_UP, KEY_UP},
  85. {SNES_DPAD_DOWN, KEY_DOWN},
  86. {SNES_DPAD_LEFT, KEY_LEFT},
  87. {SNES_DPAD_RIGHT, KEY_RIGHT},
  88. };
  89.  
  90. void (*PROCESS_INPUT_FN)(void);
  91.  
  92. // Delay for approx 100ns. Assumes 16Mhz AtMega CPU
  93. #define delay100ns()
  94. __asm__ __volatile__ ("nop\n\t");\
  95. __asm__ __volatile__ ("nop\n\t");
  96.  
  97. #define SendCmdTakeSample(clock_pin, latch_pin)\
  98. digitalWrite(clock_pin, HIGH);\
  99. digitalWrite(latch_pin, HIGH);\
  100. delay100ns();\
  101. digitalWrite(latch_pin, LOW);
  102.  
  103. #define SendCmdSendData(clock_pin)\
  104. delay100ns();\
  105. digitalWrite(clock_pin, LOW);
  106.  
  107. #define SendCmdShiftOut(clock_pin)\
  108. delay100ns();\
  109. digitalWrite(clock_pin, HIGH);
  110.  
  111. void ReadInput(uint8_t *data, int num)
  112. {
  113. int i;
  114. SendCmdTakeSample(CLOCK, LATCH);
  115.  
  116. // Read output
  117. for (i = 0; i < num; i++) {
  118. SendCmdSendData(CLOCK);
  119.  
  120. // 1 = Off, 0 = On... Bit must be inverted
  121. data[i] = (~digitalRead(DATA)) & 0x1;
  122. SendCmdShiftOut(CLOCK);
  123. }
  124. }
  125.  
  126. int GetHatState()
  127. {
  128.  
  129. /*
  130.  
  131. 0
  132. UP
  133. 315 45
  134. 270 LT RT 90
  135. 225 135
  136. DN
  137. 180
  138.  
  139. */
  140.  
  141. uint8_t x, y;
  142. const static int16_t dpad_lookup[4][4] = {
  143. { -1, 270, 90, -1},
  144. { 0, 315, 45, -1},
  145. {180, 225, 135, -1},
  146. { -1, -1, -1, -1}
  147. };
  148.  
  149. y = BUTTON_STATE[NES_DPAD_UP] | (BUTTON_STATE[NES_DPAD_DOWN] << 1);
  150. x = BUTTON_STATE[NES_DPAD_LEFT] | (BUTTON_STATE[NES_DPAD_RIGHT] << 1);
  151.  
  152. return dpad_lookup[y][x];
  153. }
  154.  
  155. void ProcessInputNES()
  156. {
  157. int i, hat0;
  158.  
  159. ReadInput((uint8_t *)&BUTTON_STATE, 8);
  160. hat0 = GetHatState();
  161.  
  162. for (i = 0; i < 4; i++) {
  163. Joystick.button(
  164. NES_JOYSTICK_MAP[i][1],
  165. BUTTON_STATE[NES_JOYSTICK_MAP[i][0]]);
  166. }
  167.  
  168. Joystick.hat(hat0);
  169. }
  170.  
  171. void ProcessInputNESUsingKeyboard()
  172. {
  173. int i;
  174. ReadInput((uint8_t *)&BUTTON_STATE, 8);
  175.  
  176. for (i = 0; i < 8; i++) {
  177. if (BUTTON_STATE[NES_KEYBOARD_MAP[i][0]]) {
  178. Keyboard.press(NES_KEYBOARD_MAP[i][1]);
  179. } else {
  180. Keyboard.release(NES_KEYBOARD_MAP[i][1]);
  181. }
  182. }
  183. }
  184.  
  185. void ProcessInputSNES()
  186. {
  187. int i, hat0;
  188.  
  189. ReadInput((uint8_t *)&BUTTON_STATE, 16);
  190. hat0 = GetHatState();
  191.  
  192. for (i = 0; i < 8; i++) {
  193. Joystick.button(
  194. SNES_JOYSTICK_MAP[i][1],
  195. BUTTON_STATE[SNES_JOYSTICK_MAP[i][0]]);
  196. }
  197.  
  198. Joystick.hat(hat0);
  199. }
  200.  
  201. void ProcessInputSNESUsingKeyboard()
  202. {
  203. int i;
  204. ReadInput((uint8_t *)&BUTTON_STATE, 16);
  205.  
  206. for (i = 0; i < 16; i++) {
  207. if (BUTTON_STATE[SNES_KEYBOARD_MAP[i][0]]) {
  208. Keyboard.press(SNES_KEYBOARD_MAP[i][1]);
  209. } else {
  210. Keyboard.release(SNES_KEYBOARD_MAP[i][1]);
  211. }
  212. }
  213. }
  214.  
  215. void ConfigureSelf()
  216. {
  217. int i, d;
  218.  
  219. if (DEVICE_TYPE == DEVICE_TYPE_AUTO) {
  220. // Auto detect device type
  221. SendCmdTakeSample(CLOCK, LATCH);
  222.  
  223. for (i = 0; i < 16; i++) {
  224. SendCmdSendData(CLOCK);
  225. d = digitalRead(DATA);
  226.  
  227. if (i < 8 && d == 1) {
  228. DEVICE_TYPE = DEVICE_TYPE_NES;
  229. } else if (i > 7 && d == 1) {
  230. DEVICE_TYPE = DEVICE_TYPE_SNES;
  231. }
  232.  
  233. SendCmdShiftOut(CLOCK);
  234. }
  235. };
  236.  
  237. if (DEVICE_TYPE == DEVICE_TYPE_NES) {
  238. if (DEVICE_METHOD == DEVICE_METHOD_JOYSTICK) {
  239. // NES, Joystick
  240. PROCESS_INPUT_FN = &ProcessInputNES;
  241. } else {
  242. // NES, Keybaord
  243. PROCESS_INPUT_FN = &ProcessInputNESUsingKeyboard;
  244. }
  245. } else {
  246. if (DEVICE_METHOD == DEVICE_METHOD_JOYSTICK) {
  247. // SNES, Joystick
  248. PROCESS_INPUT_FN = &ProcessInputSNES;
  249. } else {
  250. // SNES, Keybaord
  251. PROCESS_INPUT_FN = &ProcessInputSNESUsingKeyboard;
  252. }
  253. }
  254. }
  255.  
  256. void setup() {
  257. pinMode(CLOCK, OUTPUT);
  258. pinMode(LATCH, OUTPUT);
  259. pinMode(DATA, INPUT);
  260.  
  261. ConfigureSelf();
  262. }
  263.  
  264. void loop() {
  265. if (DEVICE_TYPE == DEVICE_TYPE_AUTO) {
  266. ConfigureSelf();
  267. }
  268.  
  269. PROCESS_INPUT_FN();
  270. delayMicroseconds(1);
  271. }
Add Comment
Please, Sign In to add comment