'*******************************************************************************
'* Wörteruhr (c)2012 by DiLi-Soft - www.liebl-net.de/hard/qlock2/qlock2.php *
'* *
'* Nachempfunden der "QLOCKTWO" von Biegert: www.qlocktwo.com *
'* *
'* Dieses Programm ist urheberrechtlich geschützt und darf ausschließlich *
'* für nichtkommerzielle Zwecke verwendet werden. *
'* *
'* Gewerbliche Nutzung ist ausgeschlossen!! *
'* *
'* Weitergabe des Quelltextes ist erwünscht - aber nur komplett, unverändert *
'* und mit diesen Copyright-Anmerkungen !!! *
'* *
'* V1.1 vom 31.8.2012, erstellt unter BASCOM-AVR 2.0.7.5 (www.mcselec.com) *
'* *
'*******************************************************************************
'$prog &HFF , &HFF , &HD1 , &H00 'ext. Quarz, JTAG off
'Lock- u. Fusebits
$regfile = "m16def.dat"
$crystal = 4194304 'Quarz/65536 = 64 !
$hwstack = 80 'viel zu viel ...
$swstack = 80 'aber ist ja Platz genug
$framesize = 80
Config Dcf77 = Pind.2 , Timer = 1 , Check = 2 , Update = 0 , Gosub = Sectic
'ständige Synchronisation + voller Validitätstest
'(
$baud = 9600 'UART-Baudrate: 9600 Baud
On Urxc Onrxd 'Interrupt-Routine setzen
Enable Urxc 'Nur für Tests !
')
Dim Index As Byte , Zeile As Byte , Zeilen_hell As Byte , Spalte As Byte
Dim 8bits As Byte , 3bits As Byte
Dim Ontime As Word , Offtime As Word
Dim Std_canvas As Byte , Std_incr As Byte
Dim Min_canvas As Byte , Old_min As Byte
Dim Sek_no_sync As Byte , Min_no_sync As Byte , Std_no_sync As Byte
Dim Ldr_val As Byte
Dim Canvas(22) As Byte '"Bildschirm-Speicher"
'11 Ausgabe-Zeilen *2 (wg. 11 Bit)
Dim Min_pat(66) As Byte '11 Pattern-Def. für Minuten *2*3
'[(Minuten\5 -1) *6 +1]...[(Minuten\5 -1) *6 +6]
'Bit-Belegung der Pattern-Definitionen der Minuten:
'| xxxxxxxx | xxxzyyyy |
' [n] [n+1]
'x: Spalte-LEDs (je 1 Bit)
'y: in Zeile (4 Bit)
'z: Std.-Inkrement
Min_pat(01) = &B00000001 '"FÜNF NACH"
Min_pat(02) = &B11100001
Min_pat(03) = &B00000001
Min_pat(04) = &B11100100
Min_pat(05) = 0
Min_pat(06) = 0
Min_pat(07) = &B11110000 '"ZEHN NACH"
Min_pat(08) = &B00000010
Min_pat(09) = &B00000001
Min_pat(10) = &B11100100
Min_pat(11) = 0
Min_pat(12) = 0
Min_pat(13) = &B00001111 '"VIERTEL NACH"
Min_pat(14) = &B11100011
Min_pat(15) = &B00000001
Min_pat(16) = &B11100100
Min_pat(17) = 0
Min_pat(18) = 0
'(
Min_pat(13) = &B00001111 '"VIERTEL"
Min_pat(14) = &B11110011
Min_pat(15) = 0
Min_pat(16) = 0
Min_pat(17) = 0
Min_pat(18) = 0
')
Min_pat(19) = &B00001111 '"ZWANZIG NACH"
Min_pat(20) = &B11100010
Min_pat(21) = &B00000001
Min_pat(22) = &B11100100
Min_pat(23) = 0
Min_pat(24) = 0
Min_pat(25) = &B00000001 '"FÜNF VOR HALB"
Min_pat(26) = &B11110001
Min_pat(27) = &B11100000
Min_pat(28) = &B00010100
Min_pat(29) = &B11110000
Min_pat(30) = &B00010101
Min_pat(31) = &B11110000 '"HALB"
Min_pat(32) = &B00010101
Min_pat(33) = 0
Min_pat(34) = 0
Min_pat(35) = 0
Min_pat(36) = 0
Min_pat(37) = &B00000001 '"FÜNF NACH HALB"
Min_pat(38) = &B11110001
Min_pat(39) = &B00000001
Min_pat(40) = &B11110100
Min_pat(41) = &B11110000
Min_pat(42) = &B00010101
Min_pat(43) = &B00001111 '"ZWANZIG VOR"
Min_pat(44) = &B11110010
Min_pat(45) = &B11100000
Min_pat(46) = &B00010100
Min_pat(47) = 0
Min_pat(48) = 0
Min_pat(49) = &B00001111 '"VIERTEL VOR"
Min_pat(50) = &B11110011
Min_pat(51) = &B11100000
Min_pat(52) = &B00010100
Min_pat(53) = 0
Min_pat(54) = 0
'(
Min_pat(49) = &B11111111 '"DREIVIERTEL"
Min_pat(50) = &B11110011
Min_pat(51) = 0
Min_pat(52) = 0
Min_pat(53) = 0
Min_pat(54) = 0
')
Min_pat(55) = &B11110000 '"ZEHN VOR"
Min_pat(56) = &B00010010
Min_pat(57) = &B11100000
Min_pat(58) = &B00010100
Min_pat(59) = 0
Min_pat(60) = 0
Min_pat(61) = &B00000001 '"FÜNF VOR"
Min_pat(62) = &B11110001
Min_pat(63) = &B11100000
Min_pat(64) = &B00010100
Min_pat(65) = 0
Min_pat(66) = 0
Dim Std_pat(26) As Byte '13 Pattern-Def. für Stunden *2
'bei Stunden >1: [Stunden*2 +1] u. [Stunden*2 +2]
'Bit-Belegung der Pattern-Definitionen der Stunden:
'| xxxxxxxx | xxx-yyyy |
' [n] [n+1]
'x: Spalte-LEDs (je 1 Bit)
'y: in Zeile (4 Bit)
'-: unbenutzt
Std_pat(1) = &B11100000 '"EIN"
Std_pat(2) = &B00000110
Std_pat(3) = &B11110000 '"EINS"
Std_pat(4) = &B00000110
Std_pat(5) = &B00000001 '"ZWEI"
Std_pat(6) = &B11100110
Std_pat(7) = &B11110000 '"DREI"
Std_pat(8) = &B00000111
Std_pat(09) = &B00000001 '"VIER"
Std_pat(10) = &B11100111
Std_pat(11) = &B00000001 '"FÜNF"
Std_pat(12) = &B11100101
Std_pat(13) = &B11111000 '"SECHS"
Std_pat(14) = &B00001000
Std_pat(15) = &B11111100 '"SIEBEN"
Std_pat(16) = &B00001001
Std_pat(17) = &B00000001 '"ACHT"
Std_pat(18) = &B11101000
Std_pat(19) = &B00011110 '"NEUN"
Std_pat(20) = &B00001010
Std_pat(21) = &B11110000 '"ZEHN"
Std_pat(22) = &B00001010
Std_pat(23) = &B00000111 '"ELF"
Std_pat(24) = &B00000101
Std_pat(25) = &B00000011 '"ZWÖLF"
Std_pat(26) = &B11101001
'Zuordnung der Zeilen und Spalten:
Zeile1 Alias Portb.7
Zeile2 Alias Portb.6
Zeile3 Alias Portb.5
Zeile4 Alias Portb.4
Zeile5 Alias Portb.3
Zeile6 Alias Portb.2
Zeile7 Alias Portb.1
Zeile8 Alias Portb.0
Zeile9 Alias Porta.7
Zeile10 Alias Porta.6
Zeile11 Alias Porta.5
Spalte1 Alias Portc.7
Spalte2 Alias Portc.6
Spalte3 Alias Portc.5
Spalte4 Alias Portc.4
Spalte5 Alias Portc.3
Spalte6 Alias Portc.2
Spalte7 Alias Portc.1
Spalte8 Alias Portc.0
Spalte9 Alias Portd.7
Spalte10 Alias Portd.6
Spalte11 Alias Portd.5
'----------------- Ausgangs- / Eingangs-Pins konfig.: ------------------------
'Zeilen:
Ddrb = &B11111111 'Zeile1 - Zeile8
Ddra = &B11100000 'Zeile9 - Zeile11; ADC0 als Input
'Spalten:
Ddrc = &B11111111 'Spalte1 - Spalte8
Ddrd = &B11100000 'Spalte9 - Spalte11
'PD2: Input (DCF-Empfänger)
'PD3: Input für Teststellung
Portb = &B11111111 'alle Zeilen AUS (low-aktiv!)
Porta = &B11100000
Portc = 0 'alle Spalten AUS (high-aktiv):
Portd = 0
'---------------------------- ADC konfig.: -----------------------------------
Admux.refs0 = 0
Admux.refs1 = 0 'Ref ist der AREF-Pin
Admux.adlar = 1 '8-bit-Mode reicht
Admux.mux0 = 0
Admux.mux1 = 0
Admux.mux2 = 0
Admux.mux3 = 0
Admux.mux4 = 0 'ADC0 ist Eingang
Adcsra.adps0 = 1
Adcsra.adps1 = 1
Adcsra.adps2 = 1 'Prescaler=128
Sfior.5 = 0
Sfior.6 = 0
Sfior.7 = 0 'ADTS2:0 : free running mode
Adcsra.5 = 1 'Auto Trigger
Adcsra.aden = 1 'ADC einschalten
Adcsra.adsc = 1 'und Conversion starten
'--------------------------------- main() ------------------------------------
'---------------------------- LED Testroutine: -------------------------------
If Pind.3 = 0 Then 'Teststellung: PIN 17 auf
Ontime = &HFFFF 'Masse: Blinkmuster ausgeben
Do
'alle Spalten EIN:
Portc = &B11111111
Portd = &B11100000
'alle Zeilen AUS:
Portb = &B11111111
Porta = &B11100000
For Zeile = 1 To 11 'alle Zeilen nacheinander EIN
Select Case Zeile
Case 01 : Zeile11 = 1
Zeile1 = 0
Case 02 : Zeile1 = 1
Zeile2 = 0
Case 03 : Zeile2 = 1
Zeile3 = 0
Case 04 : Zeile3 = 1
Zeile4 = 0
Case 05 : Zeile4 = 1
Zeile5 = 0
Case 06 : Zeile5 = 1
Zeile6 = 0
Case 07 : Zeile6 = 1
Zeile7 = 0
Case 08 : Zeile7 = 1
Zeile8 = 0
Case 09 : Zeile8 = 1
Zeile9 = 0
Case 10 : Zeile9 = 1
Zeile10 = 0
Case 11 : Zeile10 = 1
Zeile11 = 0
End Select
Waitus Ontime
Next
'alle Spalten AUS:
Portc = 0
Portd = 0
'alle Zeilen EIN:
Portb = 0
Porta = 0
For Spalte = 1 To 11 'alle Spalten nacheinander EIN
Select Case Spalte
Case 01 : Spalte11 = 0
Spalte1 = 1
Case 02 : Spalte1 = 0
Spalte2 = 1
Case 03 : Spalte2 = 0
Spalte3 = 1
Case 04 : Spalte3 = 0
Spalte4 = 1
Case 05 : Spalte4 = 0
Spalte5 = 1
Case 06 : Spalte5 = 0
Spalte6 = 1
Case 07 : Spalte6 = 0
Spalte7 = 1
Case 08 : Spalte7 = 0
Spalte8 = 1
Case 09 : Spalte8 = 0
Spalte9 = 1
Case 10 : Spalte9 = 0
Spalte10 = 1
Case 11 : Spalte10 = 0
Spalte11 = 1
End Select
Waitus Ontime
Next
Loop 'endlos weiter
End If 'Testmodus
'------------------------------ Stellphase: ----------------------------------
Sreg.7 = 1 'Interrupts erst hier freigeben !!
Portc = &B00011110 'Spalten 4-7 EIN
Portd = 0
Porta = &B11100000 'unbeteiligte Zeilen aus
Do
If Pind.2 = 1 Then 'DCF-Signal: "FUNK" blinkt
Portb = &B11101111 'Zeile 4 EIN
Else
Portb = &B11111111 'Zeile 4 AUS
End If
'die 4 blinkenden LEDs müssen über einen 100 Ohm-Vorwiderstand betrieben werden !!!
Loop Until _day > 0 'Uhr ist gestellt
'------------------------------ Hauptschleife: -------------------------------
Old_min = 99
Ontime = 999 : Offtime = 1 '1 ms per Zeile (max. 5 Zeilen)
Do
Min_canvas = _min
If Min_canvas <> Old_min Then 'wenn neue Minute
Old_min = Min_canvas 'also: nur 1x pro Minute!
'---------- Zwangs-Synchronisation nach 1 Tag: ----------
_day = 0 'siehe "sectic"-Interrupt !!
If Std_no_sync > 18 Then 'lange nicht synchronisiert
If _hour = 3 Then 'und es ist nachts 3 Uhr
If Ldr_val < 20 Then 'und es ist ziemlich dunkel
Portb = &B11111111 'alle Zeilen AUS
Porta = &B11100000
Old_min = _min
_min = 0
Do 'LEDs (und damit ggf.
nop 'Funk-Störungen) abschalten
Loop Until _day > 0 Or _min > 14 'und max. 15 Min. auf Synchro warten
Std_no_sync = 0 'neuer Zählbeginn, so oder so
Min_no_sync = 0
Sek_no_sync = 0
If _day = 0 Then 'Synchr. nicht erfolgreich:
_min = Old_min + 15 'Uhr "restaurieren"
End If
End If
End If
End If
'---------- ggf. Stunden-Korrektur: ----------
Std_canvas = _hour
If Std_canvas > 12 Then
Std_canvas = Std_canvas - 12
End If
If Std_canvas = 0 Then Std_canvas = 12
'---------- Canvas (Wiederholungs-Speicher) füllen: ----------
Canvas(1) = &B11011100 '"ES IST" ausgeben
For Index = 2 To 22
Canvas(index) = 0 'Rest leeren
Next
'---------- Canvas mit Minuten füllen: ----------
If Min_canvas > 4 Then
Index = Min_canvas \ 5
Decr Index
Index = Index * 6 'index=(((minuten div 5)-1)*6)+1
Incr Index '5...9 ->1, 10...14 -> 7, ...
8bits = Min_pat(index) 'erstes Wort
Incr Index
3bits = Min_pat(index)
Zeile = 3bits And &B00001111
Shift Zeile , Left 'index = Zeile *2 -1
Decr Zeile
Canvas(zeile) = Canvas(zeile) Or 8bits
Incr Zeile 'index = Zeile *2
Canvas(zeile) = Canvas(zeile) Or 3bits
Std_incr = 3bits And &B00010000
If Std_incr > 0 Then
Incr Std_canvas 'wg. Stunden-Inkrement
If Std_canvas > 12 Then
Std_canvas = Std_canvas - 12
End If
End If 'z.B. Halb "4" bei 3:30
Incr Index 'evtl. 2. Wort
8bits = Min_pat(index)
Incr Index
3bits = Min_pat(index)
Zeile = 3bits And &B00001111
If Zeile > 0 Then
Shift Zeile , Left
Decr Zeile
Canvas(zeile) = Canvas(zeile) Or 8bits
Incr Zeile
Canvas(zeile) = Canvas(zeile) Or 3bits
End If
Incr Index 'evtl. 3. Wort
8bits = Min_pat(index)
Incr Index
3bits = Min_pat(index)
Zeile = 3bits And &B00001111
If Zeile > 0 Then
Shift Zeile , Left
Decr Zeile
Canvas(zeile) = Canvas(zeile) Or 8bits
Incr Zeile
Canvas(zeile) = Canvas(zeile) Or 3bits
End If
Else 'nur bei Minuten <5
Canvas(20) = Canvas(20) Or &B11100000 '"UHR" anzeigen
End If 'Minuten > 4
8bits = Min_canvas Mod 5 'Einzel-Minuten ausgeben
Select Case 8bits 'über die 4 Eck-LEDs
Case 0 : 8bits = 0
Case 1 : 8bits = &B00001000
Case 2 : 8bits = &B00001100
Case 3 : 8bits = &B00001110
Case 4 : 8bits = &B00001111
End Select
Canvas(21) = Canvas(21) Or 8bits
'---------- Canvas mit Stunden füllen: ----------
If Std_canvas < 2 Then '"EIN" bzw. "EINS"
If Min_canvas < 5 Then
Index = 1 '"EIN" ... UHR
Else
Index = 3 '"EINS"
End If
Else '"ZWEI" ... "ZWÖLF"
Index = Std_canvas
Shift Index , Left
Incr Index 'index = Std *2 +1
End If 'Std <2
8bits = Std_pat(index) 'Stunden-Muster holen
Incr Index
3bits = Std_pat(index)
Zeile = 3bits And &B00001111
Shift Zeile , Left 'index = Zeile *2 -1
Decr Zeile
Canvas(zeile) = Canvas(zeile) Or 8bits 'Stunden ausgeben
Incr Zeile 'index = Zeile *2
Canvas(zeile) = Canvas(zeile) Or 3bits
End If 'Minuten <> old_min
'---------- Canvas ausgeben: ----------
Zeilen_hell = 0
For Zeile = 1 To 11 'Zeilen multiplexen
Index = Zeile 'und "Bildschirm"-Speicher
Shift Index , Left 'ausgeben
Decr Index 'index = zeile *2 -1
8bits = Canvas(index)
Incr Index 'index = zeile *2
3bits = Canvas(index)
3bits = 3bits And &B11100000 'Zeilen-Nr + Std_incr entfernen
'(
If Ontime = 0 Then '0 = ganz aus
Portb = &B11111111 'alle Zeilen AUS
Porta = &B11100000
Goto Dunkel 'kein Multiplexing !!
End If 'Nur für Tests !
')
If 8bits = 0 And 3bits = 0 Then Goto Dunkel 'wenn Zeile dunkel
Select Case Zeile
Case 01 : Portb = &B01111111 '1 Zeile ansteuern
Case 02 : Portb = &B10111111 'low-aktiv!
Case 03 : Portb = &B11011111
Case 04 : Portb = &B11101111
Case 05 : Portb = &B11110111
Case 06 : Portb = &B11111011
Case 07 : Portb = &B11111101
Case 08 : Portb = &B11111110
Case 09 : Porta = &B01100000
Case 10 : Porta = &B10100000
Case 11 : Porta = &B11000000
End Select
Portc = 8bits 'danach Spalten ansteuern
Portd = 3bits
Incr Zeilen_hell 'zählt angesteuerte Zeilen
Waitus Ontime 'Hellzeit
Portb = &B11111111 'danach alle Zeilen AUS
Porta = &B11100000 'low-aktiv!
Portc = 0 'und alle Spalten aus
Portd = 0 'high-aktiv
Waitus Offtime 'Dunkelzeit
Dunkel: 'keine Zeit( = Helligkeit)
Next 'verschwenden!!
'sorgt für gleiche Helligkeit hei untersch. Anzahl von hellen Zeilen (2-5)
For Zeile = Zeilen_hell To 4 'z.B bei 10:00: nur 2 Zeilen
Waitus Offtime 'z.B bei 10:49: 5 Zeilen!!
Waitus Ontime 'Wartezeit
Next
Loop 'Ende der Hauptschleife
'--------- Timer-Interrupt (jede Sekunde) für Helligkeitsregelung: -----------
Dim Adc_ret As Integer
Sectic:
If _hour = 0 And _min = 0 And _sec = 0 Then _day = 0 'wg. Tageswechsel !!!
If _day > 0 Then 'DCF-synchronisiert:
Sek_no_sync = 0 'no_sync-Zähler neu starten
Min_no_sync = 0
Std_no_sync = 0
End If
If _day = 0 Then '0: Semaphore für "nicht synchronisiert"
Incr Sek_no_sync 'wird von der DCF-Uhr überschrieben,
If Sek_no_sync > 59 Then 'wenn sie sich synchronisiert
Sek_no_sync = 0
Incr Min_no_sync
End If
If Min_no_sync > 59 Then
Min_no_sync = 0
Incr Std_no_sync 'zählt die nicht synchr. Zeit
End If
End If
' If Ontime = 0 Then Return 'Nur für Tests !
Ldr_val = Adch 'Helligkeitswert
Adc_ret = 5 * Ldr_val
Adc_ret = Adc_ret - 25 'Ontime = (5 * Adc_ret) - 25
If Adc_ret < 2 Then Adc_ret = 2 '= niedrigste Helligkeit
If Adc_ret > 999 Then Adc_ret = 999 '= höchste Helligkeit
Ontime = Adc_ret
Offtime = 1000 - Ontime 'Ontime + Offtime = 1ms
' Print Adc_ret ; " : " ; Ontime 'Nur für Tests
Return
'------------------------- RS232-Empfangsroutine: ----------------------------
'nur für Testzwecke !!!
'(
Dim Ser_buf As String * 5
Dim Udr_buf As Byte
Dim Dummy As String * 2
Onrxd:
Udr_buf = Udr 'Byte aus der UART auslesen
If Udr_buf <> 13 Then
If Udr_buf <> 8 Then
If Len(ser_buf) < 5 Then
Ser_buf = Ser_buf + Chr(udr_buf)
Udr = Udr_buf 'Echo auf Konsole
End If
End If
Else 'erst nach CR übergeben
Udr = 13
Udr = 10 'und CRLF zur Konsole
If Charpos(ser_buf , ":") > 0 Then ' "08:15" : Uhrzeit setzen
Dummy = Left(ser_buf , 2)
_hour = Val(dummy)
Dummy = Mid(ser_buf , 4 , 2)
_min = Val(dummy)
Else
If Charpos(ser_buf , ".") > 0 Then ' "12." : _day setzen
_day = Val(ser_buf) ' "0." : nicht synchr. setzen
Else
If Ser_buf = "?" Then ' "?" : akt. Zeit abfragen
Print _day ; "." ; _month ; "." ; _year
Print _hour ; ":" ; _min ; ":" ; _sec
Else
If Ser_buf = "??" Then ' "??" : no_sync-Zeit + Helligkeit
Print Std_no_sync ; ":" ; Min_no_sync ; ":" ; Sek_no_sync
Print Ldr_val
Else
If Charpos(ser_buf , "_") > 0 Then ' "20_: Std_no_sync setzen
Std_no_sync = Val(ser_buf)
Else
Ontime = Val(ser_buf) ' "250" : Helligkeit setzen
Offtime = 1000 - Ontime ' "0" : Multiplexing aus
End If
End If
End If
End If
End If
Ser_buf = ""
End If
Return
')
End 'end program