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 /* SPI initialization */
26 template< typename CLK, typename MOSI, typename MISO, typename SPI_SS > class SPi {
27 public:
28 
29  static void init() {
30  //uint8_t tmp;
31  CLK::SetDirWrite();
32  MOSI::SetDirWrite();
33  MISO::SetDirRead();
34  SPI_SS::SetDirWrite();
35  /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */
36  SPCR = 0x50;
37  SPSR = 0x01;
38 
39  //tmp = SPSR;
40  //tmp = SPDR;
41  }
42 };
43 
44 /* SPI pin definitions. see avrpins.h */
45 #if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
46 typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi;
47 #endif
48 #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
49 typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;
50 #endif
51 #if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__)
52 typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi;
53 #endif
54 
55 template< typename SS, typename INTR > class MAX3421e /* : public spi */ {
56  static uint8_t vbusState;
57 
58 public:
59  MAX3421e();
60  void regWr(uint8_t reg, uint8_t data);
61  uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p);
62  void gpioWr(uint8_t data);
63  uint8_t regRd(uint8_t reg);
64  uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p);
65  uint8_t gpioRd();
66  uint16_t reset();
67  int8_t Init();
68 
69  uint8_t getVbusState(void) {
70  return vbusState;
71  };
72  void busprobe();
73  uint8_t GpxHandler();
74  uint8_t IntHandler();
75  uint8_t Task();
76 };
77 
78 template< typename SS, typename INTR >
80 
81 /* constructor */
82 template< typename SS, typename INTR >
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 
100 /* write single byte into MAX3421 register */
101 template< typename SS, typename INTR >
102 void MAX3421e< SS, INTR >::regWr(uint8_t reg, uint8_t data) {
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 
113 /* returns a pointer to memory position after last written */
114 template< typename SS, typename INTR >
115 uint8_t* MAX3421e< SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
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 
130 /* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */
131 template< typename SS, typename INTR >
132 void MAX3421e< SS, INTR >::gpioWr(uint8_t data) {
133  regWr(rIOPINS1, data);
134  data >>= 4;
135  regWr(rIOPINS2, data);
136  return;
137 }
138 
139 /* single host register read */
140 template< typename SS, typename INTR >
141 uint8_t MAX3421e< SS, INTR >::regRd(uint8_t reg) {
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 
152 /* returns a pointer to a memory position after last read */
153 template< typename SS, typename INTR >
154 uint8_t* MAX3421e< SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
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 
170 /* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */
171 template< typename SS, typename INTR >
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 
180 /* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset
181  or zero if PLL haven't stabilized in 65535 cycles */
182 template< typename SS, typename INTR >
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 
206 /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
207 template< typename SS, typename INTR >
209  if(reset() == 0) { //OSCOKIRQ hasn't asserted in time
210  return( -1);
211  }
212  regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
213 
214  regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection
215 
216  /* check if device is connected */
217  regWr(rHCTL, bmSAMPLEBUS); // sample USB bus
218  while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish
219 
220  busprobe(); //check if anything is connected
221 
222  regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt
223  regWr(rCPUCTL, 0x01); //enable interrupt pin
224  return( 0);
225 }
226 
227 /* probe bus to determine device presence and speed and switch host to this speed */
228 template< typename SS, typename INTR >
230  uint8_t bus_sample;
231  bus_sample = regRd(rHRSL); //Get J,K status
232  bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte
233  switch(bus_sample) { //start full-speed or low-speed host
234  case( bmJSTATUS):
235  if((regRd(rMODE) & bmLOWSPEED) == 0) {
236  regWr(rMODE, MODE_FS_HOST); //start full-speed host
237  vbusState = FSHOST;
238  } else {
239  regWr(rMODE, MODE_LS_HOST); //start low-speed host
240  vbusState = LSHOST;
241  }
242  break;
243  case( bmKSTATUS):
244  if((regRd(rMODE) & bmLOWSPEED) == 0) {
245  regWr(rMODE, MODE_LS_HOST); //start low-speed host
246  vbusState = LSHOST;
247  } else {
248  regWr(rMODE, MODE_FS_HOST); //start full-speed host
249  vbusState = FSHOST;
250  }
251  break;
252  case( bmSE1): //illegal state
253  vbusState = SE1;
254  break;
255  case( bmSE0): //disconnected state
256  regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ);
257  vbusState = SE0;
258  break;
259  }//end switch( bus_sample )
260 }
261 
262 /* MAX3421 state change task and interrupt handler */
263 template< typename SS, typename INTR >
265  uint8_t rcode = 0;
266  uint8_t pinvalue;
267  //Serial.print("Vbus state: ");
268  //Serial.println( vbusState, HEX );
269  pinvalue = INTR::IsSet(); //Read();
270  //pinvalue = digitalRead( MAX_INT );
271  if(pinvalue == 0) {
272  rcode = IntHandler();
273  }
274  // pinvalue = digitalRead( MAX_GPX );
275  // if( pinvalue == LOW ) {
276  // GpxHandler();
277  // }
278  // usbSM(); //USB state machine
279  return( rcode);
280 }
281 
282 template< typename SS, typename INTR >
284  uint8_t HIRQ;
285  uint8_t HIRQ_sendback = 0x00;
286  HIRQ = regRd(rHIRQ); //determine interrupt source
287  //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler
288  // HIRQ_sendback |= bmFRAMEIRQ;
289  //}//end FRAMEIRQ handling
290  if(HIRQ & bmCONDETIRQ) {
291  busprobe();
292  HIRQ_sendback |= bmCONDETIRQ;
293  }
294  /* End HIRQ interrupts handling, clear serviced IRQs */
295  regWr(rHIRQ, HIRQ_sendback);
296  return( HIRQ_sendback);
297 }
298 //template< typename SS, typename INTR >
299 //uint8_t MAX3421e< SS, INTR >::GpxHandler()
300 //{
301 // uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register
308 // return( GPINIRQ );
309 //}
310 
311 #endif //_USBHOST_H_