Drive an old Laptop Display from an AVR

Drive an old laptop LCD with nothing more than an AVR and a couple TTL XOR chips!

Or drive a parallel-input LCD with nothing more than an AVR!

As Of 11-27-15:

The official code-site has changed from google-code to github. (This, here, is still the main-page).

Visit: https://github.com/ericwazhung/avr-lvds-lcd

SEE BELOW FOR MORE UPDATES!

This project is based-heavily on (and has contributed greatly to) 'commonCode'. (see also, the link at left).

Yep, it's possible!

STATUS

Development has reached a pretty good stopping-point for a while, as the system is quite functional in many configurations, (but display donations are gladly accepted!):

LVDS/FPD-Link (laptop) Displays:

    • Boe-Hydis HT12X21-H240 - 12in 1024x768

    • Samsung LTN121X1-L02 - 12in 1024x768 (Two revisions)

    • Chi Mei N121X5-L03 - 12in 1024x768

    • (There's no 1024x768 limitation, these just happen to be the displays I've acquired)

Parallel TTL displays:

    • Sony ACX705AKM - 2.4in 240x160

    • Data Image FG050720DWSWDGL1 - 10in 800x600

AVRs:

For Parallel-TTL displays, any AVR with enough pins can be used.

For LVDS displays, the AVR must have at least two PWM channels with "dead-timers" (aka "Dead Time Insertion," "Dead-Time-Generators," "Power Stage Controllers"), running at PLL frequencies.

The following are FUNCTIONAL with LVDS displays:

    • ATtiny861 (48 colors, 64 with "row-dithering". Most development has been done with this chip)

    • ATtiny85 (3 shades of blue, 1 shade of Red, 1 of green; 64 colors with row-dithering)

    • AT90PWM161 (64 colors)

The following can most-likely be used with LVDS displays, with minimal code-changes, but are untested:

    • The remainder of the AT90PWM series (AT90PWM316, etc) requires MINOR code-changes

    • ATmega32M1/64M1 should work. (PSC... PLL?)

    • ATmega16M1???

    • ATmega32u4/16u4 looks like they'll do, and have USB to boot. (see note below. Thanks 'hboy' and 'Garbz' via the Hackaday Blog)

    • ATXmegas? (see note below, also thanks 'bogdan' also from the HaD Blog)

Didja see the ATtiny85 in the list? Yep, We're talking about driving an LVDS laptop display from an 8-pin 8-bit microcontroller!

ATmega32u4/16u4 note from 'Garbz':

"If you use it let me save you some time if you don’t read a datasheet in full everytime you touch a new part. The part ships with programming protection enabled and bootloader code already in place. I bashed my head against the wall for a good 10 minutes before I realised that the preferred method of programming is via Atmel Flip using the built in bootloader over USB. Or you can erase all the chip."

Xmegas:

Could be promising: faster, more memory, and actually cheaper than the ATTiny861. Unfortunately, from what I understand, they have an "extension" scheme that means the dead-timers necessary for my FPD-Link emulation-method don't run at the PLL frequency. This will limit the data-rate, and thus refresh-rate, and some/more displays may not sync at all. There's room for exploration, and they'd likely work well with the high-resolution/low-refresh-rate (row-seg-buffer) method and displays that can handle the lower bit-rates. Possibly even providing full 1024x768 resolution(?) at likely a few Hz refresh, with their higher system clocks. SO FAR, all this timing-sensitive code is written in AVR Assembly, so conversion to Xmegas might be a bit of an undertaking.

(The high-resolution row-seg-buffer method has only been tested-functional on two displays so far).

FUNCTIONALITY:

A key-factor is that TFT displays have inherent "memory" at each pixel. This memory can be taken-advantage-of. Slow refresh-rates (even down to 1Hz) can be viewed as a steady image on many displays. Some displays can even handle refreshes as slow as once every 5 seconds, allowing for high-resolution graphics from a lowly 8-bit processor with only 512 BYTES of RAM and no external memory.

