From b8d67c40e0fcfa2a21c2381d7dde591a73fa603a Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Thu, 13 Jan 2011 11:59:07 -0700 Subject: [PATCH 1/4] first commit --- README | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README diff --git a/README b/README new file mode 100644 index 00000000..e69de29b From c83c43a83e3d8fbbeeb3b49a087979f5182555a4 Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Thu, 13 Jan 2011 12:09:36 -0700 Subject: [PATCH 2/4] first real commit --- README | 5 + avrpins.h | 376 +++++++++++++++++++++++++++++++++++++++++++++++++++++ max3421e.h | 223 +++++++++++++++++++++++++++++++ newusb.pde | 59 +++++++++ usb_ch9.h | 169 ++++++++++++++++++++++++ usbhost.h | 169 ++++++++++++++++++++++++ 6 files changed, 1001 insertions(+) create mode 100644 avrpins.h create mode 100644 max3421e.h create mode 100644 newusb.pde create mode 100644 usb_ch9.h create mode 100644 usbhost.h diff --git a/README b/README index e69de29b..7328e500 100644 --- a/README +++ b/README @@ -0,0 +1,5 @@ +This is Rev.2.0 of MAX3421E-based USB Host Library for Arduino. At the moment, this repo contains current development copy +of the code facilitating developer's exchange. For those not involved in the project, the code in its' current state doesn't bear any value. +In other words, nothing works yet. + +The code uses slightly modified Konstantin Chizhov's AVR pin templates, see the original here -> https://github.com/KonstantinChizhov/AvrProjects \ No newline at end of file diff --git a/avrpins.h b/avrpins.h new file mode 100644 index 00000000..e273d42b --- /dev/null +++ b/avrpins.h @@ -0,0 +1,376 @@ +/* copied from Konstantin Chizhov's AVR port templates */ + +#ifndef _avrpins_h_ +#define _avrpins_h_ + +//#include "WProgram.h" +#include + +#ifdef PORTA +#define USE_PORTA +#endif +#ifdef PORTB +#define USE_PORTB +#endif +#ifdef PORTC +#define USE_PORTC +#endif +#ifdef PORTD +#define USE_PORTD +#endif +#ifdef PORTE +#define USE_PORTE +#endif +#ifdef PORTF +#define USE_PORTF +#endif +#ifdef PORTG +#define USE_PORTG +#endif +#ifdef PORTH +#define USE_PORTH +#endif +#ifdef PORTJ +#define USE_PORTJ +#endif +#ifdef PORTK +#define USE_PORTK +#endif +#ifdef PORTQ +#define USE_PORTQ +#endif +#ifdef PORTR +#define USE_PORTR +#endif + +#ifdef TCCR0A +#define USE_TCCR0A +#endif +#ifdef TCCR1A +#define USE_TCCR1A +#endif +#ifdef TCCR2A +#define USE_TCCR2A +#endif + +//Port definitions for AtTiny, AtMega families. + +#define MAKE_PORT(portName, ddrName, pinName, className, ID) \ + class className{\ + public:\ + typedef uint8_t DataT;\ + public:\ + static void Write(DataT value){portName = value;}\ + static void ClearAndSet(DataT clearMask, DataT value){portName = (portName & ~clearMask) | value;}\ + static DataT Read(){return portName;}\ + static void DirWrite(DataT value){ddrName = value;}\ + static DataT DirRead(){return ddrName;}\ + static void Set(DataT value){portName |= value;}\ + static void Clear(DataT value){portName &= ~value;}\ + static void Toggle(DataT value){portName ^= value;}\ + static void DirSet(DataT value){ddrName |= value;}\ + static void DirClear(DataT value){ddrName &= ~value;}\ + static void DirToggle(DataT value){ddrName ^= value;}\ + static DataT PinRead(){return pinName;}\ + enum{Id = ID};\ + enum{Width=sizeof(DataT)*8};\ + }; + +// TCCR registers to set/clear Arduino PWM +#define MAKE_TCCR(TccrName, className) \ + class className{\ + public:\ + typedef uint8_t DataT;\ + public:\ + static void Write(DataT value){TccrName = value;}\ + static void ClearAndSet(DataT clearMask, DataT value){TccrName = (TccrName & ~clearMask) | value;}\ + static DataT Read(){return TccrName;}\ + static void Set(DataT value){TccrName |= value;}\ + static void Clear(DataT value){TccrName &= ~value;}\ + static void Toggle(DataT value){TccrName ^= value;}\ + enum{Width=sizeof(DataT)*8};\ + }; + +#ifdef USE_PORTA +MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A') +#endif +#ifdef USE_PORTB +MAKE_PORT(PORTB, DDRB, PINB, Portb, 'B') +#endif +#ifdef USE_PORTC +MAKE_PORT(PORTC, DDRC, PINC, Portc, 'C') +#endif +#ifdef USE_PORTD +MAKE_PORT(PORTD, DDRD, PIND, Portd, 'D') +#endif +#ifdef USE_PORTE +MAKE_PORT(PORTE, DDRE, PINE, Porte, 'E') +#endif + +#ifdef USE_TCCR0A +MAKE_TCCR(TCCR0A, Tccr0a) +#endif +#ifdef USE_TCCR1A +MAKE_TCCR(TCCR1A, Tccr1a) +#endif +#ifdef USE_TCCR2A +MAKE_TCCR(TCCR2A, Tccr2a) +#endif + + // this class represents one pin in a IO port. + // It is fully static. + template + class TPin + { +// BOOST_STATIC_ASSERT(PIN < PORT::Width); + public: + typedef PORT Port; + enum{Number = PIN}; + + static void Set() { PORT::Set(1 << PIN); } + + static void Set(uint8_t val){ + if(val) + Set(); + else Clear();} + + static void SetDir(uint8_t val){ + if(val) + SetDirWrite(); + else SetDirRead();} + + static void Clear(){PORT::Clear(1 << PIN);} + + static void Toggle(){PORT::Toggle(1 << PIN);} + + static void SetDirRead(){PORT::DirClear(1 << PIN);} + + static void SetDirWrite(){PORT::DirSet(1 << PIN);} + + static uint8_t IsSet(){return PORT::PinRead() & (uint8_t)(1 << PIN);} + + static void WaiteForSet(){ while(IsSet()==0){} } + + static void WaiteForClear(){ while(IsSet()){} } + }; //class TPin... + + // this class represents one bit in TCCR port. + // used to set/clear TCCRx bits + // It is fully static. + template + class TCom + { +// BOOST_STATIC_ASSERT(PIN < PORT::Width); + public: + typedef TCCR Tccr; + enum{Com = COM}; + + static void Set() { TCCR::Set(1 << COM); } + + static void Clear() { TCCR::Clear(1 << COM); } + + static void Toggle() { TCCR::Toggle(1 << COM); } + }; //class TCom... + +//Short pin definitions +#ifdef USE_PORTA +typedef TPin Pa0; +typedef TPin Pa1; +typedef TPin Pa2; +typedef TPin Pa3; +typedef TPin Pa4; +typedef TPin Pa5; +typedef TPin Pa6; +typedef TPin Pa7; +#endif + +#ifdef USE_PORTB +typedef TPin Pb0; +typedef TPin Pb1; +typedef TPin Pb2; +typedef TPin Pb3; +typedef TPin Pb4; +typedef TPin Pb5; +typedef TPin Pb6; +typedef TPin Pb7; +#endif + +#ifdef USE_PORTC +typedef TPin Pc0; +typedef TPin Pc1; +typedef TPin Pc2; +typedef TPin Pc3; +typedef TPin Pc4; +typedef TPin Pc5; +typedef TPin Pc6; +typedef TPin Pc7; +#endif + +#ifdef USE_PORTD +typedef TPin Pd0; +typedef TPin Pd1; +typedef TPin Pd2; +typedef TPin Pd3; +typedef TPin Pd4; +typedef TPin Pd5; +typedef TPin Pd6; +typedef TPin Pd7; +#endif + +#ifdef USE_PORTE +typedef TPin Pe0; +typedef TPin Pe1; +typedef TPin Pe2; +typedef TPin Pe3; +typedef TPin Pe4; +typedef TPin Pe5; +typedef TPin Pe6; +typedef TPin Pe7; +#endif + +#ifdef USE_PORTF +typedef TPin Pf0; +typedef TPin Pf1; +typedef TPin Pf2; +typedef TPin Pf3; +typedef TPin Pf4; +typedef TPin Pf5; +typedef TPin Pf6; +typedef TPin Pf7; +#endif + +#ifdef USE_PORTG +typedef TPin Pg0; +typedef TPin Pg1; +typedef TPin Pg2; +typedef TPin Pg3; +typedef TPin Pg4; +typedef TPin Pg5; +typedef TPin Pg6; +typedef TPin Pg7; +#endif + +#ifdef USE_PORTH +typedef TPin Ph0; +typedef TPin Ph1; +typedef TPin Ph2; +typedef TPin Ph3; +typedef TPin Ph4; +typedef TPin Ph5; +typedef TPin Ph6; +typedef TPin Ph7; +#endif + +#ifdef USE_PORTJ +typedef TPin Pj0; +typedef TPin Pj1; +typedef TPin Pj2; +typedef TPin Pj3; +typedef TPin Pj4; +typedef TPin Pj5; +typedef TPin Pj6; +typedef TPin Pj7; +#endif + +#ifdef USE_PORTK +typedef TPin Pk0; +typedef TPin Pk1; +typedef TPin Pk2; +typedef TPin Pk3; +typedef TPin Pk4; +typedef TPin Pk5; +typedef TPin Pk6; +typedef TPin Pk7; +#endif + +#ifdef USE_PORTQ +typedef TPin Pq0; +typedef TPin Pq1; +typedef TPin Pq2; +typedef TPin Pq3; +typedef TPin Pq4; +typedef TPin Pq5; +typedef TPin Pq6; +typedef TPin Pq7; +#endif + +#ifdef USE_PORTR +typedef TPin Pr0; +typedef TPin Pr1; +typedef TPin Pr2; +typedef TPin Pr3; +typedef TPin Pr4; +typedef TPin Pr5; +typedef TPin Pr6; +typedef TPin Pr7; +#endif + +#ifdef USE_TCCR0A +typedef TCom Tc0a; //P6 +typedef TCom Tc0b; //P5 +#endif + +#ifdef USE_TCCR1A +typedef TCom Tc1a; //P9 +typedef TCom Tc1b; //P10 +#endif + +#ifdef USE_TCCR2A +typedef TCom Tc2a; //P11 +typedef TCom Tc2b; //P3 +#endif + +template + class Tp_Tc + { + public: + static void SetDir(uint8_t val){ + if(val) + SetDirWrite(); + else SetDirRead(); + } + static void SetDirRead(){ + Tp_pin::SetDirRead(); //set pin direction + Tc_bit::Clear(); //disconnect pin from PWM + } + static void SetDirWrite(){ + Tp_pin::SetDirWrite(); + Tc_bit::Clear(); + } + }; + +/* pin definitions for cases where it's necessary to clear compare output mode bits */ + +//typedef Tp_Tc P3; //Arduino pin 3 +//typedef Tp_Tc P5; //Arduino pin 5 +//typedef Tp_Tc P6; //Arduino pin 6 +//typedef Tp_Tc P9; //Arduino pin 9 +//typedef Tp_Tc P10; //Arduino pin 10 +//typedef Tp_Tc P11; //Arduino pin 11 + +//Arduino pin numbers + +#define P0 Pd0 +#define P1 Pd1 +#define P2 Pd2 +#define P3 Pd3 +#define P4 Pd4 +#define P5 Pd5 +#define P6 Pd6 +#define P7 Pd7 + +#define P8 Pb0 +#define P9 Pb1 +#define P10 Pb2 +#define P11 Pb3 +#define P12 Pb4 +#define P13 Pb5 + +#define P14 Pc0 +#define P15 Pc1 +#define P16 Pc2 +#define P17 Pc3 +#define P18 Pc4 +#define P19 Pc5 + +#endif //_avrpins_h_ diff --git a/max3421e.h b/max3421e.h new file mode 100644 index 00000000..0ef571a8 --- /dev/null +++ b/max3421e.h @@ -0,0 +1,223 @@ +/* MAX3421E register/bit names and bitmasks */ + +#ifndef _max3421e_h_ +#define _max3421e_h_ + +/* Arduino pin definitions */ + + +/* pin numbers to port numbers */ + +//#define MAX_SS 10 +//#define MAX_INT 9 +//#define MAX_GPX 8 +//#define MAX_RESET 7 +// +//#define BPNT_0 3 +//#define BPNT_1 2 +// +//#define Select_MAX3421E digitalWrite( MAX_SS,LOW ) +//#define Deselect_MAX3421E digitalWrite( MAX_SS,HIGH ) + +/* */ + +#define ON true +#define OFF false + +#define SE0 0 +#define SE1 1 +#define FSHOST 2 +#define LSHOST 3 + +/* MAX3421E command byte format: rrrrr0wa where 'r' is register number */ +// +// MAX3421E Registers in HOST mode. +// +#define rRCVFIFO 0x08 //1<<3 +#define rSNDFIFO 0x10 //2<<3 +#define rSUDFIFO 0x20 //4<<3 +#define rRCVBC 0x30 //6<<3 +#define rSNDBC 0x38 //7<<3 + +#define rUSBIRQ 0x68 //13<<3 +/* USBIRQ Bits */ +#define bmVBUSIRQ 0x40 //b6 +#define bmNOVBUSIRQ 0x20 //b5 +#define bmOSCOKIRQ 0x01 //b0 + +#define rUSBIEN 0x70 //14<<3 +/* USBIEN Bits */ +#define bmVBUSIE 0x40 //b6 +#define bmNOVBUSIE 0x20 //b5 +#define bmOSCOKIE 0x01 //b0 + +#define rUSBCTL 0x78 //15<<3 +/* USBCTL Bits */ +#define bmCHIPRES 0x20 //b5 +#define bmPWRDOWN 0x10 //b4 + +#define rCPUCTL 0x80 //16<<3 +/* CPUCTL Bits */ +#define bmPUSLEWID1 0x80 //b7 +#define bmPULSEWID0 0x40 //b6 +#define bmIE 0x01 //b0 + +#define rPINCTL 0x88 //17<<3 +/* PINCTL Bits */ +#define bmFDUPSPI 0x10 //b4 +#define bmINTLEVEL 0x08 //b3 +#define bmPOSINT 0x04 //b2 +#define bmGPXB 0x02 //b1 +#define bmGPXA 0x01 //b0 +// GPX pin selections +#define GPX_OPERATE 0x00 +#define GPX_VBDET 0x01 +#define GPX_BUSACT 0x02 +#define GPX_SOF 0x03 + +#define rREVISION 0x90 //18<<3 + +#define rIOPINS1 0xa0 //20<<3 + +/* IOPINS1 Bits */ +#define bmGPOUT0 0x01 +#define bmGPOUT1 0x02 +#define bmGPOUT2 0x04 +#define bmGPOUT3 0x08 +#define bmGPIN0 0x10 +#define bmGPIN1 0x20 +#define bmGPIN2 0x40 +#define bmGPIN3 0x80 + +#define rIOPINS2 0xa8 //21<<3 +/* IOPINS2 Bits */ +#define bmGPOUT4 0x01 +#define bmGPOUT5 0x02 +#define bmGPOUT6 0x04 +#define bmGPOUT7 0x08 +#define bmGPIN4 0x10 +#define bmGPIN5 0x20 +#define bmGPIN6 0x40 +#define bmGPIN7 0x80 + +#define rGPINIRQ 0xb0 //22<<3 +/* GPINIRQ Bits */ +#define bmGPINIRQ0 0x01 +#define bmGPINIRQ1 0x02 +#define bmGPINIRQ2 0x04 +#define bmGPINIRQ3 0x08 +#define bmGPINIRQ4 0x10 +#define bmGPINIRQ5 0x20 +#define bmGPINIRQ6 0x40 +#define bmGPINIRQ7 0x80 + +#define rGPINIEN 0xb8 //23<<3 +/* GPINIEN Bits */ +#define bmGPINIEN0 0x01 +#define bmGPINIEN1 0x02 +#define bmGPINIEN2 0x04 +#define bmGPINIEN3 0x08 +#define bmGPINIEN4 0x10 +#define bmGPINIEN5 0x20 +#define bmGPINIEN6 0x40 +#define bmGPINIEN7 0x80 + +#define rGPINPOL 0xc0 //24<<3 +/* GPINPOL Bits */ +#define bmGPINPOL0 0x01 +#define bmGPINPOL1 0x02 +#define bmGPINPOL2 0x04 +#define bmGPINPOL3 0x08 +#define bmGPINPOL4 0x10 +#define bmGPINPOL5 0x20 +#define bmGPINPOL6 0x40 +#define bmGPINPOL7 0x80 + +#define rHIRQ 0xc8 //25<<3 +/* HIRQ Bits */ +#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume +#define bmRWUIRQ 0x02 +#define bmRCVDAVIRQ 0x04 +#define bmSNDBAVIRQ 0x08 +#define bmSUSDNIRQ 0x10 +#define bmCONDETIRQ 0x20 +#define bmFRAMEIRQ 0x40 +#define bmHXFRDNIRQ 0x80 + +#define rHIEN 0xd0 //26<<3 +/* HIEN Bits */ +#define bmBUSEVENTIE 0x01 +#define bmRWUIE 0x02 +#define bmRCVDAVIE 0x04 +#define bmSNDBAVIE 0x08 +#define bmSUSDNIE 0x10 +#define bmCONDETIE 0x20 +#define bmFRAMEIE 0x40 +#define bmHXFRDNIE 0x80 + +#define rMODE 0xd8 //27<<3 +/* MODE Bits */ +#define bmHOST 0x01 +#define bmLOWSPEED 0x02 +#define bmHUBPRE 0x04 +#define bmSOFKAENAB 0x08 +#define bmSEPIRQ 0x10 +#define bmDELAYISO 0x20 +#define bmDMPULLDN 0x40 +#define bmDPPULLDN 0x80 + +#define rPERADDR 0xe0 //28<<3 + +#define rHCTL 0xe8 //29<<3 +/* HCTL Bits */ +#define bmBUSRST 0x01 +#define bmFRMRST 0x02 +#define bmSAMPLEBUS 0x04 +#define bmSIGRSM 0x08 +#define bmRCVTOG0 0x10 +#define bmRCVTOG1 0x20 +#define bmSNDTOG0 0x40 +#define bmSNDTOG1 0x80 + +#define rHXFR 0xf0 //30<<3 +/* Host transfer token values for writing the HXFR register (R30) */ +/* OR this bit field with the endpoint number in bits 3:0 */ +#define tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1 +#define tokIN 0x00 // HS=0, ISO=0, OUTNIN=0, SETUP=0 +#define tokOUT 0x20 // HS=0, ISO=0, OUTNIN=1, SETUP=0 +#define tokINHS 0x80 // HS=1, ISO=0, OUTNIN=0, SETUP=0 +#define tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0 +#define tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0 +#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0 + +#define rHRSL 0xf8 //31<<3 +/* HRSL Bits */ +#define bmRCVTOGRD 0x10 +#define bmSNDTOGRD 0x20 +#define bmKSTATUS 0x40 +#define bmJSTATUS 0x80 +#define bmSE0 0x00 //SE0 - disconnect state +#define bmSE1 0xc0 //SE1 - illegal state +/* Host error result codes, the 4 LSB's in the HRSL register */ +#define hrSUCCESS 0x00 +#define hrBUSY 0x01 +#define hrBADREQ 0x02 +#define hrUNDEF 0x03 +#define hrNAK 0x04 +#define hrSTALL 0x05 +#define hrTOGERR 0x06 +#define hrWRONGPID 0x07 +#define hrBADBC 0x08 +#define hrPIDERR 0x09 +#define hrPKTERR 0x0A +#define hrCRCERR 0x0B +#define hrKERR 0x0C +#define hrJERR 0x0D +#define hrTIMEOUT 0x0E +#define hrBABBLE 0x0F + +#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB) +#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB) + + +#endif //_max3421e_h_ diff --git a/newusb.pde b/newusb.pde new file mode 100644 index 00000000..0fd7d701 --- /dev/null +++ b/newusb.pde @@ -0,0 +1,59 @@ +/* new USB library tests */ + +//nclude +#include "usbhost.h" + +MAX3421e Max; +uint8_t buf[10] = {0}; + +void setup() { +// Max.regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL )); +// Max.regWr( rUSBCTL, bmCHIPRES ); //Chip reset. This stops the oscillator +// Max.regWr( rUSBCTL, 0x00 ); //Remove the reset +// delay( 100 ); + Serial.begin( 115200 ); + Serial.println("Start"); + + // pinModeFast2( 8, OUTPUT) + +} + +void loop() { +// uint16_t i; +// Max.regWr( rUSBCTL, bmCHIPRES ); +// Max.regWr( rUSBCTL, 0x00 ); +// for( i = 0; i < 65535; i++ ) { +// if( ( Max.regRd( rUSBIRQ ) & bmOSCOKIRQ )) { +// break; +// } +// } + Serial.println( Max.reset(), DEC ); + //Max.reset(); + //delay( 100 ); + //Max.regRd( rREVISION ); + //Serial.println( Max.regRd( rREVISION ), HEX ); + + //Serial.println("tick"); + // uint8_t tmp; + // for( uint16_t i = 0; i < 256; i++ ) { + // tmp = Max.SPIxfer( i ); + // if( tmp != i ) { + // Serial.println("error"); + // } + // if( SPSR & 0x40 ) { + // Serial.println("WCOL"); + // } + // } + // static bool oldintval = 0; + // if( Max.intval() != oldintval ) { + // oldintval = Max.intval(); + // Serial.println( oldintval, DEC ); + // } + // Max.sstoggle(); + + //digitalWriteFast2( 8, 0 ); + //digitalWriteFast2( 8, 1 ); +} + + + diff --git a/usb_ch9.h b/usb_ch9.h new file mode 100644 index 00000000..e2b413c1 --- /dev/null +++ b/usb_ch9.h @@ -0,0 +1,169 @@ +/* USB chapter 9 structures */ +#ifndef _ch9_h_ +#define _ch9_h_ + +#include + +/* Misc.USB constants */ +#define DEV_DESCR_LEN 18 //device descriptor length +#define CONF_DESCR_LEN 9 //configuration descriptor length +#define INTR_DESCR_LEN 9 //interface descriptor length +#define EP_DESCR_LEN 7 //endpoint descriptor length + +/* Standard Device Requests */ + +#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS +#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE +#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE +#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS +#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR +#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR +#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION +#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION +#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE +#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE +#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME + +#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up +#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode + +/* Setup Data Constants */ + +#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer +#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer +#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard +#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class +#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor +#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device +#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface +#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint +#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other + +/* USB descriptors */ + +#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. +#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor. +#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor. +#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor. +#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor. +#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier. +#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration. +#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. +#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. + +/* OTG SET FEATURE Constants */ +#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP +#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP +#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP + +/* USB Endpoint Transfer Types */ +#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint. +#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint. +#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint. +#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint. +#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes + + +/* Standard Feature Selectors for CLEAR_FEATURE Requests */ +#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient +#define USB_FEATURE_TEST_MODE 2 // Device recipient + +/* HID constants. Not part of chapter 9 */ +/* Class-Specific Requests */ +#define HID_REQUEST_GET_REPORT 0x01 +#define HID_REQUEST_GET_IDLE 0x02 +#define HID_REQUEST_GET_PROTOCOL 0x03 +#define HID_REQUEST_SET_REPORT 0x09 +#define HID_REQUEST_SET_IDLE 0x0A +#define HID_REQUEST_SET_PROTOCOL 0x0B + +/* Class Descriptor Types */ +#define HID_DESCRIPTOR_HID 0x21 +#define HID_DESCRIPTOR_REPORT 0x22 +#define HID_DESRIPTOR_PHY 0x23 + +/* Protocol Selection */ +#define BOOT_PROTOCOL 0x00 +#define RPT_PROTOCOL 0x01 +/* HID Interface Class Code */ +#define HID_INTF 0x03 +/* HID Interface Class SubClass Codes */ +#define BOOT_INTF_SUBCLASS 0x01 +/* HID Interface Class Protocol Codes */ +#define HID_PROTOCOL_NONE 0x00 +#define HID_PROTOCOL_KEYBOARD 0x01 +#define HID_PROTOCOL_MOUSE 0x02 + + +/* descriptor data structures */ + +/* Device descriptor structure */ +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + uint16_t bcdUSB; // USB Spec Release Number (BCD). + uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. + uint16_t idVendor; // Vendor ID (assigned by the USB-IF). + uint16_t idProduct; // Product ID (assigned by the manufacturer). + uint16_t bcdDevice; // Device release number (BCD). + uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. + uint8_t iProduct; // Index of String Descriptor describing the product. + uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. + uint8_t bNumConfigurations; // Number of possible configurations. +} USB_DEVICE_DESCRIPTOR; + +/* Configuration descriptor structure */ +typedef struct +{ + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). + uint16_t wTotalLength; // Total length of all descriptors for this configuration. + uint8_t bNumInterfaces; // Number of interfaces in this configuration. + uint8_t bConfigurationValue; // Value of this configuration (1 based). + uint8_t iConfiguration; // Index of String Descriptor describing the configuration. + uint8_t bmAttributes; // Configuration characteristics. + uint8_t bMaxPower; // Maximum power consumed by this configuration. +} USB_CONFIGURATION_DESCRIPTOR; + +/* Interface descriptor structure */ +typedef struct +{ + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). + uint8_t bInterfaceNumber; // Number of this interface (0 based). + uint8_t bAlternateSetting; // Value of this alternate interface setting. + uint8_t bNumEndpoints; // Number of endpoints in this interface. + uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t iInterface; // Index of String Descriptor describing the interface. +} USB_INTERFACE_DESCRIPTOR; + +/* Endpoint descriptor structure */ +typedef struct +{ + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). + uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). + uint8_t bmAttributes; // Endpoint transfer type. + uint16_t wMaxPacketSize; // Maximum packet size. + uint8_t bInterval; // Polling interval in frames. +} USB_ENDPOINT_DESCRIPTOR; + +/* HID descriptor */ +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + uint8_t bDescrType; + uint16_t wDescriptorLength; +} USB_HID_DESCRIPTOR; + +#endif // _ch9_h_ diff --git a/usbhost.h b/usbhost.h new file mode 100644 index 00000000..766d9bfd --- /dev/null +++ b/usbhost.h @@ -0,0 +1,169 @@ +/* MAX3421E-based USB Host Library header file */ +#ifndef _USBHOST_H_ +#define _USBHOST_H_ + +//#include +#include "avrpins.h" +#include "max3421e.h" +#include "usb_ch9.h" + + +/* SPI initialization */ +template< typename CLK, typename MOSI, typename MISO > class SPi +{ + public: + static void init() { + uint8_t tmp; + CLK::SetDirWrite(); + MOSI::SetDirWrite(); + MISO::SetDirRead(); + /* 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; + } +}; + +/* SPI pin definitions. see avrpins.h */ +#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) +typedef SPi< Pb1, Pb2, Pb3 > spi; +#endif +#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) +typedef SPi< Pb5, Pb3, Pb4 > spi; +#endif + +template< typename SS, typename INTR > class MAX3421e /* : public spi */ +{ + public: + MAX3421e(); + void regWr( uint8_t reg, uint8_t data ); + uint8_t* bytesWr( uint8_t reg, uint8_t nbytes, uint8_t* data_p ); + void gpioWr( uint8_t data ); + uint8_t regRd( uint8_t reg ); + uint8_t* bytesRd( uint8_t reg, uint8_t nbytes, uint8_t* data_p ); + uint8_t gpioRd(); + uint16_t reset(); + uint8_t init(); +}; +/* constructor */ +template< typename SS, typename INTR > +MAX3421e< SS, INTR >::MAX3421e() +{ + /* pin and peripheral setup */ + SS::SetDirWrite(); + SS::Set(); + spi::init(); + INTR::SetDirRead(); + /* MAX3421E - full-duplex SPI, level interrupt */ + regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL )); +}; +/* write single byte into MAX3421 register */ +template< typename SS, typename INTR > +void MAX3421e< SS, INTR >::regWr( uint8_t reg, uint8_t data ) +{ + SS::Clear(); + SPDR = ( reg | 0x02 ); + while(!( SPSR & ( 1 << SPIF ))); + SPDR = data; + while(!( SPSR & ( 1 << SPIF ))); + SS::Set(); + return; +}; +/* multiple-byte write */ +/* returns a pointer to memory position after last written */ +template< typename SS, typename INTR > +uint8_t* MAX3421e< SS, INTR >::bytesWr( uint8_t reg, uint8_t nbytes, uint8_t* data_p ) +{ + SS::Clear(); + SPDR = ( reg | 0x02 ); //set WR bit and send register number + while( nbytes-- ) { + while(!( SPSR & ( 1 << SPIF ))); //check if previous byte was sent + SPDR = ( *data_p ); // send next data byte + data_p++; // advance data pointer + } + while(!( SPSR & ( 1 << SPIF ))); + SS::Set(); + return( data_p ); +} +/* 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 */ +template< typename SS, typename INTR > +void MAX3421e< SS, INTR >::gpioWr( uint8_t data ) +{ + regWr( rIOPINS1, data ); + data >>= 4; + regWr( rIOPINS2, data ); + return; +} +/* single host register read */ +template< typename SS, typename INTR > +uint8_t MAX3421e< SS, INTR >::regRd( uint8_t reg ) +{ + SS::Clear(); + SPDR = reg; + while(!( SPSR & ( 1 << SPIF ))); + SPDR = 0; //send empty byte + while(!( SPSR & ( 1 << SPIF ))); + SS::Set(); + return( SPDR ); +} +/* multiple-byte register read */ +/* returns a pointer to a memory position after last read */ +template< typename SS, typename INTR > +uint8_t* MAX3421e< SS, INTR >::bytesRd( uint8_t reg, uint8_t nbytes, uint8_t* data_p ) +{ + SS::Clear(); + SPDR = reg; + while(!( SPSR & ( 1 << SPIF ))); //wait + while( nbytes ) { + SPDR = 0; //send empty byte + nbytes--; + while(!( SPSR & ( 1 << SPIF ))); + *data_p = SPDR; + data_p++; + } + SS::Set(); + return( data_p ); +} +/* GPIO read. See gpioWr for explanation */ +/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */ +template< typename SS, typename INTR > +uint8_t MAX3421e< SS, INTR >::gpioRd() +{ + uint8_t gpin = 0; + gpin = regRd( rIOPINS2 ); //pins 4-7 + gpin &= 0xf0; //clean lower nibble + gpin |= ( regRd( rIOPINS1 ) >>4 ) ; //shift low bits and OR with upper from previous operation. + return( gpin ); +} +/* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset + or zero if PLL haven't stabilized in 65535 cycles */ +template< typename SS, typename INTR > +uint16_t MAX3421e< SS, INTR >::reset() +{ + uint16_t i = 0; + regWr( rUSBCTL, bmCHIPRES ); + regWr( rUSBCTL, 0x00 ); + while( ++i ) { + if(( regRd( rUSBIRQ ) & bmOSCOKIRQ )) { + break; + } + } + return( i ); +} +/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ +template< typename SS, typename INTR > +uint8_t MAX3421e< SS, INTR >::init() +{ + if( reset() == 0 ) { //OSCOKIRQ hasn't asserted in time + return ( -1 ); + } + regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST ); // set pull-downs, Host + + return( 0 ); +} + +#endif //_USBHOST_H_ From 9b8154f821feb8462e50285d8c3d449bd87e8480 Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Tue, 18 Jan 2011 01:49:57 -0700 Subject: [PATCH 3/4] reference code confirming Chip Reset function --- README | 4 ++-- newusb.pde | 54 +++++++++--------------------------------------------- usbhost.h | 13 +++++++------ 3 files changed, 18 insertions(+), 53 deletions(-) diff --git a/README b/README index 7328e500..5aef8626 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ This is Rev.2.0 of MAX3421E-based USB Host Library for Arduino. At the moment, this repo contains current development copy of the code facilitating developer's exchange. For those not involved in the project, the code in its' current state doesn't bear any value. -In other words, nothing works yet. +In other words, nothing works yet. The project-related activity is blogged at http://www.circuitsathome.com -The code uses slightly modified Konstantin Chizhov's AVR pin templates, see the original here -> https://github.com/KonstantinChizhov/AvrProjects \ No newline at end of file +The code uses slightly modified Konstantin Chizhov's AVR pin templates, see the original here -> https://github.com/KonstantinChizhov/AvrProjects diff --git a/newusb.pde b/newusb.pde index 0fd7d701..06ce5195 100644 --- a/newusb.pde +++ b/newusb.pde @@ -1,58 +1,22 @@ -/* new USB library tests */ +/* reference USB library test sketch */ -//nclude #include "usbhost.h" MAX3421e Max; -uint8_t buf[10] = {0}; void setup() { -// Max.regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL )); -// Max.regWr( rUSBCTL, bmCHIPRES ); //Chip reset. This stops the oscillator -// Max.regWr( rUSBCTL, 0x00 ); //Remove the reset -// delay( 100 ); Serial.begin( 115200 ); - Serial.println("Start"); - - // pinModeFast2( 8, OUTPUT) - + Serial.println("\r\nStart"); + if ( Max.reset() == -1 ) { + Serial.println("OSCOKIRQ failed to assert"); + while(1); + } } void loop() { -// uint16_t i; -// Max.regWr( rUSBCTL, bmCHIPRES ); -// Max.regWr( rUSBCTL, 0x00 ); -// for( i = 0; i < 65535; i++ ) { -// if( ( Max.regRd( rUSBIRQ ) & bmOSCOKIRQ )) { -// break; -// } -// } - Serial.println( Max.reset(), DEC ); - //Max.reset(); - //delay( 100 ); - //Max.regRd( rREVISION ); - //Serial.println( Max.regRd( rREVISION ), HEX ); - - //Serial.println("tick"); - // uint8_t tmp; - // for( uint16_t i = 0; i < 256; i++ ) { - // tmp = Max.SPIxfer( i ); - // if( tmp != i ) { - // Serial.println("error"); - // } - // if( SPSR & 0x40 ) { - // Serial.println("WCOL"); - // } - // } - // static bool oldintval = 0; - // if( Max.intval() != oldintval ) { - // oldintval = Max.intval(); - // Serial.println( oldintval, DEC ); - // } - // Max.sstoggle(); - - //digitalWriteFast2( 8, 0 ); - //digitalWriteFast2( 8, 1 ); + Serial.print("Revision Register: "); + Serial.println( Max.regRd( rREVISION ), HEX ); + delay( 1000 ); } diff --git a/usbhost.h b/usbhost.h index 766d9bfd..b66c4aa9 100644 --- a/usbhost.h +++ b/usbhost.h @@ -9,7 +9,7 @@ /* SPI initialization */ -template< typename CLK, typename MOSI, typename MISO > class SPi +template< typename CLK, typename MOSI, typename MISO, typename SPI_SS > class SPi { public: static void init() { @@ -17,6 +17,7 @@ template< typename CLK, typename MOSI, typename MISO > class SPi CLK::SetDirWrite(); MOSI::SetDirWrite(); MISO::SetDirRead(); + SPI_SS::SetDirWrite(); /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */ SPCR = 0x50; SPSR = 0x01; @@ -28,10 +29,10 @@ template< typename CLK, typename MOSI, typename MISO > class SPi /* SPI pin definitions. see avrpins.h */ #if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) -typedef SPi< Pb1, Pb2, Pb3 > spi; +typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi; #endif #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) -typedef SPi< Pb5, Pb3, Pb4 > spi; +typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi; #endif template< typename SS, typename INTR > class MAX3421e /* : public spi */ @@ -45,7 +46,7 @@ template< typename SS, typename INTR > class MAX3421e /* : public spi */ uint8_t* bytesRd( uint8_t reg, uint8_t nbytes, uint8_t* data_p ); uint8_t gpioRd(); uint16_t reset(); - uint8_t init(); + int8_t init(); }; /* constructor */ template< typename SS, typename INTR > @@ -156,7 +157,7 @@ uint16_t MAX3421e< SS, INTR >::reset() } /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ template< typename SS, typename INTR > -uint8_t MAX3421e< SS, INTR >::init() +int8_t MAX3421e< SS, INTR >::init() { if( reset() == 0 ) { //OSCOKIRQ hasn't asserted in time return ( -1 ); @@ -166,4 +167,4 @@ uint8_t MAX3421e< SS, INTR >::init() return( 0 ); } -#endif //_USBHOST_H_ +#endif //_USBHOST_H_ From 5ddbce77d219fa4e672c3e4210c291271422a4cf Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Tue, 18 Jan 2011 19:31:24 -0700 Subject: [PATCH 4/4] Reset bug fix for rev.1.xx shields --- newusb.pde | 3 ++- usbhost.h | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/newusb.pde b/newusb.pde index 06ce5195..6091af19 100644 --- a/newusb.pde +++ b/newusb.pde @@ -7,7 +7,8 @@ MAX3421e Max; void setup() { Serial.begin( 115200 ); Serial.println("\r\nStart"); - if ( Max.reset() == -1 ) { + + if ( Max.init() == -1 ) { Serial.println("OSCOKIRQ failed to assert"); while(1); } diff --git a/usbhost.h b/usbhost.h index b66c4aa9..4ad25de6 100644 --- a/usbhost.h +++ b/usbhost.h @@ -55,6 +55,11 @@ MAX3421e< SS, INTR >::MAX3421e() /* pin and peripheral setup */ SS::SetDirWrite(); SS::Set(); + /**/ + /* For shield rev.1.xx uncomment following two lines */ + P7::SetDirWrite(); + P7::Set(); + /**/ spi::init(); INTR::SetDirRead(); /* MAX3421E - full-duplex SPI, level interrupt */ @@ -167,4 +172,4 @@ int8_t MAX3421e< SS, INTR >::init() return( 0 ); } -#endif //_USBHOST_H_ +#endif //_USBHOST_H_