Home | History | Annotate | Download | only in USB_Host_Shield
      1 /*
      2  * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com
      3  * MAX3421E USB host controller support
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. Neither the name of the authors nor the names of its contributors
     14  *    may be used to endorse or promote products derived from this software
     15  *    without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 /* MAX3421E USB host controller support */
     31 
     32 #include "Max3421e.h"
     33 // #include "Max3421e_constants.h"
     34 
     35 static byte vbusState;
     36 
     37 /* Functions    */
     38 
     39 #define INT		PE6
     40 #define INT_PORT	PORTE
     41 #define INT_DDR		DDRE
     42 #define INT_PIN		PINE
     43 
     44 #define RST		PJ2
     45 #define RST_PORT	PORTJ
     46 #define RST_DDR		DDRJ
     47 #define RST_PIN		PINJ
     48 
     49 #define GPX		PJ3
     50 #define GPX_PORT	PORTJ
     51 #define GPX_DDR		DDRJ
     52 #define GPX_PIN		PINJ
     53 
     54 
     55 void MAX3421E::setRST(uint8_t val)
     56 {
     57 	if (val == LOW)
     58 		RST_PORT &= ~_BV(RST);
     59 	else
     60 		RST_PORT |= _BV(RST);
     61 }
     62 
     63 uint8_t MAX3421E::readINT(void)
     64 {
     65 	return INT_PIN & _BV(INT) ? HIGH : LOW;
     66 }
     67 
     68 uint8_t MAX3421E::readGPX(void)
     69 {
     70 	// return GPX_PIN & _BV(GPX) ? HIGH : LOW;
     71 	return LOW;
     72 }
     73 
     74 
     75 void MAX3421E::pinInit(void)
     76 {
     77 	INT_DDR &= ~_BV(INT);
     78 	RST_DDR |= _BV(RST);
     79 	digitalWrite(MAX_SS,HIGH);
     80 	setRST(HIGH);
     81 }
     82 
     83 
     84 /* Constructor */
     85 MAX3421E::MAX3421E()
     86 {
     87     spi_init();
     88 	pinInit();
     89 }
     90 
     91 byte MAX3421E::getVbusState( void )
     92 {
     93     return( vbusState );
     94 }
     95 /* initialization */
     96 //void MAX3421E::init()
     97 //{
     98 //    /* setup pins */
     99 //    pinMode( MAX_INT, INPUT);
    100 //    pinMode( MAX_GPX, INPUT );
    101 //    pinMode( MAX_SS, OUTPUT );
    102 //    //pinMode( BPNT_0, OUTPUT );
    103 //    //pinMode( BPNT_1, OUTPUT );
    104 //    //digitalWrite( BPNT_0, LOW );
    105 //    //digitalWrite( BPNT_1, LOW );
    106 //    Deselect_MAX3421E;
    107 //    pinMode( MAX_RESET, OUTPUT );
    108 //    digitalWrite( MAX_RESET, HIGH );  //release MAX3421E from reset
    109 //}
    110 //byte MAX3421E::getVbusState( void )
    111 //{
    112 //    return( vbusState );
    113 //}
    114 //void MAX3421E::toggle( byte pin )
    115 //{
    116 //    digitalWrite( pin, HIGH );
    117 //    digitalWrite( pin, LOW );
    118 //}
    119 /* Single host register write   */
    120 void MAX3421E::regWr( byte reg, byte val)
    121 {
    122       digitalWrite(MAX_SS,LOW);
    123       SPDR = ( reg | 0x02 );
    124       while(!( SPSR & ( 1 << SPIF )));
    125       SPDR = val;
    126       while(!( SPSR & ( 1 << SPIF )));
    127       digitalWrite(MAX_SS,HIGH);
    128       return;
    129 }
    130 /* multiple-byte write */
    131 /* returns a pointer to a memory position after last written */
    132 char * MAX3421E::bytesWr( byte reg, byte nbytes, char * data )
    133 {
    134     digitalWrite(MAX_SS,LOW);
    135     SPDR = ( reg | 0x02 );
    136     while( nbytes-- ) {
    137       while(!( SPSR & ( 1 << SPIF )));  //check if previous byte was sent
    138       SPDR = ( *data );               // send next data byte
    139       data++;                         // advance data pointer
    140     }
    141     while(!( SPSR & ( 1 << SPIF )));
    142     digitalWrite(MAX_SS,HIGH);
    143     return( data );
    144 }
    145 /* GPIO write. GPIO byte is split between 2 registers, so two writes are needed to write one byte */
    146 /* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */
    147 /* upper 4 bits of IOPINS1, IOPINS2 are read-only, so no masking is necessary */
    148 void MAX3421E::gpioWr( byte val )
    149 {
    150     regWr( rIOPINS1, val );
    151     val = val >>4;
    152     regWr( rIOPINS2, val );
    153 
    154     return;
    155 }
    156 /* Single host register read        */
    157 byte MAX3421E::regRd( byte reg )
    158 {
    159   byte tmp;
    160     digitalWrite(MAX_SS,LOW);
    161     SPDR = reg;
    162     while(!( SPSR & ( 1 << SPIF )));
    163     SPDR = 0; //send empty byte
    164     while(!( SPSR & ( 1 << SPIF )));
    165     digitalWrite(MAX_SS,HIGH);
    166     return( SPDR );
    167 }
    168 /* multiple-bytes register read                             */
    169 /* returns a pointer to a memory position after last read   */
    170 char * MAX3421E::bytesRd ( byte reg, byte nbytes, char  * data )
    171 {
    172     digitalWrite(MAX_SS,LOW);
    173     SPDR = reg;
    174     while(!( SPSR & ( 1 << SPIF )));    //wait
    175     while( nbytes ) {
    176       SPDR = 0; //send empty byte
    177       nbytes--;
    178       while(!( SPSR & ( 1 << SPIF )));
    179       *data = SPDR;
    180       data++;
    181     }
    182     digitalWrite(MAX_SS,HIGH);
    183     return( data );
    184 }
    185 /* GPIO read. See gpioWr for explanation */
    186 /* GPIN pins are in high nibbles of IOPINS1, IOPINS2    */
    187 byte MAX3421E::gpioRd( void )
    188 {
    189  byte tmpbyte = 0;
    190     tmpbyte = regRd( rIOPINS2 );            //pins 4-7
    191     tmpbyte &= 0xf0;                        //clean lower nibble
    192     tmpbyte |= ( regRd( rIOPINS1 ) >>4 ) ;  //shift low bits and OR with upper from previous operation. Upper nibble zeroes during shift, at least with this compiler
    193     return( tmpbyte );
    194 }
    195 /* reset MAX3421E using chip reset bit. SPI configuration is not affected   */
    196 boolean MAX3421E::reset()
    197 {
    198   byte tmp = 0;
    199     regWr( rUSBCTL, bmCHIPRES );                        //Chip reset. This stops the oscillator
    200     regWr( rUSBCTL, 0x00 );                             //Remove the reset
    201     while(!(regRd( rUSBIRQ ) & bmOSCOKIRQ )) {          //wait until the PLL is stable
    202         tmp++;                                          //timeout after 256 attempts
    203         if( tmp == 0 ) {
    204             return( false );
    205         }
    206     }
    207     return( true );
    208 }
    209 /* turn USB power on/off                                                */
    210 /* does nothing, returns TRUE. Left for compatibility with old sketches               */
    211 /* will be deleted eventually                                           */
    212 ///* ON pin of VBUS switch (MAX4793 or similar) is connected to GPOUT7    */
    213 ///* OVERLOAD pin of Vbus switch is connected to GPIN7                    */
    214 ///* OVERLOAD state low. NO OVERLOAD or VBUS OFF state high.              */
    215 boolean MAX3421E::vbusPwr ( boolean action )
    216 {
    217 //  byte tmp;
    218 //    tmp = regRd( rIOPINS2 );                //copy of IOPINS2
    219 //    if( action ) {                          //turn on by setting GPOUT7
    220 //        tmp |= bmGPOUT7;
    221 //    }
    222 //    else {                                  //turn off by clearing GPOUT7
    223 //        tmp &= ~bmGPOUT7;
    224 //    }
    225 //    regWr( rIOPINS2, tmp );                 //send GPOUT7
    226 //    if( action ) {
    227 //        delay( 60 );
    228 //    }
    229 //    if (( regRd( rIOPINS2 ) & bmGPIN7 ) == 0 ) {     // check if overload is present. MAX4793 /FLAG ( pin 4 ) goes low if overload
    230 //        return( false );
    231 //    }
    232     return( true );                                             // power on/off successful
    233 }
    234 /* probe bus to determine device presense and speed and switch host to this speed */
    235 void MAX3421E::busprobe( void )
    236 {
    237  byte bus_sample;
    238     bus_sample = regRd( rHRSL );            //Get J,K status
    239     bus_sample &= ( bmJSTATUS|bmKSTATUS );      //zero the rest of the byte
    240     switch( bus_sample ) {                          //start full-speed or low-speed host
    241         case( bmJSTATUS ):
    242             if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {
    243                 regWr( rMODE, MODE_FS_HOST );       //start full-speed host
    244                 vbusState = FSHOST;
    245             }
    246             else {
    247                 regWr( rMODE, MODE_LS_HOST);        //start low-speed host
    248                 vbusState = LSHOST;
    249             }
    250             break;
    251         case( bmKSTATUS ):
    252             if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {
    253                 regWr( rMODE, MODE_LS_HOST );       //start low-speed host
    254                 vbusState = LSHOST;
    255             }
    256             else {
    257                 regWr( rMODE, MODE_FS_HOST );       //start full-speed host
    258                 vbusState = FSHOST;
    259             }
    260             break;
    261         case( bmSE1 ):              //illegal state
    262             vbusState = SE1;
    263             break;
    264         case( bmSE0 ):              //disconnected state
    265 		regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST|bmSEPIRQ);
    266             vbusState = SE0;
    267             break;
    268         }//end switch( bus_sample )
    269 }
    270 /* MAX3421E initialization after power-on   */
    271 void MAX3421E::powerOn()
    272 {
    273     /* Configure full-duplex SPI, interrupt pulse   */
    274     regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL + bmGPXB ));    //Full-duplex SPI, level interrupt, GPX
    275     if( reset() == false ) {                                //stop/start the oscillator
    276         Serial.println("Error: OSCOKIRQ failed to assert");
    277     }
    278 
    279     /* configure host operation */
    280     regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST|bmSEPIRQ );      // set pull-downs, Host, Separate GPIN IRQ on GPX
    281     regWr( rHIEN, bmCONDETIE|bmFRAMEIE );                                             //connection detection
    282     /* check if device is connected */
    283     regWr( rHCTL,bmSAMPLEBUS );                                             // sample USB bus
    284     while(!(regRd( rHCTL ) & bmSAMPLEBUS ));                                //wait for sample operation to finish
    285     busprobe();                                                             //check if anything is connected
    286     regWr( rHIRQ, bmCONDETIRQ );                                            //clear connection detect interrupt
    287     regWr( rCPUCTL, 0x01 );                                                 //enable interrupt pin
    288 }
    289 /* MAX3421 state change task and interrupt handler */
    290 byte MAX3421E::Task( void )
    291 {
    292  byte rcode = 0;
    293  byte pinvalue;
    294     //Serial.print("Vbus state: ");
    295     //Serial.println( vbusState, HEX );
    296  pinvalue = readINT();
    297  if( pinvalue  == LOW ) {
    298         rcode = IntHandler();
    299     }
    300     pinvalue = readGPX();
    301     if( pinvalue == LOW ) {
    302         GpxHandler();
    303     }
    304 //    usbSM();                                //USB state machine
    305     return( rcode );
    306 }
    307 byte MAX3421E::IntHandler()
    308 {
    309  byte HIRQ;
    310  byte HIRQ_sendback = 0x00;
    311     HIRQ = regRd( rHIRQ );                  //determine interrupt source
    312     //if( HIRQ & bmFRAMEIRQ ) {               //->1ms SOF interrupt handler
    313     //    HIRQ_sendback |= bmFRAMEIRQ;
    314     //}//end FRAMEIRQ handling
    315     if( HIRQ & bmCONDETIRQ ) {
    316         busprobe();
    317         HIRQ_sendback |= bmCONDETIRQ;
    318     }
    319     /* End HIRQ interrupts handling, clear serviced IRQs    */
    320     regWr( rHIRQ, HIRQ_sendback );
    321     return( HIRQ_sendback );
    322 }
    323 byte MAX3421E::GpxHandler()
    324 {
    325  byte GPINIRQ = regRd( rGPINIRQ );          //read GPIN IRQ register
    326 //    if( GPINIRQ & bmGPINIRQ7 ) {            //vbus overload
    327 //        vbusPwr( OFF );                     //attempt powercycle
    328 //        delay( 1000 );
    329 //        vbusPwr( ON );
    330 //        regWr( rGPINIRQ, bmGPINIRQ7 );
    331 //    }
    332     return( GPINIRQ );
    333 }
    334 
    335 //void MAX3421E::usbSM( void )                //USB state machine
    336 //{
    337 //
    338 //
    339 //}
    340