Wednesday, May 15, 2013

Propeller VGA-lyzer Part 2

The circuit for this is pretty simple - QX-10 video in one end of a Propeller protoboard, VGA out the other.  There's some resistors to protect the Propeller inputs.  Since the QX-10 sends 12V power down the video cable, I can power the Propeller board on the QX-10 video cable alone (the white connector on the right).

As it turns out this circuit is too simple, because I have the pixel input going straight into the Propeller with no preprocessing.  I accidentally dropped a zero in my back of the envelope calculations about the input data rate.  I estimated the pixel clock to be about 1.44 MHz, which can easily be sampled by a 20 MIPS Propeller core.  In fact the pixel clock is going to be in the 14.4 MHz range, and you need more than 20 million instructions per second to read and store that many pixels per second (you have to burn some of your instructions budget to shift, store, and loop).

There's various tricks I could do with the Propeller to get around this.  Some existing Propeller video drivers use as many as four cores working together to achieve higher video output resolutions than normally would be possible.  I could use a similar technique here to share the sampling load among multiple cores.  However going to such software gymnastics to save on hardware seems like it would make it harder to debug than is worthwhile.  Since there's no penalty for reading in data 8 bits at a time rather than 1 bit at a time, I can get a free performance improvement simply by sampling the pixel data into a 74HC595 8 bit shift register on the front end before consuming it in 8 bit chunks.  This will provide a second tangible advantage over the multiple-cores method:  with a shift register on the front end I can skew the phase of the pixel clock independently of, and more finely than, the microcontroller software instruction rate.  That's important because if you sample pixels at the right rate but the wrong time you'll get shimmering.  Optimizing the phase of the pixel sampling clock with respect to the video signal will get the best picture.

However that will be a future revision of the circuit; rather than make that hardware change immediately, I decided to see what I could accomplish with the hardware I have built.  (Who knows maybe I'll discover an additional tweak or feature I need to make to the hardware, so I might as well find out what I can.)

Although I will certainly need to use assembly language for the final product, I chose to use the interpreted language Spin for preliminary exploration, because it will be easier to debug.  Even though Spin is woefully slow compared to the video data rate, it does still allow accurate and precise wait timing, and there is a trick you can do with precision timing to capture a video frame slowly over time.  The idea is rather than try to capture the entire frame at once, you wait a precise amount of time after the sync signal to capture a certain single pixel from a line, then you have to wait an entire frame to capture the next and so on.  It is slow but it will work for static images.

Speaking of debugging, I also found that an important debugging technique is to have the software toggle one or more pins at certain times in the loops.  For instance originally I tried the slow-capture trick based off the horizontal sync signal, but when that didn't work I suspected my Spin code might be too slow for the 19kHz signal and may be dropping syncs.  By having the code toggle a pin every time it captured an hsync I was able to see with the scope (actually with its frequency counter feature) that indeed the code was indicating fewer hsyncs captured than expected, and it was unstable.

After discovering my Spin code could not keep up with the horizontal sync, I swapped the nesting of my "x" and "y" loops and switched to basing all of my video capture timing off the much slower vertical syncs.  Doing this with only vertical sync is 400 times slower than even the slow horizontal sync way.  I am able to read just one pixel per frame.

I was at last able to capture something from the QX-10 video signal!  Since it takes so long to capture a frame, I tweaked the code to concentrate on just the section of the frame where something interesting is onscreen, oversampled it and blew it up.  The image below is 2x super-sampled and 2x to 3x magnified.  I can't quite be sure, but I believe through the terrible mess of jitter and noise in that frame capture I can make out the message "INSERT DISKETTE".  (The E's are suggestive.)

I'm a little disappointed that the image isn't clearer, but I guess I should be amazed that it even works.  Because what is happening in this picture is that it is taking a single sync signal for the whole frame, waiting a calculated period of time that has to be accurate to an average of 1 part in 160,000, and capturing a single pixel out of hundreds of thousands.

Tuesday, May 14, 2013

Propeller VGA-lyzer Part 1

