Ein etwas anderer Radiowecker...

Software

Anzeigesteuerug VQC10

Die Anzeige erfolgt mit 8 Stück rot leuchtenden LED-Punktmatrixanzeigen vom Typ VQC10 aus DDR-Produktion. Also schon etwas älter, aber sie sehen immer noch verdammt gut aus. Erhältlich ist so etwas höchstens noch auf Flohmärkten oder Restbeständen. Jede Anzeige hat 4 Stellen mit 5 * 7 Leuchtdioden. Insgesamt sind also 1120 Leuchtdioden zu steuern. Die Spaltenansteuerung wird intern gespeichert, während die Zeilen nichtspeichernd über Transistoren gegen +5 Volt geschaltet sind.

Zuerst werden die Ports für die Ansteuerung der Anzeige als Ausgänge deklariert. Die etwas ungewöhnliche Aufteilung der Ports beruht darauf, das der auf der Originalleiterplatte gesockelte Prozessor durch den AVR ersetzt wurde. Die Portbelegung war dort natürlich vollkommen inkompatibel, aber es sollten soviel wie möglich Leiterzüge weiter verwendet werden. Dann benötigen wir ein je Byte für die Anzeigestelle, die Zeilennummer und ein Array für die Spalten (Daten). Diverse Variablen werden für die Steuerung der Helligkeit benötigt. Der 16-bit-Timer misst die Laufzeit eines kompletten Programmdurchlaufs der Hauptschleife, um Helligkeitsschwankungen durch verschiedene Programmteile zu vermeiden.

'5 Ports für Anzeige VQC10 Stellen + 1 Port Stelle Enable
Config Portc.= Output                                     ' Ausgang Stelle 1
Config Portc.= Output                                     ' Ausgang Stelle 2
Config Porta.= Output                                     ' Ausgang Stelle 4
Config Porta.= Output                                     ' Ausgang Stelle 8
Config Porta.= Output                                     ' Ausgang Stelle 16
Config Porta.= Output                                     ' Ausgang Stelle Enabled
'3 Ports für Anzeige für VQC10 Zeilen + 1 Port Zeile Enable
Config Porta.= Output                                     ' Ausgang Zeile 1
Config Porta.= Output                                     ' Ausgang Zeile 2
Config Porta.= Output                                     ' Ausgang Zeile 4
Config Portc.= Output                                     ' Ausgang Zeile Enabled
'5 Ports für Anzeige für VQC10 Daten
Config Portb.= Output                                     ' Ausgang Daten 1
Config Portd.= Output                                     ' Ausgang Daten 2
Config Portd.= Output                                     ' Ausgang Daten 3
Config Portd.= Output                                     ' Ausgang Daten 4
Config Portb.= Output                                     ' Ausgang Daten 5
'Variablen für Anzeige dimensionieren
Dim Stelle As Byte                                          ' Variable für Stellennummer
Dim Zeilenr As Byte                                         ' Variable für Zeilennummer
Dim Daten(33) As Byte                                       ' Variable für Daten eine Zeile a 5 Pixel
Dim Helligkeit As Word                                      ' Anzeigehelligkeit
Dim Hell_schnitt As Word                                    ' Anzeigehelligkeit
Dim Helligkeit1 As Word                                     ' Anzeigehelligkeit
Dim Helligkeit_eram As Eram Word                            ' Anzeigehelligkeit im EEPROM
If Helligkeit >= 2500 Then                                  ' Fehler abfangen
   Helligkeit = 1000
   Helligkeit_eram = Helligkeit
EndIf
Dim Hell_auto As Byte                                       ' Anzeigehelligkeit Automatik ein/aus
Dim Hell_auto_eram As Eram Byte                             ' Anzeigehelligkeit Automatik EEPROM
Hell_auto = Hell_auto_eram                                  ' Automatik aus EEPROM lesen
If Hell_auto >= 2 Then                                      ' Fehler abfangen
   Hell_auto 
