My Marlin configs for Fabrikator Mini and CTC i3 Pro B
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.

usbhost.cpp 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /****************
  2. * usb_host.cpp *
  3. ****************/
  4. /****************************************************************************
  5. * Written By Marcio Teixeira 2018 - Aleph Objects, Inc. *
  6. * *
  7. * This program is free software: you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation, either version 3 of the License, or *
  10. * (at your option) any later version. *
  11. * *
  12. * This program is distributed in the hope that it will be useful, *
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15. * GNU General Public License for more details. *
  16. * *
  17. * To view a copy of the GNU General Public License, go to the following *
  18. * location: <https://www.gnu.org/licenses/>. *
  19. ****************************************************************************/
  20. /* What follows is a modified version of the MAX3421e originally defined in
  21. * lib/usbhost.c". This has been rewritten to use SPI routines from the
  22. * Marlin HAL */
  23. #include "../../../inc/MarlinConfigPre.h"
  24. #if ENABLED(USB_FLASH_DRIVE_SUPPORT) && DISABLED(USE_UHS3_USB)
  25. #if !PINS_EXIST(USB_CS, USB_INTR)
  26. #error "USB_FLASH_DRIVE_SUPPORT requires USB_CS_PIN and USB_INTR_PIN to be defined."
  27. #endif
  28. #include "Usb.h"
  29. #include "usbhost.h"
  30. uint8_t MAX3421e::vbusState = 0;
  31. // constructor
  32. void MAX3421e::cs() { WRITE(USB_CS_PIN, LOW); }
  33. void MAX3421e::ncs() { WRITE(USB_CS_PIN, HIGH); }
  34. // write single byte into MAX3421 register
  35. void MAX3421e::regWr(uint8_t reg, uint8_t data) {
  36. cs();
  37. spiSend(reg | 0x02);
  38. spiSend(data);
  39. ncs();
  40. }
  41. // multiple-byte write
  42. // return a pointer to memory position after last written
  43. uint8_t* MAX3421e::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t *data_p) {
  44. cs();
  45. spiSend(reg | 0x02);
  46. while (nbytes--) spiSend(*data_p++);
  47. ncs();
  48. return data_p;
  49. }
  50. // GPIO write
  51. // GPIO byte is split between 2 registers, so two writes are needed to write one byte
  52. // GPOUT bits are in the low nybble. 0-3 in IOPINS1, 4-7 in IOPINS2
  53. void MAX3421e::gpioWr(uint8_t data) {
  54. regWr(rIOPINS1, data);
  55. regWr(rIOPINS2, data >> 4);
  56. }
  57. // single host register read
  58. uint8_t MAX3421e::regRd(uint8_t reg) {
  59. cs();
  60. spiSend(reg);
  61. uint8_t rv = spiRec();
  62. ncs();
  63. return rv;
  64. }
  65. // multiple-byte register read
  66. // return a pointer to a memory position after last read
  67. uint8_t* MAX3421e::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t *data_p) {
  68. cs();
  69. spiSend(reg);
  70. while (nbytes--) *data_p++ = spiRec();
  71. ncs();
  72. return data_p;
  73. }
  74. // GPIO read. See gpioWr for explanation
  75. // GPIN pins are in high nybbles of IOPINS1, IOPINS2
  76. uint8_t MAX3421e::gpioRd() {
  77. return (regRd(rIOPINS2) & 0xF0) | // pins 4-7, clean lower nybble
  78. (regRd(rIOPINS1) >> 4); // shift low bits and OR with upper from previous operation.
  79. }
  80. // reset MAX3421e. Returns false if PLL failed to stabilize 1 second after reset
  81. bool MAX3421e::reset() {
  82. regWr(rUSBCTL, bmCHIPRES);
  83. regWr(rUSBCTL, 0x00);
  84. for (uint8_t i = 100; i--;) {
  85. if (regRd(rUSBIRQ) & bmOSCOKIRQ) return true;
  86. delay(10);
  87. }
  88. return false;
  89. }
  90. // initialize MAX3421e. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not
  91. bool MAX3421e::start() {
  92. // Initialize pins and SPI bus
  93. SET_OUTPUT(USB_CS_PIN);
  94. SET_INPUT_PULLUP(USB_INTR_PIN);
  95. ncs();
  96. spiBegin();
  97. spiInit(SD_SPI_SPEED);
  98. // MAX3421e - full-duplex, level interrupt, vbus off.
  99. regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET));
  100. const uint8_t revision = regRd(rREVISION);
  101. if (revision == 0x00 || revision == 0xFF) {
  102. SERIAL_ECHOLNPGM("Revision register appears incorrect on MAX3421e initialization. Got ", revision);
  103. return false;
  104. }
  105. if (!reset()) {
  106. SERIAL_ECHOLNPGM("OSCOKIRQ hasn't asserted in time");
  107. return false;
  108. }
  109. // Delay a minimum of 1 second to ensure any capacitors are drained.
  110. // 1 second is required to make sure we do not smoke a Microdrive!
  111. delay(1000);
  112. regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
  113. regWr(rHIEN, bmCONDETIE | bmFRAMEIE); // connection detection
  114. // check if device is connected
  115. regWr(rHCTL, bmSAMPLEBUS); // sample USB bus
  116. while (!(regRd(rHCTL) & bmSAMPLEBUS)) delay(10); // wait for sample operation to finish
  117. busprobe(); // check if anything is connected
  118. regWr(rHIRQ, bmCONDETIRQ); // clear connection detect interrupt
  119. regWr(rCPUCTL, 0x01); // enable interrupt pin
  120. // GPX pin on. This is done here so that busprobe will fail if we have a switch connected.
  121. regWr(rPINCTL, bmFDUPSPI | bmINTLEVEL);
  122. return true;
  123. }
  124. // Probe bus to determine device presence and speed. Switch host to this speed.
  125. void MAX3421e::busprobe() {
  126. // Switch on just the J & K bits
  127. switch (regRd(rHRSL) & (bmJSTATUS | bmKSTATUS)) {
  128. case bmJSTATUS:
  129. if ((regRd(rMODE) & bmLOWSPEED) == 0) {
  130. regWr(rMODE, MODE_FS_HOST); // start full-speed host
  131. vbusState = FSHOST;
  132. }
  133. else {
  134. regWr(rMODE, MODE_LS_HOST); // start low-speed host
  135. vbusState = LSHOST;
  136. }
  137. break;
  138. case bmKSTATUS:
  139. if ((regRd(rMODE) & bmLOWSPEED) == 0) {
  140. regWr(rMODE, MODE_LS_HOST); // start low-speed host
  141. vbusState = LSHOST;
  142. }
  143. else {
  144. regWr(rMODE, MODE_FS_HOST); // start full-speed host
  145. vbusState = FSHOST;
  146. }
  147. break;
  148. case bmSE1: // illegal state
  149. vbusState = SE1;
  150. break;
  151. case bmSE0: // disconnected state
  152. regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ);
  153. vbusState = SE0;
  154. break;
  155. }
  156. }
  157. // MAX3421 state change task and interrupt handler
  158. uint8_t MAX3421e::Task() {
  159. return READ(USB_INTR_PIN) ? 0 : IntHandler();
  160. }
  161. uint8_t MAX3421e::IntHandler() {
  162. uint8_t HIRQ = regRd(rHIRQ), // determine interrupt source
  163. HIRQ_sendback = 0x00;
  164. if (HIRQ & bmCONDETIRQ) {
  165. busprobe();
  166. HIRQ_sendback |= bmCONDETIRQ;
  167. }
  168. // End HIRQ interrupts handling, clear serviced IRQs
  169. regWr(rHIRQ, HIRQ_sendback);
  170. return HIRQ_sendback;
  171. }
  172. #endif // USB_FLASH_DRIVE_SUPPORT