Friday, 2 January 2015

Logically seeing in the new year

My awesome other half got me an 8 channel 24 MHz "Saleae Logic" USB analyser for xmas. This (cheap clone) device seems to work well with the Saleae software Version 1.1.34 (beta) and detected immediately under Linux Mint 16 Petra.

Having never used a logic analyser (or oscilloscope) before, the first thing I did was hook it up to the 25L1605D on the animal card reader board. This unofficial Saleae device doesn't come with the nice E-Z Hook connectors that the official Saleae Logic comes with, so I bought these. They're possibly not as grippy as the E-Z Hooks, but they seemed to do the job. It is however a bit of a squeeze fitting them on the PCB mounted chip in the Animal Card reader.

So. Much. Cable.
The datasheet for the 25L1605D shows that it is Serial Peripheral Interface compatible. I'm pretty new reading datasheets, and I was really hoping that the listed clock speeds of 66/86 MHz were going to be maximum values. I was hoping that the toy was cheap enough that the micro-controller would be clocking the bus significantly lower.

Saleae recommend sampling SPI at least 4 times faster than the clock rate. This means the maximum clock I could hope to sample would be 6MHz - which is quite a lot less than the values in the data sheet.

I wired everything up, configured the Saleae software to record 10 seconds worth of samples at 24 MHz, hooked up the channels to the appropriate SPI signals, pressed "Start" and precariously swiped the card through the reader to trigger the sound. The recorded data successfully decoded as SPI, but subsequent recordings of the same card were producing different results. Also, the clock signal was very irregular.

Huge gaps between clock cycles...doesn't look good
Since I was using the same animal card each time, would have expected to see the same data retrieval from the flash each time in order to produce the same sound. Since this wasn't the case I assume I have one of two problems:

  1. The SPI bus on the animal card reader is clocked higher than 6MHz (which means I can't use my new logic analyser to spy on it), or
  2. My IC hooks are interfering with each other/shorting
To confirm number 1 I would have to track down a tool that can sample at a higher rate. Unfortunately I don't own an oscilloscope or a faster logic analyser, and since I'm on holidays at the moment, I can't access these at work. I could eliminate number 2 by soldering on some pigtails and attaching to the pins that way, but to be honest, I'm pretty sure the issue is number 1 (also I'm terrible at soldering).

UPDATE: I bought a soldering station and soldered on some pigtails to the SPI pins on the flash chip but still had similar results using the Saleae software. I then decided to take it into work and get one of the guys to log the SPI bus using the sexy new 4 channel Agilent scope. Clock speed is 16 MHz so, as expected, there was no chance of getting this to work with the 24 MHz logic analyser. 

So what's a girl to do? I'd need another project in order to play with my new Logic analyser.

Enter my mate Kev to the rescue on New Year's eve - equipped with his NeoPixel ring project (and beer).

Kev is in the process of making an abstract wall clock using the NeoPixel LEDs and an Arduino. He's using this library to configure the pixel ring to show the time using various colours and patterns. The datasheet for the chainable/programmable LEDs can be found here.

Kev's setup uses a single data pin to program the chained LEDs so we simply hooked up the Saleae analyser to his breadboard and recorded 10 seconds of traffic on the single wire bus. We had no idea what the protocol was - and both being noobs, we spent a while messing with various protocols in the Saleae software before retiring to board games and festivities (oh and not ignoring our significant others due to technology distractions).

The next day I decided to approach this properly (soberly).

According to the data sheet, each LED's controller will remove 24 bits from the data stream, interpret that as the green, red and blue (in that order) intensities for itself and pass the rest of the packet onto the next chip in the chain. The signal is self-clocking, with a rising edge indicating the start of a bit and the timing of the falling edge indicating whether the value is a logical 0 or 1. Each new transmission is preceded by a reset period.

In the Saleae software, it looks a little something like this:

Despite the fact that the protocol is pretty basic, I could not work out a way to interpret it with the inbuilt analysers in the Saleae software.

In order to cater for these situations, Saleae offer a C++ SDK for writing your own analysers. Just make sure if you are using the Beta Logic software, you remember to grab the Beta analyser SDK. You get some crazy core dumps if you forget to do this :)

A custom analsyer consists of 4 main parts:
  1. A class that knows what settings are required to be configured by the user (e.g. which channels map to which parts of the protocol, baudrates, etc)
  2. A class that knows how to generate simulated signals
  3. A class that knows how to display and write to file the decoded signals
  4. A class that knows how to decode the signals into frames and packets
The 4 classes get compiled into a dynamically linked library using the provided python script. You then just tell the Logic software where to look for additional libraries in Options -> Preferences -> Developer.

There are some great PDF instructions included in the API download that walk you through the whole process of compiling and modifying the core classes to implement your analyser. I found it useful to implement the classes in the order suggested and use gdb to diagnose any issues along the way.

It took me a little while to work out how to "call" the generator code, but it is actually quite simple. If you run the Logic software without a device connected, the big green start button in the top left of the "Capture" tab is actually a "Start Simulation" button. If you have your new analyser loaded on the right hand side, it will call your generator code with the current capture settings (i.e. sample rate and time, etc).

Once I had everything working with the simulator, I was able to load the data we captured on New Year's eve, decode it and write it to file. As usual, you can find all the source code on github