My first computer was an Epson QX-10, which is an old monochrome green screen 8-bit machine.  The unit I had is long gone, but I picked up a replacement on E-bay some years ago.  I got a good deal partly because it lacked a monitor.  (The QX-10 monitor used a proprietary connector and proprietary signaling scheme, so you can't simply plug in a modern - or even an old - PC monitor.)  I was not too concerned about this, since I had tinkered before with video signals in Earl Martin's Industrial Electronics class at Vo-Tech, including a similar proprietary-video-to-PC-monitor adapter project that was successful, albeit with a different video signal and analog CRTs (now I would use an LCD monitor).

Having occasion to reorganize my home office / lab and to pull this among sundry other computing curios from storage, now is opportune to tackle this video conversion challenge.  Like most of my projects I started off assuming it would be easy and it has turned out not to be so, but I am also learning more than I expected to.

An obvious first step is to make a simple circuit that reconciles the merely electrical differences between the mystery signal and VGA spec, to say nothing of timing, and just hook up a VGA multisync monitor to see if it can lock onto the oddball timing.  In fact this was the approach that worked for the Vo-Tech project many years ago, so that I never had to go on to the next step of dealing with sync timings.  (I think I just had to make a passive R2R D/A circuit to integrate the colors or something, and I passed the sync signals straight through.)  Well I say "worked," actually the first CRT monitor I plugged that Vo-Tech project into self-destructed with the bang and acrid smoke of blown capacitors.  A lesser engineer might have doubted his circuit prototype, but I theorized the problem must be that the cheap, used monitor I'd tried it on couldn't handle the high resolution input and had burned itself up trying.  If I just connected my circuit to one of these brand new, large, expensive monitors that belonged to the school, surely it would work there.  Fortunately for my instructor's classroom budget, I was proven right and it did work then.

For the current project I looked at the sync signals in the scope to figure out what I'd need to do them electrically.  VGA is a positive-sync video standard and I could see in the scope that waveform pattern inverted in the QX-10 syncs, so I ran the sync signals through a TTL inverter chip before connecting them to the monitor.  (For the record you can also easily tell which sync signal is which by looking at the frequencies, but I had a wiring diagram to tell me that too.)  I don't think I'd connected the color signal(s) yet, but if I had I could have used a voltage divider between a resistor and a forward biased diode, since the QX-10 monochrome signal is 0-5V and the VGA colors are 0-0.7V, and I don't care about intermediate intensities just on and off.  However, after I hooked up the sync signals I could see it wasn't going to work; the LCD monitor I used was already displaying the message "Cannot sync to this video mode."  Perhaps LCD monitors have lost the multisync capability good CRTs had, or perhaps it's because I'd connected my prototype up to an old, second hand LCD monitor.  I decided not to bother to try connecting it to my own brand new, large, expensive LCD monitor.

Right, so, onto sync timings, frame buffering, and phase locking!  I will be designing "real" video converter hardware for this after all.  Here's the situation.  Completely opposite to that Vo-Tech project, the big problem with the resolution / sync frequencies from the QX-10 is that they are too slow.  Well actually the QX-10's screen resolution in pixels - 640x400 - is coincidentally the same as a VGA standard resolution, but it does its vertical refresh at the leisurely pace of 45 Hz.  (Normal would be about 60 Hz.)  This in turn makes the horizontal sync frequency lower, and the pixels clock out slower.  Thus even though the number of horizontal syncs per vertical sync is "right", the frequency at which they happen is too slow.

This difference in vertical sync refresh rates makes buffering the entire frame the obvious and really the only option.  See, if it were merely a problem of not enough lines (not enough HSyncs/second), I could buffer one line at a time, and sometimes play back the same line twice in a row to spoof a higher number of horizontal lines than the input really has.  But there's no way to fake it with a vsync mismatch; one can easily see mathematically (45-60=-15 and 45/|15|=3) that every three seconds you'll build up such a deficit of lines that your output will demand a line an entire frame away (and the new one hasn't been transmitted yet).  I am not really an expert on video conversion, but I think I can say if you have a v sync mismatch you must to buffer a whole frame.

That's ok.  This is what I wanted to do anyway.  I need 32K to buffer a whole QX-10 video frame, and my favorite microcontroller, the Propeller, has exactly 32K RAM.  I wanted to be sure I wasn't missing an obvious way to do it with less RAM, so that the premise of the project isn't invalid.  Once I have this working for the QX-10, the Propeller object I write for this might be useful for connecting all manner of vintage computer and video game systems to more modern monitors or televisions.  That's why I'm calling this project the VGA-lyzer.