= 0
   Hell_auto_eram = Hell_auto
EndIf
Dim Hell_count As Byte                                      ' Zähler für Durchschnitt
Dim Hell_loop As Byte
Dim Hell_schwell As Word                                    ' Schwellwert für LED + Relais Automatik
Dim Hell_schwell_eram As Eram Word                          ' Schwellwert für LED + Relais Automatik EEPROM
Hell_schwell = Hell_schwell_eram                            ' Schwellwert aus EEPROM laden
If Hell_schwell >= 2500 Then                                ' Fehler abfangen
   Hell_schwell 
= 1000
   Hell_schwell_eram = Hell_schwell
EndIf
Dim Hell_ds(8) As Word                                      ' Array für Durchschnitt
Dim Hell_mod As Byte                                        ' Rest Division
Dim Scroll As Byte                                          ' durchlaufender Zähler für Laufschrift
Dim Zeichenascii As Word                                    ' ASCII Wert von Zeichen
Dim Laufzeit As Word                                        ' Zeit für einen Programmdurchlauf
Dim Anzeigezeit As Word                                     ' Zeit für Anzeige hell
Dim Zeichen As String * 1                                   ' String für ein Zeichen
Dim Zeile As String * 32                                    ' String für komplette Zeile
'Timer 3 - zählt Mikrosekunden für Anzeigehelligkeit
Config Timer3 = Timer , Prescale = 8                        ' zweiter 16-bit-Timer, 8000000/8=1 MHz = 1 Mikrosekunde

Was zur Anzeige kommen soll, schreibt das Programm in die Zeichenkette "Zeile" (String mit 32 Stellen). Ich beschreibe hier nur beispielhaft eine Anzeigevariante, bei der eine komplette Zeile mit Wochentag, Datum und Uhrzeit angezeigt wird. Die Anzeige wechselt sonst im Betrieb zwischen Temperatur, nächster Weckzeit, Radiofrequenz oder Sendername. Bei der Programmierung habe ich bemerkt, das es sinnvoll ist, den String möglichst von links nach rechts auzubauen. Der Einsatz des Befehls "Mid(variable,x,y) ist ziemlich speicher- und rechenintensiv. Da zeitgleich hier aber über 1000 Leuchtdioden multiplex angesteuert werden und die Anzeige nicht flackern sollen, kommt es auf jede Mikrosekunde an.

            If Anzeige = 0 Then                             ' ANZEIGE WOCHENTAG LANG, DATUM LANG
               Zeile 
= Lookupstr(wt , Wochentag)            ' Wochentag String einfügen
               Zeile = Zeile + Space(1)
               If Wt = 0 Then                               ' Montag 6 Zeichen
                  Zeile = Zeile + Space(1)
               End If
               If Wt = 3 Or Wt = 5 Then                     ' Donnerstag + Sonnabend
                  Zeile = Zeile + Date$                     ' Datum einfügen
                  Else                                      ' Montag, Dienstag, Mittwoch, Freitag, Sonntag
                     Zeile 
= Zeile + Left(date, 6)        ' Tag.Monat. einfügen
                     Zeile = Zeile + "20"                   ' 20 einfügen
                     Zeile = Zeile + Right(date, 2)       ' Jahr einfügen
               End If
               If Wt = 0 Or Wt = 4 Or Wt = 5 Or Wt = 6 Then ' Montag, Freitag, Sonnabend, Sonntag
                  Zeile = Zeile + Space(1)
               EndIf
               Zeile = Zeile + Space(1)
            End If

