Posts

Arduino USB Host – USB Descriptors.

Get device descriptor trace

Get device descriptor trace

I finished porting USB transfers from PIC C to Arduino C++. There is now a USB class in the repository. Two main types of USB transfers – control and bulk, are implemented. If you want to know more about USB transfer mechanics, take a look at this article. The code was written to work on Microchip PIC, however, the Arduino code is almost identical.

Since we now have tools to talk to USB device, let’s start using them by looking at USB descriptors. In order for sketches from this article to work you need to copy current repository contents ( *.cpp and *.h files ) to a sub directory in your Arduino hardware libraries directory. In addition, don’t forget to supply 5V to Vbus and connect a USB device, such as flash drive or mouse to USB connector of a breakout board.

First sketch demonstrates access to device descriptor. Device descriptor is the first descriptor that the host retrieves from the device during enumeration. The information which host needs is device endpoint zero maximum packet size. In this example, maximum packet size is already set by a function in USB class, called “Task”. In addition to maximum packet size device descriptor contains other information, used during device configuration.


Continue reading Arduino USB Host – USB Descriptors.

Arduino USB host – First programs.

MAX3421E on a protoshield

MAX3421E on a protoshield

I started porting my PIC USB host code to Arduino platform. There is now a repository on GitHub. Right now it contains a single class of functions talking to MAX3421E. This is not enough to support full USB host functionality, but enough to get started. To follow examples given in this article, create a sub-directory in your Arduino hardware libraries directory and copy MAX3421E*.* files from the repository into it.

MAX3421E talks to Arduino via SPI, so you will need Arduino SPI library. SPI uses pin13 – a pin also used to blink LEDs. Some Arduinos even have this LED hard-wired to pin13. My Arduino has it, and it co-exists peacefully with MAX3421E, however, there is no guarantee it will work on others. It would depend on current drawn by the LED. If you have problems communicating with MAX3421E and/or you can’t see SPI clock on this pin with your oscilloscope or protocol analyzer, try to disconnect the LED and see if it changes anything.

Picture on the right shows the final arrangement. The breakout board sitting on top of protoshield is a 3.3V part. Since I’m using 3.3V Arduino Pro from Sparkfun, no level converters are necessary. Look at the previous article for the closeout picture and schematic. The breakout receives power from Arduino.


Continue reading Arduino USB host – First programs.

MAX3421E has arrived.

MAX3421E on a tray

MAX3421E on a tray


I just took delivery on a batch of MAX3421Es from Maxim. They are available for sale in the store for $8.00.

The MAX3421E makes the vast collection of USB peripherals available to any microprocessor, ASIC, or DSP when it operates as a USB host. For point-to-point solutions, for example, a USB keyboard or mouse interfaced to an embedded system, the firmware that operates the MAX3421E can be simple since only a targeted device is supported.

This controller is supported by open source firmware that I’m developing for 8-bit microcontrollers, including PIC18s and Arduino.

Lightweight USB host. Part 6 – introduction to HID.

MAX3421E on a keyboard

MAX3421E on a keyboard

Human interface device AKA HID is likely the most simple class for USB host to interact with. Reports are easy to parse and timing is not critical. In addition to that, HID standard defines simplified variety of the protocol, called “boot protocol”.

Modern USB keyboards, as well as mice, support boot protocol. It was designed to be used by PC BIOS during POST setup. No report parsing is necessary; as soon as device is put into configured state, it’s interrupt IN endpoint starts generating fixed-format 8-byte packet. This packet contains basic information about peripheral events. For keyboard, such packet contains information about modifier keys (control, shift, alt ) plus keys pressed. Mouse would give state of up to three buttons, plus amount of travel in X and Y direction since last poll.

