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 
19 
20 #if !defined(_usb_h_) || defined(_USBHOST_H_)
21 #error "Never include usbhost.h directly; include Usb.h instead"
22 #else
23 #define _USBHOST_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; // 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 #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
48 typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;
49 #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
50 typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi;
51 #elif defined(__MK20DX128__)
52 typedef SPi< P13, P11, P12, P10 > spi;
53 #else
54 #error "No SPI entry in usbhost.h"
55 #endif
56 
57 typedef enum {
58  vbus_on = 0,
60 } VBUS_t;
61 
62 template< typename SS, typename INTR > class MAX3421e /* : public spi */ {
63  static uint8_t vbusState;
64 
65 public:
66  MAX3421e();
67  void regWr(uint8_t reg, uint8_t data);
68  uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p);
69  void gpioWr(uint8_t data);
70  uint8_t regRd(uint8_t reg);
71  uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p);
72  uint8_t gpioRd();
73  uint16_t reset();
74  int8_t Init();
75  int8_t Init(int mseconds);
76 
77  void vbusPower(VBUS_t state) {
78  regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | state));
79  }
80 
81  uint8_t getVbusState(void) {
82  return vbusState;
83  };
84  void busprobe();
85  uint8_t GpxHandler();
86  uint8_t IntHandler();
87  uint8_t Task();
88 };
89 
90 template< typename SS, typename INTR >
92 
93 /* constructor */
94 template< typename SS, typename INTR >
96 // Leaving ADK hardware setup in here, for now. This really belongs with the other parts.
97 #ifdef BOARD_MEGA_ADK
98  // For Mega ADK, which has a Max3421e on-board, set MAX_RESET to output mode, and then set it to HIGH
99  P55::SetDirWrite();
100  P55::Set();
101 #endif
102 };
103 
104 /* write single byte into MAX3421 register */
105 template< typename SS, typename INTR >
106 void MAX3421e< SS, INTR >::regWr(uint8_t reg, uint8_t data) {
108  SS::Clear();
109  SPDR = (reg | 0x02);
110  while(!(SPSR & (1 << SPIF)));
111  SPDR = data;
112  while(!(SPSR & (1 << SPIF)));
113  SS::Set();
115  return;
116 };
117 /* multiple-byte write */
118 
119 /* returns a pointer to memory position after last written */
120 template< typename SS, typename INTR >
121 uint8_t* MAX3421e< SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
123  SS::Clear();
124  SPDR = (reg | 0x02); //set WR bit and send register number
125  while(nbytes--) {
126  while(!(SPSR & (1 << SPIF))); //check if previous byte was sent
127  SPDR = (*data_p); // send next data byte
128  data_p++; // advance data pointer
129  }
130  while(!(SPSR & (1 << SPIF)));
131  SS::Set();
133  return( data_p);
134 }
135 /* GPIO write */
136 /*GPIO byte is split between 2 registers, so two writes are needed to write one byte */
137 
138 /* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */
139 template< typename SS, typename INTR >
140 void MAX3421e< SS, INTR >::gpioWr(uint8_t data) {
141  regWr(rIOPINS1, data);
142  data >>= 4;
143  regWr(rIOPINS2, data);
144  return;
145 }
146 
147 /* single host register read */
148 template< typename SS, typename INTR >
149 uint8_t MAX3421e< SS, INTR >::regRd(uint8_t reg) {
151  SS::Clear();
152  SPDR = reg;
153  while(!(SPSR & (1 << SPIF)));
154  SPDR = 0; //send empty byte
155  while(!(SPSR & (1 << SPIF)));
156  SS::Set();
157  uint8_t rv = SPDR;
159  return(rv);
160 }
161 /* multiple-byte register read */
162 
163 /* returns a pointer to a memory position after last read */
164 template< typename SS, typename INTR >
165 uint8_t* MAX3421e< SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
167  SS::Clear();
168  SPDR = reg;
169  while(!(SPSR & (1 << SPIF))); //wait
170  while(nbytes) {
171  SPDR = 0; //send empty byte
172  nbytes--;
173  while(!(SPSR & (1 << SPIF)));
174 #if 0
175  {
176  *data_p = SPDR;
177  printf("%2.2x ", *data_p);
178  }
179  data_p++;
180  }
181  printf("\r\n");
182 #else
183  *data_p++ = SPDR;
184  }
185 #endif
186  SS::Set();
188  return( data_p);
189 }
190 /* GPIO read. See gpioWr for explanation */
191 
192 /* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */
193 template< typename SS, typename INTR >
195  uint8_t gpin = 0;
196  gpin = regRd(rIOPINS2); //pins 4-7
197  gpin &= 0xf0; //clean lower nibble
198  gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation.
199  return( gpin);
200 }
201 
202 /* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset
203  or zero if PLL haven't stabilized in 65535 cycles */
204 template< typename SS, typename INTR >
206  uint16_t i = 0;
207  regWr(rUSBCTL, bmCHIPRES);
208  regWr(rUSBCTL, 0x00);
209  while(++i) {
210  if((regRd(rUSBIRQ) & bmOSCOKIRQ)) {
211  break;
212  }
213  }
214  return( i);
215 }
216 
217 /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
218 template< typename SS, typename INTR >
221  // Moved here.
222  // you really should not init hardware in the constructor when it involves locks.
223  // Also avoids the vbus flicker issue confusing some devices.
224  /* pin and peripheral setup */
225  SS::SetDirWrite();
226  SS::Set();
227  spi::init();
228  INTR::SetDirRead();
230  /* MAX3421E - full-duplex SPI, level interrupt */
231  // GPX pin on. Moved here, otherwise we flicker the vbus.
232  regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));
233 
234  if(reset() == 0) { //OSCOKIRQ hasn't asserted in time
235  return( -1);
236  }
237 
238  regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
239 
240  regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection
241 
242  /* check if device is connected */
243  regWr(rHCTL, bmSAMPLEBUS); // sample USB bus
244  while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish
245 
246  busprobe(); //check if anything is connected
247 
248  regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt
249  regWr(rCPUCTL, 0x01); //enable interrupt pin
250 
251  return( 0);
252 }
253 
254 /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
255 template< typename SS, typename INTR >
256 int8_t MAX3421e< SS, INTR >::Init(int mseconds) {
258  // Moved here.
259  // you really should not init hardware in the constructor when it involves locks.
260  // Also avoids the vbus flicker issue confusing some devices.
261  /* pin and peripheral setup */
262  SS::SetDirWrite();
263  SS::Set();
264  spi::init();
265  INTR::SetDirRead();
267  /* MAX3421E - full-duplex SPI, level interrupt, vbus off */
268  regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET));
269 
270  if(reset() == 0) { //OSCOKIRQ hasn't asserted in time
271  return( -1);
272  }
273 
274  // Delay a minimum of 1 second to ensure any capacitors are drained.
275  // 1 second is required to make sure we do not smoke a Microdrive!
276  if(mseconds < 1000) mseconds = 1000;
277  delay(mseconds);
278 
279  regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
280 
281  regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection
282 
283  /* check if device is connected */
284  regWr(rHCTL, bmSAMPLEBUS); // sample USB bus
285  while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish
286 
287  busprobe(); //check if anything is connected
288 
289  regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt
290  regWr(rCPUCTL, 0x01); //enable interrupt pin
291 
292  // GPX pin on. This is done here so that busprobe will fail if we have a switch connected.
293  regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));
294 
295  return( 0);
296 }
297 
298 /* probe bus to determine device presence and speed and switch host to this speed */
299 template< typename SS, typename INTR >
301  uint8_t bus_sample;
302  bus_sample = regRd(rHRSL); //Get J,K status
303  bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte
304  switch(bus_sample) { //start full-speed or low-speed host
305  case( bmJSTATUS):
306  if((regRd(rMODE) & bmLOWSPEED) == 0) {
307  regWr(rMODE, MODE_FS_HOST); //start full-speed host
308  vbusState = FSHOST;
309  } else {
310  regWr(rMODE, MODE_LS_HOST); //start low-speed host
311  vbusState = LSHOST;
312  }
313  break;
314  case( bmKSTATUS):
315  if((regRd(rMODE) & bmLOWSPEED) == 0) {
316  regWr(rMODE, MODE_LS_HOST); //start low-speed host
317  vbusState = LSHOST;
318  } else {
319  regWr(rMODE, MODE_FS_HOST); //start full-speed host
320  vbusState = FSHOST;
321  }
322  break;
323  case( bmSE1): //illegal state
324  vbusState = SE1;
325  break;
326  case( bmSE0): //disconnected state
327  regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ);
328  vbusState = SE0;
329  break;
330  }//end switch( bus_sample )
331 }
332 
333 /* MAX3421 state change task and interrupt handler */
334 template< typename SS, typename INTR >
336  uint8_t rcode = 0;
337  uint8_t pinvalue;
338  //USB_HOST_SERIAL.print("Vbus state: ");
339  //USB_HOST_SERIAL.println( vbusState, HEX );
340  pinvalue = INTR::IsSet(); //Read();
341  //pinvalue = digitalRead( MAX_INT );
342  if(pinvalue == 0) {
343  rcode = IntHandler();
344  }
345  // pinvalue = digitalRead( MAX_GPX );
346  // if( pinvalue == LOW ) {
347  // GpxHandler();
348  // }
349  // usbSM(); //USB state machine
350  return( rcode);
351 }
352 
353 template< typename SS, typename INTR >
355  uint8_t HIRQ;
356  uint8_t HIRQ_sendback = 0x00;
357  HIRQ = regRd(rHIRQ); //determine interrupt source
358  //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler
359  // HIRQ_sendback |= bmFRAMEIRQ;
360  //}//end FRAMEIRQ handling
361  if(HIRQ & bmCONDETIRQ) {
362  busprobe();
363  HIRQ_sendback |= bmCONDETIRQ;
364  }
365  /* End HIRQ interrupts handling, clear serviced IRQs */
366  regWr(rHIRQ, HIRQ_sendback);
367  return( HIRQ_sendback);
368 }
369 //template< typename SS, typename INTR >
370 //uint8_t MAX3421e< SS, INTR >::GpxHandler()
371 //{
372 // uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register
379 // return( GPINIRQ );
380 //}
381 
382 #endif //_USBHOST_H_
#define GPX_VBDET
Definition: max3421e.h:80
#define rIOPINS1
Definition: max3421e.h:86
#define rHIEN
Definition: max3421e.h:153
#define FSHOST
Definition: max3421e.h:35
#define rHCTL
Definition: max3421e.h:179
void busprobe()
Definition: usbhost.h:300
#define bmCONDETIRQ
Definition: max3421e.h:149
#define bmCONDETIE
Definition: max3421e.h:161
#define bmSE1
Definition: max3421e.h:209
MAX3421e()
Definition: usbhost.h:95
#define bmCHIPRES
Definition: max3421e.h:62
void regWr(uint8_t reg, uint8_t data)
Definition: usbhost.h:106
uint8_t GpxHandler()
#define rCPUCTL
Definition: max3421e.h:65
static void init()
Definition: usbhost.h:29
#define bmJSTATUS
Definition: max3421e.h:207
#define MODE_LS_HOST
Definition: max3421e.h:230
#define bmINTLEVEL
Definition: max3421e.h:74
#define rUSBCTL
Definition: max3421e.h:60
#define bmSE0
Definition: max3421e.h:208
#define bmHOST
Definition: max3421e.h:168
#define bmSEPIRQ
Definition: max3421e.h:172
void gpioWr(uint8_t data)
Definition: usbhost.h:140
#define LSHOST
Definition: max3421e.h:36
#define rMODE
Definition: max3421e.h:165
#define MODE_FS_HOST
Definition: max3421e.h:229
#define bmKSTATUS
Definition: max3421e.h:206
#define rHRSL
Definition: max3421e.h:201
#define XMEM_ACQUIRE_SPI()
Definition: settings.h:75
int8_t Init()
Definition: usbhost.h:219
#define bmLOWSPEED
Definition: max3421e.h:169
Definition: usbhost.h:26
uint8_t Task()
Definition: usbhost.h:335
#define rHIRQ
Definition: max3421e.h:142
#define rUSBIRQ
Definition: max3421e.h:48
void vbusPower(VBUS_t state)
Definition: usbhost.h:77
uint8_t IntHandler()
Definition: usbhost.h:354
uint8_t * bytesWr(uint8_t reg, uint8_t nbytes, uint8_t *data_p)
Definition: usbhost.h:121
#define XMEM_RELEASE_SPI()
Definition: settings.h:76
#define bmFDUPSPI
Definition: max3421e.h:73
#define rPINCTL
Definition: max3421e.h:71
VBUS_t
Definition: usbhost.h:57
uint8_t gpioRd()
Definition: usbhost.h:194
#define bmFRAMEIE
Definition: max3421e.h:162
#define bmOSCOKIRQ
Definition: max3421e.h:52
uint8_t * bytesRd(uint8_t reg, uint8_t nbytes, uint8_t *data_p)
Definition: usbhost.h:165
uint16_t reset()
Definition: usbhost.h:205
#define SE0
Definition: max3421e.h:33
#define rIOPINS2
Definition: max3421e.h:98
#define bmDMPULLDN
Definition: max3421e.h:174
#define SE1
Definition: max3421e.h:34
#define bmSAMPLEBUS
Definition: max3421e.h:183
#define bmDPPULLDN
Definition: max3421e.h:175
uint8_t getVbusState(void)
Definition: usbhost.h:81
uint8_t regRd(uint8_t reg)
Definition: usbhost.h:149