Tag Archive for code

WiFi Christmas Lights

While looking for something to do with my 3.5″ Insignia Infocast, I came across this post about some controllable RGB Christmas lights: http://www.deepdarc.com/2010/11/27/hacking-christmas-lights/

WiFi-enabled Christmas lights seemed like a good way to test out a variety of things, and hopefully something to show to family members who don’t quite get what I do for work and play (while I’m not sure that WiFi Christmas lights is the best example for this, it fit the season). The result didn’t see any use during Christmas, unfortunately…setting up a Linux machine on a wireless network via the command line is not as straightforward as I’d hoped, so it never got hooked up at my family’s place. I never got around to coding any lighting programs, so only the most basic functionality is actually implemented and tested. But those basics are there: a CGI program that runs on the Infocast (which is essentially a Chumby One, with a 454 MHz ARM processor, 64 MB of RAM, and a WiFi dongle), displaying a web page and sending I2C commands to an AVR Xmega board, which itself is loaded with firmware that communicates with the LED string. A hex inverter is used as a 5V driver for the LED string communications line, and to provide some measure of protection should mishaps occur while wiring things up.

The Infocast main board plugs neatly into a solderless breadboard with the addition of a couple right angle headers to the “mod port”. I used single-row headers on both sides of the board, the header on one side soldered in “backwards” and extended with a straight header to get the needed length and spacing. The result worked quite well:

The lights themselves have simply been modified to remove the original remote control receiver, replacing it with a bit of ribbon cable and a header connector for plugging into a solderless breadboard. This is not ideal…if the connector pulls out of the breadboard, I’ve got exposed pins with 5VDC and fairly high maximum current flailing around near my largely-3.3V Infocast and AVR. It’s far more secure than the first approach, which had the connectors attached straight to the thick, unwieldy light string cables, though:

The long green jumpers are the I2C lines, the small DIP IC is a hex inverter powered off the 5.6 V from the lights and driving the LED comm line. There’s a FTDI USB-serial module that takes up entirely too much board space, but gives a serial console into the Infocast/Chumby One board. The black box underneath is the case and power supply for a dead Ethernet switch, adapted as a base for the protoboards. (someday, I’ll stuff one of the USB-serial modules into that box as well and free up some board space)

The Xmega32A4 board is one of my own design, made with Eagle, boards done by Seeed Studio, and put together with a Home Depot heat gun. A good part of the goal with this project was simply to get an Xmega talking with the embedded Linux devices via I2C, as a general purpose controller/data acquisition peripheral. This turned out to be quite trouble-free, once I figured out that my I2C addresses needed to be shifted by one bit on the Linux side (for those unfamiliar with I2C, some things consider I2C addresses to be 8 bits with the LSB a read/write flag, others consider them to simply be 7-bit addresses with the flag considered separately).

Due to various delays with the toolchain (do not run Bingo’s toolchain build scripts from avrfreaks.net, they have an entertaining failure mode in which they crawl up your directory tree executing “rm -fr *” as they go, and the script maintainers refuse to recognize this as a significant problem…fortunately I was able to restore from a recent Time Machine backup, and am now using an old toolchain until I can build a newer one that works), wireless configuration, and general lack of time, the code is nowhere near a finished product, but here it is in all its hodge-podge, undocumented glory:
xmegaxmas.tgz

ARM GCC toolchain build

I recently needed an ARM toolchain for a Luminary Cortex M3 microcontroller, and found that much of the information out there was aggravatingly vague and fragmentary, or simply out of date. So, to save others some trouble, here’s the process I used to put together an ARM toolchain using GCC 4.5.0, applicable to both Mac OS X and Linux.

First, some notes about my setup…I like to put my entire toolchain in a subdirectory of my home directory…for example, ~/arm-eabi-none/, with an entry like this in a startup file like .zshrc:

    export PATH=~/arm-none-eabi/bin:$PATH

This allows quick and easy swapping of toolchains by just renaming directories. If you’re building a new toolchain, you can just rename the other to keep it around while you test the new one. So, to start with, add a line like the above to ~/.zshrc, ~/.bashrc, or whatever is appropriate for the shell you use. Mac OS X and most Linux distros use bash by default, I prefer zsh. The following will append that line to .zshrc, creating the file if it doesn’t already exist (modify as needed for the shell you use):

    echo "export PATH=~/arm-none-eabi/bin:\$PATH" >>.zshrc

Now, either run “export PATH=~/arm-none-eabi/bin:$PATH” command or start a fresh terminal so your path is set up before continuing, and create some directories in your home directory:

    cd ~
    mkdir arm-eabi-none arm_build
    cd arm_build

