Thursday, January 9, 2014

Mixing Logic With ISP Circuitry For Programming Firmware

For the LEDgoes manufacturing & assembly stage, it would be desirable to simply secure each board to a programming jig, and the jig would be able to program both chips without hassle or confusion.  This means that we will need to insert a switching mechanism somewhere in between the ISP (in-system programmer) headers and the actual programming pins on the board so only one board at a time gets programmed.  I am quite familiar with digital logic, but don't have a knack for understanding other types of circuitry, so it struck me as a possibility to use some 74-logic to route the signals sent from the ISP to one chip at a time.

The 7400 series of transistor-transistor logic (TTL) gates date back to the mid-1960s, shortly after the invention of the transistor itself.  Some chips in this series provide basic Boolean operations, others are counters or shift registers, and still others are flip-flops and latches (memory).  Over the last 50 years, this series has been tweaked to possess many different characteristics and one can choose optimizations between power consumption and speed, not to mention optimized size and cost.

The first step in this journey was to make a connector to go from my USBtinyISP to the breadboard.  Wiring up a 3x2-pin female header to the breadboard with long, brittle wires that have a tendency to fall out before the rest have been planted in place is tedious.  It requires some patience to set up, and since leaving the equipment in that configuration for more than a few hours isn't desirable (I usually want to do other things with it after a while), I ended up using some spare ribbon cable plus some of my own headers and blank DIP sockets lying around to make my own connector.  After a couple hours of soldering and tedious testing of every pin and its neighbor, I finished this project.  However, I had to cut the male headers on top later on since there wasn't enough clearance between pins to secure the USBtinyISP's header in place.

The custom cable.  No, I do not sell these.

Once the connector was made, I picked a spot on the breadboard for it to go, and planted a 74LS08 (quad AND gate) next to it.  The '08 chip has four "A" inputs, four "B" inputs, and four "Y" outputs.  If A and B are both logic level high (5 volts), then Y will output high as well; otherwise, Y will be low (0 volts).  If any of the inputs are left floating (not necessarily set to logic level high or low), then the Y output will also be high.  Thus, it is important to add pull-up or pull-down resistors to enforce a particular state when the pin is not being driven by the ISP programmer.  You will see which type I chose later on in the schematic.
Looks like fun to try and route!

The quad AND gate is perfect because the ISP utilizes four different signals: MISO (master input slave output), MOSI (master output slave input), SCK (serial clock), and RESET (for synchronization).  It also provides 5V and 0V (ground), but I use an external power source to provide those to the circuit.  Therefore, each of these signals was wired up to each "A" input on one of my '08 chips.  Each "B" input was wired up to a common signal, the chip select.  The chip select consists of an SPDT (single-pole double-throw) switch that can connect to either 5V or ground; the output from this switch goes into all the B inputs on the first '08 chip.  However, this is only enough to program one ATmega microcontroller on the LEDgoes board; since we need to program both microcontrollers on the board, we will need a second '08 chip.  The switch output needs to be inverted to the second chip so that the second microcontroller is not being programmed at the same time as the first one.  Luckily, I happened to have some transistors lying around, and the Internet proved to be a useful guide for constructing a single-input "NOT" gate using one PNP transistor and a few resistors.  I could have used the 74LS04 (6 inverters) part, but it takes up quite a bit of space and provides many more inverters than I need for this application.

With my circuit completely built on the breadboard, I went on to mate the USBtinyISP with my special connector and, alas, it failed to synchronize with the ATmega chip on my board.  Perplexed, I checked on the USBtinyISP by wiring the output from my connector straight to my board's headers using jumper wires, and that worked fine.  I played with various combinations of pull-up and pull-down resistors on the gate's inputs and outputs, and nothing seemed to do the trick.  I checked on the timing of the 7400-series chips, and all the ones I have are designed to typically operate at 50MHz.  This is many times faster than the USBtinyISP operates, and more than 3x faster than even my ATmega chips.  Therefore, it couldn't have been a timing issue; I had to assume it was an issue with the internal circuit.

