Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MAX3421E.cpp Source File

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*)&reg, 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*)&reg, 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 //}