Ausführliche Beschreibung - Projekte

Transcrição

Ausführliche Beschreibung - Projekte
Die Geburtstagskalenderuhr
Video: http://www.youtube.com/watch?v=czhl8_Aprc8
Beschreibung des Projekts
Da ich leider manchmal die Geburtstage lieber Mitmenschen vergesse, habe ich mir gedacht, ein
Geburtstagskalender könnte vielleicht ganz nützlich sein. Wie bei einem Geburtstagskalender in
Papierform, sollten die Termine unabhängig vom jeweiligen Jahr und Wochentag am Geburtsdatum angezeigt werden. Nebenbei sollten auch andere Feiertage mit angezeigt werden.
Dazu sollte die Kalenderuhr Datum, Uhrzeit und Wochentag anzeigen und optisch und akustisch
daran erinnern, dass Heute ein besonderer Tag ist. Da ich gern fotografiere und bei Sonnenaufgang
oder Sonnenuntergang das beste Licht ist, wollte ich, dass mir die Uhr die entsprechenden Zeiten
angibt.
Datum, Uhrzeit und andere Informationen sollten auf einem 16x4 LCD-Modul angezeigt werden,
Uhrzeit und Datum der besseren Ablesbarkeit wegen auf einer zusätzlichen 7-Segmentanzeige.
-1-
Als Grundlage sollte das myAVR Board light dienen, von dem möglichst alle verfügbaren Komponenten eine Funktion bekommen sollten. Zeit und Datum sollte eine RTC-Komponente (DS1307)
liefern und sämtliche Daten sollten in einem seriellen EEPROM gespeichert werden. Die Datenübertragung sollte PC-gesteuert über das myUSBtoUART-Modul erfolgen.
Hardware
Das myAVR Board light ist die Grundlage der Kalenderuhr, auf die eine zweite (Lochraster)Platine
mit den Anzeigekomponenten gesetzt wird (Abbildung 1). Die Anzeigen sind ein 16x4 LCD-Modul
(Displaytech 164A) und eine serielle 7-Segment LED Anzeige (blau, Sparkfun Electronics). Die 7Segemtanzeige sieht nicht nur super aus (wie ich finde), sie hat auch den Vorteil nur eine einzige
Datenleitung zu benötigen. Der ATmega8 des myAVR Board light wird durch einen ATmega168
ersetzt, um etwas mehr Platz für das Programm zu haben.
Abbildung 1: Seitenansicht der Kalenderuhr
Sämtliche Daten für Geburtstage, Feiertage, Sonnenaufgänge und Sonnenuntergänge werden in
einem EEPROM (24AA128-I/P, Microchip) gespeichert. Eine Echtzeituhr (DS1307, Dallas) liefert
Datum und Uhrzeit. Das batteriegepufferte NV-RAM der Uhr dient als Speicher für Einstellungen.
Beide Komponenten werden über den seriellen I2C-Bus angesteuert. Strom liefert ein Netzteil (5V)
basierend auf dem externPowerKit von Laser & Co. Solutions GmbH. Alle diese Komponenten
werden auf dem Rasterfeld des myAVR Board light untergebracht.
-2-
Stückliste
Bauteil
Anzahl
Anbieter
myAVR Board light, Bausatz
1
Laser & Co. Solutions GmbH
16x4 LCD-Modul 164A (Displaytech)
1
Reichelt,
Art.-Nr.: LCD 164A LED
7-Segment LED Anzeige blau (seriell)
1
Watterott electronic,
Art.-Nr.: COM-09765
IC1: ATmega168PA-PU
1
IC2: EEPROM 24AA128-I/P
1
IC3: RTC DS1307
1
VR1: Spannungsregler µA 1705
1
BR1: Gleichrichter DIL B80C800DIP
1
T1: Transistor BC547C
1
D1: Diode BAT46
1
D2: Diode 1A - 1N4001
1
C6,8: Kondensator 47µF
2
C7,9: Kondensator 100nF
2
P1: Einstellpotentiometer, liegend, 5 K-Ohm
1
R2,3,6: Widerstand 10 K-Ohm
3
R5: Widerstand 480 Ohm
1
Q2: Uhrenquarz 32,768kHz (12.5 pF)
1
BAT1: Lithium-Knopfzelle: CR 2032
1
Batteriehalter 20 mm
1
IC-Sockel 28-polig (optional)
1
IC-Sockel 8-polig (optional)
2
Lochrasterplatine 100 x 100 mm
1
20 pol. Buchsenleiste gerade (RM 2,54, H: 8,5 mm)
1
10 pol. Buchsenleiste gerade (RM 2,54, H: 8,5 mm)
1
50-pol Stiftleiste gerade, RM 2,54
1
Hohlstecker-Einbaubuchse, gewinkelt
1
Wannenstecker 6-polig gerade
1
Buchsen-/Stiftleisten für Anzeigen (optional)
-3-
Schaltplan
Abbildung 2: Schaltplan
-4-
Zusammebau des myAVR Boards
Das myAVR Board light wird fast wie in der Anleitung angegeben aufgebaut. Zusätzlich wird der
6-polige Wannenstecker aufgelötet, um den ATmega168 über die ISP-Schnittstelle programmieren
zu können.
Die gewinkelte Buchsenleiste wird durch eine gerade Buchsenleiste ersetzt, die auf der Rückseite
des myAVR Boards angebracht wird. Eine Diode (D1) wird zwischen das myAVR Board light und
myUSBtoUART-Modul gelötet.
Zusätzlich wird bzw. werden:
•
PD2 und PD3 auf der Rückseite des Boards mit Taster 1 und 2 über Drähte verbunden
•
PB1 mit dem Summer verbunden.
•
PC2 mit der Photodiode verbunden.
Bestückung des Rasterfeldes auf dem myAVR Board light
Zuerst werden die Komponenten der Spannungsversorgung aufgebracht, dann die 8-poligen IC-Sockel, die Widerstände R2 und R3, der Uhrenquarz Q2 und der Batteriehalter (Abbildung 3) Nachdem die Komponenten gemäß Abb. 2 – 4 eingesetzt und verdrahtet sind, wird noch eine 10-polige
Buchsenleiste auf die Rückseite des myAVR Boards gelötet und entsprechend angeschlossen
(Abbildung 4). SDA und SCL werden mit PC4 und PC5 verbunden. LED-out wird mit der grünen
LED verbunden. Zuletzt wird der Hohlstecker über zwei Drähte mit dem Brückengleichrichter BR1
verbunden. An diesen Hohlstecker wird später das Netzteil angeschlossen.
Abbildung 3: Rasterfeld Oberseite
-5-
Abbildung 4: Rasterfeld Unterseite (Durchsicht)
Dieser Aufbau stellt für sich genommen schon eine vollständig funktionierende Einheit dar und
kann unabhängig von der Anzeigekomponente betrieben werden.
Aufbau der Anzeigekomponente
Die Anzeigekomponente wird auf einer herkömmlichen 100 x 100 mm Punktrasterplatine aufgebaut. Zuerst werden die Stiftleisten (20- und 10-polig) auf der Cu-Seite der Platine aufgelötet. Das
gestaltet sich schwierig, da Lötzinn nicht auf der unbeschichteten Seite haftet. Man muss die Stiftleisten leicht herausziehen und diese mit der Spitze des Lötkolben auf der Cu-Seite löten
(Abbildung 5).
Abbildung 5: Anbringen der Stiftleiste
Die Stiftleisten werden später mit dem myAVR Board verbunden. Man sollte sicherstellen, dass
das Board mittig auf der Punktrasterplatine sitzt. Dann werden optional die Buchsenleisten für die
-6-
Anzeigeelemente angebracht. Auch hier sollte man darauf achten, dass hinterher alles so angebracht werden kann, wie man es sich gewünscht hat. Dann werden Trimmer P1, die Widerstände
R5, R6 und der Transistor T1 aufgelötet und gemäß Abbildung 6 und Abbildung 7 verdrahtet. Es ist
hilfreich, etwas Lötzinn von der Stiftleiste bis zum nächsten Punkt auf der Rasterplatine zu ziehen,
um von hier aus die Verdrahtung durchzuführen. Die Drähte direkt an der Stiftleiste anzulöten, ist
recht schwierig.
Abbildung 6: Anzeigekomponente Oberseite (R4 und T1 liegen im realen Aufbau unterhalb des
LCD-Moduls)
-7-
Abbildung 7: Anzeigekomponente Unterseite (Durchsicht)
Die Anzeigekomponente kann jetzt mit dem myAVR Board verbunden werden. Mit P1 lässt sich
der Kontrast des LCD-Moduls regeln, die Hintergrundbeleuchtung kann über die Software (PB2)
an und ausgestellt werden. Die Kommunikation mit der seriellen 7-Segmentanzeige erfolgt über
PB0. PD4-PD7 und PC0/PC1 dienen zur Ansteuerung des LCD-Moduls.
Jetzt fehlt nur noch die Stromversorgung. Die erledigt ein Steckernetzteil mit 9V Spannung.
Anmerkung: Auf den Fotos sind noch 3 Jumper zu erkennen. Diese hatte ich zum testen des Aufbaus genutzt (Hintergrundbeleuchtung, Direktverbindung PC > 7-Segementanzeige und RW-Modus des LCD-Moduls). Für die Funktion der Uhr sind sie nicht notwendig.
-8-
Abbildung 8: Bestücktes Rasterfeld mit dem myUSBtoUART-Modul und der BAT46-Diode
(links)
Abbildung 9: Rückseite des myAVR Boards und der Anzeigekomponente (siehe dazu auch die Anmerkung auf der vorhergehenden Seite)
-9-
Programmierung
Als Programmiersprache wurde BASCOM v2 gewählt. Das fertige Programm gelangt über die ISPSchnittstelle auf den Mikrocontroller. Das Programm, dass die Daten vom PC überträgt, wurde mit
AutoIt v3 realisiert.
Programmstruktur (Atmega168)
Das Programm kann in 3 Teilbereiche gegliedert werden:
1. Anzeige von Uhrzeit, Datum, Geburtstagen, Feiertagen, Sonnenaufgängen/-untergängen
2. Empfang und Speichern von Daten und Einstellungen über das myUSBtoUART-Modul
3. Einstellungen; dazu gehören:
Uhrzeit und Datum
Hintergrundbeleuchtung des LCD-Moduls
Sommer-/Winterzeit
Zeitkorrektur
Anzeige von Uhrzeit, Datum, Geburtstagen, Feiertagen etc. (Übersicht)
Auf dem 16x4 LCD-Modul werden jeweils nach Tastendruck nacheinander folgende Bildschirme
angezeigt:
Anzeige für einen:
normalen Tag
Geburtstag
Feiertag
Startbildschirm
Taster1
Termine
um „7:43“ wird
eine Melodie
abgespielt
Taster1
Geburtstagskind „Klaus“
Sonnenaufgänge /
Sonnenuntergänge
Taster1
geboren „1951“, wird heute „60“
Datum & Uhrzeit
einstellen
Taster1
Abbildung 10: Verschiedene Anzeigen auf dem 16x4-LCD-Modul (für besser Lesbarkeit bitte
vergrößern). Video: http://www.youtube.com/watch?v=czhl8_Aprc8
- 10 -
Wie in Abbildung 10 gezeigt, ändert sich die Anzeige des Startbildschirms, wenn ein besonderes
Datum erreicht ist. Die in der zweiten Zeile angegebene Uhrzeit ist dann die Zeit, an der eine Melodie abgespielt werden kann; es kann sich dabei natürlich auch um die genaue Geburtszeit handeln.
Bei einem Geburtstag sieht man noch das Geburtsjahr und das erreichte Alter.
Die nachfolgenden Bildschirme zeigen die nächsten 3 Termine bzw. Sonnenaufgänge / Sonnenuntergänge der nächsten 3 Tage.
Der letzte Bildschirm verzweigt in den Bereich zur manuellen Zeit- bzw. Datumseinstellung. Viel
komfortabler lassen sich diese Einstellungen allerdings mit dem PC-Programm machen.
Die 7-Segmentanzeige zeigt unabhängig von den ersten 3 Bildschirmen in wechselnden Zeitabständen Uhrzeit & Datum wie folgt an:
Uhrzeit
HH:MM
Anzeigedauer: 52s
Datum
TT.MM
Anzeigedauer: 4s
Datum
JJJJ
Anzeigedauer 4s
Abbildung 11: Wechselnde Darstellung der 7-Segmentanzeige
Wenn Bildschirm 4 (Datum & Uhrzeit einstellen) erreicht wird, gibt die Anzeige „Set“ aus. Der
Doppelpunkt bei der Zeitanzeige und der Punkt bei der Datumsangabe blinken im 2s-Takt. Wenn
das Jahr angezeigt wird, wird kein (Doppel-)Punkt angezeigt
Ausgabe auf dem LCD-Modul
Die Realisierung einer Ausgabe auf einem LCD-Modul ist mit BASCOM sehr komfortabel. Dazu
muss am Anfang des Programms folgende Befehlssequenz eingefügt werden:
Config Lcdpin = Pin , Rs = Portc.0 , E = Portc.1 , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 ,
Db7 = Portd.7
Config Lcd = 16 * 4
Cursor = Off
In der Hauptprogrammschleife wird dann beispielsweise folgende Befehlssequenz verwendet:
Locate
Locate
Locate
Locate
1
2
3
4
,
,
,
,
1
1
1
1
:
:
:
:
Lcd
Lcd
Lcd
Lcd
"Datum & Uhrzeit "
Weekdaystr ; Spc(spaces)
Date$ ; Spc(8)
Time$ ; Spc(8)
Der Befehl „Cls“ wird kaum verwendet; stattdessen wird jede Zeile des LCD-Moduls vollständig
überschrieben, ggf. werden Leerzeichen (Anweisung Spc) eingefügt.
Die Umschaltung zwischen den einzelnen Bildschirmen (Abbildung 10) erledigt eine Select Case- 11 -
Anweisung in der Hauptprogrammschleife, welche die Zahl der Tastendrücke auswertet (Variable
Cntb1). Jeder Tastendruck des Tasters 1 wird über einen Debounce-Befehl ausgewertet. Debounce
(eine Art Software-Entprellung) ist optimal, allzu „nervöse“ Taster zu bändigen. Um wirklich sicher
zu gehen, wartet in der Button1-Subroutine noch ein Bitwait-Befehl auf den Taster.
Debounce Pind.2 , 0 , Button1 , Sub
...
Button1:
Bitwait Pind.2 , Reset
If Cntb1 = 3 Then Cntb1 = 0 Else Incr Cntb1
Cls
Return
Select Case Cntb1
Case 0: 'Startbildschirm
...
Case 1: 'Termine
...
Case 2: 'Sonnenauf/-untergänge
...
Case 3: 'Datum & Uhrzeit einstellen
...
End Select
Ausgabe auf der seriellen 7-Segmentanzeige
Für die Ausgabe auf der seriellen 7-Segmentanzeige muss zuerst ein Software-UART in BASCOM
realisiert werden, da das Hardware-UART für den Datenempfang zuständig sein soll:
Open "comb.0:9600,8,n,1" For Output As #1
Die serielle 7-Segementanzeige wird in der Hauptprogrammschleife dann über eine Print #1Anweisung folgendermaßen angesteuert:
Timestr = Time$
...
A = Mid(timestr , 1 , 2)
B = Mid(timestr , 4 , 2)
...
Print #1 , A ; B;
Die serielle 7-Segementanzeige kennt einige Steuerbefehle (siehe Datenblatt beim Anbieter), so
etwa zum setzen des Doppelpunkts oder des Dezimalpunkts:
Print #1
Printbin
...
Print #1
Printbin
, "w";
#1 , 16 ;
, "w";
#1 , 2;
Wichtig ist ein “;“ am Ende eines Print-Befehls, sonst zeigt das Modul nur „Müll“ an.
Die im 2s-Takt blinkende Anzeige des (Doppel)Punktes wird über den 16 Bit-Timer des
ATmega168 realisiert, dabei wird die Variable Colon_onoff auf 0 oder 1 gesetzt (ToggleAnweisung):
- 12 -
Config Timer1 = Timer , Prescale = 64
On Timer1 Toggle_colon
Enable Timer1
Start Timer1
Enable Interrupts
...
Toggle_colon:
Timer1 = 7936
Toggle Colon_onoff
If All_off = 1 Then Colon_onoff = 0
Return
Der automatische Wechsel von Datum, Uhrzeit und (Doppel-)Punkt (siehe Abbildung 11) wird
dann über einige If-Then-Else Anweisungen in der Hauptprogrammschleife realisiert
(Colon_onoff/Dp_onoff/All_off schaltet :/./ / AN bzw. AUS):
Timestr = Time$
Datestr = Date$
A = Mid(timestr , 1 , 2)
B = Mid(timestr , 4 , 2)
C = Mid(timestr , 7 , 2)
If Colon_onoff = 0 And Dp_onoff = 0 Then
Print #1 , "w";
Printbin #1 , 0 ;
Elseif Colon_onoff = 1 And Dp_onoff = 0 And All_off = 0 Then
Print #1 , "w";
Printbin #1 , 16 ;
Elseif Colon_onoff = 1 And Dp_onoff = 1 And All_off = 0 Then
Print #1 , "w";
Printbin #1 , 2 ;
Else
Print #1 , "w";
Printbin #1 , 0;
End If
If C > "30" And C <
All_off = 0
A = Mid(datestr ,
B = Mid(datestr ,
Dp_onoff = 1
Elseif C > "34" And
All_off = 1
A = "20"
B = Mid(datestr ,
Else
Dp_onoff = 0
All_off = 0
End If
"35" Then
1 , 2)
4 , 2)
C < "39" Then
7 , 2)
If A < "10" Then
A = Mid(a , 2 , 1)
Print #1 , "x" ; A ; B;
Else
Print #1 , A ; B;
End If
In der letzten If-Then-Else-Anweisung wird bei einer führenden Null das erste Segment der 7Segemtanzeige ausgeschaltet ("x"). Aus z.B. „07:34“ wird „7:34“ bzw. wird aus dem „07.04“ der
„7.04“.
Steuerung der Hintergrundbeleuchtung des LCD-Moduls
Die Hintergrundbeleuchtung des LCD-Moduls kann über das PC-Programm AN/AUS gestellt wer-
- 13 -
den. Daneben gibt es noch den Auto-Modus. Dieser Modus wertet die Helligkeit im Raum über den
Fotowiderstand des myAVR Boards und nutzt den A/D-Wandler des ATmega. Wenn es zu dunkel
ist, wird die Beleuchtung ein- und wenn es hell genug ist wieder ausgeschaltet. Unabhängig davon
wird die Hintergrundbeleuchtung um 0.00 Uhr vollständig ausgestellt und ab 7.00 wieder in den
Auto-Modus versetzt. Immer AN ist die Hintergrundbeleuchtung bei der manuellen Zeiteinstellung
und beim Abspielen einer Melodie:
Config Portc.2 -1 = Output
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Dim Licht As Word
Lcd_bl Alias Portb.2
Config Lcd_bl = Output
...
Lcd_blonoff:
Licht = Getadc(2)
If Lcd_blst = "1" Then
Lcd_bl = 1
Elseif Lcd_blst = "3" And Licht < 120 And _hour > 6 Then
Lcd_bl = 1
Else
Lcd_bl = 0
End If
Return
Die Lcd_blonoff-Subroutine wird dann in der Hauptprogrammschleife aufgerufen. Lcd_bl (ein
„Alias“ für Portb.2) schaltet die Hintergrundbeleuchtung AN oder AUS. Lcd_blst bestimmt, welcher Modus vorliegt. Die Variable Licht steuert, ab wann die Beleuchtung angeschaltet wird; 120
war hier ein guter Wert. Die Variable Lcd_blst wird im NV SRAM der DS1307-RTC gespeichert.
Wie das funktioniert, wird im Abschnitt Schreiben & Lesen von Daten & Zeiteinstellung beschrieben.
Uhrzeit & Datum
Aktuelle Uhrzeit und Datum sind in den Variablen Time$ und Date$ enthalten, die BASCOM generiert. Über den I2C-Bus wird die DS1307-RTC wie folgt angesprochen:
$lib "i2c_twi.lbx"
Config Sda = Portc.4
Config Scl = Portc.5
Const Ds1307w = &HD0
Const Ds1307r = &HD1
...
Config Clock = User
Config Date = Dmy , Separator = .
...
Getdatetime:
I2cstart
I2cwbyte Ds1307w
I2cwbyte 0
I2cstart
I2cwbyte Ds1307r
I2crbyte _sec , Ack
I2crbyte _min , Ack
I2crbyte _hour , Ack
I2crbyte Weekday , Ack
I2crbyte _day , Ack
'TWI
'DS1307 schreiben
'DS1307 lesen
- 14 -
I2crbyte _month , Ack
I2crbyte _year , Nack
I2cstop
_sec = Makedec(_sec) : _min = Makedec(_min) : _hour = Makedec(_hour)
_day = Makedec(_day) : _month = Makedec(_month) : _year = Makedec(_year)
Return
Eine Ausgabe auf dem LCD-Modul wird wie oben angegeben realisiert:
Locate
Locate
Locate
Locate
1
2
3
4
,
,
,
,
1
1
1
1
:
:
:
:
Lcd
Lcd
Lcd
Lcd
"Datum & Uhrzeit "
Weekdaystr ; Spc(spaces)
Date$ ; Spc(8)
Time$ ; Spc(8)
Der Wochentag „Weekday“ ist eine Zahl, die über eine Data-Tabelle in den entsprechenden Wochentag „Weekdaystr“ umgesetzt wird:
Weekdaystr = Lookupstr(weekday , Weekdays)
...
Weekdays:
Data "dummy" , "Montag" , "Dienstag" , "Mittwoch" , "Donnerstag" , "Freitag" , "Samstag" , "Sonntag"
Empfang von Daten über das UART
Der Empfang der Zeichen erfolgt Interrupt-gesteuert. Im Gegensatz zum Input-Befehl wird das
Programm weiter ausgeführt und wartet nicht auf eine Eingabe:
Dim L As String * 4
Dim S As String * 30
Dim Z(31) As Byte At S Overlay
Dim N As Byte
...
On Urxc Onrxd
Enable Urxc
'ggf. „Enable Interrupts“ falls noch nicht anderweitig aktiviert
...
Onrxd:
Incr N
Z(n) = UDR
Return
Eine weitere schöne Sache an BASCOM sind „Overlays“ (siehe BASCOM-Hilfe). Die über UART
empfangenen Zeichen „Z(n)“ werden zum String „S“ zusammengesetzt.
Bei jeder Übertragung werden 31 Zeichen „N“ gesendet, die ersten vier Zeichen „L“ geben an, um
welche Art von Daten es sich handelt und was der ATmega damit machen soll (Select Case,
Case...):
If N > 30 Then
L = Left(s , 4)
Select Case L
Case "TEST":
...
Case "TIME":
- 15 -
...
Case "SETT":
...
Case "SUNS":
...
Case "DATE":
...
Case "CDAT":
...
End Select
End If
Der „Case“ TEST ist der einfachste Fall, hier wird der empfangene String an den PC zurück gesendet. Das dient zur Kontrolle, ob die Kommunikation zwischen Kalenderuhr und PC funktioniert:
...
Case "TEST":
N = 0
Print S;
...
N muss nach jeder CASE-Anweisung wieder auf 0 gesetzt werden.
Schreiben & Lesen von Daten & Zeiteinstellung
Zeiteinstellungen
Datum, Wochentag und Uhrzeit können über folgende Unterprozeduren gesetzt werden (man beachte jeweils das I2Cwbyte nach Ds1307w):
Const Ds1307w = &HD0
'DS1307 schreiben
...
Setdate:
_day = Makebcd(_day) : _month = Makebcd(_month) : _year = Makebcd(_year)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 4
I2cwbyte _day
I2cwbyte _month
I2cwbyte _year
I2cstop
Waitms 10
Return
Setweekday:
I2cstart
I2cwbyte Ds1307w
I2cwbyte 3
I2cwbyte Weekday
I2cstop
Waitms 10
Return
Settime:
_sec = Makebcd(_sec) : _min = Makebcd(_min) : _hour = Makebcd(_hour)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 0
I2cwbyte _sec
I2cwbyte _min
I2cwbyte _hour
I2cstop
Waitms 10
Return
- 16 -
Zeit und Datum lassen sich in BASCOM aber auch komfortabel über die Variablen Time$ und
Date$ setzen.
Die Echtzeituhr verfügt außerdem über 56 Byte batteriegepuffertes NV SRAM. In diesem werden
diverse Einstellungen der Kalenderuhr gespeichert. Nachfolgend die Angabe, ob momentan Sommerzeit (Stset=1, Wtset=0) oder Winterzeit (Stset=0, Wtset=1) ist (man beachte wieder das
I2Cwbyte nach Ds1307w):
Const Ds1307w = &HD0
...
Writenvram:
I2cstart
I2cwbyte Ds1307w
I2cwbyte 8
I2cwbyte Stset
I2cwbyte Wtset
I2cstop
Waitms 10
Return
'DS1307 schreiben
Die Zeitdaten, die das Programm über den PC empfängt (siehe Empfang von Daten über das
UART), sehen folgendermaßen aus:
TIME :07.04.1140121:56:57xxxxxx
TIME kennzeichnet, dass es sich um eine Zeitübertragung handelt
07.04.11 ist das Datum
4 ist der Wochentag (Donnerstag)
01 zeigt an, dass wir Sommerzeit haben (10 wäre Winterzeit)
21:56:57 ist die Uhrzeit
xxxxxx ist einfach ein Platzhalter, da immer 31 Zeichen übertragen werden.
Die Echtzeituhr wird dann wie folgt eingestellt:
...
Case "TIME":
N = 0
Time$ = Mid(s , 18 , 8)
Date$ = Mid(s , 7 , 8)
Weekdayst = Mid(s , 15 , 1)
Weekday = Weekdayst
Call Setweekday
Wtsetst = Mid(s , 16 , 1)
Stsetst = Mid(s , 17 , 1)
Wtset = Val(wtsetst)
Stset = Val(stsetst)
Call Writenvram
...
Aus dem empfangenen String „s“ werden Zeit und Datum über die Mid-Anweisung extrahiert und
gesetzt. Der Wochentag „Weekday“ wird über Call Setweekday gesetzt. Ob momentan Sommerbzw. Winterzeit vorliegt, wird in das NV SRAM über Call Writenvram geschrieben.
- 17 -
Einstellen von Sommerzeit und Winterzeit
Sommer- und Winterzeit werden von der Kalenderuhr automatisch eingestellt (Letzter Sonntag im
März oder Oktober). Wichtig ist, dass bei einer Zeitübertragung vom PC aus immer angegeben werden muss, ob momentan Sommerzeit oder Winterzeit vorliegt. Bei einer Übertragung werden die
Variablen Stset und Wtset im NV SRAM gespeichert und von der nachfolgenden Routine ausgewertet:
Dst_onoff:
If _month = 3 And _day > 24 And Weekday = 7 And _hour = 2 Then
_hour = _hour + 1
Waitms 10
Call Settime
Stset = 1
Wtset = 0
Waitms 10
Call Writenvram
End If
If Wtset = 0 And _month = 10 And _day > 24 And Weekday = 7 And _hour = 3 Then
_hour = _hour - 1
Waitms 10
Call Settime
Wtset = 1
Stset = 0
Waitms 10
Call Writenvram
End If
Return
Die Anweisung _hour = _hour + 1 bzw. _hour = _hour – 1 stellt die Uhr eine Stunde vor bzw.
zurück. Über Call Settime wird die Uhrzeit gespeichert und die aktuellen Variablen Wtset und
Stset werden im NV SRAM gespeichert (Call Writenvram). Die Subroutine Dst_onoff wird in
der Hauptprogrammschleife aufgerufen.
Weitere Einstellungen
Weitere Einstellungen, die NV SRAM gespeichert werden, ist der Modus der
Hintergrundbeleuchtung und die Zeitkorrektur. Die Variablen werden über das PC-Programm
gesendet (siehe Empfang von Daten über das UART) und im NV SRAM abgelegt. Der gesendete
String ist folgendermaßen aufgebaut:
SETT: 310300000000000000000000x
SETT kennzeichnet, dass es sich um eine Einstellung handelt
3 bedeutet, dass die Hintergrundbeleuchtung auf Auto gestellt werden soll (1 = AN; 2=AUS)
1 bedeutet, dass die nachfolgende Sekundenzahl immer nach 24h abgezogen wird
(Zeitkorrektur) ; 0 würde bedeuten, dass die nachfolgende Sekundenzahl immer nach 24h
addiert wird
03 ist die Zahl der Sekunden, um die nach 24h korrigiert wird
die restlichen Nullen und das x sind Platzhalter, da immer 31 Zeichen übertragen werden.
Um die Zeitkorrektur nach 24h durchzuführen, muss die Kalenderuhr wissen, wann die Korrektur- 18 -
daten übertragen wurden. Dazu werden die BASCOM-Routinen Sysday() und Secofday() aufgerufen und die Ergebnisse zusammen mit den übertragenen Daten im NV SRAM abgelegt (Call
Writenvram_sett). Die Definition der Variablen als „Overlay“ ermöglicht eine direkte Transformation der Variablen (Systemtag, Sekdestages) als abspeicherbare Bytes (Systemtagby,
Sekdestagesby):
Dim Systemtag As Long
Dim Systemtagby(4) As Byte At Systemtag Overlay
Dim Sekdestages As Long
Dim Sekdestagesby(4) As Byte At Sekdestages Overlay
...
Case "SETT":
N = 0
Systemtag = Sysday()
Sekdestages = Secofday()
Call Writenvram_sett
Call Readnvram
...
Die Zeichen aus der Datenübertragung vom PC können direkt im NV SRAM abgelegt werden; Z(7)
ist z.B. das 7. übertragene Zeichen. Das I2Cwbyte nach Ds1307w ist diesmal 10, da 8 und 9 bereits
belegt sind (siehe Writenvram):
Writenvram_sett:
I2cstart
I2cwbyte Ds1307w
I2cwbyte 10
I2cwbyte Z(7)
I2cwbyte 0
I2cwbyte Z(8)
I2cwbyte 0
I2cwbyte Z(9)
I2cwbyte Z(10)
I2cwbyte 0
I2cwbyte Systemtagby(1)
I2cwbyte Systemtagby(2)
I2cwbyte Systemtagby(3)
I2cwbyte Systemtagby(4)
I2cwbyte Sekdestagesby(1)
I2cwbyte Sekdestagesby(2)
I2cwbyte Sekdestagesby(3)
I2cwbyte Sekdestagesby(4)
I2cstop
Waitms 10
Return
Da wichtige Einstellungsvariablen nicht im RAM des ATmega gelandet sind, muss der gerade ins
NV SRAM geschriebene Inhalt sofort wieder über Call Readnvram gelesen werden (hier erfolgt
dann die Zuordnung der Daten aus dem NV SRAM zu Variablen):
Dim Lcd_blst As String * 1
Dim Lcd_blby(2) As Byte At Lcd_blst Overlay
Dim Plusminst As String * 1
Dim Plusminby(2) As Byte At Plusminst Overlay
Dim Sekundest As String * 2
Dim Sekundeby(3) As Byte At Sekundest Overlay
- 19 -
Dim Systemtag As Long
Dim Systemtagby(4) As Byte At Systemtag Overlay
Dim Sekdestages As Long
Dim Sekdestagesby(4) As Byte At Sekdestages Overlay
...
Readnvram:
I2cstart
I2cwbyte Ds1307w
I2cwbyte 8
I2cstart
I2cwbyte Ds1307r
I2crbyte Stset , Ack
I2crbyte Wtset , Ack
I2crbyte Lcd_blby(1) , Ack
I2crbyte Lcd_blby(2) , Ack
I2crbyte Plusminby(1) , Ack
I2crbyte Plusminby(2) , Ack
I2crbyte Sekundeby(1) , Ack
I2crbyte Sekundeby(2) , Ack
I2crbyte Sekundeby(3) , Ack
I2crbyte Systemtagby(1) , Ack
I2crbyte Systemtagby(2) , Ack
I2crbyte Systemtagby(3) , Ack
I2crbyte Systemtagby(4) , Ack
I2crbyte Sekdestagesby(1) , Ack
I2crbyte Sekdestagesby(2) , Ack
I2crbyte Sekdestagesby(3) , Ack
I2crbyte Sekdestagesby(4) , Nack
I2cstop
Return
Bei jedem Reset oder direkt nach dem Einschalten der Kalenderuhr wir vor der Hauptprogrammschleife Call Readnvram ausgeführt.
Zeitkorrektur
Die DS1307-RTC + Quarz ist nicht unbedingt ein hochpräzises Zeitmessinstrument, was am Quarz
liegen kann oder allgemein am Aufbau. Die nachfolgende Subroutine korrigiert die Uhrzeit alle 24h
zu einer bestimmten Uhrzeit um +/– x Sekunden. Die nachfolgende Routine ist recht komplex, was
daran liegt, dass die Zeitkorrektur erst am darauffolgenden Tag passieren darf und dass bei einer
negativen Zeitkorrektur die Kalenderuhr nicht in einer Korrekturschleife hängen bleibt. Sekundest
(Sekunde, um die korrigiert wird) und Plusminst (Zeitkorrektur + oder – ) werden aus dem NV
SRAM gelesen (Readnvram) (über „Overlay“ umgewandelt), ebenso Systemtag (Datum der Zeitkorrekturübertragung) und Sekdestages (Sekunde des Tages, an dem die Zeitkorrekturübertragung stattfand) (siehe vorheriger Abschnitt):
Dim Korrektur As Long
Dim Sekundelong As Long
Dim Sysd As Long
Dim Secd As Long
Dim Zeitkorrekturbit As Bit
...
Zeitkorrektur:
Call Readnvram
Sysd = Sysday()
Secd = Secofday()
Sekundelong = Val(sekundest)
If Secd = 86399 Then Zeitkorrekturbit = 0
- 20 -
If Plusminst = "0" Then Korrektur = Sekdestages + Sekundelong
If Plusminst = "1" Then Korrektur = Sekdestages - Sekundelong
If Sysd <> Systemtag And Secd = Sekdestages And Sekundelong <> 0 And Zeitkorrekturbit = 0 Then
Time$ = Time(korrektur)
Zeitkorrekturbit = 1
End If
Return
'
Sysd und Secd entsprechen der aktuellen Systemsekunde und dem aktuellen Systemdatum. Nur
wenn diese nicht den gespeicherten Daten entsprechen, wird die Zeitkorrektur angewendet (letzte
If-Then-Else-Anweisung). Die Zeit wird über die BASCOM-Funktion Time aus der korrigierten
Sekunde des Tages eingestellt (Time$ = Time(korrektur)). Danach muss das Zeitkorrekturbit auf 1 gesetzt werden, um zu verhindern, dass bei einer negativen Korrektur die Zeit immer
wieder neu eingestellt wird. Am Ende des Tages wird das Zeitkorrekturbit wieder auf 0 gesetzt
(If Secd = 86399 Then Zeitkorrekturbit = 0).
Sonnenaufgänge und Sonnenuntergänge speichern und abrufen
Sonnenaufgänge und Sonnenuntergänge für einen bestimmten Standort zu berechnen, ist recht
aufwendig, so dass diese Daten nur übertragen (siehe Empfang von Daten über das UART) und im
EEPROM abgespeichert werden. Der gesendete String ist folgendermaßen aufgebaut:
SUNS: 421704:2420:280000000000x
SUNS kennzeichnet, dass es sich um einen Sonnenauf/untergang handelt
4217 ist der Tag des Sonnenauf/untergangs (gerechnet ab dem 01.01.2000)
04:24 ist der Zeitpunkt des Sonnenaufgangs
20:28 ist der Zeitpunkt des Sonnenuntergangs
die restlichen Nullen und das x sind Platzhalter, da immer 31 Zeichen übertragen werden.
Die nachfolgende CASE-Anweisung ruft die Subroutine Eepromwsonne auf:
...
Case "SUNS":
N = 0
Call Eepromwsonne
...
Const Eeprw = &HA0
Const Eeprr = &HA1
Dim Adresse_sonne As Word
Dim Adresse_sonne_high As Byte
Dim Adresse_sonne_low As Byte
Dim X As Byte
...
Eepromwsonne:
N = 0
For X = 7 To 20
Adresse_sonne_high = High(adresse_sonne)
- 21 -
Adresse_sonne_low = Low(adresse_sonne)
I2cstart
I2cwbyte
I2cwbyte
I2cwbyte
I2cwbyte
I2cstop
Eeprw
Adresse_sonne_high
Adresse_sonne_low
Z(x)
Waitms 10
Incr Adresse_sonne
Next
If Adresse_sonne > 1399 Then Adresse_sonne = 0
'14 bytes pro sonnenauf/-untergang /
Return
Da es sich um ein größeres EEPROM handelt, muss man den Adressbereich in High- und Low
trennen, was BASCOM praktischerweise über die Funktionen High und Low erledigt. Ansonsten
muss man noch beachten, dass von jedem übertragenen String nur die Zeichen 7 bis 20 gespeichert
(For X = 7 To 20....I2cwbyte Z(x)...). Nach 100 übertragenen Tagen wird die Adresse wieder auf 0 gesetzt.
Gelesen werden diese Daten über die nachfolgende Funktion. Übergeben wird der Funktion als Argument die Adresse (adresse_sonne) und man erhält als Ergebnis einen String, der den Tag und
die Uhrzeiten für Sonnenaufgang bzw. Sonnenuntergang beinhaltet:
Const Eeprw = &HA0
Const Eeprr = &HA1
Dim Sonnetagst As String * 14
Dim Sonnetagby(14) As Byte At Sonnetagst Overlay
Dim
Dim
Dim
Dim
Adresse_sonne As Word
Adresse_sonne_high As Byte
Adresse_sonne_low As Byte
X As Byte
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Stageeprom As String * 14
Stageepromday As String * 4
Sahst As String * 2
Sarest As String * 3
Suhst As String * 2
Surest As String * 3
Sahstn As Integer
Suhstn As Integer
...
Function Eepromrsonne(adresse_sonne As Word) As String * 14
For X = 1 To 14
Adresse_sonne_high = High(adresse_sonne)
Adresse_sonne_low = Low(adresse_sonne)
I2cstart
I2cwbyte Eeprw
I2cwbyte Adresse_sonne_high
I2cwbyte Adresse_sonne_low
I2cstart
I2cwbyte Eeprr
I2crbyte Sonnetagby(x) , Nack
I2cstop
- 22 -
Incr Adresse_sonne
Next
Stageeprom = Sonnetagst
Stageepromday = Left(stageeprom , 4)
If Stset = 1 And Wtset = 0 Then
Sahst = Mid(stageeprom , 5 , 2)
Sarest = Mid(stageeprom , 7 , 3)
Suhst = Mid(stageeprom , 10 , 2)
Surest = Mid(stageeprom , 12 , 3)
Sahstn = Val(sahst)
Incr Sahstn
Sahst = Str(sahstn)
Sahst = Format(sahst , "00")
Suhstn = Val(suhst)
Incr Suhstn
Suhst = Str(suhstn)
Suhst = Format(suhst , "00")
Stageeprom = Stageepromday + Sahst + Sarest + Suhst + Surest
End If
Eepromrsonne = Stageeprom
End Function
Auf den ersten Blick wirkt diese Funktion recht umfangreich, da ggf. die Sommerzeit berücksichtigt
werden muss. Eigentlich werden sonst nur 14 Bytes zu einem String zusammengesetzt, der den Tag
und die Uhrzeiten für Sonnenaufgang bzw. Sonnenuntergang beinhaltet.
Geburtstagstermine und Feiertage (kurz Termine) speichern und abrufen
Im Vergleich zur Sonnenaufgangs- oder Sonnenuntergangsdaten sind die Funktionen, um Geburtstage und Feiertage im EEPROM abzuspeichern oder von dort zu lesen etwas komplexer. Das liegt
hauptsächlich darin begründet, dass die Anzahl der abzuspeichernden Daten nicht konstant ist (im
Fall Sonnenaufgänge und Sonnenuntergänge waren es genau 100) und das zu bestimmten Terminen bestimmte Aktionen ausgeführt werden sollen.
Als erstes muss bei jeder Datenübertragung vom PC die Startadresse der Datenspeicherung auf Ihren Ursprungswert zurück gesetzt werden, da der ATmega nicht weiß, ob jetzt der erste oder irgendeinen nachfolgender Termin gesendet wird. Dazu wird vom PC vor der eigentlichen Datenübertragung folgender String gesendet (siehe Empfang von Daten über das UART):
CDATxxxxxxxxxxxxxxxxxxxxxxxxxxx
CDAT kennzeichnet, dass die Startadresse zur Terminspeicherung im EEPROM angesteuert
werden soll
die restlichen x sind Platzhalter, da immer 31 Zeichen übertragen werden.
Die nachfolgende CASE-Anweisung setzt dann das EEPROM auf die Startadresse:
- 23 -
Dim Adresse_terminw As Word
...
Case "CDAT":
N = 0
Adresse_terminw = 0
...
Danach sendet der PC folgenden String (bzw. mehrere Strings, je nach der Anzahl der Termine):
DATE0304195127780G1Klaus
1
DATE kennzeichnet, dass es sich um einen Termin handelt
03041951 ist das Geburtsdatum (03.04.1951)
27780 ist die Uhrzeit und gleichzeitig die Zeit, an der eine Melodie abgespielt wird;
angegeben als Sekunde des Tages (07:43)
G kennzeichnet, dass es sich um einen Geburtstag handelt (F = Feiertag)
1 ist die abzuspielende Melodie (0= Keine Melodie)
Klaus ist das Geburtstagskind; bis zu 10 Zeichen sind hier möglich
1 kennzeichnet, dass 1 Termin übertragen wird (2 für 2 Termine, 3 für 3 usw.; max. 99).
Am Ende der Übertragung werden zwei DATE-Strings gesendet, die nur Nullen enthalten,
DATE000000000000000000000000000. Das hat den Zweck, das Ende der aktuell übertragenen Terminliste zu kennzeichnen. Da die Daten im EEPROM nicht gelöscht, sondern nur immer wieder
überschrieben werden, könnte der Fall eintreten, dass eine evtl. vorher im EEPROM abgelegte Liste länger war als die gerade übertragene. Durch die beiden letzten DATE-Strings wird verhindert,
dass die Termine der alten Liste auf der Kalenderuhr angezeigt werden.
Die nachfolgende CASE-Anweisung ruft die Subroutine Eepromwtermine auf:
...
Case "DATE":
N = 0
Call Eepromwtermine
...
Const Eeprw = &HA0
Const Eeprr = &HA1
Dim Adresse_terminw As Word
Dim Adresse_termine14k As Word
Dim Adresse_termine_high14k As Byte
Dim Adresse_termine_low14k As Byte
...
Eepromwtermine:
N = 0
For X = 5 To 31
Adresse_termine14k = 1400 + Adresse_terminw
Adresse_termine_high14k = High(adresse_termine14k)
Adresse_termine_low14k = Low(adresse_termine14k)
- 24 -
I2cstart
I2cwbyte
I2cwbyte
I2cwbyte
I2cwbyte
I2cstop
Eeprw
Adresse_termine_high14k
Adresse_termine_low14k
Z(x)
Waitms 10
Incr Adresse_terminw
Next
Return
Diese Subroutine ist analog zur Subroutine Eepromwsonne, mit dem Unterschied, dass die Startadresse mit 1400 addiert wird (sonst würden die Daten für den Sonnenaufgang bzw. Sonnenuntergang überschrieben werden) und dass die Startadresse am Ende nicht zurückgesetzt wird (das erledigt „CDAT“). Von jedem übertragenen String werden nur die Zeichen 5 bis 31 gespeichert (For X =
5 To 31....I2cwbyte Z(x)...).
Gelesen werden diese Daten über die nachfolgende Funktion. Übergeben wird der Funktion als Argument die Speicheradresse eines Termins (adresse_termine) und man erhält als Ergebnis über
die BASCOM-Funktion Dayofyear den Tag im Jahr, an dem das Ereignis stattfindet (Termindate):
Const Eeprw = &HA0
Const Eeprr = &HA1
Dim
Dim
Dim
Dim
Adresse_termine As Word
Adresse_termine14k As Word
Adresse_termine_high14k As Byte
Adresse_termine_low14k As Byte
Dim Terminest As String * 28
Dim Termineby(28) As Byte At Terminest Overlay
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Termine_t As String * 2
Termine_m As String * 2
Termine_j As String * 2
Termine_jv As String * 4
Termine_jvi As Integer
Terminedatest As String * 8
Terminedate As Integer
Dim Schaltjahr As Integer
Dim Termine_ij As Integer
...
Function Gettermintag(adresse_termine As Word) As Integer
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine
Adresse_termine_high14k = High(adresse_termine14k)
Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart
I2cwbyte Eeprw
I2cwbyte Adresse_termine_high14k
I2cwbyte Adresse_termine_low14k
I2cstart
I2cwbyte Eeprr
I2crbyte Termineby(x) , Nack
I2cstop
- 25 -
Incr Adresse_termine
Next
Termine_t = Left(terminest , 2)
Termine_m = Mid(terminest , 3 , 2)
Termine_j = Mid(terminest , 7 , 2)
Termine_jv = Mid(terminest , 5 , 4)
Terminedatest = Termine_t + "." + Termine_m + "." + Termine_j
Terminedate = Dayofyear(terminedatest)
Termine_ij = Val(termine_j)
Schaltjahr = Termine_ij Mod 4
If Schaltjahr = 0 And Terminedate > 59 Then
Decr Terminedate
End If
'Schaltjahr
Gettermintag = Terminedate
End Function
Zuerst muss das im EEPROM abgelegte Datum (z.B. 03041951) in ein für die Funktion Dayofyear
verwertbares Datumsformat umgeformt werden (aus 030411951 wird 03.04.1951). Das Jahr wird
noch einmal extra als Zahl in die Variable Termine_ij geschrieben. Wenn man mit Dayofyear arbeitet, muss man wissen, ob das Jahr ein Schaltjahr ist. Das lässt sich bequem über die Anweisung
Schaltjahr = Termine_ij Mod 4 ermitteln (jedes Schaltjahr zwischen 1901 und 2099 ist ohne
Rest durch 4 teilbar). Das betrifft natürlich nur Termine nach dem 28. Februar (...Terminedate
> 59).
Für die Nutzung der Terminfunktion der Kalenderuhr sind aber noch ein paar weitere Funktionen
nötig. Die folgende Funktion, Getterminadresse, ermittelt die Speicheradresse eines bestimmten
Termins im EEPROM. Übergeben wird der Funktion als Argument der Tag heute, der über die
BASCOM-Funktion Dayofyear(Date$) in der Hauptprogrammschleife erzeugt wird und man erhält als Ergebnis die Speicheradresse des Termins des heutigen Tages:
Dim Maxadressew As Word
Dim Heute As Integer
Dim Alarm_heute As Bit
...
Function Getterminadresse(heute As Integer) As Word
Maxadressew = Getmaxadressetermine(0)
For Adresse_termine = 0 To Maxadressew Step 27
Terminedate = Gettermintag(adresse_termine)
If Terminedate = Heute Then Alarm_heute = 1 Else Alarm_heute = 0
If Terminedate >= Heute Then Exit For
Next
Getterminadresse = Adresse_termine
End Function
Hauptsächlich bedient sich diese Funktion der Ergebnisse der Funktionen
Getmaxadressetermine und Gettermintag. Falls der heutige Tag ein besonderer Tag ist
- 26 -
(Geburtstag oder Feiertag), setzt die Funktion die Variable Alarm_heute auf 1.
Die Funktion Getmaxadressetermine ermittelt die Speicheradresse des letzten Termins einer Reihe von Terminen. Übergeben wird der Funktion als Argument adresse_termine (Speicheradresse eines bestimmten Termins), das aber im Programm immer 0 ist. Es wäre also nicht wirklich notwendig gewesen, die nachfolgenden Anweisungen in eine Funktion zu packen, der Übersichtlichkeit halber habe ich es aber so gelassen. Als Ergebnis erhält man die oben erwähnte Speicheradresse des letzten Termins:
Const Eeprw = &HA0
Const Eeprr = &HA1
Dim Maxadressew As Word
Dim Maxadressest As String * 2
...
Function Getmaxadressetermine(adresse_termine As Word) As Word
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine
Adresse_termine_high14k = High(adresse_termine14k)
Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart
I2cwbyte Eeprw
I2cwbyte Adresse_termine_high14k
I2cwbyte Adresse_termine_low14k
I2cstart
I2cwbyte Eeprr
I2crbyte Termineby(x) , Nack
I2cstop
Incr Adresse_termine
Next
Maxadressest = Mid(terminest , 26 , 2)
Maxadressew = Val(maxadressest)
Maxadressew = Maxadressew * 27
Getmaxadressetermine = Maxadressew
End Function
Die Funktion setzt den ersten im EEPROM gespeicherten Termin-String wieder zusammen. Die
letzten zwei Zeichen des Strings (Maxadressest = Mid(terminest , 26 , 2)) enthalten die
maximale Anzahl an übertragenen Datensätzen (siehe DATE-String). Daraus lässt sich dann die
Speicheradresse des letzten Termins ermitteln.
Die Funktionen Eepromrtermine gibt einen im EEPROM abgelegten String aus. Übergeben wird
der Funktion als Argument adresse_termine, also die Speicheradresse eines bestimmten Termins:
Const Eeprw = &HA0
Const Eeprr = &HA1
Dim
Dim
Dim
Dim
Termine_t As
Termine_m As
Termine_p As
Terminelcdst
String * 2
String * 2
String * 10
As String * 16
- 27 -
...
Function Eepromrtermine(adresse_termine As Word) As String * 16
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine
Adresse_termine_high14k = High(adresse_termine14k)
Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart
I2cwbyte Eeprw
I2cwbyte Adresse_termine_high14k
I2cwbyte Adresse_termine_low14k
I2cstart
I2cwbyte Eeprr
I2crbyte Termineby(x) , Nack
I2cstop
Incr Adresse_termine
Next
Termine_t = Left(terminest , 2)
Termine_m = Mid(terminest , 3 , 2)
Termine_p = Mid(terminest , 16 , 10)
Terminelcdst = Termine_t + "." + Termine_m + " " + Termine_p
If Termine_t = "00" Then Terminelcdst = Space(16)
Eepromrtermine = Terminelcdst
End Function
Die Funktion setzt im ersten Schritt einen im EEPROM gespeicherten Termin-String wieder zusammen. Dabei wird aus „0304195127780G1Klaus
1“ „03.04 Klaus
„. Das sind
dann genau 16 Zeichen, entsprechend der Anzeigegröße des LCD-Moduls. Das Ergebnis wird in der
Variable Terminelcdst gespeichert. Falls der Termin-String nur Nullen enthält (bzw. die ersten
beiden Zeichen 00 sind), werden 16 Leerzeichen ausgegeben (If Termine_t = "00" Then
Terminelcdst = Space(16)).
Eine letzte Funktion in diesem Zusammenhang ist Eepromrtermine_alarm. Übergeben wird der
Funktion als Argument adresse_termine, also die Speicheradresse eines bestimmten Termins.
Als Ergebnis ermittelt die Funktion die Sekunde des Tages, an dem ggf. eine Melodie abgespielt
werden soll:
Const Eeprw = &HA0
Const Eeprr = &HA1
Dim Termine_sek As String * 5
Dim Termine_mu As String * 1
Dim Termine_geburtstag As String * 1
Dim Termine_alarml As Long
...
Function Eepromrtermine_alarm(adresse_termine As Word) As Long
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine
Adresse_termine_high14k = High(adresse_termine14k)
Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart
I2cwbyte Eeprw
I2cwbyte Adresse_termine_high14k
- 28 -
I2cwbyte Adresse_termine_low14k
I2cstart
I2cwbyte Eeprr
I2crbyte Termineby(x) , Nack
I2cstop
Incr Adresse_termine
Next
Termine_sek = Mid(terminest , 9 , 5)
Termine_mu = Mid(terminest , 15 , 1)
Termine_geburtstag = Mid(terminest , 14 , 1)
'Musik abspielen?
'Geburtstag oder Feiertag
Termine_alarml = Val(termine_sek)
Eepromrtermine_alarm = Termine_alarml
End Function
Die Funktion ermittelt wie beschrieben aus einem im EEPROM gespeicherten Termin-String die
Sekunde des Tages (Termine_sek), die Information, ob Musik abgespielt werden soll und welche
(Termine_mu) und die Information, ob es sich um einen Geburtstag oder Feiertag handelt
(Termine_geburtstag) (siehe dazu auch DATE-String). Die Variablen Termine_mu und
Termine_geburtstag werden zwar nicht direkt als Ergebnis der Funktion übermittelt, werden
aber innerhalb der Funktion mit Werten gefüllt, die in der Hauptprogrammschleife abgerufen werden.
Ausgabe von gespeicherten Daten auf dem 16x4-LCD-Modul
Sämtliche gespeicherten Daten, sowie Datum & Uhrzeit werden innerhalb der Hauptprogrammschleife ausgegeben. Durch drücken des Tasters kann zwischen verschiedenen Ausgabebildschirmen umgeschaltet werden. Die Zahl der Tastendrücke wird über eine CASE-Anweisung ausgewertet
(siehe Anzeige von Uhrzeit, Datum, Geburtstagen, Feiertagen etc. (Übersicht)). Der erste Ausgabebildschirm zeigt normalerweise Wochentag, Datum und Uhrzeit an. Liegt ein besonderer Termin
vor, wir dieser angezeigt:
Dim Adresse_termine As Word
Dim Termine_geburtstag As String * 1
Dim Termine_alarmst As String * 6
Dim Termine_alarml As Long
Dim Alarm_heute As Bit
Dim Termin_heute As String * 16
Dim Termine_jv As String * 4
Dim Termine_jvi As Integer
Dim Bdate As String * 2
Dim Bdatei As Integer
Dim Alter As Integer
Dim Spaces As Integer
...
Select Case Cntb1
Case 0:
If Alarm_heute = 1 Then
Adresse_termine = Getterminadresse(heute)
Termin_heute = Eepromrtermine(adresse_termine)
Termin_heute = Mid(termin_heute , 7 , 10)
- 29 -
Termine_alarml = Eepromrtermine_alarm(adresse_termine)
Termine_alarmst = Time(termine_alarml)
Termine_alarmst = Left(termine_alarmst , 5)
Bdate = Mid(datestr , 7 , 2)
Bdate = "20" + Bdate
Termine_jvi = Val(termine_jv)
Bdatei = Val(bdate)
Alter = Bdatei - Termine_jvi
Locate 1 , 1 : Lcd "Heute " ; Termin_heute
If Termine_geburtstag = "G" Then
Locate 2 , 1 : Lcd Termine_alarmst ; " " ; Termine_jv ; " " ; Alter ; " J"
Else
Locate 2 , 1 : Lcd Termine_alarmst ; Spc(11)
End If
Locate 3 , 1 : Lcd Date$ ; Spc(8)
Locate 4 , 1 : Lcd Time$ ; Spc(8)
Else
Spaces = Len(weekdaystr)
Spaces = 16 - Spaces
Locate
Locate
Locate
Locate
1
2
3
4
,
,
,
,
1
1
1
1
:
:
:
:
Lcd
Lcd
Lcd
Lcd
"Datum & Uhrzeit "
Weekdaystr ; Spc(spaces)
Date$ ; Spc(8)
Time$ ; Spc(8)
End If
...
Ob ein besonderer Termin vorliegt, gibt die Variable Alarm_heute an. Die auszugebenden Daten
werden aus dem EEPROM geladen. Die entsprechenden Funktionen dazu (Getterminadresse,
Eepromrtermine, Eepromrtermine_alarm) wurden im vorangegangenen Kapitel vorgestellt. Das
Alter (Variable Alter) des Geburtstagskindes wird ebenfalls berechnet. Die Ausgabe eines Feiertages oder Geburtstages ist unterschiedlich. Die Variable Termine_geburtstag zeigt an, ob es sich
bei dem Termin um einen Feiertag (F) oder Geburtstag (G) handelt. Der Variablen wird durch das
Aufrufen der Funktion Eepromrtermine_alarm der entsprechende Wert zugewiesen. Die verschiedenen Ausgabebildschirme sind in Abbildung 10 dargestellt.
Der nächste Ausgabebildschirm zeigt die nächsten 3 anstehenden Termine:
Dim Adresse_termine As Word
Dim Heute As Integer
Dim Maxadressew As Word
Dim Eepromrtermine_heute As String * 17
...
Case 1:
Heute = Dayofyear(date$)
Maxadressew = Getmaxadressetermine(0)
Adresse_termine = Getterminadresse(heute)
Eepromrtermine_heute = Eepromrtermine(adresse_termine)
If Adresse_termine > Maxadressew Then Adresse_termine = 0
Locate 1 , 1 : Lcd "Termine" ; Spc(9)
If Eepromrtermine_heute <> "
" Then
Locate 2 , 1 : Lcd Eepromrtermine(adresse_termine)
Else
Adresse_termine = 0
Locate 2 , 1 : Lcd Eepromrtermine(adresse_termine)
- 30 -
End If
Adresse_termine = Adresse_termine + 27
Locate 3 , 1 : Lcd Eepromrtermine(adresse_termine)
Adresse_termine = Adresse_termine + 27
Locate 4 , 1 : Lcd Eepromrtermine(adresse_termine)
...
Zuerst wird der Variablen Heute der Tag des Jahres zugewiesen. Die Variable Maxadressew enthält die Gesamtzahl der Termine. Sollte der letzte Termin erreicht sein, wird Adresse_termine
auf null gesetzt. Das bedeutet, nachdem der letzte im EEPROM abgelegte Termin angezeigt wurde,
wird wieder der erste im EEPROM abgelegte Termin angezeigt. Nachdem die Adresse des ersten
anzuzeigenden Termins bekannt ist, werden einfach die beiden nächsten abgespeicherten Termine
angezeigt (Adresse_termine = Adresse_termine + 27). Damit nicht irgendwann Termine aus
einer alten Terminliste oder Datenmüll angezeigt wird, enthalten die letzten beiden im EEPROM
abgelegten Einträge nur Nullen (siehe DATE-String). Die Funktionen Getmaxadressetermine,
Getterminadresse und Eepromrtermine wurden im vorangegangenen Kapitel vorgestellt. Der
Ausgabebildschirm ist in Abbildung 10 dargestellt.
Im nächsten Ausgabebildschirm werden die Uhrzeiten für die Sonnenaufgänge bzw. Sonnenuntergänge der heutigen Tages und der folgenden 2 Tage angegeben. Der Übersichtlichkeit halber, werden im folgenden Abschnitt Funktionsaufrufe und Berechnungen teilweise ausführlicher dargestellt, als eigentlich für die Funktion der Kalenderuhr notwendig.
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Stageeprom As String * 14
Stageepromday As String * 4
Sahst As String * 2
Sarest As String * 3
Suhst As String * 2
Surest As String * 3
Sahstn As Integer
Suhstn As Integer
Dim Sa As String * 5
Dim Su As String * 5
Dim Sysdx As Long
Dim Sysdw As Word
Dim Systemtageepr As String * 5
Dim Systemtageeprl As Long
...
Case 2:
Sa = Eepromrsonne(0)
Systemtageepr = Mid(sa , 1 , 4)
Systemtageeprl = Val(systemtageepr)
Sysdx = Sysday()
Sysdw = Sysdx - Systemtageeprl
Sysdw = Sysdw * 14
Sa = Eepromrsonne(sysdw)
Sa = Mid(sa , 5 , 5)
Su = Eepromrsonne(sysdw)
Su = Mid(su , 10 , 5)
Locate 1 , 1 : Lcd "SonnenA/U 3 Tage"
Locate 2 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
Sysdx = Sysday()
Sysdx = Sysdx + 1
- 31 -
Sysdw = Sysdx - Systemtageeprl
Sysdw = Sysdw * 14
Sa = Eepromrsonne(sysdw)
Sa = Mid(sa , 5 , 5)
Su = Eepromrsonne(sysdw)
Su = Mid(su , 10 , 5)
Locate 3 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
Sysdx = Sysday()
Sysdx = Sysdx + 2
Sysdw = Sysdx - Systemtageeprl
Sysdw = Sysdw * 14
Sa = Eepromrsonne(sysdw)
Sa = Mid(sa , 5 , 5)
Su = Eepromrsonne(sysdw)
Su = Mid(su , 10 , 5)
Locate 4 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
...
Zuerst wird der erste im EEPROM gespeicherte String über die Funktion Eepromrsonne abgefragt
(siehe dazu auch Sonnenaufgänge und Sonnenuntergänge speichern und abrufen). Aus diesem
String wird der (System)Tag (gerechnet ab dem 01.01.2000) ermittelt (Systemtageeprl). Danach
wird der aktuelle Systemtag über die BASCOM-Funktion Sysday ermittelt. Über die Subtraktion
des aktuellen Systemtages mit dem ersten gespeicherten Systemtag (Sysdw = Sysdx - Systemtageeprl) erhält man nach der Multiplikation mit 14 (Sysdw = Sysdw * 14) die Speicheradresse
des heutigen Tages im EEPROM. Der gespeicherte String, der die Daten des heutigen Tages enthält, wird über die Funktion Eepromrsonne ermittelt. Aus diesem String werden die Zeitangaben
für den Sonnenaufgang (Sa) und Sonnenuntergang (Su) ermittelt. Für die Anzeige der Daten des
nächsten Tages wird der aktuelle Systemtag mit 1 addiert (Sysdx = Sysdx + 1) , für den übernächsten Tag mit 2 (Sysdx = Sysdx + 2). Der Ausgabebildschirm ist in Abbildung 10 dargestellt.
Der nächste Ausgabebildschirm (Case 3)widmet sich der manuellen Einstellung von Wochentag,
Datum und Zeit (Abbildung 10). Auf eine ausführliche Erläuterung dieses Programmteils wird an
dieser Stelle verzichtet, da sich Datum und Zeit bequemer über das PC-Programm einstellen lassen
(siehe Zeiteinstellungen).
Abspielen einer Melodie
Ob eine und wann eine Melodie abgespielt wird, wird in der Hauptprogrammschleife ermittelt:
Dim Adresse_termine As Word
Dim Termine_alarml As Long
Dim Alarm_heute As Bit
Dim Termin_heute As String * 16
Dim Termine_mu As String * 1
...
Heute = Dayofyear(date$)
...
Adresse_termine = Getterminadresse(heute)
Termine_alarml = Eepromrtermine_alarm(adresse_termine)
If Termine_alarml = Secofday() And Alarm_heute = 1 And Termine_mu <> "0" Then
Call Play_music(termine_mu)
End If
...
- 32 -
Zuerst wird die Speicheradresse des heutigen Tages über die Funktion Getterminadresse ermittelt. Die Funktion Eepromrtermine_alarm ermittelt die Sekunde des Tages, an dem die Melodie
abgespielt werden soll. Mit der If-Anweisung wird ermittelt, ob alle Bedingungen für das Abspielen einer Melodie erfüllt sind. Den Variablen Alarm_heute und Termine_mu werden Werte durch
das Aufrufen der Funktionen Getterminadresse und Eepromrtermine_alarm zugewiesen. Die
aktuelle Sekunde des Tages wird über die BASCOM-Funktion Secofday ermittelt. Ist diese Sekundenzahl gleich der Sekunde, die im EEPROM gespeichert wurde und ist der heutige Tag ein besonderer Tag und ist die Variable Termine_mu ungleich “0“, wird schließlich Call Play_music(termine_mu) ausgeführt. Der Subroutine Play_music wird die Nummer der abzuspielenden
Melodie übergeben. Durch den Aufruf der Subroutine und der nachfolgenden Select Case...CaseAnweisungen wir die Melodie abgespielt:
Lcd_bl Alias Portb.2
Config Lcd_bl = Output
Config Portb.1 = Output
Speaker Alias Portb.1
...
Dim Note As Integer
Dim Laenge As Integer
Dim Pause As Integer
...
Sub Play_music(song_nr As String * 1)
If Lcd_bl = 0 Then Lcd_bl = 1
Select Case Song_nr
Case "1"
For I = 0 To 55
Note = Lookup(i , Happyb)
Incr I
If Note = 0 Then
Pause = Lookup(i , Happyb)
Waitms Pause
Else
Laenge = Lookup(i , Happyb)
Sound Speaker , Note , Laenge
End If
Next I
Case "2"
For I = 0 To 57
Note = Lookup(i , Merryx)
Incr I
If Note = 0 Then
Pause = Lookup(i , Merryx)
Waitms Pause
Else
Laenge = Lookup(i , Merryx)
Sound Speaker , Note , Laenge
End If
Next I
End Select
...
Happyb:
Data 65% , 587% , 65% , 587% , 147% , 523% , 131% , 587% , 175%
Data 440% , 165% , 466% , 0% , 250% , 65% , 587% , 65% , 587% , 147%
Data 523% , 131% , 587% , 196% , 392% , 175% , 440% , 0% , 250% , 65%
Data 587% , 65% , 587% , 262% , 294% , 220% , 349% , 175% , 440% , 165%
Data 466% , 147% , 523% , 0% , 125% , 117% , 330% , 117% , 330% , 220%
Data 349% , 175% , 440% , 196% , 392% , 175% , 440%
- 33 -
Merryx:
Data 147% , 523% , 196% , 392% , 98% , 392% , 110% , 349% , 98% , 392%
Data 92% , 415% , 165% , 466% , 131% , 587% , 165% , 466% , 220% , 349%
Data 110% , 349% , 124% , 311% , 110% , 349% , 98% , 392% , 185% , 415%
Data 294% , 523% , 247% , 311% , 124% , 311% , 131% , 294% , 124% , 311%
Data 110% , 349% , 196% , 392% , 165% , 466% , 73% , 523% , 73% , 523%
Data 165% , 466% , 220% , 349% , 185% , 415% , 196% , 392%
Die Tonausgabe erledigt in BASCOM die Anweisung Sound mit den Variablen Speaker, Note,
Laenge. Speaker ist dabei ein Alias auf Portb.1 (siehe auch Schaltplan), die Werte für Note und
Laenge werden über Lookup aus einer Data-Tabelle gelesen. Die Variable I in der For-Next-Anweisung gibt die Nummer des Wertes in der Tabelle an. Pausen (ohne Ton) werden über den Wert
Note = 0 ermöglicht. Im oberen Code-Abschnitt sind zwei Melodien angegeben. Insgesamt wären
9 möglich. Beim Abspielen einer Melodie wird die Hintergrundbeleuchtung des LCD-Moduls eingeschaltet. Die Berechnung der Werte für die Variablen Note und Laenge wird im nächsten Kapitel
erläutert.
Programmstruktur des PC-Programms (tool.au3)
Die Programmierung des PC-Programms erfolgte mit AutoIt v3. Die Datenübertragung nutzt die
Bibliothek CommMG.au3 v2.8 von Martin Gibson. Die Programmoberfläche wurde mit Koda erstellt. Auf die Programmierung werde ich nachfolgend nicht so ausführlich eingehen, wie im vorangegangenen Kapitel. Der Programmcode ist (so denke ich) recht übersichtlich. Innerhalb der
Hauptprogrammschleife werden über Switch und Case jeweils nach bestimmten Aktionen (Mausklick) bestimmte Programmteile ausgeführt. Der Befehl _CommSendString sendet die im Kapitel
Empfang von Daten über das UART erwähnten Strings an die Kalenderuhr. Die Übertragung ist
relativ langsam (dafür sicher), kann aber je nach System und Anbindung auch schneller erfolgen.
Das muss man individuell austesten. Wenn die Kalenderuhr nur Datenmüll anzeigen sollte, erfolgt
die Übertragung jedenfalls zu schnell für das System. Daneben enthält das Programm Funktionen,
um Sonnenaufgänge bzw. Sonnenuntergänge und variable Feiertage, wie etwa die Osterfeiertage zu
berechnen.
Das Programm besteht aus 3 Tabs, die verschiedene Funktionen des Programms zusammenfassen.
Diese Funktionen werden nachfolgend kurz vorgestellt.
- 34 -
Datum, Uhrzeit, Einstellungen, Sonnenaufgänge und Sonnenuntergänge
Nach dem Öffnen des Programms wird folgender Tab gezeigt:
Auswahl des COM-Ports
Test-String senden
TEST: Gesendet & Empfangen 1234
Sommerzeit?
Datum und Zeit individuell einstellen
Datum / Zeit senden
Gesendeter String
Datum und Zeit des PCs
TIME :18.04.1110122:27:40xxxxxx
Hintergrundbeleuchtung
Einstellungen senden
Zeitkorrektur
Gesendeter String
SETT: 100000000000000000000000x
Fortschrittsbalken
Sonnena./u. senden
Abbildung 12: Erstes Tab (Registerkarte) des PC-Programms. Die dem Screenshot hinzugefügten
Erläuterungen zu den Steuerfunktionen sind Blau gedruckt.
Die Funktionen sind relativ selbsterklärend. Zuerst muss der passende COM-Port ausgewählt werden. Die Einstellung kann getestet werden, in dem man einen Test-String sendet. Datum und Uhrzeit können zu Testzwecken auf jeden beliebigen Wert eingestellt und übertragen werden. Sind die
Häkchen bei Systemdatum und/oder Systemzeit gesetzt, wird das aktuelle Datum bzw. die aktuelle
Uhrzeit des PCs übertragen (siehe Zeiteinstellungen). Einstellungen zur Hintergrundbeleuchtung
und zur Zeitkorrektur können ebenfalls gesetzt und gesendet werden (siehe Weitere Einstellungen
und Steuerung der Hintergrundbeleuchtung des LCD-Moduls). Als letzte Funktion auf diesem Tab
können Sonnenaufgänge und Sonnenuntergänge an die Kalenderuhr gesendet werden (siehe
Sonnenaufgänge und Sonnenuntergänge speichern und abrufen). Im Programmcode des AutoItSkripts müssen ggf. noch Breitengrad und Längengrad des Ortes angepasst werden.
- 35 -
Geburtstage und Feiertage
Eine Liste von Geburtstagen und Feiertage kann im folgenden Tab angelegt, gespeichert und an die
Kalenderuhr übertragen werden:
(Geburts-)Datum(Geburts-)Zeit Geburtstag oder Feiertag? Ausgabetext (10 Zeichen)
Welche Melodie?
Gesendeter String
Hinzufügen
Fortschrittsbalken
DATE3112201143200F0Silvester 15
Termine: Speichern / Laden / an die Kalenderuhr senden
Abbildung 13: Zweites Tab (Registerkarte) des PC-Programms. Die dem Screenshot hinzugefügten
Erläuterungen zu den Steuerfunktionen sind Blau gedruckt.
Die Termine werden automatisch nach Datum (Tag und Monat) sortiert und können auf dem PC
gespeichert und wieder geladen werden. Feiertage hinzufügen fügt automatisch eine Reihe von
Feiertagen zur Terminliste hinzu. Das Datum der variablen Feiertage (Ostern, Pfingsten und Himmelfahrt) wird vom PC-Programm jeweils vorher berechnet. Momentan kann nur zwischen 2 Melodien bzw. keiner Melodie gewählt werden. Ohne größere Anpassung des Codes wären bis zu 9
Melodien möglich. Mit Senden wird die Terminliste schließlich übertragen (siehe
Geburtstagstermine und Feiertage (kurz Termine) speichern und abrufen).
- 36 -
Der Melodiegenerator
Das ist eine Funktion des Programms, die mit Hilfe des myAVR Boards Klingeltöne, wie sie etwa
um das Jahr 2000 herum üblich waren, wieder abspielbar macht. Auf der folgenden Internetseite
ist recht ausführlich erklärt, wie Noten für die BASCOM-Sound Anweisung umgesetzt werden
können:
http://www.mcselec.com/index.php?option=com_content&task=view&id=221&Itemid=57
Anhand der dort angegebenen Berechnungen, die hauptsächlich von der Frequenz des eingesetzten
Quarzes abhängen, können z.B. über eine Tabellenkalkulation für jede mögliche Note die entsprechenden Werte ausgerechnet werden.
Auf der nachfolgenden Internetseite finden sich z.B. noch jede Menge Klingeltöne, die einfach nur
in das Programmfenster des PC-Programms kopiert werden müssen:
http://www.xs4all.nl/~vbergen/ringtones/siemens/index_2000.html
Name der Melodie
Klingelton im Siemens (C25/S25/C35/S35/M35)-Format
BASCOM-Code
Abbildung 14: Drittes Tab (Registerkarte) des PC-Programms. Die dem Screenshot
hinzugefügten Erläuterungen zu den Steuerfunktionen sind Blau gedruckt.
- 37 -
Im unteren Bereich steht der BASCOM-Code für den entsprechenden Klingelton bzw. die Melodie,
der nur noch in das Programm eingefügt werden muss. Die entsprechenden Variablen wurden zu
Programmbeginn deklariert.
Fazit
Soviel zum Projekt der Kalenderuhr. Fast alle Funktionen des myAVR Boards konnten genutzt
werden. Nur die beiden Potis sind noch frei, sowie ein Pin des ATmega.
Softwareseitig ist noch etwas Speicherplatz vorhanden, der mit weiteren Melodien oder mit
Programmcode gefüllt werden kann, auch das EEPROM hat noch Platz für Daten.
Der Programmcode bietet bestimmt dem einen oder anderen erfahrenen BASCOM-Programmierer
noch Ansätze zum optimieren. Funktionsfähig ist er jedenfalls und läuft so wie er ist, seit einiger
Zeit stabil.
Ohne Hilfe hätte ich die Kalenderuhr niemals zum laufen bekommen. An erster Stelle soll hier die
BASCOM-Hilfe stehen, die wirklich sehr umfangreich ist und schon viele Lösungsansätze bietet:
http://avrhelp.mcselec.com/index.html
Sehr hilfreich bei der Programmierung waren auch die folgenden Internetseiten:
http://halvar.at/elektronik/kleiner_bascom_avr_kurs/
http://www.rn-wissen.de/index.php/Kategorie:Quellcode_Bascom
http://www.rowalt.de/mc/index.htm
Die im PC-Programm verwendeten Funktionen sind, soweit übernommen, dort gekennzeichnet.
Hardwareseitig waren mir die von der Laser & Co. Solutions GmbH bereitgestellten Schaltpläne
eine große Hilfe, so wurde der Aufbau fast zum Kinderspiel.
Bei der Zusammenstellung von Texten und Abbildungen bin ich mit großer Sorgfalt vorgegangen.
Trotzdem kann ich Fehler nicht vollständig ausschließen. Für fehlerhafte Angaben und deren
Folgen kann ich weder irgendeine Haftung noch juristische Verantwortung übernehmen.
Sebastian Dechert
- 38 -
BASCOM-Quellcode
Die wichtigsten Programmteile werden im Kapitel Programmierung ausführlich erklärt.
$regfile = "m168def.dat"
$crystal = 3686400
$baud = 9600
$lib "i2c_twi.lbx"
Config Sda = Portc.4
Config Scl = Portc.5
Const Ds1307w = &HD0
Const Ds1307r = &HD1
Const Eeprw = &HA0
Const Eeprr = &HA1
'
Config Timer1 = Timer , Prescale = 64
On Timer1 Toggle_colon
Enable Timer1
Start Timer1
Enable Interrupts
Config Lcdpin = Pin , Rs = Portc.0 , E = Portc.1 , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 ,
Db7 = Portd.7
Config Lcd = 16 * 4
Cursor = Off
Config Clock = User
Config Date = Dmy , Separator = .
On Urxc Onrxd
Enable Urxc
Config Pind.2 = 0
Config Pind.3 = 0
Portd.2 = 1
Portd.3 = 1
Lcd_bl Alias Portb.2
Config Lcd_bl = Output
Config Portb.1 = Output
Speaker Alias Portb.1
Config Portc.2 -1 = Output
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Dim Licht As Word
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
A As String * 10
B As String * 10
C As String * 10
D As Integer
E As Integer
F As Integer
G As Integer
H As Integer
I As Integer
J As Integer
K As Integer
Timestr As String * 10
Datestr As String * 10
Weekdaystr As String * 10
Colon_onoff As Bit
Dp_onoff As Bit
All_off As Bit
Weekday As Byte
Weekdayst As String * 1
Cntb1 As Integer
Cntb2 As Integer
Exitbyte As Byte
- 39 -
Dim
Dim
Dim
Dim
Stset As Byte
Wtset As Byte
Stsetst As String * 1
Wtsetst As String * 1
Dim
Dim
Dim
Dim
L As String * 4
S As String * 30
Z(31) As Byte At S Overlay
N As Byte
Dim Lcd_blst As String * 1
Dim Lcd_blby(2) As Byte At Lcd_blst Overlay
Dim Plusminst As String * 1
Dim Plusminby(2) As Byte At Plusminst Overlay
Dim Sekundest As String * 2
Dim Sekundeby(3) As Byte At Sekundest Overlay
Dim Systemtag As Long
Dim Systemtagby(4) As Byte At Systemtag Overlay
Dim Sekdestages As Long
Dim Sekdestagesby(4) As Byte At Sekdestages Overlay
Dim
Dim
Dim
Dim
Dim
Korrektur As Long
Sekundelong As Long
Sysd As Long
Secd As Long
Zeitkorrekturbit As Bit
Dim Sonnetagst As String * 14
Dim Sonnetagby(14) As Byte At Sonnetagst Overlay
Dim
Dim
Dim
Dim
Adresse_sonne As Word
Adresse_sonne_high As Byte
Adresse_sonne_low As Byte
X As Byte
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Xx As Word
Stageeprom As String * 14
Stageepromday As String * 4
Sahst As String * 2
Sarest As String * 3
Suhst As String * 2
Surest As String * 3
Sahstn As Integer
Suhstn As Integer
Dim Sa As String * 5
Dim Su As String * 5
Dim Sysdx As Long
Dim Sysdw As Word
Dim Systemtageepr As String * 5
Dim Systemtageeprl As Long
Dim Terminest As String * 28
Dim Termineby(28) As Byte At Terminest Overlay
Dim
Dim
Dim
Dim
Dim
Adresse_terminw As Word
Adresse_termine As Word
Adresse_termine14k As Word
Adresse_termine_high14k As Byte
Adresse_termine_low14k As Byte
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Termine_t As String * 2
Termine_m As String * 2
Termine_j As String * 2
Termine_x As String * 1
Termine_p As String * 10
Terminedatest As String * 8
Terminedate As Integer
Heute As Integer
Terminelcdst As String * 16
Maxadressest As String * 2
- 40 -
Dim Maxadressew As Word
Dim Schaltjahr As Integer
Dim Termine_ij As Integer
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Termine_sek As String * 5
Termine_mu As String * 1
Termine_geburtstag As String * 1
Termine_alarmst As String * 6
Termine_alarml As Long
Alarm_heute As Bit
Termin_heute As String * 16
Termine_jv As String * 4
Termine_jvi As Integer
Bdate As String * 2
Bdatei As Integer
Alter As Integer
Spaces As Integer
Dim Eepromrtermine_heute As String * 17
Dim Dummy As Byte
Dim Note As Integer
Dim Laenge As Integer
Dim Pause As Integer
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Declare
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Sub
Happy_mel
Merry_mel
Setup
Setupweekday
Setweekday
Setdate
Settime
Setuptime
Gotomain
Dst_onoff
Sun_riseset
Delnvram
Writenvram
Writenvram_sett
Readnvram
Setup1
Lcd_blonoff
Zeitkorrektur
Eepromwsonne
Eepromwtermine
Play_music(song_nr As String)
Declare
Declare
Declare
Declare
Declare
Declare
Function
Function
Function
Function
Function
Function
Eepromrsonne(byval Adresse_sonne As Word) As String
Eepromrtermine(byval Adresse_termine As Word) As String
Getterminadresse(byval Heute As Integer) As Word
Getmaxadressetermine(byval Adresse_termine As Word) As Word
Gettermintag(byval Adresse_termine As Word) As Integer
Eepromrtermine_alarm(byval Adresse_termine As Word) As Long
'Wochentag, Uhrzeit und Datum ohne Setup einstellen
'Time$ = "00:04:00"
'Date$ = "08:02:11"
'Weekday = 1
'Call Setweekday
Open "comb.0:9600,8,n,1" For Output As #1
Waitms 500
Print #1 , "v";
Close #1
'Reset der 7Seg.-Anzeige
'Print #1 , "z";
'Printbin #1 , 128 ;
'Close #1
'Helligkeit der 7Seg.-Anzeige einstellen
Waitms 500
- 41 -
Call Readnvram
Waitms 500
'Call Delnvram
'NV-Ram der RTC loeschen
Cls
'#####################################################
'# main loop
#
'#####################################################
Do
Call Dst_onoff
Call Lcd_blonoff
Call Zeitkorrektur
Heute = Dayofyear(date$)
Termine_j = Mid(date$ , 7 , 2)
Termine_ij = Val(termine_j)
Schaltjahr = Termine_ij Mod 4
If Schaltjahr = 0 And Heute >= 60 Then
Decr Heute
End If
'Schaltjahr
Adresse_termine = Getterminadresse(heute)
Termine_alarml = Eepromrtermine_alarm(adresse_termine)
If Termine_alarml = Secofday() And Alarm_heute = 1 And Termine_mu <> "0" Then
Call Play_music(termine_mu)
Else
End If
Timestr = Time$
Datestr = Date$
Weekdaystr = Lookupstr(weekday , Weekdays)
A = Mid(timestr , 1 , 2)
B = Mid(timestr , 4 , 2)
C = Mid(timestr , 7 , 2)
If Colon_onoff = 0 And Dp_onoff = 0 Then
Print #1 , "w";
Printbin #1 , 0 ;
'Close #1
Elseif Colon_onoff = 1 And Dp_onoff = 0 And All_off = 0 Then
Print #1 , "w";
Printbin #1 , 16 ;
'Close #1
Elseif Colon_onoff = 1 And Dp_onoff = 1 And All_off = 0 Then
Print #1 , "w";
Printbin #1 , 2 ;
Else
Print #1 , "w";
Printbin #1 , 0;
End If
If C > "30" And C <
All_off = 0
A = Mid(datestr ,
B = Mid(datestr ,
Dp_onoff = 1
Elseif C > "34" And
All_off = 1
A = "20"
B = Mid(datestr ,
Else
Dp_onoff = 0
All_off = 0
End If
"35" Then
1 , 2)
4 , 2)
C < "39" Then
7 , 2)
If A < "10" Then
A = Mid(a , 2 , 1)
Print #1 , "x" ; A ; B;
- 42 -
Else
Print #1 , A ; B;
End If
Select Case Cntb1
Case 0:
If Alarm_heute = 1 Then
Adresse_termine = Getterminadresse(heute)
Termin_heute = Eepromrtermine(adresse_termine)
Termin_heute = Mid(termin_heute , 7 , 10)
Termine_alarml = Eepromrtermine_alarm(adresse_termine)
Termine_alarmst = Time(termine_alarml)
Termine_alarmst = Left(termine_alarmst , 5)
Bdate = Mid(datestr , 7 , 2)
Bdate = "20" + Bdate
Termine_jvi = Val(termine_jv)
Bdatei = Val(bdate)
Alter = Bdatei - Termine_jvi
Locate 1 , 1 : Lcd "Heute " ; Termin_heute
If Termine_geburtstag = "G" Then
Locate 2 , 1 : Lcd Termine_alarmst ; " " ; Termine_jv ; " " ; Alter ; " J"
Else
Locate 2 , 1 : Lcd Termine_alarmst ; Spc(11)
End If
Locate 3 , 1 : Lcd Date$ ; Spc(8)
Locate 4 , 1 : Lcd Time$ ; Spc(8)
Else
Spaces = Len(weekdaystr)
Spaces = 16 - Spaces
Locate
Locate
Locate
Locate
1
2
3
4
,
,
,
,
1
1
1
1
:
:
:
:
Lcd
Lcd
Lcd
Lcd
"Datum & Uhrzeit "
Weekdaystr ; Spc(spaces)
Date$ ; Spc(8)
Time$ ; Spc(8)
End If
Case 1:
Heute = Dayofyear(date$)
Maxadressew = Getmaxadressetermine(0)
Adresse_termine = Getterminadresse(heute)
Eepromrtermine_heute = Eepromrtermine(adresse_termine)
If Adresse_termine > Maxadressew Then Adresse_termine = 0
Locate 1 , 1 : Lcd "Termine" ; Spc(9)
If Eepromrtermine_heute <> "
" Then
Locate 2 , 1 : Lcd Eepromrtermine(adresse_termine)
Else
Adresse_termine = 0
Locate 2 , 1 : Lcd Eepromrtermine(adresse_termine)
End If
Adresse_termine = Adresse_termine + 27
Locate 3 , 1 : Lcd Eepromrtermine(adresse_termine)
Adresse_termine = Adresse_termine + 27
Locate 4 , 1 : Lcd Eepromrtermine(adresse_termine)
Case 2:
Sa = Eepromrsonne(0)
Systemtageepr = Mid(sa , 1 , 4)
Systemtageeprl = Val(systemtageepr)
- 43 -
Sysdx = Sysday()
Sysdw = Sysdx - Systemtageeprl
Sysdw = Sysdw * 14
Sa = Eepromrsonne(sysdw)
Sa = Mid(sa , 5 , 5)
Su = Eepromrsonne(sysdw)
Su = Mid(su , 10 , 5)
Locate 1 , 1 : Lcd "SonnenA/U 3 Tage"
Locate 2 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
Sysdx = Sysday()
Sysdx = Sysdx + 1
Sysdw = Sysdx - Systemtageeprl
Sysdw = Sysdw * 14
Sa = Eepromrsonne(sysdw)
Sa = Mid(sa , 5 , 5)
Su = Eepromrsonne(sysdw)
Su = Mid(su , 10 , 5)
Locate 3 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
Sysdx = Sysday()
Sysdx = Sysdx + 2
Sysdw = Sysdx - Systemtageeprl
Sysdw = Sysdw * 14
Sa = Eepromrsonne(sysdw)
Sa = Mid(sa , 5 , 5)
Su = Eepromrsonne(sysdw)
Su = Mid(su , 10 , 5)
Locate 4 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
Case 3:
Exitbyte = 0
Call Setup
End Select
Debounce Pind.2 , 0 , Button1 , Sub
If N > 30 Then
L = Left(s , 4)
Select Case L
Case "TEST":
N = 0
Print S;
Case "TIME":
N = 0
Time$ = Mid(s , 18 , 8)
Date$ = Mid(s , 7 , 8)
Weekdayst = Mid(s , 15 , 1)
Weekday = Weekdayst
Call Setweekday
Wtsetst = Mid(s , 16 , 1)
Stsetst = Mid(s , 17 , 1)
Wtset = Val(wtsetst)
Stset = Val(stsetst)
Call Writenvram
Case "SETT":
N = 0
Systemtag = Sysday()
Sekdestages = Secofday()
- 44 -
Call Writenvram_sett
Call Readnvram
Case "SUNS":
N = 0
Call Eepromwsonne
Case "DATE":
N = 0
Call Eepromwtermine
Case "CDAT":
N = 0
Adresse_terminw = 0
End Select
End If
Loop
'#####################################################
'# UART Interuppt / Zeichen über UART empfangen
#
'#####################################################
Onrxd:
Incr N
Z(n) = Udr
Return
'#####################################################
'# Datum & Uhrzeit einstellen / CASE 2
#
'#####################################################
Setup:
Bitwait Pind.2 , Reset
Lcd_bl = 1
Cls
Print #1 , "SEtx" ;
Print #1 , "w";
Printbin #1 , 0 ;
While Cntb1
Locate 1
Locate 2
Locate 3
Locate 4
Debounce
Debounce
Wend
= 3
, 1 : Lcd "Datum & Uhrzeit"
, 1 : Lcd " einstellen"
, 1 : Lcd ">T1=Uebernehmen<"
, 1 : Lcd ">T2=Einstellen<"
Pind.2 , 0 , Gotomain , Sub
Pind.3 , 0 , Setupweekday , Sub
Return
'------Setupweekday:
Cls
While Exitbyte = 0
Weekdaystr = Lookupstr(weekday , Weekdays)
Locate 1 , 1 : Lcd "Wochentag einst."
Locate 2 , 1 : Lcd Weekdaystr ; "
"
Debounce Pind.2 , 0 , Setupdate , Sub
Debounce Pind.3 , 0 , Incrweekday , Sub
Waitms 20
- 45 -
Wend
Return
'------Incrweekday:
Bitwait Pind.3 , Reset
If Weekday < 7 Then Incr Weekday Else Weekday = 1
Return
'-------Setupdate:
Call Setweekday
Locate 2 , 1 : Lcd "Tag" ; Spc(13)
A = Mid(datestr , 1 , 2)
B = Mid(datestr , 4 , 2)
C = Mid(datestr , 7 , 2)
D = Val(a) : E = Val(b) : F = Val(c)
While Exitbyte = 0
A = Str(d)
A = Format(a , "00")
B = Str(e)
B = Format(b , "00")
C = Str(f)
C = Format(c , "00")
Locate 1 , 1 : Lcd "Datum einst.
"
Locate 3 , 1 : Lcd A ; "." ; B ; "." ; C
Debounce Pind.2 , 0 , Setupdmy , Sub
Debounce Pind.3 , 0 , Incrdmy , Sub
Waitms 20
Wend
Call Setuptime
Return
'------Incrdmy:
Bitwait Pind.3 , Reset
Select Case I
Case 0:
Locate 2 , 1 :
If D < 31 Then
Case 1:
Locate 2 , 1 :
If E < 12 Then
Case 2:
Locate 2 , 1 :
If F < 30 Then
End Select
Lcd "Tag" ; Spc(13)
Incr D Else D = 1
Lcd "Monat" ; Spc(11)
Incr E Else E = 1
Lcd "Jahr" ; Spc(12)
Incr F Else F = 11
Return
'-------Setupdmy:
Bitwait Pind.2 , Reset
If I > 1 Then
I = 0
_day = D : _month = E : _year = F
Call Setdate
Exitbyte = 1
- 46 -
Else
Incr I
End If
Return
'-------Setuptime:
Locate 2 , 1 : Lcd "Stunde" ; Spc(10)
A = Mid(timestr , 1 , 2)
B = Mid(timestr , 4 , 2)
C = Mid(timestr , 7 , 2)
G = Val(a) : H = Val(b) : J = Val(c)
While Exitbyte = 1
A = Str(g)
A = Format(a , "00")
B = Str(h)
B = Format(b , "00")
C = Str(j)
C = Format(c , "00")
Locate 1 , 1 : Lcd "Uhrzeit einst. "
Locate 4 , 1 : Lcd A ; ":" ; B ; ":" ; C
Debounce Pind.2 , 0 , Setuphms , Sub
Debounce Pind.3 , 0 , Incrhms , Sub
Waitms 20
Wend
Return
'------Incrhms:
Bitwait Pind.3 , Reset
Select Case I
Case 0:
Locate 2 , 1 :
If G < 23 Then
Case 1:
Locate 2 , 1 :
If H < 59 Then
Case 2:
Locate 2 , 1 :
If J < 59 Then
End Select
Lcd "Stunde" ; Spc(10)
Incr G Else G = 0
Lcd "Minute" ; Spc(10)
Incr H Else H = 0
Lcd "Sekunde" ; Spc(9)
Incr J Else J = 0
Return
'-------Setuphms:
Bitwait Pind.2 , Reset
If I > 1 Then
I = 0
_hour = G : _min = H : _sec = J
Call Settime
Call Gotomain
Exitbyte = 2
Else
Incr I
End If
Return
'#####################################################
'# ENDE Datum & Uhrzeit einstellen
#
'#####################################################
- 47 -
'#####################################################################
'# DS1307 Datum, Uhrzeit & Einstellungen auslesen und schreiben
#
'#####################################################################
Getdatetime:
I2cstart
I2cwbyte Ds1307w
I2cwbyte 0
I2cstart
I2cwbyte Ds1307r
I2crbyte _sec , Ack
I2crbyte _min , Ack
I2crbyte _hour , Ack
I2crbyte Weekday , Ack
I2crbyte _day , Ack
I2crbyte _month , Ack
I2crbyte _year , Nack
I2cstop
_sec = Makedec(_sec) : _min = Makedec(_min) : _hour = Makedec(_hour)
_day = Makedec(_day) : _month = Makedec(_month) : _year = Makedec(_year)
Return
Setdate:
_day = Makebcd(_day) : _month = Makebcd(_month) : _year = Makebcd(_year)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 4
I2cwbyte _day
I2cwbyte _month
I2cwbyte _year
I2cstop
Waitms 10
Return
Setweekday:
I2cstart
I2cwbyte Ds1307w
I2cwbyte 3
I2cwbyte Weekday
I2cstop
Waitms 10
Return
Settime:
_sec = Makebcd(_sec) : _min = Makebcd(_min) : _hour = Makebcd(_hour)
I2cstart
I2cwbyte Ds1307w
I2cwbyte 0
I2cwbyte _sec
I2cwbyte _min
I2cwbyte _hour
I2cstop
Waitms 10
Return
Delnvram:
For K = 8 To 63
I2cstart
I2cwbyte Ds1307w
I2cwbyte K
I2cwbyte 00
I2cwbyte 00
I2cstop
Waitms 10
Next
Return
Writenvram:
I2cstart
I2cwbyte Ds1307w
I2cwbyte 8
I2cwbyte Stset
I2cwbyte Wtset
I2cstop
Waitms 10
Return
- 48 -
Writenvram_sett:
I2cstart
I2cwbyte Ds1307w
I2cwbyte 10
I2cwbyte Z(7)
I2cwbyte 0
I2cwbyte Z(8)
I2cwbyte 0
I2cwbyte Z(9)
I2cwbyte Z(10)
I2cwbyte 0
I2cwbyte Systemtagby(1)
I2cwbyte Systemtagby(2)
I2cwbyte Systemtagby(3)
I2cwbyte Systemtagby(4)
I2cwbyte Sekdestagesby(1)
I2cwbyte Sekdestagesby(2)
I2cwbyte Sekdestagesby(3)
I2cwbyte Sekdestagesby(4)
I2cstop
Waitms 10
Return
Readnvram:
I2cstart
I2cwbyte
I2cwbyte
I2cstart
I2cwbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2crbyte
I2cstop
Return
Ds1307w
8
Ds1307r
Stset , Ack
Wtset , Ack
Lcd_blby(1) , Ack
Lcd_blby(2) , Ack
Plusminby(1) , Ack
Plusminby(2) , Ack
Sekundeby(1) , Ack
Sekundeby(2) , Ack
Sekundeby(3) , Ack
Systemtagby(1) , Ack
Systemtagby(2) , Ack
Systemtagby(3) , Ack
Systemtagby(4) , Ack
Sekdestagesby(1) , Ack
Sekdestagesby(2) , Ack
Sekdestagesby(3) , Ack
Sekdestagesby(4) , Nack
'#####################################################################
'# Ende DS1307 Datum, Uhrzeit & Einstellungen auslesen und schreiben #
'#####################################################################
'#####################################################################
'# I2C EEPROM Sonnenauf/-untergangsdaten lesen und schreiben
#
'#####################################################################
Eepromwsonne:
N = 0
For X = 7 To 20
Adresse_sonne_high = High(adresse_sonne)
Adresse_sonne_low = Low(adresse_sonne)
I2cstart
I2cwbyte
I2cwbyte
I2cwbyte
I2cwbyte
I2cstop
Eeprw
Adresse_sonne_high
Adresse_sonne_low
Z(x)
Waitms 10
Incr Adresse_sonne
- 49 -
Next
If Adresse_sonne > 1399 Then Adresse_sonne = 0
Return
'-----------------Function Eepromrsonne(adresse_sonne As Word) As String * 14
For X = 1 To 14
Adresse_sonne_high = High(adresse_sonne)
Adresse_sonne_low = Low(adresse_sonne)
I2cstart
I2cwbyte Eeprw
I2cwbyte Adresse_sonne_high
I2cwbyte Adresse_sonne_low
I2cstart
I2cwbyte Eeprr
I2crbyte Sonnetagby(x) , Nack
I2cstop
Incr Adresse_sonne
Next
Stageeprom = Sonnetagst
Stageepromday = Left(stageeprom , 4)
If Stset = 1 And Wtset = 0 Then
Sahst = Mid(stageeprom , 5 , 2)
Sarest = Mid(stageeprom , 7 , 3)
Suhst = Mid(stageeprom , 10 , 2)
Surest = Mid(stageeprom , 12 , 3)
Sahstn = Val(sahst)
Incr Sahstn
Sahst = Str(sahstn)
Sahst = Format(sahst , "00")
Suhstn = Val(suhst)
Incr Suhstn
Suhst = Str(suhstn)
Suhst = Format(suhst , "00")
Stageeprom = Stageepromday + Sahst + Sarest + Suhst + Surest
End If
Eepromrsonne = Stageeprom
End Function
'#####################################################################
'# ENDE I2C EEPROM Sonnenauf/-untergangsdaten lesen und schreiben
#
'#####################################################################
'#####################################################################
'# I2C EEPROM Termine lesen und schreiben
#
'#####################################################################
Eepromwtermine:
N = 0
For X = 5 To 31
Adresse_termine14k = 1400 + Adresse_terminw
Adresse_termine_high14k = High(adresse_termine14k)
- 50 -
Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart
I2cwbyte
I2cwbyte
I2cwbyte
I2cwbyte
I2cstop
Eeprw
Adresse_termine_high14k
Adresse_termine_low14k
Z(x)
Waitms 10
Incr Adresse_terminw
Next
Return
'-----------------Function Getterminadresse(heute As Integer) As Word
Maxadressew = Getmaxadressetermine(0)
For Adresse_termine = 0 To Maxadressew Step 27
Terminedate = Gettermintag(adresse_termine)
If Terminedate = Heute Then Alarm_heute = 1 Else Alarm_heute = 0
If Terminedate >= Heute Then Exit For
Next
Getterminadresse = Adresse_termine
End Function
'-----------------Function Gettermintag(adresse_termine As Word) As Integer
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine
Adresse_termine_high14k = High(adresse_termine14k)
Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart
I2cwbyte Eeprw
I2cwbyte Adresse_termine_high14k
I2cwbyte Adresse_termine_low14k
I2cstart
I2cwbyte Eeprr
I2crbyte Termineby(x) , Nack
I2cstop
Incr Adresse_termine
Next
Termine_t = Left(terminest , 2)
Termine_m = Mid(terminest , 3 , 2)
Termine_j = Mid(terminest , 7 , 2)
Termine_jv = Mid(terminest , 5 , 4)
Terminedatest = Termine_t + "." + Termine_m + "." + Termine_j
Terminedate = Dayofyear(terminedatest)
Termine_ij = Val(termine_j)
Schaltjahr = Termine_ij Mod 4
If Schaltjahr = 0 And Terminedate > 59 Then
Decr Terminedate
End If
'Schaltjahr
Gettermintag = Terminedate
End Function
- 51 -
'------------------Function Eepromrtermine(adresse_termine As Word) As String * 16
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine
Adresse_termine_high14k = High(adresse_termine14k)
Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart
I2cwbyte Eeprw
I2cwbyte Adresse_termine_high14k
I2cwbyte Adresse_termine_low14k
I2cstart
I2cwbyte Eeprr
I2crbyte Termineby(x) , Nack
I2cstop
Incr Adresse_termine
Next
Termine_t = Left(terminest , 2)
Termine_m = Mid(terminest , 3 , 2)
Termine_p = Mid(terminest , 16 , 10)
Terminelcdst = Termine_t + "." + Termine_m + " " + Termine_p
If Termine_t = "00" Then Terminelcdst = Space(16)
Eepromrtermine = Terminelcdst
End Function
'-----------------Function Getmaxadressetermine(adresse_termine As Word) As Word
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine
Adresse_termine_high14k = High(adresse_termine14k)
Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart
I2cwbyte Eeprw
I2cwbyte Adresse_termine_high14k
I2cwbyte Adresse_termine_low14k
I2cstart
I2cwbyte Eeprr
I2crbyte Termineby(x) , Nack
I2cstop
Incr Adresse_termine
Next
Maxadressest = Mid(terminest , 26 , 2)
Maxadressew = Val(maxadressest)
Maxadressew = Maxadressew * 27
Getmaxadressetermine = Maxadressew
End Function
'--------------------------Function Eepromrtermine_alarm(adresse_termine As Word) As Long
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine
- 52 -
Adresse_termine_high14k = High(adresse_termine14k)
Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart
I2cwbyte Eeprw
I2cwbyte Adresse_termine_high14k
I2cwbyte Adresse_termine_low14k
I2cstart
I2cwbyte Eeprr
I2crbyte Termineby(x) , Nack
I2cstop
Incr Adresse_termine
Next
Termine_sek = Mid(terminest , 9 , 5)
Termine_mu = Mid(terminest , 15 , 1)
Termine_geburtstag = Mid(terminest , 14 , 1)
'Musik abspielen?
'Geburtstag oder Feiertag
Termine_alarml = Val(termine_sek)
Eepromrtermine_alarm = Termine_alarml
End Function
'#####################################################################
'# ENDE I2C EEPROM Termine lesen und schreiben
#
'#####################################################################
'------------------Toggle_colon:
Timer1 = 7936
Toggle Colon_onoff
If All_off = 1 Then Colon_onoff = 0
Return
'-----------------Button1:
Bitwait Pind.2 , Reset
If Cntb1 = 3 Then Cntb1 = 0 Else Incr Cntb1
Cls
Return
'-----------------Button2:
Bitwait Pind.3 , Reset
If Cntb2 = 2 Then Cntb2 = 0 Else Incr Cntb2
Return
'---------Gotomain:
Bitwait Pind.2 , Reset
Cntb1 = 0
Cls
Return
'#####################################################
'# LCD BL an/aus
#
'#####################################################
Lcd_blonoff:
Licht = Getadc(2)
If Lcd_blst = "1" Then
Lcd_bl = 1
Elseif Lcd_blst = "3" And Licht < 120 And _hour > 6 Then
Lcd_bl = 1
Else
Lcd_bl = 0
End If
- 53 -
Return
'#####################################################
'# ENDE LCD BL an/aus
#
'#####################################################
'#####################################################
'# Sommer-/Winterzeit einstellen
#
'#####################################################
Dst_onoff:
If _month = 3 And _day > 24 And Weekday = 7 And _hour = 2 Then
_hour = _hour + 1
Waitms 10
Call Settime
Stset = 1
Wtset = 0
Waitms 10
Call Writenvram
End If
If Wtset = 0 And _month = 10 And _day > 24 And Weekday = 7 And _hour = 3 Then
_hour = _hour - 1
Waitms 10
Call Settime
Wtset = 1
Stset = 0
Waitms 10
Call Writenvram
End If
Return
'#####################################################
'# Ende Sommer-/Winterzeit einstellen
#
'#####################################################
'#####################################################
'# Zeitkorrektur
#
'#####################################################
Zeitkorrektur:
Call Readnvram
Sysd = Sysday()
Secd = Secofday()
Sekundelong = Val(sekundest)
If Secd = 86399 Then Zeitkorrekturbit = 0
If Plusminst = "0" Then Korrektur = Sekdestages + Sekundelong
If Plusminst = "1" Then Korrektur = Sekdestages - Sekundelong
If Sysd <> Systemtag And Secd = Sekdestages And Sekundelong <> 0 And Zeitkorrekturbit = 0 Then
Time$ = Time(korrektur)
Zeitkorrekturbit = 1
End If
Return
'#####################################################
'# Ende Zeitkorrektur
#
'#####################################################
'#####################################################
'# Musik abspielen
#
'#####################################################
Sub Play_music(song_nr As String * 1)
If Lcd_bl = 0 Then Lcd_bl = 1
Select Case Song_nr
Case "1"
For I = 0 To 55
Note = Lookup(i , Happyb)
- 54 -
Incr I
If Note = 0 Then
Pause = Lookup(i , Happyb)
Waitms Pause
Else
Laenge = Lookup(i , Happyb)
Sound Speaker , Note , Laenge
End If
Next I
Case "2"
For I = 0 To 57
Note = Lookup(i , Merryx)
Incr I
If Note = 0 Then
Pause = Lookup(i , Merryx)
Waitms Pause
Else
Laenge = Lookup(i , Merryx)
Sound Speaker , Note , Laenge
End If
Next I
End Select
End Sub
'#####################################################
'# Ende Musik abspielen
#
'#####################################################
End
Weekdays:
Data "dummy" , "Montag" , "Dienstag" , "Mittwoch" , "Donnerstag" , "Freitag" , "Samstag" , "Sonntag"
Happyb:
Data 65% , 587% , 65% , 587% , 147% , 523% , 131% , 587% , 175%
Data 440% , 165% , 466% , 0% , 250% , 65% , 587% , 65% , 587% , 147%
Data 523% , 131% , 587% , 196% , 392% , 175% , 440% , 0% , 250% , 65%
Data 587% , 65% , 587% , 262% , 294% , 220% , 349% , 175% , 440% , 165%
Data 466% , 147% , 523% , 0% , 125% , 117% , 330% , 117% , 330% , 220%
Data 349% , 175% , 440% , 196% , 392% , 175% , 440%
Merryx:
Data 147% , 523% , 196% , 392% , 98% , 392% , 110% , 349% , 98% , 392%
Data 92% , 415% , 165% , 466% , 131% , 587% , 165% , 466% , 220% , 349%
Data 110% , 349% , 124% , 311% , 110% , 349% , 98% , 392% , 185% , 415%
Data 294% , 523% , 247% , 311% , 124% , 311% , 131% , 294% , 124% , 311%
Data 110% , 349% , 196% , 392% , 165% , 466% , 73% , 523% , 73% , 523%
Data 165% , 466% , 220% , 349% , 185% , 415% , 196% , 392%
- 55 -
AutoIt-Quellcode
;-----------------------------------------------------------------------------------------; Tool fuer die Geburtstagskalenderuhr
; Benutzt CommMG.au3 V2.8 von Martin Gibson
; http://www.autoitscript.com/forum/topic/45842-serial-port-com-port-udf/
; http://www.mosaiccgl.co.uk/AutoItDownloads/confirm.php?get=COMMGv2.zip
;
; Berechnung der Zeiten für Sonnenauf bzw. -untergang aus dem AutoIt Skript
; IsItDark von JustinTime
; http://www.autoitscript.com/forum/topic/20946-script-to-determine-sunrisesunset-times-etc/
;
; Berechnung des Osterdatums nach der Formel von Lichtenberg
; http://de.wikipedia.org/wiki/Gau%C3%9Fsche_Osterformel
;------------------------------------------------------------------------------------------#include <ButtonConstants.au3>
#include <ComboConstants.au3>
#include <DateTimeConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <CommMG.au3>;or if you save the commMg.dll in the @scripdir use #include @SciptDir &
'\commmg.dll'
#Include <GuiListBox.au3>
#include <File.au3>
#include <GuiListView.au3>
#Include <Date.au3>
Const $longitude = 9.935556 ; Goettingen
Const $latitude = 51.533889 ; Goettingen
Const $TZ = 1 ;Zeitzone
Const $pi = 3.1415926535897932384626433832795
Const $isdst=0
$RADEG=180/$pi
$DEGRAD=$pi/180
$MyDocsFolder = "::{450D8FBA-AD25-11D0-98A8-0800361B1103}"
Local $avArray[8]
$avArray[0] = "Dummy"
$avArray[1] = "Sonntag"
$avArray[2] = "Montag"
$avArray[3] = "Dienstag"
$avArray[4] = "Mittwoch"
$avArray[5] = "Donnerstag"
$avArray[6] = "Freitag"
$avArray[7] = "Samstag"
$time = @HOUR & ":" & @MIN & ":" & @SEC
$date1 = @YEAR & "/" & @MON & "/" & @MDAY
$date = @MDAY & "." & @MON & "." & stringmid(@YEAR,3,2)
#Region ### START Koda GUI section ### Form=
$Form1_1 = GUICreate("Tool", 629, 515, 138, 42)
$Tab1 = GUICtrlCreateTab(24, 24, 585, 465)
$TabSheet1 = GUICtrlCreateTabItem("Einstellungen")
$Combo1 = GUICtrlCreateCombo("COM1", 64, 110, 81, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))
GUICtrlSetData(-1, "COM2|COM3|COM4|COM5|COM6|COM7|COM8|COM9|COM10|COM11|COM12")
$TimeInp = GUICtrlCreateDate($time, 184, 174, 94, 21, BitOR($DTS_UPDOWN,$DTS_TIMEFORMAT))
$DateInp = GUICtrlCreateDate($date, 64, 174, 94, 21, BitOR($DTS_SHORTDATEFORMAT,$DTS_UPDOWN))
$Sommerzeit = GUICtrlCreateCheckbox("Sommerzeit", 472, 166, 97, 25)
GUICtrlSetState(-1, $GUI_CHECKED)
$Sysdate = GUICtrlCreateCheckbox("Systemdatum", 472, 198, 97, 25)
GUICtrlSetState(-1, $GUI_CHECKED)
$Systime = GUICtrlCreateCheckbox("Systemzeit", 472, 230, 97, 25)
GUICtrlSetState(-1, $GUI_CHECKED)
$Label1 = GUICtrlCreateLabel("COM-Port", 160, 110, 50, 17)
$Sendtime = GUICtrlCreateButton("Datum / Zeit senden", 64, 222, 121, 41)
$Sendtest = GUICtrlCreateButton("Test", 264, 102, 65, 33)
$Input2 = GUICtrlCreateInput("", 344, 110, 208, 22, BitOR($GUI_SS_DEFAULT_INPUT,$ES_READONLY))
- 56 -
$Weekday = GUICtrlCreateCombo($avArray[@WDAY], 296, 174, 88, 25, BitOR($CBS_DROPDOWN,
$CBS_AUTOHSCROLL))
GUICtrlSetData(-1, "Sonntag|Montag|Dienstag|Mittwoch|Donnerstag|Freitag|Samstag")
$Input4 = GUICtrlCreateInput("", 208, 230, 208, 22, BitOR($GUI_SS_DEFAULT_INPUT,$ES_READONLY))
;#####
$Group1 = GUICtrlCreateGroup("LCD-Hintergrundbeleuchtung", 64, 289, 201, 57)
$An = GUICtrlCreateRadio("An", 80, 313, 57, 17)
GUICtrlSetState(-1, $GUI_CHECKED)
$Aus = GUICtrlCreateRadio("Aus", 144, 313, 57, 17)
$Auto = GUICtrlCreateRadio("Auto", 208, 313, 49, 17)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Group2 = GUICtrlCreateGroup("Korrektur", 312, 289, 225, 57)
$plus = GUICtrlCreateRadio("+", 328, 313, 25, 18)
GUICtrlSetState(-1, $GUI_CHECKED)
$minus = GUICtrlCreateRadio("-", 368, 313, 25, 18)
$Sekunden = GUICtrlCreateCombo("00", 402, 313, 51, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))
GUICtrlSetData(-1, "01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|
27|28|29|30")
$Label3 = GUICtrlCreateLabel("s in 24 h", 467, 313, 54, 18)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Sendsettings = GUICtrlCreateButton("Einstellungen senden", 64, 360, 121, 41, $BS_MULTILINE)
$Input5 = GUICtrlCreateInput("", 210, 372, 208, 22, BitOR($GUI_SS_DEFAULT_INPUT,$ES_READONLY))
$Sonnebutton = GUICtrlCreateButton(" Zeiten für Sonnenauf-/untergänge der nächsten 100 Tage senden
", 63, 420, 233, 41, $BS_MULTILINE)
$ProgressSonne = GUICtrlCreateProgress(320, 424, 241, 33)
$TabSheet2 = GUICtrlCreateTabItem("Geburtstage und Feiertage")
$TDate = GUICtrlCreateDate($Date, 40, 72, 81, 22, 0)
$Ttime = GUICtrlCreateDate($Time, 136, 72, 73, 22, BitOR($DTS_UPDOWN,$DTS_TIMEFORMAT))
$TWh = GUICtrlCreateCombo("Geburtstag", 224, 72, 76, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))
GUICtrlSetData(-1, "Feiertag")
$TSound = GUICtrlCreateCombo("Keine Melodie", 312, 72, 105, 25, BitOR($CBS_DROPDOWN,
$CBS_AUTOHSCROLL))
GUICtrlSetData(-1, "Melodie 1|Melodie 2")
$TInpEreig = GUICtrlCreateInput("Klaus", 432, 72, 113, 22)
GUICtrlSetLimit(-1, 10)
$Tadd = GUICtrlCreateButton("+", 560, 72, 25, 25)
$TChange = GUICtrlCreateButton("Eintrag ändern", 432, 136, 113, 25)
$TDel = GUICtrlCreateButton("Eintrag löschen", 432, 178, 113, 25)
$TDelAll = GUICtrlCreateButton("Alle löschen", 432, 218, 113, 25)
$TFeiertag = GUICtrlCreateButton("Feiertage hinzufügen", 432, 256, 113, 25)
$Input3 = GUICtrlCreateInput("", 264, 449, 209, 22, BitOR($GUI_SS_DEFAULT_INPUT,$ES_READONLY))
$TList = GUICtrlCreateListView("Datum|Uhrzeit|Anlass|Melodie|Text|#", 40, 121, 377, 314)
GUICtrlSendMsg(-1,
GUICtrlSendMsg(-1,
GUICtrlSendMsg(-1,
GUICtrlSendMsg(-1,
GUICtrlSendMsg(-1,
GUICtrlSendMsg(-1,
$LVM_SETCOLUMNWIDTH,
$LVM_SETCOLUMNWIDTH,
$LVM_SETCOLUMNWIDTH,
$LVM_SETCOLUMNWIDTH,
$LVM_SETCOLUMNWIDTH,
$LVM_SETCOLUMNWIDTH,
0,
1,
2,
3,
4,
5,
70)
70)
60)
60)
90)
0)
$TSave = GUICtrlCreateButton("Speichern", 40, 448, 65, 25)
$TLoad = GUICtrlCreateButton("Laden", 112, 448, 65, 25)
$TSend = GUICtrlCreateButton("Senden", 184, 448, 65, 25)
$TProgress = GUICtrlCreateProgress(480, 448, 113, 22)
$TabSheet3 = GUICtrlCreateTabItem("Melodiegenerator")
$MelodieName = GUICtrlCreateInput("Melodie", 52, 64, 169, 22)
$Eingabe = GUICtrlCreateEdit("", 52, 97, 521, 137)
$Ausgabe = GUICtrlCreateEdit("", 52, 309, 521, 161, BitOR($GUI_SS_DEFAULT_EDIT,$ES_READONLY)) ;
$Generate = GUICtrlCreateButton("Code generieren", 200, 248, 217, 41)
$DelAll = GUICtrlCreateButton("Alles löschen", 445, 248, 113, 41)
GUICtrlCreateTabItem("")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
GUICtrlSetState($Systime, $GUI_CHECKED)
GUICtrlSetState($Sysdate, $GUI_CHECKED)
- 57 -
While 1
Local $sportSetError
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $Sommerzeit
Case $Sysdate
Case $Systime
Case $combo1
$setport = StringReplace(GUICtrlRead($Combo1), 'COM', '')
_CommSetPort($setport, $sportSetError, 9600, 8, 0, 1, 0)
if $sportSetError = '' Then
MsgBox(262144, 'Verbunden','Verbunden mit COM' & $setport)
Else
MsgBox(262144, 'Verbindungsfehler', $sportSetError)
EndIf
$mode = 1
Case $Sendtest
sleep (1000)
GUICtrlSetData($input2, "")
_CommSendString("TEST: Gesendet & Empfangen 1234")
sleep (1000)
$instr = _CommGetString()
if $instr <> "" then
GUICtrlSetData($input2, $instr)
else
GUICtrlSetData($input2, "Falscher Port oder Fehler")
endif
Case $Sendtime
$a=GUICtrlRead($Sommerzeit)
$b=GUICtrlRead($Sysdate)
$c=GUICtrlRead($Systime)
if $a=1 then
$wt=0
$st=1
elseif $a <> 1 then
$wt=1
$st=0
endif
if $b=1 then
$day=@MDAY
$month=@MON
$year2=stringmid(@YEAR,3,4)
$date=$day & "." & $month & "." & $year2 & weekday2number($avArray[@WDAY])
else
$date=stringmid(GUICtrlRead($DateInp),1,6) & stringmid(GUICtrlRead($DateInp),9,2) &
weekday2number(GUICtrlRead($Weekday))
EndIf
if $c=1 then
$time=@HOUR &":"& @MIN &":"& @SEC
else
$time=GUICtrlRead($TimeInp)
EndIf
$Sendstr="TIME :" & $date &
_CommSendString($Sendstr)
sleep (1000)
$instr = _CommGetString()
if $instr <> "" then
GUICtrlSetData($input4,
else
GUICtrlSetData($input4,
GUICtrlSetData($input4,
endif
$wt & $st & $time & "xxxxxx"
$instr)
"")
$sendstr)
Case $Sendsettings
if GUICtrlRead($an)=1 then $LCD=1
- 58 -
if
if
if
if
if
GUICtrlRead($aus)=1 then $LCD=2
GUICtrlRead($auto)=1 then $LCD=3
GUICtrlRead($plus)=1 then $plusminus=0
GUICtrlRead($minus)=1 then $plusminus=1
Number(GUICtrlRead($Sekunden)) < 10 then
$null=0
else
$null = ""
EndIf
$Sendstrsett = "SETT: " & $LCD & $plusminus & GUICtrlRead($Sekunden) &
"00000000000000000000x"
_CommSendString($Sendstrsett)
sleep (1000)
GUICtrlSetData($input5,$Sendstrsett)
Case $Sonnebutton
$b=GUICtrlRead($Sysdate)
if $b=1 then
$day = ( 367 * (@YEAR) - int((7 * ((@YEAR) + (((@MON) + 9) / 12))) / 4) + int((275 *
(@MON)) / 9) + (@MDAY) - 730530)
else
$Jahr=stringmid(GUICtrlRead($DateInp),7,4)
$Monat=stringmid(GUICtrlRead($DateInp),4,2)
$MTag=stringmid(GUICtrlRead($DateInp),1,2)
$day = ( 367 * ($Jahr) - int((7 * (($Jahr) + ((($Monat) + 9) / 12))) / 4) + int((275
* ($Monat)) / 9) + ($MTag) - 730530)
EndIf
For $Iday =0 to 99
$nday=$day+$Iday
$SunTimes=SunTimes($nday,0)
$Sendstrsonne="SUNS: " & $nday-1 & $SunTimes & "0000000000x"
_CommSendString($Sendstrsonne)
GUICtrlSetData($input5,$Sendstrsonne)
GUICtrlSetData($ProgressSonne, $Iday+1)
sleep(500)
Next
Case $Tadd
_GUICtrlListView_RegisterSortCallBack($TList)
$TerminT=StringLeft(GUICtrlRead($Tdate),2)
$TerminM=StringMid(GUICtrlRead($Tdate),4,2)
$TerminDatum = $TerminM & $TerminT
GUICtrlCreateListViewItem(GUICtrlRead($Tdate) & "|" & GUICtrlRead($Ttime) & "|" &
GUICtrlRead($Twh) & "|" & GUICtrlRead($TSound) & "|" & StringFormat("%-10s",GUICtrlRead($TInpEreig))
&"|" & $TerminDatum, $TList)
_GUICtrlListView_SortItems($TList,5)
_GUICtrlListView_UnRegisterSortCallBack ($TList)
Case $TChange
$line =
_GUICtrlListView_GetItemTextString($TList,Number(_GUICtrlListView_GetSelectedIndices($TList)))
$linesplit = StringSplit($line,"|")
$date_tchange=StringMid($linesplit[1],7,4) & "/" & StringMid($linesplit[1],4,2) & "/" &
StringMid($linesplit[1],1,2)
GUICtrlSetData($Tdate,$date_tchange)
GUICtrlSetData($Ttime,$date_tchange & " " & $linesplit[2])
GUICtrlSetData($Twh, $linesplit[3])
GUICtrlSetData($Tsound, $linesplit[4])
GUICtrlSetData($TInpEreig, $linesplit[5])
_GUICtrlListView_DeleteItem($TList,Number(_GUICtrlListView_GetSelectedIndices($TList)))
Case $Tdel
_GUICtrlListView_DeleteItemsSelected($TList)
Case $TDelall
_GUICtrlListView_DeleteAllItems($TList)
Case $TFeiertag
_GUICtrlListView_RegisterSortCallBack($TList)
GUICtrlCreateListViewItem("01.01." & @YEAR & "|" & "00:00:01"
& "Keine Melodie" & "|" & "Neujahr
" & "|" & "0101", $TList)
- 59 -
& "|" & "Feiertag"
& "|"
GUICtrlCreateListViewItem("01.05."
& "Keine Melodie" & "|" & "1. Mai
" & "|"
GUICtrlCreateListViewItem("08.05."
& "Keine Melodie" & "|" & "Muttertag " & "|"
GUICtrlCreateListViewItem("03.10."
& "Keine Melodie" & "|" & "D. Einheit" & "|"
GUICtrlCreateListViewItem("24.12."
& "Keine Melodie" & "|" & "Heiligab. " & "|"
GUICtrlCreateListViewItem("25.12."
& "Keine Melodie" & "|" & "1. Weihft." & "|"
GUICtrlCreateListViewItem("26.12."
& "Keine Melodie" & "|" & "2. Weihft." & "|"
GUICtrlCreateListViewItem("31.12."
& "Keine Melodie" & "|" & "Silvester " & "|"
&
&
&
&
&
&
&
&
&
&
&
&
&
&
@YEAR &
"0501",
@YEAR &
"0508",
@YEAR &
"1003",
@YEAR &
"1224",
@YEAR &
"1225",
@YEAR &
"1226",
@YEAR &
"1231",
"|" & "12:00:00"
$TList)
"|" & "12:00:00"
$TList)
"|" & "12:00:00"
$TList)
"|" & "12:00:00"
$TList)
"|" & "12:00:00"
$TList)
"|" & "12:00:00"
$TList)
"|" & "12:00:00"
$TList)
& "|" & "Feiertag"
& "|"
& "|" & "Feiertag"
& "|"
& "|" & "Feiertag"
& "|"
& "|" & "Feiertag"
& "|"
& "|" & "Feiertag"
& "|"
& "|" & "Feiertag"
& "|"
& "|" & "Feiertag"
& "|"
$Osterdatum=Ostern(@YEAR)
$OsternT=StringLeft($Osterdatum,2)
$OsternM=StringMid($Osterdatum,4,2)
$OsternMT=$OsternM & $OsternT
If (@MON & @MDAY) >
$OsternMT then
$Osterdatum=Ostern(@YEAR+1)
$OsternT=StringLeft($Osterdatum,2)
$OsternM=StringMid($Osterdatum,4,2)
$OsternY=StringMid($Osterdatum,7,4)
$OsternMT=$OsternM & $OsternT
GUICtrlCreateListViewItem($Osterdatum & "|" & "12:00:00"
"Keine Melodie" & "|" & "Ostersonn." & "|" &$OsternMT, $TList)
& "|" & "Feiertag"
& "|" &
Dim $KarfreitagY, $KarfreitagM, $KarfreitagT
$Karfreitag= _DateToDayValue ($OsternY, $OsternM, $OsternT) -2
$Karfreitag= _DayValueToDate ($Karfreitag, $KarfreitagY, $KarfreitagM, $KarfreitagT)
$Karfreitag = $KarfreitagT & "." & $KarfreitagM & "." & $KarfreitagY
$KarfreitagMT = $KarfreitagM & $KarfreitagT
GUICtrlCreateListViewItem($Karfreitag & "|" & "12:00:00" & "|" & "Feiertag"
"Keine Melodie" & "|" & "Karfreitag" & "|" & $KarfreitagMT, $TList)
& "|" &
Dim $OstermontagY, $OstermontagM, $OstermontagT
$Ostermontag = _DateToDayValue ($OsternY, $OsternM, $OsternT) + 1
$Ostermontag = _DayValueToDate ($Ostermontag, $OstermontagY, $OstermontagM,
$OstermontagT)
$Ostermontag = $OstermontagT & "." & $OstermontagM & "." & $OstermontagY
$OstermontagMT = $OstermontagM & $OstermontagT
GUICtrlCreateListViewItem($Ostermontag & "|" & "12:00:00"
"Keine Melodie" & "|" & "Ostermon. " & "|" &$OstermontagMT, $TList)
& "|" & "Feiertag"
& "|" &
Dim $HimmelfahrtY, $HimmelfahrtM, $HimmelfahrtT
$Himmelfahrt= _DateToDayValue ($OsternY, $OsternM, $OsternT) + 39
$Himmelfahrt= _DayValueToDate ($Himmelfahrt, $HimmelfahrtY, $HimmelfahrtM, $HimmelfahrtT)
$Himmelfahrt = $HimmelfahrtT & "." & $HimmelfahrtM & "." & $HimmelfahrtY
$HimmelfahrtMT = $HimmelfahrtM & $HimmelfahrtT
GUICtrlCreateListViewItem($Himmelfahrt & "|" & "12:00:00" & "|" & "Feiertag"
"Keine Melodie" & "|" & "Vatertag " & "|" & $HimmelfahrtMT, $TList)
& "|" &
Dim $PfingstsonntagY, $PfingstsonntagM, $PfingstsonntagT
$Pfingstsonntag= _DateToDayValue ($OsternY, $OsternM, $OsternT) + 49
$Pfingstsonntag= _DayValueToDate ($Pfingstsonntag, $PfingstsonntagY, $PfingstsonntagM,
$PfingstsonntagT)
$Pfingstsonntag = $PfingstsonntagT & "." & $PfingstsonntagM & "." & $PfingstsonntagY
$PfingstsonntagMT = $PfingstsonntagM & $PfingstsonntagT
GUICtrlCreateListViewItem($Pfingstsonntag & "|" & "12:00:00" & "|" & "Feiertag"
"Keine Melodie" & "|" & "Pfingstso." & "|" & $PfingstsonntagMT, $TList)
Dim $PfingstmontagY, $PfingstmontagM, $PfingstmontagT
- 60 -
& "|" &
$Pfingstmontag = _DateToDayValue ($OsternY, $OsternM, $OsternT) + 50
$Pfingstmontag = _DayValueToDate ($Pfingstmontag, $PfingstmontagY, $PfingstmontagM,
$PfingstmontagT)
$Pfingstmontag = $PfingstmontagT & "." & $PfingstmontagM & "." & $PfingstmontagY
$PfingstmontagMT = $PfingstmontagM & $PfingstmontagT
GUICtrlCreateListViewItem($Pfingstmontag & "|" & "12:00:00" & "|" & "Feiertag"
"Keine Melodie" & "|" & "Pfingstmo." & "|" & $PfingstmontagMT, $TList)
& "|" &
_GUICtrlListView_SortItems($TList,5)
_GUICtrlListView_UnRegisterSortCallBack ($TList)
Case $TSave
$TerminFile=FileSaveDialog ( "Termine speichern", $MyDocsFolder, "Text (*.txt)" ,
2,"termine.txt" )
Fileopen($TerminFile,2)
For $iIndex = 0 to _GUICtrlListView_GetItemCount($TList)-1
FileWriteLine ($TerminFile, _GUICtrlListView_GetItemTextString($TList, $iIndex))
Next
FileClose($TerminFile)
Case $TLoad
$TerminFile=FileOpenDialog ( "Termine öffnen", $MyDocsFolder, "Text (*.txt)" ,
2,"termine.txt" )
_GUICtrlListView_DeleteAllItems($TList)
$endoffile = _FileCountLines($TerminFile)
Fileopen($TerminFile,0)
For $I = 1 to $endoffile
$line = FileReadLine($TerminFile,$I)
$linesplit=StringSplit($line,"|")
GUICtrlCreateListViewItem($linesplit[1] & "|" & $linesplit[2] & "|" & $linesplit[3] &
"|" & $linesplit[4] & "|" & $linesplit[5] &"|" & $linesplit[6], $TList)
Next
FileClose($TerminFile)
Case $Tsend
_CommSendString("CDATxxxxxxxxxxxxxxxxxxxxxxxxxxx")
Sleep(500)
For $iIndex = 0 to _GUICtrlListView_GetItemCount($TList)-1
$TerminString=_GUICtrlListView_GetItemTextString($TList, $iIndex)
$TerminSec=Secofday(Stringmid($TerminString,12,8))
$TerminSec=StringFormat("%5s",$TerminSec)
$TerminSec=StringReplace($TerminSec," ","0")
$TerminString=StringReplace($TerminString,".","",2)
$TerminString=StringReplace($TerminString,":","",2)
$TerminString=StringReplace($TerminString,"|","")
$TerminString=StringReplace($TerminString,"Geburtstag","G")
$TerminString=StringReplace($TerminString,"Feiertag","F")
$TerminString=StringReplace($TerminString,"Keine Melodie","0")
$TerminString=StringReplace($TerminString,"Melodie ","")
$TerminString="DATE" & StringLeft($TerminString, 8) & $TerminSec &
StringMid($TerminString,15,12)
$TerminString=StringFormat("%-29s",$TerminString)
$TerminString=$TerminString &
StringFormat("%2s",string(_GUICtrlListView_GetItemCount($TList)))
_CommSendString($TErminString)
Sleep(1000)
GUICtrlSetData($Input3,$TerminString)
GUICtrlSetData($TProgress, (100*($iIndex+1))/(_GUICtrlListView_GetItemCount($TList)))
Next
Sleep(1000)
_CommSendString("DATE000000000000000000000000000")
Sleep(1000)
_CommSendString("DATE000000000000000000000000000")
Sleep(1000)
Case $Generate
;http://www.mcselec.com/index.php?option=com_content&task=view&id=221&Itemid=57
;http://www.xs4all.nl/~vbergen/ringtones/siemens/index_2000.html
$AusgabeText=""
- 61 -
GUICtrlSetData($Ausgabe, $AusgabeText="")
Dim $AusgabeText
Dim $Zaehler
Dim $mP
$Zaehler=0
Dim $C1[2][6] = [["C1","C1(1)","C1(1/2)","C1(1/4)","C1(1/8)","C1(1/16)"],
[1174,523,262,131,65,33]]
Dim $Cis1[2][6] = [["Cis1","Cis1(1)","Cis1(1/2)","Cis1(1/4)","Cis1(1/8)","Cis1(1/16)"],
[1108,555,277,139,69,35]]
Dim $D1[2][6] = [["D1","D1(1)","D(1/2)","D(1/4)","D(1/8)","D(1/16)"],
[1046,587,294,147,73,37]]
Dim $Dis1[2][6] = [["Dis1","Dis1(1)","Dis(1/2)","Dis(1/4)","Dis(1/8)","Dis(1/16)"],
[987,622,311,156,78,39]]
Dim $E1[2][6] = [["E1","E1(1)","E1(1/2)","E1(1/4)","E1(1/8)","E1(1/16)"],
[932,659,330,165,82,41]]
Dim $F1[2][6] = [["F1","F1(1)","F1(1/2)","F1(1/4)","F1(1/8)","F1(1/16)"],
[880,698,349,175,87,44]]
Dim $Fis1[2][6] = [["Fis1","Fis1(1)","Fis1(1/2)","Fis1(1/4)","Fis1(1/8)","Fis1(1/16)"],
[830,740,370,185,92,46]]
Dim $G1[2][6] = [["G1","G1(1)","G1(1/2)","G1(1/4)","G1(1/8)","G1(1/16)"],
[784,784,392,196,98,49]]
Dim $Gis1[2][6] = [["Gis1","Gis1(1)","Gis1(1/2)","Gis1(1/4)","Gis1(1/8)","Gis1(1/16)"],
[740,830,415,208,104,52]]
Dim $A1[2][6] = [["A1","A1(1)","A1(1/2)","A1(1/4)","A1(1/8)","A1(1/16)"],
[698,880,440,220,110,55]]
Dim $Ais1[2][6] = [["Ais1","Ais1(1)","Ais1(1/2)","Ais1(1/4)","Ais1(1/8)","Ais1(1/16)"],
[659,932,466,233,117,58]]
Dim $B1[2][6] = [["B1","B1(1)","B1(1/2)","B1(1/4)","B1(1/8)","B1(1/16)"],
[622,988,494,247,124,62]]
Dim $H1[2][6] = [["H1","H1(1)","H1(1/2)","H1(1/4)","H1(1/8)","H1(1/16)"],
[622,988,494,247,124,62]]
Dim $C2[2][6] = [["C2","C2(1)","C2(1/2)","C2(1/4)","C2(1/8)","C2(1/16)"],
[587,1047,523,262,131,65]]
Dim $Cis2[2][6] = [["Cis2","Cis2(1)","Cis2(1/2)","Cis2(1/4)","Cis2(1/8)","Cis2(1/16)"],
[554,1109,554,277,139,69]]
Dim $D2[2][6] = [["D2","D2(1)","D2(1/2)","D2(1/4)","D2(1/8)","D2(1/16)"],
[523,1175,587,294,147,73]]
Dim $Dis2[2][6] = [["Dis2","Dis2(1)","Dis2(1/2)","Dis2(1/4)","Dis2(1/8)","Dis2(1/16)"],
[494,1244,622,311,156,78]]
Dim $E2[2][6] = [["E2","E2(1)","E2(1/2)","E2(1/4)","E2(1/8)","E2(1/16)"],
[466,1318,659,330,165,82]]
Dim $F2[2][6] = [["F2","F2(1)","F2(1/2)","F2(1/4)","F2(1/8)","F2(1/16)"],
[440,1396,698,349,175,87]]
Dim $Fis2[2][6] = [["Fis2","Fis2(1)","Fis2(1/2)","Fis2(1/4)","Fis2(1/8)","Fis2(1/16)"],
[415,1480,740,370,185,92]]
Dim $G2[2][6] = [["G2","G2(1)","G2(1/2)","G2(1/4)","G2(1/8)","G2(1/16)"],
[392,1567,784,392,196,98]]
Dim $Gis2[2][6] = [["Gis2","Gis2(1)","Gis2(1/2)","Gis2(1/4)","Gis2(1/8)","Gis2(1/16)"],
[370,1661,831,415,208,104]]
Dim $A2[2][6] = [["A2","A2(1)","A2(1/2)","A2(1/4)","A2(1/8)","A2(1/16)"],
[349,1760,880,440,220,110]]
Dim $Ais2[2][6] = [["Ais2","Ais2(1)","Ais2(1/2)","Ais2(1/4)","Ais2(1/8)","Ais2(1/16)"],
[330,1862,932,466,233,117]]
Dim $B2[2][6] = [["B2","B2(1)","B2(1/2)","B2(1/4)","B2(1/8)","B2(1/16)"],
[311,1976,988,494,247,124]]
Dim $H2[2][6] = [["H2","H2(1)","H2(1/2)","H2(1/4)","H2(1/8)","H2(1/16)"],
[311,1976,988,494,247,124]]
Dim $C3[2][6] = [["C3","C3(1)","C3(1/2)","C3(1/4)","C3(1/8)","C3(1/16)"],
[294,2090,1047,523,262,131]]
Dim $Cis3[2][6] = [["Cis3","Cis3(1)","Cis3(1/2)","Cis3(1/4)","Cis3(1/8)","Cis3(1/16)"],
[277,2218,1109,554,277,139]]
Dim $D3[2][6] = [["D3","D3(1)","D3(1/2)","D3(1/4)","D3(1/8)","D3(1/16)"],
[262,2345,1175,587,294,147]]
Dim $Dis3[2][6] = [["Dis3","Dis3(1)","Dis3(1/2)","Dis3(1/4)","Dis3(1/8)","Dis3(1/16)"],
[247,2487,1245,622,311,156]]
Dim $E3[2][6] = [["E3","E3(1)","E3(1/2)","E3(1/4)","E3(1/8)","E3(1/16)"],
[233,2637,1319,659,330,165]]
Dim $F3[2][6] = [["F3","F3(1)","F3(1/2)","F3(1/4)","F3(1/8)","F3(1/16)"],
[220,2793,1397,698,349,175]]
Dim $Fis3[2][6] = [["Fis3","Fis3(1)","Fis3(1/2)","Fis3(1/4)","Fis3(1/8)","Fis3(1/16)"],
[208,2954,1480,740,370,185]]
Dim $G3[2][6] = [["G3","G3(1)","G3(1/2)","G3(1/4)","G3(1/8)","G3(1/16)"],
[196,3135,1568,784,392,196]]
Dim $Gis3[2][6] = [["Gis3","Gis3(1)","Gis3(1/2)","Gis3(1/4)","Gis3(1/8)","Gis3(1/16)"],
[185,3321,1661,831,415,208]]
Dim $A3[2][6] = [["A3","A3(1)","A3(1/2)","A3(1/4)","A3(1/8)","A3(1/16)"],
- 62 -
[179,3432,1720,880,440,220]]
Dim $Ais3[2][6] = [["Ais3","Ais3(1)","Ais3(1/2)","Ais3(1/4)","Ais3(1/8)","Ais3(1/16)"],
[165,3724,1865,932,466,233]]
Dim $B3[2][6] = [["B3","B3(1)","B3(1/2)","B3(1/4)","B3(1/8)","B3(1/16)"],
[156,3938,1976,988,494,247]]
Dim $H3[2][6] = [["H3","H3(1)","H3(1/2)","H3(1/4)","H3(1/8)","H3(1/16)"],
[156,3938,1976,988,494,247]]
Dim $P[2][6] = [["P","P(1)","P(1/2)","P(1/4)","P(1/8)","P(1/16)"],
[0,2000,1000,500,250,125]]
$MelodieText=GUICtrlRead($Eingabe)
$MelodieText=StringReplace($MelodieText," ","x")
$MelodieText=StringSplit($MelodieText,"x")
For $m=1 to $MelodieText[0]
$mP=$m+1
For $C= 0 to 5
If $MelodieText[$m] = $C1[0][$C] Then
$AusgabeText=$AusgabeText & $C1[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Cis1[0][$C] Then
$AusgabeText=$AusgabeText & $Cis1[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $D1[0][$C] Then
$AusgabeText=$AusgabeText & $D1[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Dis1[0][$C] Then
$AusgabeText=$AusgabeText & $Dis1[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $E1[0][$C] Then
$AusgabeText=$AusgabeText & $E1[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $F1[0][$C] Then
$AusgabeText=$AusgabeText & $F1[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Fis1[0][$C] Then
$AusgabeText=$AusgabeText & $Fis1[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $G1[0][$C] Then
$AusgabeText=$AusgabeText & $G1[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Gis1[0][$C] Then
$AusgabeText=$AusgabeText & $Gis1[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $A1[0][$C] Then
$AusgabeText=$AusgabeText & $A1[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Ais1[0][$C] Then
$AusgabeText=$AusgabeText & $Ais1[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $B1[0][$C] Then
$AusgabeText=$AusgabeText & $B1[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $H1[0][$C] Then
$AusgabeText=$AusgabeText & $H1[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $C2[0][$C] Then
$AusgabeText=$AusgabeText & $C2[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Cis2[0][$C] Then
$AusgabeText=$AusgabeText & $Cis2[1][$C]
$Zaehler=$Zaehler+1
EndIf
- 63 -
"%, " & $C1[1][0] & "%, "
& "%, " & $Cis1[1][0] & "%, "
"%, " & $D1[1][0] & "%, "
& "%, " & $Dis1[1][0] & "%, "
"%, " & $E1[1][0] & "%, "
"%, " & $F1[1][0] & "%, "
& "%, " & $Fis1[1][0] & "%, "
"%, " & $G1[1][0] & "%, "
& "%, " & $Gis1[1][0] & "%, "
"%, " & $A1[1][0] & "%, "
& "%, " & $Ais1[1][0] & "%, "
"%, " & $B1[1][0] & "%, "
"%, " & $H1[1][0] & "%, "
"%, " & $C2[1][0] & "%, "
& "%, " & $Cis2[1][0] & "%, "
If $MelodieText[$m] = $D2[0][$C] Then
$AusgabeText=$AusgabeText & $D2[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Dis2[0][$C] Then
$AusgabeText=$AusgabeText & $Dis2[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $E2[0][$C] Then
$AusgabeText=$AusgabeText & $E2[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $F2[0][$C] Then
$AusgabeText=$AusgabeText & $F2[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Fis2[0][$C] Then
$AusgabeText=$AusgabeText & $Fis2[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $G2[0][$C] Then
$AusgabeText=$AusgabeText & $G2[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Gis2[0][$C] Then
$AusgabeText=$AusgabeText & $Gis2[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $A2[0][$C] Then
$AusgabeText=$AusgabeText & $A2[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Ais2[0][$C] Then
$AusgabeText=$AusgabeText & $Ais2[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $B2[0][$C] Then
$AusgabeText=$AusgabeText & $B2[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $H2[0][$C] Then
$AusgabeText=$AusgabeText & $H2[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $C3[0][$C] Then
$AusgabeText=$AusgabeText & $C3[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Cis3[0][$C] Then
$AusgabeText=$AusgabeText & $Cis3[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $D3[0][$C] Then
$AusgabeText=$AusgabeText & $D3[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Dis3[0][$C] Then
$AusgabeText=$AusgabeText & $Dis3[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $E3[0][$C] Then
$AusgabeText=$AusgabeText & $E3[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $F3[0][$C] Then
$AusgabeText=$AusgabeText & $F3[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Fis3[0][$C] Then
$AusgabeText=$AusgabeText & $Fis3[1][$C]
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $G3[0][$C] Then
$AusgabeText=$AusgabeText & $G3[1][$C] &
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Gis3[0][$C] Then
- 64 -
"%, " & $D2[1][0] & "%, "
& "%, " & $Dis2[1][0] & "%, "
"%, " & $E2[1][0] & "%, "
"%, " & $F2[1][0] & "%, "
& "%, " & $Fis2[1][0] & "%, "
"%, " & $G2[1][0] & "%, "
& "%, " & $Gis2[1][0] & "%, "
"%, " & $A2[1][0] & "%, "
& "%, " & $Ais2[1][0] & "%, "
"%, " & $B2[1][0] & "%, "
"%, " & $H2[1][0] & "%, "
"%, " & $C3[1][0] & "%, "
& "%, " & $Cis3[1][0] & "%, "
"%, " & $D3[1][0] & "%, "
& "%, " & $Dis3[1][0] & "%, "
"%, " & $E3[1][0] & "%, "
"%, " & $F3[1][0] & "%, "
& "%, " & $Fis3[1][0] & "%, "
"%, " & $G3[1][0] & "%, "
$AusgabeText=$AusgabeText & $Gis3[1][$C] & "%,
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $A3[0][$C] Then
$AusgabeText=$AusgabeText & $A3[1][$C] & "%, "
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $Ais3[0][$C] Then
$AusgabeText=$AusgabeText & $Ais3[1][$C] & "%,
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $B3[0][$C] Then
$AusgabeText=$AusgabeText & $B3[1][$C] & "%, "
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $H3[0][$C] Then
$AusgabeText=$AusgabeText & $H3[1][$C] & "%, "
$Zaehler=$Zaehler+1
EndIf
If $MelodieText[$m] = $P[0][$C] Then
$AusgabeText=$AusgabeText & $P[1][0] & "%, " &
$Zaehler=$Zaehler+1
EndIf
Next
" & $Gis3[1][0] & "%, "
& $A3[1][0] & "%, "
" & $Ais3[1][0] & "%, "
& $B3[1][0] & "%, "
& $H3[1][0] & "%, "
$P[1][$C] & "%, "
Next
$PrgCode = "For I = 0 To " & $Zaehler*2-1 & Chr(13) & Chr(10) & "
Note = Lookup(I, " &
GUICtrlRead($MelodieName) & ")" & Chr(13) & Chr(10)
$PrgCode = $PrgCode & " Incr I" & Chr(13) & Chr(10)
$PrgCode = $PrgCode & " If Note = 0 Then" & Chr(13) & Chr(10) & "
Pause =
Lookup(I ," & GUICtrlRead($MelodieName) & ")" & Chr(13) & Chr(10)
$PrgCode = $PrgCode & "
Waitms Pause" & Chr(13) & Chr(10) & "
Else" & Chr(13) &
Chr(10)
$PrgCode = $PrgCode & "
Laenge = Lookup(I, " & GUICtrlRead($MelodieName) & ")" &
Chr(13) & Chr(10)
$PrgCode = $PrgCode & "
Sound Speaker , Note , Laenge " & Chr(13) & Chr(10) & " End
If" & Chr(13) & Chr(10) & "Next I" & Chr(13) & Chr(10) & Chr(13) & Chr(10)
$PrgCode = $PrgCode & GUICtrlRead($MelodieName) & ":" & Chr(13) & Chr(10) & "Data "
$AusgabeText = StringTrimRight ($AusgabeText,2)
GUICtrlSetData($Ausgabe,$PrgCode & $AusgabeText)
Case $DelAll
$AusgabeText=""
GUICtrlSetData($Ausgabe, "")
GUICtrlSetData($Eingabe, "")
EndSwitch
WEnd
Func weekday2number (ByRef $Weekday)
if $Weekday = "Montag" then $Weekdayn=1
if $Weekday = "Dienstag" then $Weekdayn=2
if $Weekday = "Mittwoch" then $Weekdayn=3
if $Weekday = "Donnerstag" then $Weekdayn=4
if $Weekday = "Freitag" then $Weekdayn=5
if $Weekday = "Samstag" then $Weekdayn=6
if $Weekday = "Sonnabend" then $Weekdayn=6
if $Weekday = "Sonntag" then $Weekdayn=7
Return $Weekdayn
Endfunc
Func SecOfday (ByRef $Ttime)
$SecOfDay=Number(StringLeft($Ttime,2))*60*60+Number(StringMid
($Ttime,4,2))*60+Number(StringMid ($Ttime,7,2))
Return $SecOfDay
EndFunc
Func Ostern (Byref $Jahr)
;Ostern Wikipedia nach Lichtenberg
$K = $Jahr / 100
$M = Int(15 + (3*$K + 3) / 4 - (8*$K + 13) / 25)
$S = Int(2 - (3*$K + 3) / 4)
$A = Mod($Jahr, 19)
$D = Mod((19*$A + $M), 30)
- 65 -
$R = Int(($D + $A / 11) / 29)
$OG = 21 + $D - $R
$SZ = 7 - Mod(Int(($Jahr + $Jahr / 4 + $S)), 7)
$OE = 7 - Mod(($OG - $SZ), 7)
$OS = $OG + $OE
If $OS > 31 then
$OS=$OS -31
$Monat="04"
Else
$Monat="03"
EndIf
$OS=StringFormat("%02s",$OS)
$Osterdatum = $OS &"."& $Monat& "." & $Jahr
Return $Osterdatum
EndFunc
; aus IsItDark von JustinTime
Func SunTimes ($day, $isdst)
Dim $day, $n, $i, $w, $m, $l, $e, $e1, $a, $xv, $yv, $v, $xs, $ys, $xe, $ecl, $lonsun, $ye, $ze,
$ra, $dec, $h, $r, $E1
Dim $GMST0, $UT_Sun_in_south, $LHA, $hour_rise, $hour_set, $min_rise, $min_set
; Orbital elements of the Sun:
$N = 0.0
$i = 0.0
$w = 282.9404 + 0.0000470935 * $day
$a = 1.000000
$e = 0.016709 - 0.000000001151 * $day
$M = 356.0470 + 0.9856002585 * $day
$M = rev($M)
$ecl = 23.4393 - 0.0000003563 * $day
$L = $w + $M
if ($L < 0 OR $L > 360) then
$L = rev($L)
Endif
; position of the Sun
$E1 = $M + $e*(180/$pi) * sind($M) * ( 1.0 + $e * cosd($M) )
$xv = cosd($E1) - $e
$yv = sqrt(1.0 - $e * $e) * sind($E1)
$v = atan2d($yv, $xv)
$r = sqrt($xv * $xv + $yv * $yv)
$lonsun = $v + $w
if ($lonsun < 0 OR $lonsun > 360) then
$lonsun = rev($lonsun)
Endif
$xs = $r * cosd($lonsun)
$ys = $r * sind($lonsun)
$xe = $xs
$ye = $ys * cosd($ecl)
$ze = $ys * sind($ecl)
$RA = atan2d($ye, $xe)
$Dec = atan2d($ze, (sqrt(($xe * $xe)+($ye * $ye))))
$h=-0.833
$GMST0 = $L + 180
if ($GMST0 < 0 OR $GMST0 > 360) then
$GMST0 = rev($GMST0)
Endif
$UT_Sun_in_south = ( $RA - $GMST0 - $longitude ) / 15.0
if ($UT_Sun_in_south < 0) then
$UT_Sun_in_south=$UT_Sun_in_south + 24
Endif
$LHA= (sind($h) - (sind($latitude) * sind($Dec)))/(cosd($latitude) * cosd($Dec))
if ($LHA > -1 AND $LHA < 1) then
$LHA=acosd($LHA)/15
else
$SunTimes = "No sunrise;No sunset"
return $suntimes
- 66 -
Endif
$hour_rise=$UT_Sun_in_south - $LHA
$hour_set=$UT_Sun_in_south + $LHA
$min_rise=int(($hour_rise-int($hour_rise)) * 60)
$min_set=int(($hour_set-int($hour_set)) * 60)
$hour_rise=(int($hour_rise) + ($TZ + $isdst))
$hour_set=(int($hour_set) + ($TZ + $isdst))
if ($min_rise < 10) then
$min_rise = StringRight("0000" & $min_rise, 2)
Endif
if ($min_set < 10) then
$min_set = StringRight("0000" & $min_set, 2)
Endif
;slightly modified the formatting of the following line format from original version.
if $hour_rise < 10 then
$null=0
else
$null = ""
EndIf
$SunTimes = $null & $hour_rise & ":" & $min_rise & $hour_set & ":" & $min_set
Return $Suntimes
EndFunc
;Now all the Support Funcs
Func sind($qqq)
$sind = sin(($qqq) * $DEGRAD)
return $sind
EndFunc
Func cosd($qqq)
$cosd = cos(($qqq) * $DEGRAD)
return $cosd
EndFunc
Func tand($qqq)
$tand = tan(($qqq) * $DEGRAD)
return $tand
EndFunc
Func atand($qqq)
$atand = ($RADEG * atan($qqq))
return $atand
EndFunc
Func asind($qqq)
$asind = ($RADEG * asin($qqq))
return $asind
EndFunc
Func acosd($qqq)
$acosd = ($RADEG * acos_new($qqq))
return $acosd
EndFunc
Func atan2d ($qqq, $qqq1)
$atan2d = ($RADEG * atan2($qqq, $qqq1))
return $atan2d
EndFunc
Func rev($qqq)
Dim $x
$x = ($qqq - int($qqq/360.0) * 360.0)
if ($x <= 0) then
$x = $x + 360
Endif
$rev = $x
return $rev
EndFunc
Func atan2($ys,$xs)
; from the Draw Arrows tip
; @ http://www.devx.com/upload/free/features/VBPJ/techtips/techtips11.pdf
; by —Jim Deutch, Syracuse, New York
- 67 -
Dim $theta
If $xs <> 0 Then
$theta = Atan($ys / $xs)
If $xs < 0 Then
$theta = $theta + $pi
Endif
Else
If $ys < 0 Then
$theta = 3 * $pi / 2 ;90
Else
$theta = $pi / 2 ;270
Endif
Endif
$atan2 = $theta
return $atan2
EndFunc
Func acos_new($x)
$acos_new = Atan(-$X / Sqrt(-$X * $X + 1)) + 2 * Atan(1)
return $acos_new
EndFunc
- 68 -

Documentos relacionados