'##############################################################################
' LCD-Display.BAS                                              Stand 17.04.2017
' ---------------                                              (C) Markus Fulde
'
' Testprogramm zur Inbetriebnahme des Display DOGM128x64 Grafik-Display
'
' Die Inbetriebnahme erfolgt mit einem Steckbrett auf Basis ATMega8L
'
' Die Spezialität bei BASCOM mit diesem Display besteht in der Verwendung einer
' speziellen Library und der nicht vollständigen Unterstützung des Displays
' durch BASCOM. BASCOM selbst bietet nur Zugriffsmöglichkeiten und Textfunk-
' tionen aber keine Grafikfunktionen.
' Diese werde in diesem Beispielprogramm von Hand dazuprogrammiert.
'
' Die für die LCD-Display-Ansteuerung notwendigen Routinen sind
' als solche gekennzeichnet und bereits zur späteren Verwendung
' ausgelagert.
'
' Die Anbindung des Display erfolgt über SPI mit einer Betriebsspannung von
' 3.3V
'
'##############################################################################

' Die folgenden BASCOM Befehle funktionieren:
' - Glcdcmd
' - Glcddata
' - Setfont
' - Lcdat
' - SHOWPIC
' - Display On | Off

' Die folgenden Befehle funktionieren nicht
' - Cursor On|Off Blink|Noblink
' - Deflcdchar

' Probleme Und Nachteile Dieses Displays:
' - Das Display verfügt nur über eine 3.3V Logik und kann somit nicht an 5V
'   betrieben werden bzw. ist eine entsprechende LevelShifter-Logik notwendig
' - Im vom Display zur Verfügung gestellten SPI Mode kann nur schreibend und
'   nicht lesend auf das Display zugegriffen werden.
'   Um Grafiken abbilden zu können ist daher ein großer Buffer im RAM des
'   Kontrollers notwendig. Die wenigstens ATmega's bieten ausreichend Speicher
'   um solch eine Kopie des Grafikspeichers zu halten.
'   128 Spalten und 64 Zeilen ergeben 8192 Bits (1 Bit für jedes Pixel S/W).
'   Für den Grafikspeicher sind also 1024 Byte RAM notwendig.

'##############################################################################

'------------------------------------------------------------------------------
' Compilerinstruktionen und Compilerdirektiven
'------------------------------------------------------------------------------
$regfile = "m8def.dat"                                      ' Definitionsdatei für ATmega128 laden
$crystal = 8000000                                          ' Quarzfrequenz für 16 MHz festlegen

$hwstack = 40
$swstack = 40
$framesize = 40

' Hier wird die spezielle Grafik-LIB von BASCOM geladen
$lib "glcdeadogm128x6.lbx"

'------------------------------------------------------------------------------
' Allgemeine Zusatzinformatonen zu Programmbeginn
'------------------------------------------------------------------------------

' Generelle Informationen zum Display

' Das 128x64 Display ist organisiert in 8 Pages, jede Page mit 8 Pixel Höhe
' und einer Tiefe von 132.
' Die einfachste Möglichkeit Grafiken auf das Display zu schreiben ist das
' updaten bzw. beschreiben einer gesamten Page

' Pages:
'
' +------------------------------------------------------+
' | Column Addresses für Page 1                          | Page 0 - 0000
' +------------------------------------------------------+
' | Column Addresses für Page 2                          | Page 1 - 0001
' +------------------------------------------------------+
' | ....                                                 | Page 2 - 0010
' +------------------------------------------------------+
' | ....                                                 | Page 3 - 0011
' +------------------------------------------------------+
' | ....                                                 | Page 4 - 0100
' +------------------------------------------------------+
' | ....                                                 | Page 5 - 0101
' +------------------------------------------------------+
' | ....                                                 | Page 6 - 0110
' +------------------------------------------------------+
' | ....                                                 | Page 7 - 0111
' +------------------------------------------------------+

' Column Addresses:
'
'     S00 S01 S02 S03 S04 S05 S06       S83 hex - Column address
'    +---+---+---+---+---+---+---+ ... +---+      |
' D0 |   |   |   |   |   |   |   |     |   |      +---- Column most significant 4 bit
'    +---+---+---+---+---+---+---+     +---+      +---- Column least significant 4 bit
' D1 |   |   |   |   |   |   |   |     |   |
'    +---+---+---+---+---+---+---+     +---+
' D2 |   |   |   |   |   |   |   |     |   |
'    +---+---+---+---+---+---+---+     +---+
' D3 |   |   |   |   |   |   |   |     |   |
'    +---+---+---+---+---+---+---+     +---+
'    ...
'    +---+---+---+---+---+---+---+     +---+
' D7 |   |   |   |   |   |   |   |     |   |
' |  +---+---+---+---+---+---+---+     +---+
' |
' +---- Data (Datenbits innerhalb des geschriebenen Datenbyte) - jedes Bit ist ein Pixel