Look at the code, function HIDMprobe or HIDKprobe. This function is called during enumeration to configure device which was just attached. By default, HID peripheral is configured to talk report protocol. In order to change it to boot protocol, host has to send “Set protocol” request with single data byte set to 0. After this is done, device starts generating interrupts( i.e., host can start periodically polling interrupt endpoint for new data.

It is worth mentioning that not all HID devices support boot protocol. Interface subclass set to 1 indicates that boot protocol is supported for this interface.

The first byte in 8-byte packet from a keyboard contains states of modifier keys – Control, Shift, Alt, and Windows. The next byte is reserved, it’s state means nothing to us. Last 6 bytes is a keyboard buffer – it contains so-called HID codes of keys being pressed since last poll.


Continue reading Lightweight USB host. Part 6 – introduction to HID.

Lightweight USB Host. Part 5 – control transfers.

MAX3421E and mouse

MAX3421E and mouse

All data on USB bus is transferred under host control. Even though some transfers are called IN and some other OUT, they all start at the host. There are four types of transfers, the most interesting of which is control transfer. This type of transfer is used all the time in communication with every class of devices. In this article, I give a short description on programming control transfers.

Control transfer consists of three steps( or stages ): setup, data, and status. Some of them carry necessary data in setup packet itself and don’t have data stage at all. Good example of such short request is “Set address” – the information to transfer is just one byte and is sent by filling a certain setup packet field.

Even though USB specification defines several different destinations for the transfer, such as device, interface and endpoint, on the lowest level each packet address consists of two parts – device and endpoint. Some endpoints are IN or OUT only. Other, such as “default control pipe” AKA endpoint 0, are bi-directional. Before each transfer can be sent out, peripheral address must be loaded into MAX3421E PERADDR register.


Continue reading Lightweight USB Host. Part 5 – control transfers.

Arduino USB host – Pre-prototyping.

Arduino USB Host Shield prototype

Arduino USB Host Shield prototype


I have been thinking about expanding ways to use my recently conceived USB Host controller based on MAX3421E. Nice and very popular AVR development platform called Arduino looked like logical target. After quick Internet search, I went to SparkFun to pick up an 3.3V 8 MHz Atmega168 Arduino Pro, a protoshield, and USB to serial cable. After checking that everything works fine together, I populated a MAX3421E breakout and soldered it on the top of protoshield ( see schematic ).

I wanted to make a quick prototype and not worry about level translation for now. Arduino Pro is 3.3V and is able to talk to MAX3421E directly. The circuitry to adapt this shield for 5V Arduinos will be added later. This is going to be interesting since MAX3421E is not only a USB controller but also a port expander. It provides 8 general purpose outputs and 8 inputs, which can be configured as interrupt sources, all accessible via SPI. I’m using 1 input and 1 output for Vbus tracking, the rest is available for general use.

In order to use Atmega’s SPI peripheral I imported SPI library from Arduino playground. The default initialization will work. Below is the quick sketch that I wrote to make sure that MAX3421E is talking. Here I’m defining pins, setting initial state, and configuring MAX3421E SPI to full-duplex mode. This is not the right way to initialize MAX3421E, however, the beauty of this controller is that its SPI subsystem is separate from the rest of the chip and will work in any state as long as power is applied. No fancy resets are necessary.


Continue reading Arduino USB host – Pre-prototyping.

Lightweight USB Host. Part 4 – The code.

MAX3421E breakout

MAX3421E breakout


A couple of updates. First, second prototype for the breakout board arrived from BatchPCB (pictured on the right ). I placed an order for the first batch with PCBcart, it is supposed to be here in 2 weeks. Also, I made this prototype public at BatchPCB, this is the product link. The prototype has a little defect – the USB connector is placed a little bit too close to resistors; however, it’s totally buildable, just make sure you insert USB connector last, when the rest is soldered and checked.

Second, I created a code repository for the project. From now on, all firmware development will be posted there. The hardware files don’t change that often; they will still be hosted here in downloads section.

At present, the code doesn’t do much past enumeration. From USB point of view, it knows how to generate control and bulk-IN transfers; bulk-OUT is going to be written together with mass storage client driver code, which is going to be next big step. Also, it is probably buggy and this is my reason for publishing it – “given enough eyeballs, all bugs are shallow”. If you try the code and it doesn’t work, let me know. Or better yet, fork a code, fix it and let me know what you fixed and why.


Continue reading Lightweight USB Host. Part 4 – The code.

Lightweight USB Host. Part 3 – accessing MAX3421E.

MAX3421E protoboard setup

MAX3421E protoboard setup


In previous article I wrote about ways to build the project. Picture on the right shows one built on a piece of protoboard. The PIC is clocked at 64MHz using internal oscillator and SPI clock is 16MHz. It works well.
I’d like to start describing the code with an overview of a project layout. All project-related definitions are contained in project_config.h file. Types like BYTE, WORD, BOOL are defined in Generic_Types.h, the rest goes to a header file with the same name as .c module.

At present, the code consists of SPI functions, MAX3421E register read/write functions, MAX3421E event handler, and a small CLI used primarily to aid in debugging. SPI functions are explained in Interfacing LCD via SPI article, take a look if you haven’t already. In this article I will be talking about MAX3421E low-level routines.


Continue reading Lightweight USB Host. Part 3 – accessing MAX3421E.

Build responsibly. A new case from an old bottle.

Xbee module case

Xbee module case


My Xbee sensor project is picking up steam. The PIC part of API module is finished, the host part is close to completion. Since Python is new to me, the development is not as fast as I would like it to be, but I’m getting there. In the meantime, I started thinking about converting my coordinator setup, consisting of bare USB board with Xbee module, to something more permanent and professionally looking.

Picture on the right shows the materials. The idea is very simple: drill a 1/4″ hole in the cap, fasten Xbee to the cap using RP-SMA connector, cut another hole in the side of a bottle for the USB cable and screw things together. The whole project was completed in 15 minutes. The all-new Zigbee coordinator is waiting.

Oleg.

Playing Xbee. Part 4 – API.

Setting serial speed on Xbee module

Setting serial speed on Xbee module


Xbee module supports two modes of operation – transparent mode and API mode. To create simple point-to-point links, Xbee works nicely in transparent mode without much coding. However, if your goal is to build a network consisting of more than two devices, AT mode becomes too difficult to bear. You will spend almost all the time switching in and out of command mode, wasting time and draining batteries in the process. On the other hand, in API mode commands and data travel in specially formatted frames and no switching is necessary. Another advantage of API mode is that serial speed on transmitters doesn’t have to match – one can be configured for 115200bps, another for 2400bps, third left with default 9600bps. There is another nice feature called remote command; you can remotely request the state of Xbee module pins, for example, or change an output pin level. It means that for simple measuring and control applications no MCU is even necessary at the sensor.

API mode requires re-flashing module firmware and some extra coding on both sides of the link. I started with upgrading the firmware. Picture on the right shows X-CTU screen with serial speed drop-down expanded – along with loading API firmware I’m changing the speed of coordinator Xbee to 115200.


Continue reading Playing Xbee. Part 4 – API.