USB Host Shield 2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
usbhost.h
Go to the documentation of this file.
1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2 
3 This software may be distributed and modified under the terms of the GNU
4 General Public License version 2 (GPL2) as published by the Free Software
5 Foundation and appearing in the file GPL2.TXT included in the packaging of
6 this file. Please note that GPL2 Section 2[b] requires that all works based
7 on this software must also be made publicly available under the terms of
8 the GPL2 ("Copyleft").
9 
10 Contact information
11 -------------------
12 
13 Circuits At Home, LTD
14 Web : http://www.circuitsathome.com
15 e-mail : support@circuitsathome.com
16 */
17 /* MAX3421E-based USB Host Library header file */
18 #ifndef _USBHOST_H_
19 #define _USBHOST_H_
20 
21 #include "avrpins.h"
22 #include "max3421e.h"
23 #include "usb_ch9.h"
24 
25 
26 /* SPI initialization */
27 template< typename CLK, typename MOSI, typename MISO, typename SPI_SS > class SPi
28 {
29  public:
30  static void init() {
31  uint8_t tmp;
32  CLK::SetDirWrite();
33  MOSI::SetDirWrite();
34  MISO::SetDirRead();
35  SPI_SS::SetDirWrite();
36  /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */
37  SPCR = 0x50;
38  SPSR = 0x01;
39 
40  tmp = SPSR;
41  tmp = SPDR;
42  }
43 };
44 
45 /* SPI pin definitions. see avrpins.h */
46 #if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
47 typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi;
48 #endif
49 #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
50 typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;
51 #endif
52 #if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__)
53 typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi;
54 #endif
55 
56 template< typename SS, typename INTR > class MAX3421e /* : public spi */
57 {
58  static uint8_t vbusState;
59 
60  public:
61  MAX3421e();
62  void regWr( uint8_t reg, uint8_t data );
63  uint8_t* bytesWr( uint8_t reg, uint8_t nbytes, uint8_t* data_p );
64  void gpioWr( uint8_t data );
65  uint8_t regRd( uint8_t reg );
66  uint8_t* bytesRd( uint8_t reg, uint8_t nbytes, uint8_t* data_p );
67  uint8_t gpioRd();
68  uint16_t reset();
69  int8_t Init();
70  uint8_t getVbusState( void ) { return vbusState; };
71  void busprobe();
72  uint8_t GpxHandler();
73  uint8_t IntHandler();
74  uint8_t Task();
75 };
76 
77 template< typename SS, typename INTR >
79 
80 /* constructor */
81 template< typename SS, typename INTR >
83 {
84  /* pin and peripheral setup */
85  SS::SetDirWrite();
86  SS::Set();
87  spi::init();
88  INTR::SetDirRead();
89 #ifdef BOARD_MEGA_ADK
90  /* For Mega ADK, which has Max3421e on-board, set MAX_RESET to Output mode, and pull Reset to HIGH */
91  DDRJ |= _BV(PJ2);
92  PORTJ &= ~_BV(PJ2);
93  PORTJ |= _BV(PJ2);
94 #endif
95 
96  /* MAX3421E - full-duplex SPI, level interrupt */
97  regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL ));
98 };
99 /* write single byte into MAX3421 register */
100 template< typename SS, typename INTR >
101 void MAX3421e< SS, INTR >::regWr( uint8_t reg, uint8_t data )
102 {
103  SS::Clear();
104  SPDR = ( reg | 0x02 );
105  while(!( SPSR & ( 1 << SPIF )));
106  SPDR = data;
107  while(!( SPSR & ( 1 << SPIF )));
108  SS::Set();
109  return;
110 };
111 /* multiple-byte write */
112 /* returns a pointer to memory position after last written */
113 template< typename SS, typename INTR >
114 uint8_t* MAX3421e< SS, INTR >::bytesWr( uint8_t reg, uint8_t nbytes, uint8_t* data_p )
115 {
116  SS::Clear();
117  SPDR = ( reg | 0x02 ); //set WR bit and send register number
118  while( nbytes-- ) {
119  while(!( SPSR & ( 1 << SPIF ))); //check if previous byte was sent
120  SPDR = ( *data_p ); // send next data byte
121  data_p++; // advance data pointer
122  }
123  while(!( SPSR & ( 1 << SPIF )));
124  SS::Set();
125  return( data_p );
126 }
127 /* GPIO write */
128 /*GPIO byte is split between 2 registers, so two writes are needed to write one byte */
129 /* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */
130 template< typename SS, typename INTR >
131 void MAX3421e< SS, INTR >::gpioWr( uint8_t data )
132 {
133  regWr( rIOPINS1, data );
134  data >>= 4;
135  regWr( rIOPINS2, data );
136  return;
137 }
138 /* single host register read */
139 template< typename SS, typename INTR >
140 uint8_t MAX3421e< SS, INTR >::regRd( uint8_t reg )
141 {
142  SS::Clear();
143  SPDR = reg;
144  while(!( SPSR & ( 1 << SPIF )));
145  SPDR = 0; //send empty byte
146  while(!( SPSR & ( 1 << SPIF )));
147  SS::Set();
148  return( SPDR );
149 }
150 /* multiple-byte register read */
151 /* returns a pointer to a memory position after last read */
152 template< typename SS, typename INTR >
153 uint8_t* MAX3421e< SS, INTR >::bytesRd( uint8_t reg, uint8_t nbytes, uint8_t* data_p )
154 {
155  SS::Clear();
156  SPDR = reg;
157  while(!( SPSR & ( 1 << SPIF ))); //wait
158  while( nbytes ) {
159  SPDR = 0; //send empty byte
160  nbytes--;
161  while(!( SPSR & ( 1 << SPIF )));
162  *data_p = SPDR;
163  data_p++;
164  }
165  SS::Set();
166  return( data_p );
167 }
168 /* GPIO read. See gpioWr for explanation */
169 /* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */
170 template< typename SS, typename INTR >
172 {
173  uint8_t gpin = 0;
174  gpin = regRd( rIOPINS2 ); //pins 4-7
175  gpin &= 0xf0; //clean lower nibble
176  gpin |= ( regRd( rIOPINS1 ) >>4 ) ; //shift low bits and OR with upper from previous operation.
177  return( gpin );
178 }
179 /* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset
180  or zero if PLL haven't stabilized in 65535 cycles */
181 template< typename SS, typename INTR >
183 {
184  uint16_t i = 0;
185  regWr( rUSBCTL, bmCHIPRES );
186  regWr( rUSBCTL, 0x00 );
187  while( ++i ) {
188  if(( regRd( rUSBIRQ ) & bmOSCOKIRQ )) {
189  break;
190  }
191  }
192  return( i );
193 }
195 //template< typename SS, typename INTR >
196 //int8_t MAX3421e< SS, INTR >::Init()
197 //{
198 // if( reset() == 0 ) { //OSCOKIRQ hasn't asserted in time
199 // return ( -1 );
200 // }
201 // regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST ); // set pull-downs, Host
202 //
203 // return( 0 );
204 //}
205 /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
206 template< typename SS, typename INTR >
208 {
209  if( reset() == 0 )
210  { //OSCOKIRQ hasn't asserted in time
211  return ( -1 );
212  }
213  regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST ); // set pull-downs, Host
214 
215  regWr( rHIEN, bmCONDETIE|bmFRAMEIE ); //connection detection
216 
217  /* check if device is connected */
218  regWr( rHCTL,bmSAMPLEBUS ); // sample USB bus
219  while(!(regRd( rHCTL ) & bmSAMPLEBUS )); //wait for sample operation to finish
220 
221  busprobe(); //check if anything is connected
222 
223  regWr( rHIRQ, bmCONDETIRQ ); //clear connection detect interrupt
224  regWr( rCPUCTL, 0x01 ); //enable interrupt pin
225  return( 0 );
226 }
227 
228 /* probe bus to determine device presense and speed and switch host to this speed */
229 template< typename SS, typename INTR >
231 {
232  uint8_t bus_sample;
233  bus_sample = regRd( rHRSL ); //Get J,K status
234  bus_sample &= ( bmJSTATUS|bmKSTATUS ); //zero the rest of the byte
235  switch( bus_sample ) { //start full-speed or low-speed host
236  case( bmJSTATUS ):
237  if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {
238  regWr( rMODE, MODE_FS_HOST ); //start full-speed host
239  vbusState = FSHOST;
240  }
241  else {
242  regWr( rMODE, MODE_LS_HOST); //start low-speed host
243  vbusState = LSHOST;
244  }
245  break;
246  case( bmKSTATUS ):
247  if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {
248  regWr( rMODE, MODE_LS_HOST ); //start low-speed host
249  vbusState = LSHOST;
250  }
251  else {
252  regWr( rMODE, MODE_FS_HOST ); //start full-speed host
253  vbusState = FSHOST;
254  }
255  break;
256  case( bmSE1 ): //illegal state
257  vbusState = SE1;
258  break;
259  case( bmSE0 ): //disconnected state
261  vbusState = SE0;
262  break;
263  }//end switch( bus_sample )
264 }
265 /* MAX3421 state change task and interrupt handler */
266 template< typename SS, typename INTR >
268 {
269  uint8_t rcode = 0;
270  uint8_t pinvalue;
271  //Serial.print("Vbus state: ");
272  //Serial.println( vbusState, HEX );
273  pinvalue = INTR::IsSet(); //Read();
274  //pinvalue = digitalRead( MAX_INT );
275  if( pinvalue == 0 ) {
276  rcode = IntHandler();
277  }
278 // pinvalue = digitalRead( MAX_GPX );
279 // if( pinvalue == LOW ) {
280 // GpxHandler();
281 // }
282 // usbSM(); //USB state machine
283  return( rcode );
284 }
285 template< typename SS, typename INTR >
287 {
288  uint8_t HIRQ;
289  uint8_t HIRQ_sendback = 0x00;
290  HIRQ = regRd( rHIRQ ); //determine interrupt source
291  //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler
292  // HIRQ_sendback |= bmFRAMEIRQ;
293  //}//end FRAMEIRQ handling
294  if( HIRQ & bmCONDETIRQ ) {
295  busprobe();
296  HIRQ_sendback |= bmCONDETIRQ;
297  }
298  /* End HIRQ interrupts handling, clear serviced IRQs */
299  regWr( rHIRQ, HIRQ_sendback );
300  return( HIRQ_sendback );
301 }
302 //template< typename SS, typename INTR >
303 //uint8_t MAX3421e< SS, INTR >::GpxHandler()
304 //{
305 // uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register
312 // return( GPINIRQ );
313 //}
314 
315 #endif //_USBHOST_H_