'------------------------------------------------------------------------------
' Definition von Ressourcen
'------------------------------------------------------------------------------

' ----- LED's -----
Alive_pin Alias Pinc.0                                      ' GPIO für Alive-LED (für DDR oder Input)
Alive Alias Portc.0                                         ' GPIO für Alive-LED (für Output oder Pullup)

' ----- LCD-Display -----
' LCD-Display
Glcd_cs1 Alias Portd.4                                      ' GPIO PD4
Glcd_a0 Alias Portd.7                                       ' GPIO PD7
Glcd_si Alias Portb.3                                       ' MOSI
Glcd_sclk Alias Portb.5                                     ' SCK
Glcd_rst Alias Portd.5                                      ' GPIO PD5

'------------------------------------------------------------------------------
' Definition von Konstaten
'------------------------------------------------------------------------------

' ----- Für Testumgebung bzw. Traceausgaben -----
Const Main_testmodus = 1                                    ' Flag für Testmodus Allgemeinsystem
Const Lcd_testmodus = 1                                     ' Flag

Const Demo_part_1 = 1                                       ' Einfache Ausgabe Text
Const Demo_part_2 = 1                                       ' Erweiterete Display Funktionen
Const Demo_part_3 = 1                                       ' Bildfunktionen
Const Demo_part_4 = 1                                       ' Grafikspeicher

' ----- Allgemeine Systemkonstanten -----

' Tatsächliches Allgemeines
' Const Led_aus = 0
' Const Led_ein = 1

Const Led_aus = 1                                           ' Achtung !! bei STK500 ist Logik gedreht!!
Const Led_ein = 0                                           ' Achtung !! bei STK500 ist Logik gedreht!!

Const False = 0
Const True = 1

' Zeitvorgabe für Sekunden-Timer
Const Timervorgabe = 34286                                  ' Timer von 1 Sekunden (SekundenTick)

' ----- LCD -----

Const Glcd_cmd_display_off = &B10101110                     ' (1.1) LCD Display - off
Const Glcd_cmd_display_on = &B10101111                      ' (1.1) LCD Display - on

Const Glcd_cmd_display_start_line = &B01000000              ' (2) Set the display RAM display start line address
'                                       ||||||              '     &B01xxxxxx 0x00-0x63
'                            variabel:  xxxxxx

Const 
#$A = &B10110000                ' (3) Sets the display RAM page address
'                                       ||||                '     &B1011xxxx 0x00 - 0x07 (Page 0 - 7)
'                          variabel:    xxxx

Const Glcd_cmd_column_address_set_msca = &B00010000         ' (4.1) Sets the most significant 4 bits of the display RAM column address
'                                              ||||         '       &B0001xxxx 0x00 - 0x07 (Block 0 - 7)
'                                 variabel:    xxxx

Const Glcd_cmd_column_address_set_lsca = &B00000000         ' (4.2) Sets the least significant 4 bits of the display RAM column address
'                                              ||||         '       &B0000xxxx 0x00 - 0x0F (Column 0 - 15)
'                                 variabel:    xxxx

Const Glcd_cmd_disp_normal = &B10100110                     ' (9.1) Display - normal
Const Glcd_cmd_disp_inverted = &B10100111                   ' (9.2) Display - inverted

Const Glcd_cmd_disp_all_point_normal = &B10100100           ' (10.1) Display all points - normal display
Const Glcd_cmd_disp_all_point_on = &B10100101               ' (10.2) Display all points - all poins ON

Const Glcd_cmd_reset = &B11100010                           ' (14) Internal reset

Const Glcd_cmd_set_contrast = &B10000001                    ' (18.1) Electronic volume mode set
Const Glcd_cmd_set_contrast_data = &B00000000               ' (18.2) Electronic volume register set
'                                       ||||||               '        &B00xxxxxx 0x00 - 0x3F (0-63)
'                            variabel:  xxxxxx

Const Glcd_cmd_nop = &B11100011                             ' (22) NOP

'------------------------------------------------------------------------------
' Definition von Variablen und Datentypen
'------------------------------------------------------------------------------

' ----- Temporäre Hilfsvariablen -----
Dim Temp_byte_1 As Byte                                     ' Temporäre Byte Variable 1
Dim Temp_byte_2 As Byte                                     ' Temporäre Byte Variable 2
Dim Temp_byte_3 As Byte                                     ' Temporäre Byte Variable3

' ----- Variablen für LCD-Display -----

'------------------------------------------------------------------------------
' Prototyping
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
' Konfiguration und Basiseinstellungen (Projekt und Testumgebung)
'------------------------------------------------------------------------------