To build a GCC toolchain, you need GMP, MPFR, and MPC. These may be already installed on your system, if not, you’ll need to install them. If you use a package management system, that may simplify things. You may also want to install them on your system, or build them specifically for your GCC toolchain. I chose the last approach, statically linking them into the toolchain to avoid disturbing any existing installs and to reduce dependencies on the system.

While we’re at it, lets get some other stuff we’ll need. You’ll also need binutils, gcc-core and optionally g++, newlib, gdb, and openocd.
GMP can be obtained from http://gmplib.org/, MPFR from http://www.mpfr.org/, and MPC from http://www.multiprecision.org/. The versions I used are gmp-5.0.1, mpfr-2.4.2, and mpc-0.8.1. Download and decompress these:

    wget ftp://ftp.gmplib.org/pub/gmp-5.0.1/gmp-5.0.1.tar.bz2 http://www.mpfr.org/mpfr-current/mpfr-2.4.2.tar.bz2 http://www.multiprecision.org/mpc/download/mpc-0.8.1.tar.gz
    tar -xjf gmp-5.0.1.tar.bz2
    tar -xjf mpfr-2.4.2.tar.bz2
    tar -xzf mpc-0.8.1.tar.gz

And the GCC toolchain…pick an appropriate mirror from http://www.gnu.org/prep/ftp.html and do the same for binutils, gcc-core, g++ if you’re using C++, and gdb. I used gcc-core-4.5.0, gcc-g++-4.5.0, binutils-2.20, and gdb-7.1:

    wget http://ftp.wayne.edu/pub/gnu/binutils/binutils-2.20.tar.bz2 http://ftp.wayne.edu/pub/gnu/gcc/gcc-4.5.0/gcc-core-4.5.0.tar.bz2  http://ftp.wayne.edu/pub/gnu/gcc/gcc-4.5.0/gcc-g++-4.5.0.tar.bz2 http://ftp.wayne.edu/pub/gnu/gdb/gdb-7.1.tar.bz2
    tar -xjf binutils-2.20.tar.bz2
    tar -xjf gcc-core-4.5.0.tar.bz2
    tar -xjf gcc-g++-4.5.0.tar.bz2
    tar -xjf gdb-7.1.tar.bz2

(if you’re wondering where g++ went, it untarred into the gcc-4.5.0 directory)
And newlib, from ftp://sources.redhat.com/pub/newlib/index.html. I used newlib-1.18.0:

    wget ftp://sources.redhat.com/pub/newlib/newlib-1.18.0.tar.gz
    tar -xzf newlib-1.18.0.tar.gz

Now, to build GMP, MPFR, and MPC. Again, I’m building temporary copies and linking them statically, you can skip this step if you want to use existing installed versions, or you can install them system-wide instead.

    mkdir gmp-5.0.1/build; cd gmp-5.0.1/build
    ../configure --prefix=$HOME/arm_build/gmp --disable-shared --enable-static
    make; make install
    cd ../../
    mkdir mpfr-2.4.2/build; cd mpfr-2.4.2/build
    ../configure --prefix=$HOME/arm_build/mpfr --with-gmp=$HOME/arm_build/gmp --disable-shared --enable-static
    make; make install
    cd ../../
    mkdir mpc-0.8.1/build; cd mpc-0.8.1/build
    ../configure --prefix=$HOME/arm_build/mpc --with-gmp=$HOME/arm_build/gmp --with-mpfr=$HOME/arm_build/mpfr --disable-shared --enable-static
    make; make install
    cd ../../

There’s some “make check” targets you should run as well to make sure things are working, though I omitted them from the above.

Finally, to the GCC toolchain. First, you need to build binutils, but the version downloaded above is slightly broken. Open binutils-2.20/gas/as.h and change line 241,

    #define know(p)			/* know() checks are no-op.ed  */

to:

    #define know(p)	do {} while(0)		/* know() checks are no-op.ed  */

When compiling this on my 64-bit Mac Pro, I also had to make some changes to binutils-2.20/binutils/strings.c to disable use of some deprecated data types and functions. This was not necessary on the 32 bit OS X and Linux systems I’ve built this on, and I don’t know if it’s needed on 64 bit Linux systems. There’s probably a cleaner way to do it, but I just commented out the relevant branches of the #ifdefs from lines 83 to 96:

    //#ifdef HAVE_FOPEN64
    //typedef off64_t file_off;
    //#define file_open(s,m) fopen64(s, m)
    //#else
    typedef off_t file_off;
    #define file_open(s,m) fopen(s, m)
    //#endif
    //#ifdef HAVE_STAT64
    //typedef struct stat64 statbuf;
    //#define file_stat(f,s) stat64(f, s)
    //#else
    typedef struct stat statbuf;
    #define file_stat(f,s) stat(f, s)
    //#endif

