diff options
Diffstat (limited to 'lib/usbhost/USB_Host_Shield_2.0/usbhost.h')
-rw-r--r-- | lib/usbhost/USB_Host_Shield_2.0/usbhost.h | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/lib/usbhost/USB_Host_Shield_2.0/usbhost.h b/lib/usbhost/USB_Host_Shield_2.0/usbhost.h new file mode 100644 index 000000000..eba480e60 --- /dev/null +++ b/lib/usbhost/USB_Host_Shield_2.0/usbhost.h | |||
@@ -0,0 +1,529 @@ | |||
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 | #if USING_SPI4TEENSY3 | ||
26 | #include <spi4teensy3.h> | ||
27 | #include <sys/types.h> | ||
28 | #endif | ||
29 | |||
30 | /* SPI initialization */ | ||
31 | template< typename SPI_CLK, typename SPI_MOSI, typename SPI_MISO, typename SPI_SS > class SPi { | ||
32 | public: | ||
33 | #if USING_SPI4TEENSY3 | ||
34 | static void init() { | ||
35 | // spi4teensy3 inits everything for us, except /SS | ||
36 | // CLK, MOSI and MISO are hard coded for now. | ||
37 | // spi4teensy3::init(0,0,0); // full speed, cpol 0, cpha 0 | ||
38 | spi4teensy3::init(); // full speed, cpol 0, cpha 0 | ||
39 | SPI_SS::SetDirWrite(); | ||
40 | SPI_SS::Set(); | ||
41 | } | ||
42 | #elif SPI_HAS_TRANSACTION | ||
43 | static void init() { | ||
44 | SPI.begin(); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction() | ||
45 | } | ||
46 | #elif !defined(SPDR) | ||
47 | static void init() { | ||
48 | SPI_SS::SetDirWrite(); | ||
49 | SPI_SS::Set(); | ||
50 | SPI.begin(); | ||
51 | #if defined(__MIPSEL__) | ||
52 | SPI.setClockDivider(1); | ||
53 | #elif defined(__ARDUINO_X86__) | ||
54 | #ifdef SPI_CLOCK_1M // Hack used to check if setClockSpeed is available | ||
55 | SPI.setClockSpeed(12000000); // The MAX3421E can handle up to 26MHz, but in practice this was the maximum that I could reliably use | ||
56 | #else | ||
57 | SPI.setClockDivider(SPI_CLOCK_DIV2); // This will set the SPI frequency to 8MHz - it could be higher, but it is not supported in the old API | ||
58 | #endif | ||
59 | #else | ||
60 | SPI.setClockDivider(4); // Set speed to 84MHz/4=21MHz - the MAX3421E can handle up to 26MHz | ||
61 | #endif | ||
62 | } | ||
63 | #elif defined(RBL_NRF51822) | ||
64 | static void init() { | ||
65 | SPI_SS::SetDirWrite(); | ||
66 | SPI_SS::Set(); | ||
67 | SPI.begin(); | ||
68 | // SPI.setFrequency(SPI_FREQUENCY_8M); | ||
69 | } | ||
70 | #else | ||
71 | static void init() { | ||
72 | //uint8_t tmp; | ||
73 | SPI_CLK::SetDirWrite(); | ||
74 | SPI_MOSI::SetDirWrite(); | ||
75 | SPI_MISO::SetDirRead(); | ||
76 | SPI_SS::SetDirWrite(); | ||
77 | /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */ | ||
78 | SPCR = 0x50; | ||
79 | SPSR = 0x01; // 0x01 | ||
80 | /**/ | ||
81 | //tmp = SPSR; | ||
82 | //tmp = SPDR; | ||
83 | } | ||
84 | #endif | ||
85 | }; | ||
86 | |||
87 | /* SPI pin definitions. see avrpins.h */ | ||
88 | #if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | ||
89 | typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi; | ||
90 | #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) | ||
91 | typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi; | ||
92 | #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) | ||
93 | typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi; | ||
94 | #elif (defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))) || defined(__ARDUINO_X86__) || defined(__MIPSEL__) | ||
95 | typedef SPi< P13, P11, P12, P10 > spi; | ||
96 | #elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__) | ||
97 | typedef SPi< P76, P75, P74, P10 > spi; | ||
98 | #elif defined(RBL_NRF51822) | ||
99 | typedef SPi< P16, P18, P17, P10 > spi; | ||
100 | #else | ||
101 | #error "No SPI entry in usbhost.h" | ||
102 | #endif | ||
103 | |||
104 | typedef enum { | ||
105 | vbus_on = 0, | ||
106 | vbus_off = GPX_VBDET | ||
107 | } VBUS_t; | ||
108 | |||
109 | template< typename SPI_SS, typename INTR > class MAX3421e /* : public spi */ { | ||
110 | static uint8_t vbusState; | ||
111 | |||
112 | public: | ||
113 | MAX3421e(); | ||
114 | void regWr(uint8_t reg, uint8_t data); | ||
115 | uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p); | ||
116 | void gpioWr(uint8_t data); | ||
117 | uint8_t regRd(uint8_t reg); | ||
118 | uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p); | ||
119 | uint8_t gpioRd(); | ||
120 | uint16_t reset(); | ||
121 | int8_t Init(); | ||
122 | int8_t Init(int mseconds); | ||
123 | |||
124 | void vbusPower(VBUS_t state) { | ||
125 | regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | state)); | ||
126 | } | ||
127 | |||
128 | uint8_t getVbusState(void) { | ||
129 | return vbusState; | ||
130 | }; | ||
131 | void busprobe(); | ||
132 | uint8_t GpxHandler(); | ||
133 | uint8_t IntHandler(); | ||
134 | uint8_t Task(); | ||
135 | }; | ||
136 | |||
137 | template< typename SPI_SS, typename INTR > | ||
138 | uint8_t MAX3421e< SPI_SS, INTR >::vbusState = 0; | ||
139 | |||
140 | /* constructor */ | ||
141 | template< typename SPI_SS, typename INTR > | ||
142 | MAX3421e< SPI_SS, INTR >::MAX3421e() { | ||
143 | // Leaving ADK hardware setup in here, for now. This really belongs with the other parts. | ||
144 | #ifdef BOARD_MEGA_ADK | ||
145 | // For Mega ADK, which has a Max3421e on-board, set MAX_RESET to output mode, and then set it to HIGH | ||
146 | P55::SetDirWrite(); | ||
147 | P55::Set(); | ||
148 | #endif | ||
149 | }; | ||
150 | |||
151 | /* write single byte into MAX3421 register */ | ||
152 | template< typename SPI_SS, typename INTR > | ||
153 | void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) { | ||
154 | XMEM_ACQUIRE_SPI(); | ||
155 | #if SPI_HAS_TRANSACTION | ||
156 | SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 | ||
157 | #endif | ||
158 | SPI_SS::Clear(); | ||
159 | |||
160 | #if USING_SPI4TEENSY3 | ||
161 | uint8_t c[2]; | ||
162 | c[0] = reg | 0x02; | ||
163 | c[1] = data; | ||
164 | spi4teensy3::send(c, 2); | ||
165 | #elif SPI_HAS_TRANSACTION | ||
166 | uint8_t c[2]; | ||
167 | c[0] = reg | 0x02; | ||
168 | c[1] = data; | ||
169 | SPI.transfer(c, 2); | ||
170 | #elif !defined(SPDR) | ||
171 | SPI.transfer(reg | 0x02); | ||
172 | SPI.transfer(data); | ||
173 | #else | ||
174 | SPDR = (reg | 0x02); | ||
175 | while(!(SPSR & (1 << SPIF))); | ||
176 | SPDR = data; | ||
177 | while(!(SPSR & (1 << SPIF))); | ||
178 | #endif | ||
179 | |||
180 | SPI_SS::Set(); | ||
181 | #if SPI_HAS_TRANSACTION | ||
182 | SPI.endTransaction(); | ||
183 | #endif | ||
184 | XMEM_RELEASE_SPI(); | ||
185 | return; | ||
186 | }; | ||
187 | /* multiple-byte write */ | ||
188 | |||
189 | /* returns a pointer to memory position after last written */ | ||
190 | template< typename SPI_SS, typename INTR > | ||
191 | uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { | ||
192 | XMEM_ACQUIRE_SPI(); | ||
193 | #if SPI_HAS_TRANSACTION | ||
194 | SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 | ||
195 | #endif | ||
196 | SPI_SS::Clear(); | ||
197 | |||
198 | #if USING_SPI4TEENSY3 | ||
199 | spi4teensy3::send(reg | 0x02); | ||
200 | spi4teensy3::send(data_p, nbytes); | ||
201 | data_p += nbytes; | ||
202 | #elif SPI_HAS_TRANSACTION | ||
203 | SPI.transfer(reg | 0x02); | ||
204 | SPI.transfer(data_p, nbytes); | ||
205 | data_p += nbytes; | ||
206 | #elif defined(__ARDUINO_X86__) | ||
207 | SPI.transfer(reg | 0x02); | ||
208 | SPI.transferBuffer(data_p, NULL, nbytes); | ||
209 | data_p += nbytes; | ||
210 | #elif !defined(SPDR) | ||
211 | SPI.transfer(reg | 0x02); | ||
212 | while(nbytes) { | ||
213 | SPI.transfer(*data_p); | ||
214 | nbytes--; | ||
215 | data_p++; // advance data pointer | ||
216 | } | ||
217 | #else | ||
218 | SPDR = (reg | 0x02); //set WR bit and send register number | ||
219 | while(nbytes) { | ||
220 | while(!(SPSR & (1 << SPIF))); //check if previous byte was sent | ||
221 | SPDR = (*data_p); // send next data byte | ||
222 | nbytes--; | ||
223 | data_p++; // advance data pointer | ||
224 | } | ||
225 | while(!(SPSR & (1 << SPIF))); | ||
226 | #endif | ||
227 | |||
228 | SPI_SS::Set(); | ||
229 | #if SPI_HAS_TRANSACTION | ||
230 | SPI.endTransaction(); | ||
231 | #endif | ||
232 | XMEM_RELEASE_SPI(); | ||
233 | return ( data_p); | ||
234 | } | ||
235 | /* GPIO write */ | ||
236 | /*GPIO byte is split between 2 registers, so two writes are needed to write one byte */ | ||
237 | |||
238 | /* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */ | ||
239 | template< typename SPI_SS, typename INTR > | ||
240 | void MAX3421e< SPI_SS, INTR >::gpioWr(uint8_t data) { | ||
241 | regWr(rIOPINS1, data); | ||
242 | data >>= 4; | ||
243 | regWr(rIOPINS2, data); | ||
244 | return; | ||
245 | } | ||
246 | |||
247 | /* single host register read */ | ||
248 | template< typename SPI_SS, typename INTR > | ||
249 | uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) { | ||
250 | XMEM_ACQUIRE_SPI(); | ||
251 | #if SPI_HAS_TRANSACTION | ||
252 | SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 | ||
253 | #endif | ||
254 | SPI_SS::Clear(); | ||
255 | |||
256 | #if USING_SPI4TEENSY3 | ||
257 | spi4teensy3::send(reg); | ||
258 | uint8_t rv = spi4teensy3::receive(); | ||
259 | SPI_SS::Set(); | ||
260 | #elif !defined(SPDR) || SPI_HAS_TRANSACTION | ||
261 | SPI.transfer(reg); | ||
262 | uint8_t rv = SPI.transfer(0); // Send empty byte | ||
263 | SPI_SS::Set(); | ||
264 | #else | ||
265 | SPDR = reg; | ||
266 | while(!(SPSR & (1 << SPIF))); | ||
267 | SPDR = 0; // Send empty byte | ||
268 | while(!(SPSR & (1 << SPIF))); | ||
269 | SPI_SS::Set(); | ||
270 | uint8_t rv = SPDR; | ||
271 | #endif | ||
272 | |||
273 | #if SPI_HAS_TRANSACTION | ||
274 | SPI.endTransaction(); | ||
275 | #endif | ||
276 | XMEM_RELEASE_SPI(); | ||
277 | return (rv); | ||
278 | } | ||
279 | /* multiple-byte register read */ | ||
280 | |||
281 | /* returns a pointer to a memory position after last read */ | ||
282 | template< typename SPI_SS, typename INTR > | ||
283 | uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { | ||
284 | XMEM_ACQUIRE_SPI(); | ||
285 | #if SPI_HAS_TRANSACTION | ||
286 | SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0 | ||
287 | #endif | ||
288 | SPI_SS::Clear(); | ||
289 | |||
290 | #if USING_SPI4TEENSY3 | ||
291 | spi4teensy3::send(reg); | ||
292 | spi4teensy3::receive(data_p, nbytes); | ||
293 | data_p += nbytes; | ||
294 | #elif SPI_HAS_TRANSACTION | ||
295 | SPI.transfer(reg); | ||
296 | memset(data_p, 0, nbytes); // Make sure we send out empty bytes | ||
297 | SPI.transfer(data_p, nbytes); | ||
298 | data_p += nbytes; | ||
299 | #elif defined(__ARDUINO_X86__) | ||
300 | SPI.transfer(reg); | ||
301 | SPI.transferBuffer(NULL, data_p, nbytes); | ||
302 | data_p += nbytes; | ||
303 | #elif !defined(SPDR) | ||
304 | SPI.transfer(reg); | ||
305 | while(nbytes) { | ||
306 | *data_p++ = SPI.transfer(0); | ||
307 | nbytes--; | ||
308 | } | ||
309 | #else | ||
310 | SPDR = reg; | ||
311 | while(!(SPSR & (1 << SPIF))); //wait | ||
312 | while(nbytes) { | ||
313 | SPDR = 0; // Send empty byte | ||
314 | nbytes--; | ||
315 | while(!(SPSR & (1 << SPIF))); | ||
316 | #if 0 | ||
317 | { | ||
318 | *data_p = SPDR; | ||
319 | printf("%2.2x ", *data_p); | ||
320 | } | ||
321 | data_p++; | ||
322 | } | ||
323 | printf("\r\n"); | ||
324 | #else | ||
325 | *data_p++ = SPDR; | ||
326 | } | ||
327 | #endif | ||
328 | #endif | ||
329 | |||
330 | SPI_SS::Set(); | ||
331 | #if SPI_HAS_TRANSACTION | ||
332 | SPI.endTransaction(); | ||
333 | #endif | ||
334 | XMEM_RELEASE_SPI(); | ||
335 | return ( data_p); | ||
336 | } | ||
337 | /* GPIO read. See gpioWr for explanation */ | ||
338 | |||
339 | /* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */ | ||
340 | template< typename SPI_SS, typename INTR > | ||
341 | uint8_t MAX3421e< SPI_SS, INTR >::gpioRd() { | ||
342 | uint8_t gpin = 0; | ||
343 | gpin = regRd(rIOPINS2); //pins 4-7 | ||
344 | gpin &= 0xf0; //clean lower nibble | ||
345 | gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation. | ||
346 | return ( gpin); | ||
347 | } | ||
348 | |||
349 | /* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset | ||
350 | or zero if PLL haven't stabilized in 65535 cycles */ | ||
351 | template< typename SPI_SS, typename INTR > | ||
352 | uint16_t MAX3421e< SPI_SS, INTR >::reset() { | ||
353 | uint16_t i = 0; | ||
354 | regWr(rUSBCTL, bmCHIPRES); | ||
355 | regWr(rUSBCTL, 0x00); | ||
356 | while(++i) { | ||
357 | if((regRd(rUSBIRQ) & bmOSCOKIRQ)) { | ||
358 | break; | ||
359 | } | ||
360 | } | ||
361 | return ( i); | ||
362 | } | ||
363 | |||
364 | /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ | ||
365 | template< typename SPI_SS, typename INTR > | ||
366 | int8_t MAX3421e< SPI_SS, INTR >::Init() { | ||
367 | XMEM_ACQUIRE_SPI(); | ||
368 | // Moved here. | ||
369 | // you really should not init hardware in the constructor when it involves locks. | ||
370 | // Also avoids the vbus flicker issue confusing some devices. | ||
371 | /* pin and peripheral setup */ | ||
372 | SPI_SS::SetDirWrite(); | ||
373 | SPI_SS::Set(); | ||
374 | spi::init(); | ||
375 | INTR::SetDirRead(); | ||
376 | XMEM_RELEASE_SPI(); | ||
377 | /* MAX3421E - full-duplex SPI, level interrupt */ | ||
378 | // GPX pin on. Moved here, otherwise we flicker the vbus. | ||
379 | regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); | ||
380 | |||
381 | if(reset() == 0) { //OSCOKIRQ hasn't asserted in time | ||
382 | return ( -1); | ||
383 | } | ||
384 | |||
385 | regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host | ||
386 | |||
387 | regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection | ||
388 | |||
389 | /* check if device is connected */ | ||
390 | regWr(rHCTL, bmSAMPLEBUS); // sample USB bus | ||
391 | while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish | ||
392 | |||
393 | busprobe(); //check if anything is connected | ||
394 | |||
395 | regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt | ||
396 | regWr(rCPUCTL, 0x01); //enable interrupt pin | ||
397 | |||
398 | return ( 0); | ||
399 | } | ||
400 | |||
401 | /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ | ||
402 | template< typename SPI_SS, typename INTR > | ||
403 | int8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) { | ||
404 | XMEM_ACQUIRE_SPI(); | ||
405 | // Moved here. | ||
406 | // you really should not init hardware in the constructor when it involves locks. | ||
407 | // Also avoids the vbus flicker issue confusing some devices. | ||
408 | /* pin and peripheral setup */ | ||
409 | SPI_SS::SetDirWrite(); | ||
410 | SPI_SS::Set(); | ||
411 | spi::init(); | ||
412 | INTR::SetDirRead(); | ||
413 | XMEM_RELEASE_SPI(); | ||
414 | /* MAX3421E - full-duplex SPI, level interrupt, vbus off */ | ||
415 | regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET)); | ||
416 | |||
417 | if(reset() == 0) { //OSCOKIRQ hasn't asserted in time | ||
418 | return ( -1); | ||
419 | } | ||
420 | |||
421 | // Delay a minimum of 1 second to ensure any capacitors are drained. | ||
422 | // 1 second is required to make sure we do not smoke a Microdrive! | ||
423 | if(mseconds < 1000) mseconds = 1000; | ||
424 | delay(mseconds); | ||
425 | |||
426 | regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host | ||
427 | |||
428 | regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection | ||
429 | |||
430 | /* check if device is connected */ | ||
431 | regWr(rHCTL, bmSAMPLEBUS); // sample USB bus | ||
432 | while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish | ||
433 | |||
434 | busprobe(); //check if anything is connected | ||
435 | |||
436 | regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt | ||
437 | regWr(rCPUCTL, 0x01); //enable interrupt pin | ||
438 | |||
439 | // GPX pin on. This is done here so that busprobe will fail if we have a switch connected. | ||
440 | regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL)); | ||
441 | |||
442 | return ( 0); | ||
443 | } | ||
444 | |||
445 | /* probe bus to determine device presence and speed and switch host to this speed */ | ||
446 | template< typename SPI_SS, typename INTR > | ||
447 | void MAX3421e< SPI_SS, INTR >::busprobe() { | ||
448 | uint8_t bus_sample; | ||
449 | bus_sample = regRd(rHRSL); //Get J,K status | ||
450 | bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte | ||
451 | switch(bus_sample) { //start full-speed or low-speed host | ||
452 | case( bmJSTATUS): | ||
453 | if((regRd(rMODE) & bmLOWSPEED) == 0) { | ||
454 | regWr(rMODE, MODE_FS_HOST); //start full-speed host | ||
455 | vbusState = FSHOST; | ||
456 | } else { | ||
457 | regWr(rMODE, MODE_LS_HOST); //start low-speed host | ||
458 | vbusState = LSHOST; | ||
459 | } | ||
460 | break; | ||
461 | case( bmKSTATUS): | ||
462 | if((regRd(rMODE) & bmLOWSPEED) == 0) { | ||
463 | regWr(rMODE, MODE_LS_HOST); //start low-speed host | ||
464 | vbusState = LSHOST; | ||
465 | } else { | ||
466 | regWr(rMODE, MODE_FS_HOST); //start full-speed host | ||
467 | vbusState = FSHOST; | ||
468 | } | ||
469 | break; | ||
470 | case( bmSE1): //illegal state | ||
471 | vbusState = SE1; | ||
472 | break; | ||
473 | case( bmSE0): //disconnected state | ||
474 | regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ); | ||
475 | vbusState = SE0; | ||
476 | break; | ||
477 | }//end switch( bus_sample ) | ||
478 | } | ||
479 | |||
480 | /* MAX3421 state change task and interrupt handler */ | ||
481 | template< typename SPI_SS, typename INTR > | ||
482 | uint8_t MAX3421e< SPI_SS, INTR >::Task(void) { | ||
483 | uint8_t rcode = 0; | ||
484 | uint8_t pinvalue; | ||
485 | //USB_HOST_SERIAL.print("Vbus state: "); | ||
486 | //USB_HOST_SERIAL.println( vbusState, HEX ); | ||
487 | pinvalue = INTR::IsSet(); //Read(); | ||
488 | //pinvalue = digitalRead( MAX_INT ); | ||
489 | if(pinvalue == 0) { | ||
490 | rcode = IntHandler(); | ||
491 | } | ||
492 | // pinvalue = digitalRead( MAX_GPX ); | ||
493 | // if( pinvalue == LOW ) { | ||
494 | // GpxHandler(); | ||
495 | // } | ||
496 | // usbSM(); //USB state machine | ||
497 | return ( rcode); | ||
498 | } | ||
499 | |||
500 | template< typename SPI_SS, typename INTR > | ||
501 | uint8_t MAX3421e< SPI_SS, INTR >::IntHandler() { | ||
502 | uint8_t HIRQ; | ||
503 | uint8_t HIRQ_sendback = 0x00; | ||
504 | HIRQ = regRd(rHIRQ); //determine interrupt source | ||
505 | //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler | ||
506 | // HIRQ_sendback |= bmFRAMEIRQ; | ||
507 | //}//end FRAMEIRQ handling | ||
508 | if(HIRQ & bmCONDETIRQ) { | ||
509 | busprobe(); | ||
510 | HIRQ_sendback |= bmCONDETIRQ; | ||
511 | } | ||
512 | /* End HIRQ interrupts handling, clear serviced IRQs */ | ||
513 | regWr(rHIRQ, HIRQ_sendback); | ||
514 | return ( HIRQ_sendback); | ||
515 | } | ||
516 | //template< typename SPI_SS, typename INTR > | ||
517 | //uint8_t MAX3421e< SPI_SS, INTR >::GpxHandler() | ||
518 | //{ | ||
519 | // uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register | ||
520 | //// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload | ||
521 | //// vbusPwr( OFF ); //attempt powercycle | ||
522 | //// delay( 1000 ); | ||
523 | //// vbusPwr( ON ); | ||
524 | //// regWr( rGPINIRQ, bmGPINIRQ7 ); | ||
525 | //// } | ||
526 | // return( GPINIRQ ); | ||
527 | //} | ||
528 | |||
529 | #endif // _USBHOST_H_ | ||