You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
8.9 KiB

  1. /* Dreamcast to USB : Sega dc controllers to USB adapter
  2. * Copyright (C) 2013 Raphal Assnat
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. *
  18. * The author may be contacted at raph@raphnet.net
  19. */
  20. #include <avr/io.h>
  21. #include <avr/interrupt.h>
  22. #include <avr/pgmspace.h>
  23. #include <avr/wdt.h>
  24. #include <avr/sleep.h>
  25. #include <util/delay.h>
  26. #include <string.h>
  27. #include "usbdrv.h"
  28. #include "oddebug.h"
  29. #include "gamepad.h"
  30. #include "dc_pad.h"
  31. static usbMsgPtr_t rt_usbHidReportDescriptor = USB_NO_MSG;
  32. static usbMsgLen_t rt_usbHidReportDescriptorSize = 0;
  33. static usbMsgPtr_t rt_usbDeviceDescriptor = USB_NO_MSG;
  34. static usbMsgLen_t rt_usbDeviceDescriptorSize = 0;
  35. #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__) || \
  36. defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328__) || \
  37. defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88__) || \
  38. defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88P__) || \
  39. defined(__AVR_ATmega88PA__)
  40. #define AT168_COMPATIBLE
  41. #endif
  42. const PROGMEM int usbDescriptorStringSerialNumber[] = {
  43. USB_STRING_DESCRIPTOR_HEADER(4),
  44. '1','0','0','0'
  45. };
  46. char usbDescriptorConfiguration[] = { 0 }; // dummy
  47. uchar my_usbDescriptorConfiguration[] = { /* USB configuration descriptor */
  48. 9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
  49. USBDESCR_CONFIG, /* descriptor type */
  50. 18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 9, 0,
  51. /* total length of data returned (including inlined descriptors) */
  52. 1, /* number of interfaces in this configuration */
  53. 1, /* index of this configuration */
  54. 0, /* configuration name string index */
  55. #if USB_CFG_IS_SELF_POWERED
  56. USBATTR_SELFPOWER, /* attributes */
  57. #else
  58. USBATTR_BUSPOWER, /* attributes */
  59. #endif
  60. USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
  61. /* interface descriptor follows inline: */
  62. 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
  63. USBDESCR_INTERFACE, /* descriptor type */
  64. 0, /* index of this interface */
  65. 0, /* alternate setting for this interface */
  66. USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */
  67. USB_CFG_INTERFACE_CLASS,
  68. USB_CFG_INTERFACE_SUBCLASS,
  69. USB_CFG_INTERFACE_PROTOCOL,
  70. 0, /* string index for interface */
  71. //#if (USB_CFG_DESCR_PROPS_HID & 0xff) /* HID descriptor */
  72. 9, /* sizeof(usbDescrHID): length of descriptor in bytes */
  73. USBDESCR_HID, /* descriptor type: HID */
  74. 0x01, 0x01, /* BCD representation of HID version */
  75. /* 22 */ 15, /* target country code : 15 = Japan */
  76. /* 23 */ 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */
  77. /* 24 */ 0x22, /* descriptor type: report */
  78. /* 25 */ USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0, /* total length of report descriptor */
  79. //#endif
  80. #if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */
  81. 7, /* sizeof(usbDescrEndpoint) */
  82. USBDESCR_ENDPOINT, /* descriptor type = endpoint */
  83. 0x81, /* IN endpoint number 1 */
  84. 0x03, /* attrib: Interrupt endpoint */
  85. 8, 0, /* maximum packet size */
  86. USB_CFG_INTR_POLL_INTERVAL, /* in ms */
  87. #endif
  88. };
  89. static Gamepad *curGamepad;
  90. /* ----------------------- hardware I/O abstraction ------------------------ */
  91. static void hardwareInit(void)
  92. {
  93. /* PORTB
  94. *
  95. * Bit Description Direction Level/pu
  96. * 0 Jumpers common Out 0
  97. * 1 JP1 In 1
  98. * 2 JP2 In 1
  99. * 3 MOSI In 1
  100. * 4 MISO In 1
  101. * 5 SCK In 1
  102. * 6 -
  103. * 7 -
  104. */
  105. DDRB = 0x01;
  106. PORTB = 0xFE;
  107. // temporaty debug pin PB4
  108. DDRB |= 0x10;
  109. /*
  110. * PORTC
  111. *
  112. * Bit
  113. * 0 Pin 1
  114. * 1 Pin 5
  115. */
  116. DDRC = 0x00;
  117. PORTC = 0xff;
  118. /*
  119. * For port D, activate pull-ups on all lines except the D+, D- and bit 1.
  120. *
  121. * For historical reasons (a mistake on an old PCB), bit 1
  122. * is now always connected with bit 0. So bit 1 configured
  123. * as an input without pullup.
  124. *
  125. * Usb pin are init as output, low. (device reset). They are released
  126. * later when usbReset() is called.
  127. */
  128. PORTD = 0xf8;
  129. DDRD = 0x01 | 0x04;
  130. /* Configure timers */
  131. #if defined(AT168_COMPATIBLE)
  132. TCCR2A= (1<<WGM21);
  133. TCCR2B=(1<<CS22)|(1<<CS21)|(1<<CS20);
  134. // OCR2A=196; // for 60 hz
  135. OCR2A=50; // for 60 hz
  136. #else
  137. TCCR2 = (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20);
  138. //OCR2 = 196; // for 60 hz
  139. OCR2 = 50; // for 60 hz
  140. #endif
  141. }
  142. #if defined(AT168_COMPATIBLE)
  143. #define mustPollControllers() (TIFR2 & (1<<OCF2A))
  144. #define clrPollControllers() do { TIFR2 = 1<<OCF2A; } while(0)
  145. #else
  146. #define mustPollControllers() (TIFR & (1<<OCF2))
  147. #define clrPollControllers() do { TIFR = 1<<OCF2; } while(0)
  148. #endif
  149. static void usbReset(void)
  150. {
  151. /* [...] a single ended zero or SE0 can be used to signify a device
  152. reset if held for more than 10mS. A SE0 is generated by holding
  153. both th D- and D+ low (< 0.3V).
  154. */
  155. PORTD &= ~(0x01 | 0x04); // Set D+ and D- to 0
  156. DDRD |= 0x01 | 0x04;
  157. _delay_ms(15);
  158. DDRD &= ~(0x01 | 0x04);
  159. }
  160. static uchar reportBuffer[16]; /* buffer for HID reports */
  161. /* ------------------------------------------------------------------------- */
  162. /* ----------------------------- USB interface ----------------------------- */
  163. /* ------------------------------------------------------------------------- */
  164. usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq)
  165. {
  166. if ((rq->bmRequestType & USBRQ_TYPE_MASK) != USBRQ_TYPE_STANDARD)
  167. return 0;
  168. if (rq->bRequest == USBRQ_GET_DESCRIPTOR)
  169. {
  170. // USB spec 9.4.3, high byte is descriptor type
  171. switch (rq->wValue.bytes[1])
  172. {
  173. case USBDESCR_DEVICE:
  174. usbMsgPtr = rt_usbDeviceDescriptor;
  175. return rt_usbDeviceDescriptorSize;
  176. case USBDESCR_HID_REPORT:
  177. usbMsgPtr = rt_usbHidReportDescriptor;
  178. return rt_usbHidReportDescriptorSize;
  179. case USBDESCR_CONFIG:
  180. usbMsgPtr = (usbMsgPtr_t)my_usbDescriptorConfiguration;
  181. return sizeof(my_usbDescriptorConfiguration);
  182. }
  183. }
  184. return 0;
  185. }
  186. usbMsgLen_t usbFunctionSetup(uchar data[8])
  187. {
  188. usbRequest_t *rq = (void *)data;
  189. usbMsgPtr = (usbMsgPtr_t)reportBuffer;
  190. if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
  191. if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
  192. return curGamepad->buildReport(reportBuffer, rq->wValue.bytes[0]);
  193. }
  194. }else{
  195. /* no vendor specific requests implemented */
  196. }
  197. return 0;
  198. }
  199. /* ------------------------------------------------------------------------- */
  200. int main(void)
  201. {
  202. char must_report = 0;
  203. int i;
  204. hardwareInit();
  205. curGamepad = dcGetGamepad();
  206. curGamepad->init();
  207. reconnect:
  208. // configure report descriptor according to
  209. // the current gamepad
  210. rt_usbHidReportDescriptor = (usbMsgPtr_t)curGamepad->reportDescriptor;
  211. rt_usbHidReportDescriptorSize = curGamepad->reportDescriptorSize;
  212. rt_usbDeviceDescriptor = (usbMsgPtr_t)curGamepad->deviceDescriptor;
  213. rt_usbDeviceDescriptorSize = curGamepad->deviceDescriptorSize;
  214. // patch the config descriptor with the HID report descriptor size
  215. my_usbDescriptorConfiguration[25] = rt_usbHidReportDescriptorSize;
  216. usbReset();
  217. usbInit();
  218. set_sleep_mode(SLEEP_MODE_IDLE);
  219. sei();
  220. for(;;){ /* main event loop */
  221. wdt_reset();
  222. if (curGamepad->descriptorsChanged && curGamepad->descriptorsChanged()) {
  223. goto reconnect;
  224. }
  225. // this must be called at each 50 ms or less
  226. usbPoll();
  227. if (mustPollControllers())
  228. {
  229. clrPollControllers();
  230. sleep_enable();
  231. sleep_cpu();
  232. sleep_disable();
  233. _delay_us(100);
  234. curGamepad->update();
  235. for (i=0; i<curGamepad->num_reports; i++) {
  236. if (curGamepad->changed(i+1)) {
  237. must_report |= (1<<i);
  238. }
  239. }
  240. }
  241. if(must_report)
  242. {
  243. for (i=0; i<curGamepad->num_reports; i++) {
  244. int len;
  245. if (!(must_report & (1<<i)))
  246. continue;
  247. len = curGamepad->buildReport(reportBuffer, i+1);
  248. while(!usbInterruptIsReady()) {
  249. usbPoll();
  250. }
  251. usbSetInterrupt(reportBuffer, len);
  252. must_report &= ~(1<<i);
  253. }
  254. }
  255. }
  256. return 0;
  257. }
  258. /* ------------------------------------------------------------------------- */