This project's original aim was to drive an old laptop display directly from an AVR, to the fullest extent(s) possible. It has grown quite a bit since then. It now works with Numerous Displays, via configuration-options. It now works with both FPD-Link displays, as well as Parallel-interfaced. It's also the home of my "Mario Question Box" code... several of these boxes have been built, using different displays. (Hit the box, get a reward!) Quite a bit of limit-pushing has been done, much of which is display-specific... (I mention in many places that the current state-of-the-art makes use of my high-resolution "row-segment-buffer", but that hasn't been the case in quite some time. The "Question Box" uses a 16x16 frame-buffer, which works with every display implemented so far.) Many other options have been created, including refreshes *only* when an image changes... At such slow bit-rates this makes for much smoother-looking images (using the TFTs' inherent memory to hold the image until the next refresh). AS OF 11-27-15: This has been exported from google-code. The OFFICIAL source for avr-lvds-lcd is now https://github.com/ericwazhung/avr-lvds-lcd/ As-of 7-8-14: This and many other such files have not been updated for quite some time. Today I'm uploading v90 of the code. You'll see notes in this file referencing "now" as, e.g. v62. Yes, it's been a while, and there have been numerous significant changes since then, including quite a bit of new functionality, which kinda tends to burry the older functionality. 7-12-14: We're now at v94, which has been tested-functional with three different displays. Basically: Start in mainConfig.h... This has (most) configuration options. Start with "BLUE_TESTING" and "DE_BLUE"... (Check 'makefile' to change the processor-selection.) FEEL FREE to email me with questions... it'll help me organize! Configuration As-Distributed: (can be configured differently, as described above) * 1024x768 laptop display (FPD-Link/"LVDS") * ATtiny861 * "DE_BLUE" (Fills the screen with blue, for sync-testing) Necessary circuitry components: * ATtiny861 (AT90PWM161 is also implemented) * TTL Buffer \ Only necessary for LVDS-displays; I use the 74LS86 XOR * TTL Inverter / for both purposes. * (Newer TTL chips may require 8 100ohm resistors in series with the outputs) * .1uF caps for power-filtering * 3.3-3.6V power supply * (CCFL LCD-backlight inverter) * (Optional: LED+resistor, and push-button) Pinout/Wiring Info: * pinout.h * (see also files in _interfaces/) Build Process: 'make fuse' --Configure the AVR's FUSE bits 'make clean' --(It's wise to run this any time any change is made) 'make' 'make run' --Burn it to the AVR's FLASH Tools: (Visit _commonCode_localized/_make/avrCommon.mk to change) * avr-gcc4.8 (4.4 should work, but some options might have to be removed from commonWarnings.mk) * avr-dude * usbTinyISP ------------------ From here, on, notes are REALLY OLD. The original code-site for this code is located at: https://code.google.com/p/avr-lvds-lcd/ If that ever changes, I will be sure to note it here, and link from the google-code page. As it stands, this project is in no way associated with or hosted at GitHub As I'm relatively unfamiliar with versioning utilities like Git, and am new to contributing to the OpenSource scene, I'm trying to keep an open mind about the fact that someone seems to be hosting my code on GitHub.com. (And that that site is the first result in a Google Search!). I'm glad for the exposure, and grateful to know that even if I lose access to my account or die or something, my hard work will still be available to others! But, I thought part of the point of these OpenSource/Versioning systems is that of trying to keep an original master-branch somewhere locatable, along with keeping contributors in contact... To that end: Again, the original code-site for this code is located at: https://code.google.com/p/avr-lvds-lcd/ And the non-code site is at: https://sites.google.com/site/geekattempts/home-1/drive-an-old-laptop-display-from-an-avr And, I'd absolutely be grateful to anyone attempting projects based on my code to get in touch with me, just so I know it wasn't a complete waste of time. Email below. -------------- As-of 3-19-14, there are no contributors to this project besides myself. Dang-near every line of code here and in the subdirectories is my work including makefiles, etc. I have made-reference where others' work has been helpful. Some of the code here has been developed over more than a decade, and this project itself is several years in the making. Please be respectful... if you find anything here useful, awesome! If you use it verbatim, please give credit where it's due. Either way, it'd be awesome if you'd let me know (I'll link yah). If you find yourself profitting from it, please send me a beer (or cash is always handy). The only BIG restrictions are: If you *intend* to profit off my work, you must contact me first. ** That includes, if you host my work on a revenue-making site! ** If your intent is related to military, NSA, or other creepy purposes, you do NOT have my permission to use my work. I'm EricWazHung [at] gmail dotcom or visit: https://sites.google.com/site/geekattempts/ (I hate this legal bullshit, people should just have basic human decency then none of this would be necessary.) The End Of the Legalities ---------- (This document written at the time of the first upload version 60ish. Some of it may be outdated. This is version 65. Though it's quite likely I'll forget to update this note, come v66). I'll say up-front there's QUITE A BIT of redundancy and left-over notes which are no longer relevent to the current version. (This has been cleaned up *quite a bit* as of the latest version... those no-longer-relevent bits have been moved to _old/ and _unusedIdeas/). Also, there're a *ton* of configurable options which render much of the code unused... e.g. "racer" is a game I've been working on, it uses a potentiometer connected to an ADC as a controller... the ADC is not used at all for the "Mario"/"QUESTION" stuff... Similar for sineTable, and a few others... (a/o v65: the above is related to "SEG_QUESTION." FB_QUESTION is a different story, the ADC is used in FB_QUESTION for "hit-detection" via piezo-element. This isn't well-documented, yet. And SEG_QUESTION is *quite old* in comparison to FB_QUESTION) Stuff in _commonCode_localized/ is stuff I use regularly for various projects... _commonCode.../lcdStuff is a good place to start looking for graphical LCD stuff, specifically. Most of the remaining graphical LCD stuff is located in the main directory. I'm only *barely* familiar with this git/version-tracking stuff... (first attempt was yesterday) Previously, I had my own version-tracking scheme. They're not particularly compatible... As of this writing, this first "distribution" contains the 59th functional version of the code... when I move on to 60, it may be difficult to use my versioning-scheme along with git to upload it... (a/o v61: yeah, git and my versioning scheme are *not at all* compatible. Trying to keep it git-friendly is making things I've done for years quite a bit more difficult...) So the updates may be pretty irregular. We'll see how it goes. As it stands, this is meant to work with an ATtiny861, the pinout should be burried in various places in code. YAY! (a/o v61: check pinout.h, it should be all contained in there) To use as-is (with an LVDS/FPD-Link display): You'll need an ATtiny861 (For LVDS the AVR model is *very* specific, as this pseudo-FPD-Link implementation *requires* PWM Dead-Timers and Three PWM channels, with complementary outputs. I've only seen these options available on two AVR chips, this and the AT90PWM-som'n) Two 74LS86 XOR chips (or buffers and inverters...?) A Samsung LTN121X1-L02 12.1in 1024x768 display (and an inverter to drive its backlight) (other displays *may* work, but I can't vouch for 'em. I have another that won't sync at all...) and a 3.3 or 3.6V supply. I use a USB-Tiny, avr-gcc, and avr-dude for programming my AVRs (look into _commonCode.../_make/avrCommon.mk if you need to change this or anything else... also reallyCommon2.mk) I generally upload it after a compile, so you might be able to get away with just "make fuse" and "make flash". Otherwise: You should be able to do "make clean" "make" "make fuse" "make flash" There are *several* options that are currently unused and haven't been tested for quite some time... E.G. it has been used at much higher refresh rates (and much lower resolution) with a tiny frame-buffer... Currently it uses a "Row-Segment Buffer" which is reloaded after each row is drawn... These row-segments are defined by a color-value and a number of pixels... Depending on the amount of memory used otherwise, the number of row-segments can be increased or decreased. (They take 2 Bytes apiece, so there's a *definite* limit of 256 row-segments). There're something like 341 drawable pixels per row (streched across 1024 physical)... So, you can see it's impossible to have a different color in every drawable pixel in a row... (not enough memory!) (Note that the AT90PWM161 has 1K. It may not be difficult to port to this chip, in which case, every drawable pixel could be individually written!) Because of the limited memory and the limited horizontal resolution, text is hard to display in a row... (But you can rotate the screen and text 90-degrees, as the 768 rows are each calculated and drawn individually) There are several drawing/game/... modes that have been tested recently (a/o v61: all SEG_<mode>'s have been tested. See their descriptions in mainConfig.h) Here are a couple examples: SEG_QUESTION displays 16x16 pixel images, which are changed by pressing the button (It uses sprites from Mario Brothers... Thanks Nintendo!) Some day I'll build a box and attach the button to a bump-sensor and hang 'em around the city... but you might beat me to it. If you do, I want to see pictures! SEG_RACER is a game similar to "Racer" from the ol' TI-82 days... It's an attempt at a few things: Is it possible to make a fast-pace game with a slow-refresh-rate? Let's make use of that high resolution! Keep the "car" in the green track by moving a potentiometer. The further you go, the harder it gets. Again, this is my first distribution of any sort, so I have no idea what'll happen on others' systems, though I did my best to make it distributable). I look forward to hearing others' experiences! (See also the README file in _commonCode.../lcdStuff/...) ------ Give it a few seconds (several in fact) to "boot". I don't know why, because code-wise I think it starts sending signals immediately... The screen usually appears black with a single row of white at the top until the first frame syncs up. ------ Another Note: I have two of these Samsung displays... I've had *both* of them working at one time or another. But doing some testing for this distribution, one is quite flakey. It seems it's not syncing correctly with the LVDS data-bits. The effect-of-which is what I'd call "snow" appearing pretty regularly across the image. The image displays and syncs for the most part, but the colors are coming through flakily. Not sure what's wrong, but switching to the other display and it works perfectly. (a/o v61: doubling the LVDS-bit-rate has fixed the problem, and it now works with *both* LTN121X1 displays in my posession. Let this be a lesson: If you see *something* on your screen, it's *quite likely* you'll be able to sync it up properly with a little work. Note that my two LTN121X1 displays have different revisions of the same LVDS receiver chip, I don't have the part-numbers in front of me. See below for a bunch of theorizing as to why it wasn't working, as written *when* it wasn't working.) ---- Theories --- Thing is, these data-rates are *horrendously* slow compared to the display specifications... It's quite plausible (in fact *likely*) that I'm right on the threshold of the rates the LVDS chipsets in these displays can sync with (certainly *way* below their ratings). We're not talking about syncing in terms of the display's syncing with the image-data, we're talking about each packet of (pixel) data syncing up with the receiver. So here's a bit of the technicalities in case you're wondering, as far as what I think might be happening (I've documented similar elsewhere). There's a PLL (clock regenerator) in the LVDS-receiver.... it takes the actual "Clock" signal, which is 1/7th of the bit-rate, and bumps that signal up by 7 in order to know when to sample each bit. These circuits usually have lower frequency limits... (How do they multiply a frequency? Do they use capacitors?) Anyways, the result is it seems it's sampling the bits at the wrong times. The effect is like a baud-rate that's not quite right... the first few bits would come through properly, but the later bits might get sampled at the wrong time. So, why would the display have worked previously, and show snow now? Well, it's winter-time... maybe it's a thermal thing. Or maybe I'm just crazy and the thing was never tested. Anyways, it's just a theory. Actually, another theory might be the new circuit-board. I might not have tested this board with both displays, and the main display I'd been working with broke off the connector, so I had to try the less-tested display first upon revisiting this project... The new circuit-board totally disregards some of my notes elsewhere: To use gates within the *same* XOR chip for both the negative and positive inputs of each channel, in order to avoid potential speed-differences between chips. (In fact, I built this board with a 74LS00 and 74LS32, NAND and OR, wired to act as an inverter and a buffer... because I have them in much greater supply. I tried swapping them with my trusty XORs and the effect was the same... Maybe this other display is less sensitive to misalignment between the positive and negative inputs... or the resistance in the display is different, or a million other things. I haven't scoped it.) ---- End of theorizing ---- As it is, the code is pretty limited to the current state-of-the-art... I haven't messed with lower resolutions (which equate to faster-bit-rates and faster refresh-rates) for quite some time. The code's in there, I think, but it's burried so deep it'll take me some time to dig it up. That said... Don't give up if your display doesn't work right off the bat. Likewise, starting with the current state of the code is a bit of a crap- shoot if you're not working with the exact same display. When starting with a new display, I usually start with "DE_BLUE" which is one of the simplest LVDS signals for the display to receive (displays a full blue screen, if it's syncing correctly). Then "BLUE_VERT_BAR" and go on from there. Again, it's been a while. If you have identical equipment, you might be lucky with the code as-configured. Or you might get some ugliness as I just experienced. (a/o v61: the latest configuration is with the doubled-pixel-clock, so it should be more functional with more displays) Another note: The display used is DE-Only, which means it doesn't pay attention to the Hsync and Vsync bits. As far as I'm aware, that code is implemented properly. My other two displays (also from iBook G3's) are *not* DE-Only, and neither of them sync. OTOH, one explicitly states in its data-sheet that refresh-rates that are too slow will be disregarded "to protect the liquid crystals". If you see that note, you'll be hard-pressed to get the display working with this system... it relies heavily on stretching the displays' limits.) Good luck and have fun!