-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added sources for USB Host shield from https://github.com/felis/USB_H…
- Loading branch information
1 parent
08a2e1f
commit c1da27d
Showing
17 changed files
with
4,309 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ | ||
/* MAX3421E USB host controller support */ | ||
|
||
#include "Max3421e.h" | ||
// #include "Max3421e_constants.h" | ||
|
||
static byte vbusState; | ||
|
||
/* Functions */ | ||
|
||
/* Constructor */ | ||
MAX3421E::MAX3421E() | ||
{ | ||
spi_init(); | ||
pinMode( MAX_INT, INPUT); | ||
pinMode( MAX_GPX, INPUT ); | ||
pinMode( MAX_SS, OUTPUT ); | ||
digitalWrite(MAX_SS,HIGH); | ||
pinMode( MAX_RESET, OUTPUT ); | ||
digitalWrite( MAX_RESET, HIGH ); //release MAX3421E from reset | ||
} | ||
|
||
byte MAX3421E::getVbusState( void ) | ||
{ | ||
return( vbusState ); | ||
} | ||
/* initialization */ | ||
//void MAX3421E::init() | ||
//{ | ||
// /* setup pins */ | ||
// pinMode( MAX_INT, INPUT); | ||
// pinMode( MAX_GPX, INPUT ); | ||
// pinMode( MAX_SS, OUTPUT ); | ||
// //pinMode( BPNT_0, OUTPUT ); | ||
// //pinMode( BPNT_1, OUTPUT ); | ||
// //digitalWrite( BPNT_0, LOW ); | ||
// //digitalWrite( BPNT_1, LOW ); | ||
// Deselect_MAX3421E; | ||
// pinMode( MAX_RESET, OUTPUT ); | ||
// digitalWrite( MAX_RESET, HIGH ); //release MAX3421E from reset | ||
//} | ||
//byte MAX3421E::getVbusState( void ) | ||
//{ | ||
// return( vbusState ); | ||
//} | ||
//void MAX3421E::toggle( byte pin ) | ||
//{ | ||
// digitalWrite( pin, HIGH ); | ||
// digitalWrite( pin, LOW ); | ||
//} | ||
/* Single host register write */ | ||
void MAX3421E::regWr( byte reg, byte val) | ||
{ | ||
digitalWrite(MAX_SS,LOW); | ||
SPDR = ( reg | 0x02 ); | ||
while(!( SPSR & ( 1 << SPIF ))); | ||
SPDR = val; | ||
while(!( SPSR & ( 1 << SPIF ))); | ||
digitalWrite(MAX_SS,HIGH); | ||
return; | ||
} | ||
/* multiple-byte write */ | ||
/* returns a pointer to a memory position after last written */ | ||
char * MAX3421E::bytesWr( byte reg, byte nbytes, char * data ) | ||
{ | ||
digitalWrite(MAX_SS,LOW); | ||
SPDR = ( reg | 0x02 ); | ||
while( nbytes-- ) { | ||
while(!( SPSR & ( 1 << SPIF ))); //check if previous byte was sent | ||
SPDR = ( *data ); // send next data byte | ||
data++; // advance data pointer | ||
} | ||
while(!( SPSR & ( 1 << SPIF ))); | ||
digitalWrite(MAX_SS,HIGH); | ||
return( data ); | ||
} | ||
/* GPIO write. GPIO byte is split between 2 registers, so two writes are needed to write one byte */ | ||
/* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */ | ||
/* upper 4 bits of IOPINS1, IOPINS2 are read-only, so no masking is necessary */ | ||
void MAX3421E::gpioWr( byte val ) | ||
{ | ||
regWr( rIOPINS1, val ); | ||
val = val >>4; | ||
regWr( rIOPINS2, val ); | ||
|
||
return; | ||
} | ||
/* Single host register read */ | ||
byte MAX3421E::regRd( byte reg ) | ||
{ | ||
byte tmp; | ||
digitalWrite(MAX_SS,LOW); | ||
SPDR = reg; | ||
while(!( SPSR & ( 1 << SPIF ))); | ||
SPDR = 0; //send empty byte | ||
while(!( SPSR & ( 1 << SPIF ))); | ||
digitalWrite(MAX_SS,HIGH); | ||
return( SPDR ); | ||
} | ||
/* multiple-bytes register read */ | ||
/* returns a pointer to a memory position after last read */ | ||
char * MAX3421E::bytesRd ( byte reg, byte nbytes, char * data ) | ||
{ | ||
digitalWrite(MAX_SS,LOW); | ||
SPDR = reg; | ||
while(!( SPSR & ( 1 << SPIF ))); //wait | ||
while( nbytes ) { | ||
SPDR = 0; //send empty byte | ||
nbytes--; | ||
while(!( SPSR & ( 1 << SPIF ))); | ||
*data = SPDR; | ||
data++; | ||
} | ||
digitalWrite(MAX_SS,HIGH); | ||
return( data ); | ||
} | ||
/* GPIO read. See gpioWr for explanation */ | ||
/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */ | ||
byte MAX3421E::gpioRd( void ) | ||
{ | ||
byte tmpbyte = 0; | ||
tmpbyte = regRd( rIOPINS2 ); //pins 4-7 | ||
tmpbyte &= 0xf0; //clean lower nibble | ||
tmpbyte |= ( regRd( rIOPINS1 ) >>4 ) ; //shift low bits and OR with upper from previous operation. Upper nibble zeroes during shift, at least with this compiler | ||
return( tmpbyte ); | ||
} | ||
/* reset MAX3421E using chip reset bit. SPI configuration is not affected */ | ||
boolean MAX3421E::reset() | ||
{ | ||
byte tmp = 0; | ||
regWr( rUSBCTL, bmCHIPRES ); //Chip reset. This stops the oscillator | ||
regWr( rUSBCTL, 0x00 ); //Remove the reset | ||
while(!(regRd( rUSBIRQ ) & bmOSCOKIRQ )) { //wait until the PLL is stable | ||
tmp++; //timeout after 256 attempts | ||
if( tmp == 0 ) { | ||
return( false ); | ||
} | ||
} | ||
return( true ); | ||
} | ||
/* turn USB power on/off */ | ||
/* does nothing, returns TRUE. Left for compatibility with old sketches */ | ||
/* will be deleted eventually */ | ||
///* ON pin of VBUS switch (MAX4793 or similar) is connected to GPOUT7 */ | ||
///* OVERLOAD pin of Vbus switch is connected to GPIN7 */ | ||
///* OVERLOAD state low. NO OVERLOAD or VBUS OFF state high. */ | ||
boolean MAX3421E::vbusPwr ( boolean action ) | ||
{ | ||
// byte tmp; | ||
// tmp = regRd( rIOPINS2 ); //copy of IOPINS2 | ||
// if( action ) { //turn on by setting GPOUT7 | ||
// tmp |= bmGPOUT7; | ||
// } | ||
// else { //turn off by clearing GPOUT7 | ||
// tmp &= ~bmGPOUT7; | ||
// } | ||
// regWr( rIOPINS2, tmp ); //send GPOUT7 | ||
// if( action ) { | ||
// delay( 60 ); | ||
// } | ||
// if (( regRd( rIOPINS2 ) & bmGPIN7 ) == 0 ) { // check if overload is present. MAX4793 /FLAG ( pin 4 ) goes low if overload | ||
// return( false ); | ||
// } | ||
return( true ); // power on/off successful | ||
} | ||
/* probe bus to determine device presense and speed and switch host to this speed */ | ||
void MAX3421E::busprobe( void ) | ||
{ | ||
byte bus_sample; | ||
bus_sample = regRd( rHRSL ); //Get J,K status | ||
bus_sample &= ( bmJSTATUS|bmKSTATUS ); //zero the rest of the byte | ||
switch( bus_sample ) { //start full-speed or low-speed host | ||
case( bmJSTATUS ): | ||
if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) { | ||
regWr( rMODE, MODE_FS_HOST ); //start full-speed host | ||
vbusState = FSHOST; | ||
} | ||
else { | ||
regWr( rMODE, MODE_LS_HOST); //start low-speed host | ||
vbusState = LSHOST; | ||
} | ||
break; | ||
case( bmKSTATUS ): | ||
if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) { | ||
regWr( rMODE, MODE_LS_HOST ); //start low-speed host | ||
vbusState = LSHOST; | ||
} | ||
else { | ||
regWr( rMODE, MODE_FS_HOST ); //start full-speed host | ||
vbusState = FSHOST; | ||
} | ||
break; | ||
case( bmSE1 ): //illegal state | ||
vbusState = SE1; | ||
break; | ||
case( bmSE0 ): //disconnected state | ||
vbusState = SE0; | ||
break; | ||
}//end switch( bus_sample ) | ||
} | ||
/* MAX3421E initialization after power-on */ | ||
void MAX3421E::powerOn() | ||
{ | ||
/* Configure full-duplex SPI, interrupt pulse */ | ||
regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL + bmGPXB )); //Full-duplex SPI, level interrupt, GPX | ||
if( reset() == false ) { //stop/start the oscillator | ||
Serial.println("Error: OSCOKIRQ failed to assert"); | ||
} | ||
|
||
/* configure host operation */ | ||
regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST|bmSEPIRQ ); // set pull-downs, Host, Separate GPIN IRQ on GPX | ||
regWr( rHIEN, bmCONDETIE|bmFRAMEIE ); //connection detection | ||
/* check if device is connected */ | ||
regWr( rHCTL,bmSAMPLEBUS ); // sample USB bus | ||
while(!(regRd( rHCTL ) & bmSAMPLEBUS )); //wait for sample operation to finish | ||
busprobe(); //check if anything is connected | ||
regWr( rHIRQ, bmCONDETIRQ ); //clear connection detect interrupt | ||
regWr( rCPUCTL, 0x01 ); //enable interrupt pin | ||
} | ||
/* MAX3421 state change task and interrupt handler */ | ||
byte MAX3421E::Task( void ) | ||
{ | ||
byte rcode = 0; | ||
byte pinvalue; | ||
//Serial.print("Vbus state: "); | ||
//Serial.println( vbusState, HEX ); | ||
pinvalue = digitalRead( MAX_INT ); | ||
if( pinvalue == LOW ) { | ||
rcode = IntHandler(); | ||
} | ||
pinvalue = digitalRead( MAX_GPX ); | ||
if( pinvalue == LOW ) { | ||
GpxHandler(); | ||
} | ||
// usbSM(); //USB state machine | ||
return( rcode ); | ||
} | ||
byte MAX3421E::IntHandler() | ||
{ | ||
byte HIRQ; | ||
byte HIRQ_sendback = 0x00; | ||
HIRQ = regRd( rHIRQ ); //determine interrupt source | ||
//if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler | ||
// HIRQ_sendback |= bmFRAMEIRQ; | ||
//}//end FRAMEIRQ handling | ||
if( HIRQ & bmCONDETIRQ ) { | ||
busprobe(); | ||
HIRQ_sendback |= bmCONDETIRQ; | ||
} | ||
/* End HIRQ interrupts handling, clear serviced IRQs */ | ||
regWr( rHIRQ, HIRQ_sendback ); | ||
return( HIRQ_sendback ); | ||
} | ||
byte MAX3421E::GpxHandler() | ||
{ | ||
byte GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register | ||
// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload | ||
// vbusPwr( OFF ); //attempt powercycle | ||
// delay( 1000 ); | ||
// vbusPwr( ON ); | ||
// regWr( rGPINIRQ, bmGPINIRQ7 ); | ||
// } | ||
return( GPINIRQ ); | ||
} | ||
|
||
//void MAX3421E::usbSM( void ) //USB state machine | ||
//{ | ||
// | ||
// | ||
//} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ | ||
/* MAX3421E functions */ | ||
#ifndef _MAX3421E_H_ | ||
#define _MAX3421E_H_ | ||
|
||
|
||
//#include <Spi.h> | ||
//#include <WProgram.h> | ||
#include "WProgram.h" | ||
#include "Max3421e_constants.h" | ||
|
||
class MAX3421E /* : public SPI */ { | ||
// byte vbusState; | ||
public: | ||
MAX3421E( void ); | ||
byte getVbusState( void ); | ||
// void toggle( byte pin ); | ||
static void regWr( byte, byte ); | ||
char * bytesWr( byte, byte, char * ); | ||
static void gpioWr( byte ); | ||
byte regRd( byte ); | ||
char * bytesRd( byte, byte, char * ); | ||
byte gpioRd( void ); | ||
boolean reset(); | ||
boolean vbusPwr ( boolean ); | ||
void busprobe( void ); | ||
void powerOn(); | ||
byte IntHandler(); | ||
byte GpxHandler(); | ||
byte Task(); | ||
private: | ||
static void spi_init() { | ||
uint8_t tmp; | ||
// initialize SPI pins | ||
pinMode(SCK_PIN, OUTPUT); | ||
pinMode(MOSI_PIN, OUTPUT); | ||
pinMode(MISO_PIN, INPUT); | ||
pinMode(SS_PIN, OUTPUT); | ||
digitalWrite( SS_PIN, HIGH ); | ||
/* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */ | ||
SPCR = 0x50; | ||
SPSR = 0x01; | ||
/**/ | ||
tmp = SPSR; | ||
tmp = SPDR; | ||
} | ||
// void init(); | ||
friend class Max_LCD; | ||
}; | ||
|
||
|
||
|
||
|
||
#endif //_MAX3421E_H_ |
Oops, something went wrong.