I’m always on the lookout for a quality addition to my lab that would respect my strict budget. Recently, I’ve found myself pushing the Hertz barrier with every other project I do and hence desperately wanted a high bandwidth scope. Unfortunately, only recently have 70 MHz to 100 MHz become really affordable, whilst a new quad channel oscilloscope in the 500 MHz to 1 GHz range still costs a fortune to acquire. My only option was to find an absolute miracle in the form of an old high bandwidth scope.
It seemed the Gods of Hand Me Down electronics were smiling upon me when I found this dumpster destined HP 54542C. It appeared to be in fairy good shape and was the Top Dog in its day. But something had to be broken right? Sure enough, the screen was clearly faulty and illegible. Want to know how I fixed it? Four letters: FPGA.
Some shallow research on this scope revealed some interesting history. This was supposedly HP’s first high end scope with an LCD and was also the precursor to the Infiniium series of scopes that would go on to rule the market. The LCD did feel like an afterthought though. The scope had an otherwise identical variant with a CRT display, and the version I acquired simply had the CRT guts removed and a colour LCD installed by HP. I hoped the LCD was at fault and not the ASIC’s driving it, this seemed like a good bet as a gentle tap would sometimes bring the screen back to life!
I began investigating the root cause, and started by taking apart the LCD. I found some liquid had been spilt all over it; nothing had corroded, but cleaning and reinstalling did not make any difference. Reuniting the scope with the dumpster wasn’t an option, because apart from the LCD, the scope felt like an absolute treasure trove. Even though the LCD’s driver board was completely useless now, it came from a time when the industry had not yet moved onto subatomic pin pitch on wire-to-board connectors. This meant I could conveniently solder on a standard 26 pin ribbon cable to tap off all the required signals and begin the process of reverse engineering the protocol in use.
Reverse Engineering the LCD Protocols
The first step of the process was to determine the signals on the connector. I was on the look-out for the most generic set of signals required to drive any LCD. This must include a few strictly periodic signals, a couple somewhat random signals and ofcourse the usual power and ground. The periodic signals would most likely be the pixel clock and the synchronisation signals which would mark the start of a new line and frame; on the other hand the random looking signals would be the actual pixel data to be displayed. Judging by its age, a fairly simple protocol was expected. Guided by this intuition I began probing the connector and soon enough I had all 25 signals figured out.
I only found two perfectly periodic signals: one, a relatively low 31.25 kHz signal gated at a suspicious 60 Hz, and the other a 25 MHz square wave. The former had to be a combined synchronisation signal. The 60 Hz was a dead giveaway as it corresponded to the nominal frame rate. The 31.25 kHz underlying signal must then correspond to the horizontal line rate within a frame. Finally, the 25 MHz signal had to be the clock for the whole system, in fact it was the pixel clock.
Next, I had to make sense of the random-looking signals which were evidently the pixel data. Firstly, the need for a 25 pin connector was clearly alluding to some kind of parallel RGB configuration. In total I found nine such signals which perfectly divides by three and concluded that the LCD was using nine bits per pixel and three bits per colour channel R,G and B respectively.
Figuring out the scheme and pin-out was part of the challenge. Perhaps more important was determining the the timings of the signals in use. Almost always, raw display signals have what are called “porches”. These can be thought of as regions within each frame where data cannot be written. These originated in the days of CRT where the physical beam of electrons took time to sweep from the end of a line back to the start of the other, or even from the bottom of the screen to the top. Although less pronounced in modern electronic screens, these regions still exist because the LCD controller takes time processing and shuffling incoming data.
Determining the timings
To extract the timings I tried to correlate the pixel data with the synchronisation signals. I was looking for any regions where the pixels were consistently unasserted.
After staring at the data for a while, it was clear the LCD was using a simple, single porch scheme on both the horizontal and vertical portion of the combined sync signal. This was easy to determine because the pixels were set to either all high or all low during this period. Once I had pinpointed these regions, I used the cursors to measure their duration and translated that time to an equivalent number of pixels.
This was a critical piece of information that would ensure a stable and correct reproduction on the VGA monitor. The plan was to feed these values as constants into Verilog, and use counters to “trip” the corresponding logic to achieve the required waveforms.
Lastly, the LCDs’s resolution had to be determined as I would have to run the replacement monitor at the same settings. This was done by simply measuring the various active periods and comparing them to other signals such as the pixel clock that had a period 40 ns. The horizontal active time was measured to be around 25.7 us, hence constituting of a total of 642.5 pixels and similarly the vertical active period was 15.42 ms and with a horizontal period of 30 us, that corresponds to 481 lines. Clearly this was a standard 640 x 480 display with a refresh rate of 60 Hz.
Finding an able substitute
So the existing display turned out to be pretty ordinary in the end, and a replacement seemed entirely plausible. Unfortunately, the size was a bit odd; it’s easy to find seven-inch screens but eight? Even though I could not find any reasonably priced drop in replacement on the web, the size just happened to be the same as that used by many modern after market LCD installations on cars. These are nice cheap “EYOYO” branded monitors (£50) and accept literally all forms of video input from all Analog to VGA and even HDMI. They also support a much higher resolution of 1024 * 768. I’m surprised this screen is not massively popular within the Raspberry Pi community.
Finally, everything seemed to be clicking together. Not only could I replace the LCD with this VGA monitor, it would fit in perfectly as the scope even had enough room for a CRT!
So exactly, how does one perform the LCD to VGA conversion? With an FPGA of course!
At this point the only thing standing between me and a functioning 500 MHz scope was successfully convert the aforementioned LCD signals to VGA. It was clear such relatively fast processing could only be done on an FPGA, but which one? My intention was to, at some point, leave the FPGA inside the scope with the screen, so I needed something small and cheap. Luckily, eBay seems to have a ton of these old Altera Cyclone II based development boards for a mind boggling £10! These are rather capable FPGA’s, hosting about 4K logic elements and ideal for a small scale project like this.
A common way these display conversions are performed are using frame buffers. The idea is to buffer a whole frame, perform the conversion and spit it out at the other end. Unfortunately this calls for a decent sized external RAM on the FPGA. These FPGA boards are notorious for not having any external RAM, hence this scheme was out of the question. After a bit of thinking, I came to the realisation that the LCD signals and VGA were not that dissimilar after all. What if I could convert from one to the other on a line-by-line basis, and circumvent the need for a frame buffer at all?
- A Pixel clock
- Combined synchronisation signals
- Front porch only
whereas VGA has:
- No Pixel clock
- Separate synchronisation signals
- Front and Back porch with a Synchronisation period
Going into detail of how VGA works is beyond the scope of this article, but I’ll fix that later. For now, if we simply inspect the timing sketch, we see that the only difference between the two signals is the number of occurrences and locations of the porches and the placement of valid data.
The sketch makes the conversion look simple but is only valid if the two frames are in complete sync. To tell the FPGA to start produce a corresponding LCD frame over VGA, we must first determine the start of a new frame coming from the LCD connector so that we could sync to it. This is perhaps the trickiest part of the process, because merely examining the edges of the combined synchronisation signal from the LCD is not sufficient.
We must instead measure the time between two edges and flag the occurrence of a new frame. The rest is a relatively straightforward set of logic gates that produces the above timing diagram. Lastly, as the LCD does not have a back porch or sync pulse, the incoming RGB data must be offset in time using a tiny FIFO so that it aligns up perfectly where the VGA monitor expects it. Once translating the above into Verilog was completed, I proceeded to deal with the hardware.
The hardware setup was luckily very minimalistic. HP was not quite utilising the LCD to its fullest potential. Inspecting the individual bits of each channel revealed a lot of redundancy: the various bits were almost always identical, indicating a very shallow utilisation of the full nine-bit colour palette. This was not shocking as HP was mostly reusing firmware from the CRT version of the scope. All of this meant that I got away with just hooking up the MSB of each colour channel with almost no loss in the final image. This saved me even more precious memory on the FPGA.
The biggest problem was that the LCD was using 5 V TTL signals. The FPGA can accept at best 3.3 V signals so level conversion had to be performed. I decided to leverage the input clamping diodes in some of the 74HC series logic buffers to perform this conversion. This tends to ruin rise/fall times significantly though. For example the 74HC4050 even has polysilicon resistors in series with the diode in the die, displacing the need for an external series resistor. I played it safe and added 1 kΩ series resistors to the input of these buffer and the output of was fed into the FPGA. The output of the FPGA’s HSYNC and VSYNC outputs were hooked up directly to the monitor whilst the RGB lines were connected via 330 Ω resistors.
After taming the 25 MHz pixel clock to behave on a breadboard and hooking up the FPGA to the new external
monitor’s VGA port, the scope was restored to its formal glory! Although everything worked perfectly, this setup was quite noise-prone. All I need to do now is make a PCB and grant the VGA monitor a permanent residence inside the scope.
So what’s next you ask? Well, currently the only way to save screenshots is via an outdated floppy drive. But since we have now have the LCD data going through an FPGA, why not write that to an SD card?