From c83c43a83e3d8fbbeeb3b49a087979f5182555a4 Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Thu, 13 Jan 2011 12:09:36 -0700 Subject: [PATCH] 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_