Grafik Library fr das Nokia 6100 Farbdisplay und kompatible. Version 1.1.
Copyright 2004 Hagen Reddmann, HaReddmann at T-Online dot de

Dank geht an F. Maximilian Thiele aka Ape, me at apetech dot de 
http://www.apetech.de/nokia6100.php


Das Nokia ist ein 132x132x4096 Farben Display das bei eBay ziemlich preiswert ersteigert werden kann.
Bitte ersteigert nur die Display bei denen man die braune flexible Leiterplatte sieht, ansonsten knnt ihr nicht
die Kabel einfach anlten. 
Das Display nutzt eine serielle Datenertragung per SPI aber mit intern verschalteter MOSI/MISO line.
Der PCF8833 kann mit einer maximalen SPI Datenrate von 6.5 MHz bedient werden. Allerdings habe ich mein 
Display ohne Problem nun schon seit Tagen mit einem ATMega32 auf 8Mhz SPI zum laufen.


Hier nun eine Grafik Library in WinAVR C.

Das ZIP sollte mit Option Ordnern entpacken, entpackt werden.
Der Test Source, in ..\test\, wurde fr ein ATmega32 at 16Mhz compiliert. Er kann mit einigen Einschrnkungen in den 
verfgaren Fonts sofort fr den ATMega8 compiliert werden. Dazu sollte im MakeFile die MCU auf ATMega8 gesetzt werden,
und im Header File glcd.h der Wert DELAY_ONE_MILLISECOND an die Taktfrequenz angepasst werden.
Fr andere MCU msst ihr die PORT Einstellungen im Headerfile ndern.

Was kann die Library ?
- Pixel setzen
- Linien zeichnen
- Rechtecke fllen, mit Border
- Ellipsen und Kreise zeichnen, ebenfalls fllen und Border
- Proportionale und Fixed Fonts mit mehreren Farben darstellen
- Zeichenausgaben knnen mit Hilfe eines separaten Fenster (glcd_Window) formatiert werden.
- zur Erstellung eigener Fonts habe ich einen kleinen Font Editor programmiert
- mit Hilfe von groen Fonts knnen Icons/Bitmaps dargestellt werden
- alle Ausgaben knnen durch ein separates Clipping Rect beschnitten werden
- alle Ausgaben ans Display knnen 0, 90, 180 oder 270 rotiert werden
- alle Grafikfunktionen untersttzen transparentes zeichnen
- Hardware Scrolling
- standardmig ist die Farbanzahl des Display auf 256 Farbmodus reduziert. Dies kann aber mit leichten nderungen
  am Source auf 12Bit oder sogar 16Bit Farbmodus erhht werden. 
- Da bis auf ganz wenige Funktionen alle Funktionen Hardwareunabhnig sind knnen alle Zeichenroutinen fr andere
  GLCD's benutzt werden.


Was kann die Library niemals ?
- alle Operationen die eine direkte Verkpfung der Pixeldaten im RAM des Controllers durchfhren, knnen mit dem
  PCF8833 nicht programmiert werden. Es gibt keine Mglichkeit den RAM des Controllers auszulesen.
- solche Operationen mssten dann also mit Hilfe eines Display-RAMs in der MCU erledigt werden. Allerdings ist dies
  fr die kleinen AVR's und dem "langsammen" SPI untragbar.
  
  
Nun noch einige wichtige Interna's:

Auf Grund der Gegebenheiten unterscheidet sich diese Library in dem Handling der Koordinaten.
Normalerweise wrde ein Rechteck mit den Koordinaten 10,10,100,100 auf dem Display die Pixel innerhalb 10,10,99,99 fllen. 
Also die Pixelspalte 10 bis 99 und Pixelzeilen 10 bis 99. Dies ist vergleichbar mit einem Clippingrect von 10,10,100,100.
Nun meine Library zeichnet aber die Spalten 10 bis 100 und Zeilen 10 bis 100 und das dazugehrige Clippingrect ist 10,10,100,100. D.h. alle Pixeloperationen beziehen sich immer inklusive der Koordinaten.
Diese Vorgehenweise ist notwendig da das Nokia LCD einen Pixelbereich von 132x132 zulsst. Es zeigt zwar nur die Pixel im Bereich (1,1,130,130) an, d.h. das LCD selber ist ein 130x130 Teil, aber im Falle des Hardware Scrollings werden die zustzlichen 2 Pixelzeilen als Buffer benutzt. Diese Pixelzeilen befinden sich normalerweise MITTEN im RAM, zwischen dem Middle Scroll und Bottom Scroll Area. In diesem Moment mssen wir also fr das Top Scroll Area in der Pixelspalte 0 statt 1 beginnen zu zeichnen. Mehr dazu kann man im Datenblatt des PCF8833 nachlesen, oder im main.c Source.