' --------------------------------- CONFIG ------------------------------------

' ----- Timer -----

' Konfiguration eines Timers für 1 Sekunden Timer-Tick (Scheduler und Alive)
Config Timer1 = Timer , Prescale = 256                      ' Timer 1 verwenden
On Timer1 Sekunden_tick                                     ' Interrupt Routine
Timer1 = Timervorgabe
Enable Timer1                                               ' Interrupt für Sekunden-Tack

' ----- LCD Display -----

' Konfiguration LCD Display
Config Graphlcd = 128 * 64eadogm , Cs1 = Glcd_cs1 , A0 = Glcd_a0 , Si = Glcd_si , Sclk = Glcd_sclk , Rst = Glcd_rst

Initlcd                                                     ' LCD Initialisieren (normal beim ersten LCD Zugriff automatisch)
Cls                                                         ' Display löschen

Setfont Font8x8tt                                           ' Kleiner FONT laden

' ------------------------------- Port's und Pin's ----------------------------

' ----- LED-Konfigurationen -----
Config Alive_pin = Output

' ------------------------------ Variablen und Werte --------------------------

' ----- LED-Konfigurationen -----
Alive = Led_aus                                             ' Alive-LED aus

' ----- LCD-Display -----

'------------------------------------------------------------------------------
' Und los gehts, hier noch die Restarbeiten
'------------------------------------------------------------------------------

' ----- Freigabe aller Interrupts ----
Enable Interrupts                                           ' Damit auch Empfang von Daten über Buffer

' ---------------------------------- Gosub's ----------------------------------

' #############################################################################
'
'                             Hauptprogramm ConvCtrl
'
' #############################################################################

#if Demo_part_1
   Lcdat 1 , 1 , "11111111"
   Lcdat 2 , 1 , "88888888"
   Lcdat 3 , 1 , "EA-DOGM182x64 Test1" , 1                  ' Text invers ausgeben
   Wait 5
   Cls
#endif

' ----------------------------------------------
' ----- Hier ist die Programmhauptschleife -----
' ----------------------------------------------

Do                                                          ' Hauptschleife

   #if Demo_part_2

      Cls

      Lcdat 1 , 1 , "abcdefgh"
      Lcdat 2 , 1 , "ABCDEFGH"
      Lcdat 3 , 1 , "EA-DOGM182x64 Test1" , 1               ' Text invers ausgeben

      Glcdcmd Glcd_cmd_set_contrast                         'Kontrast einstellen
      Glcdcmd Glcd_cmd_set_contrast_data + 1
      'Glcdcmd &B00000001                                    'Kontrast auf 1 Setzen
      Lcdat 5 , 1 , "Kontrast 1  " , 1

      Wait 2
      Glcdcmd Glcd_cmd_set_contrast                         'Kontrast setzen
      Glcdcmd Glcd_cmd_set_contrast_data + 2
      ' Glcdcmd &B00000010                                    'Kontrast auf 2 Setzen
      Lcdat 5 , 1 , "Kontrast 2  " , 1

      Wait 2
      Glcdcmd Glcd_cmd_set_contrast                         'Kontrast setzen
      Glcdcmd Glcd_cmd_set_contrast_data + 4
      ' Glcdcmd &B00000100                                    'Kontrast auf 4 Setzen
      Lcdat 5 , 1 , "Kontrast 4  " , 1

      Wait 2
      Glcdcmd Glcd_cmd_set_contrast                         'Kontrast setzen
      Glcdcmd Glcd_cmd_set_contrast_data + 8
      ' Glcdcmd &B00001000                                    'Kontrast auf 8 Setzen
      Lcdat 5 , 1 , "Kontrast 8  " , 1

      Wait 2
      Glcdcmd Glcd_cmd_set_contrast                         'Kontrast setzen
      Glcdcmd Glcd_cmd_set_contrast_data + 16
      ' Glcdcmd &B00010000                                    'Kontrast auf 16 Setzen
      Lcdat 5 , 1 , "Kontrast 16  " , 1

      Wait 2
      Glcdcmd Glcd_cmd_set_contrast                         'Kontrast setzen
      Glcdcmd Glcd_cmd_set_contrast_data + 32
      ' Glcdcmd &B00100000                                    'Kontrast auf 32 Setzen
      Lcdat 5 , 1 , "Kontrast 32  " , 1

      Wait 2
      Glcdcmd Glcd_cmd_set_contrast                         'Kontrast setzen
      Glcdcmd Glcd_cmd_set_contrast_data + 63
      ' Glcdcmd &B00111111                                    'Kontrast auf 63 Setzen
      Lcdat 5 , 1 , "Kontrast max " , 1

      Wait 2
      Glcdcmd Glcd_cmd_set_contrast                         'Kontrast setzen -> bester Kontrast
      Glcdcmd Glcd_cmd_set_contrast_data + 20
      ' Glcdcmd 20                                            'Kontrast auf 20 Setzen
      Lcdat 5 , 1 , "Kontrast 20  " , 1

      Wait 5
   #endif

   #if Demo_part_3

      Showpic 0 , 0 , Picture                               ' BGF Grafik anzeigen
      Wait 5

      Display Off                                           ' Display ausschalten mit BASCOM Befehl
      Wait 2
      Display On                                            ' Display einschalten mit BASCOM Befehl
      Wait 2

      Glcdcmd Glcd_cmd_display_off                          ' Display ausschalten mit GLCD Befehl
      Wait 2
      Glcdcmd Glcd_cmd_display_on                           ' Display einschalten mit GLCD Befehl
      Wait 2

      Glcdcmd Glcd_cmd_disp_inverted                        ' Display invers betreiben
      Wait 2
      Glcdcmd Glcd_cmd_disp_normal                          ' Display Normalmodus
      Wait 5
   #endif

   #if Demo_part_4

      Cls

      ' ---- Linie auf Display erzeugen ----

      ' Sets the display RAM page adress
      Glcdcmd 
