From 8130e5618e1c08bba21d8e4d4e50684e3610092b Mon Sep 17 00:00:00 2001 From: Oleg Mazurov Date: Sun, 26 Jun 2011 21:27:44 -0600 Subject: [PATCH] Teensy support added to avrpins.h, usbhost.h --- avrpins.h | 124 ++++++++++++++- examples/board_qc/board_qc.pde | 266 +++++++++++++++++++++++++++++++++ usbhost.h | 5 +- 3 files changed, 391 insertions(+), 4 deletions(-) create mode 100644 examples/board_qc/board_qc.pde diff --git a/avrpins.h b/avrpins.h index f2909024..fcf12a28 100644 --- a/avrpins.h +++ b/avrpins.h @@ -449,10 +449,10 @@ template #define P52 Pb1 #define P53 Pb0 -#endif //"Mega" pin definitions +#endif //"Mega" pin numbers #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) -//"Classical" Arduino pin numbers +//"Classic" Arduino pin numbers #define P0 Pd0 #define P1 Pd1 @@ -477,6 +477,124 @@ template #define P18 Pc4 #define P19 Pc5 -#endif +#endif // "Classic" Arduino pin numbers + +#if defined(__AVR_ATmega32U4__) +// Teensy 2.0 pin numbers +// http://www.pjrc.com/teensy/pinout.html +#define P0 Pb0 +#define P1 Pb1 +#define P2 Pb2 +#define P3 Pb3 +#define P4 Pb7 +#define P5 Pd0 +#define P6 Pd1 +#define P7 Pd2 +#define P8 Pd3 +#define P9 Pc6 +#define P10 Pc7 +#define P11 Pd6 +#define P12 Pd7 +#define P13 Pb4 +#define P14 Pb5 +#define P15 Pb6 +#define P16 Pf7 +#define P17 Pf6 +#define P18 Pf5 +#define P19 Pf4 +#define P20 Pf1 +#define P21 Pf0 +#define P22 Pd4 +#define P23 Pd5 +#define P24 Pe6 +#endif // Teensy 2.0 + +#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) +// Teensy++ 2.0 pin numbers +// http://www.pjrc.com/teensy/pinout.html +#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 Pe0 +#define P9 Pe1 +#define P10 Pc0 +#define P11 Pc1 +#define P12 Pc2 +#define P13 Pc3 +#define P14 Pc4 +#define P15 Pc5 +#define P16 Pc6 +#define P17 Pc7 +#define P18 Pe6 +#define P19 Pe7 +#define P20 Pb0 +#define P21 Pb1 +#define P22 Pb2 +#define P23 Pb3 +#define P24 Pb4 +#define P25 Pb5 +#define P26 Pb6 +#define P27 Pb7 +#define P28 Pa0 +#define P29 Pa1 +#define P30 Pa2 +#define P31 Pa3 +#define P32 Pa4 +#define P33 Pa5 +#define P34 Pa6 +#define P35 Pa7 +#define P36 Pe4 +#define P37 Pe5 +#define P38 Pf0 +#define P39 Pf1 +#define P40 Pf2 +#define P41 Pf3 +#define P42 Pf4 +#define P43 Pf5 +#define P44 Pf6 +#define P45 Pf7 +#endif // Teensy++ 2.0 + +#if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) +// Sanguino pin numbers +// http://sanguino.cc/hardware +#define P0 Pb0 +#define P1 Pb1 +#define P2 Pb2 +#define P3 Pb3 +#define P4 Pb4 +#define P5 Pb5 +#define P6 Pb6 +#define P7 Pb7 +#define P8 Pd0 +#define P9 Pd1 +#define P10 Pd2 +#define P11 Pd3 +#define P12 Pd4 +#define P13 Pd5 +#define P14 Pd6 +#define P15 Pd7 +#define P16 Pc0 +#define P17 Pc1 +#define P18 Pc2 +#define P19 Pc3 +#define P20 Pc4 +#define P21 Pc5 +#define P22 Pc6 +#define P23 Pc7 +#define P24 Pa0 +#define P25 Pa1 +#define P26 Pa2 +#define P27 Pa3 +#define P28 Pa4 +#define P29 Pa5 +#define P30 Pa6 +#define P31 Pa7 +#endif // Sanguino #endif //_avrpins_h_ diff --git a/examples/board_qc/board_qc.pde b/examples/board_qc/board_qc.pde new file mode 100644 index 00000000..41863e5d --- /dev/null +++ b/examples/board_qc/board_qc.pde @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* variables */ +uint8_t rcode; +uint8_t usbstate; +//uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; +USB_DEVICE_DESCRIPTOR buf; + +/* objects */ +USB Usb; +//USBHub hub(&Usb); + + +void setup() +{ + Serial.begin( 115200 ); + Notify(PSTR("\r\nCircuits At Home 2011")); + Notify(PSTR("\r\nUSB Host Shield Quality Control Routine")); + /* check init */ +// if (Usb.Init() == -1) { +// Notify(PSTR("\r\nOSCOKIRQ failed to assert")); +// halt55(); +// } + /* SPI quick test - check revision register */ + Notify(PSTR("\r\nReading REVISION register... Die revision ")); + { + uint8_t tmpbyte = Usb.regRd( rREVISION ); + switch( tmpbyte ) { + case( 0x01): //rev.01 + Notify(PSTR("01")); + break; + case( 0x12): //rev.02 + Notify(PSTR("02")); + break; + case( 0x13): //rev.03 + Notify(PSTR("03")); + break; + default: + Notify(PSTR("invalid. Value returned: ")); + print_hex( tmpbyte, 8 ); + halt55(); + break; + }//switch( tmpbyte... + }//check revision register + /* SPI long test */ + { + Notify(PSTR("\r\nSPI long test. Transfers 1MB of data. Each dot is 64K")); + uint8_t sample_wr = 0; + uint8_t sample_rd = 0; + uint8_t gpinpol_copy = Usb.regRd( rGPINPOL ); + for( uint8_t i = 0; i < 16; i++ ) { + for( uint16_t j = 0; j < 65535; j++ ) { + Usb.regWr( rGPINPOL, sample_wr ); + sample_rd = Usb.regRd( rGPINPOL ); + if( sample_rd != sample_wr ) { + Notify(PSTR("\r\nTest failed. ")); + Notify(PSTR("Value written: ")); + print_hex( sample_wr, 8 ); + Notify(PSTR(" read: ")); + print_hex( sample_rd, 8 ); + halt55(); + }//if( sample_rd != sample_wr.. + sample_wr++; + }//for( uint16_t j... + Notify(PSTR(".")); + }//for( uint8_t i... + Usb.regWr( rGPINPOL, gpinpol_copy ); + Notify(PSTR(" SPI long test passed")); + }//SPI long test + /* GPIO test */ + /* in order to simplify board layout, GPIN pins on text fixture are connected to GPOUT */ + /* in reverse order, i.e, GPIN0 is connected to GPOUT7, GPIN1 to GPOUT6, etc. */ + { + uint8_t tmpbyte; + Notify(PSTR("\r\nGPIO test. Connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, and so on")); + for( uint8_t sample_gpio = 0; sample_gpio < 255; sample_gpio++ ) { + Usb.gpioWr( sample_gpio ); + tmpbyte = Usb.gpioRd(); + /* bit reversing code copied vetbatim from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */ + tmpbyte = ((tmpbyte * 0x0802LU & 0x22110LU) | (tmpbyte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; + if( sample_gpio != tmpbyte ) { + Notify(PSTR("\r\nTest failed. Value written: ")); + print_hex( sample_gpio, 8 ); + Notify(PSTR(" Value read: ")); + print_hex( tmpbyte , 8 ); + Notify(PSTR(" ")); + press_any_key(); + break; + }//if( sample_gpio != tmpbyte... + }//for( uint8_t sample_gpio... + Notify(PSTR("\r\nGPIO test passed.")); + }//GPIO test + /* PLL test. Stops/starts MAX3421E oscillator several times */ + { + Notify(PSTR("\r\nPLL test. 100 chip resets will be performed")); + /* check current state of the oscillator */ + if(!( Usb.regRd( rUSBIRQ ) & bmOSCOKIRQ )) { //wrong state - should be on + Notify(PSTR("\r\nCurrent oscillator state unexpected.")); + press_any_key(); + } + /* Restart oscillator */ + Notify(PSTR("\r\nResetting oscillator")); + for( uint16_t i = 0; i < 101; i++ ) { + Notify(PSTR("\rReset number ")); + Serial.print( i, DEC ); + Usb.regWr( rUSBCTL, bmCHIPRES ); //reset + if( Usb.regRd( rUSBIRQ ) & bmOSCOKIRQ ) { //wrong state - should be off + Notify(PSTR("\r\nCurrent oscillator state unexpected.")); + halt55(); + } + Usb.regWr( rUSBCTL, 0x00 ); //release from reset + uint16_t j = 0; + for( j = 0; j < 65535; j++ ) { //tracking off to on time + if( Usb.regRd( rUSBIRQ ) & bmOSCOKIRQ ) { + Notify(PSTR(" Time to stabilize - ")); + Serial.print( j, DEC ); + Notify(PSTR(" cycles")); + break; + } + }//for( uint16_t j = 0; j < 65535; j++ + if( j == 0 ) { + Notify(PSTR("PLL failed to stabilize")); + press_any_key(); + } + }//for( uint8_t i = 0; i < 255; i++ + + }//PLL test + /* initializing USB stack */ + if (Usb.Init() == -1) { + Notify(PSTR("\r\nOSCOKIRQ failed to assert")); + halt55(); + } + Notify(PSTR("\r\nChecking USB device communication.\r\n")); +} + +void loop() +{ + delay( 200 ); + Usb.Task(); + usbstate = Usb.getUsbTaskState(); + //usbstate = Usb.getVbusState(); + //Notify(PSTR("\r\nUSB Task State: ")); + //print_hex( usbstate, 8 ); + /**/ + + switch( usbstate ) { + case( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE ): + Notify(PSTR("\rWaiting for device ...")); + break; + case( USB_ATTACHED_SUBSTATE_RESET_DEVICE ): + Notify(PSTR("\r\nDevice connected. Resetting")); + break; + case( USB_ATTACHED_SUBSTATE_WAIT_SOF ): + Notify(PSTR("\rReset complete. Waiting for the first SOF...")); + break; + case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE ): + Notify(PSTR("\r\nSOF generation started. Enumerating device.")); + break; + case( USB_STATE_ADDRESSING ): + Notify(PSTR("\r\nSetting device address")); + break; + case( USB_STATE_RUNNING ): + Notify(PSTR("\r\nGetting device descriptor")); + rcode = Usb.getDevDescr( 1, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)&buf ); + + if( rcode ) { + Notify(PSTR("\rError reading device descriptor. Error code ")); + print_hex( rcode, 8 ); + } + else { + /**/ + Notify(PSTR("\r\nDescriptor Length:\t")); + print_hex( buf.bLength, 8 ); + Notify(PSTR("\r\nDescriptor type:\t")); + print_hex( buf.bDescriptorType, 8 ); + Notify(PSTR("\r\nUSB version:\t\t")); + print_hex( buf.bcdUSB, 16 ); + Notify(PSTR("\r\nDevice class:\t\t")); + print_hex( buf.bDeviceClass, 8 ); + Notify(PSTR("\r\nDevice Subclass:\t")); + print_hex( buf.bDeviceSubClass, 8 ); + Notify(PSTR("\r\nDevice Protocol:\t")); + print_hex( buf.bDeviceProtocol, 8 ); + Notify(PSTR("\r\nMax.packet size:\t")); + print_hex( buf.bMaxPacketSize0, 8 ); + Notify(PSTR("\r\nVendor ID:\t\t")); + print_hex( buf.idVendor, 16 ); + Notify(PSTR("\r\nProduct ID:\t\t")); + print_hex( buf.idProduct, 16 ); + Notify(PSTR("\r\nRevision ID:\t\t")); + print_hex( buf.bcdDevice, 16 ); + Notify(PSTR("\r\nMfg.string index:\t")); + print_hex( buf.iManufacturer, 8 ); + Notify(PSTR("\r\nProd.string index:\t")); + print_hex( buf.iProduct, 8 ); + Notify(PSTR("\r\nSerial number index:\t")); + print_hex( buf.iSerialNumber, 8 ); + Notify(PSTR("\r\nNumber of conf.:\t")); + print_hex( buf.bNumConfigurations, 8 ); + /**/ + Notify(PSTR("\r\n\nAll tests passed. Press RESET to restart test")); + while(1); + } + break; + case( USB_STATE_ERROR ): + Notify(PSTR("\rUSB state machine reached error state")); + break; + + default: + //Notify(PSTR("\rUndefined State")); + break; + }//switch( usbstate... + +}//loop()... + +/* constantly transmits 0x55 via SPI to aid probing */ +void halt55() +{ + + Notify(PSTR("\r\nUnrecoverable error - test halted!!!")); + Notify(PSTR("\r\n0x55 pattern is transmitted via SPI")); + Notify(PSTR("\r\nPress RESET to restart test")); + + while( 1 ) { + Usb.regWr( 0x55, 0x55 ); + } +} +/* prints hex numbers with leading zeroes */ +void print_hex(int v, int num_places) +{ + int mask=0, n, num_nibbles, digit; + + for (n=1; n<=num_places; n++) { + mask = (mask << 1) | 0x0001; + } + v = v & mask; // truncate v to specified number of places + + num_nibbles = num_places / 4; + if ((num_places % 4) != 0) { + ++num_nibbles; + } + do { + digit = ((v >> (num_nibbles-1) * 4)) & 0x0f; + Serial.print(digit, HEX); + } while(--num_nibbles); +} +/* prints "Press any key" and returns when key is pressed */ +void press_any_key() +{ + Notify(PSTR("\r\nPress any key to continue...")); + while( Serial.available() == 0 ); //wait for input + Serial.read(); //empty input buffer + return; +} diff --git a/usbhost.h b/usbhost.h index e8210759..36aa6674 100644 --- a/usbhost.h +++ b/usbhost.h @@ -44,12 +44,15 @@ template< typename CLK, typename MOSI, typename MISO, typename SPI_SS > class SP }; /* SPI pin definitions. see avrpins.h */ -#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) +#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi; #endif #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi; #endif +#if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) +typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi; +#endif template< typename SS, typename INTR > class MAX3421e /* : public spi */ {