TL;DR
With regards to the USB host library:
- Which is the correct file to modify the Arduino pin used for the USB Host slave select (SS) line?
I would like to add USB host functionality, to a particular Arduino setup, whilst, also, being able to use an Ethernet/SD (or just SD) shield.
As both the Ethernet shield and USB Host shield use pin 10 to select the W5500 and MAX3421E respectively1, obviously I can not use a standard USB Host shield. However, I could employ one of the small form factor boards, such as the USB Host Shield 2.0 Arduino UNO MEGA ADK Compatible Google Android ADK which I found on eBay:
As this board is not in the usual shield "shape", one would not be constrained by which pin to connected to which MAX3421E input/output, in particular the chip select (SS) input. So, one could use a pin (or pins) that is not reserved by the Ethernet shield.
However, it does not appear to be possible to simply specify the "select pin" (i.e. the Arduino pin connected to the SS line) when using the USB Host shield library (or any of the pins used by the library), in setup()
.
Therefore, I wondered if it was possible to modify the library, so that the pin used to select the USB/MAX3421E could be changed, either by:
- "Hardcoding" a different "select" pin number into a header file;
- Adding an argument to the
Init()
method, or; - Adding a method to the
USB
class, such asUsb.DefineSelect()
.
The latter two options, I could work through, given the time. However, as a quick and dirty hack, where would I hardcode in a change from pin 10 to a pin of my choosing? Does anyone know? Has anyone had to do this?
Nitty-gritty
I have had a look through the library to see where pin 10 is defined as the chip select, and avrpins.h looked like a possible candidate for modification, although it would be rather "rude" (for want of a better word) and probably mess up the other boards.
usbhost.h seems a much better proposition. Looking at usbhost.h, the lines 88-91:
#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi;
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;
Looking at the statement
typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;
the last argument appears to be the pin used for select. For the Uno (ATmega328P), in avrpins.h (line 535) Pb2
is P10
(pin 10), so I could substitute Pb2
for some other pin definition, i.e. Pd5
for P5
(pin 5) (line 529 in avrpins.h).
However, what I don't understand is that for the statement
typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi;
which deals with the Mega (ATmega2560), in avrpins.h (line 512) Pb0
is P53
(pin 53). As Pb4
is actually P10
(pin 10) (line 466), why is Pb0
en lieu of Pb4
used? That doesn't tie up with the fact that Pin 10 is used for both the Uno and Mega boards. It seems to suggest the pin 10 is used on the Uno and pin 53 is used on the Mega. Unless I have misinterpreted the typedef
.
Footnote
1 For the USB host shield, from Arduino USB Host Shield
Arduino communicates with the MAX3421E using the SPI bus (through the ICSP header). This is on digital pins 10, 11, 12, and 13 on the Uno and pins 10, 50, 51, and 52 on the Mega. On both boards, pin 10 is used to select the MAX3421E. Pins 7, 8 and 9 are used for GPX, INT and RES pins.
The key piece of information here is that pin 10 is used by both the Uno and Mega boards.
For the Ethernet shield, from Arduino Ethernet Shield V2
Arduino communicates with both the W5500 and SD card using the SPI bus (through the ICSP header). This is on digital pins 10, 11, 12, and 13 on the Uno and pins 50, 51, and 52 on the Mega. On both boards, pin 10 is used to select the W5500 and pin 4 for the SD card. These pins cannot be used for general I/O. On the Mega, the hardware SS pin, 53, is not used to select either the W5500 or the SD card, but it must be kept as an output or the SPI interface won't work.
Note that because the W5500 and SD card share the SPI bus, only one at a time can be active. If you are using both peripherals in your program, this should be taken care of by the corresponding libraries. If you're not using one of the peripherals in your program, however, you'll need to explicitly deselect it. To do this with the SD card, set pin 4 as an output and write a high to it. For the W5500, set digital pin 10 as a high output.
Here, yet again, the key piece of information here is that pin 10 is used by both the Uno and Mega boards to select the Ethernet.
typedef
for the Mega board bePb4
and notPb0
?" Maybe I need to recheck my understanding of the code, in the morning.typedef
s that I found inusbhost.h
are not what I should be looking at.