Jetzt folgt die eigentiche Ansteuerung und Helligkeitsregelung der Anzeige. Praktisch erfolgt die Steuerung der Anzeige so, das während eines Programmdurchlaufs eine komplette Zeile (32 Stellen) der Anzeige mit Daten gefüllt wird, dann wird die Anzeige dieser Zeile eingeschaltet, es folgt ein Programmdurchlauf der Hauptschleife + Wartezeit für Helligkeitsregelung, jetzt wird die Zeilennummer erhöht, anschließend wieder die Zeile mit neuen Daten befüllt, Zeile wird eingeschaltet, Programmdurchlauf + Wartezeit, Zeilennummer erhöhen usw. bis alle 7 Zeilen angezeigt wurden. Dann beginnt das Spiel wieder mit der ersten Zeile.
In den ersten beiden Zeilen wird die Zeilennummer der anzuzeigenden Zeile erhöht bzw. wieder auf 1 gesetzt. Wenn eine große Helligkeit der Anzeige erforderlich ist, erfolgt die Zuweisung der Daten anschließend noch in der Hellphase der Anzeige (lange Laufzeit = große Helligkeit). Falls das Radio eingeschaltet ist, wird anschließend der Mindestwert für die Helligkeit auf 1000 gesetzt. In der nächsten Zeile wird die Laufzeit einer kompletten Hauptschleife aus Timer 3 in Mikrosekunden übernommen. Falls diese kleiner ist als die geforderte Helligkeit der Anzeige, wird das Programm bis zum Erreichen der Anzeigezeit gestoppt (Zeile immer noch hell gesteuert). Erst nach Ablauf dieser Wartezeit wird die Anzeige abgeschaltet um die Daten für die nächste Zeile laden zu können. Falls die Anzeige relativ dunkel leuchten soll, erfolgt die Zuweisung der Daten für eine Zeile erst jetzt in dieser Schleife, in der auch die Daten direkt auf die Portleitungen ausgegeben werden. Anschließend wird der Timer neu gestartet und entsprechende Zeilenleitung angesteuert.

'Anzeigeroutine
   Incr Zeilenr                                             ' Zeilennummer um 1 erhöhen
   If Zeilenr >= 8 Then : Zeilenr = 1 : End If              ' Zeilen 1 bis 7
   Stelle = 32                                              ' Stellennummer auf 32 setzen
   If Helligkeit >= 1800 Then
      Do
         Zeichen = Mid(zeile , Stelle , 1)                  ' Zeichen Stelle aus Zeile ermitteln
         Daten
(33) = Asc(zeichen)                           ' ASCII von Zeichen Stelle
         Zeichenascii = Daten(33) * 7                       ' ASCII 29 beginnt an Pos 7, 30 bei 14 usw.
         Zeichenascii 
= Zeichenascii + Zeilenr              ' Zeile addieren
         Daten
(stelle) = Lookup(zeichenascii , Zeichensatz) ' 5 Datenbits aus Zeichensatz holen
         Decr Stelle                                        ' Stellennummer um 1 erhöhen
      Loop Until Stelle = 0                                 ' ">=" schneller als "=" oder ">"
      Stelle = 32                                           ' Stellennummer auf 32 setzen
   End If
   If Portd.= 1 Then                                      ' wenn Relais für Radio an PortD.1 eingeschaltet
      If Helligkeit < 1000 Then
         Helligkeit1 = 1000                                 ' Helligkeit auf Mindestwert 1000
      End If
      Else
         Helligkeit1 = Helligkeit
   End If
   Laufzeit 
= Timer3                                        ' Zeit für 1 Programmdurchlauf aus Timer 3 übernehmen
   If Laufzeit < Helligkeit1 Then                           ' wenn es länger dauert, nicht warten
      Anzeigezeit = Helligkeit1 - Laufzeit                  ' Anzeigezeit errechnen
      Waitus Anzeigezeit                                    ' wait mit Variable erst ab Version 1.12.x.x!!!
   End If
   Portc.= 1                                              ' ZeileCE - Zeile ausschalten
   Do
      If Helligkeit < 1800 Then
         If Stelle >= 1 Then
            Zeichen = Mid(zeile , Stelle , 1)               ' Zeichen Stelle aus Zeile ermitteln
            Daten(33) = Asc(zeichen)                        ' ASCII von Zeichen Stelle
            Zeichenascii 
