Skip to content

Commit

Permalink
Added sources for USB Host shield from https://github.com/felis/USB_H…
Browse files Browse the repository at this point in the history
  • Loading branch information
salvestrini committed Apr 17, 2011
1 parent 08a2e1f commit c1da27d
Show file tree
Hide file tree
Showing 17 changed files with 4,309 additions and 0 deletions.
270 changes: 270 additions & 0 deletions libs/USBHost/Max3421e.cpp
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
//{
//
//
//}
54 changes: 54 additions & 0 deletions libs/USBHost/Max3421e.h
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_
Loading

0 comments on commit c1da27d

Please sign in to comment.