Not being much of a circuit man myself, I attempted to jettison the '08 with another logic chip: the 74LS373 (octal D-latch).  This chip features eight "D" inputs and eight "Q" outputs.  As long as /OE is attached to ground (since it's active low, hence the slash) and L (the latch) is high, the signals going into D pass straight through Q.  However, once L is set to low, the values of Q freeze to whatever values D had right at the falling edge of the L signal (essentially, the very nanosecond L goes from high to low).  With L at ground, the inputs D can change all day long and never affect the outputs Q, so in essence, this chip is a (comparatively very expensive) form of memory.  For 1GB worth of RAM using standard DIP-socket '373 chips, it would cost you on the order of $100 million, even when buying in bulk from an electronics retailer.  That and I doubt there are even 1 billion of these chips in service or ready to be sold.  DRAM found in computers as conventional "memory" is far more efficient, but would be substantially more difficult to incorporate into this application (plus, it's really the latch behavior we're looking for anyway).

Now, I would need two '373 chips (because unfortunately there's no way to latch only 4 of the 8 outputs at a time), and would wire the switch output to the L pin on one '373 and the inverted switch output to the L pin on the other.  The four ISP signals would be routed into each D, and the output from this gate would be wired from Q into the headers on my LEDgoes panels.  There was just one problem; this approach failed too.  Even when wiring the special connector's outputs directly to my board, that failed.  I panicked, and it was getting late, so I simply called it a night.

Starting fresh the next day, I wired up each signal individually to the D-latch, and left the others passing straight through to the LEDgoes board.  I also found some wiring errors, and after correcting those, I was back on track with successful programming each time.  After hooking up just MOSI, testing it, and then adding SCK and RST successfully into the gate and seeing that programming still worked, I had real trouble with the MISO signal.  Every time I wired this signal from my special connector through the gate, programming would fail.  I tried various combinations of pull-up and pull-down resistors, and even load resistors.  I searched for schematics that might indicate how others corrected this problem, and without knowing what the impedance is on that particular signal compared to the others (and not finding any schematics with the answer), I had an epiphany:

You need all four signals present and synchronized for the ATmega chip to be programmed!

As such, it's OK if we just let MISO go straight through to both chips without passing through the gates first.  Without the presence of the other three signals, any fluctuations on MISO are meaningless.  Heck, even with two pins connected straight to both microcontrollers, it still shouldn't affect their contents anyway.  With this realization, I eliminated the need for a second 7400-series chip, and took the design back to a single '08 (quad AND) chip to do the job.  MOSI and MISO are both going straight through from the USBtinyISP to the pin headers on the boards, and only SCK and RST are getting toggled by the '08 chip.  Two of the gates are controlling SCK, two are controlling RST; and each of those gates receives input from either the switch or the inverted switch signal, thus only one chip at a time is seeing the SCK and RST signals.

Here's the jig I ended up designing.  I'll use the toner-transfer method to produce a PCB (with the top/red layer only) once I get approval from the "this makes sense" committee.

As a future project, it would be nice to ditch the physical switch and substitute that action for something the USBtinyISP could directly control.  What I envision would consist of perhaps an I2C-addressable register that would be set or cleared based on some combination or pattern of signals from the USBtinyISP.  With such a register, I could write a program to bit-bang the appropriate data from the USBtinyISP to switch that bit.  Or, perhaps I could use the GPIO pins on the Raspberry Pi to provide the whole feature set I need.  Once the electronics are done, I would write a script that incorporates the appropriate avrdude commands to write the firmware and check for validity of the output.  AVRdude outputs error messages when appropriate, but if it's something like a "Byte mismatch at 0x308: 0xFF != 0x37", then I tend to miss it (since it's not highlighted a different color on the terminal) and continue to work with the board, wondering why it's screwing up.

The circuit in a form that actually works.  Only MOSI & RST are going through the AND gates.

No comments:

Post a Comment