A trip to Vetco yield three 34-pin IDC connectors and some ribbon cable. I built a nice & short cable, hooked it up, and the lights worked normally. So that is good.
The signals from the logic analyzer looked a little better, and I was able to make some measurements.
All the pulses are negative, which is expected because TTL is much better at sinking current than sourcing current.
The pulse width is 360nS. If that is one clock-tick wide, that means things are running at 2.78 MHz, which is pretty much as expected. The delay between the row/column strobes is about 2mS.
Let’s do some math:
At 16 MHz, the clock cycle time is 62.5 nS, which means I would have less than 6 clock cycles to respond to the interrupt and read the data values. My online reading has showed that the AVR needs at least 8 cycles just to *start* executing my interrupt vector, which means using interrupts to read the data directly isn’t going to work.
At which point we step back and analyze the options.
- Go with a different microcontroller. An arm-based solution running at 100+ MHz would probably work.
- They make buffer chips for a reason – just use them, and things will be great.
- Use polling
#1 sounds more complicated than I want to get right now. #2 would obviously work, at the cost of some additional external circuitry. My first reaction to #3 is “yuck yuck yuck”, because polling is rarely a clean solution, and it would probably be a bitch to get my logic plus I2C/ USB to work at the same time as polling. However, if I was willing to burn an extra AVR, I could probably build the bus-reading part in one and then use another one for the process & communication. Still yuck.
So, it looks like buffer chips are the simplest part. The driver board uses a 74LS374, which is an octal D-type positive edge-triggered flip-flop. When the clock signal goes from low->high (ie at the end of the strobe pulse), it grabs the current values on the inputs and saves them into the outputs, which could be read at our leisure.
So, just put one of these in-line with the data, hook it up to the strobe, grab an interrupt from the strobe, and then the data will be ready and waiting when we need it, right?
Well, that will work, but I need to get both row and column data out. If I use two buffers, that uses 16 input pins, plus two for the strobe interrupts, plus two for communication, which means 20 pins total. Which is precisely the number of pins on an arduino, so it will work, but with with no room for bells and whistles, which I much confess a certain fondness for.
If I come up with a way to combine the strobes, I can use a single buffer chip. What I want sounds like an OR operation, but remembering that the strobes trigger negative and spending a few moments with truth tables, it turns out what I really want is an AND; it will be high when both inputs are high, and will go low when either input is low.
And… that’s not going to problematic. The flip-flop is triggered on the rising edge which is right at the end of of the pulse. If we put a gate in front of it, we add a propagation delay of something like 20-50 nS, and we might miss the data.
Is there an alternative? Well, yes, there is. The 374 has an output enable input. Pull it low, and the chip will drive the outputs. Drive it high, and it disconnects the outputs. That will let us parallel two of the 374s and enable the one that we want from the Arduino. Works, but that is going to be a whole bunch of data lines and is going to make the circuit board layout interesting.
So, that’s where I am right now, but I’ve asked a few people if there are better alternatives.
There were a number of different faster microcontroller suggestions. There are a few that look workable – and I am professional at software and amateur at hardware – but I’m not excited about spinning up on a whole new toolchain.
On the hardware side, it turns out there are some better choices. A couple people suggested a 74HC165 as a nice choice, as it lets you read the data out serially. Slower, but with 7 less lines and the PCB routing in my head was already getting pretty bad. But… that chip both clocks in and clocks out on a master clock, which doesn’t work for what I need.
Enter the 74HC595, which has separate clocks for the store and read operations. It’s a tiny bit inconvenient in that it’s modal – you have to control whether it’s in “load in parallel on load clock” and “read out serially on read clock”, but it’s still simpler. I can only find it in SOIC, so I ordered some adapters from adafruit to go along with it. That, and some nice connectors for the ribbon cable. BTW, that thing that you put on the end of a ribbon cable is not called a “connector”, it’s called a “female header”. I have the usual digikey exasperation until I figured that out.
When that all shows up, I can breadboard the hardware, and then start on the software. The matrix decoding seems pretty straightforward to implement, but dealing with flashing lights looks to be challenging. While I could just send out a state change whenever a light turns on or off, it would be more convenient if I could just say that a specific light was on, off, or flashing. I have to do flash detection somewhere because I need to detect the difference between flashing and on for some things I want to do.