Now, go on and build binutils:

    mkdir binutils-2.20/build; cd binutils-2.20/build
    ../configure --prefix=$HOME/arm-none-eabi --target=arm-none-eabi --enable-interwork --enable-multilib --disable-nls --disable-shared --disable-threads --with-gcc --with-gnu-as --with-gnu-ld
    make; make install
    cd ../../

Building newlib for ARM requires an ARM GCC compiler, but building a full ARM GCC compiler requires newlib. You need to build an intermediate version of GCC using the –without-headers option to let it know it can’t rely on libc headers existing. Also, c++ support is unnecessary for this. Note the different make targets, “make all-gcc” and “make install-gcc”!

    mkdir gcc-4.5.0/build; cd gcc-4.5.0/build
    ../configure --prefix=$HOME/arm-none-eabi --target=arm-none-eabi --enable-interwork --enable-multilib --enable-languages=c --with-newlib --disable-nls --disable-shared --disable-threads --with-gnu-as --with-gnu-ld --with-gmp=$HOME/arm_build/gmp --with-mpfr=$HOME/arm_build/mpfr --with-mpc=$HOME/arm_build/mpc --without-headers
    make all-gcc; make install-gcc
    cd ../../

Next, build newlib:

    mkdir newlib-1.18.0/build; cd newlib-1.18.0/build
    ../configure --prefix=$HOME/arm-none-eabi --target=arm-none-eabi --enable-interwork --enable-multilib --with-gnu-as --with-gnu-ld --disable-nls
    make; make install
    cd ../../

Now that newlib’s built, you can build the full GCC:

    cd gcc-4.5.0
    rm -rf build
    mkdir build; cd build
    ../configure --prefix=$HOME/arm-none-eabi --target=arm-none-eabi --enable-interwork --enable-multilib --enable-languages=c,c++ --with-newlib --disable-nls --disable-shared --disable-threads --with-gnu-as --with-gnu-ld --with-gmp=$HOME/arm_build/gmp --with-mpfr=$HOME/arm_build/mpfr --with-mpc=$HOME/arm_build/mpc
    make; make install
    cd ../../

Now, that’s enough to allow you to compile programs, but you will need a debugger as well. Compile GDB:

    mkdir gdb-7.1/build; cd gdb-7.1/build
    ../configure --prefix=$HOME/arm-none-eabi --target=arm-none-eabi --disable-nls --with-gmp=$HOME/arm_build/gmp --with-mpfr=$HOME/arm_build/mpfr --with-mpc=$HOME/arm_build/mpc --with-libexpat
    make; make install
    cd ../../

Note that libexpat must be specified to get full support for things like memory maps sent to GDB from OpenOCD. Make sure it took…GDB will happily continue the configure and build process without XML support without telling you if it is unable to find or use the library, only giving you a “warning: Can not parse XML memory map; XML support was disabled at compile time” message at run time. You should get the following somewhere in your build output when you do make:

    checking for libexpat... yes
    checking how to link with libexpat... -lexpat
    checking for XML_StopParser... yes

OpenOCD:
I keep OpenOCD separate from my GCC toolchain, again installing it to ~/openocd so I can easily swap versions. You can get the latest release from http://developer.berlios.de/projects/openocd, or check it out of the Git repository with:

    git clone git://openocd.git.sourceforge.net/gitroot/openocd/openocd

The release has the advantage of reliability, but I used the latest version in the repository.

