Logic Analyzer I2C Probe
At the latest hamfest, I got myself another logic analyzer.
Now you'd say "another", well, most people have only one, if they have one at all. Like everything that seems to happen this way, there's a story attached.
It used to be that I was debugging 6502 designs. Now the 6502 processor was what ran the Apple ][, the Commodore, and the Pet. I, of course, had my own custom design. The 6502 had separate address and data busses, and roughly 8 status lines such as read/write; NMI, IRQ, and so on. When debugging a design, I had to either watch for a data pattern on an oscilloscope, or hope that I found what was going on by using an oscilloscope, or failing that, set breakpoints and debug in hardware. Heaven help me if I tried to debug ROM code which could not be modified to have a breakpoint.
That's one reason I got a PROM programmer, to do that kind of project. I have at least 3 now, I just haven't gotten rid of the older ones.
So a logic analyzer would give me the capability of monitoring all the data lines, all the address lines, all the status lines and more. I could set it to trigger on a condition like "processor ran away" or "accessing the problem chip."
I'd have to build it, of course. Logic analyzers were not affordable when I needed one for that. That design got slightly tabled, because it was going to be a complex design, probably have its own microprocessor in it to set up some of the latches and trigger conditions, and it was going to be wirewrap. As I said, complex.
Enter a few years ago when I was still living in Alabama. In my first real ebay foray, I bought a HP 1631D logic analyzer from someone up in Huntsville. While that was about a 2 hour drive, I found that it was closer than not, and I'd be able to check out the analyzer before I paid for it. Nice deal, really.
A word about surplus logic analyzers. While you may or may not be able to find the manuals, the pods are another matter. HP (although there are other manufacturers such as Tektronix) made two varieties of logic analyzer. One type had active pods, which had amplifiers, comparators, and so on in the pods themselves. The other type, a somewhat later design, had the comparators in the logic analyzer, and the pods had only passive components.
While you can probably fake a passive pod, the active pods are another matter. Frequently, these are sold from government surplus, and the mindless minions take the pods, put them in a "wire" category, and then probably throw them away. After all, they're just cables. Without the pods, the logic analyzer is a good source of spare parts. You might be able to do something with it, but I would not bet on getting full bandwidth, etc... The passive pods can be another matter, as we'll see.
So the HP 1631D turned out to be a very nice logic analyzer. You can get two types of analyzer functions, timing and state. Timing acts like an oscilloscope, you have an internal clock and you sample at a regular rate. This produces a time/data graph that looks like an oscilloscope presentation. It's very useful for looking at timing relationships.
The other method is a state capture. This samples the data coming in at regular intervals, but those intervals are determined by an external clock (such as a signal saying that there's a valid address from a processor). The presentation here is mostly a list of values, although the values can be presented variously, depending on the logic analyzer. You can label values.
The 1631D has 16 timing channels, 43 state channels, and very nicely, a two channel digital oscilloscope built in. It's a very nice machine. It can be remotely controlled by an IEEE-488 bus controller (HP made several), talk to a printer over that IEEE-488 bus, and talk to an external disk drive the same way.
Now there's the problem. You see, you can go through and set up the logic analyzer for a particular circuit. You label all the signals, decide what the patterns are to trigger the data capture, and so on...
Now turn off the logic analyzer. Your setups (often 10 minutes worth of work) are toast. They aren't there, because this logic analyzer has no way to store the setup data. We were not amused.
Enter the 9122 disk drive. It's designed to solve just that kind of problem. You can store all the data externally. I managed to trade for one, got it, and other than the drive being somewhat dinged up, I got it to work a little, talk to the analyzer not at all, and basically left it there.
For those of you in the know, there was an assumption I'd made that was completely wrong. We'll get to that later.
Now I had a complex logic analyzer, useful, but not completely. So at the hamfest, I decided (on a whim) that if I found a decent one, I'd buy it. I'd been surfing ebay to see what was out there, and had gotten somewhat of an idea about prices.
So walking by a trailer, what do I see but a nice HP logic analyzer, with a disk drive. I look on the back, IEEE-488 (a good thing), and RS-232 (an even better thing). IEEE-488 interfaces are complex, and I haven't gotten mine up and running yet. Board's made, though. I looked at it carefully, noted that it seemed to have sufficient cables, saw little enough screen burn, and saw that it had a floppy disk to go with the drive, and no manuals. It did have one probe, and they looked to be passive, rather than active. I made an offer, we bargained a bit, and shortly later, I was the proud owner of somewhat of a pig in a poke.
When I got it home (and this was a good hamfest for me), I plugged it in, and watched it boot up. It passed all the tests except the boot test, for I had not put the floppy in yet. Ok, put the floppy in, hit a key, and "system not found", etc...
Well, the system was not on the floppy, so I guess that there was not enough ROM to put the operating system in. (Nowadays, there would have been, you can get an 8 megabyte PROM for not a whole lot. 8 megabytes is a lot of code).
Searching through the internet found that this was an HP 1651B, and HP was kind enough (at the agilent website, which bought the HP test equipment line), to have the operating manual and the service manual (no schematics, though). Even better, they had a ZIP archive of a disk utility and the operating system.
Now I ought to explain that the disk drive was a single disk drive, a double sided double density (720K) non standard Sony drive that is probably going to be miserable to replace if it goes. It also uses the HP LIF (Logical Interchange Format). Hmmm... Not such a good thing.
However, the utility allows me to format an LIF disk, copy files to it, install the operating system (no boot sector needs to be added), and in general, make the logic analyzer happy. I searched for an older laptop with a floppy drive, and ended up digging out an old Hitachi color laptop running Win98. What the heck, it worked.
Back at the hamfest the next day, I looked for 720K floppies, none to be had. Looked for 720K floppies at every major office supply store on the way home, ditto. Managed to find one off in a box somewhere, so that was enough.
Logic analyzer worked just fine, thank you. I later found a number of 720K floppies that I'd been too stubborn to throw away. Most of them formatted properly and are spares.
Now the analyzer (1651B) can save the setups to the disk, and even better, saves the captured data to the disk as well. It'll do 32 channels (total) either timing analysis or state assignable in two groups of 16 channels. The 1650B was the one that did the 80 channels. That's ok, you can do a lot with 16 channels. Besides, I do have the 1631D just sitting there.
So I got one set of pod grabbers with the machine, and one of the little hooks for getting into the circuit. No, unfortunately, the grabber hooks in the 1631D don't fit the pod. While I got enough cables (and even more than I could use, go figure that one out), the cables have a 50 pin IDC connector on the back that plugs into the logic analyzer, and a little passive socket with individual short leads terminating in little sockets. The terminating block is the key here.
The cable is woven, somewhat resistive, balanced for noise and signal transfer, and probably not something that I could replace without a problem. However, I could only use 16 channels directly because the pods had a series resistor (about 90.9K 1%) and perhaps a parallel capacitor with that. The pod resistor forms a voltage divider with the internal resistors in the logic analyzer. Best to see if I can find another one of them.
Now the basic problem that I'd been having is debugging the I2C messages going back and forth between some of the processors. Logic analyzers (and I tried this) do a miserable job with serial data, and a very good job with parallel data. So what was needed was a way to get the serial I2C bus working into a parallel logic enabled analyzer.
Designs
DESIGN #1
The first design was based on a minimalist hardware approach, making use of what I already have. The Mega series of chips from ATMEL (which I use heavily) has TWI (read I2C) hardware built into it. That simplifies the design of the driver a lot, but has one particular disadvantage, it has the chip's address in hardware. You can either respond to a general call, or your specific address. If you want to respond to all addresses, then you're out of luck. Enter the Tiny series of chips. I use the Tiny2313, which had the most inputs and outputs. I migrated from the 90S2313. The Tiny2313 has a USI, universal serial interface, which is programmed to respond to the I2C bus. The determination of that "It's me" is made in software. So the obvious solution was "it's always me".
Wiring the keyboard scanner output pins back to some of the data pins on an existing
board, adding a few jumpers and writing some software seemed to be a plan. Main
problem was, though, that while a start condition on the bus is an event that the
processor notes (and interrupts on), a stop condition may be noted, but is not an
interrupt. I wanted to note start, stop, data, address, and ack/nack conditions.
(I think I covered how the I2C bus works somewhere else.) That would be difficult
with this design.
DESIGN #2
Enter the hardware. I dug out a copy of B2 Spice (the free version, limited, but nice) and put in a design to make sure that the discrete TTL design would work. I simulated certain parts of it, just enough to make sure that the start detector and stop detector logic would behave. I had taken some design hints from the internal (and partial) schematic of the MEGA processors.
I drew up the schematic and started to lay out the board. Lots of TTL chips on a board can be fun. As you've noted in other sections, I design my boards as single sided boards (maximize the bottom traces), then add top traces to finish the design. Since I do not use plated through holes, the design rules are that there is a separate VIA with an eyelet making the connection from top to bottom layers. This has the consequence of making the board use real estate for through connections, but has the advantage of making the board very producible in my garage (ok, etching is on the driveway... drilling is in the lab, design is on the couch. I do shear the boards in the garage, though).
To make the design story more succinct, while the board was very nice using the autorouter and Eagle's design rules, which are optimized for plated through hole design, it was rather miserable using my design rules. This became a reference design.
DESIGN #3
Enter the ineffable GAL. A GAL is short for Generic Array Logic. It's a way of programming a chip at the hardware interconnect level to actually connect gates and flip flops together to make logic. One GAL or PAL (programmable array logic) can replace a number of chips. You can have registers, and/or/nor/xor gates, multiplexers, etc. Very nice concept, and it's the baby brother of an ASIC (Application Specific Integrated Circuit). Oh, and the PAL is often program once, the GAL is generally reprogrammable, a very good thing here.
So I partitioned the design into several GALS, and went from there. First, I started with a 50 MHz oscillator. I needed a source for delay clock since Atmel used one in their designs to delay the data to the start/stop logic.
Now 50 MHz was too fast for what I needed, so I found a 74S74 and used it as a divide by 2 to give me a 25 MHz basic clock. Period = 40 ns. Dividing that by 16 with a 74LS193 gave me a jumper selectable set of periods of 40, 80, 160, 320, and 640 ns. That ought to be enough.
A note on GAL design: I was using the venerable GAL22V10, which is 22 input lines, 10 outputs, all in a 24 pin package. Obviously, you don't use all those input lines at the same time. The main problems with the GAL is that this design (and the 16V8, and the 20V10) makes certain design assumptions that were to bite me later in the design process.
One assumption is that the registers have a common clock. No exceptions, no options. There's also a limit on what you can do with the clock, for instance, I don't think you can invert it in the chip. So you can't use the registers as counters, even though you could create a design that would do that. The design would not "fit" the chip. Actually, that's wrong, you can, but you have to use a state machine concept, which I have no experience with other than theory.
So all the delays had to be with shift registers, which the chip will do. My delay chip, then, is a 5 stage delay for each signal (SDA-data and SCL-clock). Using 3 pins each, I run an internal multiplexer to select the delay from none to 5 stages. The delay clock is coming from the 74LS193, and is jumper selectable there. So I can have any delay from none to about 3 microseconds. That ought to be enough. Now strangely enough, this design for the GAL worked just fine, and is very appropriate for the chip.
The start stop logic is a little different. Start is defined as an illegal condition, and so is stop. The rules of the I2C bus require that the data remain stable while the clock is high. Data is clocked into the chip (is valid) on the positive edge of the clock. Well, the data changes from high to low while the clock is high for a start, and changes from low to high on a stop. The logic is relatively simple, you run the clock to the D input of a flip-flop (74LS74 is fine), and then run the data to the clock pin. The stop logic (74LS74's clock on a rising clock pulse) is fine, the chip only sets on a stop pulse. The start logic needs an inverter in the data line, but that's no big deal. Now the basic logic for the delay generators was this: I wanted to go to a logic analyzer. So I wanted a condition to be present, then have a pulse with a delay between the leading edge and the condition, then let the condition go away. Basically, I wanted the condition, pulse, condition goes away.
The logic here is that I take a shift register, run it from the delay clock, and then look down the chain a bit. Say that there are 4 stages. As the pulse propagates down the shift registers with each delay clock, we decode states. One state is that the pulse has happened after the first second delay clock (minimum delay one period, max two), and if I look at the not output of the next flip-flop in the chain and this second flip-flop, I will get a gate to respond to this. On the next clock pulse, while the first gate is ok, the inverted output will be false. I get a pulse delayed by a minimum of one delay clock, and wide by one delay clock. Doing the same a little down the line, I can reset the data latch with a pulse later in the process. You can see the schematic. This is a common technique.
I wanted to put two of them in one chip, but that was not to be. There's a wonderful thing called a non-buried node in the GAL design. Enough combinational logic, and you steal an output pin for use with that gate output, even though it's run internally only. "Design does not fit"... I was not happy. You want a GAL that can have buried nodes that do not steal from the output pins. The Lattice GALs (manufacturer, long story) do not have this feature. Now Atmel has a series of chips, the AT750 series, which does have this feature.
On the other hand, I have the design tools for the Lattice series (free, and needs a periodic renewal), a programmer (Needham's electronics, but an old one), and best of all, 10 of the things that I bought a while back and have not used. Lattice 22V10B it is, limitations and all.
So after a lot of "Design doesn't fit", I had one chip that was driven by a 74LS74, produced the delays I needed, and was the same for the start and stop logic. OK, so far so good. Other than trimming which delay and how much delay I wanted (realized by reprogramming which shift register outputs went to which gate), that design was just fine.
Now on to the data. Here was the first problem. I knew I wanted a 10 stage shift register. The idea was to clock the 8 bits of the data into the chip and present it to the logic analyzer in a parallel manner. So far, I had a start condition and stop condition tag, a nice "store" pulse that identified that event, and it all worked. The data in the I2C system is followed by a pulse that indicates an ACK condition (data accepted) or a NACK condition (data not accepted). That's a ninth bit. I added a tenth bit to tell the circuit that the data was ready.
So the idea was that (since the clear was asynchronous in the chip), to clear the register at a start condition, load a 1 into the first register, load data, and when the 1 appears at the end of the data chain, tag the data as available, reset the data chain and clock another 1 in. Back where we started.
I didn't use the preset because I thought I could use either preset or clear, but not both. Partitioning this used 3 GALS, one for the shift register data itself, one for the pretag data generator and clock generator, one for the reset logic that generated the clear signal.
The timing diagram shows some of the results and problems. Note the little notch in the clock pulse that was supposed to clock in the extra data bit, the start detect logic was fine, but otherwise, it was a mess.
To make an otherwise long story shorter, it didn't work worth squat. Too complicated and the timing was not really nice. The limitations of the chips were starting to be nasty. You can see the result in the photo of the board after a bunch of debugging. Even though you can reprogram the innards of the GAL, you still have to cut traces to make the additional signals available.
That's the board after I tried debugging it. Not a nice sight.
One next step was to realize that there was a preset available. So I didn't have to generate an artificial 1 for the data input, just preset the first register. Well, that didn't work well either. Main problem is that the clear is asynchronous (happens immediately regardless of clock), but the preset is synchronous (needs a clock). Generating the clock was nasty. Design didn't work.
The killer on the whole thing was that even if I had gotten it to work, the connections to the logic analyzer were wrong, so it wouldn't have worked anyway.
Time for a redesign and a new board.
DESIGN #4
I had the start stop logic working, the delays were working, and the data logic was nasty. OK, somewhere in there I needed to tag the SRQ change, and did (it went into the pretag logic chip). So the main problem was with the synchronous nature of the preset. Enter the 74LS74 and the venerable 74LS164. The 74LS164 is an 8 bit serial in parallel out shift register with an asynchronous clear. The 74LS74 is two D flip-flops with separate clear and preset lines. Just what I needed.
I built a shift register out of the two chips, replacing the 74LS74 section that drove the pretag logic (now replaced) and replacing the GAL with the 74LS164. Simpler design, cheaper, and it works better. To preset the whole shift register, I generate the data tag with another delay (reset logic), which is just another delay after the data valid tag. I use the start detector to also preset the whole shift register train. I do not need to generate an extra clock pulse.
The timing diagram is my sanity check on the shift register logic, it's driven with square waves, so it's going to be a little atypical, but the data goes through as needed, that's the "end of data/TAG" pulse you see.
After a bit of cockpit trouble with the logic analyzer, and a bit of reprogramming to adjust the delays, the design actually works. Playing with the controls of the logic analyzer, (and realizing that the data was available on the negative going edge of the store pulse not the positive edge) gave me a display screen where I could identify the start condition, the stop condition, the potential address, the data, and the ack/nack pulses.
In this timing diagram you can see the start pulse, the stop pulse, and the data tag pulses to the logic analyzer (STORE). The start and stop data tags themselves are not shown. Note that the data register is set (PRESET) on the start pulse and the end of data. That's shortly after TAG goes to a logic 1. Note that this diagram shows the start, data, clock, and stop conditions. You clock the data into the logic analyzer on the falling edge of the store clock. TAG is not going to the logic analyzer.
DESIGN #5
Talking to the Atmel local field engineer, it was suggested that I use a bit banger approach. I did a design with a processor doing the bit banging, and not being able to leave well enough alone, I added a jogwheel, 4 pushbuttons, 3 LEDs, and a 16 character LCD display. I now had a design that (in theory) could not only monitor the I2C bus, but also simulate parts, generate test patterns for the logic analyzer or the I2C bus, etc.
Software has yet to be written for that design, but the board is made. Some small modification are that the bits are wrong going to the display (software fix, next version fixes the hardware), and the power pins are reversed, read the schematic wrong, fixed the library part so it's now obvious which is the pin and which is the shell on the power pin jack.
Here's design #5 as a board, untested except for power on tests. The graphics processor is under the display, inputs are to the right. Outputs to top and left. Jogwheel is at the bottom, and the switches and indicators are below the display. The chip in the middle is the jogwheel processor. This is designed to be self powered and can use either a battery or logic analyzer power, too. It can function as a "dumb" probe, or provide data patterns to the logic analyzer. What else it can do is a matter of programming.
DESIGN 4 rebuild photos
Board drilled and trimmed without feedthrough rivets and parts.
Board under test. The board to the left is the pulse translator board that takes bipolar pulses and makes TTL level pulses out of them. Comparators and line drivers only.
The smaller board to the lower left is a breakout board. I may redesign that, I'm not really happy about the results and the design. It does odd things to the circuit. A direct wire connection, long daisy chain cable, seems to work better. The chip with the gold "data" on it is the replaced chip. It's a 22v10B GAL.
Little better closeup of the board. Dip clips can be your friends... The precision resistors on the right side are part of the voltage divider network for the logic analyzer. On the other side are SMT jumpers. You either put an 8 pf capacitor across them, or short them to drive TTL circuits.
The board could not have fit better, width wise, had I measured. A little machining of the case here and there and we're fine. The two replaced chips are lower right and above the connector. The board could be remotely powered through the terminal strip, or the logic analyzer can power it. It draws about 280 ma or so, and the logic analyzer is good for 600 ma maximum. That'll work here.
The pod, hooked up, and packaged. The logo is printed on photo paper, laminated, and stuck to the box with double sided tape. Hey, it works.
That's all there is for now, other than perhaps adding a shot of the logic analyzer output.