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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
  2. This software may be distributed and modified under the terms of the GNU
  3. General Public License version 2 (GPL2) as published by the Free Software
  4. Foundation and appearing in the file GPL2.TXT included in the packaging of
  5. this file. Please note that GPL2 Section 2[b] requires that all works based
  6. on this software must also be made publicly available under the terms of
  7. the GPL2 ("Copyleft").
  8. Contact information
  9. -------------------
  10. Circuits At Home, LTD
  11. Web : http://www.circuitsathome.com
  12. e-mail : [email protected]
  13. */
  14. /* MAX3421E-based USB Host Library header file */
  15. #if !defined(_usb_h_) || defined(_USBHOST_H_)
  16. #error "Never include usbhost.h directly; include Usb.h instead"
  17. #else
  18. #define _USBHOST_H_
  19. #if USING_SPI4TEENSY3
  20. #include <spi4teensy3.h>
  21. #include <sys/types.h>
  22. #endif
  23. /* SPI initialization */
  24. template< typename SPI_CLK, typename SPI_MOSI, typename SPI_MISO, typename SPI_SS > class SPi {
  25. public:
  26. #if USING_SPI4TEENSY3
  27. static void init() {
  28. // spi4teensy3 inits everything for us, except /SS
  29. // CLK, MOSI and MISO are hard coded for now.
  30. // spi4teensy3::init(0,0,0); // full speed, cpol 0, cpha 0
  31. spi4teensy3::init(); // full speed, cpol 0, cpha 0
  32. SPI_SS::SetDirWrite();
  33. SPI_SS::Set();
  34. }
  35. #elif SPI_HAS_TRANSACTION
  36. static void init() {
  37. SPI.begin(); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction()
  38. }
  39. #elif !defined(SPDR)
  40. static void init() {
  41. SPI_SS::SetDirWrite();
  42. SPI_SS::Set();
  43. SPI.begin();
  44. #if defined(__MIPSEL__)
  45. SPI.setClockDivider(1);
  46. #elif defined(__ARDUINO_X86__)
  47. #ifdef SPI_CLOCK_1M // Hack used to check if setClockSpeed is available
  48. SPI.setClockSpeed(12000000); // The MAX3421E can handle up to 26MHz, but in practice this was the maximum that I could reliably use
  49. #else
  50. SPI.setClockDivider(SPI_CLOCK_DIV2); // This will set the SPI frequency to 8MHz - it could be higher, but it is not supported in the old API
  51. #endif
  52. #else
  53. SPI.setClockDivider(4); // Set speed to 84MHz/4=21MHz - the MAX3421E can handle up to 26MHz
  54. #endif
  55. }
  56. #elif defined(RBL_NRF51822)
  57. static void init() {
  58. SPI_SS::SetDirWrite();
  59. SPI_SS::Set();
  60. SPI.begin();
  61. // SPI.setFrequency(SPI_FREQUENCY_8M);
  62. }
  63. #else
  64. static void init() {
  65. //uint8_t tmp;
  66. SPI_CLK::SetDirWrite();
  67. SPI_MOSI::SetDirWrite();
  68. SPI_MISO::SetDirRead();
  69. SPI_SS::SetDirWrite();
  70. /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */
  71. SPCR = 0x50;
  72. SPSR = 0x01; // 0x01
  73. /**/
  74. //tmp = SPSR;
  75. //tmp = SPDR;
  76. }
  77. #endif
  78. };
  79. /* SPI pin definitions. see avrpins.h */
  80. #if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  81. typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi;
  82. #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
  83. typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;
  84. #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
  85. typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi;
  86. #elif (defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))) || defined(__ARDUINO_X86__) || defined(__MIPSEL__)
  87. typedef SPi< P13, P11, P12, P10 > spi;
  88. #elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)
  89. typedef SPi< P76, P75, P74, P10 > spi;
  90. #elif defined(RBL_NRF51822)
  91. typedef SPi< P16, P18, P17, P10 > spi;
  92. #else
  93. #error "No SPI entry in usbhost.h"
  94. #endif
  95. typedef enum {
  96. vbus_on = 0,
  97. vbus_off = GPX_VBDET
  98. } VBUS_t;
  99. template< typename SPI_SS, typename INTR > class MAX3421e /* : public spi */ {
  100. static uint8_t vbusState;
  101. public:
  102. MAX3421e();
  103. void regWr(uint8_t reg, uint8_t data);
  104. uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p);
  105. void gpioWr(uint8_t data);
  106. uint8_t regRd(uint8_t reg);
  107. uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p);
  108. uint8_t gpioRd();
  109. uint16_t reset();
  110. int8_t Init();
  111. int8_t Init(int mseconds);
  112. void vbusPower(VBUS_t state) {
  113. regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | state));
  114. }
  115. uint8_t getVbusState(void) {
  116. return vbusState;
  117. };
  118. void busprobe();
  119. uint8_t GpxHandler();
  120. uint8_t IntHandler();
  121. uint8_t Task();
  122. };
  123. template< typename SPI_SS, typename INTR >
  124. uint8_t MAX3421e< SPI_SS, INTR >::vbusState = 0;
  125. /* constructor */
  126. template< typename SPI_SS, typename INTR >
  127. MAX3421e< SPI_SS, INTR >::MAX3421e() {
  128. // Leaving ADK hardware setup in here, for now. This really belongs with the other parts.
  129. #ifdef BOARD_MEGA_ADK
  130. // For Mega ADK, which has a Max3421e on-board, set MAX_RESET to output mode, and then set it to HIGH
  131. P55::SetDirWrite();
  132. P55::Set();
  133. #endif
  134. };
  135. /* write single byte into MAX3421 register */
  136. template< typename SPI_SS, typename INTR >
  137. void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) {
  138. XMEM_ACQUIRE_SPI();
  139. #if SPI_HAS_TRANSACTION
  140. SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0
  141. #endif
  142. SPI_SS::Clear();
  143. #if USING_SPI4TEENSY3
  144. uint8_t c[2];
  145. c[0] = reg | 0x02;
  146. c[1] = data;
  147. spi4teensy3::send(c, 2);
  148. #elif SPI_HAS_TRANSACTION
  149. uint8_t c[2];
  150. c[0] = reg | 0x02;
  151. c[1] = data;
  152. SPI.transfer(c, 2);
  153. #elif !defined(SPDR)
  154. SPI.transfer(reg | 0x02);
  155. SPI.transfer(data);
  156. #else
  157. SPDR = (reg | 0x02);
  158. while(!(SPSR & (1 << SPIF)));
  159. SPDR = data;
  160. while(!(SPSR & (1 << SPIF)));
  161. #endif
  162. SPI_SS::Set();
  163. #if SPI_HAS_TRANSACTION
  164. SPI.endTransaction();
  165. #endif
  166. XMEM_RELEASE_SPI();
  167. return;
  168. };
  169. /* multiple-byte write */
  170. /* returns a pointer to memory position after last written */
  171. template< typename SPI_SS, typename INTR >
  172. uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
  173. XMEM_ACQUIRE_SPI();
  174. #if SPI_HAS_TRANSACTION
  175. SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0
  176. #endif
  177. SPI_SS::Clear();
  178. #if USING_SPI4TEENSY3
  179. spi4teensy3::send(reg | 0x02);
  180. spi4teensy3::send(data_p, nbytes);
  181. data_p += nbytes;
  182. #elif SPI_HAS_TRANSACTION
  183. SPI.transfer(reg | 0x02);
  184. SPI.transfer(data_p, nbytes);
  185. data_p += nbytes;
  186. #elif defined(__ARDUINO_X86__)
  187. SPI.transfer(reg | 0x02);
  188. SPI.transferBuffer(data_p, NULL, nbytes);
  189. data_p += nbytes;
  190. #elif !defined(SPDR)
  191. SPI.transfer(reg | 0x02);
  192. while(nbytes) {
  193. SPI.transfer(*data_p);
  194. nbytes--;
  195. data_p++; // advance data pointer
  196. }
  197. #else
  198. SPDR = (reg | 0x02); //set WR bit and send register number
  199. while(nbytes) {
  200. while(!(SPSR & (1 << SPIF))); //check if previous byte was sent
  201. SPDR = (*data_p); // send next data byte
  202. nbytes--;
  203. data_p++; // advance data pointer
  204. }
  205. while(!(SPSR & (1 << SPIF)));
  206. #endif
  207. SPI_SS::Set();
  208. #if SPI_HAS_TRANSACTION
  209. SPI.endTransaction();
  210. #endif
  211. XMEM_RELEASE_SPI();
  212. return ( data_p);
  213. }
  214. /* GPIO write */
  215. /*GPIO byte is split between 2 registers, so two writes are needed to write one byte */
  216. /* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */
  217. template< typename SPI_SS, typename INTR >
  218. void MAX3421e< SPI_SS, INTR >::gpioWr(uint8_t data) {
  219. regWr(rIOPINS1, data);
  220. data >>= 4;
  221. regWr(rIOPINS2, data);
  222. return;
  223. }
  224. /* single host register read */
  225. template< typename SPI_SS, typename INTR >
  226. uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) {
  227. XMEM_ACQUIRE_SPI();
  228. #if SPI_HAS_TRANSACTION
  229. SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0
  230. #endif
  231. SPI_SS::Clear();
  232. #if USING_SPI4TEENSY3
  233. spi4teensy3::send(reg);
  234. uint8_t rv = spi4teensy3::receive();
  235. SPI_SS::Set();
  236. #elif !defined(SPDR) || SPI_HAS_TRANSACTION
  237. SPI.transfer(reg);
  238. uint8_t rv = SPI.transfer(0); // Send empty byte
  239. SPI_SS::Set();
  240. #else
  241. SPDR = reg;
  242. while(!(SPSR & (1 << SPIF)));
  243. SPDR = 0; // Send empty byte
  244. while(!(SPSR & (1 << SPIF)));
  245. SPI_SS::Set();
  246. uint8_t rv = SPDR;
  247. #endif
  248. #if SPI_HAS_TRANSACTION
  249. SPI.endTransaction();
  250. #endif
  251. XMEM_RELEASE_SPI();
  252. return (rv);
  253. }
  254. /* multiple-byte register read */
  255. /* returns a pointer to a memory position after last read */
  256. template< typename SPI_SS, typename INTR >
  257. uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
  258. XMEM_ACQUIRE_SPI();
  259. #if SPI_HAS_TRANSACTION
  260. SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0
  261. #endif
  262. SPI_SS::Clear();
  263. #if USING_SPI4TEENSY3
  264. spi4teensy3::send(reg);
  265. spi4teensy3::receive(data_p, nbytes);
  266. data_p += nbytes;
  267. #elif SPI_HAS_TRANSACTION
  268. SPI.transfer(reg);
  269. memset(data_p, 0, nbytes); // Make sure we send out empty bytes
  270. SPI.transfer(data_p, nbytes);
  271. data_p += nbytes;
  272. #elif defined(__ARDUINO_X86__)
  273. SPI.transfer(reg);
  274. SPI.transferBuffer(NULL, data_p, nbytes);
  275. data_p += nbytes;
  276. #elif !defined(SPDR)
  277. SPI.transfer(reg);
  278. while(nbytes) {
  279. *data_p++ = SPI.transfer(0);
  280. nbytes--;
  281. }
  282. #else
  283. SPDR = reg;
  284. while(!(SPSR & (1 << SPIF))); //wait
  285. while(nbytes) {
  286. SPDR = 0; // Send empty byte
  287. nbytes--;
  288. while(!(SPSR & (1 << SPIF)));
  289. #if 0
  290. {
  291. *data_p = SPDR;
  292. printf("%2.2x ", *data_p);
  293. }
  294. data_p++;
  295. }
  296. printf("\r\n");
  297. #else
  298. *data_p++ = SPDR;
  299. }
  300. #endif
  301. #endif
  302. SPI_SS::Set();
  303. #if SPI_HAS_TRANSACTION
  304. SPI.endTransaction();
  305. #endif
  306. XMEM_RELEASE_SPI();
  307. return ( data_p);
  308. }
  309. /* GPIO read. See gpioWr for explanation */
  310. /* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */
  311. template< typename SPI_SS, typename INTR >
  312. uint8_t MAX3421e< SPI_SS, INTR >::gpioRd() {
  313. uint8_t gpin = 0;
  314. gpin = regRd(rIOPINS2); //pins 4-7
  315. gpin &= 0xf0; //clean lower nibble
  316. gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation.
  317. return ( gpin);
  318. }
  319. /* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset
  320. or zero if PLL haven't stabilized in 65535 cycles */
  321. template< typename SPI_SS, typename INTR >
  322. uint16_t MAX3421e< SPI_SS, INTR >::reset() {
  323. uint16_t i = 0;
  324. regWr(rUSBCTL, bmCHIPRES);
  325. regWr(rUSBCTL, 0x00);
  326. while(++i) {
  327. if((regRd(rUSBIRQ) & bmOSCOKIRQ)) {
  328. break;
  329. }
  330. }
  331. return ( i);
  332. }
  333. /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
  334. template< typename SPI_SS, typename INTR >
  335. int8_t MAX3421e< SPI_SS, INTR >::Init() {
  336. XMEM_ACQUIRE_SPI();
  337. // Moved here.
  338. // you really should not init hardware in the constructor when it involves locks.
  339. // Also avoids the vbus flicker issue confusing some devices.
  340. /* pin and peripheral setup */
  341. SPI_SS::SetDirWrite();
  342. SPI_SS::Set();
  343. spi::init();
  344. INTR::SetDirRead();
  345. XMEM_RELEASE_SPI();
  346. /* MAX3421E - full-duplex SPI, level interrupt */
  347. // GPX pin on. Moved here, otherwise we flicker the vbus.
  348. regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));
  349. if(reset() == 0) { //OSCOKIRQ hasn't asserted in time
  350. return ( -1);
  351. }
  352. regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
  353. regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection
  354. /* check if device is connected */
  355. regWr(rHCTL, bmSAMPLEBUS); // sample USB bus
  356. while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish
  357. busprobe(); //check if anything is connected
  358. regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt
  359. regWr(rCPUCTL, 0x01); //enable interrupt pin
  360. return ( 0);
  361. }
  362. /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
  363. template< typename SPI_SS, typename INTR >
  364. int8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) {
  365. XMEM_ACQUIRE_SPI();
  366. // Moved here.
  367. // you really should not init hardware in the constructor when it involves locks.
  368. // Also avoids the vbus flicker issue confusing some devices.
  369. /* pin and peripheral setup */
  370. SPI_SS::SetDirWrite();
  371. SPI_SS::Set();
  372. spi::init();
  373. INTR::SetDirRead();
  374. XMEM_RELEASE_SPI();
  375. /* MAX3421E - full-duplex SPI, level interrupt, vbus off */
  376. regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET));
  377. if(reset() == 0) { //OSCOKIRQ hasn't asserted in time
  378. return ( -1);
  379. }
  380. // Delay a minimum of 1 second to ensure any capacitors are drained.
  381. // 1 second is required to make sure we do not smoke a Microdrive!
  382. if(mseconds < 1000) mseconds = 1000;
  383. delay(mseconds);
  384. regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
  385. regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection
  386. /* check if device is connected */
  387. regWr(rHCTL, bmSAMPLEBUS); // sample USB bus
  388. while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish
  389. busprobe(); //check if anything is connected
  390. regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt
  391. regWr(rCPUCTL, 0x01); //enable interrupt pin
  392. // GPX pin on. This is done here so that busprobe will fail if we have a switch connected.
  393. regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));
  394. return ( 0);
  395. }
  396. /* probe bus to determine device presence and speed and switch host to this speed */
  397. template< typename SPI_SS, typename INTR >
  398. void MAX3421e< SPI_SS, INTR >::busprobe() {
  399. uint8_t bus_sample;
  400. bus_sample = regRd(rHRSL); //Get J,K status
  401. bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte
  402. switch(bus_sample) { //start full-speed or low-speed host
  403. case( bmJSTATUS):
  404. if((regRd(rMODE) & bmLOWSPEED) == 0) {
  405. regWr(rMODE, MODE_FS_HOST); //start full-speed host
  406. vbusState = FSHOST;
  407. } else {
  408. regWr(rMODE, MODE_LS_HOST); //start low-speed host
  409. vbusState = LSHOST;
  410. }
  411. break;
  412. case( bmKSTATUS):
  413. if((regRd(rMODE) & bmLOWSPEED) == 0) {
  414. regWr(rMODE, MODE_LS_HOST); //start low-speed host
  415. vbusState = LSHOST;
  416. } else {
  417. regWr(rMODE, MODE_FS_HOST); //start full-speed host
  418. vbusState = FSHOST;
  419. }
  420. break;
  421. case( bmSE1): //illegal state
  422. vbusState = SE1;
  423. break;
  424. case( bmSE0): //disconnected state
  425. regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ);
  426. vbusState = SE0;
  427. break;
  428. }//end switch( bus_sample )
  429. }
  430. /* MAX3421 state change task and interrupt handler */
  431. template< typename SPI_SS, typename INTR >
  432. uint8_t MAX3421e< SPI_SS, INTR >::Task(void) {
  433. uint8_t rcode = 0;
  434. uint8_t pinvalue;
  435. //USB_HOST_SERIAL.print("Vbus state: ");
  436. //USB_HOST_SERIAL.println( vbusState, HEX );
  437. pinvalue = INTR::IsSet(); //Read();
  438. //pinvalue = digitalRead( MAX_INT );
  439. if(pinvalue == 0) {
  440. rcode = IntHandler();
  441. }
  442. // pinvalue = digitalRead( MAX_GPX );
  443. // if( pinvalue == LOW ) {
  444. // GpxHandler();
  445. // }
  446. // usbSM(); //USB state machine
  447. return ( rcode);
  448. }
  449. template< typename SPI_SS, typename INTR >
  450. uint8_t MAX3421e< SPI_SS, INTR >::IntHandler() {
  451. uint8_t HIRQ;
  452. uint8_t HIRQ_sendback = 0x00;
  453. HIRQ = regRd(rHIRQ); //determine interrupt source
  454. //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler
  455. // HIRQ_sendback |= bmFRAMEIRQ;
  456. //}//end FRAMEIRQ handling
  457. if(HIRQ & bmCONDETIRQ) {
  458. busprobe();
  459. HIRQ_sendback |= bmCONDETIRQ;
  460. }
  461. /* End HIRQ interrupts handling, clear serviced IRQs */
  462. regWr(rHIRQ, HIRQ_sendback);
  463. return ( HIRQ_sendback);
  464. }
  465. //template< typename SPI_SS, typename INTR >
  466. //uint8_t MAX3421e< SPI_SS, INTR >::GpxHandler()
  467. //{
  468. // uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register
  469. //// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload
  470. //// vbusPwr( OFF ); //attempt powercycle
  471. //// delay( 1000 );
  472. //// vbusPwr( ON );
  473. //// regWr( rGPINIRQ, bmGPINIRQ7 );
  474. //// }
  475. // return( GPINIRQ );
  476. //}
  477. #endif // _USBHOST_H_