Die Grafiklibrary stellt verschiedene globale Variablen zur Verfgung.

  glcdColor_t     glcd_Colors[1 << COLOR_TABLE_BITS];

    Farbtabelle. In dieser normalerweise 4 Farben fassenden Tabelle stehen die Fraben fr die verschiedenen Zeichenroutinen.
    glcd_Colors[0] ist der Hintergrung, eg. die Fllfarbe fr Rechtecke oder Elipsen oder Fonts.
    glcd_Colors[1] ist die Vordergrundfarbe, also die Linienfarbe fr Linien, Rechtecke, Ellipsen oder Fonts.
    glcd_Colors[2] ist die Rahmenfarbe fr glcdFrame() oder die 3. Fontfarbe fr 4 Farben Fonts.
    glcd_Colors[3] ist die Schattenfarbe fr glcdFrame() oder die 4. Fontfarbe fr 4 Farben Fonts.
    Jede dieser Farbeintrge kann auf NONE gesetzt werden. Zb. glcdSetBkColor(NONE) setzt glcd_Colors[0] = NONE. Ein Rechteck,
    oder Ellipse oder Font oder Frame wrde also transparent gezeichnet.
    Es gibt einige Makros im Header zur Vereinfachung des Farbzugriffes auf diese Farbtabelle. Normalerweise sollte man immer
    diese Makros benutzen da dadurch der Source portable bleibt.
    glcdBkColor, glcdFgColor, glcdFrColor, glcdShColor sind Substitutionen um auf die Eintrge in der Farbtabelle lesend zuzugreifen.
    Mit glcdSetColor(Index, Color), glcdSetBkColor(color), glcdSetFgColor(color), glcdSetColors(FgColor, BkColor) wird schreibend
    zugegriffen. ber das #define COLOR_TABLE_BITS kann diese Farbtabelle in der Gre an die Erfordernisse angepasst werden. Sollten
    zB. Fonts mit mehr als 4 Farben benutzt werden so mu sogar dieser Wert gendert werden.


  uint8_t         glcd_MemCtrl;

    Hardwareabhnige Variable die den Speicherzugriffsmodus des PCF8833 festlegt. Damit wird auch das Farbformat des LCD eingestellt.


  glcdFlags_t     glcd_Flags;

    glcd_Flags.AutoLineFeed, wenn 1 wird bei der Zeichenausgabe ein automatischer Zeileumbruch durchgefhrt. Dabei wird glcd_Cursor
    automatisch innerhalb glcd_Window bewegt, sobald eine Textausgabe die glcd_Cursor bewegt ausserhalb von glcd_Window gert.

    glcd_Flags.FixedFont, wenn 1 wird der aktuelle Font als Font mit fester Zeichenbreite gezeichnet. Ansonsten werden die Zeichen im
    proportionalen Modus gezeichnet. Der propoertionale Modus bringt ein besseres Bild und spart Platz. Grundstzlich sind alle Font's
    von Hause aus proportionale und fixed Fonts, aber dazu spter mehr...


  glcdPoint_t     glcd_Cursor;        

    aktuelle Position fr Schriften. Mit glcdMoveTo(x, y) wird der Cursor gesetzt. Beachtet das keinerlei interne berprfungen
    gemacht werden ob der Cursor sichtbar ist, also innerhalb glcd_Window und glcd_Clip.

  glcdRect_t      glcd_Window;         

    aktuelles Fenster fr Textausgaben, innerhalb dieser Grenzen wird glcd_Cursor bei glcd_Flags.AutoLineFeed bewegt.
    Man sollte ber glcdSetRect(glcd_Window, x1, y1, x2, y2); auf dieses Rect zugreifen.

  glcdRect_t      glcd_Clip;
     Clipping Koordinaten, alle Grafikausgaben ausserhalb dieser Grenzen werden beschnitten. Angenommen glcd_Clip wird mit
     glcdSetRect(glcd_Clip, 10, 10, 50, 60); gesetzt, dann wird alles innerhalb und inklusive der Spalten 10 bis gleich 50, und
     den Pixelzeilen 10 bis gleich 60 beschnitten. D.h. also was ausserhalb von (10, 10, 50, 60) ist wird nicht dargstellt.

  char            glcd_FontFirstChar;   // erstes Zeichen im Font
  char            glcd_FontLastChar;    // letztes Zeichen im Font
  uint8_t         glcd_FontWidth;       // fixed Zeichenbreite des Fonts
  uint8_t         glcd_FontHeight;      // Zeichenhhe
  uint8_t         glcd_FontBitsPixel;   // Farbtiefe des Fonts
  glcdFontFunc_t  glcd_FontRead;        // User definierte Readcallback fr die Fontdaten
  glcdFontData_t  glcd_FontData;        // die eigentlichen Fontdaten beginnen hier, abhngig von der Readcallback

     diese Variablen definieren alles was ntig ist um die Fontausgaben zu realisieren.
     Eine Fontdatei besteht aus einem Header, der Zeichenbreiten-Tabelle und die Bitdaten der Zeichen.
     Der Header enthlt:

     // fr alle Fonttypen gemein
       uint16_t FileSize;        // Bytegre der Daten inklusive FileSize, linear im Speicher nacheinander abgelegte Fonts knnen
                                 // somit durchiteriert werden.
       uint8_t  FontWidth;
       uint8_t  FontHeight;
       uint8_t  BitsPerPixel;    // Farbtiefe des Fonts, nur 1,2,8 werden zZ. untersttzt, spich 2,4 und 256 Farben.
                                 // falls das MSB gesetzt ist so wurde der Font komprimiert gespeichert
       char     FontFirstChar;   // das erste Zeichen im Font
       char     FontLastChar;    // das letzte Zeichen im Font
       
       uint8_t  CharWidths[FontLastChar - FontFirstChar +1]; // diese array enthlt die Zeichenbreite pro Zeichen,
                                                             // undefinierte Zeichen haben Breite 0
   
     // falls der Font komprimiert ist
       uint8_t  BytePadding;     // jeder Datenblock zu einem Zeichen wird auf ein Vielfaches von BytePadding ausgerichtet
       uint8_t  RLETable[3];     // dynamische Run Length Tabelle
       uint8_t  CharByteSizes[FontLastChar - FontFirstChar +1]; // zu jedem Zeichen die Byteanzahl / BytePadding

     // wieder fr alle Fonttypen gleich
       uint8_t  FontBits[];  // die Bitmapdaten des Fonts. Dabei werden Spaltenweise die Bits pro Zeichen nacheinander ohne irgendwelches
                             // Padding gespeichert, bei unkomprimierten Fonts. 


    Alle Zeichen eines Font's kleiner #128 sind Textsymbole und haben am rechten Rand eine virtuelle Leerspalte an Pixel'n. D.h. diese
    Leerspalte wird NICHT in den Fontdaten gespeichert sondern zur Laufzeit in der Zeichenroutine hinzugefgt. Damit sparen wir gerade
    im Proportionalem Modus einiges an Speicher. Zustzlich kann im Fixed Modus das Zeichen besser zentriert werden.
    Alle Zeichen >= #128 besitzen diese Leerspalte NICHT. Im OEM Zeichensatz knnen so die Terminalchars, eg. Blockzeichen zu textuellen
    Formatierungen von Rahmen usw. lckenlos dargestellt werden. Eine Terminalsimulation ist also ohne Probleme mglich.
    Weitestgehend entspricht diese Vorgehensweise den alten EGA,VGA Karten.
    Ein 8x11 2 Farbenfont mit 95 Zeichen belegt mit dieser Struktur nur ca. 684 Bytes statt ca. 1147 Bytes. Der Berechnungsoverhead zur 
    Laufzeit ist minimal grer.
    Die Fonts benutzen eine Callback zum Lesen der Fontdaten. Jedesmal beim Selektieren eines Font's ber glcdSelectFont() mu diese
    Lese-Callback bergeben werden. Man kann nun eigene Callback's schreiben die z.B. die Fontdaten aus externen I2C EEPROMS o.. holen.
    Alle Aufrufe dieser Callback, und das verwendete Font-Format, wurden dahingehend optimiert das die Leseoperationen sequentiell
    erfolgen. Somit kann man die Benutzer-Callback so aufbauen das zB. I2C EEPROM's in Blcken ausgelsen werden knnen ohne das man
    den Chip und die Speicheradresse jedesmal neu selektieren mu. Lineares Lesen von I2C EEPROM Fonts ist also mglich.   
    Beim Zeichnen eines Zeiches werden insgesammt drei lineare Blcke aus den Fontdaten gelesen. Als erstes 1 Byte mit der Zeichenbreite,
    dann x Bytes = (aktuelles Zeichen - FontFirstChar -1) sequentiell in die Zeichenbreiten-Tabelle oder Zeichengren-Tabelle, 
    danach noch ein Block sequentiell mit den Fontdaten zum Zeichen. Bei unkomprimierten Fonts sind das 
    (Zeichenbreite * Fonthhe * BitsPerPixel + 7) / 8 Bytes. Bei komprimierten Fonts sind das CharByteSizes[Zeichen - FontFirstChar] Bytes.

 
  Fragen und Anregungen bitte an obige EMail Adresse.

Gru Hagen


Changes:

Version 2.0.

Diese Version ist eine komplett berarbeitete und vollstndig verbesserte Version. Alle Funktionen wurden in handmade Assembler geschrieben.

Dadurch ergeben sich mehrere Vorteile:

1.) die Grafikfunktionen bentigen wesentlich weniger Speicher. Im besten Falle wird die Gre des eingelinkten Codes ca. 600 Bytes bentigen
um damit schon das LCD ansteuern zu knnen und Rechtecke ausfllen zu knnen. Im Falle das ALLE Funktionen bentzt werden bentigt die Library
nur 2800 Bytes. Die Version 1.1. Libary in reinem WinAVR C Source, mit wesentlich schlechteren und wenigeren Features bentigte mindestens 
4500 Bytes an Code !! Somit bentigt die neue Library nur noch 50% an Resourcen und ist zudem noch leistungsfhiger.

2.) die Library ist nun eine echte Link-Bibliothek. Dies bedeutet das nur Funktionen in das fertige Program eingelinkt werden die auch tatschlich bentigt werden.

3.) durch die Mglichkeiten in Assembler ergeben sich besondere Features wie eben die automatische Initialisierng des Display im Startup Code des
Programmes. D.h. im Normalfalle ist ein Aufruf der Funktion glcdDisplayInit() nicht ntig, da dies autom. durch den Startup Code erfolgt.
Gleiches gilt fr die globale Initialisierung der Library Daten.

Was ist neu !?

- glcdDisplayInit() initialisiert nur noch das Display, wichtig! ist das der Display RAM nicht mehr automatisch gelscht wird, d.h. es ist
  Aufgabe des Anwenders zu einem passenden Zeitpunkt glcdClearScreen() aufzurufen oder aber einfach das Display RAM zu befllen.
- glcdDisplayOn() schaltet das Display ein und mu vom Anwender der Lib manuell aufgerufen werden
- glcdDisplayOff() schaltet das Display/Booster aus.
- glcdDisplayBuffer() kann Speicherdaten Blockweise an das Display senden, gnstig fr eigene Bitmap Funktionen
- glcdDisplaySetColors() kann die Farbtabelle zum mappen im 8 Bit Farbmodus setzen
- glcdWait() ist absolut exakt (ohne Interrupts), dessen Wartezeit betrgt exakt x Millisekunden + 2 Taktzyklen fr den Aufruf der Funktion
- glcdSetOrientation() und glcd_MemCtrl wurden um 2 zustzliche virtuelle Flags erweitert die die aktuelle Ausrichtung des Displays enthalten
- glcdClearScreen() hat nun einen Parameter der angibt ob das Clipping bercksichtigt werden soll oder nicht. Wird <> 0 bergeben so wird
  glcdClearScreen() das aktive ClipRect nicht bercksichtigen.
- glcdSelectFont() kann ohne Callback aufgerufen werden, sprich Callback == 0 bedeutet das die Lib den Font aus dem Flash liest.
- glcdCharsCallback() ist eine neue Funktion mit deren Hilfe Strings ber eine Callback berechnet oder auf gezeichnet werden knnen.
  Diese Funktion ist Kernstck fr die neuen Funktionen glcdPrint() und glcdCharsWidth().
- glcdPrint() zeichnet einen nullterminierten String auf dem Display. Der String kann im RAM oder FLASH gespeichert sein.
- glcdCharsWidth() berechnet die Breite in Pixeln eines Strings. Der String kann im RAM oder FLASH gespeichert sein.
- glcdPut() ist eine Funktion die in fdevopen() als Devicehandler benutzt werden kann.
- die Wartezeit in glcdDisplayInit() wurde auf Grund von nderungen an der Initialisierung von 65 Millisekunden auf 5 ms reduziert.
- es kann nun auch der 65535 Farben Modus eingestellt werden
- das Clipping kann deaktiviert werden
- glcdEllipse(), glcdLine() und alle Font Routinen sind erheblich beschleunigt wurden und bentigen zur Laufzeit wesentlich weniger Stack.
- glcdEllipse() nutzt einen besseren Algorithmus als in Version 1.1.
- glcdLine(), der Algo. konnte in Assembler wesentlich effizienter gestaltet werden als in C mglich
- glcd_Flags.Clipping ist neu und bestimmt ob das Clipping aktiv oder deaktivert ist. Standardmig ist das Clipping deaktiviert, es mu also
  explizit aktiviert werden um wirksam zu werden.
- glcd_Flags ist nun eine Union, und ber ads Member .All knnen in einem Rutsch alle Flags gesetzt werden.
- glcdPutPixel() bentigt vor dessen Aufruf einen Aufruf von glcdSetAddr(), nach diesem Aufruf kann innerhalb dieser Koordinaten sequentiell
  Pixels gesetzt werden.
- glcdDisplayBuffer() kann aber glcdPutPixel() ersetzen und einen ganzen Puffer voll Pixel in einem Rutsch setzen. In der DEMO gibts dazu ein
  Beispiel.
- glcdDisplayRead() ist neu und kann daten vom Display abfragen.
- meine LSFR-SG Zufallsgenerator Implementierung ist in die Lib integriert wurden.
- der LFSR kann so konfiguriert werden das die beiden Polynome S,A dynamisch zur Laufuzeit nderbar sind. Dadurch ist die Benutzung des LFSR's
  fr Kryptographie mglich.
- in glcd.inc wurden Makro's integriert zur Erzeugung von RGB Farbwerten, abhnig vom gewhlten Farbmodus der Bibliothek.
- Die Bibliothek nutzt jetzt IMMER den SPI Interrupt. Es zeigte sich das es wichtig ist das Chip Select Signal des PCF8833 zurckzusetzen nach  
  einer Datenbertragung.
- sollte der gcc Linker Probleme bekommen mit den Relocation der Funktionen so kann ber das Define USE_FAR_JUMP auf Enhanced AVR's die 
  Long Jumps/Calls aktiviert werden, danach sollte die Lib auf jedem BIG-AVR laufen.
- die Bibliothek ist in weiten Teilen so codiert das sie auf den meisten AVR's laufen sollte, SPI vorausgesetzt.
- es gibt in der include glcd.inc und im header glcd.h einige DEFINES ber denen die Lib konfiguriert werden kann. Jede nderung dieser
  Defines bentigt eine Recompilation der Library.

USE_HIGHCOLOR        65535 Farben benutzen, dabei gibt es 4096 Echtfarben und der Rest wird durch den PCF8833 gedithert
USE_ORGINALCOLORS    im 256 Farbenmodus wird dadurch das Original-Farb-Mapping benutzt.
COLOR_TABLE_BITS     die Anzahl 2^x an farben in der internen Farbtabelle. Will man zB. 16 Farbige Fonts benutzten so mu dieser Wert auf 4 stehen.	
SCREEN_COLOR0
SCREEN_COLOR1
SCREEN_COLOR2
SCREEN_COLOR3	     die 4 Standardfarben fr eine 4 Farbtabelle. Diese Werte werden durch den Initialisierungscode autom. in die Farbtabelle
                     kopiert. Durch nderung dieser Werte kann man also einiges an zustzlichen Code sparen.	
ORIENTATION_DEFAULT  die Standardausrichtung des Displays. Auch dieser Wert dient zur autom. Initialisierung und kann zus. Code sparen
USE_CLIPPING         fr sehr kompakte Anwendungen kann das implizite dynamsiche Clipping deaktiviert werden. Dies kann bis zu 
                     600 Bytes an Code sparen.
XTAL                 die Taktfrequenz des Targetdevice, sollte im Makefile gendert werden





Version 1.1.
- komprimierte Fonts sind nun mglich, die Kompressionsrate betrgt zwischen 30% bis zu 50% und bei ganz groen Fonts sogar weit ber 200%.
  Mit meinen Mehrfarben-Fonts konnte ich mehr als die Hlte an Speicher einsparen.
- Fontroutinen wurden becleant und sind jetzt effizienter
- Fontroutinen untersttzen nun auch Fonts mit 8,16,32,64,128 und 256 Farben, eg. 1,2,3,4,5,6,7,8 Bits per Pixel. 
  Dazu mu aber in glcd.h der Wert COLOR_TABLE_BITS angepasst werden.
- komprimierte Fonts werden schneller und effizienter angezeigt als nicht komprimierte Fonts
- Der Font Editor wurde komplett berarbeitet:
  Bei groen Fonts hatte der alte Editor starke Probleme mit der Performance, beseitigt.
- Der Editor kann nun Fonts mit bis zu 16 Farben erzeugen. Es sind theoretisch aber mehr mglich.
- Der Editor untersttzt nun auch das Fllen von Pixelbereichen.
- Der Editor untersttzt und erzeugt automatisch komprimierte Fonts, wenn diese weniger Resourcen verbrauchen.
- Der Editor hat nun eine Zeichen-Vorschau.
- In glcd.h wurde zustzliche #define's eingefgt mit denen es mglich ist bestimmte Grafikfunktionen zu deaktivieren, das sind
  USE_LINES -> glcdLine()
  USE_ELLIPSES -> glcdEllipse()
  USE_FONTS -> alle Font Funktionen
  Dadurch kann man den Resourcenverbrauch tunen.
- USE_ISR, damit kann eingestellt werden ob das Chip Select Signal des PCF8833 automatisch nach Beendigung der SPI Transmission
  zurckgesetzt werden soll. Normalerweise mu man dieses define aktivieren falls mehrere Slaves am SPI hngen. Es zeigte sich aber
  das ohne USE_ISR, also mit dauerhaftem CS Signal fr den PCF8833, die Stranflligkeit bei langen Zuleitungen zum LCD erhht wird.
  In meinen Test's betraff dies immer das Ein/Ausschalten der Schreibtischlampe. Wurde USE_ISR nicht definiert so kommt es beim
  Display Test Program sehr schnell zu Abstrzen des LCD Controllers. Leider gibt es keine Mglichkeit den Status der bertragung
  zum LCD querzuchecken. Deshalb empfehle ich USR_ISR zu definieren, auch wenn dadurch die Performance ganz leicht runter geht.
  Auf alle Flle hat USR_ISR die Anflligkeit des LCD's enorm reduziert, in fact selbst 1000'maliges Ein/Ausschalten meiner Schreibtisch-
  lampe hat keine Abstze mehr provoziert. Fairerweise mu ich aber sagen das 1.) die Zuleitungen zum LCD ca. 50cm lang sind, das 2.) die
  Lampe direkt ca. 25cm ber dem STK500 Board angebracht ist, 3.) die Lampe eine normale Glhbirne ist und 4.) der Schalter einer von
  diesen Leitungs-Schnappschaltern ist. Gleich neben dieser Zuleitung liegt meine Logitech-Funkmaus.
  Irgendwelche Entstrmanahmen wie zustzliche Kondensatoren oder Pullup-Widerstnde wurden nicht benutzt, und das STK500 und somit das
  LCD + ATmega32 16MHz wurden auf 2.7V Vcc eingestellt !! Bei diesen Testbedinungen ist es eigentlich logisch das eventuelle Strungen
  auftreten mssen. Um so erfreulicher ist es das mit dem USE_ISR keinerlei Abstrze vorkamen, besonders wenn man bedenkt das das 
  LCD mit dem benutzten 8MHz SPI eigentlich overtuned wurde (PCF8833 kann laut Datenblatt nur 6.5MHz SPI).


Die Font Komprimierung:
  Fr eine effiziente Komprimierung auf AVR's habe ich mich von vorhinein fr ein einfaches RLE = Run Length Encoding entschieden.
  Weil eben die Dekomprimierung sehr effizient ist. Ich konnte aber keine normale RLE Komprimierungen wie sie in Windows-Bitmaps
  benutzt wird verwenden. Es zeigte sich das diese Verfahren zu schlechte Kompressionsraten fr Fonts liefern und zudem noch unhandlich
  bei vielen verschiedenen Font-Farbtiefen sind. Desweiteren reagieren fast alle RLE Verfahren nicht dynamisch auf die Erfordernisse
  die die zu komprimierenden Daten stellen. Ok, man htte ja eine Huffman Codierung benutzen knnen, aber auch diese wre ziemlich
  ineffizient in unserem Fall, auf Grund der sehr groen Lookup Tabellen.
  Nun, die Font Routinen benutzen ein RLE Verfahren mit dynamisch angepasster Lngentabelle. D.h. bei der Komprimierung werden 4 Lngen-
  codes ausgewhlt so da die erzielte Komprimierung die bestmgliche ist. Dabei werden die am "hufigsten" vorkommenden Pixellngen mit
  gleicher Farbe als 2 Bit Werte codiert. Sogesehen ist das von mir benutzte RLE Verfahren auch eine Mini-Huffmann-Codierung.
  Insgesammt gibt es nur 4 solcher Lngen in einer Tabelle mit 4 Eintrgen. Logischerweise ist der erste Eintrag in dieser Tabelle
  immer die Lnge 1, sprich 1 Pixel mit der aktuellen Farbe. Erstaunlicherweise arbeitet das Verfahren ziemlich effizient, 
  und ich konnte Komprimierungen erzielen die weit ber 200% lagen. Insgesammt bentigt diese dynamische-RLE-Komprimierung nur 4
  zustzliche Bytes. Oben habe ich das "hufigsten" separiert um auszudrcken das dies nur eine starke Vereinfachung des Verfahrens
  ist. Tatschlich werden nicht unbedingt die hufigst vorkommenden gleichfarbigen Pixellngen als Lngentabelle benutzt sondern
  die jenigen die mit absoluter Sicherheit die tatschlich beste Komprimierung ergeben. Dazu wird mit einem speziellen "Such-
  Algorithmus" alle Kombinationen der auftretenden Hufigkeiten durchgespielt, und die kompletten Fontdaten mit jeweils allen
  Kombinationen komprimiert. Diejenige Lngenkombination mit der hchsten Komprimierung wird dann gewhlt. In einem normal groen
  Mehrfarbfont gibt es ca. 100 verschiedene Pixellngen. Davon mu nun eine Kombination von 3 Lngen gefunden werden die die hchste
  Komprimierung liefern. Jede der mglichen Kombinationen kann die beste Kombination sein, unabhnig von ihrer eigenstndigen
  Hufigkeit. Eine andere Annahme als Suchstrategie ist grundstzlich falsch, auch ich hatte dies erst bersehen. Denn alle nicht
  in der RLE-Lngentabelle erfassten Pixellngen mssen ja zusammengesetzt werden aus diesen 4 Lngenangaben, und die Reihenfolge des
  Vorkommens der einzelnen Lngenhufigkeiten in den Fontdaten ist ebenfalls ausschlaggebend. Dies ist auch der Grund warum die RLELnge[0]
  immer 1 sein mu. Eine druchschnittlich gute Komprimierung erhlt man bei einer Lngentabelle der Form (1,2,4,8). Allerdings auch hier
  kann es durchaus sein das zb. beim jeweiligen Font die Lngentabelle (1,2,5,13) doppelt bessere Komprimierungen ergibt !! 
  Der Suchalgorithmus zur Komprimierung der Fontdaten mu also nicht nur die Hufigkeiten der einzelnen gleichfarbigen Pixellngen
  bercksichtigen, sondern auch deren Auftreten in den Fontdaten und das mglichst clevere Zerlegen aller nicht in der 4 Bytes
  Lngentabelle codierten Pixellngen. Dies geht nur mit einem testweisen Komprimieren der Fontdaten. So, dies erklrt auch warum
  bei sehr groen Fonts der Font Editor eine lngere Zeit zur Komprimeirung der Daten bentigt. Allerdings drfte dies nicht so
  enorm stren da diese Komprimierung im Hintergrund in einem eigenen Thread abluft. Auf alle Flle ist die benutzte RLE Codierung
  weit effizienter als die in Windows-Bitmaps oder in PNG Bitmaps benutzte, das habe ich getestet.



Nachdem ich die MAP Files des durch den WinAVR Compiler erzeugten Codes genauer analysiert habe musste ich feststellen das er an einigen
Stellen enorm ineffizient optimiert und der Linker noch ineffizienter arbeitet, schade :(
Besonders erschttert war ich ber den Resourcenverbrauch der integerierten rand() Funktion. Mehr als 800 Bytes an Code ist definitiv viel
zu viel fr einen stink normalen LCG (linear congruential generator).
Aus diesem Grunde habe ich mal meinen LFSRG aus meinen Delphi Sourcen portiert. Nach der ersten, reinen C Umsetzung, musste ich
wieder feststellen das der WinAVR Compiler aus einem so einfachen und echt Hardware-nahem LFSR unmglichen Code erzeugt. Deshalb findet 
ihr den LFSR als Assembler Source im Ordner \lfsr\. Wenn man den C Overhead entfernt, der die Register sichert, kommt man auf einen reinen
Assemblercode von 72 Bytes ! Der Source knnte also auch fr ASM Freaks sehr interessant sein.

Das von mir benutzte mathematische Verfahren ist 
1.) schneller als der LCG von rand()
2.) wesentlich code effizienter als rand()
3.) hat bessere statistiche Eigenschanften, er ist also zuflliger als ein LCG
4.) ist kryptographisch weit sicherer als der LCG von rand()

Das Verfahren ist ein LFSR-SG, also ein Linear Feedback Shift Register Shrinking Generator mit einer Periode von 2^63 -2. Diese Periode
IST IMMER garantiert, egal wie die Seedregister belegt sind. Der LCG() von rand() hat eine maximale Periode von 2^31-1 diese ist aber
abhngig vom Seed des Generators, kann also wesentlich krzer sein. Fr die "Nicht-Mathematiker", wenn man die Seed Register mit einem
beliebigen Wert fllt dann mu man 2^63 -2 Bits erzeugen bis die Seed-Register wieder den Anfangswert bekommen. Man kann also 9223372036854775806 Bits nacheinander erzeugen ohne statistische Wiederholungen in der Zufallsfolge. Das sind 1023 Penta Bytes == 
1023 * 1024 Terra Bytes !!

Damit der LFSR-SG arbeitet bentigt er zwei nicht reduzierbare Polynome (irreducible polynoms) im GF(2) -> Galois Field 2.
Um euch die Erzeugung bzw. Auswahl solcher Polynome leichter zu machen habe ich in der Datei lfsr.inc jeweils 1000 solcher Polynome
hinterlegt. Diese Polynome sind auf ihre "Nicht-Reduzierbarkeit" geprft und wurden zufllig erzeugt. Wichtig ist nur das ihr
als Polynom_S und Polynome_A in der Datei lfsr.S aus der richtigen zugehrigen Tabelle auswhlt. Dabei wird das LFSR S mit dem Polsynom_S
betrieben, welches ein Degree von 32 besitzen mu. Das LFSR A wird mit Polynom_A betrieben welches einen Degree von 31 haben mu.
Die kryptografische Sicherheit dieses LFSR-SG betrgt 126 Bits, solange die benutzten Polynome NICHT fr Aussenstehende bekannt sind !
D.h. die Funktion lfsr() kann als Source benutzt werden fr eine einfache XOR Verschlsselung, man mu aber sicherstellen das die beiden
Polynome A & S nicht ffentlich bekannt werden. In den Registern lfsr_S und lfsr_A kann man den Verschlsselungs-Schlssel ablegen.
Dieser Schlssel hat dann eine effektive Lnge von 63 Bits + die 63 Bits der beiden Polynome ergeben 126 Bits. Sind dieser Schlssel
und die Polynome fr einen Angreifer nicht bekannt so mu er eine Bruteforce Attacke auf 126 Bit Schlsselraunm durchfhren.

Als Randbemerkung: die BasicCard's, das sind SmartCard's einer deutschen Firma, benutzten lange Zeit das gleiche Verfahren. D.h. der Code
ist kompatibel mit den in diesen BasicCard's eingesetzem Zufallsgenerator.

Gru Hagen


 



