;**************************************************************************** ;* * ;* LCD Controller für Dualscan 640x480 LCD * ;* * ;**************************************************************************** ;* * ;* Einfacher LCD Controller für ein SW 640x480 LCD, wie es in vielen alten * ;* Notebooks verbaut ist. * ;* Außer einem mega8515, einem 74HC32, dem 74x573 Adresslatch im Datenbus, * ;* und einem 64kB SRAM (mit 55ns oder schneller) werden keine weiteren * ;* Bauteile benötig. Neue Daten werden über RS232 mit 115200Baud in den * ;* Speicher geladen. Allerdings kann man auch jedes andere Interface wie * ;* z.B. SPI verwenden, solange dafür nicht zuviel Rechenzeit benötigt * ;* wird. Immerhin müssen (mehr oder weniger) kontinuierlich 2,5MB/s * ;* ausgegeben werden ! Damit das ganze problemlos funktioniert, läuft der * ;* AVR mit 18,432MHz und steuert das LCD mit rund 65Hz an. * ;* * ;* Der Datentransfer über RS232 behindert die Datenausgabe auf dem LCD * ;* nicht, man sieht also keinm Flackern oder ähnliches. Nur beim Löschen * ;* von Zeilen muss man aufpassen: Es dauert sehr viel länger, eine Zeile * ;* zu löschen und das LCD anzusteuern, als den nächsten Befehl zu senden * ;* Hier kommt es kurz zu einem Flackern, wenn man viele Löschbefehle * ;* direkt hintereinander sendet. Dafür lässt sich das LCD aber in sehr * ;* kurzer Zeit Zeilen weise löschen. * ;* * ;* Die Datenübertragung läuft über den UART, der im 9bit Modus betrieben * ;* wird. Das 9.Bit entscheidet zwischen Daten und Befehl. Ist es gesetzt, * ;* handelt es sich um ein Befehl, ist es gelöscht dann wird der Wert als * ;* Daten oder als Parameter eines zuvor gesendeten Befehls behandelt. * ;* * ;* Befehle: * ;* * ;* 001 Set Cursor. Gefolgt von zwei Parametern, nämlich der Zeilen * ;* und Spaltenadresse. Die Zeilenadresse liegt im Bereich 0-239, * ;* und die Spaltenadresse im Bereich 0-79 (plus 128, falls die * ;* Position in der unteren Displayhälfte liegt.) * ;* * ;* 010 Clear Line. Dieser Befehl benötigt keinen Parameter und löscht * ;* die aktuelle Zeile. Danach wird der Cursor auf den Beginn der * ;* nächsten Zeile gesetzt. So kann man 480 mal diesen Befehl * ;* senden, um das ganze LCD zu löschen. Allerdings ist dieser * ;* Befehl sehr komplex, und benötigt daher einiges an Zeit. Sendet * ;* man also diesen Befehl öfters ohne Pause, dann kommt es zu * ;* einem kurzen Flackern des LCDs. * ;* * ;* 011 Clear LCD. Dieser Befehl löscht das LCD in extrem kurzer Zeit. * ;* Aber wie auch schon beim Clear Line Befehl, benötigt er einiges * ;* an Zeit um den kompletten Speicher zu löschen. Das LCD Timing * ;* wird zwar nicht ganz eingehalten, aber man merkt nichts davon. * ;* * ;* Daten: Nach dem Senden eines Datenwertes wird dieser in den Speicher * ;* geschrieben, und der Adresszähler anschließend erhöht. * ;* Jedes Byte enthält 8 nebeneinanderliegende Pixel. Im SRAM * ;* werden dagegen 4 nebeneinander liegende Pixel aus der oberen, * ;* und 4 nebeneinander liegende Pixel aus der unteren Hälfte * ;* gespeichert. Das mach das Laden von Daten etwas komplizierter, * ;* vereinfacht und beschleunigt die Ausgabe extrem. * ;* * ;* IO Pins: * ;* * ;* * ;* PD0 RXD RS232 Dateneingang * ;* PD3 EXSCL Aktivierung für XSCL. Dieser Pin aktiviert über ein * ;* 74HC32 den Schiebetakt für die Daten * ;* PD4 LP Latchpuls. Der Impuls läd die Daten aus dem Schiebe- * ;* register ins Display. Dient als HSync. * ;* PD5 FLM VSync für das LCD. Das LCD springt in die erste Zeile. * ;* PD6 WR\ Write Enable für das SRAM. * ;* PD7 RD\ Output Enable für das SRAM und XSCL über den 74HC32 * ;* für das LCD. Bei jedem Lesevorgang werden die Daten ins * ;* LCD geladen * ;* PB0 EnLCD Schaltet über einen PNP und einen PNP Transistor die * ;* LCD Spannung, damit im Falle eines Fehlers (z.B. Ausfall* ;* der +5V) das LCD nicht zerstört wird. * ;* PB1 Busy Zeigt durch einen High Pegel an, ob der uC mit dem Laden* ;* von Daten oder Ausführen von Befehlen beschäftigt ist. * ;* Da das Laden von Daten schneller geht, als das Senden * ;* eines Wertes, braucht man Busy eigentlich nur bei den * ;* Clear Line und Clear LCD Befehlen abzufragen. * ;* * ;**************************************************************************** .include "m8515def.inc" ;@18,432MHz .def null=r0 .def eins=r1 .def temp =r16 .def temp2 =r17 .def temp3 =r18 .def Bits =r19 .def NextOp =r20 ;Zähler für Parameter eines Befehls .def tempm =r21 .def Flags =r22 .def XAdresseLow=r26 ;Writepointer Spalte .def ZeileL =r27 ;Writepointer Zeile LSB .def AdresseLow =r30 ;Readpointer Spalte .def AdresseHigh=r31 ;Readpointer Zeile ;PortB .equ EnLCD =0 ;LCD Spannung einschalten .equ Busy =1 ;PortD .equ XSCL =3 ;Enable XSCL .equ LP =4 ;HSync .equ FLM =5 ;VSync ;Flags .equ Frame =0 ;Warten bis 1/(60fps * 242 Zeilen) Sekunden vorbei ist, ehe die nächste Zeile ausgegeben wird. .equ ZeileH =7 ;Writepointer Zeile MSB, entscheidet zwischen obere und untere Displayhälte, also zwischen Hig und Low Nibble eines RAM Bytes .org 0000 rjmp reset .org OVF0addr ;Timer 0 rjmp Framestart .org URXCaddr ;Interruptvektor für UART-Empfang rjmp RXRoutine .org 32 reti Framestart: out Tcnt0, tempm sbr Flags, (1< Max ? brne normal clr XAdresseLow ;Spalten Adresse = 0 inc ZeileL ;Zeilen Adresse ++ cpi ZeileL, 244 ;Zeilen Adresse in untere Displayhälfte ? brne normal ldi ZeileL, 4 ;Zeile = Beginn XRAM sbr Flags, (1< Max ? brne normal clr XAdresseLow ;Spalten Adresse = 0 inc ZeileL cpi ZeileL, 244 ;Zeilen Adresse in untere Displayhälfte ? brne normal ldi ZeileL, 4 ;Zeile = Beginn XRAM cbr Flags, (1<