#$A + 0                 'Zeile 0

      For Temp_byte_1 = 0 To 7

         ' Sets the most significant 4 bits o fthe display RAM column address
         Temp_byte_3 = Glcd_cmd_column_address_set_msca + Temp_byte_1
         Glcdcmd Temp_byte_3

         For Temp_byte_2 = 0 To 15
            ' Sets the least significant 4 bits o fthe display RAM column address
            Temp_byte_3 = Glcd_cmd_column_address_set_lsca + Temp_byte_2
            Glcdcmd Temp_byte_3

            Glcddata &B10100101                             ' Pattern erzeugt Linienmuster
         Next Temp_byte_2
      Next Temp_byte_1

      Wait 5

      ' ---- Schachbrettmuster auf Display erzeugen ----

      For Temp_byte_2 = 0 To 7
         Temp_byte_3 = 
#$A + Temp_byte_2
         Glcdcmd Temp_byte_3                                ' Setze RAM Page 1-8, 8 Piuxel hoch

         Glcdcmd Glcd_cmd_column_address_set_msca + 0       ' Setze Block 0 von Page x
         Glcdcmd Glcd_cmd_column_address_set_lsca + 0       ' Setze Column 0 von Block 0

         For Temp_byte_1 = 1 To 16

            ' Pattern erzeugt Schachbrettmuster
            Glcddata &HF0
            Glcddata &HF0
            Glcddata &HF0
            Glcddata &HF0
            Glcddata &H0F
            Glcddata &H0F
            Glcddata &H0F
            Glcddata &H0F
         Next Temp_byte_1
      Next Temp_byte_2

      Wait 5

   #endif

Loop                                                        ' Hauptschleife

'## End Hauptprogramm #########################################################

End

'******************************************************************************
' Interruptroutinen
'******************************************************************************

'------------------------------------------------------------------------------
' Interrupt-Service-Routine (Timer1): Sekunden_tick
' Routine zur Auswertung des Timer Interrupts
'------------------------------------------------------------------------------
Sekunden_tick:

   ' ----- Programmcode -----

   Timer1 = Timervorgabe                                    ' Timer neu laden
   Toggle Alive                                             ' Alive-LED toggeln lassen

Return
'-- End Sekunden_tick  --------------------------------------------------------

'******************************************************************************
' Subroutinen
'******************************************************************************

' ***************
' * LCD-Display *
' ***************

'******************************************************************************
' GOSubroutinen
'******************************************************************************

' ***************
' * LCD-Dsiplay *
' ***************

'------------------------------------------------------------------------------
' Devices schließend und ggf. "Terminate Programm execution"
'------------------------------------------------------------------------------

' System halt
End                                                         'end program

'------------------------------------------------------------------------------
' Definition von globalen Konstantenfeldern
'------------------------------------------------------------------------------

' ------------------------------- Grafiken für das GLCD -----------------------

'include the picture data
Picture:
$bgf "BASCOM.bgf"

' ------------------------------- FONT's für das GLCD -------------------------

' Include Font nach dem END und damit nach dem Programmcode damit nicht FONT-
' Data als Code interpretiert wird (sollte ganz am Ende stehen)
$include "font8x8TT.font"

' ----------------------------------------------------------------------------

'###################################### END ###################################

'################################### Historie #################################
' 28.10.2018 : Version 1.0
'              Erstellung der 1. Version der generellen Inbetriebnahme DOGM128
'##############################################################################