(Note, this is likely hard on your display's pixels. I had two systems with two different displays running constantly for months on end in a wide range of weather conditions, and both suffered only minor image degradation. That-said, this is a hack, use it wisely!).

There are basically two modes:

    • high-refresh-rate/low-resolution

    • high-resolution/low-refresh-rate.

HIGH RESOLUTION / LOW-REFRESH

This Test-Patten shows its capabilities at high-resolution. Rotated 90 degrees due to limited row-memory's limiting long rows of horizontal text. The color-pattern at the top uses up the remaining row-segment-memory (intentionally set low, for testing-purposes). 48 displayable colors.

Currently running at a maximum resolution of 341 pixels stretched across 1024 "horizontal" (vertical, in this orientation), by 768 "vertical", 48-colors, <1Hz refresh. This refresh-rate is *just about the lower-limit* for this TFTs' ability to retain the image. It's possible to see some degredation near the bottom of the screen (which varies depending on the row currently being drawn, an interesting effect). Higher refresh rates are possible, at the expense of horizontal resolution, and eliminate the image-degradation at the bottom of the screen.

This "high-resolution" mode has only been tested with the Samsung display, some displays definitely don't like the slow bit-rate. In the works: DOUBLED horizontal resolution, so ~680x768 addressable pixels. (Horizontally limited by memory to ~100 "color segments", but they can be any multiple of 1/680th of a screenwidth in length).

This mode has only been tested on LVDS displays. It occurs to me, now, that most(?) parallel-interfaced TFT displays would likely work well with this mode!

Hardware Specs:

(Don't be fooled by the PCB in the image below, I just had a bunch of 'em from another project and needed a tiny-pitch breakout for the LCD cable. Listed are the only parts used in this configuration)

    • Atmel AVR: ATtiny861 - 512Bytes of RAM, 3x Hardware PWM channels with "Dead-Time Generators" and "complementary" outputs (in quotes, because the outputs aren't exactly inverted, the dead-time-generators affect the negative and positive outputs differently, which is essential for simulating FPD-Link compatible signals).

    • 2x 74LS86 XORs (from 1980)

    • 3.6V

    • A forgiving LCD display (such as the Samsung LTN121X1 shown in the image). Other displays are likely to work, it's a matter of experimenting. See notes in the code and at the bottom.

    • LCD backlight inverter

    • (Wire, and a handful of 0.1uF Decoupling Capacitors)

TODO: 1D-games?

http://hackaday.com/2016/07/17/video-games-in-as-few-dimensions-as-possible/

TODO: "FlappyScope"

Racer:

Shown on the display, below: "Racer" a game similar to one from the ol' TI-82 days... turn a potentiometer to keep the "car" (black vertical-ish line) on the green track. This was a test to see if it was possible to make a high-paced game at slow refresh-rates (Refresh can be seen as a black horizontal line). The red track is what's ahead (wrapping around at the bottom of the screen back to the top). The current position on the track is shown in green just above the refresh-line where it follows the red-track. The previous lap is shown below the refresh-line. So, at any one time you can see the track ahead for one full screen and the track behind for one full screen. (It makes sense when seen in motion...) When the car is on-track, the course is displayed in cyan, when the car is off-track it's displayed in magenta.

Listed Statistics:

    • Level (Cyan)

    • Number of rows kept-on-track (Green)

    • Number of rows total in this game (Red)

    • Percent of the time on-track (Yellow)

Another test-pattern, was just an experiment, but I thought it looked cool. And it visualizes something else I'd been working on over the years ('hfModulation' in _commonCode).

LOW RESOLUTION / HIGH REFRESH

When resolution isn't a concern, the refresh-rate can be bumped-up dramatically... This allows for animations, eliminates pixel deterioration, and more.

Mario Question-Box:

The power-up boxes from "Super Mario Brothers" are always fun to hit... With this circuit, you can build a life-sized one... It changes colors, just as in the game, and hitting the bottom gives a power-up "reward".

(All props to Nintendo for inspiring generations).

This system has been developed quite a bit, containing

    • sprites (from both Mario 1 and Mario 3, as well as some custom sprites)

    • color-palettes

    • animations

    • "camera" motion

    • ...

Occasionally you might get a Goomba, so be on your toes and hit him again to squash him.

(This photo was taken when implemented in high-resolution/low-refresh mode. Thus, you can see the color-change occurring as it refreshes. In low-resolution/high-refresh mode, the color-transitions and steps in animations appear instantaneous).

This was a later-version, installed in my building's laundry-room running 24/7 for nearly a year before it was stolen.

They musta been planning to steal it for a while, as it was bolted down to the ceiling. Never mind the power-cord which by then was well-hidden and thoroughly-ziptied amongst pipes and conduits for a good 30 feet to the outlet.

Its tap-sensor was a peizo element attached to the bottom, so it responds whenever you literally hit its underside.

Here is a Sony ACX705AKM parallel-interfaced display doing the job with an Atmel ATtiny84 AVR, wired for 64 colors. It's *a bit* smaller, so maybe more-realistically sized for "hand-mario" running on a table/desk. I tried to sell these at one point. (If you're interested in one, I have a couple left! I'm asking $50, but that's not set in stone. Send me an email! ericwazhung at gmail dot com).

Stencil-Clock Concept:

"Mood Light" (install a bright light behind, shine on a wall)

Stage-Light color-filter

More...

CIRCUIT:

The only parts necessary for this circuit are:

    • A compatible AVR (8bit)

    • Two TTL chips (usually 74LS86 XORs, but others are usable) (only necessary for LVDS displays)

    • wire

    • capacitors

    • and the LCD.

PCB: The PCB shown in the image below is only being used as a breadboard with a tiny-pitch breakout for my LVDS cable's connector. Shown with a 74LS00 NAND and a 74LS32 OR, used as a buffer and inverter. As-Wired it's pin-compatible with the 74LS86's recommended in my documentation. (And I have since swapped them out). However, ideally, (especially at faster bit/refresh rates) the buffer and inverter for each LVDS signal would come from the same chip.

The key here is that none of these "abilities" (functionality at extremely low bit-rates, retaining images at extremely low refresh-rates, syncability with huge horizontal front-porches, repeating of lines, etc.) are documented by the manufacturers, and in fact go completely against the documented limits. They can only be found by experimentation... And maybe a bit of understanding about what you're working with (e.g. TFTs by definition have "memory" at each pixel, so why not take advantage of that?)

Other extremes having been pushed on the AVR-side include using the PLL at 128MHz (documented to "saturate" at 85MHz) running the system clock at 32MHz (via the PLL, documented limit at 16MHz). Figuring out how to use the PWM outputs to create pseudo-FPD-Link serial-data signals that actually cover a reasonable range of colors and timing-signals. Pushing 512Bytes of RAM to handle a color image at 200x768 (That'd be 153KB in a frame-buffer!), and figuring out how to stretch that into a possible resolution of 600x768 or higher...

And yet even more extremes pushed: Being able to view these 128MHz signals on an analog oscilloscope rated for 20MHz. Level-triggering the 'scope on the fact that certain digital bit-patterns cause increased analog-overshoot and DC-offsets... (At these bit-rates and with this equipment, the digital bit-streams become quite a bit more analog, and therefore can not only be triggered at a certain point in the refresh, but the various porches and syncs can also be recognized when zoomed way-out).

...Using TTL chips rated for 4.5-5.5V at 3.3V; rated for loads of >1Kohm at a load of 100ohms and finding the signals output are dang-near perfect for LVDS voltage-requirements. (Running them at frequencies way higher than they're rated and finding the analog effects to be useful).

And then there're other possibilities... For instance, considering the fact that two of the serial-streams are nothing more than color-data, essentially "red" and "green", it's entirely possible to have the timing generated by the processor and image-data generated by an entirely different source. With little more than two comparators, outputs tied directly to the red and green serial channels, this could easily be turned into a dual-trace oscilloscope. With an actual LVDS serializer chip, or maybe even a simple shift-register, it could be three-trace.

Then some other possibilities discovered... this "Data-Enable-Only" display (and possibly most DE-Only displays?) tries so hard to find valid syncing-signals that you can get interesting effects by simply sending a constant DE-signal... With nothing more than a crystal oscillator (27MHz in my case), two shift-registers (one for the pixel clock, and one for the sync signal), a buffer, and an inverter, (no AVR necessary!), solid-colors can be generated... Could be used, e.g., for an adjustable color-filter on a stage-light. Or by introducing a bit of randomness it creates some interesting soothing "meditation" patterns. Again, just a handful of TTL parts.

It's maybe not possible with an 8-bit microcontroller to do full-color-full-resolution-fast-refresh video, but a shitton is possible.

Display/Functionality Notes: (As of 3/4/14)

Different displays have different (undocumented) functionality. With the several I've tested, I've attempted to create a step-by-step procedure to get a new display going (or find out early-on if it's not possible. So far I haven't run into one that couldn't be coaxed into working with this system).

Several of the tested LVDS displays were removed from old 12in G3/G4 iBooks. Two revisions of the same Samsung model, a Chi-Mei, and a Boe-Hydis have been tested. All are pretty standard laptop TFTs: 1024x768, FPD-Link/LVDS single-channel, DE-Only displays. (The code is written to work with non DE-Only displays--those that pay attention to the H-sync and V-sync signals--but this is untested.)

Each display has its quirks and its benefits.

E.G.: The Samsung displays seem to work well with really long horizontal-blanking-periods, whereas the ChiMei display does not seem to like that at all. (This "feature" is extraordinarily handy for high-resolution/low-refresh, where each row's pixel-data is calculated during the horizontal-blanking-period before it).

E.G.2: One revision of the Samsung display works fine at low bit-rates, but the other requires a faster bit-rate.

E.G.3: The Samsung displays have visible refresh; rows are blacked-out before they're redrawn, resulting in visible flicker at high refresh-rates and noticeable scrolling at low refresh-rates. The ChiMei does not have this effect and is visually quite appealing (but so-far limited to low-resolution). The Boe-Hydis has invisible refresh and looks *excellent*, but has not yet been tested in high-resolution/low-refresh mode.

Again, I've done my best to make the testing-procedure relatively step-by-step.

The first step is pretty much go-no-go. If the display doesn't show anything (is completely blank), then it's unlikely this circuit/code will work with your display. Out of four displays, I've only had one which I couldn't get working (was it IDTech?), and the final attempt (before I accidentally stepped on it) was long before this testing procedure was established.

From there, it's simply a matter of selecting increasingly complex test-patterns... first a solid blue screen, then a blue/black screen divided vertically, then diagonally, and so on. These patterns help to adjust/experiment with timing-values, which may be nowhere near the spec'd values, since we're working way out of specs already. (In fact, once I had a 1024x768 display which somehow magically stretched 680 pixels across the entire screen when its bit-rate was slowed... odd, since the pixel-clock is sent along with the pixel-data!).

Basically, if that first test works, then it's quite likely the display can at least handle a very small frame-buffer... which is perfect for, e.g., the "Mario" project, where each full-screen image is only 16x16 anyhow. Or use it to draw solid colors, e.g. as a color-filter for a stage-light. Or, again, the circuit here could be used exclusively to drive the LCD timing signals, and the actual green/red data could come from an external source (like an analog-comparator to create an oscilloscope?). (see ATtiny85 note below for an example)

If you care for higher resolution, at the cost of refresh-rate, then further tests allow for testing that feasibility. Again, increasing the resolution beyond the available memory requires calculating image-data before drawing each row. This has to be done somewhere, so it ends up happening in the horizontal-blanking period. If the display can't handle long horizontal-blanks (like the ChiMei), then this'll be discovered early-on in that part of the testing.

Certainly, this testing-procedure could stand to be improved... more displays to experiment/develop with certainly wouldn't hurt. I'm also somewhat intrigued with the idea of using this system to make use of the still-usable portions of broken displays... maybe the broken part could even be cut off with a glass-cutter, or at least covered by the project-housing. Further, I'm not 100% convinced the row-calculation stuff is a problem with the ChiMei display, so at some point it might be worth fine-tuning those tests a bit more. With its lack of a visible refresh, it would be almost ideal for 1Hz refresh at high resolution. (Except, maybe, for my "Racer" game...?).

ATtiny85 Implementation Note: The ATtiny85 only has two LVDS-"compatible" PWM signals. These two signals are used for Blue/Timing and the Pixel-Clock. The "Red" and "Green" LVDS signals are driven by simple digital-outputs which are updated at the displayed "pixel" rate. E.G. when the "Red" output is 1, the entire bit-stream of 7 data-bits is 1's, resulting in a full-on of "Red." Same for "Green." (I quote these, because technically the LVDS signal carrying the red-bits also contains Green's LSB, so technically, "full-on red" is actually full-on of red, plus a *tiny* bit of green. Similarly, the "green" LVDS-signal contains the two LSBs of blue, so a full-on of green contains a tiny bit of blue. These effects are basically invisible.)

Please see the additional related pages: