With a little research and some USB tracing, I wrote a Windows program — and an Android app — that turns my Fretlight guitar into a BCD mode binary clock!
(Update: I now also have a Raspberry Pi version.)
What Is a Fretlight Guitar?
A Fretlight guitar is a teaching aid for guitarists. It has LEDs embedded in the fretboard. The LEDs are controlled by software on a computer, which is connected to the guitar through a USB cable. The software lights the LEDs to show scales, chords, and songs. Check out this demo if you want to learn more about it.
Why Did I Turn It Into a Binary Clock?
I wanted to know the guitar’s API because I thought it would be cool to control it (not that I knew what I wanted to do with it). When searching I found demos of unconventional uses of the Fretlight: the LED Fretboard Light Show and Conway’s Game of Life on FretLight Guitar. I immediately thought of a binary clock, realizing the six columns of LEDs were a perfect match.
Researching The Fretlight Interface
Optek Music Systems has a Fretlight SDK that’s available by application, but I found open source software that implemented interfaces: Fretlight Animator (the code behind “Conway’s Game of Life”) and TuxGuitar Light Plugin. Fretlight Animator is written in C#, but I wanted something in C++. Nonetheless, the code was well documented, so I had all that I needed to write my own implementation. TuxGuitar Light Plugin, written in Java, was also a good reference, confirming what I learned from Fretlight Animator.
(If you are not familiar with guitar tablature, the lines correspond to the six guitar strings, with the thick string at the bottom and thin string at the top. The numbers are the frets, with fret 0 meaning the open string.)
The USB traffic confirmed what was encoded in Fretlight Animator and TuxGuitar.
The Fretlight Interface
The Fretlight is a simple USB HID. The host controls the status of the LEDs by sending reports to the guitar’s interrupt OUT endpoint. Each report is 8 bytes, with a one-byte report ID (0) and a 7-byte packet. Each packet contains a one-byte packet ID and 6 bytes of LED data. Each LED is specified by one bit: a 1 turns the LED on, and a 0 turns the LED off. With 48 bits per packet, you need three packets to specify the status of all 132 LEDs.
Packet ID 1 controls the LEDs in frets 0 through 7, packet ID 2 controls the LEDs in frets 8 through 15, and packet ID 3 controls the LEDs in frets 16 through 21. Each bit in each packet corresponds to a unique combination of fret and string. Fret numbers range from 0-21, and string numbers range from 1-6, with 1 being the high E (thinnest string). Here is the layout of the LEDs, with ‘f’ standing for fret, and ‘s’ standing for string:
bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 Packet ID 1 Byte 0: f6s5 f6s6 f7s1 f7s2 f7s3 f7s4 f7s5 f7s6 Byte 1: f5s3 f5s4 f5s5 f5s6 f6s1 f6s2 f6s3 f6s4 Byte 2: f4s1 f4s2 f4s3 f4s4 f4s5 f4s6 f5s1 f5s2 Byte 3: f2s5 f2s6 f3s1 f3s2 f3s3 f3s4 f3s5 f3s6 Byte 4: f1s3 f1s4 f1s5 f1s6 f2s1 f2s2 f2s3 f2s4 Byte 5: f0s1 f0s2 f0s3 f0s4 f0s5 f0s6 f1s1 f1s2 Byte 6: (0x01) Packet ID 2 Byte 0: f14s5 f14s6 f15s1 f15s2 f15s3 f15s4 f15s5 f15s6 Byte 1: f13s3 f13s4 f13s5 f13s6 f14s1 f14s2 f14s3 f14s4 Byte 2: f12s1 f12s2 f12s3 f12s4 f12s5 f12s6 f13s1 f13s2 Byte 3: f10s5 f10s6 f11s1 f11s2 f11s3 f11s4 f11s5 f11s6 Byte 4: f9s3 f9s4 f9s5 f9s6 f10s1 f10s2 f10s3 f10s4 Byte 5: f8s1 f8s2 f8s3 f8s4 f8s5 f8s6 f9s1 f9s2 Byte 6: (0x02) Packet ID 3 Byte 0: xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx Byte 1: f21s3 f21s4 f21s5 f21s6 xxxxx xxxxx xxxxx xxxxx Byte 2: f20s1 f20s2 f20s3 f20s4 f20s5 f20s6 f21s1 f21s2 Byte 3: f18s5 f18s6 f19s1 f19s2 f19s3 f19s4 f19s5 f19s6 Byte 4: f17s3 f17s4 f17s5 f17s6 f18s1 f18s2 f18s3 f18s4 Byte 5: f16s1 f16s2 f16s3 f16s4 f16s5 f16s6 f17s1 f17s2 Byte 6: (0x03)
(The unused bits in packet ID 3 are marked with ‘x’s.)
Overview of My Windows Code
I wrote my program in Visual C++ (Visual Studio 2013). I used hidapi as my USB API because it was extremely simple (I turned to it after trying to wade through Microsoft’s HID examples.) I created a project, included files hidapi.h and hid.c, and changed a few compile and link options.
I used calls hid_init(), hid_open(), hid_write(), hid_close(), and hid_exit(). I used hid_open() to open the Fretlight HID, using its vendor ID (0x0925) and product ID (0x2000). (I don’t know why the vendor ID is 0x0925 — that is assigned to Lakeview Research!). I used hid_write() to send packets to the guitar (hid_write() automatically knew to send to the guitar’s interrupt OUT endpoint).
I initialized local variables to represent the current time on my computer, and then set a one second timer. Each time the timer popped I incremented the time, created the packet (packet ID 3), and sent it to the guitar. I used 19 LEDs: f21s6, f18s5, f19s5, f20s5, f21s5, f19s4, f20s4, f21s4, f18s3, f19s3, f20s3, f21s3, f19s2, f20s2, f21s2, f18s1, f19s1, f20s1, and f21s1.
I picked those frets for several reasons:
- The LEDs are spaced about as closely as on my real binary clock.
- The clock is easier to read being up against the last fret (there can’t be any hidden “off” LEDs below it).
- The LEDs are all in the same packet.
I only implemented BCD mode, and only for 12-hour time.
Overview of My Android Code
After writing and debugging my Windows program I wrote an equivalent Android app to run the Fretlight as a binary clock. I wrote it in Java, using Android Studio. I used the Android USB Host API, classes UsbManager, UsbDevice, UsbInterface, UsbEndpoint, and UsbDeviceConnection. I used the bulkTransfer() method of the UsbDeviceConnection class to send HID packets to the guitar. (I modeled my USB code on the USB HID Terminal app.)
To use an Android device as a USB host, it must support USB OTG; this support is in Android 3.1 and higher. You also need a female USB to male micro USB adapter to connect the Fretlight cable to the device. When writing the app, I enabled wireless debugging, since the device’s USB slot was connected to the guitar.
On Reflective Fret Markers
The Fretlight has reflective, circular, LED-sized fret markers, which is a poor design; sometimes they look like a lit LED! See how that plays out in my binary clock by watching the last few seconds of my video (watch when the time turns 10:30:00).