;**************************************************************************** ;* ;* 40 x 25 TV Terminal / TV Controller ;* ;* Version 3.0 ;* ;* © by Benedikt ;* ;* Email: benedikt83 ät gmx.net ;* ;**************************************************************************** ;* ;* Erweiterung v2 - von Sven K. (oog) ;* ;* ;* 2010-09-05 (Y-M-D) ;* ;* - 8*16 Zeichensatz eingebaut ;* - 8*16 Zeichensatz mit inverser Schrift eingebaut (#define Font_inv) ;* - Neue Video-Modes 12, 13 und 14 mit 8*16 Zeichensatz ;* - Zeichensatzdaten liegen am Ende des Flash ;* ;* Optimierung für 7" LCD Monitor ;* - Doppelte Zeilenausgabe für Textmode (stretch_y) ;* - doppelt hoher Zeichenausgabe und 16 Pixel Font in Kombination ;* - Neue Video-Modes 15-18 mit doppelt hoher Zeichenausgabe ;* - Korrekturwert für Video Interrupt gefixt (war mein Fehler) ;* ;* ********************************************************* ;* ;* 2010-08-27 (Y-M-D) ;* ;* 1) Dynamischer Bildspeicher mit EOL-Zeichen Support ;* 2) TVText Startadresse ;* 3) TVTextDaten im RAM, freie Register für Hauptprogramm ;* 4) Breite Schrift, 20 Zeichen/Zeile ;* 5) Leerzeilen für bessere Lesbarkeit ;* 6) Abstand zwischen Zeichen ;* 7) Bildparameter zusammengefasst zu Video-Modes (vmode_n) ;* 8) Grafikmodus ;* 9) Bildzähler ;* 10) Einfache Grafikfunktionen ;* ;* ;* 1) Dynamischer Bildspeicher mit EOL-Zeichen Support ;* ;* Eine Null im Bildspeicher signalisiert das Zeilenende, ähnlich wie beim ;* ZX81 mit 1 KB RAM. Das nächste Zeichen wird in neuer Zeile ausgegeben. ;* Der Bildschirm darf größer als der vorhandene Speicher sein, siehe die ;* Demo mit 40*32 Zeichen. ;* ;* Vorteil: Geringer Speicherbedarf ;* Nachteil: Keine fester Bezug von Bildspeicher und Zeichenposition ;* ;* EOL-Modus aktivieren mit: ;* #define eolsupport ;* ;* Zeichencode für Zeilenende definieren: ;* .equ EOLChar=0 ;* ;* Der Code liegt im gleichen Speicher und Timing-Abschnitt wie ;* "#define HOR_FILL", und kann mit diesem nicht zusammen verwendet ;* werden. ;* ;* ;* 2) TVText Startadresse ;* ;* Die Startadresse des Bildschirmspeicher ist frei einstellbar. Zusammen ;* mit dem EOL-Modus kann man beispielsweise einen Text scrollen, der länger ;* als der Bildschirm ist. ;* Die Variable tvstart(h/l) zeigt auf den Bildspeicher. ;* ;* ;* 3) Im Interrupt genutzte Register werden gesichert. ;* ;* Alle Register sind frei für das Hauptprogramm. Eine Integration des ;* Videotreibers in eigene Projekte wird so einfacher. ;* ;* ;* 4) Breite Schrift ;* ;* Die SPI-Clock läuft mit halber Geschwindigkeit. Zeichen erscheinen ;* daher doppelt breit ;* ;* ;* 5) Leerzeilen mit ein Pixel höhe ;* ;* Zwischen den Zeilen kann eine beliebige Anzahl Leerzeilen ausgegeben ;* werden. Dies wird über die Konstante Blanks eingestellt. ;* Leerzeilen erhöhen die Lesbarkeit und verringern die CPU-Last, da ;* im Interrupt dann keine Zeichenausgabe erfolgt. ;* ;* ;* 6) Abstand zwischen Zeichen ;* ;* Mit "#define h_blank" wird nach jedem Zeichen ein Füllpixel ausgegeben. ;* So können 16 / 32 Zeichen auf voller Bildbreite angezeigt werden ;* ;* ;* 7) Bildparameter ;* ;* Die für die Darstellung wichtigen Bildparameter sind zusammengefasst ;* und als Parametersätze für unterschiedliche Video-Modes definiert. ;* Anhand der Beispiele lassen sich leicht eigene Modes erstellen. ;* ;* ;* 8) Grafikmodus ;* ;* Mit "#define gfxmode_n" wird der Grafixmodus aktiviert. Folgende Modes ;* sind implementiert: ;* ;* gfxmode_1 : 80*64 Pixel, zusammenhängend ;* gfxmode_2 : 80*64 Pixel, mit Trennlinie (LCD-ähnliches Design) ;* ;* Im Grafikmodus wird von jedem Byte das LSB zuerst ausgegeben, was ;* mit der Hardware-Verschaltung des Videoausgangs an PB1 zusammenhängt. ;* Es gibt eine darauf angepasste Ausgabefunktion (putpixel). ;* ;* ;* 9) Bildzähler ;* ;* Die Variable frames dient als Zähler für die angezeigten TV-Bilder. ;* Ein Programm kann dies als Zeitbasis für Animationen oder zur Synchronisation ;* bei der Bildansteuerung verwenden. ;* ;* ;* 10) Einfache Grafikfunktionen ;* ;* Es gibt einige grundlegende Grafikfunktionen. ;* - putpixel - einen Punkt zeichnen ;* - hline - horizontale Linie ;* - vline - vertikale Linie ;* - rect - Rechteck Außenlinie ;* - box - ausgefülltes Rechteck ;* ;* 'color' enthält die Zeichenfarbe Schwarz, Weiß oder Invertiert ;* ;* Das Demo-Bild zeigt die Anwendung der Grafikfunktionen. ;* Textmode und Grafikmode sind getrennt, so dass nur die jeweils sinnvollen ;* Programmteile eingebunden werden. ;* ;* Deaktiviert man "#define demo", wird aller unnützer Ballast abgeschaltet ;* und es läuft nur der Videotreiber. ;* ;**************************************************************************** ;* ;* Die Software darf frei kopiert und verändert werden, solange sie nicht ;* ohne meine Erlaubnis für kommerzielle Zwecke eingesetzt wird. ;* ;**************************************************************************** ;* ;* Diese Software erzeugt ein PAL ähnliches Videosignal, das von allen von ;* mir getesteten TV Geräten aktzeptiert wird. ;* Somit lassen sich beliebige Texte darstellen. Dank vollständigem ASCII ;* Zeichensatz sind auch ASCII Grafiken möglich. ;* ;* Das besondere an dieser Software: Das Timing wird per Timer gesteuert, ;* der AVR kann daher nebenbei problemlos andere Aufgaben erledigen, da ;* die Bilderzeugung lediglich etwa 60% der CPU Leistung benötigt. ;* Die Sync Signale werden vollständig per Timer im PWM Modus erzeugt, ;* die Bildausgabe erfolgt im Interrupt mit automatischer Jitter- ;* kompensation (Idee von Bernhard Schulz). ;* Das Hauptprogramm darf also den Interrupt um bis zu 10 Takte blockieren. ;* Im Hauptprogramm darf jede beliebige Software laufen, solange diese mit ;* den freien Registern und dem wenigen SRAM auskommt. ;* ;* Fuse Bit High: 11001001 = 0XC9 (CKOPT enabled) ;* Fuse Bit Low: 01101110 = 0x6E (externer Quarz, BOD enabled) ;* ;* IO Pins: * ;* ;* PB1 muss mit PB3 verbunden werden ;* PB2 Sync Ausgang: über 1kOhm an Ausgang ;* PB3 Pixeldaten: über 330Ohm an Ausgang, Ausgang über 100Ohm an Masse ;* PB4 DNU (muss frei gelassen werden) ;* PB5 DNU (muss frei gelassen werden) ;* PB6 XTAL 16MHz Quarz ;* PB7 XTAL 16MHz Quarz ;* ;**************************************************************************** .include "m8def.inc" ;.include "m16def.inc" ;#define mega16 ;Im Interrupt genutzte und geänderte Register: .def spian =r16 .def spiaus =r17 .def X_Cnt =r18 .def tempi =r19 ;zusätzlich: X und Z ;Sonstige Register, für Hauptprogramm frei: .def temp =r16 .def temp2 =r17 .def RX =r18 .def px1 =r19 ;gfx parameter .def py1 =r20 .def px2 =r21 ;gfx parameter .def py2 =r22 .def color =r23 ;gfx colour .def data1 =r24 ;gfx data1 ;zusätzlich: Y #ifdef mega16 ;PortB .equ DOUT =3 ;Pixeldaten \ .equ SS =4 ; } Verbinden .equ MOSI =5 ;Pixeldaten / .equ MISO =6 ;NC .equ SCK =7 ;NC ;PortD .equ Sync =4 ;Sync Ausgang (OCR1B) #else ;PortB .equ DOUT =1 ;Pixeldaten \ .equ SS =2 ; } Verbinden .equ MOSI =3 ;Pixeldaten / .equ MISO =4 ;NC .equ SCK =5 ;NC ;PortB .equ Sync =2 ;Sync Ausgang (OCR1B) #endif .equ Baudrate =250000 #define demo ;Liste der Video-Modes ;#define vmode_0 ;44x34 ;#define vmode_1 ;40x32 ;#define vmode_2 ;40x25 ;#define vmode_3 ;40x25 mit Leerzeile ;#define vmode_4 ;40x20 ;#define vmode_5 ;40x16 ;#define vmode_6 ;32x24 ;#define vmode_7 ;32x24 mit Abstand ;#define vmode_8 ;32x16 ;#define vmode_9 ;20x16 ;#define vmode_10 ;20x10 ;#define vmode_11 ;16x8 ;#define vmode_12 ;40x16 8x16 Zeichensatz ;#define vmode_13 ;40x12 8x16 Zeichensatz ;#define vmode_14 ;20x12 8x16 Zeichensatz ;#define vmode_15 ;40x12 Zeichen doppelt hoch ;#define vmode_16 ;20x12 Zeichen doppelt hoch #define vmode_17 ;20x8 8x16 Zeichensatz, Zeichen doppelt hoch ;#define vmode_18 ;32x8 8x16 Zeichensatz, Zeichen doppelt hoch ;#define gfxmode_1 ;80x64 ;#define gfxmode_2 ;80x64 LCD Pixel Modus ;#define gfxmode_3 ;80x64 schmal ;#define gfxmode_4 ;80x64 schmal, LCD Pixel Modus ;#define gfxmode_5 ;88x72 ;#define gfxmode_6 ;88x72 LCD Pixel Modus ;#define gfxmode_7 ;96x80 ;#define gfxmode_8 ;96x80 LCD Pixel Modus ;#define LCD ;Zeichen 128-135: Balkenanzeige #define HOR_FILL ;Lücken zwischen den Zeichen füllen ;#define eolsupport ;Nicht zusammen mit HOR_FILL setzen .equ EOLChar=0 ;Zeichencode für Zeilenende .equ tvmem=1000 ;Größe für Bildspeicher, wenn eolsupport gesetzt ist #define Font_inv ;Zeichensatz normal/invers, je 128 Zeichen ;(Achtung: muss vom Zeichensatz unterstützt werden) ;Farben für gfxmode .equ black =0 ;Hintergrund .equ white =255 ;Vordergrund .equ invert =254 ;Invertieren ; Video Mode 0: (44*34) eolsupport mit übergroßem Bildschirm ; Max. Größe für LCD-TV #ifdef vmode_0 .equ XSize =44 ;Bildgröße in X Richtung in Nibbles .equ YSize =34 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =161 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =26 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 1: (40*32) eolsupport mit übergroßem Bildschirm #ifdef vmode_1 .equ XSize =40 ;Bildgröße in X Richtung in Nibbles .equ YSize =32 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =32 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 2: (40*25) original tvtext modus #ifdef vmode_2 .equ XSize =40 ;Bildgröße in X Richtung in Nibbles .equ YSize =25 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =54 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 3: (40*25) Eine Leerzeile #ifdef vmode_3 .equ XSize =40 ;Bildgröße in X Richtung in Nibbles .equ YSize =25 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =1 ;Leerzeilen zwischen Zeilen ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =42 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 4: (40*20) mit Leerzeilen #ifdef vmode_4 .equ XSize =40 ;Bildgröße in X Richtung in Nibbles .equ YSize =20 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =3 ;Leerzeilen zwischen Zeilen ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =48 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 5: (40*16) mit Leerzeilen #ifdef vmode_5 .equ XSize =40 ;Bildgröße in X Richtung in Nibbles .equ YSize =16 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =5 ;Leerzeilen zwischen Zeilen ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =50 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 6: (32*24) mit Leerzeilen #ifdef vmode_6 .equ XSize =32 ;Bildgröße in X Richtung in Nibbles .equ YSize =24 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =260 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =54 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 7: (32*24) mit Leerzeilen und Zeichenabstand #ifdef vmode_7 .equ XSize =32 ;Bildgröße in X Richtung in Nibbles .equ YSize =24 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =1 ;Leerzeilen zwischen Zeilen ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile #define h_blank ;Abstand zwischen Zeichen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =44 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 8: (32*16) #ifdef vmode_8 .equ XSize =32 ;Bildgröße in X Richtung in Nibbles .equ YSize =16 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =5 ;Leerzeilen zwischen Zeilen ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile #define h_blank ;Abstand zwischen Zeichen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =50 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 9: (20*16) stretch_x modus #ifdef vmode_9 .equ XSize =20 ;Bildgröße in X Richtung in Nibbles .equ YSize =16 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =5 ;Leerzeilen zwischen Zeilen #define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =50 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 10: (20*10) #ifdef vmode_10 .equ XSize =20 ;Bildgröße in X Richtung in Nibbles .equ YSize =10 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =12 ;Leerzeilen zwischen Zeilen #define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =50 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 11: (16*8) Kombination von stretch_x und h_blank #ifdef vmode_11 .equ XSize =16 ;Bildgröße in X Richtung in Nibbles .equ YSize =8 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =20 ;Leerzeilen zwischen Zeilen #define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile #define h_blank ;Abstand zwischen Zeichen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =50 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 12: (40*16) #ifdef vmode_12 .equ XSize =40 ;Bildgröße in X Richtung in Nibbles .equ YSize =16 ;Bildgröße in Y Richtung pro Halbbild .equ Height =16 ;Zeichenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen #define Font8x16 ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =186 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =36 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 13: (40*12) #ifdef vmode_13 .equ XSize =40 ;Bildgröße in X Richtung in Nibbles .equ YSize =12 ;Bildgröße in Y Richtung pro Halbbild .equ Height =16 ;Zeichenhöhe .equ Blanks =5 ;Leerzeilen zwischen Zeilen #define Font8x16 ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =186 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =40 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 14: (20*12) #ifdef vmode_14 .equ XSize =20 ;Bildgröße in X Richtung in Nibbles .equ YSize =12 ;Bildgröße in Y Richtung pro Halbbild .equ Height =16 ;Zeichenhöhe .equ Blanks =5 ;Leerzeilen zwischen Zeilen #define Font8x16 #define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =180 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =40 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 15: (40*12) #ifdef vmode_15 .equ XSize =40 ;Bildgröße in X Richtung in Nibbles .equ YSize =12 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =2 ;Leerzeilen zwischen Zeilen ;#define Font8x16 #define stretch_y ;Pixel doppelt hoch, Zeile doppelt ausgeben ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =186 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =40 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 16: (20*12) #ifdef vmode_16 .equ XSize =20 ;Bildgröße in X Richtung in Nibbles .equ YSize =12 ;Bildgröße in Y Richtung pro Halbbild .equ Height =8 ;Zeichenhöhe .equ Blanks =2 ;Leerzeilen zwischen Zeilen ;#define Font8x16 #define stretch_y ;Pixel doppelt hoch, Zeile doppelt ausgeben #define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =180 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =40 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 17: (20*8) #ifdef vmode_17 .equ XSize =20 ;Bildgröße in X Richtung in Nibbles .equ YSize =8 ;Bildgröße in Y Richtung pro Halbbild .equ Height =16 ;Zeichenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen #define Font8x16 #define stretch_y ;Pixel doppelt hoch, Zeile doppelt ausgeben #define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile ;#define h_blank ;Abstand zwischen Zeichen .equ XStart =180 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =36 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ; Video Mode 18: (32*8) #ifdef vmode_18 .equ XSize =32 ;Bildgröße in X Richtung in Nibbles .equ YSize =8 ;Bildgröße in Y Richtung pro Halbbild .equ Height =16 ;Zeichenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen #define Font8x16 #define stretch_y ;Pixel doppelt hoch, Zeile doppelt ausgeben ;#define stretch_x ;Pixel doppelt breit, halbe Zeichenzahl/Zeile #define h_blank ;Abstand zwischen Zeichen .equ XStart =190 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =36 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif #ifdef gfxmode_1 #define gfxmode #define gfx_w1 .equ XSize =10 ;Anzahl Bytes/Zeile .equ YSize =64 ;Anzahl Zeilen .equ Height =4 ;Zelenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen .equ XStart =160 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =32 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif #ifdef gfxmode_2 #define gfxmode #define gfx_w1 #define gfxpix .equ XSize =10 ;Anzahl Bytes/Zeile .equ YSize =64 ;Anzahl Zeilen .equ Height =3 ;Zelenhöhe .equ Blanks =1 ;Leerzeilen zwischen Zeilen .equ XStart =160 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =32 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif #ifdef gfxmode_3 #define gfxmode ;#define gfx_w1 .equ XSize =10 ;Anzahl Bytes/Zeile .equ YSize =64 ;Anzahl Zeilen .equ Height =4 ;Zelenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen .equ XStart =220 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =32 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif #ifdef gfxmode_4 #define gfxmode ;#define gfx_w1 #define gfxpix .equ XSize =10 ;Anzahl Bytes/Zeile .equ YSize =64 ;Anzahl Zeilen .equ Height =3 ;Zelenhöhe .equ Blanks =1 ;Leerzeilen zwischen Zeilen .equ XStart =220 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =32 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif #ifdef gfxmode_5 #define gfxmode .equ XSize =11 ;Anzahl Bytes/Zeile .equ YSize =72 ;Anzahl Zeilen .equ Height =3 ;Zelenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =52 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif #ifdef gfxmode_6 #define gfxmode #define gfxpix .equ XSize =11 ;Anzahl Bytes/Zeile .equ YSize =72 ;Anzahl Zeilen .equ Height =2 ;Zelenhöhe .equ Blanks =1 ;Leerzeilen zwischen Zeilen .equ XStart =200 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =52 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif #ifdef gfxmode_7 #define gfxmode .equ XSize =12 ;Anzahl Bytes/Zeile .equ YSize =80 ;Anzahl Zeilen .equ Height =3 ;Zelenhöhe .equ Blanks =0 ;Leerzeilen zwischen Zeilen .equ XStart =160 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =44 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif #ifdef gfxmode_8 #define gfxmode #define gfxpix .equ XSize =12 ;Anzahl Bytes/Zeile .equ YSize =80 ;Anzahl Zeilen .equ Height =2 ;Zelenhöhe .equ Blanks =1 ;Leerzeilen zwischen Zeilen .equ XStart =160 ;Anzahl an CPU Takten zwischen Beginn HSync und Bild- ;beginn (mindestens 30, und mindestens HSyncbreite) .equ BPSize =44 ;VSync Back Porch in Zeilen (Y Verschiebung) #endif ;Horizontal .equ SyncWidth =75 ;Anzahl an CPU Takten für HSync ;Vertikal .equ VSize =4 ;VSync Impuls in Zeilen ;Interne Konstanten #ifdef stretch_y ;Zeile doppelt ausgeben .equ BildSize =YSize*(Height+Blanks)*2 ;Bildhöhe in Zeilen .equ BildStart =313-BildSize+YSize ;Bildhöhe in SyncZeilen+Zeichen ;(interner Zähler) .equ FPSize =(313-YSize*(Height+Blanks)*2)-VSize-BPSize ;Frontporchbreite in Zeilen .equ FPStart =YSize ;Frontporch Start in internen Zählerzeilen .equ VSStart =FPStart+FPSize ;Vsyncstart in internen Zählerzeilen .equ BPStart =VSStart+VSize ;Backporchstart in internen Zählerzeilen #else ;stretch_y .equ BildSize =YSize*(Height+Blanks) ;Bildhöhe in Zeilen .equ BildStart =313-BildSize+YSize ;Bildhöhe in SyncZeilen+Zeichen ;(interner Zähler) .equ FPSize =(313-YSize*(Height+Blanks))-VSize-BPSize ;Frontporchbreite in Zeilen .equ FPStart =YSize ;Frontporch Start in internen Zählerzeilen .equ VSStart =FPStart+FPSize ;Vsyncstart in internen Zählerzeilen .equ BPStart =VSStart+VSize ;Backporchstart in internen Zählerzeilen #endif ;stretch_y ;.equ BildSize =YSize*(Height+Blanks) ;Bildhöhe in Zeilen ;.equ BildStart =313-BildSize+YSize ;Bildhöhe in SyncZeilen+Zeichen ; ;(interner Zähler) ;.equ FPSize =(313-YSize*(Height+Blanks))-VSize-BPSize ; ;Frontporchbreite in Zeilen ;.equ FPStart =YSize ;Frontporch Start in internen Zählerzeilen ;.equ VSStart =FPStart+FPSize ;Vsyncstart in internen Zählerzeilen ;.equ BPStart =VSStart+VSize ;Backporchstart in internen Zählerzeilen .dseg ;Sicherung der im Interrupt geänderten Register s_xh: .byte 1 s_xl: .byte 1 s_zh: .byte 1 s_zl: .byte 1 s_zh_line: .byte 1 s_sreg: .byte 1 s_X_Cnt: .byte 1 s_tempi: .byte 1 ;Daten der Interrupt-Routine m_Y_Cnt: .byte 1 m_C_Cnt: .byte 1 m_tvptrh: .byte 1 ;Zeiger auf auszugebendes Zeichen (xh/xl) m_tvptrl: .byte 1 tvstarth: .byte 1 ;Bildspeicher Startadresse tvstartl: .byte 1 frame: .byte 1 ;Zählt TV-Bilder (50/Sekunde) #ifdef gfxmode DDRAM: .byte XSize*YSize ;DDRAM #else ;gfxmode #ifdef eolsupport DDRAM: .byte tvmem ;DDRAM #else DDRAM: .byte XSize*YSize ;DDRAM #endif #endif ;gfxmode ;********************************************* ; Makros ;********************************************* .macro nops ;Pixelbreite mit NOP vergrößern #ifdef gfx_w1 nop ;nop ;nop #else ;gfx_w1 ;nop ;nop #endif ;gfx_w1 .endmacro .macro lnops ;Pixelausgleich, letztes Pixel #ifdef gfx_w1 nop #endif ;gfx_w1 ; nop nop nop #ifdef gfxpix cbi PORTB, DOUT ;Bild: schwarz (gfxmode LCD Design) #else nop nop #endif nop .endmacro .macro dnops ;Pixelausgleich zwischen Pixeln nop lnops .endmacro ;**************************************************************************** ; Interrupt Vektoren ;**************************************************************************** .cseg .org 0 rjmp Reset .org OC1Aaddr ;Bildbeginn ;****************************************** ; register save - part 1 - critical timing ;****************************************** ; push tempi sts s_tempi,tempi in tempi, sreg sts s_sreg, tempi sts s_zh,zh sts s_zl,zl sts s_X_Cnt,X_Cnt lds tempi,m_Y_Cnt cpi tempi,YSize ;Bildbereich oder schon VSync + Zubehör ? brlo lineout rjmp handle_VSync lineout: in ZL, TCNT1L ;Timerwert lesen in ZH, TCNT1H .equ ticks=3 ;-2 .. 3 (möglichst hoch setzen) subi ZL, low(XStart+ticks-comp) ;und Korrekturwert berechnen sbci ZH, high(XStart+ticks-comp) ijmp ;Wartezeit korrigieren nop nop nop nop nop nop nop nop nop nop nop nop nop ; nop ; nop ; nop ; nop comp: ;##100902 ;********************************************* ; register save - part 2a - noncritical timing ;********************************************* sts s_xh,xh ; save xh/xl sts s_xl,xl lds xh,m_tvptrh ; load pointer to actual character into xh/xl lds xl,m_tvptrl ;********************************************* ; Eine Bildzeile im Grafikmodus ausgeben ;********************************************* #ifdef gfxmode ;comp: ;##100902 lds ZH,s_zh_line lds tempi,m_C_Cnt ;insert optionally blank lines cpi tempi,Blanks+1 brsh gfxstart rjmp skiphloop gfxstart: ldi tempi, XSize mov X_Cnt, tempi hloop: ;Loop für 1 Zeile ld tempi, X+ ;2 ASCII aus RAM lesen 2 #ifdef gfxpix cbi PORTB, DOUT ;Bild: schwarz (gfxmode LCD Design) #else nop nop #endif rol tempi ;1 out PORTB, tempi ;1 Bit 0 ror tempi ;1 nops dnops out PORTB, tempi ;1 Bit 1 ror tempi ;1 nops dnops out PORTB, tempi ;1 Bit 2 ror tempi ;1 nops dnops out PORTB, tempi ;1 Bit 3 ror tempi ;1 nops dnops out PORTB, tempi ;1 Bit 4 ror tempi ;1 nops dnops out PORTB, tempi ;1 Bit 5 ror tempi ;1 nops dnops out PORTB, tempi ;1 Bit 6 ror tempi ;1 dec X_Cnt ;1 nops lnops out PORTB, tempi ;1 Bit 7 nops #ifdef gfx_w1 breq gfxend ;1/2 rjmp hloop ;2 #else ;gfx_w1 brne hloop #endif ;gfx_w1 gfxend: nop ;1 Letztes Pixel zeichnen nop ;1 nop ;1 #ifndef gfxpix nop ;1 nop ;1 #endif skiphloop: cbi PORTB, DOUT ;Bild: schwarz ;********************************************* ; Eine Bildzeile im Textmodus ausgeben ;********************************************* #else ;gfxmode push spian push spiaus #ifdef mega16 ldi spian, (1< nächste Pixelzeile #ifdef stretch_y cpi tempi,Blanks*2+1 #else ;stretch_y cpi tempi,Blanks+1 #endif ;stretch_y ;cpi tempi,Blanks+1 brlo blankskip ;Keine Adressänderung bei Leerzeilen lds XL,m_tvptrl ;Textadresse wieder an Anfang der Textzeile setzen lds XH,m_tvptrh blankskip: rjmp exit_int skipcloop: ;Alles für neue Textzeile einrichten #ifndef gfxmode #ifdef stretch_y ;##100902 ldi ZH, font >> 6 ;ROM Font address high byte #else ;stretch_y ldi ZH, font >> 7 ;ROM Font address high byte #endif ;stretch_y #endif ;gfxmode #ifdef stretch_y ;Zeile doppelt ausgeben ldi tempi, (Height+Blanks)*2 ;Zeichenhöhen Counter laden #else ;stretch_y ldi tempi, Height+Blanks ;Zeichenhöhen Counter laden #endif ;stretch_y ; ldi tempi, Height+Blanks ;Zeichenhöhen Counter laden sts m_C_Cnt,tempi lds tempi,m_Y_Cnt ;Zeilencounter erhöhen inc tempi sts m_Y_Cnt,tempi rjmp exit_int handle_VSync: ;********************************************* ; register save - part 2b - noncritical timing ;********************************************* sts s_xh,xh sts s_xl,xl lds ZH,s_zh_line inc tempi ;Zeilenzähler erhöhen sts m_Y_Cnt,tempi cpi tempi, VSStart ;Beginn VSync ? breq VSyncstart cpi tempi, BPStart ;Ende VSync ? breq VSyncende cpi tempi, BildStart ;Bildende ? brsh Bildbeginn rjmp exit_int VSyncstart: ldi tempi, (1<' st Y+, temp ldi temp,0 st Y+, temp ldi temp,'>' st Y+, temp st Y+, temp ldi temp,0 st Y+, temp ldi temp,'>' st Y+, temp ldi temp,0 st Y+, temp ; ASCII Codes ldi temp, 32 clrloop: st Y+, temp tst temp ;Hinter 0 Zeilenumbrüche einfügen für EOLSupport brne nozero ldi xl,0 ldi xh,'>' st Y+, xh st Y+, xl st Y+, xh st Y+, xh st Y+, xl st Y+, xh st Y+, xl nozero: inc temp #ifdef eolsupport ldi temp2, high(tvmem+DDRAM) cpi YL, low(tvmem+DDRAM) #else ldi temp2, high(XSize*YSize+DDRAM) cpi YL, low(XSize*YSize+DDRAM) #endif cpc YH, temp2 brlo clrloop #endif ;gfxmode #else ;#def demo ; ASCII Codes ldi temp, 32 clrloop: st Y+, temp inc temp #ifdef eolsupport ldi temp2, high(tvmem+DDRAM) cpi YL, low(tvmem+DDRAM) #else ldi temp2, high(XSize*YSize+DDRAM) cpi YL, low(XSize*YSize+DDRAM) #endif cpc YH, temp2 brlo clrloop #endif ldi XL, low(DDRAM) ldi XH, high(DDRAM) sts tvstarth,xh ;save tv screen start pointer sts tvstartl,xl sts m_tvptrh,xh sts m_tvptrl,xl ldi temp, (1<