Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UsbHostMAX3421E_Hello
MAX3421E.cpp
00001 #include "MAX3421E.h" 00002 00003 uint8_t MAX3421E::vbusState = 0; 00004 00005 /* constructor */ 00006 MAX3421E::MAX3421E(PinName mosi, PinName miso, PinName sck, PinName ss, PinName intr) : 00007 _spi(mosi, miso, sck), 00008 _ss(ss), 00009 _intr(intr) 00010 {} 00011 00012 /* write single byte into MAX3421 register */ 00013 void MAX3421E::regWr(uint8_t reg, uint8_t data) 00014 { 00015 _ss = 0; 00016 char tx[2]; 00017 tx[0] = reg | 0x02; 00018 tx[1] = data; 00019 _spi.write(tx, 2, NULL, 2); 00020 _ss = 1; 00021 return; 00022 } 00023 00024 /* multiple-byte write */ 00025 00026 /* returns a pointer to memory position after last written */ 00027 uint8_t* MAX3421E::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) 00028 { 00029 _ss = 0; 00030 const char data = reg | 0x02; 00031 _spi.write(&data, 1, NULL, 1); 00032 _spi.write((const char*)data_p, nbytes, NULL, nbytes); 00033 data_p += nbytes; 00034 _ss = 1; 00035 return(data_p); 00036 } 00037 00038 /* GPIO write */ 00039 /*GPIO byte is split between 2 registers, so two writes are needed to write one byte */ 00040 00041 /* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */ 00042 void MAX3421E::gpioWr(uint8_t data) 00043 { 00044 regWr(rIOPINS1, data); 00045 data >>= 4; 00046 regWr(rIOPINS2, data); 00047 return; 00048 } 00049 00050 /* single host register read */ 00051 uint8_t MAX3421E::regRd(uint8_t reg) 00052 { 00053 _ss = 0; 00054 _spi.write((const char*)®, 1, NULL, 1); 00055 uint8_t rv = 0; 00056 _spi.write((const char*)&rv, 1, (char*)&rv, 1); 00057 _ss = 1; 00058 return(rv); 00059 } 00060 00061 /* multiple-byte register read */ 00062 00063 /* returns a pointer to a memory position after last read */ 00064 uint8_t* MAX3421E::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) 00065 { 00066 _ss = 0; 00067 _spi.write((const char*)®, 1, NULL, 1); 00068 memset(data_p, 0, nbytes); // Make sure we send out empty bytes 00069 _spi.write((const char*)data_p, nbytes, (char*)data_p, nbytes); 00070 data_p += nbytes; 00071 _ss = 1; 00072 return(data_p); 00073 } 00074 00075 /* GPIO read. See gpioWr for explanation */ 00076 /** @brief Reads the current GPI input values 00077 * @retval uint8_t Bitwise value of all 8 GPI inputs 00078 */ 00079 00080 /* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */ 00081 uint8_t MAX3421E::gpioRd() 00082 { 00083 uint8_t gpin = 0; 00084 gpin = regRd(rIOPINS2); //pins 4-7 00085 gpin &= 0xf0; //clean lower nibble 00086 gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation. 00087 return(gpin); 00088 } 00089 00090 /** @brief Reads the current GPI output values 00091 * @retval uint8_t Bitwise value of all 8 GPI outputs 00092 */ 00093 00094 /* GPOUT pins are in low nibbles of IOPINS1, IOPINS2 */ 00095 uint8_t MAX3421E::gpioRdOutput() 00096 { 00097 uint8_t gpout = 0; 00098 gpout = regRd(rIOPINS1); //pins 0-3 00099 gpout &= 0x0f; //clean upper nibble 00100 gpout |= (regRd(rIOPINS2) << 4); //shift high bits and OR with lower from previous operation. 00101 return(gpout); 00102 } 00103 00104 /* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset 00105 or zero if PLL haven't stabilized in 65535 cycles */ 00106 uint16_t MAX3421E::reset() 00107 { 00108 uint16_t i = 0; 00109 regWr(rUSBCTL, bmCHIPRES); 00110 regWr(rUSBCTL, 0x00); 00111 while (++i) { 00112 if ((regRd(rUSBIRQ) & bmOSCOKIRQ)) { 00113 break; 00114 } 00115 } 00116 00117 return(i); 00118 } 00119 00120 /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ 00121 int8_t MAX3421E::init() 00122 { 00123 // Moved here. 00124 00125 // you really should not init hardware in the constructor when it involves locks. 00126 // Also avoids the vbus flicker issue confusing some devices. 00127 /* pin and peripheral setup */ 00128 _ss = 1; 00129 _spi.frequency(26000000); 00130 00131 /* MAX3421E - full-duplex SPI, level interrupt */ 00132 // GPX pin on. Moved here, otherwise we flicker the vbus. 00133 regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); 00134 00135 if (reset() == 0) { 00136 00137 //OSCOKIRQ hasn't asserted in time 00138 return(-1); 00139 } 00140 00141 regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host 00142 regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection 00143 00144 /* check if device is connected */ 00145 regWr(rHCTL, bmSAMPLEBUS); // sample USB bus 00146 while (!(regRd(rHCTL) & bmSAMPLEBUS)); 00147 00148 //wait for sample operation to finish 00149 busprobe(); //check if anything is connected 00150 regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt 00151 regWr(rCPUCTL, 0x01); //enable interrupt pin 00152 return(0); 00153 } 00154 00155 /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ 00156 int8_t MAX3421E::init(int mseconds) 00157 { 00158 // Moved here. 00159 00160 // you really should not init hardware in the constructor when it involves locks. 00161 // Also avoids the vbus flicker issue confusing some devices. 00162 /* pin and peripheral setup */ 00163 _ss = 1; 00164 _spi.frequency(26000000); // MAX3421E max frequency 00165 00166 /* MAX3421E - full-duplex SPI, level interrupt, vbus off */ 00167 regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET)); 00168 00169 if (reset() == 0) { 00170 00171 //OSCOKIRQ hasn't asserted in time 00172 return(-1); 00173 } 00174 00175 // Delay a minimum of 1 second to ensure any capacitors are drained. 00176 // 1 second is required to make sure we do not smoke a Microdrive! 00177 if (mseconds < 1000) 00178 mseconds = 1000; 00179 wait_ms(mseconds); 00180 00181 regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host 00182 regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection 00183 00184 /* check if device is connected */ 00185 regWr(rHCTL, bmSAMPLEBUS); // sample USB bus 00186 while (!(regRd(rHCTL) & bmSAMPLEBUS)); 00187 00188 //wait for sample operation to finish 00189 busprobe(); //check if anything is connected 00190 regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt 00191 regWr(rCPUCTL, 0x01); //enable interrupt pin 00192 00193 // GPX pin on. This is done here so that busprobe will fail if we have a switch connected. 00194 regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); 00195 00196 return(0); 00197 } 00198 00199 /* probe bus to determine device presence and speed and switch host to this speed */ 00200 void MAX3421E::busprobe() 00201 { 00202 uint8_t bus_sample; 00203 bus_sample = regRd(rHRSL); //Get J,K status 00204 bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte 00205 switch (bus_sample) { //start full-speed or low-speed host 00206 case (bmJSTATUS): 00207 if ((regRd(rMODE) & bmLOWSPEED) == 0) { 00208 regWr(rMODE, MODE_FS_HOST); //start full-speed host 00209 vbusState = FSHOST; 00210 } 00211 else { 00212 regWr(rMODE, MODE_LS_HOST); //start low-speed host 00213 vbusState = LSHOST; 00214 } 00215 break; 00216 00217 case (bmKSTATUS): 00218 if ((regRd(rMODE) & bmLOWSPEED) == 0) { 00219 regWr(rMODE, MODE_LS_HOST); //start low-speed host 00220 vbusState = LSHOST; 00221 } 00222 else { 00223 regWr(rMODE, MODE_FS_HOST); //start full-speed host 00224 vbusState = FSHOST; 00225 } 00226 break; 00227 00228 case (bmSE1): //illegal state 00229 vbusState = SE1; 00230 break; 00231 00232 case (bmSE0): //disconnected state 00233 regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ); 00234 vbusState = SE0; 00235 break; 00236 } //end switch( bus_sample ) 00237 } 00238 00239 /* MAX3421 state change task and interrupt handler */ 00240 uint8_t MAX3421E::task(void) 00241 { 00242 uint8_t rcode = 0; 00243 uint8_t pinvalue; 00244 //USB_HOST_SERIAL.print("Vbus state: "); 00245 00246 //USB_HOST_SERIAL.println( vbusState, HEX ); 00247 pinvalue = _intr; //Read(); 00248 00249 //pinvalue = digitalRead( MAX_INT ); 00250 if (pinvalue == 0) { 00251 rcode = intHandler(); 00252 } 00253 00254 // pinvalue = digitalRead( MAX_GPX ); 00255 // if( pinvalue == LOW ) { 00256 // GpxHandler(); 00257 // } 00258 // usbSM(); //USB state machine 00259 return(rcode); 00260 } 00261 00262 /** 00263 * @brief 00264 * @note 00265 * @param 00266 * @retval 00267 */ 00268 uint8_t MAX3421E::intHandler() 00269 { 00270 uint8_t HIRQ; 00271 uint8_t HIRQ_sendback = 0x00; 00272 HIRQ = regRd(rHIRQ); //determine interrupt source 00273 00274 //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler 00275 // HIRQ_sendback |= bmFRAMEIRQ; 00276 //}//end FRAMEIRQ handling 00277 if (HIRQ & bmCONDETIRQ) { 00278 busprobe(); 00279 HIRQ_sendback |= bmCONDETIRQ; 00280 } 00281 00282 /* End HIRQ interrupts handling, clear serviced IRQs */ 00283 regWr(rHIRQ, HIRQ_sendback); 00284 return(HIRQ_sendback); 00285 } 00286 00287 //template< typename SPI_SS, typename INTR > 00288 //uint8_t MAX3421E::GpxHandler() 00289 //{ 00290 // uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register 00291 //// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload 00292 //// vbusPwr( OFF ); //attempt powercycle 00293 //// wait_ms( 1000 ); 00294 //// vbusPwr( ON ); 00295 //// regWr( rGPINIRQ, bmGPINIRQ7 ); 00296 //// } 00297 // return( GPINIRQ ); 00298 //}
Generated on Tue Jul 12 2022 18:12:04 by
1.7.2