PowerBook reverse engineering for fun and no profit

(Drafts don't always save on here...I don't know if there's a maximum size or what, but I guess now this post is extra-refined.)

With Omaha2 complete, I moved on to capturing signals from GSC, starting in passive-matrix mode because I can use my singular display panel at the same time I'm running the logic analyzer. I made a few test programs that call SetDepth (to simulate choosing a color depth in the Control Strip) and write to the framebuffer in various repeating patterns. For anyone doing this in the future, make sure you have the system set to 32-bit addressing, or the OS will step in and rewrite the framebuffer with parts of windows while your program is running. The first, most notable thing about GSC is that it formats its output quite differently from passive-matrix mode Omaha2 (this is in 4-grey mode):
1781659454279.png
Instead of a continuous stream of byte clocks (CL2) with line clocks (CL1) at intervals, bursts of CL2 pulses are evenly spaced and ended with CL1 pulses, with just...nothing between them. FLM_F is also much longer, starting a few cycles into a block of CL2 pulses and lasting until the end of that block, and M_F is always high, instead of alternating.

I noticed that the first bits on D7-D4 of the line synchronous with FLM repeat every 4 lines. There are still 32000 CL2 clocks per frame, and 160 per line, they're just spaced differently. In hindsight, the explanation for this should have been obvious, but I didn't put the pieces together. In fact, I got so stumped that I went and Googled the screens.

If you Google for the Sharp LM64P51 or LM64P58, you get absolutely nothing except vintage Apple threads. If you Google for the Hitachi LMG5200, you get one result. From this result I found some leads that took me to lots of other Hitachi and Sharp monochrome passive matrix displays, all 320x240 or 640x480. The most enlightening of these was the Sharp LM64P839, whose datasheet I'm attaching here for the curious. From this datasheet we glean a lot of information: not only was I correct about the data format, but the dual nibble bus is actually a de facto standard! These are dual-scan passive-matrix displays, which means that two parts of the display are scanned at one time, just as I discovered. Here's the block diagram from the datasheet:

1781659961665.png
The data bits are called DU0-DU3 and DL0-DL3, for "display upper" and "display lower". The M signal is also internally generated (which explains why GSC doesn't send it), and is apparently used to prevent DC voltage from building up inside the liquid crystal and causing damage. Sharp calls the row drivers "COM" and the column drivers "SEG", which explains why the silkscreen on my LM64P58 says "STAB" and "CTAB" (though I don't know what "TAB" is for). Presumably GSC does send M when it's in active-matrix mode? We'll find out.

We also learn that FLM, which Sharp calls "S" but Hitachi calls "FLM", stands for "first line marker". The waveform recommended is:

1781660295902.png
and this exactly matches what we see. This waveform specification is identical between different manufacturers and different models, which explains why all the display revisions are electrically compatible.

At this point I realized what I was seeing on the logic analyzer. GSC is dithering the display by alternating pixel states between frames, so that the state of each greyscale pixel averages out to somewhere between on and off. We can confirm this by looking at some pixel data from a program called GreyScreen4GreyOneColor, which sets the whole screen to the byte 0x5f = 0b01_01_11_11, or two pixels light grey and then two black. With this, we see these values sent for the first 4 pixels of four consecutive frames:
D71000
D60010
D51111
D41111

This is obviously a dithered signal. For dark grey (0b10), two out of four frames are 1 and the others are zero. Clearly GSC's dithering algorithm has some complexity, because not only are adjacent pixels' dithering offset from one another, even when they're the same color, but it seems to intentionally not use some on-off combinations (3/4 frames set to 1 just isn't used, in this case).

GSC expands this for 16-grey mode by dithering across a 16-frame interval. It behaves the same otherwise. In each of the three color depths GSC supports, it changes the frequency and timing of the signals it generates. 4-color mode and 16-color mode behave the same as 4-grey and 16-grey mode, respectively. The display datasheets I found recommend certain frame clock frequencies for ideal monochrome results (minimal flicker, highest dynamic range, etc), so presumably GSC is using what Apple determined as the best timing for each mode. Here's the specs, measured on my oscilloscope:

Black and white: 61.0094 Hz FLM, 12.2019 kHz CL1
4 grey: 87.0400 Hz FLM, 17.4080 kHz CL1
16 grey: 119.415 Hz FLM, 23.8829 kHz CL1

I actually think that black and white mode looks a little flickery, but that might just be me. The CL1 frequency determines the amount of dead time between blocks of CL2 pulses, and in 16-grey mode there's almost no time between them. The period of a CL2 pulse is independent of the selected pixel depth, and one block of CL2 pulses is always 40.80 us long.

GSC also has registers, located at 0x50020000 in 32-bit mode, which is new since Omaha and Omaha2 were fully autonomous. These can be read by the CPU and mirror every 32 bytes. One byte near the end appears to be some kind of counter, and a few others change depending on the display mode selected. Other than that I have no idea what they do.
 

Attachments

At this point I realized what I was seeing on the logic analyzer. GSC is dithering the display by alternating pixel states between frames, so that the state of each greyscale pixel averages out to somewhere between on and off.
Makes sense - so greyscale is not really a ‘feature’ of these panels, it’s just how it’s being driven by GSC.

Does the active matrix panel also use dithering to generate greys? I’m guessing not, but…
 
Back
Top