Now you’ll want to configure OpenOCD to use the JTAG device you’re using. If you’re using Mac OS X and one of the common FTDI based JTAG interfaces, you’ll want to install libftdi (http://freshmeat.net/projects/libftdi/) first, and use –enable-ft2232_libftdi. I have not had luck getting the FTD2XX direct drivers to work, OpenOCD will run for a bit and then crash. Run “configure –help” to get a list of other supported JTAG devices. I also had to install libusb, which can be obtained from http://www.libusb.org/.

    cd openocd
    ./bootstrap
    mkdir build; cd build
    ../configure --enable-maintainer-mode --prefix=$HOME/openocd --enable-ft2232_libftdi
    make; make install

You will also need to add OpenOCD to your path:

    echo "export PATH=~/openocd/bin:\$PATH" >>~/.zshrc

Character LCDs over SPI

Character LCDs with HD44780/KS0066U-compatible controllers are a widespread standard in electronics equipment, and are readily available and accessible to the hobbyist. However, microcontroller I/O pins are a scarce resource, and these LCDs use a parallel interface that requires 11 pins for a full implementation of the 8-bit interface. These controllers do have a 4-bit mode that reduces the requirement by 4 pins, and one pin can be saved by hard wiring the display in write mode, but 6 I/O pins must still be dedicated to the display, or at least shared with things that tolerate having the display connected. The big 4×40 displays are worse…these controllers are rather archaic, and each can only handle 2×40 lines. These “4×40” displays thus actually have two controllers, sharing data and control lines but with separate enable lines, and so require 7 IO pins at minimum.

One common solution: the 74595 shift register. This device consists of an 8 bit long shift register with separate output latches…you shift data in, and then latch it into the output registers to update all outputs simultaneously. This is essentially the same hardware used for SPI, and conveniently, the ‘595 can be wired to take input directly from a SPI bus, serving as a primitive port expander. For some reason many people bit-bang the shift register, manually toggling GPIO pins to clock data into it, but the ‘595 is perfectly capable of being driven faster and more efficiently by an AVR’s SPI hardware. 8 outputs is enough to talk to a dual-controller 4×40 LCD with one pin free for a smaller LCD or backlight control, or up to 3 separate LCDs, while only using the SPI bus and one slave select. An example for a single-controller LCD:

The shift register data is transferred to the output latches on the positive going edge of the store clock input. That input thus behaves much like a slave select, the only difference being the behavior when less than 8 bits are clocked in before the rising “deselect” edge…the chip has no “selected” state and will output whatever the last 8 bits on the bus were on the “deselect” rising edge, so make sure not to select it if you don’t intend to write to it. The output enable and shift register clear inputs are active low: the first is tied to ground so that the outputs are always enabled, and the shift register clear input is tied to VCC .

This does come at some cost. An additional part is required, obviously: the shift register itself. The 4-bit protocol is a little more complicated to initialize and use, and takes two SPI transfers for every command to the LCD. Perhaps the biggest drawback is that the shift register is incapable of reading from the LCD. Data can not be stored in the LCD DDRAM, and it is not possible to poll the LCD state, so control is purely open-loop: you must wait for the LCD to process each operation before proceeding to the next. The cost of the ‘595 is a small fraction of that of the LCD though, and readback from the display is generally not needed. And as a side benefit to all this, if the VHC logic family is used, the shift register will handle 3.3V or 5V inputs regardless of the LCD/shift register power supply…no additional translation of logic levels is necessary. With the increasing use of 3.3V parts and the high availability of old but cheap 5V LCD modules, this can be particularly useful.

When prototyping, it also takes up breadboard space, which is nearly as precious a resource as GPIO pins. I made an adaptor board for my 4×40 character module that allows it to be connected via a 5-pin connector (never mind the “screensaver”):

Some people do clever things with RC networks to automatically latch the data in the shift register after a transfer is done, which can save the slave select pin, but I’ve gone for SPI compatibility instead. With the separate slave select, the LCD can share the bus with other SPI devices.

Source code for AVR microcontrollers with SPI ports, using AVR-GCC:
http://github.com/cjameshuff/shiftlcd

More information:
http://en.wikipedia.org/wiki/HD44780_Character_LCD
http://www.fairchildsemi.com/ms/MS/MS-512.pdf
http://www.fairchildsemi.com/ds/74/74VHC595.pdf

Projects

Some JavaScript experiments: (<canvas> tag typically required)

[image:10]

Video gallery

Code

Some random pieces of code that may be of use.

Binary definitions: there is no standard format for binary numbers in C, yet they are very commonly used in embedded programming. This file simply defines preprocessor constants of the form b0101, b11110000, etc. Includes 2, 3, 4, and 8 bit constants, and an additional 8 bit set intended for small bitmaps, used in the bitmap font below.
http://files.arklyffe.com/bindefs.h

8×8 bitmap character font: used to display text on graphical LCDs or POV displays. Requires bindefs.h above.
http://files.arklyffe.com/charfont.h
http://files.arklyffe.com/charfont.c

Driver for HD44780/KS0066U-compatible character LCDs connected through a 74595 shift register via SPI:
http://files.arklyffe.com/shiftlcd.h
http://files.arklyffe.com/shiftlcd.c