= Daten(33) * 7                    ' ASCII 29 beginnt an Pos 7, 30 bei 14 usw. (7 Zeilen)
            Zeichenascii 
= Zeichenascii + Zeilenr           ' Zeile addieren
            Daten
(stelle) = Lookup(zeichenascii , Zeichensatz)       ' 5 Datenbits aus Zeichensatz holen
         End If
      End If
      Porta.= 1                                           ' StelleCE - Stelle ausschalten, H an cp VQC10
      Portb.= Daten(stelle).4                             ' Datenbit 1 ausgeben
      Portd.= Daten(stelle).3                             ' Datenbit 2 ausgeben
      Portd.= Daten(stelle).2                             ' Datenbit 3 ausgeben
      Portd.= Daten(stelle).1                             ' Datenbit 4 ausgeben
      Portb.= Daten(stelle).0                             ' Datenbit 5 ausgeben, fertig
      Decr Stelle                                           ' Stellennummer um 1 verringern
      Portc.= Stelle.0                                    ' Stellenbit 1 ausgeben
      Portc.= Stelle.1                                    ' Stellenbit 2 ausgeben
      Porta.= Stelle.2                                    ' Stellenbit 4 ausgeben
      Porta.= Stelle.3                                    ' Stellenbit 8 ausgeben
      Porta.= Stelle.4                                    ' Stellenbit 16 ausgeben
      Porta.= 0                                           ' StelleCE - Stelle gültig, L an cp VQC10
   Loop Until Stelle = 255                                  ' Schleife verlassen
   Timer3 = 0                                               ' Timer für Laufzeit starten
   Porta.= Zeilenr.0                                      ' Zeilenbit 1 ausgeben
   Porta.= Zeilenr.1                                      ' Zeilenbit 2 ausgeben
   Porta.= Zeilenr.2                                      ' Zeilenbit 4 ausgeben

Im weiteren Verlauf erfolgen noch einige selten auszuführende Aktionen, die ohnehin in der Dunkelphase der Anzeige erfolgen sollen, weil sie eine zu lange Laufzeit haben und dadurch die Anzeige zum Flackern bringen. Anschließend wird die Zeile eingeschaltet:

   Portc.= 0                                              ' ZeileCE - Zeile gültig und Zeile einschalten

Das ist die Tabelle für die Wochentage in Langform:

Wochentag:
Data "Montag" , "Dienstag" , "Mittwoch" , "Donnerstag" , "Freitag" , "Sonnabend" , "Sonntag"

Der Zeichensatz für die 5*7 Matrix mußte selbst erstellt werden. Das lässt sich relativ komfortabel direkt in BASCOM erledigen. Dafür existiert dort ein Werkzeug namens "LCD-Designer". Man muss dessen Ausgabe nur an die hier erforderlichen 7 Zeilen anpassen. Hier ein Auszug aus der kompletten Zeichensatz-Tabelle:

Zeichensatz:
Data 14 , 17 , 17 , 14 , 17 , 17 , 14                       ' 8 ASCII 056
Data 14 , 17 , 17 , 15 , 1 , 2 , 12                         ' 9 ASCII 057
Data 32 , 32 , 4 , 32 , 32 , 4 , 32                         ' : ASCII 058
Data 32 , 32 , 32 , 32 , 6 , 2 , 4                          ' ; ASCII 059
Data 32 , 2 , 4 , 8 , 4 , 2 , 32                            ' < ASCII 060
Data 32 , 32 , 14 , 32 , 14 , 32 , 32                       ' = ASCII 061
Data 32 , 8 , 4 , 2 , 4 , 8 , 32                            ' > ASCII 062
Data 14 , 17, 1 , 2 , 4 , 32 , 4                            ' ? ASCII 063