Last July, I experimented with adding Wi-Fi to the Monulator prototype. With Wi-Fi, a Monulator wouldn't need to be plugged in to a PC to retrieve information. So far, it's working great! I have a Monulator that's scraping a NASA Web site every five minutes, indicating how likely it is I can see an aurora borealis where I live. (Sadly, no auroras yet – they're very rarely visible at 45 N latitude.)

Look Ma, no host! The Monulator displays the current aurora Kp index.
Look Ma, no host! The Monulator displays the current aurora Kp index.

The one bummer about adding Wi-Fi to the Monulator is that it's expensive. The Roving Networks (now Microchip) RN171XV module is about $30 US in quantity, which is simply too much. But then I stumbled across the TI CC3000 Wi-Fi module. It'll do 802.11b/g in the 2.4GHz spectrum, for only $10 US in quantity. It's exciting to think I could add Wi-Fi capability to the Monulator for a modest incremental cost!

I got a development board a couple of weeks ago, and have struggled mightily to get the CC3000 to talk with an ARM microcontroller and my Web server. But I have made real progress!

My rig for developing CC3000 driver code -- CC3000 module, LPC11U14 dev board, Black Magic Probe, Bus Pirate, and HackRF (serving as a high-current power supply).
My rig for developing CC3000 driver code – CC3000 module, LPC11U14 dev board, Black Magic Probe, Bus Pirate, and HackRF (serving as a high-current power supply).

The CC3000 does not use a serial/UART interface like most of the other Wi-Fi modules. The CC3000 talks SPI. This is great, because SPI can transfer data very quickly (16MHz on the CC3000). SPI is also transfer-oriented, so sending and receiving commands is (arguably) simpler than managing command and data modes of a stream-oriented API (typical of a simple serial interface). Unfortunately, TI did a very poor job of documenting the CC3000's command protocol. There's some low-level documentation on their CC3000 Wiki, but details about command and response data structures is missing completely. I've had to wade through their "host driver" code to understand the protocol. In that process, I also learned that what TI posted to the Wiki is not always correct (a common Wiki phenomenon). Among the revelations, TI says the SPI interface uses a particular style of clock/data synchronization (CPHA=0, CPOL=0, but the next sentence, the datasheet and this forum post describe a CPHA=1 configuration.

Eventually, I got my own CC3000 driver code working, and was able to communicate with the CC3000 at a basic level. I saww that the firmware on my module was quite old (version 1.7, while the current version is 1.10.1). TI provides sample code for updating the firmware, but it only works for their MSP430 and Stellaris microcontrollers, Windows, and proprietary/closed development tools. That won't work for me, so I ported the patch update code. This was rather scary, as I was sure I'd have a bug in my code and would brick my CC3000 module. At a couple of points, it looked like I had. But it turns out their bootloader and update process is robust, and I was able to back out my applied (and messed-up) patches and re-write them correctly.

I used to debug in a fancy IDE, but these days I like GDB --tui.
I used to debug in a fancy IDE, but these days I like GDB –tui.

Commands issued to the CC3000 over SPI are wrapped in an "HCI" structure, which looks a lot like your ordinary RPC (remote procedure call). On top of the HCI layer, they've implemented an API modeled after BSD sockets. But it seems like their sockets implementation doesn't behave quite the same as it does on a PC. For instance, when I'm connected to sharebrained.com via HTTP, my PC sockets test program disconnects after the HTTP body content is downloaded. On the CC3000 side, I receive no indication that the server has disconnected – the socket is not signaled as closed, and I see no indication via select(). So I'll have to parse the HTTP response header (and I should anyway) to figure out when I'm done downloading. Not sure what I should do if no Content-Length is provided by the server. Time to break out the HTTP RFC…