]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhost.h
lufa: usb-usb: Use LUFA startup instead of cusotom
[max/tmk_keyboard.git] / tmk_core / protocol / usb_hid / USB_Host_Shield_2.0 / usbhost.h
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_