'##############################################################################
' StarLight_Master.BAS                                         Stand 07.03.2011
' --------------------                                         (C) Markus Fulde
'
' Steuerprogramm für Mastereinheit der StarLight Deckenbeleuchtungselektronik
'
' Das Steuerprogramm verfügt über die folgenden einzelnen Funktions- und
' Teilkomponenten:
'     - Spannungsversorgung für +5V
'     - Mikrocontroller ATmega128 (inkl. ISP, RS232 und Reset)
'     - 16 MHz externer Clock
'     - LCD-Display 3x16
'     - 3 Taster und Schalter
'     - LED-Anzeigen für Funktionsanzeige
'     - RS485-Interface für Kommunikation mit Slaves
'     - Externes I2C-EEPROM
'     - 1-Wire Temperatursensor für Umgebungstemperatur
'     - SCART-Adapter-Anbindung für Funkübertragung
'     - Akustischer Signalgeber
'
'     - Funktions- und Debug-Steuerung über RS232
'
' Das Masterprogramm stell die Verbindung zwischen der Betty-Fernbedienung und
' den Slaves her. Die Slaves selbst sind "dumme" Einheiten welche Kommandos
' und Steuerbefehle vom Master erhalten.
' Der Master empfängt Kommandos von Betty, setzt diese auf dem RS485-Bus für
' die Slaves um, sammels Antworten und sendet diese zurück zur Betty.
' Der Master überwacht die Funktionen, speichert Einstellungen persistent und
' initialisiert das Gesamtsystem.
'
'##############################################################################

'------------------------------------------------------------------------------
' Compilerinstruktionen und Compilerdirektiven
'------------------------------------------------------------------------------
$regfile = "m128def.dat"                                    ' Definitionsdatei für ATmega128 laden
$crystal = 16000000                                         ' Quarzfrequenz für 16 MHz festlegen
$hwstack = 256                                              ' HW-Stack auf 256 Bytes erweitern
$swstack = 256                                              ' SW-Stack auf 256 Bytes erweitern
$framesize = 256                                            ' Framesize auf 256 Byte festlegen

$lib "i2c_twi.lbx"                                          ' we do not use software emulated I2C but the TWI

' $baud = 38400                                               ' Baudrate für RS232 auf 38400 Bauf festlegen
' Hinweis: Direktive nicht notwendig da Konfiguration über CONFIG

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

' ASCII Table (Incomplete)
' Decimal  Hex    Binary       Value   Beschreibung
' -------  ---    --------     -----   ------------------
' 000      000    00000000     NUL     (Null char.)
' 008      008    00001000     BS      (Backspace)
' 009      009    00001001     HT      (Horizontal Tab)
' 010      00A    00001010     LF      (Line Feed)
' 012      00C    00001100     FF      (Form Feed)
' 013      00D    00001101     CR      (Carriage Return)
' 032      020    00100000     SPACE   (Leerzeichen)
' 048      030    00110000     0       (Beginn der Ziffern)
' 049      031    00110001     1       (..)
' 052      034    00110100     4       (..)
' 065      041    01000001     A       (Beginn der Zeichen)
' 066      042    01000010     B       (..)
' 067      043    01000011     C       (..)

' Hinweis: Im Datenblatt wird die zeit von 750 ms nur in Verbindung mit dem
' parasite power mode genannt. Test in der Praxis haben interessanter Weise
' jedoch ergeben, das auch mit normaler Spannungsversorgung beim DS18S20 Zeiten
' bis 700 ms erreicht werden. Wird zu zeitig ausgelesen liefert der Sensor den
' Fehlercode 10101010 welcher 170 DEZ = 85°C entspricht. Wird dieser Wert bei
' erstmaligem Convert T ausgelesen ist dies ein Zeichen dafür, dass der Sensor
' den Konvertierungsvorgang noch nicht abgeschlossen hat.

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

' ----- LED's -----
' Übertemperatur-LED
Temp_led_pin Alias Pina.1                                   ' GPIO für Übertemperatur-LED (für DDR oder Input)
Temp_led Alias Porta.1                                      ' GPIO für Übertemperatur-LED (für Output oder PullUp)

Alive_pin Alias Pina.0                                      ' GPIO für Alive-LED (für DDR oder Input)
Alive Alias Porta.0                                         ' GPIO für Alive-LED (für Output oder Pullup)

Led_3_pin Alias Pina.2                                      ' GPIO für Reserve-LED (für DDR oder Input)
Led_3 Alias Porta.2                                         ' GPIO für Reserve-LED (für Output oder Pullup)

' ----- Soundausgabe -----
' Piezo
Piezo_pin Alias Pine.2                                      ' GPIO für Soundausgabe (für DDR oder Input)
Piezo Alias Porte.2                                         ' GPIO für Soundausgabe (für Output oder PullUp)

' ----- SCART GPIO-Pin -----
Scart_pin Alias Pine.5                                      ' GPIO für Soundausgabe (für DDR oder Input)
Scart Alias Porte.5                                         ' GPIO für Soundausgabe (für Output oder PullUp)

' ----- DS1820: 1Wire-Interface DS18S20
1wire_port Alias Porte.3                                    ' 1Wire-Interface für Temperatursensor

' ----- DIM: Durchgangsbeleuchtung -----
' Steuerung für Durchgangsbeleuchtungs-Relais
Relais_pin Alias Pine.4                                     ' GPIO für SSR-Steuerleitung (für DDR oder Input)
Relais Alias Porte.4                                        ' GPIO für SSR-Steuerleitung (für Output oder PullUp)

' ----- LCD: Alias für LCD-Steuerung -----
Lcd_light_pin Alias Pinc.6                                  ' GPIO für LCD Hintergrundbeleuchtung (für DDR oder Input)
Lcd_light Alias Portc.6                                     ' GPIO für LCD Hintergrundbeleuchtung (für Output oder Pullup)

' ----- Key: Tastatur -----
Key_1_pin Alias Pina.4                                      ' GPIO für Taste 1 (für DDR oder Input)
Key_1 Alias Porta.4                                         ' GPIO für Taste 1 (für Output oder Pullup)

Key_2_pin Alias Pina.5                                      ' GPIO für Taste 2 (für DDR oder Input)
Key_2 Alias Porta.5                                         ' GPIO für Taste 2 (für Output oder Pullup)

Key_3_pin Alias Pina.6                                      ' GPIO für Taste 3 (für DDR oder Input)
Key_3 Alias Porta.6                                         ' GPIO für Taste 3 (für Output oder Pullup)

Key_4_pin Alias Pina.7                                      ' GPIO für Taste 4 (für DDR oder Input)
Key_4 Alias Porta.7                                         ' GPIO für Taste 4 (für Output oder Pullup)

' ----- TWI Interface für EEPROM -----
Sda_port Alias Portd.1                                      ' Data ist an D.1
Scl_port Alias Portd.0                                      ' Clock ist an D.0

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

' ----- Für Testumgebung bzw. Traceausgaben -----

Const System_testmodus = 0                                  ' Testmodus zum Abfackeln aller Funktionen vor Systemstart

Const Main_testmodus = 0                                    ' Flag für Testmodus Allgemeinsystem
Const Scart_testmodus = 0                                   ' Flag für SCART Testmodus
Const Scart_rx_testmodus = 0                                ' Flag für SCART Testmodus
Const Scart_tx_testmodus = 0                                ' Flag für SCART Testmodus
Const Scart_proc_testmodus = 0                              ' Flag für SCART Testmodus
Const Temp_testmodus = 0                                    ' Flag für Testmodus Temperaturüberwachung
Const Timer_testmodus = 0                                   ' Flag für Testmodus Timer
Const Rs485_testmodus = 0                                   ' Flag für Testmodus RS485
Const Lcd_testmodus = 0                                     ' Flag für LCD-Testmodus
Const Eeprom_testmodus = 0                                  ' Testmodus für EEPROM
Const Scheduler_testmodus = 0                               ' Flag für Testmodus Scheduler
Const Key_testmodus = 0                                     ' Flag für Testmodus der Tastatur
Const Menue_testmodus = 0                                   ' Flag für Testmodus der Menüs
Const Screensaver_testmodus = 0                             ' Testmodus für Screensaver
Const Error_testmodus = 0                                   ' Flag für Error-Testmodus
Const Startupreset_testmodus = 0                            ' Flag für Untersuchungen des StartUp-Reset
Const Empfangsueberwachung_testmodus = 0                    ' Flag für globale Empfangsüberwachung mit Timerout
Const Ee_data_indizierung_testmodus = 0                     ' Flag für den Umgang mit den Dimmerdaten über Overlay

' ----- Systemcheck -----
Const Looptime = 100                                        ' Dauer der Schleifenzeit in ms für Check
Const Texttime = 1                                          ' Dauer der Textanzeigezeit in s für Check

' ----- Allgemeine Systemkonstanten -----
Const Led_aus = 0
Const Led_ein = 1

Const Licht_aus = 0
Const Licht_ein = 1

Const Scart_aus = 0
Const Scart_ein = 1

Const Dauerlicht_aus = 0
Const Dauerlicht_ein = 1

Const Pullup_aus = 0
Const Pullup_ein = 1

Const True = 1
Const False = 0

' Zeitvorgabe für Sekunden-Timer
Const Timervorgabe = 3036

' Zeitvorgabe für Receive-Timeout-Überwachung
Const Receive_timeout = 2

' ----- System-Demo -----
Const Sweep_down = 0
Const Sweep_up = 1

' ----- Sound: Akustik-Wiedergabe -----
Const Sound_aus = 0
Const Sound_ein = 1
Const Sound_ein_delay = 100                                 ' Soundlänge in MS
Const Sound_pause_delay = 100                               ' Soundpause in MS
Const Sound_default = False                                 ' Default ist Sound aus

' ----- Relais: Hauptrelais-Steuerung -----
Const Relais_aus = 0
Const Relais_ein = 1

' ----- DS1820: Temperatursensor -----
Const Ds1820_skip_rom_command = &HCC                        ' Code für Skip ROM
Const Ds1820_convert_t_command = &H44                       ' Code für Convert T
Const Ds1820_scratchpad_command = &HBE                      ' Code für Read scratchpad

Const Ds1820_delay_time = 750                               ' 750ms Wartezeit

Const Ds1820_auswertung = 30                                ' Default Auswerteintervall in Sekunden
Const Ds1820_auswertung_start = 2                           ' Default Auswerteintervall in Sekunden

Const Slave_temp_auswertung = 30                            ' Default Auswerteintervall in Sekunden

Const Uebertemperatur_default = 50                          ' Konstante für Übertemperatur

Const Max_temperatur = 99                                   ' maximale Uebertemperatur
Const Min_temperatur = 00                                   ' minimale Uebertemperatur

' ----- LCD: LCD-Dispplay ---
' LCD: Konstanten für LCD-Kontrast (Range 0-63 / 6 Bit)
Const Lcd_kontrast_default = 12                             ' Default Kontrast empirisch ermittelt

' LCD: screensaver
Const Lcd_screensaver_default = 1                           ' Defaultwert für Screensaver auf TRUE setzen
Const Lcd_screensaver_delay = 20                            ' 60 Sekunden Delay für Screensaver

' ----- RS485: Systembus RS485 Interface -----

' Allgemeines
Const Nachrichtenlaenge = 10                                ' Länger der gesamtbotschaft in Bytes
Const Framelaenge = 5                                       ' Länger der Nutzdaten

Const Masteradresse = &H00                                  ' Master hat Adresse 0
Const Broadcastadresse = &HFF                               ' Adresse für alle uns alles (Broadcast)

Const Slave_1_adresse = &H01                                ' Adresse des Slave 1
Const Slave_2_adresse = &H02                                ' Adresse des Slave 2
Const Slave_3_adresse = &H03                                ' Adresse des Slave 3
Const Slave_4_adresse = &H04                                ' Adresse des Slave 4
Const Slave_5_adresse = &H05                                ' Adresse des Slave 5
Const Slave_6_adresse = &H06                                ' Adresse des Slave 6
Const Slave_7_adresse = &H07                                ' Adresse des Slave 7
Const Slave_8_adresse = &H08                                ' Adresse des Slave 8

Const Undefined = &HFF                                      ' Platzhalter

Const Wait_time = 1                                         ' Wartezeit in ms für RE
Const Rs485_answer_timeout = 2                              ' Wartezeit in Sekunden für Timeout

' Kommunikation Master -> Slave
Const Cmd_licht_schalten = &H01                             ' Steuerwort für Licht schalten
Const Cmd_dimmer_schalten = &H02                            ' Steuerwort für Dimmer steuern
Const Cmd_sound_schalten = &H03                             ' Steuerwort für Sound schalten
Const Cmd_licht_dimmer_schalten = &H04                      ' Steuerwort für Licht schalten und Dimmer steuern
Const Cmd_status_abfragen = &H05                            ' Steuerwort für Status abfragen
Const Cmd_uebertemperatur_setzen = &H06                     ' Steuerwort für Übertemperatur setzen
Const Cmd_sweep_mode = &H07                                 ' Steuerwort für Sweep-Demo-Modus

' Kommunikation Slave -> Master
Const Resp_ack = &HFF                                       ' Response Acknowledge                             '
Const Resp_uetemp = &H01                                    ' Response Übertemperatur
Const Resp_status = &H02                                    ' Response Status

' ----- SCART -----
Const Scart_ping_delay = 250                                ' 250 ms
Const Wait_scart_switch_on = 500                            ' 500 ms
Const Scart_processing_time = 1000                          ' 1000 ms
Const Scart_max_loop_count = 3                              ' 3 Retries
Const Scart_counter_delay = 3                               ' 3 Sekunden auf Antwort von SCART warten beim Senden

Const Scart_cmd_nop = &H00                                  ' PING
Const Scart_cmd_transmit = &H01                             ' Datentransfer
Const Scart_cmd_demo = &HFF                                 ' Demo-Modus

Const Scart_return_error = &H00                             ' Fehler
Const Scart_return_ready = &H01                             ' OK
Const Scart_return_rf_packet = &H02                         ' Datenpaket
Const Scart_return_rf_default = &H03                        ' Default

Const Rf_rx_nachrichtenlaenge = 11                          ' 11 Byte Nachrichtenlänge
Const Rf_rx_framelaenge = 3                                 ' Nutzdateninhalt 3 Bytes

Const Rf_tx_nachrichtenlaenge = 10                          ' 11 Byte Nachrichtenlänge
Const Rf_tx_protokolllaenge = 8                             ' 8 Byte Protokoll-Laenge
Const Rf_tx_framelaenge = 5                                 ' Nutzdateninhalt 5 Bytes

Const Rf_cmd_status_abfragen = &H00                         ' Kommando für Status abfragen
Const Rf_cmd_licht_schalten = &H01                          ' Kommando für Licht schalten
Const Rf_cmd_dimmer_schalten = &H02                         ' Kommando für Dimmer steuern
Const Rf_cmd_sound_schalten = &H03                          ' Kommando für Sound schalten
Const Rf_cmd_gesamtlicht = &H04                             ' Kommand für alle Lampen schalten
Const Rf_cmd_dimmer_onoff = &H05                            ' Kommando um Dimmer zu schalten
Const Rf_cmd_demomodus = &H06                               ' Kommando um Demomodus zu aktivieren
Const Rf_cmd_dimmer_steuern = &H07                          ' Kommando um Dimmstufe und Status zu schalten

Const Rf_resp_ack = &HFF                                    ' Response Acknowledge
Const Rf_resp_status = &H01                                 ' Response Status

Const Rf_cmd_scart_send = &H01                              ' Kommando für SCART um Datenblock zu senden

' ----- Dimmer -----

' Defaultwerte für Setting-Einstellungen
Const Dimmer_default = &H10                                 ' Dimmer Default = 16
Const Licht_default = &H00                                  ' Licht_default = AUS

' Maximalgrenzen
Const Max_dimmer = 31                                       ' maximaler Dimmerwert
Const Min_dimmer = 1                                        ' minimaler Dimmerwert

' ----- Externes und internes EEPROM -----

' Definition für EEPROM-Paging
Const Blockwritecounter_init = &H00000000                   ' Counter für Schreibzyklen
Const Blockwritecounter_limit = &H000F4240                  ' Grenze 1.000.000 Schreibzyklen
' Const Blockwritecounter_limit = &H00000030                  ' Grenze 20 Schreibzyklen zum Test

Const Data_block_count_init = &H0001                        ' Counter für EEPROM-Blöcke

' Aktuelle EEPROM-Datenstruktur
Const Akt_external_ee_version = &H01                        ' Aktuelle EEPROM-Datenstruktur extern
Const Akt_internal_ee_version = &H02                        ' Aktuelle EEPROM-Datenstruktur intern

' EE: Konstanten für Betriebsdaten (externes EEPROM)
Const Ee_data_version_extern_adress = &H0000                ' Bytewert für Datenversion
Const Ee_data_block_count_adress = &H0001                   ' Word für Block-Counter

Const Ee_data_blocklength = &H20                            ' Die Blocklänge beträgt 32 Bytes
Const Ee_data_struct_length = 20                            ' Länger der Datenstruktur

Const Ee_data_start_adress = &H0020                         ' An dieser Adresse beginnen die Datenblöcke
Const Ee_data_end_adress = &HFFE0                           ' An dieser Adresse beginnt der letzte Block

' EE:  Adressen für das exerne EEPROM
Const Address_write = &B10100000                            ' Adresse des 24C512 = &HA0 (schreiben)
Const Address_read = &B10100001                             ' Adresse des 24C512 = &HA1 (lesen

' Update-Timer
Const Ee_data_update_timer_value = 30                       ' Alle 30 Sekunden soll upgedated werden

' ----- MENUE:  Menue -----
' Die Menüsteuerung erfolgt über die Tasten Schwarz | Gelb | Blau | Rot
' Die Tasten haben folgenden Funktion:
'     Schwarz = Hoch
'     Gelb    = Runter
'     Blau    = Links
'     Rot     = Rechts
Const Key_buttons = 4                                       'Anzahl der Tasten für das Menü

' Die logische Zustands-NULL für das Menue
Const Key_null = 0                                          'keine Taste gedrückt

' Wartezeit von Scr01 vor Einstieg in Hauptmenue
Const Menue_scr01_delay = 1                                 ' Delay-Time 1 Sekunden
Const Menue_update_time = 5                                 ' 5 Sekunden Pause Für Fehlermeldung -update

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

' ----- Temporäre Hilfsvariablen bzw. allgemeingültige Arbeitsvariablen -----

' Achtung: Aufpassen dass sich bei verschachtelten Gosubs Variablen nicht gegenseitig
'          überschreiben!!

' Testroutine zum Auslesen der Reset-Ursache
#if Startupreset_testmodus
   Dim Mcucsr_1 As Byte
   Dim Mcucsr_2 As Byte
   Mcucsr_1 = Mcucsr                                        ' Mcucsr zum 1. Mal lesen
   Mcucsr = 0                                               ' zurücksetzen
#endif

' Variablendefinitionen
Dim Temp_byte_1 As Byte                                     ' Temporäre Byte Variable 1
Dim Temp_byte_2 As Byte                                     ' Temporäre Byte Variable 2
Dim Temp_byte_3 As Byte                                     ' Temporäre Byte Variable 3
Dim Temp_byte_4 As Byte                                     ' Temporäre Byte Variable 4
Dim Temp_byte_5 As Byte                                     ' Temporäre Byte Variable 5
Dim Temp_byte_6 As Byte                                     ' Temporäre Byte Variable 6
Dim Temp_byte_7 As Byte                                     ' Temporäre Byte Variable 7
Dim Temp_byte_8 As Byte                                     ' Temporäre Byte Variable 8

Dim Temp_word_1 As Word                                     ' Temporäre Word Variable 1
Dim Temp_word_2 As Word                                     ' Temporäre Word Variable 2
Dim Temp_word_3 As Word                                     ' Temporäre Word Variable 3

Dim Temp_int_1 As Integer                                   ' Temporäre Integer Variable 1
Dim Temp_int_2 As Integer                                   ' Temporäre Integer Variable 2
Dim Temp_int_3 As Integer                                   ' Temporäre Integer Variable 3

Dim Temp_single_1 As Single                                 ' Temporäre Single Variable 1
Dim Temp_single_2 As Single                                 ' Temporäre Single Variable 2
Dim Temp_single_3 As Single                                 ' Temporäre Single Variable 3

' ----- Variablen für globale Receive Timeout Überwachung
Dim Receive_timeout_counter As Word                         ' Vaiable für Counter
Dim Receive_timeout_flag As Byte                            ' Flag für Counter-Überwachung

' ----- Variablen für flobale Fehlerbehandlung -----
Dim Err_scart As Byte                                       ' Variable für Fehler im bereich SCART
Dim Err_global_flag As Byte                                 ' Globales Fehlerflag

' ----- Variable für SecTick Scheduler -----

' Bemerkung: Mit dem Wertebereich 0..65535 einer Word-Variable kann der Zeitraum
'            65535 / 60 / 60 von 18 Stunden abgedeckt werden. Es ist nicht an-
'            zunehmen, dass die Lichtanlage länger als 18 Stunden eingeschaltet
'            ist, sonst müsste man den Überlauf des Timercounter verhindern.
'            Darauf wird aktuell wissentlich verzichtet.

Dim Timercounter As Word                                    ' Scheduler-Variable

' ----- Variablen für Beleuchtung -----
Dim Lichtflag As Byte                                       ' Flag ob Licht eingeschaltet oder aus
Dim Anlagenflag As Byte                                     ' Globale Variable für Lichtanlage

' ----- Variable für SoundFlag -----
Dim Soundflag As Byte                                       ' Flag für Sound

' ----- DS1820: Temperatursensor -----
Dim Ds1820_device_count As Byte                             ' Variable für Anzahl aller Devices auf 1Wire
Dim Ds1820_rom_code(8) As Byte                              ' Variable für 64-Bit Lasered ROm Code
Dim Ds1820_error_flag As Byte                               ' Globale Variable für Fehlermeldungen
Dim Ds1820_scratchpad(9) As Byte                            ' Varible für Scratchpad
Dim Ds1820_messwert As Integer                              ' Globale Variable für Integer-Messert
Dim Ds1820_temperatur As Byte                               ' Gloable Temperatur zum Casten

Dim Ds1820_erfassungs_counter As Word                       ' Globaler Zähler für Temperaturauswertung

Dim Flag_uebertemperatur As Byte                            ' Flag für Übertemperatur
Dim Uebertemperatur As Byte                                 ' Globale Arbeitsvariable für Uebertemperatur

Dim Slave_temp_counter As Word                              ' Globaler Zähler für Temperaturauswertung
Dim Slave_temp_bitfeld As Byte                              ' Jedes Bit repräsentiert einen Slave

' ----- Temperatur der Slaves -----
Dim Slave_temperatur(8) As Byte                             ' Slave-Temperaturen

' ----- Variablen für Umgang mit RS232-SCART-Interface -----
Dim Serialcharwaiting As Byte                               ' Arbeitsvariable um Zeichen abzufrage
Dim Serialstring As String * 255                            ' Arbeitsvariable um String aufzubauen

' ----- Variable für RS485 Slave-Adresse -----

' Algemeines
Dim Rs485_slaveadresse As Byte                              ' Slave-Adresse des Dimmers
Dim Rs485_receive_timer As Word                             ' Counter für Empfangszeigt

' RS485: Globale Sendestruktur
Dim Tx_zieladresse As Byte                                  ' Senden: Zieladresse
Dim Tx_quelladresse As Byte                                 ' Senden: Quelladresse
Dim Tx_framelength As Byte                                  ' Senden: Datenlänge
Dim Tx_kommando As Byte                                     ' Senden: Kommando
Dim Tx_licht As Byte                                        ' Senden: Datum Licht
Dim Tx_dimmstufe As Byte                                    ' Senden: Datum Dimmer
Dim Tx_temperatur As Byte                                   ' Senden: Temperatur
Dim Tx_sound As Byte                                        ' Senden: Datum Sound
Dim Tx_checksumme As Word                                   ' Senden: Cheksumme
Dim Tx_buffer(nachrichtenlaenge) As Byte At Tx_zieladresse Overlay       ' Overlay über Datenstruktur

Dim Tx_bufferindex As Byte                                  ' Sende-Zeiger

' RS485: Globale Empfangsstruktur
Dim Rx_zieladresse As Byte                                  ' Empfangen: Zieladresse
Dim Rx_quelladresse As Byte                                 ' Empfangen: Quelladresse
Dim Rx_framelength As Byte                                  ' Empfangen: Datenlänge
Dim Rx_kommando As Byte                                     ' Empfangen: Kommando
Dim Rx_licht As Byte                                        ' Empfangen: Datum Licht
Dim Rx_dimmstufe As Byte                                    ' Empfangen: Datum Dimmer
Dim Rx_temperatur As Byte                                   ' Empfangen: Temperatur
Dim Rx_sound As Byte                                        ' Empfangen: Datum Sound
Dim Rx_checksumme As Word                                   ' Empfangen: Checksumm
Dim Rx_buffer(nachrichtenlaenge) As Byte At Rx_zieladresse Overlay       ' Overlay über Datenstruktur

Dim Rx_bufferindex As Byte                                  ' Empfangs-Zeiger
Dim Rs485_data_received As Byte                             ' Flag Empfangsindikator

' ----- Variablen für LCD-Display -----
Dim Kontrastwert As Byte                                    ' Arbeitsvariable für Kontrastwerte
Dim Text(6) As String * 16                                  ' Texte für programmgesteuerte Demo-Ausgaben

' ----- Variablen für Fehlerhandling -----
Dim Error_msg_1(10) As String * 16                          ' Texte für Fehlermeldungen Zeile 1
Dim Error_msg_2(10) As String * 16                          ' Texte für Fehlermeldungen Zeile 2
Dim Error_flags(10) As Byte                                 ' Flag-Array für Fehlermeldungen
Dim Error_index As Byte                                     ' Index auf aktuellen Fehler
Dim Error_show_flag As Byte                                 ' Flag ob Fehlertext oder kein Fehler

' ----- Variablen für SCART-Adapter -----

' Globale Sendestruktur für RF-Verbindung Master -> Betty
' Header
Dim Rf_tx_paket_type As Byte                                ' [1] Paket-Typ-Kennzeichnung für SCART-Adapter (Header)
Dim Rf_tx_frame_len As Byte                                 ' [2] Daten-Paket-größe für SCART-Adapter (Header)
' Protokoll
Dim Rf_tx_framelength As Byte                               ' [3] Senderichtung: Nachrichtenlänge
Dim Rf_tx_kommando As Byte                                  ' [4] Senderichtung: Kommando
Dim Rf_tx_dimmer As Byte                                    ' [5] Senderichtung: Dimmerstatus
Dim Rf_tx_dimmwert As Byte                                  ' [6] Senderichtung: Dimmwert
Dim Rf_tx_temperatur As Byte                                ' [7] Senderichtung: Temperatur des Slave
Dim Rf_tx_sound As Byte                                     ' [8] Senderichtung. Sound
Dim Rf_tx_checksumme As Word                                ' [9] Senderichtung: Checksumme
' Overlay
Dim Rf_tx_buffer(rf_tx_nachrichtenlaenge) As Byte At Rf_tx_paket_type Overlay       ' Overlay

Dim Rf_tx_bufferindex As Byte                               ' Buffer-Index
Dim Rf_send_request As Byte                                 ' Sendeanforderung
Dim Rf_tx_errorflag As Byte                                 ' Sendefehler

' Globale Empfangsstruktur für RF-Verbindung Betty -> Master
' Header
Dim Rf_rx_paket_type As Byte                                ' [1] Paket-Typ-Kennzeichnung des SCART-Adapters (Header)
Dim Rf_rx_frame_len As Byte                                 ' [2] Daten-Paket-größe des SCART-Adapters (Header)
Dim Rf_rx_dest_addr As Byte                                 ' [3] Destination Address
Dim Rf_rx_src_addr As Byte                                  ' [4] Source Address
Dim Rf_rx_data_type As Byte                                 ' [5] Paket Data Type
' Protokoll
Dim Rf_rx_framelength As Byte                               ' [6] Empfangsrichtung: Nachrichtenlänge
Dim Rf_rx_kommando As Byte                                  ' [7] Empfangsrichtung: Kommando
Dim Rf_rx_parameter_1 As Byte                               ' [8] Empfangsrichtung: Parameter 1
Dim Rf_rx_parameter_2 As Byte                               ' [9] Empfangsrichtung : Parameter 2
Dim Rf_rx_checksumme As Word                                ' [10] Empfangsrichtung: Checksumme (2 Byte)
' Overlay
Dim Rf_rx_buffer(rf_rx_nachrichtenlaenge) As Byte At Rf_rx_paket_type Overlay       ' Overlay

Dim Rf_rx_bufferindex As Byte                               ' Buffer-Index
Dim Rf_data_received As Byte                                ' Empfangsflag
Dim Rf_rx_errorflag As Byte                                 ' Empfangsfehler

' Sonstiges
Dim Scart_antwort_counter As Word                           ' Globaler Zähler um Antwort von Scart zu erfassen

' ----- EEPROM Datenstrukturen und persistente Datenhaltung -----

' EE: EEPROM Datenstruktur internes EEPROM - Setting-Daten
Dim Ee_data_version_intern As Eram Byte At &H0000           ' Speicherstelle für Datenversion
Dim Ee_data_temperature As Eram Byte At &H0001              ' Speicherstelle für Temperaturschwelle
Dim Ee_data_sound As Eram Byte At &H0002                    ' Speicherstelle für Soundausgabe

' EE: EEPROM Datenstruktur externes EEPROM
Dim Ee_data_version_extern As Byte                          ' Datenversion
Dim Ee_data_block_count As Word                             ' Counter für EEPROM-Blöcke

' Schreib-Counter für EEPROM-Block
Dim Ee_data_block_write_count As Long

' Byte(1) Dimmermodul 1 - Schaltzustand
Dim Ee_data_mod1_light As Byte
' Byte(2) Dimmermodul 1 - Dimmerstufe
Dim Ee_data_mod1_dimm As Byte
Dim Persistenz_dimmer_1(2) As Byte At Ee_data_mod1_light Overlay

' Byte(3) Dimmermodul 2 - Schaltzustand
Dim Ee_data_mod2_light As Byte
' Byte(4) Dimmermodul 2 - Dimmerstufe
Dim Ee_data_mod2_dimm As Byte
Dim Persistenz_dimmer_2(2) As Byte At Ee_data_mod2_light Overlay

' Byte(5) Dimmermodul 3 - Schaltzustand
Dim Ee_data_mod3_light As Byte
' Byte(6) Dimmermodul 3 - Dimmerstufe
Dim Ee_data_mod3_dimm As Byte
Dim Persistenz_dimmer_3(2) As Byte At Ee_data_mod3_light Overlay

' Byte(7) Dimmermodul 4 - Schaltzustand
Dim Ee_data_mod4_light As Byte
' Byte(8) Dimmermodul 4 - Dimmerstufe
Dim Ee_data_mod4_dimm As Byte
Dim Persistenz_dimmer_4(2) As Byte At Ee_data_mod4_light Overlay

' Byte(9) Dimmermodul 5 - Schaltzustand
Dim Ee_data_mod5_light As Byte
' Byte(10) Dimmermodul 5 - Dimmerstufe
Dim Ee_data_mod5_dimm As Byte
Dim Persistenz_dimmer_5(2) As Byte At Ee_data_mod5_light Overlay

' Byte(11) Dimmermodul 6 - Schaltzustand
Dim Ee_data_mod6_light As Byte
' Byte(12) Dimmermodul 6 - Dimmerstufe
Dim Ee_data_mod6_dimm As Byte
Dim Persistenz_dimmer_6(2) As Byte At Ee_data_mod6_light Overlay

' Byte(13) Dimmermodul 7 - Schaltzustand
Dim Ee_data_mod7_light As Byte
' Byte(14) Dimmermodul 7 - Dimmerstufe
Dim Ee_data_mod7_dimm As Byte
Dim Persistenz_dimmer_7(2) As Byte At Ee_data_mod7_light Overlay

' Byte(15) Dimmermodul 8 - Schaltzustand
Dim Ee_data_mod8_light As Byte
' Byte(16) Dimmermodul 8 - Dimmerstufe
Dim Ee_data_mod8_dimm As Byte
Dim Persistenz_dimmer_8(2) As Byte At Ee_data_mod8_light Overlay

' Overlaystrukturen für Byte-Arrays definieren
Dim Ee_data_lightning_struct(16) As Byte At Ee_data_mod1_light Overlay       ' Datenstruktur für Einstellungen
Dim Ee_data_struct(20) As Byte At Ee_data_block_write_count Overlay       ' Overlay über alles

' EE: Variablen
Dim Ee_adresse As Word                                      ' EEPROM-Adresse

' Temporäre Arbeitsvariablen
Dim Ee_adrl_temp As Byte
Dim Ee_adrh_temp As Byte

' Arbeitsvariable zum Update von Dimmdaten
Dim Ee_dimmer_update(8) As Byte                             ' Array für Updateflags
Dim Ee_update_counter As Word                               ' Globaler Zähler zum Abspeichern von EEPROM-Daten

' ----- KEY: Tastatur -----
Dim Key_taste As Byte                                       ' Variable enthält Tastennummer
Dim Key_taste_buffer As Byte                                ' Buffer für aktuelle Taste
Dim Key_keypressed As Byte                                  ' Zustandsflag

' ----- MENUE:  Menue -----
' Tastencodes
Dim Key_codes(key_buttons) As Byte                          ' Array für Tastencodes
Dim Key_shortcut_status As Byte                             ' Statusflag für Short-Cut Modus

' Textausgaben
Dim Menue_lcd_textbuffer(3) As String * 17                  ' Auslesebuffer für die Menü-Strings
Dim Menue_ausgabeflags As Byte                              ' Ausgabeflags wie viele Zeilen
Dim Menue_menueupdate_flag As Byte                          ' Flag für zyklisches Update von Menüs
Dim Menue_update_counter As Word                            ' Sectic counter für Menü-Update

' Zustandsvariablen
Dim Menue_state As Word                                     ' aktueller State
Dim Menue_state_buffer As Word                              ' gebufferter Menüstatus
Dim Menue_state_renew As Byte                               ' Flag
Dim Menue_state_gosub As Word                               ' aktuelles Unterprogramm

' Arbeitsvariablen für universelles Dimmereinstellunge
Dim Menue_dimmer_status As Byte                             ' Status [AN/AUS]
Dim Menue_dimmer_dimmwert As Byte                           ' Dimmwert [00-32]
Dim Menue_dimmer As Byte                                    ' Aktueller Dimmer

' Sonstige Arbeitsvariablen
Dim Menue_datenuebernahme_flag As Byte                      ' Datenübernahmeflag für Time und Date
Dim Menue_data_changed_flag As Byte                         ' Flag für Datenübernahme in Settings

' ----- LCD: Display -----
Dim Lcd_screensaver As Byte                                 ' Flag für Screen-Saver-Modus
Dim Lcd_screensaver_counter As Word                         ' Sectic counter für Screensaver
Dim Lcd_screensaver_aktiv As Byte                           ' Flag ob Screensaver aktiv ist

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

' ========== Subroutinen ==========

' ----- LCD:  Für LCD-Display -----
Declare Sub Lcd_writesingleline(byval Line1 As Byte , Text1 As String)
Declare Sub Lcd_writedoubleline(byval Line1 As Byte , Byval Line2 As Byte , Text1 As String , Text2 As String)
Declare Sub Lcd_writetrippleline(text1 As String , Text2 As String , Text3 As String)

' ========== Funktionen ==========

' ----- Funktionen für SCART-Adapter -----
Declare Function Scart_init() As Byte
Declare Function Scart_send(byval Resp_code As Byte , Byval Dimmer As Byte) As Byte
Declare Function Scart_ack_send(byval Ack_type As Byte ) As Byte

' ----- Funktionen für EEPROM und persistente Datenhaltung -----
Declare Sub Ee_write_eeprom_byte(byval Adress As Word , Byval Value As Byte)
Declare Sub Ee_write_eeprom_word(byval Adress As Word , Byval Value As Word)

Declare Function Ee_read_eeprom_byte(byval Adress As Word) As Byte
Declare Function Ee_read_eeprom_word(byval Adress As Word) As Word

' ----- Funktionen für Slave-Kommunikation via RS485 -----
Declare Function Rs485_status_abfragen(byval Slave As Byte) As Byte
Declare Function Rs485_last_used_mode() As Byte
Declare Function Rs485_licht_schalten(byval Slave As Byte , Byval Status As Byte) As Byte
Declare Function Rs485_dimmwert_setzen(byval Slave As Byte , Byval Dimmerwert As Byte) As Byte
Declare Function Rs485_sound_schalten(byval Slave As Byte , Byval Soundstatus As Byte) As Byte
Declare Function Rs485_licht_dimmer_schalten(byval Slave As Byte , Byval Status As Byte , Byval Dimmerwert As Byte , Byval Soundstatus As Byte) As Byte
Declare Function Rs485_temperatur_setzen(byval Slave As Byte , Byval Temperatur As Byte) As Byte
Declare Function Rs485_sweep_mode(byval Slave As Byte , Byval Modus As Byte) As Byte

' ----- Allgemeine Funktionen -----
Declare Function Byte2string(byval Value As Byte , Byval Character As Byte) As String

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

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

' ----- RS232 -----

' Hardware RS232 konfigurieren = interne RS232

' Serialport für RS485 Systeminterface
Config Com1 = 57600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Serialin = Buffered , Size = 254
Config Serialout = Buffered , Size = 254

' Serialport für Kommunikation mit SCART-Adapter
Config Com2 = 38400 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Serialin1 = Buffered , Size = 254
Config Serialout1 = Buffered , Size = 254

' Serialport für RS485 Systeminterface
Open "com1:" For Binary As #1

' Serialport für Kommunikation mit SCART-Adapter
Open "com2:" For Binary As #2

' Software RS232 Kanal 3 und 4 konfigurieren = externe RS232
' Anschluss an Mega128 über PORTD.4 für RxD und PORTD.5 für TxD.

' Achtung: Tracesausgaben zum PC erfolgen über SW-RS232. Die HW-RS232 wird zur
' Kommunikation mit dem RS485-Systembus als auch mit dem SCART-Funkinterface verwendet

' Öffnen eines Transmit-Kanals (#3) für Ausgaben
Open "comd.5:38400,8,n,1" For Output As #3

' Öffnen eines Receive-Kanals (#4) für Eingaben
Open "comd.4:38400,8,n,1" For Input As #4

' ggf. Traceausgaben ausgeben
#if Main_testmodus
   ' Systemstart auf RS232 ausgeben
   Print #3 , "** Iginiton sequence start **"
#endif

' ----- Konfiguration 1-Wire-Interface für Temperatursensor -----
Config 1wire = 1wire_port                                   ' Konfiguration 1-Wire-Interface

' ----- Konfiguration LCD Display -----
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.4 , Rs = Portc.5
Config Lcd = 16 * 3 , Chipset = Dogm163v5
Initlcd
Waitms 100
Cursor Off Noblink
Cls                                                         ' Clear Screen

' Definition benutzerdefinierter Zeichen
' Benutzerdefiniertes LCD-Zeichen Pfeil Hoch
Deflcdchar 1 , 4 , 14 , 31 , 21 , 4 , 4 , 4 , 32
' Benutzerdefiniertes LCD-Zeichen Pfeil Runter
Deflcdchar 2 , 4 , 4 , 4 , 21 , 31 , 14 , 4 , 32
' Benutzerdefiniertes LCD-Zeichen Pfeil Links
Deflcdchar 3 , 32 , 6 , 12 , 31 , 12 , 6 , 32 , 32
' Benutzerdefiniertes LCD-Zeichen Pfeil Rechts
Deflcdchar 4 , 32 , 12 , 6 , 31 , 6 , 12 , 32 , 32
' Benutzerdefiniertes LCD-Zeichen Enter
Deflcdchar 5 , 32 , 14 , 17 , 21 , 17 , 14 , 32 , 32

' Erstes Lebenszeichen Auf Display Schreiben
Lcd_light = Licht_ein                                       ' Hintergrundbeleuchtung einschalten
Locate 1 , 7 : Lcd "***"
Locate 2 , 5 : Lcd "StarLight"
Locate 3 , 7 : Lcd "***"

' ----- Konfiguration TWI-Interface für EEPROM -----
Config Sda = Sda_port
Config Scl = Scl_port

I2cinit                                                     ' we need to set the pins in the proper state

Config Twi = 400000                                         ' Taktfrequenz 400 kBaud
'Config Twi = 100000

' TWI gleich einschalten, das macht BASCOM ansonsten erst beim I2CStart
Twcr = &B00000100                                           ' nur TWEN setzen

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

' Konfiguration eines Timers für 1 Sekunden Timer-Tick (Scheduler und Alive)
Config Timer3 = Timer , Prescale = 256
On Timer3 Irq_sekunden_tick
Timer3 = Timervorgabe
Enable Timer3

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

' ----- LED-Konfigurationen -----
Config Alive_pin = Output                                   ' PIN auf Ausgang schalten
Config Temp_led_pin = Output                                ' PIN auf Ausgang schalten
Config Led_3 = Output                                       ' PIN auf Ausgang schalten

' ----- Sound-Konfiguration -----
Config Piezo_pin = Output                                   ' PIN auf Ausgang schalten

' ----- Hauptrelais -----
Config Relais_pin = Output                                  ' PIN auf Ausgang schalten

' ----- LCD-Display -----
Config Lcd_light_pin = Output                               ' PIN auf Ausgang schalten

' ----- SCART GPIO -----
Config Scart_pin = Output                                   ' PIN auf Ausgang schalten

' ----- Tastatur -----
Config Key_1_pin = Input                                    ' PIN auf Eingang schalten
Key_1 = Pullup_ein                                          ' Internen PullUp aktivieren

Config Key_2_pin = Input                                    ' PIN auf Eingang schalten
Key_2 = Pullup_ein                                          ' Internen PullUp aktivieren

Config Key_3_pin = Input                                    ' PIN auf Eingang schalten
Key_3 = Pullup_ein                                          ' Internen PullUp aktivieren

Config Key_4_pin = Input                                    ' PIN auf Eingang schalten
Key_4 = Pullup_ein                                          ' Internen PullUp aktivieren

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

' ----- LCD-Konfiguration -----
Kontrastwert = Lcd_kontrast_default                         ' Kontrastwert
Text(1) = "1234567890123456"                                ' Testtext 1
Text(2) = "ABCDEFGHIJKLMNOP"                                ' Testtext 2
Text(3) = "   Hallo Welt   "                                ' Testtext 3

' ----- Texte für Fehlermeldungen -----
'                 1234567890123456"
Error_msg_1(1) = "Scart-Adapter   "                         ' Fehlertext 1
Error_msg_2(1) = "antwortet nicht "

Error_msg_1(2) = "Uebertemperatur "                         ' Fehlertext 2
Error_msg_2(2) = "                "

Error_msg_1(3) = "RF Kommunikation"                         ' Fehlertext 3
Error_msg_2(3) = "fehlerhaft      "

Error_msg_1(4) = "Slave-Komm      "                         ' Fehlertext 4
Error_msg_2(4) = "fehlerhaft      "

Error_msg_1(5) = "CRC-Fehler auf  "                         ' Fehlertext 5
Error_msg_2(5) = "RS485 Systembus "

Error_msg_1(6) = "Slave(s) melden "                         ' Fehlertext 6
Error_msg_2(6) = "UeTemp xxxxxxxx "

Error_msg_1(7) = "CRC-Fehler bei  "                         ' Fehlertext 7
Error_msg_2(7) = "RF Kommunikation"

Error_msg_1(8) = "RK Anfrage SCART"                         ' Fehlertext 8
Error_msg_2(8) = "out of rangen   "

Error_msg_1(9) = "Empfangstimeout "                         ' Fehlertext 9
Error_msg_2(9) = "Buffer geloescht"

Error_msg_1(10) = "kein Fehler"                             ' Fehlertext 10 = Default
Error_msg_2(10) = "vorhanden"

Error_index = 10                                            ' Index auf kein Fehler
Error_show_flag = False                                     ' kein Fehler
Err_global_flag = False                                     ' kein Fehler

' ----- Globale Empfangs-Timeout-Überwachung -----
Receive_timeout_counter = 0                                 ' Counter auf NULL
Receive_timeout_flag = False                                ' Flag auf False

' ----- LED-Konfigurationen -----
Alive = Led_aus                                             ' Alive-LED aus
Temp_led = Led_aus                                          ' Übertemperatur LED aus
Led_3 = Led_aus                                             ' Reserve-LED aus

' ----- Sound-Konfiguration -----
Piezo = Sound_aus                                           ' Sound aus auf Port ausgeben

' ----- Hauptrelais -----
Anlagenflag = True                                          ' Anlage ist ein
Relais = Relais_aus                                         ' Relaissteuerung AUS
Lichtflag = Dauerlicht_ein                                  ' Dauerlicht bleibt zunächst EIN

' ----- SCART GPIO -----
Scart = Scart_aus                                           ' SCART aus

' ----- Globale Variable für SecTick Scheduler -----
Timercounter = 0                                            ' Sekunden-Counter auf 0 initialisieren

' ----- DS18S20 und Temperatur -----
Ds1820_temperatur = 0                                       ' Zunächst Temperatur auf NULL setzen
Flag_uebertemperatur = False                                ' Flag zur Steuerung des Übertemperatur-Handlings
Slave_temp_bitfeld = &B00000000                             ' Alle Bits NULL setzen

' ----- RS485 -----
' Sende- und Empfangsstrukturen initialisieren
Rx_bufferindex = 1                                          ' Index auf 1
Tx_bufferindex = 1                                          ' Index auf 1

Rs485_data_received = False                                 ' Receive-Status

' RS485 Empfangbuffer und Sendebuffer löschen
Clear Serialin                                              ' RxD
Clear Serialout                                             ' TxD

' ----- globales Fehlerhandling -----
Err_scart = False                                           ' Fehlervariable für SCART_Fehler initialisieren

' ----- SCART: Semaphoren für Empfang und Senden -----
Rf_data_received = False                                    ' Semaphore Daten Empfangen
Rf_send_request = False                                     ' Semaphore Daten senden

' ----- SCART Datenstrukturen -----
Rf_rx_bufferindex = 1                                       ' Bufferindex Empfangen
Rf_tx_bufferindex = 1                                       ' Bufferinde Senden
Rf_rx_errorflag = False                                     ' Globales Errorflag für Empfang
Rf_tx_errorflag = True                                      ' Globales Errorflag für Senden

' SCART Empfangsbuffer und Sendebuffer löschen
Clear Serialin1                                             ' RxD
Clear Serialout1                                            ' TxD

' Datenstrukturen in Arrays initialisieren
For Temp_byte_1 = 1 To 8

   ' ----- EEPROM -----
   ' Updatestruktur initialisieren
   Ee_dimmer_update(temp_byte_1) = False                    ' Wert auf False setzen = kein Update

   ' ----- Slave-Temperatur -----
   ' Datenstrukur initialisieren
   Slave_temperatur(temp_byte_1) = &H00                     ' Wert auf 0°C setzen

   ' ----- Fehler-Flags -----
   ' Datenstruktur initialisieren
   Error_flags(temp_byte_1) = False                         ' Wert auf False setzen

Next Temp_byte_1                                            ' Schleife über alle Felder des Arrays

' ----- MENUE: Strukturen und Variablen -----

' Tastencodes
Key_codes(1) = 1                                            ' Taste Hoch
Key_codes(2) = 2                                            ' Taste Runter
Key_codes(3) = 3                                            ' Taste Links
Key_codes(4) = 4                                            ' Taste Rechts
Key_keypressed = False                                      ' keine Taste betätigt

'Initial state variables
Menue_state = Loadlabel(men5)                               ' Startbildschirm

' ggf. Traces ausgeben
#if Menue_testmodus
   Print #3 , "MenueState : " ; Hex(menue_state)
#endif

Menue_state_renew = 1                                       ' Menüstatus wurde geändert
Key_taste = Key_null                                        ' keine Taste gedrückt

Menue_datenuebernahme_flag = 0                              ' Datenübernahmeflag initialisieren
Menue_data_changed_flag = 0                                 ' Flag ob sich Daten wirklich geändert haben
Menue_menueupdate_flag = 0                                  ' Flag für zyklisches Update Menüdaten

' Anmerkung: Mittels Menue_data_change_flag soll unnötiges Schreiben in das
'            EEPROM verhindert werden.

' ----- LCD:  LCD-Display -----
Lcd_screensaver = Lcd_screensaver_default                   ' Screensaver auf AUS setzen
Lcd_screensaver_aktiv = False                               ' Screensaver ist nicht aktiv

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

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

' ----- DS18S20: Konfiguration Temperatursensor -----
Gosub Ds1820_konfig                                         ' Konfiguration
Gosub Ds1820_start_measurement                              ' Erstmaliges Messen auslösen

' ----- Freigabe aller Interrupts ----
Enable Interrupts                                           ' freigeben

' ----- LCD-Display -----
Gosub Lcd_kontrastset                                       ' Kontrast einstellen

' ----- EEPROM -----
' Initialisierung des internen EEPROM aufrufen und ggf. Traces schreiben
Gosub Ee_init_internal_eeprom

' Initialisierung des externen EEPROM aufrufen und ggf. Traces schreiben
Gosub Ee_init_external_eeprom

' ---------------------------------- Systemtest -------------------------------

' Falls System_testmodus gesetzt ist wird kurzer System-Check durchlaufen.
' Alle relevanten Funktionen werden einmal angefahren und entsprechender Output
' auf der Trace-Schnittstelle wird erzeugt.
#if System_testmodus

   ' *** LCD-Display ***

   ' LCD Beleuchtung blinken
   For Temp_byte_1 = 1 To 3
      Gosub Lcd_beleuchtung_an
      Waitms Looptime                                       ' Wartezeit für Testschleifen
      Gosub Lcd_beleuchtung_aus
      Waitms Looptime                                       ' Wartezeit für Testschleifen
   Next Temp_byte_1
   Gosub Lcd_beleuchtung_an

   ' Testtext in Zeil 1 ausgeben
   Locate 1 , 1
   Lcd Text(1)
   Wait Texttime

   ' Display löschen
   Cls

   ' Testtext in Zeil 2 ausgeben
   Locate 2 , 1
   Lcd Text(2)
   Wait Texttime

   ' Display löschen
   Cls

   ' Testtext in Zeil 3 ausgeben
   Locate 3 , 1
   Lcd Text(3)
   Wait Texttime

   ' Display löschen
   Cls

   ' LCD Beleuchtung aus
   Gosub Lcd_beleuchtung_aus

   ' *** LED's ***

   ' LED's blinken lassen
   For Temp_byte_1 = 1 To 3
      Temp_led = Led_ein
      Led_3 = Led_ein
      Waitms Looptime                                       ' Wartezeit für Testschleifen
      Temp_led = Led_aus
      Led_3 = Led_aus
      Waitms Looptime                                       ' Wartezeit für Testschleifen
   Next Temp_byte_1

   ' *** Sound ***

   ' Piezo piepsen lassen
   For Temp_byte_1 = 1 To 3
      Piezo = Sound_ein
      Waitms Looptime
      Piezo = Sound_aus
      Waitms Looptime
   Next Temp_byte_1

   ' *** Hauptrelais ***

   ' Relais einschalten -> LED sollte leuchten und Durchgangsbeleuchtung geht aus
   ' => Hauptrelais für Duchgangsbeleuchtung wird unterbrochen
   Relais = Relais_ein
   Lichtflag = Dauerlicht_aus

   ' 2 Sekunden warten
   Wait 2

   ' Relais ausschalten -> LED sollte ausgehen und Dauerlicht geht wieder ein
   ' => Hauptrelais wird aktiv, Durchgangsbeleuchtung leuchtet
   Relais = Relais_aus
   Lichtflag = Dauerlicht_ein

   ' *** Temperatursensor ***

   Print #3 , "Funktion: 1Wire-Konfiguration auslesen und ausgeben"
   Gosub Ds1820_konfig_detect

   Print #3 , "Funktion: DS18S20 Teperaturmessung"

   ' Warten bis Temperatur konvertiert
   Waitms Ds1820_delay_time

   Gosub Ds1820_measurement

   Print #3 , "Gemessene Temperatur : " ; Ds1820_temperatur
   Print #3 , ""                                            ' Leerzeile ausgeben

   ' *** Tastaturtest ***
   Print #3 , "Key 1 betaetigen"

   ' Warte so lange bis Taste 1 betätigt
   Do
      ' Key-Pin einlesen
      Temp_byte_1 = Key_1_pin
   Loop Until Temp_byte_1 = 0

   Print #3 , "Key 2 betaetigen"

  ' Warte so lange bis Taste 2 betätigt
   Do
      ' Key-Pin einlesen
      Temp_byte_1 = Key_2_pin
   Loop Until Temp_byte_1 = 0

   Print #3 , "Key 3 betaetigen"

  ' Warte so lange bis Taste 3 betätigt
   Do
      ' Key-Pin einlesen
      Temp_byte_1 = Key_3_pin
   Loop Until Temp_byte_1 = 0

   Print #3 , "Key 2 betaetigen"

  ' Warte so lange bis Taste 4 betätigt
   Do
      ' Key-Pin einlesen
      Temp_byte_1 = Key_4_pin
   Loop Until Temp_byte_1 = 0

   Print #3 , "Key OK"

   ' *** RS485 Kommunikation ***

   ' Auf einen Test der RS485 Kommunikation wird verzichtet da er das Gesamtsystem
   ' durch unmotiviertes Senden von Bytes stören kann.

#endif                                                      ' Ende Systemtest

' ----- SCART initialisieren -----

' Variablen vorinitialisieren
Temp_byte_1 = Scart_max_loop_count                          ' Retry-Counter laden
Err_scart = False                                           ' Fehlerwert vorbesetzen
                                                            ' True = alles OK, False = Fehler

' Schleife solange bis Scart reagiert hat oder 3 Versuche durchgeführt wurden
Do
   Temp_byte_2 = Scart_init()                               ' Versuche Scart zu initialisieren
                                                            ' True = alles OK, False = Fehler
   ' ggf. Trace auf RS232 ausgeben
   #if Main_testmodus
      Print #3 , "Scart_init liefert : " ; Hex(temp_byte_2)
   #endif

   ' Prüfung ob Scart reagiert
   If Temp_byte_2 = False Then
      ' NEIN, dann Retry-Counter verringern

      ' ggf. Trace auf RS232 ausgeben
      #if Main_testmodus
         Print #3 , "Retry " ; Temp_byte_1
      #endif

      Decr Temp_byte_1
      ' Scart-Adapter nochmals abschalten und warten
      Scart = Scart_aus

      Waitms Scart_ping_delay                               ' nochmals warten
   Else
      ' JA, dann Fehler zurücksetzen und Abbruchbedingung setzen

      ' ggf. Trace auf RS232 ausgeben
      #if Main_testmodus
         Print #3 , "++ Alles Gut, SCART hat reagiert"
      #endif

      Err_scart = True                                      ' True = alles OK, False = Fehler
      Temp_byte_1 = 0

   End If                                                   ' Scart-Reaktion

Loop Until Temp_byte_1 = 0                                  ' Maximal 3 Wiederholungen

' Prüfen ob SCART-Problem vorhanden
If Err_scart = False Then                                   ' True = alles OK, False = Fehler
   ' JA

   ' ggf. Trace auf RS232 ausgeben
   #if Error_testmodus
      Print #3 , "[1] Error(1): SCART Fehler setzen"
   #endif

   ' ## Error ##
   ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
   Error_flags(1) = True                                    ' Fehler in Matrix eintragen
   Err_global_flag = True

End If                                                      ' SCART-Problem

' ----- Scheduler noch korrekt setzen und los -----

' Daten für Temperaturüberwachung setzen
Ds1820_erfassungs_counter = Timercounter + Ds1820_auswertung_start
Slave_temp_counter = Timercounter + Slave_temp_auswertung

' Daten für EEPROM-Daten speichern
Ee_update_counter = Timercounter + Ee_data_update_timer_value

' Daten für Menü-Update
Menue_update_counter = Timercounter + Menue_update_time

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

' Display löschen
Cls                                                         ' Clear Screen

' Display auf richtigen Bildschirm schalten
Gosub Menue_change_state_by_sub

' Abhängig von den Einstellung ggf. Screensaver starten
If Lcd_screensaver = True Then
   Lcd_screensaver_counter = Timercounter + Lcd_screensaver_delay
End If                                                      ' Screensaver

' Start auf jeden Fall auf RS 232 ausgeben
Print #3 , "** OK, let's GO **"

' ggf. Ausgabesound erzeugen
If Soundflag = Sound_ein Then

   ' Soundflag gesetzt, darum Beep ausgeben
   Gosub Sound_double_beep

End If                                                      ' Soundprüfung

' Gesamtsystem in LUM schalten
Temp_byte_1 = Rs485_last_used_mode()                        ' True = alles OK, False = Fehler

' Überprüfen ob LUM einen Fehler ausgelöst hat.
If Temp_byte_1 = False Then                                 ' True = alles OK, False = Fehler
   ' JA

   ' ggf. Trace auf RS232 ausgeben
   #if Error_testmodus
      Print #3 , "[2] Error(4): Fehler bei Ausführung von LUM"
   #endif

   ' ## Error ##
   ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
   Error_flags(4) = True                                    ' Fehler in Matrix eintragen
   Err_global_flag = True

End If                                                      ' LUM Fehler

' Globale Sound-Einstellungen laden / keine Überprüfung des Ergebnis wegen Broadcast
Temp_byte_1 = Rs485_sound_schalten(broadcastadresse , Soundflag)

' ggf. MCUCSR-Register ausgeben
#if Startupreset_testmodus
   Mcucsr_2 = Mcucsr                                        ' Mcucsr zum 2. Mal lesen
   Print #3 , "Mcucsr 1 : " ; Bin(mcucsr_1)
   Print #3 , "Mcucsr 2 : " ; Bin(mcucsr_2)
#endif

' Kontrolle noch für Dauerlicht auf Dimmer schalten
Relais = Relais_ein                                         ' Relaissteuerung ein
Lichtflag = Dauerlicht_aus                                  ' Dauerlicht aus

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

Do

   ' ----- SCART abfragen und verarbeiten -----
   Gosub Scart_receive_check

   ' Wurde ein gültiges Kommando empfangen?
   If Rf_data_received = True Then
      ' JA

      ' In Abhängigkeit der Konstante Traceausgabe schreiben
      #if Scart_testmodus
         Print #3 , "Mainloop - SCART-Datenpaket empfangen"
      #endif

      ' Datenpaket prozessieren
      Gosub Scart_verarbeitung

   End If                                                   ' Verarbeitung

   ' ----- Tastatur abfragen und auswerten -----
   '
   ' +---+     +---+     +---+     +---+
   ' | 1 |SW1  | 2 |SW2  | 3 |SW3  | 4 |SW4
   ' +---+     +---+     +---+     +---+

   Debounce Key_1_pin , 0 , Key_handle_key_1 , Sub
   Debounce Key_2_pin , 0 , Key_handle_key_2 , Sub
   Debounce Key_3_pin , 0 , Key_handle_key_3 , Sub
   Debounce Key_4_pin , 0 , Key_handle_key_4 , Sub

   ' Prüfen ob Taste betätigt wurde
   If Key_keypressed = True Then
      ' JA

      ' ggf. Ausgabesound erzeugen
      If Soundflag = Sound_ein Then

         ' Soundflag gesetzt, darum Beep ausgeben
         Gosub Sound_one_beep
      End If                                                ' Soundprüfung

      ' Prüfung ob aktuell Screensaver aktiv
      If Lcd_screensaver = True Then
         ' JA, Screensaver ist eingeschaltet

         ' Zunächste Zeitintervall neu setzen
         Lcd_screensaver_counter = Timercounter + Lcd_screensaver_delay

         ' Prüfen ob Screensaver aktiv oder nicht
         If Lcd_screensaver_aktiv = True Then
            ' JA, Screensaver ist aktiv

            ' Ggf. Trace ausgeben
            #if Screensaver_testmodus                       ' Trace
               Print #3 , "Mainloop: Screensaver wird passiv"
            #endif                                          ' Trace

            ' Taste ignorieren, zunächste Display einschalten
            Key_taste = 0

            ' Screensaver deaktivieren
            Lcd_screensaver_aktiv = False

            ' Display einschalten
            Gosub Lcd_display_an
            ' LCD Beleuchtung ein
            Gosub Lcd_beleuchtung_an

         End If                                             ' Screensaver aktiv
      End If                                                ' Screensaver eingeschaltet

      ' Wenn Taste noch nicht durch SleepMode abgefangen dann Menü
      If Key_taste <> 0 Then
         ' JA

         ' Tasten für spätere Auswertung buffern
         Key_taste_buffer = Key_taste                       ' Taste buffern

         'Menüeintrag und Tastencodes finden und ggf. State wechseln
         'hier nur Tastendruck auswerten
         Gosub Menue_change_state

         'Pointer nach Statuswechsel neu setzen
         If Menue_state_renew = 1 Then
            Gosub Menue_change_state
         End If                                             ' Menü-Update angefordert

         ' Bereits schon LCD refresh auslösen bevor Unterprogramm angesprungen
         ' wird da im unterprogramm ggf. noch Inhalte ergänzt werden.
         If Menue_state_renew = 1 Then
            Menue_state_renew = 0
            Gosub Lcd_print
         End If                                             ' Erneutes Menü-Update prüfen

         'Unterprogramm des aktuellen State anspringen
         Gosub Menue_call_subroutine

      End If                                                ' Taste noch aktiv

      ' globales Flag für Signalisierung zurücksetzen da Auswertung jetzt durchgeführt
      Key_keypressed = False
   End If                                                   ' Taste betätigt

   ' Nochmals LCD refresh falls Menü von außen verändert
   If Menue_state_renew = 1 Then
      Menue_state_renew = 0
      Gosub Lcd_print
   End If                                                   ' Menü-Update angefordert

   ' ===== SW Timer Scheduler =====
   Gosub Scheduler

Loop

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

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

'------------------------------------------------------------------------------
' Interrupt-Service-Routine (Timer3): Irq_sekunden_tick
' Routine zur Auswertung des Timer Interrupts und zur Erzeugung des Sekunden-
' takts.
'------------------------------------------------------------------------------

Irq_sekunden_tick:

   Incr Timercounter                                        ' Timercounter erhöhen
   Timer3 = Timervorgabe                                    ' Timer neu laden

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Timer_testmodus
      Print #3 , Timercounter
   #endif

   ' Alive-LED toggeln lassen
   Toggle Alive

   ' Prüfen ob Übertemperatur vorliegt
   ' ## Error ##
   If Flag_uebertemperatur = True Then
      ' JA -> Übertemperatur -> dann piepsen
      Toggle Piezo
      Toggle Temp_led
   End If                                                   ' Übertemperatur

   ' Prüfung ob globaler Fehler
   ' ## Error ##
   If Err_global_flag = True Then
      ' JA -> LED toggeln
      Toggle Led_3
   End If                                                   ' Übertemperatur

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

'******************************************************************************
' Funktionen
'******************************************************************************

' *********
' * SCART *
' *********

'------------------------------------------------------------------------------
' Function: Scart_init
' Funktion initialisiert das SCART-Interface und liefert Ergebnis zurück, on
' Initialisierung erfolgreich war oder nicht.
'
' Parameter:    keiner
'
' Rückgabewert: TRUE  = SCART ist initialisiert bzw. vorhanden und reagiert
'               FALSE = Es ist ein Fehler aufgetreten und SCART reagiert nicht
'------------------------------------------------------------------------------
Function Scart_init() As Byte

   ' ----- lokale Variablen -----
   Local Help_byte_1 As Byte
   Local Result_byte As Byte
   Result_byte = False

   Local Loop_counter As Byte
   Loop_counter = 0

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

   ' ggf. Traceoutput schreiben
   #if Scart_testmodus
      Print #3 , ""                                         ' Leerzeile
      Print #3 , "Scart_init: Enter Funktion Scart_init()"
   #endif

   ' Notwendige Dateninhalte in Sendeframe welche sich nie ändern initialisieren
   ' 0x01 <n> <data_1> ... <data_n>          transmitt n Bytes (n<=61)
   Rf_tx_paket_type = Rf_cmd_scart_send                     ' 0x01     - Immer 0x01
   Rf_tx_frame_len = Rf_tx_protokolllaenge                  ' <n>      - Definition über Konstante, aktuell 10
   Rf_tx_framelength = Rf_tx_framelaenge                    ' <data_1> - Definition über Konstante, aktuell 5

   ' Scart-Adapter einschalten
   Scart = Scart_ein

   Waitms Wait_scart_switch_on

   ' Zunächst Empfangsbuffer von SCART-Adapter löschen
   Clear Serialin1

   ' ===== Daten senden =====

   Do
      ' Loop-Counter erhöhen
      Incr Loop_counter

      ' ggf. Traceoutput schreiben
      #if Scart_testmodus
         Print #3 , "Scart_init: Sende Anfrage " ; Loop_counter
      #endif

      ' Nun PING in Form eines NOP an SCART-Adapter senden
      Printbin #2 , Scart_cmd_nop;

      ' Warte Zeit X auf SCART
      ' Waitms Scart_ping_delay ' Schlechte Lösung

      ' Besser ist es über Timer gesteuert zu warten und ggf. abzubrechen.
      Scart_antwort_counter = Timercounter + Scart_counter_delay

      Do
         ' Bufferstatus der RS232 Kanal 2 lesen
         Serialcharwaiting = Ischarwaiting(#2)              'Check if B or b pressed then goto

         ' Wiedehole Scheife solange bis Überwachungscounter abgelaufen oder Antwort von SCAR erhalten

      Loop Until Serialcharwaiting = 1 Or Timercounter >= Scart_antwort_counter       ' Überwachungscounter

      ' ggf. Traceouput schreiben
      #if Scart_tx_testmodus
         If Serialcharwaiting <> 1 Then
            Print #3 , "Scart_init: LOOP durch Timeout verlassen"
         End If                                             ' kein Zeichen empfangen
      #endif

   ' Wiederhole die Schleife solange bis SCART geantwortet hat oder 3 Retries gemacht wurden
   Loop Until Loop_counter >= Scart_max_loop_count Or Serialcharwaiting = 1       ' Ende Retrie oder Antwort

   ' ggf. Traceouput schreiben
   #if Scart_tx_testmodus
      If Serialcharwaiting <> 1 Then
         Print #3 , "Scart_init: LOOP nach Retries durch Timeout verlassen"
      End If                                                ' kein Zeichen empfangen
   #endif

   ' ===== READY empfangen / warten =====

   ' Prüfen ob Zeichen in Buffer wartet
   If Serialcharwaiting = 1 Then
      ' JA, es wartet ein Zeichen im Buffer und Routine wurde nicht durch Retrie abgebrochen

      ' Einlesen des ersten Zeichens im Buffer
      Help_byte_1 = Inkey(#2)

      ' ggf. Zeichen auf RS232 Kanal 1 ausgeben
      #if Scart_testmodus
         Print #3 , "Scart_init: Empfangen : " ; Hex(help_byte_1);
      #endif

      ' Prüfen ob empfangenes Byte READY war
      If Help_byte_1 = Scart_return_ready Then
         'JA, empfangenes Byte war Ready

         ' Result_byte auf TRUE setzen
         Result_byte = True

      End If                                                ' Prüfung auf Ready
   End If                                                   ' Zeichen im Buffer?

   #if Scart_testmodus
      Print #3 , ""
      Print #3 , "Scart_init: Schleife mit Zähler " ; Loop_counter ; " verlassen"
   #endif

   ' Ergebnis and Rückgabeparameter übergeben
   Scart_init = Result_byte

End Function
'-- End Scart_init ------------------------------------------------------------

'------------------------------------------------------------------------------
' Function: Scart_send
' Funktion sendet einen Datenframe über SCART an die Betty.
'
' Parameter:    Resp_code = Antwort-Kommando
'               Dimmer    = Für welchen Slave/Dimmer Antwort erfolgt
'
' Rückgabewert: TRUE  = Funktion erfolgreich
'               FALSE = Es ist ein Fehler aufgetreten
'------------------------------------------------------------------------------
Function Scart_send(byval Resp_code As Byte , Byval Dimmer As Byte) As Byte

   ' ----- lokale Variablen -----
   Local Help_byte_1 As Byte
   Local Result_byte As Byte
   Result_byte = False

   Local Loop_counter As Byte
   Loop_counter = 0

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

   ' ggf. Traceoutput schreiben
   #if Scart_tx_testmodus
      Print #3 , ""                                         ' Leerzeile
      Print #3 , "Scart_send: Enter Funktion Scart_send()"
   #endif

   ' Zunächst Empfangsbuffer von SCART-Adapter löschen
   Clear Serialin1

   ' Response-Code setzen
   Rf_tx_kommando = Resp_code

   ' [1] Paket-Typ-Kennzeichnung für SCART-Adapter (Header)
   ' [2] Daten-Paket-größe für SCART-Adapter (Header)
   ' [3] Senderichtung: Nachrichtenlänge
   ' [4] Senderichtung: Kommando
   ' [5] Senderichtung: Dimmerstatus
   ' [6] Senderichtung: Dimmwert
   ' [7] Senderichtung: Temperatur des Slave
   ' [8] Senderichtung. Sound
   ' [9] Senderichtung: Checksumme

   ' Position in Datenstruktur für Dimmerstatus und Dimmwert berechnen und

   ' Bemerkung: Indexrechnung zur Verdeutlichung
   '  Index Bedeutung   Dimmer   Berechnung
   '  1     Status      1        Dimmer * 2 - 1 = 1 * 2 - 1 = 1
   '  2     Dimmwert    1        Dimmer * 2     = 1 * 2     = 2
   '  3     Status      2        Dimmer * 2 - 1 = 2 * 2 - 1 = 3
   '  4     Dimmwert    2        Dimmer * 2     = 2 * 2     = 4
   '  5     Status      3        Dimmer * 2 - 1 = 3 * 2 - 1 = 5
   '  6     Dimmwert    3        Dimmer * 2     = 3 * 2     = 6
   '  7     Status      4        Dimmer * 2 - 1 = 4 * 2 - 1 = 7
   '  8     Dimmwert    4        Dimmer * 2     = 4 * 2     = 8
   '  9     Status      5        Dimmer * 2 - 1 = 5 * 2 - 1 = 9
   ' 10     Dimmwert    5        Dimmer * 2     = 5 * 2     = 10
   ' 11     Status      6        Dimmer * 2 - 1 = 6 * 2 - 1 = 11
   ' 12     Dimmwert    6        Dimmer * 2     = 6 * 2     = 12
   ' 13     Status      7        Dimmer * 2 - 1 = 7 * 2 - 1 = 13
   ' 14     Dimmwert    7        Dimmer * 2     = 7 * 2     = 14
   ' 15     Status      8        Dimmer * 2 - 1 = 8 * 2 - 1 = 15
   ' 16     Dimmwert    8        Dimmer * 2     = 8 * 2     = 16

   ' Daten in Sendestruktur laden
   Help_byte_1 = Dimmer * 2
   Rf_tx_dimmwert = Ee_data_lightning_struct(help_byte_1 )

   #if Ee_data_indizierung_testmodus
      Print #3 , "[1] Rf_tx_dimmwert Ee_data_lightning_struct " ; Help_byte_1 ; " = " ; Rf_tx_dimmwert
   #endif

   Decr Help_byte_1
   Rf_tx_dimmer = Ee_data_lightning_struct(help_byte_1 )

   #if Ee_data_indizierung_testmodus
      Print #3 , "[2] Rf_tx_dimmer Ee_data_lightning_struct " ; Help_byte_1 ; " = " ; Rf_tx_dimmer
   #endif

   ' Temperatur laden
   Rf_tx_temperatur = Slave_temperatur(dimmer )

   ' Soundflag laden
   Rf_tx_sound = Soundflag

   ' CRC berechnen
   Rf_tx_checksumme = Crc16(rf_tx_buffer(3) , 6)

   ' ggf. Traceouput schreiben
   #if Scart_tx_testmodus
      Print #3 , "Rf_tx_dimmwert  : " ; Hex(rf_tx_dimmwert)
      Print #3 , "Rf_tx_dimmer    : " ; Hex(rf_tx_dimmer)
      Print #3 , "Rf_tx_temperatur: " ; Hex(rf_tx_temperatur)
      Print #3 , "Rf_tx_sound     : " ; Hex(rf_tx_sound)
      Print #3 , "Rf_tx_checksumme: " ; Hex(rf_tx_checksumme)
   #endif

   ' ggf. Trache schreiben
   #if Scart_tx_testmodus
      Print #3 , "Scart_send: TX: "
      For Help_byte_1 = 1 To Rf_tx_nachrichtenlaenge Step 1
         Print #3 , Hex(rf_tx_buffer(help_byte_1));
      Next Help_byte_1
      Print #3 , ""                                         ' Leerzeile
   #endif

   ' ===== Daten senden =====

   Do
      ' Loop-Counter erhöhen
      Incr Loop_counter

      ' ggf. Traceoutput schreiben
      #if Scart_tx_testmodus
         Print #3 , "Scart_send: Datenframe Sendung " ; Loop_counter
      #endif

      ' Nun Byte-Array an SCART-Adapter senden
      Printbin #2 , Rf_tx_buffer(1)

      ' Warte Zeit X auf SCART - Antwort !! Uneffizient da System solange wartet
      ' Waitms Scart_processing_time

      ' Besser ist es über Timer gesteuert zu warten und ggf. abzubrechen.
      Scart_antwort_counter = Timercounter + Scart_counter_delay

      Do
         ' Bufferstatus der RS232 Kanal 2 lesen
         Serialcharwaiting = Ischarwaiting(#2)              'Check ob Zeichen im Empfangsbuffer

         ' Wiedehole Scheife solange bis Überwachungscounter abgelaufen oder Antwort von SCAR erhalten

      Loop Until Serialcharwaiting = 1 Or Timercounter >= Scart_antwort_counter       ' Überwachungscounter

      ' ggf. Traceouput schreiben
      #if Scart_tx_testmodus
         If Serialcharwaiting <> 1 Then
            Print #3 , "Scart_send: LOOP durch Timeout verlassen"
         End If                                             ' kein Zeichen empfangen
      #endif

   ' Wiederhole die Schleife solange bis SCART geantwortet hat oder 3 Retries gemacht wurden
   Loop Until Loop_counter > Scart_max_loop_count Or Serialcharwaiting = 1       ' Ende Treies oder Antwort

   ' ggf. Traceouput schreiben
   #if Scart_tx_testmodus
      If Serialcharwaiting <> 1 Then
         Print #3 , "Scart_send: LOOP nach Retries durch Timeout verlassen"
      End If                                                ' kein Zeichen empfangen
   #endif

   ' ===== READY empfangen / warten =====

   ' Prüfen ob Zeichen in Buffer wartet
   If Serialcharwaiting = 1 Then
      ' JA, es wartet ein Zeichen im Buffer und Routine wurde nicht durch Retrie abgebrochen

      ' Einlesen des ersten Zeichens im Buffer -> Zeichen MUSS READY sein!!
      Help_byte_1 = Inkey(#2)

      ' ggf. Zeichen auf RS232 Kanal 1 ausgeben
      #if Scart_tx_testmodus
         Print #3 , "Scart_send: Empfangen : " ; Hex(help_byte_1);
      #endif

      ' Prüfen ob empfangenes Byte READY war
      If Help_byte_1 = Scart_return_ready Then
         'JA, empfangenes Byte war Ready

         ' Result_byte auf TRUE setzen
         Result_byte = True

      End If                                                ' Prüfung auf Ready
   End If                                                   ' Zeichen im Buffer?

   #if Scart_tx_testmodus
      Print #3 , ""
      Print #3 , "Scart_send: Schleife mit Zähler " ; Loop_counter ; " verlassen"
   #endif

   ' Ergebnis and Rückgabeparameter übergeben
   Scart_send = Result_byte

End Function
'-- End Scart_send ------------------------------------------------------------

'------------------------------------------------------------------------------
' Function: Scart_ack_send
' Funktion sendet einen Datenframe über SCART an die Betty.
'
' Parameter:    Ack_type = 0 bedeutet Anlage ausgeschaltet
'                          1 bedeutet Anlage eingeschaltet
'
' Rückgabewert: TRUE  = Funktion erfolgreich
'------------------------------------------------------------------------------
Function Scart_ack_send(byval Ack_type As Byte ) As Byte

   ' ----- lokale Variablen -----
   Local Help_byte_1 As Byte
   Local Result_byte As Byte
   Result_byte = False

   Local Loop_counter As Byte
   Loop_counter = 0

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

   ' ggf. Traceoutput schreiben
   #if Scart_tx_testmodus
      Print #3 , ""                                         ' Leerzeile
      Print #3 , "Scart_ack_send: Enter Funktion Scart_ack_send()"
      Print #3 , "Ack_type = " ; Ack_type
   #endif

   ' Zunächst Empfangsbuffer und Sendevuffer löschen
   Clear Serialin1
   Clear Serialout1

   ' Response-Code setzen
   Rf_tx_kommando = Rf_resp_ack                             ' &HFF

   ' Datenstruktur laden
   Rf_tx_dimmer = Ack_type
   Rf_tx_dimmwert = Undefined
   Rf_tx_temperatur = Uebertemperatur                       ' In ACK wird Übertemperaturwert an Betty übertragen
   Rf_tx_sound = Soundflag                                  ' In ACK wird Soundflag an Betty übertragen

   ' CRC berechnen
   Rf_tx_checksumme = Crc16(rf_tx_buffer(3) , 6)

   ' ggf. Trache schreiben
   #if Scart_tx_testmodus
      Print #3 , ""                                         ' Leerzeile
      Print #3 , "Scart_send: TX: "
      For Help_byte_1 = 1 To Rf_tx_nachrichtenlaenge Step 1
         Print #3 , Hex(rf_tx_buffer(help_byte_1)) ;
      Next Help_byte_1
      Print #3 , ""                                         ' Leerzeile
   #endif

   ' ===== Daten senden =====

   Do
      ' Loop-Counter erhöhen
      Incr Loop_counter

      ' ggf. Traceoutput schreiben
      #if Scart_tx_testmodus
         Print #3 , "Scart_ack_send: Datenframe Sendung " ; Loop_counter
      #endif

      ' Nun Byte-Array an SCART-Adapter senden
      Printbin #2 , Rf_tx_buffer(1)

      ' Warte Zeit X auf SCART - Antwort !! Uneffizient da System solange wartet
      ' Waitms Scart_processing_time

      ' Besser ist es über Timer gesteuert zu warten und ggf. abzubrechen.
      Scart_antwort_counter = Timercounter + Scart_counter_delay

      Do
         ' Bufferstatus der RS232 Kanal 2 lesen
         Serialcharwaiting = Ischarwaiting(#2)              'Check ob Zeichen im Empfangsbuffer

         ' Wiedehole Scheife solange bis Überwachungscounter abgelaufen oder Antwort von SCAR erhalten

      Loop Until Serialcharwaiting = 1 Or Timercounter >= Scart_antwort_counter       ' Überwachungscounter

      ' ggf. Traceouput schreiben
      #if Scart_tx_testmodus
         If Serialcharwaiting <> 1 Then
            Print #3 , "Scart_ack_send: LOOP durch Timeout verlassen"
         End If                                             ' kein Zeichen empfangen
      #endif

   ' Wiederhole die Schleife solange bis SCART geantwortet hat oder 3 Retries gemacht wurden
   Loop Until Loop_counter > Scart_max_loop_count Or Serialcharwaiting = 1       ' Ende Retries oder Antwort

   ' ggf. Traceouput schreiben
   #if Scart_tx_testmodus
      If Serialcharwaiting <> 1 Then
         Print #3 , "Scart_ack_send: LOOP nach Retries durch Timeout verlassen"
      End If                                                ' kein Zeichen empfangen
   #endif

   ' ===== READY empfangen / warten =====

   ' Prüfen ob Zeichen in Buffer wartet
   If Serialcharwaiting = 1 Then
      ' JA, es wartet ein Zeichen im Buffer und Routine wurde nicht durch Retrie abgebrochen

      ' Einlesen des ersten Zeichens im Buffer -> Zeichen MUSS READY sein!!
      Help_byte_1 = Inkey(#2)

      ' ggf. Zeichen auf RS232 Kanal 1 ausgeben
      #if Scart_tx_testmodus
         Print #3 , "Scart_ack_send: Empfangen : " ; Hex(help_byte_1);
      #endif

      ' Prüfen ob empfangenes Byte READY war
      If Help_byte_1 = Scart_return_ready Then
         'JA, empfangenes Byte war Ready

         ' Result_byte auf TRUE setzen
         Result_byte = True

      End If                                                ' Prüfung auf Ready
   End If                                                   ' Zeichen im Buffer?

   #if Scart_tx_testmodus
      Print #3 , ""
      Print #3 , "Scart_ack_send: Schleife mit Zähler " ; Loop_counter ; " verlassen"
   #endif

   ' Ergebnis and Rückgabeparameter übergeben
   Scart_ack_send = Result_byte

End Function
'-- End Scart_ack_send ------------------------------------------------------------

' *********
' * RS485 *
' *********

'------------------------------------------------------------------------------
' Rs485 - Funktion: Rs485_last_used_mode()
' Funktion sendet Licht, Dimmwert und Sound-Status an alle Slaves zur
' Einstellung z.B. bei Systemstart
'
' Parameter:     keiner
'
' Rückgabewert:  Bytevariable
'                TRUE  = Slaves haben geantwortet bzw. Ausführung OK
'                FALSE = Es ist ein Fehler aufgetreten
'
'------------------------------------------------------------------------------
Function Rs485_last_used_mode() As Byte

   ' ----- Lokale Variable definieren -----
   Local Result_byte As Byte
   Result_byte = True

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

   ' Anmerkung:
   ' LUM für alle 8 Dimmer könnte auch über FOR-Schleife realisiert werden.
   ' Es müssen die Adressen des Ziels und die Parameter für Dimmerstatus und
   ' Dimmerstufe richtig gesetzt werden.
   ' Um nicht rechnen zu müssen oder mit Select Case zu arbeiten wird auf
   ' high-end Programmierung verzichtet und die Sequenz wir sequentiell
   ' herunterprogrammiert.

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_last_used_mode"
   #endif

   ' === Dimmer 1 ===

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , " "
      Print #3 , "Rs485_last_used_mode: Dimmer 1"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave_1_adresse                         ' Adresse des Slave
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_licht_dimmer_schalten                  ' Kommando Licht schalten
   Tx_licht = Ee_data_mod1_light                            ' Dimmerstatus
   Tx_dimmstufe = Ee_data_mod1_dimm                         ' Dimmwert
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Soundflag                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Überwachungstimer aufziehen
   Rs485_receive_timer = Timercounter + Rs485_answer_timeout

   Do
      ' Auf Empfang prüfen
      Gosub Rs485_receive_check

      ' Wiederhole Schleife solange bis Counter abgelaufen oder Botschaft empfangen

   Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Rs485_last_used_mode: LOOP ende"
   #endif

   ' Prüfen ob ein Datenpaket empfangen wurde
   If Rs485_data_received = True Then
      ' JA, Datenpaket prozessieren und prüfen ob korrekte Antwrot vom Slave

      ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
      If Rx_kommando = Resp_ack And Rx_quelladresse = Slave_1_adresse Then
         ' JA, dann alles OK, zusätzliche Daten übernehmen

         ' Temperatur übernehmen
         Slave_temperatur(1) = Rx_temperatur

      Else                                                  ' Acknowledge
         ' ggf. Trace schreiben
         #if Rs485_testmodus
            Print #3 , "Rs485_last_used_mode: Dimmer 1 Daten im Frame falsch"
         #endif
         Result_byte = False                                ' Ergebnis setzen
      End If                                                ' Fehlerbehandlung
   Else                                                     ' Datenpaket empfangen
      ' ggf. Trace schreiben
      #if Rs485_testmodus
         Print #3 , "Rs485_last_used_mode: Dimmer 1 Timeout"
      #endif
      Result_byte = False                                   ' Ergebnis setzen
   End If                                                   ' Fehlerbehandlung

   ' Receiver zurücksetzen
   Rs485_data_received = False

   ' === Dimmer 2 ===

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , " "
      Print #3 , "Rs485_last_used_mode: Dimmer 2"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave_2_adresse                         ' Adresse des Slave
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_licht_dimmer_schalten                  ' Kommando Licht schalten
   Tx_licht = Ee_data_mod2_light                            ' Dimmerstatus
   Tx_dimmstufe = Ee_data_mod2_dimm                         ' Dimmwert
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Soundflag                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Überwachungstimer aufziehen
   Rs485_receive_timer = Timercounter + Rs485_answer_timeout

   Do
      ' Auf Empfang prüfen
      Gosub Rs485_receive_check

      ' Wiederhole Schleife solange bis Counter abgelaufen oder Botschaft empfangen

   Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Rs485_last_used_mode: LOOP ende"
   #endif

   ' Prüfen ob ein Datenpaket empfangen wurde
   If Rs485_data_received = True Then
      ' JA, Datenpaket prozessieren und prüfen ob korrekte Antwrot vom Slave

      ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
      If Rx_kommando = Resp_ack And Rx_quelladresse = Slave_2_adresse Then
         ' JA, dann alles OK, zusätzliche Daten übernehmen

         ' Temperatur übernehmen
         Slave_temperatur(2) = Rx_temperatur

      Else                                                  ' Acknowledge
         ' ggf. Trace schreiben
         #if Rs485_testmodus
            Print #3 , "Rs485_last_used_mode: Dimmer 2 Daten im Frame falsch"
         #endif
         Result_byte = False                                ' Ergebnis setzen
      End If                                                ' Fehlerbehandlung
   Else                                                     ' Daten empfangen
      ' ggf. Trace schreiben
      #if Rs485_testmodus
         Print #3 , "Rs485_last_used_mode: Dimmer 2 Timeout"
      #endif
      Result_byte = False                                   ' Ergebnis setzen
   End If                                                   ' Fehlerbehandlung

   ' Receiver zurücksetzen
   Rs485_data_received = False

   ' === Dimmer 3 ===

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , " "
      Print #3 , "Rs485_last_used_mode: Dimmer 3"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave_3_adresse                         ' Adresse des Slave
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_licht_dimmer_schalten                  ' Kommando Licht schalten
   Tx_licht = Ee_data_mod3_light                            ' Dimmerstatus
   Tx_dimmstufe = Ee_data_mod3_dimm                         ' Dimmwert
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Soundflag                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Überwachungstimer aufziehen
   Rs485_receive_timer = Timercounter + Rs485_answer_timeout

   Do
      ' Auf Empfang prüfen
      Gosub Rs485_receive_check

      ' Wiederhole Schleife solange bis Counter abgelaufen oder Botschaft empfangen

   Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Rs485_last_used_mode: LOOP ende"
   #endif

   ' Prüfen ob ein Datenpaket empfangen wurde
   If Rs485_data_received = True Then
      ' JA, Datenpaket prozessieren und prüfen ob korrekte Antwrot vom Slave

      ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
      If Rx_kommando = Resp_ack And Rx_quelladresse = Slave_3_adresse Then
         ' JA, dann alles OK, zusätzliche Daten übernehmen

         ' Temperatur übernehmen
         Slave_temperatur(3) = Rx_temperatur

      Else                                                  ' Acknowledge
         ' ggf. Trace schreiben
         #if Rs485_testmodus
            Print #3 , "Rs485_last_used_mode: Dimmer 3 Daten im Frame falsch"
         #endif
         Result_byte = False                                ' Ergebnis setzen
      End If                                                ' Fehlerbehandlung
   Else                                                     ' Daten empfangen
      ' ggf. Trace schreiben
      #if Rs485_testmodus
         Print #3 , "Rs485_last_used_mode: Dimmer 3 Timeout"
      #endif
      Result_byte = False                                   ' Ergebnis setzen
   End If                                                   ' Fehlerbehandlung

   ' Receiver zurücksetzen
   Rs485_data_received = False

   ' === Dimmer 4 ===

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , " "
      Print #3 , "Rs485_last_used_mode: Dimmer 4"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave_4_adresse                         ' Adresse des Slave
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_licht_dimmer_schalten                  ' Kommando Licht schalten
   Tx_licht = Ee_data_mod4_light                            ' Dimmerstatus
   Tx_dimmstufe = Ee_data_mod4_dimm                         ' Dimmwert
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Soundflag                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Überwachungstimer aufziehen
   Rs485_receive_timer = Timercounter + Rs485_answer_timeout

   Do
      ' Auf Empfang prüfen
      Gosub Rs485_receive_check

      ' Wiederhole Schleife solange bis Counter abgelaufen oder Botschaft empfangen

   Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Rs485_last_used_mode: LOOP ende"
   #endif

   ' Prüfen ob ein Datenpaket empfangen wurde
   If Rs485_data_received = True Then
      ' JA, Datenpaket prozessieren und prüfen ob korrekte Antwrot vom Slave

      ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
      If Rx_kommando = Resp_ack And Rx_quelladresse = Slave_4_adresse Then
         ' JA, dann alles OK, zusätzliche Daten übernehmen

         ' Temperatur übernehmen
         Slave_temperatur(4) = Rx_temperatur

      Else                                                  ' Acknowledge
         ' ggf. Trace schreiben
         #if Rs485_testmodus
            Print #3 , "Rs485_last_used_mode: Dimmer 4 Daten im Frame falsch"
         #endif
         Result_byte = False                                ' Ergebnis setzen
      End If                                                ' Fehlerbehandlung
   Else                                                     ' Daten empfangen
      ' ggf. Trace schreiben
      #if Rs485_testmodus
         Print #3 , "Rs485_last_used_mode: Dimmer 4 Timeout"
      #endif
      Result_byte = False                                   ' Ergebnis setzen
   End If                                                   ' Fehlerbehandlung

   ' Receiver zurücksetzen
   Rs485_data_received = False

   ' === Dimmer 5 ===

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , " "
      Print #3 , "Rs485_last_used_mode: Dimmer 5"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave_5_adresse                         ' Adresse des Slave
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_licht_dimmer_schalten                  ' Kommando Licht schalten
   Tx_licht = Ee_data_mod5_light                            ' Dimmerstatus
   Tx_dimmstufe = Ee_data_mod5_dimm                         ' Dimmwert
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Soundflag                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Überwachungstimer aufziehen
   Rs485_receive_timer = Timercounter + Rs485_answer_timeout

   Do
      ' Auf Empfang prüfen
      Gosub Rs485_receive_check

      ' Wiederhole Schleife solange bis Counter abgelaufen oder Botschaft empfangen

   Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Rs485_last_used_mode: LOOP ende"
   #endif

   ' Prüfen ob ein Datenpaket empfangen wurde
   If Rs485_data_received = True Then
      ' JA, Datenpaket prozessieren und prüfen ob korrekte Antwrot vom Slave

      ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
      If Rx_kommando = Resp_ack And Rx_quelladresse = Slave_5_adresse Then
         ' JA, dann alles OK, zusätzliche Daten übernehmen

         ' Temperatur übernehmen
         Slave_temperatur(5) = Rx_temperatur

      Else                                                  ' Acknowledge
         ' ggf. Trace schreiben
         #if Rs485_testmodus
            Print #3 , "Rs485_last_used_mode: Dimmer 5 Daten im Frame falsch"
         #endif
         Result_byte = False                                ' Ergebnis setzen
      End If                                                ' Fehlerbehandlung
   Else                                                     ' Daten empfangen
      ' ggf. Trace schreiben
      #if Rs485_testmodus
         Print #3 , "Rs485_last_used_mode: Dimmer 5 Timeout"
      #endif
      Result_byte = False                                   ' Ergebnis setzen
   End If                                                   ' Fehlerbehandlung

   ' Receiver zurücksetzen
   Rs485_data_received = False

   ' === Dimmer 6 ===

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , " "
      Print #3 , "Rs485_last_used_mode: Dimmer 6"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave_6_adresse                         ' Adresse des Slave
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_licht_dimmer_schalten                  ' Kommando Licht schalten
   Tx_licht = Ee_data_mod6_light                            ' Dimmerstatus
   Tx_dimmstufe = Ee_data_mod6_dimm                         ' Dimmwert
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Soundflag                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Überwachungstimer aufziehen
   Rs485_receive_timer = Timercounter + Rs485_answer_timeout

   Do
      ' Auf Empfang prüfen
      Gosub Rs485_receive_check

      ' Wiederhole Schleife solange bis Counter abgelaufen oder Botschaft empfangen

   Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Rs485_last_used_mode: LOOP ende"
   #endif

   ' Prüfen ob ein Datenpaket empfangen wurde
   If Rs485_data_received = True Then
      ' JA, Datenpaket prozessieren und prüfen ob korrekte Antwrot vom Slave

      ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
      If Rx_kommando = Resp_ack And Rx_quelladresse = Slave_6_adresse Then
         ' JA, dann alles OK, zusätzliche Daten übernehmen

         ' Temperatur übernehmen
         Slave_temperatur(6) = Rx_temperatur

      Else                                                  ' Acknowledge
         ' ggf. Trace schreiben
         #if Rs485_testmodus
            Print #3 , "Rs485_last_used_mode: Dimmer 6 Daten im Frame falsch"
         #endif
         Result_byte = False                                ' Ergebnis setzen
      End If                                                ' Fehlerbehandlung
   Else                                                     ' Daten empfangen
      ' ggf. Trace schreiben
      #if Rs485_testmodus
         Print #3 , "Rs485_last_used_mode: Dimmer 6 Timeout"
      #endif
      Result_byte = False                                   ' Ergebnis setzen
   End If                                                   ' Fehlerbehandlung

   ' Receiver zurücksetzen
   Rs485_data_received = False

   ' === Dimmer 7 ===

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , " "
      Print #3 , "Rs485_last_used_mode: Dimmer 7"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave_7_adresse                         ' Adresse des Slave
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_licht_dimmer_schalten                  ' Kommando Licht schalten
   Tx_licht = Ee_data_mod7_light                            ' Dimmerstatus
   Tx_dimmstufe = Ee_data_mod7_dimm                         ' Dimmwert
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Soundflag                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Überwachungstimer aufziehen
   Rs485_receive_timer = Timercounter + Rs485_answer_timeout

   Do
      ' Auf Empfang prüfen
      Gosub Rs485_receive_check

      ' Wiederhole Schleife solange bis Counter abgelaufen oder Botschaft empfangen

   Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Rs485_last_used_mode: LOOP ende"
   #endif

   ' Prüfen ob ein Datenpaket empfangen wurde
   If Rs485_data_received = True Then
      ' JA, Datenpaket prozessieren und prüfen ob korrekte Antwrot vom Slave

      ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
      If Rx_kommando = Resp_ack And Rx_quelladresse = Slave_7_adresse Then
         ' JA, dann alles OK, zusätzliche Daten übernehmen

         ' Temperatur übernehmen
         Slave_temperatur(7) = Rx_temperatur

      Else                                                  ' Acknowledge
         ' ggf. Trace schreiben
         #if Rs485_testmodus
            Print #3 , "Rs485_last_used_mode: Dimmer 7 Daten im Frame falsch"
         #endif
         Result_byte = False                                ' Ergebnis setzen
      End If                                                ' Fehlerbehandlung
   Else                                                     ' Datenpaket empfangen
      ' ggf. Trace schreiben
      #if Rs485_testmodus
         Print #3 , "Rs485_last_used_mode: Dimmer 7 Timeout"
      #endif
      Result_byte = False                                   ' Ergebnis setzen
   End If                                                   ' Fehlerbehandlung

   ' Receiver zurücksetzen
   Rs485_data_received = False

   ' === Dimmer 8 ===

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , " "
      Print #3 , "Rs485_last_used_mode: Dimmer 8"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave_8_adresse                         ' Adresse des Slave
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_licht_dimmer_schalten                  ' Kommando Licht schalten
   Tx_licht = Ee_data_mod8_light                            ' Dimmerstatus
   Tx_dimmstufe = Ee_data_mod8_dimm                         ' Dimmwert
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Soundflag                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Überwachungstimer aufziehen
   Rs485_receive_timer = Timercounter + Rs485_answer_timeout

   Do
      ' Auf Empfang prüfen
      Gosub Rs485_receive_check

      ' Wiederhole Schleife solange bis Counter abgelaufen oder Botschaft empfangen

   Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Rs485_last_used_mode: LOOP ende"
   #endif

   ' Prüfen ob ein Datenpaket empfangen wurde
   If Rs485_data_received = True Then
      ' JA, Datenpaket prozessieren und prüfen ob korrekte Antwrot vom Slave

      ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
      If Rx_kommando = Resp_ack And Rx_quelladresse = Slave_8_adresse Then
         ' JA, dann alles OK, zusätzliche Daten übernehmen

         ' Temperatur übernehmen
         Slave_temperatur(8) = Rx_temperatur

      Else                                                  ' Acknowledge
         ' ggf. Trace schreiben
         #if Rs485_testmodus
            Print #3 , "Rs485_last_used_mode: Dimmer 8 Daten im Frame falsch"
         #endif
         Result_byte = False                                ' Ergebnis setzen
      End If                                                ' Fehlerbehandlung
   Else                                                     ' Datenpaket empfangen
      ' ggf. Trace schreiben
      #if Rs485_testmodus
         Print #3 , "Rs485_last_used_mode: Dimmer 8 Timeout"
      #endif
      Result_byte = False                                   ' Ergebnis setzen
   End If                                                   ' Fehlerbehandlung

   ' Receiver zurücksetzen
   Rs485_data_received = False

   ' Ergebnis and Rückgabeparameter übergeben
   Rs485_last_used_mode = Result_byte

End Function
'-- End Rs485_last_used_mode --------------------------------------------------

'------------------------------------------------------------------------------
' Rs485 - Funktion: Rs485_licht_schalten
' Funktion sendet Kommando zum Schalten (EIN/AUS) an Slave und wartet auf
' positive Quittierung
'
' Parameter:     Slave  = Adresse des Slave, 0xFF ist BoradCast-Message
'                Status = Schaltzustand [Licht_ein / Licht_aus]
'
' Rückgabewert:  Bytevariable
'                TRUE  = Slave hat geantwortet bzw. Ausführung OK
'                FALSE = Es ist ein Fehler aufgetreten
'
' Anmerkung: Bei Broadcast-Message wird nicht auf Antwort gewartet
'------------------------------------------------------------------------------
Function Rs485_licht_schalten(byval Slave As Byte , Byval Status As Byte) As Byte

   ' ----- Lokale Variable definieren -----
   Local Result_byte As Byte
   Result_byte = False

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

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_licht_schalten"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave                                   ' Übergabeparameter 1
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_licht_schalten                         ' Kommando Licht schalten
   Tx_licht = Status                                        ' Übergabeparameter 2
   Tx_dimmstufe = Undefined                                 ' Wird zum Lichtschalten nicht benötigt
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Undefined                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Anhang Message-Type prüfen ob Slave antworten wird:

   Select Case Slave

      ' === Normale Botschaft ===
      Case Slave_1_adresse To Slave_8_adresse:

         #if Rs485_testmodus
            Print #3 , "Rs485_licht_schalten: Normale Botschaft"
         #endif

         ' Überwachungstimer aufziehen
         Rs485_receive_timer = Timercounter + Rs485_answer_timeout

         Do
            ' Empfang prüfen
            Gosub Rs485_receive_check

            ' Wiederhole Schleife so lange bis Timeout abgelaufen oder Daten Empfangen

         Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

         ' Prüfen ob ein Datenpaket empfangen wurde
         If Rs485_data_received = True Then
            ' JA

            ' Datenpaket prozessieren und prüfen ob korrekte Antwort vom Slave

            ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
            If Rx_kommando = Resp_ack And Rx_quelladresse = Slave Then
               ' JA, dann alles OK, zusätzliche Daten übernehmen

               ' Temperatur übernehmen
               Slave_temperatur(slave) = Rx_temperatur

               ' MaFu: hier könnte man noch überprüfen, ob die empfangenen
               ' Dimmwerte und Statuswerte noch valide sind und ggf. die
               ' eigenen gespeicherten Daten anpassen.

               Result_byte = True                           ' Ergebnis setzen

            End If                                          ' Acknowledge
         End If                                             ' Daten empfangen

         ' Receiver zurücksetzen
         Rs485_data_received = False

      ' === Broadcast-Botschaft ===
      Case Broadcastadresse:

         #if Rs485_testmodus
            Print #3 , "Rs485_licht_schalten: Broadcast-Message"
         #endif

         ' Keine besondere Auswertung
         Result_byte = True

   End Select                                               ' Auswertung

   ' Ergebnis and Rückgabeparameter übergeben
   Rs485_licht_schalten = Result_byte

End Function
'-- End Rs485_licht_schalten --------------------------------------------------

'------------------------------------------------------------------------------
' Rs485 - Funktion: Rs485_dimmwert_setzen
' Funktion sendet Kommando zum Setzen des Dimmwerts [00..32] an Slave und
' wartet auf positive Quittierung
'
' Parameter:     Slave    = Adresse des Slave, 0xFF ist BoradCast-Message
'                Dimmwert = Dimmwert [00..32]
'
' Rückgabewert:  Bytevariable
'                TRUE  = Slave hat geantwortet bzw. Ausführung OK
'                FALSE = Es ist ein Fehler aufgetreten
'
' Anmerkung: Bei Broadcast-Message wird nicht auf Antwort gewartet
'------------------------------------------------------------------------------
Function Rs485_dimmwert_setzen(byval Slave As Byte , Byval Dimmerwert As Byte) As Byte

   ' ----- Lokale Variable definieren -----
   Local Result_byte As Byte
   Result_byte = False

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

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_dimmwert_setzen"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave                                   ' Übergabeparameter 1
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_dimmer_schalten                        ' Kommando Licht schalten
   Tx_licht = Undefined                                     ' Wird zum Lichtschalten nicht benötigt
   Tx_dimmstufe = Dimmerwert                                ' Übergabeparameter 2
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Undefined                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Anhang Message-Type prüfen ob Slave antworten wird:

   Select Case Slave

      ' === Normale Botschaft ===
      Case Slave_1_adresse To Slave_8_adresse:

         #if Rs485_testmodus
            Print #3 , "Rs485_dimmwert_setzen: Normale Botschaft"
         #endif

         ' Überwachungstimer aufziehen
         Rs485_receive_timer = Timercounter + Rs485_answer_timeout

         Do
            ' Empfang prüfen
            Gosub Rs485_receive_check

            ' Wiederhole Schleife so lange bis Timeout abgelaufen oder Daten Empfangen

         Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

         ' Prüfen ob ein Datenpaket empfangen wurde
         If Rs485_data_received = True Then
            ' JA

            ' Datenpaket prozessieren und prüfen ob korrekte Antwort vom Slave

            ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
            If Rx_kommando = Resp_ack And Rx_quelladresse = Slave Then
               ' JA, dann alles OK, zusätzliche Daten übernehmen

               ' Temperatur übernehmen
               Slave_temperatur(slave) = Rx_temperatur

               ' MaFu: hier könnte man noch überprüfen, ob die empfangenen
               ' Dimmwerte und Statuswerte noch valide sind und ggf. die
               ' eigenen gespeicherten Daten anpassen.

               Result_byte = True                           ' Ergebnis setzen

            End If                                          ' Acknowledge
         End If                                             ' Daten empfangen

         ' Receiver zurücksetzen
         Rs485_data_received = False

      ' === Broadcast-Botschaft ===
      Case Broadcastadresse:

         #if Rs485_testmodus
            Print #3 , "Rs485_dimmwert_setzen: Broadcast-Message"
         #endif

         ' Keine besondere Auswertung

         Result_byte = True

   End Select                                               ' Auswertung

   ' Ergebnis and Rückgabeparameter übergeben
   Rs485_dimmwert_setzen = Result_byte

End Function
'-- End Rs485_dimmwert_setzen -------------------------------------------------

'------------------------------------------------------------------------------
' Rs485 - Funktion: Rs485_sound_schalten
' Funktion sendet Kommando zum Setzen der Soundwiedergabe [EIN/AUS] und
' wartet auf positive Quittierung
'
' Parameter:     Slave    = Adresse des Slave, 0xFF ist BoradCast-Message
'                Sound    = Soundwert [AN/AUS]
'
' Rückgabewert:  Bytevariable
'                TRUE  = Slave hat geantwortet bzw. Ausführung OK
'                FALSE = Es ist ein Fehler aufgetreten
'
' Anmerkung: Bei Broadcast-Message wird nicht auf Antwort gewartet
'------------------------------------------------------------------------------
Function Rs485_sound_schalten(byval Slave As Byte , Byval Soundstatus As Byte) As Byte

   ' ----- Lokale Variable definieren -----
   Local Result_byte As Byte
   Result_byte = False

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

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_sound_schalten"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave                                   ' Übergabeparameter 1
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_sound_schalten                         ' Kommando Licht schalten
   Tx_licht = Undefined                                     ' Wird zum Lichtschalten nicht benötigt
   Tx_dimmstufe = Undefined                                 ' Übergabeparameter 2
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Soundstatus                                   ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Anhang Message-Type prüfen ob Slave antworten wird:

   Select Case Slave

      ' === Normale Botschaft ===
      Case Slave_1_adresse To Slave_8_adresse:

         #if Rs485_testmodus
            Print #3 , "Rs485_sound_schalten: Normale Botschaft"
         #endif

         ' Überwachungstimer aufziehen
         Rs485_receive_timer = Timercounter + Rs485_answer_timeout

         Do
            ' Empfang prüfen
            Gosub Rs485_receive_check

            ' Wiederhole Schleife so lange bis Timeout abgelaufen oder Daten Empfangen

         Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

         ' Prüfen ob ein Datenpaket empfangen wurde
         If Rs485_data_received = True Then
            ' JA

            ' Datenpaket prozessieren und prüfen ob korrekte Antwort vom Slave

            ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
            If Rx_kommando = Resp_ack And Rx_quelladresse = Slave Then
               ' JA, dann alles OK, zusätzliche Daten übernehmen

               ' Temperatur übernehmen
               Slave_temperatur(slave) = Rx_temperatur

               ' MaFu: hier könnte man noch überprüfen, ob die empfangenen
               ' Dimmwerte und Statuswerte noch valide sind und ggf. die
               ' eigenen gespeicherten Daten anpassen.

               Result_byte = True                           ' Ergebnis setzen

            End If                                          ' Acknowledge
         End If                                             ' Daten empfangen

         ' Receiver zurücksetzen
         Rs485_data_received = False

      ' === Broadcast-Botschaft ===
      Case Broadcastadresse:

         #if Rs485_testmodus
            Print #3 , "Rs485_sound_schalten: Broadcast-Message"
         #endif

         ' Keine besondere Auswertung

         Result_byte = True

   End Select                                               ' Auswertung

   ' Ergebnis and Rückgabeparameter übergeben
   Rs485_sound_schalten = Result_byte

End Function
'-- End Rs485_sound_schalten --------------------------------------------------

'------------------------------------------------------------------------------
' Rs485 - Funktion: Rs485_temperatur_setzen
' Funktion sendet Kommando zum Setzen der Übertemperatur [000..255] und
' wartet auf positive Quittierung
'
' Parameter:     Slave    = Adresse des Slave, 0xFF ist BoradCast-Message
'                Sound    = Übertemperatur [000..255]
'
' Rückgabewert:  Bytevariable
'                TRUE  = Slave hat geantwortet bzw. Ausführung OK
'                FALSE = Es ist ein Fehler aufgetreten
'
' Anmerkung: Bei Broadcast-Message wird nicht auf Antwort gewartet
'------------------------------------------------------------------------------
Function Rs485_temperatur_setzen(byval Slave As Byte , Byval Temperatur As Byte) As Byte

   ' ----- Lokale Variable definieren -----
   Local Result_byte As Byte
   Result_byte = False

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

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_temperatur_setzen"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave                                   ' Übergabeparameter 1
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_uebertemperatur_setzen                 ' Kommando Licht schalten
   Tx_licht = Undefined                                     ' Wird zum Lichtschalten nicht benötigt
   Tx_dimmstufe = Undefined                                 ' Wird zum Lichtschalten nicht benötigt
   Tx_temperatur = Temperatur                               ' Übergabeparameter 2
   Tx_sound = Undefined                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Anhang Message-Type prüfen ob Slave antworten wird:

   Select Case Slave

      ' === Normale Botschaft ===
      Case Slave_1_adresse To Slave_8_adresse:

         #if Rs485_testmodus
            Print #3 , "Rs485_temperatur_setzen: Normale Botschaft"
         #endif

         ' Überwachungstimer aufziehen
         Rs485_receive_timer = Timercounter + Rs485_answer_timeout

         Do
            ' Empfang prüfen
            Gosub Rs485_receive_check

            ' Wiederhole Schleife so lange bis Timeout abgelaufen oder Daten Empfangen

         Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

         ' Prüfen ob ein Datenpaket empfangen wurde
         If Rs485_data_received = True Then
            ' JA

            ' Datenpaket prozessieren und prüfen ob korrekte Antwort vom Slave

            ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
            If Rx_kommando = Resp_ack And Rx_quelladresse = Slave Then
               ' JA, dann alles OK, zusätzliche Daten übernehmen

               ' Temperatur übernehmen
               Slave_temperatur(slave) = Rx_temperatur

               ' MaFu: hier könnte man noch überprüfen, ob die empfangenen
               ' Dimmwerte und Statuswerte noch valide sind und ggf. die
               ' eigenen gespeicherten Daten anpassen.

               Result_byte = True                           ' Ergebnis setzen

            End If                                          ' Acknowledge
         End If                                             ' Daten empfangen

         ' Receiver zurücksetzen
         Rs485_data_received = False

      ' === Broadcast-Botschaft ===
      Case Broadcastadresse:

         #if Rs485_testmodus
            Print #3 , "Rs485_temperatur_setzen: Broadcast-Message"
         #endif

         ' Keine besondere Auswertung

         Result_byte = True

   End Select                                               ' Auswertung

   ' Ergebnis and Rückgabeparameter übergeben
   Rs485_temperatur_setzen = Result_byte

End Function
'-- End Rs485_temperatur_setzen -----------------------------------------------

'------------------------------------------------------------------------------
' Rs485 - Funktion: Rs485_sweep_mode
' Funktion aktiviert den Sweep-Modus Up and Down in Abhängigkeit der Parameter
'
' Parameter:     Slave    = Adresse des Slave, 0xFF ist BroadCast-Message
'                Modus    = 0 = SweepUp / 1 = SweepDown
'
' Rückgabewert:  Bytevariable
'                TRUE  = Rückgabewert für diese Funktion ist immer True
'
'------------------------------------------------------------------------------
Function Rs485_sweep_mode(byval Slave As Byte , Byval Modus As Byte) As Byte

   ' ----- Lokale Variable definieren -----
   Local Result_byte As Byte
   Result_byte = True

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

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_sweep_mode"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave                                   ' Übergabeparameter 1
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_sweep_mode                             ' Kommando Sweep-Modus
   Tx_licht = Modus                                         ' Übergabeparameter 2
   Tx_dimmstufe = Undefined                                 ' Wird zum Lichtschalten nicht benötigt
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Undefined                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Auf Sweep-Mode gibt es keine Antwort

   ' Ergebnis and Rückgabeparameter übergeben
   Rs485_sweep_mode = Result_byte

End Function
'-- End Rs485_sweep_mode ------------------------------------------------------

'------------------------------------------------------------------------------
' Rs485 - Funktion: Rs485_licht_dimmer_schalten
' Funktion sendet Kommando zum
'     - Schalten des Dimmers [EIN/AUS]
'     - Setzen des Dimmwertes [00..32]
'     - Setzen der Soundwiedergabe [EIN/AUS]
' an den Slave und wartet auf positive Quittierung
'
' Parameter:     Slave    = Adresse des Slave, 0xFF ist BoradCast-Message
'                Status   = Schaltzustand des Dimmers [EIN/AUS]
'                Dimmwert = Dimmwert [00..32]
'                Sound    = Soundwert [AN/AUS]
'
' Rückgabewert:  Bytevariable
'                TRUE  = Slave hat geantwortet bzw. Ausführung OK
'                FALSE = Es ist ein Fehler aufgetreten
'
' Anmerkung: Bei Broadcast-Message wird nicht auf Antwort gewartet
'------------------------------------------------------------------------------
Function Rs485_licht_dimmer_schalten(byval Slave As Byte , Byval Status As Byte , Byval Dimmerwert As Byte , Byval Soundstatus As Byte) As Byte

   ' ----- Lokale Variable definieren -----
   Local Result_byte As Byte
   Result_byte = False

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

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_licht_dimmer_schalten"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave                                   ' Übergabeparameter 1
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_licht_dimmer_schalten                  ' Kommando Licht schalten
   Tx_licht = Status                                        ' Übergabeparameter 2
   Tx_dimmstufe = Dimmerwert                                ' Übergabeparameter 3
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Soundstatus                                   ' Übergabeparameter 4

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Anhang Message-Type prüfen ob Slave antworten wird:

   Select Case Slave

      ' === Normale Botschaft ===
      Case Slave_1_adresse To Slave_8_adresse:

         #if Rs485_testmodus
            Print #3 , "Rs485_licht_dimmer_schalten: Normale Botschaft"
         #endif

         ' Überwachungstimer aufziehen
         Rs485_receive_timer = Timercounter + Rs485_answer_timeout

         Do
            ' Empfang prüfen
            Gosub Rs485_receive_check

            ' Wiederhole Schleife so lange bis Timeout abgelaufen oder Daten Empfangen

         Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

         ' Prüfen ob ein Datenpaket empfangen wurde
         If Rs485_data_received = True Then
            ' JA

            ' Datenpaket prozessieren und prüfen ob korrekte Antwort vom Slave

            ' Prüfen ob Botschaft Acknowledge ist und Botschaft zum richtigen Slave gehört
            If Rx_kommando = Resp_ack And Rx_quelladresse = Slave Then
               ' JA, dann alles OK, zusätzliche Daten übernehmen

               ' Temperatur übernehmen
               Slave_temperatur(slave) = Rx_temperatur

               ' MaFu: hier könnte man noch überprüfen, ob die empfangenen
               ' Dimmwerte und Statuswerte noch valide sind und ggf. die
               ' eigenen gespeicherten Daten anpassen.

               Result_byte = True                           ' Ergebnis setzen

            End If                                          ' Ack und Antwort
         End If                                             ' Daten empfangen

         ' Receiver zurücksetzen
         Rs485_data_received = False

      ' === Broadcast-Botschaft ===
      Case Broadcastadresse:

         #if Rs485_testmodus
            Print #3 , "Rs485_licht_dimmer_schalten: Broadcast-Message"
         #endif

         ' Keine besondere Auswertung

         Result_byte = True

   End Select                                               ' Auswertung

   ' Ergebnis and Rückgabeparameter übergeben
   Rs485_licht_dimmer_schalten = Result_byte

End Function
'-- End Rs485_licht_dimmer_schalten -------------------------------------------

'------------------------------------------------------------------------------
' Rs485 - Funktion: Rs485_status_abfragen
' Funktion sendet Kommando zur Statusabfrage an Slave und wertet Antwort aus
'
' Parameter:     Slave  = Adresse des Slave, 0xFF ist BoradCast-Message
'
' Rückgabewert:  Bytevariable
'                TRUE  = Slave hat geantwortet bzw. Ausführung OK
'                FALSE = Es ist ein Fehler aufgetreten
'
' Anmerkung: Funktion kann nicht als Broadcast gesendet werden!
'------------------------------------------------------------------------------
Function Rs485_status_abfragen(byval Slave As Byte) As Byte

   ' ----- Lokale Variable definieren -----
   Local Result_byte As Byte
   Result_byte = False

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

   ' ggf. trace auf RS232 ausgeben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_status_abfragen"
   #endif

   ' Sende-Datenstruktur laden
   Tx_zieladresse = Slave                                   ' Übergabeparameter 1
   Tx_quelladresse = Masteradresse                          ' Adresse des Masters
   Tx_framelength = Framelaenge                             ' Framlänge ist immer 4
   Tx_kommando = Cmd_status_abfragen                        ' Kommando Status abfragen
   Tx_licht = Undefined                                     ' Wird zum Lichtschalten nicht benötigt
   Tx_dimmstufe = Undefined                                 ' Wird zum Lichtschalten nicht benötigt
   Tx_temperatur = Undefined                                ' Wird zum Lichtschalten nicht benötigt
   Tx_sound = Undefined                                     ' Wird zum Lichtschalten nicht benötigt

   ' Anmerkung: Die CheckSumme CRC16 wird vor Übertragung durch RS485_send ermittelt

   ' Daten versenden
   Gosub Rs485_send

   ' Überwachungstimer aufziehen
   Rs485_receive_timer = Timercounter + Rs485_answer_timeout

   Do
      ' Empfang prüfen
      Gosub Rs485_receive_check

      ' Wiederhole Schleife so lange bis Timeout abgelaufen oder Daten Empfangen

   Loop Until Rs485_data_received = True Or Timercounter >= Rs485_receive_timer

   ' Prüfen ob ein Datenpaket empfangen wurde
   If Rs485_data_received = True Then
      ' JA

      ' Datenpaket prozessieren und prüfen ob korrekte Antwrot vom Slave

      ' Prüfen ob Botschaft Status-Antwort ist und Botschaft zum richtigen Slave gehört
      If Rx_kommando = Resp_status And Rx_quelladresse = Slave Then
         ' JA, dann alles OK, zusätzliche Daten übernehmen

         ' Temperatur übernehmen
         Slave_temperatur(slave) = Rx_temperatur

         ' Sound ist nicht relevant und wird aktuell nicht ausgewertet

         ' Nun Dimmwert und Status auswerten und ggf. Einstellungen updaten
         Select Case Slave

            ' === Dimmer 1 ===
            Case Slave_1_adresse:
               ' Dimmermodul 1 - Schaltzustand
               If Rx_licht <> Ee_data_mod1_light Then
                  Ee_data_mod1_light = Rx_licht
                  Ee_dimmer_update(1) = True
               End If                                       ' Check Lichtstatus

               ' Dimmermodul 1 - Dimmerstufe
               If Rx_dimmstufe <> Ee_data_mod1_dimm Then
                  Ee_data_mod1_dimm = Rx_dimmstufe
                  Ee_dimmer_update(1) = True
               End If                                       ' Check Dimmstufe

            ' === Dimmer 2 ===
            Case Slave_2_adresse:
               ' Dimmermodul 2 - Schaltzustand
               If Rx_licht <> Ee_data_mod2_light Then
                  Ee_data_mod2_light = Rx_licht
                  Ee_dimmer_update(2) = True
               End If                                       ' Check Lichtstatus

               ' Dimmermodul 2 - Dimmerstufe
               If Rx_dimmstufe <> Ee_data_mod2_dimm Then
                  Ee_data_mod2_dimm = Rx_dimmstufe
                  Ee_dimmer_update(2) = True
               End If                                       ' Check Dimmstufe

            ' === Dimmer 3 ===
            Case Slave_3_adresse:
               ' Dimmermodul 3 - Schaltzustand
               If Rx_licht <> Ee_data_mod3_light Then
                  Ee_data_mod3_light = Rx_licht
                  Ee_dimmer_update(3) = True
               End If                                       ' Check Lichtstatus

               ' Dimmermodul 3 - Dimmerstufe
               If Rx_dimmstufe <> Ee_data_mod3_dimm Then
                  Ee_data_mod3_dimm = Rx_dimmstufe
                  Ee_dimmer_update(3) = True
               End If                                       ' Check Dimmstufe

            ' === Dimmer 4 ===
            Case Slave_4_adresse:
               ' Dimmermodul 4 - Schaltzustand
               If Rx_licht <> Ee_data_mod4_light Then
                  Ee_data_mod4_light = Rx_licht
                  Ee_dimmer_update(4) = True
               End If                                       ' Check Lichtstatus

               ' Dimmermodul 4 - Dimmerstufe
               If Rx_dimmstufe <> Ee_data_mod4_dimm Then
                  Ee_data_mod4_dimm = Rx_dimmstufe
                  Ee_dimmer_update(4) = True
               End If                                       ' Check Dimmstufe

            ' === Dimmer 5 ===
            Case Slave_5_adresse:
               ' Dimmermodul 5 - Schaltzustand
               If Rx_licht <> Ee_data_mod5_light Then
                  Ee_data_mod5_light = Rx_licht
                  Ee_dimmer_update(5) = True
               End If                                       ' Check Lichtstatus

               ' Dimmermodul 5 - Dimmerstufe
               If Rx_dimmstufe <> Ee_data_mod5_dimm Then
                  Ee_data_mod5_dimm = Rx_dimmstufe
                  Ee_dimmer_update(5) = True
               End If                                       ' Check Dimmstufe

            ' === Dimmer 6 ===
            Case Slave_6_adresse:
               ' Dimmermodul 6 - Schaltzustand
               If Rx_licht <> Ee_data_mod6_light Then
                  Ee_data_mod6_light = Rx_licht
                  Ee_dimmer_update(6) = True
               End If                                       ' Check Lichtstatus

               ' Dimmermodul 6 - Dimmerstufe
               If Rx_dimmstufe <> Ee_data_mod6_dimm Then
                  Ee_data_mod6_dimm = Rx_dimmstufe
                  Ee_dimmer_update(6) = True
               End If                                       ' Check Dimmstufe

            ' === Dimmer 7 ===
            Case Slave_7_adresse:
               ' Dimmermodul 7 - Schaltzustand
               If Rx_licht <> Ee_data_mod7_light Then
                  Ee_data_mod7_light = Rx_licht
                  Ee_dimmer_update(7) = True
               End If                                       ' Check Lichtstatus

               ' Dimmermodul 7 - Dimmerstufe
               If Rx_dimmstufe <> Ee_data_mod7_dimm Then
                  Ee_data_mod7_dimm = Rx_dimmstufe
                  Ee_dimmer_update(7) = True
               End If                                       ' Check Dimmstufe

            ' === Dimmer 8 ===
            Case Slave_8_adresse:
               ' Dimmermodul 8 - Schaltzustand
               If Rx_licht <> Ee_data_mod8_light Then
                  Ee_data_mod8_light = Rx_licht
                  Ee_dimmer_update(8) = True
               End If                                       ' Check Lichtstatus

               ' Dimmermodul 8 - Dimmerstufe
               If Rx_dimmstufe <> Ee_data_mod8_dimm Then
                  Ee_data_mod8_dimm = Rx_dimmstufe
                  Ee_dimmer_update(8) = True
               End If                                       ' Check Dimmstufe

         End Select                                         ' Slave-Adresse

         Result_byte = True                                 ' Ergebnis setzen

      End If
   End If                                                   ' Daten empfangen

   ' Receiver zurücksetzen
   Rs485_data_received = False

   ' Ergebnis and Rückgabeparameter übergeben
   Rs485_status_abfragen = Result_byte

End Function
'-- End Rs485_status_abfragen -------------------------------------------------

' **********
' * EEPROM *
' **********

'------------------------------------------------------------------------------
' EE - Funktion: Ee_read_eeprom_byte
' Funktion um ein einzelnes Byte von einer bestimmten Speicheradresse aus dem
' EEPROM zu lesen.
'
' Parameter:     Adress = Adresse (Word) von der das Byte gelesen werden soll
'
' Rückgabewert:  Bytevariable die von der Adresse ausgelesen wurde.
'------------------------------------------------------------------------------
Function Ee_read_eeprom_byte(byval Adress As Word) As Byte

   ' ----- Lokale Variable definieren -----
   Local Ee_adrl As Byte
   Local Ee_adrh As Byte
   Local Temp_byte As Byte

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

   ' ggf. trace auf RS232 ausgeben
   #if Eeprom_testmodus
      Print #3 , "Enter Ee_read_eeprom_byte"
   #endif

   ' Adresse in High-Byte und Low-Byte zerlegen
   Ee_adrl = Low(adress)
   Ee_adrh = High(adress)

   ' Kommunikation über I2C-Bus
   I2cstart                                                 ' START-Sequenz senden
   I2cwbyte Address_write                                   ' Daten schreiben initiieren
   I2cwbyte Ee_adrh                                         ' High-Byte der Adresse übertragen
   I2cwbyte Ee_adrl                                         ' Low-Byte der Adresse übertragen

   I2cstart                                                 ' START-Sequenz erneut senden
   I2cwbyte Address_read                                    ' Daten lesen initiieren
   I2crbyte Temp_byte , Nack                                ' Byte auslesen und quittieren
   I2cstop                                                  ' STOP-Sequenz

   #if Eeprom_testmodus
      Print #3 , "Ee_read_eeprom_byte: Ee_read_eeprom_byte: " ; Hex(temp_byte)
   #endif

   ' Temporäre Variable als Rückgabewert übergeben
   Ee_read_eeprom_byte = Temp_byte

End Function
'-- End Ee_read_eeprom_byte ---------------------------------------------------

'------------------------------------------------------------------------------
' EE - Funktion: Ee_read_eeprom_word
' Funktion um ein zwei Bytes (Word) von einer bestimmten Speicheradresse aus
' dem EEPROM zu lesen.
'
' Parameter:     Adress = Adresse (Word) von der das Word gelesen werden soll
'
' Rückgabewert:  Wordvariable die von der Adresse ausgelesen wurde.
'------------------------------------------------------------------------------
Function Ee_read_eeprom_word(byval Adress As Word) As Word

   ' ----- Lokale Variable definieren -----
   Local Ee_adrl As Byte
   Local Ee_adrh As Byte

   Local Ee_datal As Byte
   Local Ee_datah As Byte

   Local Temp_word As Word

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

   ' ggf. trace auf RS232 ausgeben
   #if Eeprom_testmodus
      Print #3 , "Enter Ee_read_eeprom_word"
   #endif

   ' Adresse in High-Byte und Low-Byte zerlegen
   Ee_adrl = Low(adress)
   Ee_adrh = High(adress)

   ' Kommunikation über I2C-Bus
   I2cstart                                                 ' START-Sequenz senden
   I2cwbyte Address_write                                   ' Daten schreiben initiieren
   I2cwbyte Ee_adrh                                         ' High-Byte der Adresse übertragen
   I2cwbyte Ee_adrl                                         ' Low-Byte der Adresse übertragen

   I2cstart                                                 ' START-Sequenz erneut senden
   I2cwbyte Address_read                                    ' Daten lesen initiieren
   I2crbyte Ee_datah , Ack                                  ' High-Byte auslesen und weiter
   I2crbyte Ee_datal , Nack                                 ' Low-Byte auslesen und Ende
   I2cstop                                                  ' STOP-Sequenz

   #if Eeprom_testmodus
      Print #3 , "Ee_read_eeprom_word: Data high: " ; Hex(ee_datah)
      Print #3 , "Ee_read_eeprom_word: Data low:  " ; Hex(ee_datal)
   #endif

   ' Temporäre Variable als Rückgabewert übergeben
   Temp_word = Ee_datah
   Shift Temp_word , Left , 8
   Temp_word = Temp_word And &HFF00
   Temp_word = Temp_word + Ee_datal

   Ee_read_eeprom_word = Temp_word

End Function
'-- End Ee_read_eeprom_byte ---------------------------------------------------

' *******************
' * Common routines *
' *******************

'------------------------------------------------------------------------------
' Function: Byte2string
' Funktion liefert als Ergebnis eine "rechtsbündig" formatierten String einer
' übergebenen Byte-Variablen. Der String ist max. 3 Zeichen groß und beinhaltet
' ggf. bei kleineren Zahlen das übergebene Character als Füllzeichen von links
' führend aufgefüllt.
'
' Parameter:    Value     = Byte das als SString formatiert werden soll
'               Character = ASCII-Wert des Zeichens mit dem ggf. aufgefüllt
'               werden soll.
' Rückgabewert: String der Byte-Variablen inkl. Füllzeichen
'------------------------------------------------------------------------------
Function Byte2string(byval Value As Byte , Byval Character As Byte) As String

   ' ----- lokale Variablen -----
   Local String_length As Byte
   Local Process_string As String * 4

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

   ' Basis-String anlegen
   Process_string = Str(value)
   ' Länge ermitteln
   String_length = Len(process_string)

   ' Abhängig von Länge Füllzeichen ergänzen
   Select Case String_length
      Case 1:
         ' Wenn Länge 1 müssen zwei Füllzeichen links ergänzt werden
         Process_string = Chr(character) + Process_string
         Process_string = Chr(character) + Process_string
      Case 2:
         ' Wenn Länge 2 muss ein Füllzeichen links ergänzt werden
         Process_string = Chr(character) + Process_string
   End Select                                               ' Stringlänge

   ' Bearbeiteter String an Übergabeparameter übergeben
   Byte2string = Process_string

End Function
'-- End Byte2string -----------------------------------------------------------

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

' ********************
' * LCD:  Display    *
' ********************

'------------------------------------------------------------------------------
' LCD - Sub-Routine: Lcd_writesingleline
' Gibt einen einzeiligen Texte auf dem LCD-Display aus.
' Parameter: line1 = Zeile in der die Ausgabe erfolgen soll
'            text1 = Text der ausgegeben werden soll
'------------------------------------------------------------------------------
Sub Lcd_writesingleline(line1 As Byte , Text1 As Sring)

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

   Cls                                                      ' Bildschirm löschen
   Locate Line1 , 1 : Lcd Text1                             ' Ausgabe Zeil 1

End Sub
'-- End Lcd_writesingleline ---------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Sub-Routine: Lcd_writedoubleline
' Gibt einen zweizeiligen Texte auf dem LCD-Display aus.
' Die Reihenfolge und die Textposition kann frei gewählt werden
' Parameter: line1 = 1. Zeile in der die 1. Ausgabe erfolgen soll
'            line2 = 2. Zeile in der die 2. Ausgabe erfolgen soll
'            text1 = 1. Text der auf 1. Position ausgegeben werden soll
'            text2 = 2. Text der auf 2. Position ausgegeben werden soll
'------------------------------------------------------------------------------
Sub Lcd_writedoubleline(line1 As Byte , Line2 As Byte , Text1 As String , Text2 As String)

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

   Cls                                                      ' Bildschirm löschen
   Locate Line1 , 1 : Lcd Text1                             ' Ausgabe Zeil 1
   Locate Line2 , 1 : Lcd Text2                             ' Ausgabe Zeile 2

End Sub
'-- End Lcd_writedoubleline ---------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Sub-Routine: Lcd_writetrippleline
' Gibt einen dreizeiligen Texte auf dem LCD-Display aus.
' Parameter: text1 = 1. Text der in Zeile 1 ausgegeben werden soll
'            text2 = 2. Text der in Zeile 2 ausgegeben werden soll
'            text3 = 3. Text der in Teile 3 ausgegeben werden soll
'------------------------------------------------------------------------------
Sub Lcd_writetrippleline(text1 As String , Text2 As String , Text3 As String)

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

   ' Variablen für Positionierung definieren und festlegen
   ' Hinweis: Interessanter Weise funktioniert Ausgabe nicht bei direkter Zuweisung!
   Dim Line1 As Byte , Line2 As Byte , Line3 As Byte
   Line1 = 1
   Line2 = 2
   Line3 = 3

   ' Ausgabe der Texte
   Cls                                                      ' Bildschirm löschen
   Locate Line1 , 1 : Lcd Text1                             ' Ausgabe Zeile 1
   Locate Line2 , 1 : Lcd Text2                             ' Ausgabe Zeile 2
   Locate Line3 , 1 : Lcd Text3                             ' Ausgabe Zeile 3

End Sub
'-- End Lcd_writetrippleline --------------------------------------------------

' **********
' * EEPROM *
' **********

'------------------------------------------------------------------------------
' EE - Subroutine: Ee_write_eeprom_byte
' Subroutine um ein einzelnes Byte an eine bestimmte Speicheradresse in das
' EEPROM zu schreiben.
'
' Parameter:   Adress = Adresse (Word) an die geschrieben werden soll
'              Value  = Bytevariable die geschrieben werden soll
'------------------------------------------------------------------------------
Sub Ee_write_eeprom_byte(byval Adress As Word , Byval Value As Byte)

   ' ----- Lokale Variable definieren -----
   Local Ee_adrl As Byte
   Local Ee_adrh As Byte

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

   ' ggf. trace auf RS232 ausgeben
   #if Eeprom_testmodus
      Print #3 , "Enter Ee_write_eeprom_byte"
   #endif

   ' Adresse in High-Byte und Low-Byte zerlegen
   Ee_adrl = Low(adress)
   Ee_adrh = High(adress)

   ' ggf. trace auf RS232 ausgeben
   #if Eeprom_testmodus
      Print #3 , "Ee_write_eeprom_byte: Data high: " ; Hex(ee_adrl)
      Print #3 , "Ee_write_eeprom_byte: Data low:  " ; Hex(ee_adrh)
   #endif

   ' Kommunikation über I2C-Bus
   I2cstart                                                 ' START-Sequenze senden
   I2cwbyte Address_write                                   ' Daten schreiben initiieren
   I2cwbyte Ee_adrh                                         ' High-Byte der Adresse übertragen
   I2cwbyte Ee_adrl                                         ' Low-Byte der Adresse übertragen
   I2cwbyte Value                                           ' Byte-Variable übertragen
   I2cstop                                                  ' STOP-Sequenz

End Sub
'-- End Ee_write_eeprom_byte --------------------------------------------------

'------------------------------------------------------------------------------
' EE - Subroutine: Ee_write_eeprom_word
' Subroutine um ein zwei Bytes (Word) an eine bestimmte Speicheradresse in das
' EEPROM zu schreiben.
'
' Parameter:   Adress = Adresse (Word) an die geschrieben werden soll
'              Value  = Wordvariable die geschrieben werden soll
'------------------------------------------------------------------------------
Sub Ee_write_eeprom_word(byval Adress As Word , Byval Value As Word)

   ' ----- Lokale Variable definieren -----
   Local Ee_adrl As Byte
   Local Ee_adrh As Byte

   Local Ee_datal As Byte
   Local Ee_datah As Byte

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

   ' ggf. trace auf RS232 ausgeben
   #if Eeprom_testmodus
      Print #3 , "Enter Ee_write_eeprom_word"
   #endif

   ' Adresse in High-Byte und Low-Byte zerlegen
   Ee_adrl = Low(adress)
   Ee_adrh = High(adress)

   ' Word in einzelne Bytes zerlegen
   Ee_datal = Low(value)
   Ee_datah = High(value)

   #if Eeprom_testmodus
      Print #3 , "Ee_write_eeprom_word: Data high: " ; Hex(ee_datah)
      Print #3 , "Ee_write_eeprom_word: Data low:  " ; Hex(ee_datal)
   #endif

   ' Kommunikation über I2C-Bus
   I2cstart                                                 ' START-Sequenze senden
   I2cwbyte Address_write                                   ' Daten schreiben initiieren
   I2cwbyte Ee_adrh                                         ' High-Byte der Adresse übertragen
   I2cwbyte Ee_adrl                                         ' Low-Byte der Adresse übertragen
   I2cwbyte Ee_datah                                        ' High-Byte aus Variable übertragen
   I2cwbyte Ee_datal                                        ' Low-byte aus Variable übertragen
   I2cstop                                                  ' STOP-Sequenz

End Sub
'-- End Ee_write_eeprom_word --------------------------------------------------

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

' ************
' * Tastatur *
' ************

'------------------------------------------------------------------------------
' Gosub-Routine: Key_handle_key_1
' Routine behandelt das Betätigen der Taste 1
'------------------------------------------------------------------------------
Key_handle_key_1:

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

   Key_taste = 1
   Key_keypressed = True

Return
'-- End Key_handle_key_1 ------------------------------------------------------

'------------------------------------------------------------------------------
' Gosub-Routine: Key_handle_key_2
' Routine behandelt das Betätigen der Taste 2
'------------------------------------------------------------------------------
Key_handle_key_2:

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

   Key_taste = 2
   Key_keypressed = True

Return
'-- End Key_handle_key_2 ------------------------------------------------------

'------------------------------------------------------------------------------
' Gosub-Routine: Key_handle_key_3
' Routine behandelt das Betätigen der Taste 3
'------------------------------------------------------------------------------
Key_handle_key_3:

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

   Key_taste = 3
   Key_keypressed = True

Return
'-- End Key_handle_key_3 ------------------------------------------------------

'------------------------------------------------------------------------------
' Gosub-Routine: Key_handle_key_4
' Routine behandelt das Betätigen der Taste 4
'------------------------------------------------------------------------------
Key_handle_key_4:

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

   Key_taste = 4
   Key_keypressed = True

Return
'-- End Key_handle_key_4 ------------------------------------------------------

' *********
' * SCART *
' *********

' Binary mode:
' ============

' 0x00                                    NOP
' 0x01 <n> <data_1> ... <data_n>          transmitt n Bytes (n<=61)
' 0xFF                                    force demo packet

' Return value
' 0x00                                    syntax error
' 0x01                                    ready
' 0x02 <n ><data_1> ... <data_n>          n Bytes Data Received über Funktion Rf_packet_binary
' 0x03 <n> <data_1> ... <data_n>          n bytes data received über Funktion DEFAULT

'------------------------------------------------------------------------------
' Gosub-Routine: Scart_receive_check
' Routine überprüft ob im Empfangsbuffer Zeichen vorliegen, liest diese und
' baut die Empfangsstruktur auf. Danach wird ein Flag gesetzt, dass eine
' Botschafft erfolgreich empfangen wurde.
' Das Empfangen neuer Botschaften ist über eine Sempahore verriegelt. Erst
' wenn die Empfangene Botschaft verarbeitet ist, wird der Empfang einer neuen
' Botschaft zugelassen.
'------------------------------------------------------------------------------
Scart_receive_check:

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

   ' Prüfen ob noch ein Datenpaket auf Verarbeitung wartet
   If Rf_data_received = False Then

      ' NEIN, es wartet kein Datenpaket mehr auf Verarbeitung,
      ' die neuen Daten können empfangen werden

      ' Prüfen ob ein Zeichen im Empfangsbuffer wartet
      If Ischarwaiting(#2) <> 0 Then

         ' JA, es wartet ein Zeichen

         ' Prüfen ob Zeichen erstes Zeichen ist, wenn JA dann Überwachung starten
         If Rf_rx_bufferindex = 1 Then

            ' JA rf_rx_bufferindex ist 1, damit wurde noch kein Zeichen empfangen

            '  Nun Timer aufziehen für Überwachung des Empfangs und Flag setzen
            Receive_timeout_flag = True                     ' Timeout aktvieren
            Receive_timeout_counter = Timercounter + Receive_timeout

            ' ggf. Trace ausgeben
            #if Empfangsueberwachung_testmodus
               Print #3 , "Scart_receive_check: Starte Receive-Ueberwachung"
            #endif
         End If                                             ' Erstes Zeichen empfangen

         ' Zeichen in RF-RX-Buffer einlesen
         Rf_rx_buffer(rf_rx_bufferindex) = Inkey(#2)

         ' Ggf Trace ausgeben
         #if Scart_rx_testmodus
            Print #3 , Hex(rf_rx_buffer(rf_rx_bufferindex)) ; " " ;
         #endif

         ' Bufferindex erhöhen
         Incr Rf_rx_bufferindex

         ' Prüfen ob Botschaft vollständig empfangen
         If Rf_rx_bufferindex > Rf_rx_nachrichtenlaenge Then

            'Alle Datenfelder komplett empfangen

            ' Timerüberachung deaktivieren
            Receive_timeout_flag = False

            ' ggf. Trace ausgeben
            #if Empfangsueberwachung_testmodus
               Print #3 , "Scart_receive_check: Beende Receive-Ueberwachung"
            #endif

            ' Fehlerflag zurücksetzen
            Rf_rx_errorflag = False

            Rf_rx_bufferindex = 1                           ' Index zurücksetzen
            Clear Serialin1                                 ' Buffer löschen

            ' ggf. Zeichen auf RS232 Kanal 1 ausgeben
            #if Scart_rx_testmodus
               Print #3 , " "
               Print #3 , "[1]  Rf_rx_paket_type : " ; Hex(rf_rx_paket_type)
               Print #3 , "[2]  Rf_rx_frame_len  : " ; Hex(rf_rx_frame_len)
               Print #3 , "[3]  Rf_rx_dest_addr  : " ; Hex(rf_rx_dest_addr)
               Print #3 , "[4]  Rf_rx_src_addr   : " ; Hex(rf_rx_src_addr)
               Print #3 , "[5]  Rf_rx_data_type  : " ; Hex(rf_rx_data_type)
               Print #3 , "[6]  Rf_rx_frame_len  : " ; Hex(rf_rx_frame_len)
               Print #3 , "[7]  Rf_rx_kommando   : " ; Hex(rf_rx_kommando)
               Print #3 , "[8]  Rf_rx_parameter_1: " ; Hex(rf_rx_parameter_1)
               Print #3 , "[9]  Rf_rx_parameter_2: " ; Hex(rf_rx_parameter_2)
               Print #3 , "[10] Rf_rx_checksumme : " ; Hex(rf_rx_checksumme)
               Print #3 , ""
               Print #3 , "Rx: ";
               For Temp_byte_1 = 1 To Rf_rx_nachrichtenlaenge
                  Print #3 , Hex(rf_rx_buffer(temp_byte_1)) ; " " ;
               Next Temp_byte_1
               Print #3 , ""
            #endif

            ' Prüfung ob Checksumme gültig
            Temp_word_1 = Crc16(rf_rx_buffer(6) , 4)
            If Temp_word_1 = Rf_rx_checksumme Then
               ' JA, Checksumme ist korrekt

               #if Scart_rx_testmodus
                  Print #3 , "CRC korrekt!"
               #endif

               ' Prüfen ob Paket-Typ korrekt und damit Übertragung Betty->Master OK
                If Rf_rx_paket_type = Scart_return_rf_packet Then
                  ' JA

                  ' Flag setzen dass Datenpaket empfangen wurde
                  Rf_data_received = True
                Else                                        ' RF_PACKET_BINARY
                  Rf_rx_errorflag = True                    ' Fehler aufgetreten
                  #if Scart_rx_testmodus
                     Print #3 , "Empfangenes Datenpaket entspricht nicht RF_PACKET_BINARY"
                     Temp_byte_1 = Scart_return_rf_packet
                     Print #3 , "Soll : " ; Hex(temp_byte_1)
                     Print #3 , "Ist  : " ; Hex(rf_rx_paket_type)
                  #endif
                End If                                      ' Nicht RF_PACKET_BINARY
            Else
               Rf_rx_errorflag = True                       ' Fehler aufgetreten
               #if Scart_rx_testmodus
                  Print #3 , "CRC falsch!"
                  Print #3 , "Ist: " ; Hex(temp_word_1) ; " - Soll: " ; Hex(rf_rx_checksumme)
               #endif
            End If                                          ' Checksummen-Prüfung

         End If                                             ' Botschaft vollständig
      End If                                                ' Wartet ein Zeichen?
   End If                                                   ' Verarbeitungssemaphore

   ' Prüfen ob ein RF-Kommunikationsproblem aufgetreten
   If Rf_rx_errorflag = True Then
      ' JA

      ' ggf. Trace auf RS232 ausgeben
      #if Error_testmodus
         Print #3 , "[3] Error(3): RF Kommunikationsfehler"
      #endif

      ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
      ' ## Error ##
      Error_flags(3) = True                                 ' Fehler in Matrix eintragen
      Err_global_flag = True

      ' Fehlerflag wieder zurücksetzen
      Rf_rx_errorflag = False

   End If                                                   ' RF Kommunikationsfehler

Return
'-- End Scart_receive_check ---------------------------------------------------

'------------------------------------------------------------------------------
' Gosub-Routine: Scart_verarbeitung
' Routine verarbeitet die via SCART empfangenen Botschaften
'------------------------------------------------------------------------------
Scart_verarbeitung:

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

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Scart_proc_testmodus
      Print #3 , "Enter Scart_verarbeitung"
   #endif

   ' Protokoll-Spec:
   ' 0x00 Statusabfrage/PING
   ' 0x01 Lichtanlage  an/aus
   ' 0x02 Dimmer einstellen
   ' 0x03 Sound an/aus
   ' 0x04 Alle Lampen an/aus
   ' 0x05 Dimmer 1-8 an/aus
   ' 0x06 Demomodus schalten

   ' Semaphore zurücksetzen so dass ein weiteres Paket verarbeitet werden kann
   Rf_data_received = False

   ' temporäres Fehlerflag zurücksetzen
   ' Temp_byte_1 wird für RF-Kommunikation verwendet
   ' Temp_byte_6 wird für RS485 Kommunikation verwendet
   ' Temp_byte_3 wird für sonstiges verwendet
   Temp_byte_1 = False

   ' Hinweis zur Ablaufsteuerung
   ' [1] Anlage kann mittels Toggelkommando ein und ausgeschaltet werden.
   '     Ausschalten erfolgt über globales Kommando Licht AUS
   '     Einschalten erfolgt über LUM, Datenwerte werden nicht im EEPROM gespeichert
   '     Wird die Anlage in der Zwischzeit Spannunglos geschaltet erfolgt LUM
   ' [2] Bei allen Funktionen muss berücksichtig werden, dass Anlage AUS sein kann
   '     In diesem Fall erfolgt ein NACK mit ACK und Parameter = 0

   Select Case Rf_rx_kommando

      ' === Status abfragen 0x00 ===
      Case Rf_cmd_status_abfragen:

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Scart_proc_testmodus
            Print #3 , "Scart_verarbeitung: 0x00 - Statusabfrage/PING"
            Print #3 , "Scart_verarbeitung: Parameter 1 : " ; Hex(rf_rx_parameter_1)
            Print #3 , "Scart_verarbeitung: Parameter 2 : " ; Hex(rf_rx_parameter_2)
         #endif

         ' prüfen ob Parameter 1 korrekte Inhalte besitzt
         If Rf_rx_parameter_1 >= Slave_1_adresse And Rf_rx_parameter_1 <= Slave_8_adresse Then

            ' JA, Daten innerhalb des erlaubten Range

            ' prüfen ob Anlage eingeschaltet oder ausgeschaltet ist.
            If Anlagenflag = True Then
               ' Anlage eingeschaltet

               ' Statusabfrage des angefragten Slaves (enthalten in Parameter 1)
               Temp_byte_1 = Scart_send(rf_resp_status , Rf_rx_parameter_1)

               ' Bei der Statusabfrage müssen keine Daten persistent gespeichert werden

            Else                                            ' Anlage eingeschaltet
               ' Acknowledge senden mit Anlage = AUS
               Temp_byte_1 = Scart_ack_send(false)

            End If                                          ' Anlage ausgeschaltet
         Else                                               ' Gültige Anfrage
            ' Fehlerflag setzen
            Rf_rx_errorflag = True
         End If                                             ' Ungültige Anfrage

         ' Rückgabewert für RS485 Kommunikation für Fehlerauswertung faken
         Temp_byte_6 = True

         ' ggf. Trace auf RS232 ausgeben
         #if Error_testmodus
            If Temp_byte_1 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RF-Kommunikation bei CMD 0x00"
            End If
            If Temp_byte_6 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RS485-Kommunikation bei CMD 0x00"
            End If
         #endif

      ' === Lichtanlage schalten 0x01 ===
      Case Rf_cmd_licht_schalten:

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Scart_proc_testmodus
            Print #3 , "Scart_verarbeitung: 0x01 - Lichtanlage an/aus"
            Print #3 , "Scart_verarbeitung: Parameter 1 : " ; Hex(rf_rx_parameter_1)
            Print #3 , "Scart_verarbeitung: Parameter 2 : " ; Hex(rf_rx_parameter_2)
         #endif

         ' prüfen ob Anlage eingeschaltet oder ausgeschaltet ist.
         If Anlagenflag = True Then
            ' Anlage eingeschaltet -> Anlage Ausschalten

            ' Akustisches Feedback unabhängig von Soundflag geben
            Gosub Sound_one_beep

            ' Botschaft an Slaves senden
            Temp_byte_6 = Rs485_licht_schalten(broadcastadresse , Licht_aus)

            ' Flag unmschalten
            Anlagenflag = False

            ' Temp-LED als Indikator missbrauchen
            Temp_led = Led_ein

            ' Wenn Anlage ausgeschaltet wird dann sollen auch alle Daten sofort gespeichert werden
            Gosub Ee_data_update                            ' Benutzt Temp_byte_1 und Temp_byte_2

         Else                                               ' Anlage eingeschaltet

            ' Anlage ausgeschaltet -> Anlage einschalten LUM

            ' Akustisches Feedback unabhängig von Soundflag geben
            Gosub Sound_double_beep

            ' Botschaft an Slaves senden
            Temp_byte_6 = Rs485_last_used_mode()

            ' Flag unmschalten
            Anlagenflag = True

            ' Temp-LED als Indikator missbrauchen
            Temp_led = Led_aus

            ' Scheduler erneut setzen
            Slave_temp_counter = Timercounter + Slave_temp_auswertung

         End If                                             ' Anlage ausgeschaltet

         ' Ist ein Fehler aufgetreten?
         If Temp_byte_6 = True Then
            ' Acknowledge für Slave inkl. Daten senden
            Temp_byte_1 = Scart_ack_send(true)
         Else
            ' Acknowledge für Slave inkl. Daten senden
            Temp_byte_1 = Scart_ack_send(false)
         End If

         ' ggf. Trace auf RS232 ausgeben
         #if Error_testmodus
            If Temp_byte_1 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RF-Kommunikation bei CMD 0x01"
            End If
            If Temp_byte_6 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RS485-Kommunikation bei CMD 0x01"
            End If
         #endif

      ' === Dimmer steuern 0x02 ===
      Case Rf_cmd_dimmer_schalten:

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Scart_proc_testmodus
            Print #3 , "Scart_verarbeitung: 0x02 - Dimmer einstellen"
            Print #3 , "Scart_verarbeitung: Parameter 1 : " ; Hex(rf_rx_parameter_1)       ' Dimmer
            Print #3 , "Scart_verarbeitung: Parameter 2 : " ; Hex(rf_rx_parameter_2)       ' Dimmwert
         #endif

         ' Parameter 1 enthält Auswahl Dimmer 1..8, 0xFF bedeutet Broadcast für alle Dimmer
         ' Parameter 2 enthält Auswahl der Dimmstufe

         ' Dimmer schalten
         Temp_byte_6 = Rs485_dimmwert_setzen(rf_rx_parameter_1 , Rf_rx_parameter_2)

         ' prüfen ob Anlage eingeschaltet oder ausgeschaltet ist.
         If Anlagenflag = True Then
            ' Anlage eingeschaltet

            ' Prüfen welcher Dimmer oder ob Broadcast

            If Rf_rx_parameter_1 = Broadcastadresse Then

               ' Behandlung aller Dimmer

               ' Daten persistent speichert

               ' Bemerkung: Indexrechnung zur Verdeutlichung
               '  Index Bedeutung   Dimmer   Berechnung
               '  1     Status      1        Dimmer * 2 - 1 = 1 * 2 - 1 = 1
               '  2     Dimmwert    1        Dimmer * 2     = 1 * 2     = 2
               '  3     Status      2        Dimmer * 2 - 1 = 2 * 2 - 1 = 3
               '  4     Dimmwert    2        Dimmer * 2     = 2 * 2     = 4
               '  5     Status      3        Dimmer * 2 - 1 = 3 * 2 - 1 = 5
               '  6     Dimmwert    3        Dimmer * 2     = 3 * 2     = 6
               '  7     Status      4        Dimmer * 2 - 1 = 4 * 2 - 1 = 7
               '  8     Dimmwert    4        Dimmer * 2     = 4 * 2     = 8
               '  9     Status      5        Dimmer * 2 - 1 = 5 * 2 - 1 = 9
               ' 10     Dimmwert    5        Dimmer * 2     = 5 * 2     = 10
               ' 11     Status      6        Dimmer * 2 - 1 = 6 * 2 - 1 = 11
               ' 12     Dimmwert    6        Dimmer * 2     = 6 * 2     = 12
               ' 13     Status      7        Dimmer * 2 - 1 = 7 * 2 - 1 = 13
               ' 14     Dimmwert    7        Dimmer * 2     = 7 * 2     = 14
               ' 15     Status      8        Dimmer * 2 - 1 = 8 * 2 - 1 = 15
               ' 16     Dimmwert    8        Dimmer * 2     = 8 * 2     = 16

               For Temp_byte_5 = 1 To 8 Step 1

                  ' Indexpointer auf Datenstruktur Dimmwert berechnen und Daten eintragen
                  Temp_byte_3 = Temp_byte_5 * 2
                  Ee_data_lightning_struct(temp_byte_3 ) = Rf_rx_parameter_2

                  #if Ee_data_indizierung_testmodus
                     Print #3 , "[5] Temp_byte_3 Ee_data_lightning_struct " ; Temp_byte_3 ; " = " ; Rf_rx_parameter_2
                  #endif

                  Ee_dimmer_update(temp_byte_5) = True      ' Flag für Update setzen

               Next Temp_byte_5

               ' Unverzüglich EEPROM-Datenstruktur in EEPROM schreiben auslösen
               Gosub Ee_data_update

               ' Acknowledge senden mit Anlage = EIN
               Temp_byte_1 = Scart_ack_send(true)

            Else                                            ' alle Dimmer

               ' Daten persistent speichert
               ' Indexpointer auf Datenstruktur Dimmwert berechnen und Daten eintragen
               Temp_byte_3 = Rf_rx_parameter_1 * 2
               Ee_data_lightning_struct(temp_byte_3 ) = Rf_rx_parameter_2

               #if Ee_data_indizierung_testmodus
                  Print #3 , "[6] Temp_byte_3 Ee_data_lightning_struct " ; Temp_byte_3 ; " = " ; Rf_rx_parameter_2
               #endif

               Ee_dimmer_update(rf_rx_parameter_1) = True   ' Flag für Update setzen
               ' Auf unverzügliches Dimmer speichern wird verzichtet da mit Dimmstufe gespielt werden kann
               ' Gosub Ee_data_update

               ' Acknowledge für Slave inkl. Daten senden
               Temp_byte_1 = Scart_send(rf_resp_status , Rf_rx_parameter_1)

            End If                                          ' einzelne Dimmer

            ' ggf. Sound ausgeben
            If Soundflag = Sound_ein Then
               Gosub Sound_one_beep
            End If                                          ' Soundausgabe

         Else                                               ' Anlage eingeschaltet
            ' Acknowledge senden mit Anlage = AUS
            Temp_byte_1 = Scart_ack_send(false)

            ' Rückgabewert für RS485 Kommunikation für Fehlerauswertung faken
            Temp_byte_6 = True

         End If                                             ' Anlage ausgeschaltet

         ' ggf. Trace auf RS232 ausgeben
         #if Error_testmodus

            If Temp_byte_1 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RF-Kommunikation bei CMD 0x02"
            End If

            If Temp_byte_6 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RS485-Kommunikation bei CMD 0x02"
            End If

         #endif

      ' === Sound schalten 0x03 ===
      Case Rf_cmd_sound_schalten:

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Scart_proc_testmodus
            Print #3 , "Scart_verarbeitung: 0x03 - Sound an/aus"
            Print #3 , "Scart_verarbeitung: Parameter 1 : " ; Hex(rf_rx_parameter_1)
            Print #3 , "Scart_verarbeitung: Parameter 2 : " ; Hex(rf_rx_parameter_2)
         #endif

         Select Case Rf_rx_parameter_1
            Case Sound_ein :
               #if Scart_proc_testmodus
                  Print #3 , "Schalte Sound EIN"
               #endif
               Gosub Sound_one_beep

            Case Sound_aus :
               #if Scart_proc_testmodus
                  Print #3 , "Schalte Sound AUS"
               #endif
               Gosub Sound_double_beep

         End Select

         ' Soundflag aus Variable global übernehmen
         Soundflag = Rf_rx_parameter_1

         ' Parameter persisten speichern
         Ee_data_sound = Soundflag

         ' Update an Slaves senden
         Temp_byte_6 = Rs485_sound_schalten(broadcastadresse , Soundflag )

         ' Acknowledge auf Broadcast senden in Abhänhigkeit des Anlagenstatus
         Temp_byte_1 = Scart_ack_send(anlagenflag)

         ' ggf. Trace auf RS232 ausgeben
         #if Error_testmodus

            If Temp_byte_1 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RF-Kommunikation bei CMD 0x03"
            End If

            If Temp_byte_6 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RS485-Kommunikation bei CMD 0x03"
            End If

         #endif

      ' === Alle Lampen schalten 0x04 ===
      Case Rf_cmd_gesamtlicht:

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Scart_proc_testmodus
            Print #3 , "Scart_verarbeitung: 0x04 - Alle Lampen an/aus"
            Print #3 , "Scart_verarbeitung: Parameter 1 : " ; Hex(rf_rx_parameter_1)
            Print #3 , "Scart_verarbeitung: Parameter 2 : " ; Hex(rf_rx_parameter_2)
         #endif

         ' prüfen ob Anlage eingeschaltet oder ausgeschaltet ist.
         If Anlagenflag = True Then
            ' Anlage eingeschaltet

            ' Update an Slaves senden
            Temp_byte_6 = Rs485_licht_schalten(broadcastadresse , Rf_rx_parameter_1)

            ' ggf. Sound ausgeben
            If Soundflag = Sound_ein Then
               Gosub Sound_one_beep
            End If                                          ' Soundausgabe

            ' Daten persistent speichert
            ' Indexpointer auf Datenstruktur Dimmwert berechnen und Daten eintragen

            ' Bemerkung: Indexrechnung zur Verdeutlichung
            '  Index Bedeutung   Dimmer   Berechnung
            '  1     Status      1        Dimmer * 2 - 1 = 1 * 2 - 1 = 1
            '  2     Dimmwert    1        Dimmer * 2     = 1 * 2     = 2
            '  3     Status      2        Dimmer * 2 - 1 = 2 * 2 - 1 = 3
            '  4     Dimmwert    2        Dimmer * 2     = 2 * 2     = 4
            '  5     Status      3        Dimmer * 2 - 1 = 3 * 2 - 1 = 5
            '  6     Dimmwert    3        Dimmer * 2     = 3 * 2     = 6
            '  7     Status      4        Dimmer * 2 - 1 = 4 * 2 - 1 = 7
            '  8     Dimmwert    4        Dimmer * 2     = 4 * 2     = 8
            '  9     Status      5        Dimmer * 2 - 1 = 5 * 2 - 1 = 9
            ' 10     Dimmwert    5        Dimmer * 2     = 5 * 2     = 10
            ' 11     Status      6        Dimmer * 2 - 1 = 6 * 2 - 1 = 11
            ' 12     Dimmwert    6        Dimmer * 2     = 6 * 2     = 12
            ' 13     Status      7        Dimmer * 2 - 1 = 7 * 2 - 1 = 13
            ' 14     Dimmwert    7        Dimmer * 2     = 7 * 2     = 14
            ' 15     Status      8        Dimmer * 2 - 1 = 8 * 2 - 1 = 15
            ' 16     Dimmwert    8        Dimmer * 2     = 8 * 2     = 16

            For Temp_byte_3 = 1 To 8 Step 1

               Temp_byte_4 = Temp_byte_3 * 2
               Decr Temp_byte_4
               Ee_data_lightning_struct(temp_byte_4) = Rf_rx_parameter_1

               #if Ee_data_indizierung_testmodus
                  Print #3 , "[7] Temp_byte_4 Ee_data_lightning_struct " ; Temp_byte_4 ; " = " ; Rf_rx_parameter_1
               #endif

               Ee_dimmer_update(temp_byte_3 ) = True        ' Flag für Update setzen

            Next Temp_byte_3

            ' Unverzüglich EEPROM-Datenstruktur in EEPROM schreiben auslösen
            Gosub Ee_data_update

            ' Acknowledge auf Broadcast senden in Abhänhigkeit des Anlagenstatus
            Temp_byte_1 = Scart_ack_send(true)

         Else                                               ' Anlage eingeschaltet
            ' Acknowledge senden mit Anlage = AUS
            Temp_byte_1 = Scart_ack_send(false)

            ' Rückgabewert für RS485 Kommunikation für Fehlerauswertung faken
            Temp_byte_6 = True

         End If                                             ' Anlage ausgeschaltet

         ' ggf. Trace auf RS232 ausgeben
         #if Error_testmodus
            If Temp_byte_1 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RF-Kommunikation bei CMD 0x04"
            End If
            If Temp_byte_6 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RS485-Kommunikation bei CMD 0x04"
            End If
         #endif

      ' === Dimmer schalten 0x05 ===
      Case Rf_cmd_dimmer_onoff:

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Scart_proc_testmodus
            Print #3 , "Scart_verarbeitung: 0x05 - Dimmer 1-8 an/aus"
            Print #3 , "Scart_verarbeitung: Parameter 1 : " ; Hex(rf_rx_parameter_1)       ' Dimmerauswahl 1..8
            Print #3 , "Scart_verarbeitung: Parameter 2 : " ; Hex(rf_rx_parameter_2)       ' Dimmer EIN oder AUS
         #endif

         ' prüfen ob Anlage eingeschaltet oder ausgeschaltet ist.
         If Anlagenflag = True Then
            ' Anlage eingeschaltet

            ' Update an Dimmer senden
            Temp_byte_6 = Rs485_licht_schalten(rf_rx_parameter_1 , Rf_rx_parameter_2)

            ' ggf. Sound ausgeben
            If Soundflag = Sound_ein Then
               Gosub Sound_one_beep
            End If                                          ' Soundausgabe

            ' Daten persistent speichert

            ' Bemerkung: Indexrechnung zur Verdeutlichung
            '  Index Bedeutung   Dimmer   Berechnung
            '  1     Status      1        Dimmer * 2 - 1 = 1 * 2 - 1 = 1
            '  2     Dimmwert    1        Dimmer * 2     = 1 * 2     = 2
            '  3     Status      2        Dimmer * 2 - 1 = 2 * 2 - 1 = 3
            '  4     Dimmwert    2        Dimmer * 2     = 2 * 2     = 4
            '  5     Status      3        Dimmer * 2 - 1 = 3 * 2 - 1 = 5
            '  6     Dimmwert    3        Dimmer * 2     = 3 * 2     = 6
            '  7     Status      4        Dimmer * 2 - 1 = 4 * 2 - 1 = 7
            '  8     Dimmwert    4        Dimmer * 2     = 4 * 2     = 8
            '  9     Status      5        Dimmer * 2 - 1 = 5 * 2 - 1 = 9
            ' 10     Dimmwert    5        Dimmer * 2     = 5 * 2     = 10
            ' 11     Status      6        Dimmer * 2 - 1 = 6 * 2 - 1 = 11
            ' 12     Dimmwert    6        Dimmer * 2     = 6 * 2     = 12
            ' 13     Status      7        Dimmer * 2 - 1 = 7 * 2 - 1 = 13
            ' 14     Dimmwert    7        Dimmer * 2     = 7 * 2     = 14
            ' 15     Status      8        Dimmer * 2 - 1 = 8 * 2 - 1 = 15
            ' 16     Dimmwert    8        Dimmer * 2     = 8 * 2     = 16

            ' Indexpointer auf Datenstruktur Status berechnen und Daten eintragen
            Temp_byte_3 = Rf_rx_parameter_1 * 2
            Decr Temp_byte_3
            Ee_data_lightning_struct(temp_byte_3) = Rf_rx_parameter_2

            #if Ee_data_indizierung_testmodus
               Print #3 , "[8] Temp_byte_3 Ee_data_lightning_struct " ; Temp_byte_3 ; " = " ; Rf_rx_parameter_2
            #endif

            Ee_dimmer_update(rf_rx_parameter_1) = True      ' Flag für Update setzen
            ' Unverzüglich EEPROM-Datenstruktur in EEPROM schreiben auslösen
            Gosub Ee_data_update

            ' Acknowledge für Slave inkl. Daten senden
            Temp_byte_1 = Scart_send(rf_resp_status , Rf_rx_parameter_1)

         Else                                               ' Anlage eingeschaltet
            ' Acknowledge senden mit Anlage = AUS
            Temp_byte_1 = Scart_ack_send(false)

            ' Rückgabewert für RS485 Kommunikation für Fehlerauswertung faken
            Temp_byte_6 = True

         End If                                             ' Anlage ausgeschaltet

         ' ggf. Trace auf RS232 ausgeben
         #if Error_testmodus
            If Temp_byte_1 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RF-Kommunikation bei CMD 0x05"
            End If
            If Temp_byte_6 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RS485-Kommunikation bei CMD 0x05"
            End If
         #endif

      ' === Demomodus schalten 0x06 ===
      Case Rf_cmd_demomodus:

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Scart_proc_testmodus
            Print #3 , "Scart_verarbeitung: 0x06 - Demomodus"
            Print #3 , "Scart_verarbeitung: Parameter 1 : " ; Hex(rf_rx_parameter_1)
            Print #3 , "Scart_verarbeitung: Parameter 2 : " ; Hex(rf_rx_parameter_2)
         #endif

         ' prüfen ob Anlage eingeschaltet oder ausgeschaltet ist.
         If Anlagenflag = True Then

            ' Acknowledge senden mit Anlage = EIN
            Temp_byte_1 = Scart_ack_send(true)

            ' Demomodus ausführen
            Gosub Rs485_demomode

            ' Normalmodus wieder herstellen

            ' Gesamtsystem in LUM schalten
            Temp_byte_6 = Rs485_last_used_mode()

         Else                                               ' Anlage eingeschaltet
            ' Acknowledge senden mit Anlage = AUS
            Temp_byte_1 = Scart_ack_send(false)

            ' Rückgabewert für RS485 Kommunikation für Fehlerauswertung faken
            Temp_byte_6 = True

         End If                                             ' Anlage ausgeschaltet

      ' === Dimmer schalten und Dimmwert setzen 0x07 ===
      Case Rf_cmd_dimmer_steuern:

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Scart_proc_testmodus
            Print #3 , "Scart_verarbeitung: 0x07 -Dimmer schalten und Dimmwert setzen"
            Print #3 , "Scart_verarbeitung: Parameter 1 : " ; Hex(rf_rx_parameter_1)       ' Dimmerauswahl 1..8
            Print #3 , "Scart_verarbeitung: Parameter 2 : " ; Hex(rf_rx_parameter_2)       ' Dimmer EIN oder AUS
         #endif

         ' Bemerkung zu Parameter 1:
         ' Low-Nibble  1..8 = Dimmer 1..8
         '             0x0F = alle Dimmer
         ' High-Nibble 0x80 = Dimmer einschalten (Bit 7)
         '             0x00 = Dimmer ausschalten (Bit 7)

         ' prüfen ob Anlage eingeschaltet oder ausgeschaltet ist.
         If Anlagenflag = True Then
            ' Anlage eingeschaltet

            ' Aufgabe zerlegen

            ' Dimmeradresse erzeugen
            Temp_byte_4 = Rf_rx_parameter_1 And &H0F        ' Maske über LOW Nibble
            If Temp_byte_4 = &H0F Then
               Temp_byte_4 = Broadcastadresse
            End If

            ' Schaltzustand herstellen
            Temp_byte_5 = Rf_rx_parameter_1
            Shift Temp_byte_5 , Right , 7
            Temp_byte_5 = Temp_byte_5 And &H01

            ' Function Rs485_licht_dimmer_schalten(byval Slave As Byte , Byval Status As Byte , Byval Dimmerwert As Byte , Byval Soundstatus As Byte) As Byte

            ' Update an Dimmer senden
            #if Scart_proc_testmodus
               Print #3 , "Scart_verarbeitung: Rs485_licht_dimmer_schalten"
               Print #3 , "Scart_verarbeitung: Parameter 1 : " ; Hex(temp_byte_4)
               Print #3 , "Scart_verarbeitung: Parameter 2 : " ; Hex(temp_byte_5)
               Print #3 , "Scart_verarbeitung: Parameter 3 : " ; Hex(rf_rx_parameter_2)
               Print #3 , "Scart_verarbeitung: Parameter 4 : " ; Hex(soundflag)
            #endif
            Temp_byte_6 = Rs485_licht_dimmer_schalten(temp_byte_4 , Temp_byte_5 , Rf_rx_parameter_2 , Soundflag )

            ' prüfen welcher Dimmer oder ob Broadcast

            If Temp_byte_4 = Broadcastadresse Then

               ' Behandlung aller Dimmer

               ' Daten persistent speichert

               ' Bemerkung: Indexrechnung zur Verdeutlichung
               '  Index Bedeutung   Dimmer   Berechnung
               '  1     Status      1        Dimmer * 2 - 1 = 1 * 2 - 1 = 1
               '  2     Dimmwert    1        Dimmer * 2     = 1 * 2     = 2
               '  3     Status      2        Dimmer * 2 - 1 = 2 * 2 - 1 = 3
               '  4     Dimmwert    2        Dimmer * 2     = 2 * 2     = 4
               '  5     Status      3        Dimmer * 2 - 1 = 3 * 2 - 1 = 5
               '  6     Dimmwert    3        Dimmer * 2     = 3 * 2     = 6
               '  7     Status      4        Dimmer * 2 - 1 = 4 * 2 - 1 = 7
               '  8     Dimmwert    4        Dimmer * 2     = 4 * 2     = 8
               '  9     Status      5        Dimmer * 2 - 1 = 5 * 2 - 1 = 9
               ' 10     Dimmwert    5        Dimmer * 2     = 5 * 2     = 10
               ' 11     Status      6        Dimmer * 2 - 1 = 6 * 2 - 1 = 11
               ' 12     Dimmwert    6        Dimmer * 2     = 6 * 2     = 12
               ' 13     Status      7        Dimmer * 2 - 1 = 7 * 2 - 1 = 13
               ' 14     Dimmwert    7        Dimmer * 2     = 7 * 2     = 14
               ' 15     Status      8        Dimmer * 2 - 1 = 8 * 2 - 1 = 15
               ' 16     Dimmwert    8        Dimmer * 2     = 8 * 2     = 16

               For Temp_byte_7 = 1 To 8 Step 1

                  ' Indexpointer auf Datenstruktur Dimmwert berechnen und Daten eintragen
                  Temp_byte_3 = Temp_byte_7 * 2             ' Dimmwert
                  Temp_byte_8 = Temp_byte_3 - 1             ' Status

                  Ee_data_lightning_struct(temp_byte_8 ) = Temp_byte_5       ' Status schreiben
                  Ee_data_lightning_struct(temp_byte_3 ) = Rf_rx_parameter_2       ' Dimmwert schreiben

                  #if Ee_data_indizierung_testmodus
                     Print #3 , "[x5] Temp_byte_3 Ee_data_lightning_struct " ; Temp_byte_3 ; " = " ; Rf_rx_parameter_2
                  #endif

                  Ee_dimmer_update(temp_byte_7) = True      ' Flag für Update setzen

               Next Temp_byte_7                             ' Schleife über alle 8 Dimmer

               ' Unverzüglich EEPROM-Datenstruktur in EEPROM schreiben auslösen
               Gosub Ee_data_update

               ' Acknowledge senden mit Anlage = EIN
               Temp_byte_1 = Scart_ack_send(true)

            Else                                            ' Broadcastbotschaft

               ' Botschaft war nicht Broadcast also nur Daten für einen Dimmer speichern

               ' Indexpointer auf Datenstruktur Status berechnen und Daten eintragen
               ' Temp_byte_4 enthält Dimmeradresse

               ' Indexpointer auf Datenstruktur Dimmwert berechnen und Daten eintragen
               Temp_byte_3 = Temp_byte_4 * 2                ' Dimmwert
               Temp_byte_8 = Temp_byte_3 - 1                ' Status

               Ee_data_lightning_struct(temp_byte_8 ) = Temp_byte_5       ' Status schreiben
               Ee_data_lightning_struct(temp_byte_3 ) = Rf_rx_parameter_2       ' Dimmwert schreiben

               #if Ee_data_indizierung_testmodus
                  Print #3 , "[x8] Temp_byte_3 Ee_data_lightning_struct " ; Temp_byte_3 ; " = " ; Rf_rx_parameter_2
               #endif

               Ee_dimmer_update(temp_byte_4) = True         ' Flag für Update setzen
               ' Unverzüglich EEPROM-Datenstruktur in EEPROM schreiben auslösen
               Gosub Ee_data_update

               ' Acknowledge für Slave inkl. Daten senden
               Temp_byte_1 = Scart_send(rf_resp_status , Temp_byte_4)

            End If                                          ' Ein Dimmer adressiert

            ' ggf. Sound ausgeben
            If Soundflag = Sound_ein Then
               Gosub Sound_one_beep
            End If                                          ' Soundausgabe

         Else                                               ' Anlage eingeschaltet
            ' Acknowledge senden mit Anlage = AUS
            Temp_byte_1 = Scart_ack_send(false)

            ' Rückgabewert für RS485 Kommunikation für Fehlerauswertung faken
            Temp_byte_6 = True

         End If                                             ' Anlage ausgeschaltet

         ' ggf. Trace auf RS232 ausgeben
         #if Error_testmodus
            If Temp_byte_1 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RF-Kommunikation bei CMD 0x05"
            End If
            If Temp_byte_6 <> True Then
               Print #3 , "Scart_verarbeitung: Fehler in RS485-Kommunikation bei CMD 0x05"
            End If
         #endif

   End Select                                               ' Dimmerkommandos

   ' Prüfen ob ein RF-Kommunikationsproblem aufgetreten
   If Temp_byte_1 = False Then
      ' JA

      ' Beim Einstieg in Funktion wird Temp_byte_1 auf false vorinitialisiert.
      ' Beim Durchlauf wird eine SCART-Funktion durchlaufen deren Ergebnis die
      ' Variable Temp_byte_1 aufnimmt.

      ' ggf. Trace auf RS232 ausgeben
      #if Error_testmodus
         Print #3 , "[10] Error(3): RF Kommunikationsfehler"
      #endif

      ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
      ' ## Error ##
      Error_flags(3) = True                                 ' Fehler in Matrix eintragen
      Err_global_flag = True

   End If                                                   ' RF Kommunikationsfehler

   ' Prüfen ob ein RS485-Kommunikationsproblem aufgetreten
   If Temp_byte_6 = False Then
      ' JA

      ' ggf. Trace auf RS232 ausgeben
      #if Error_testmodus
         Print #3 , "[11] Error(4): RS485 Kommunikationsfehler im Block Verarbeitung"
      #endif

      ' ## Error ##
      ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
      Error_flags(4) = True                                 ' Fehler in Matrix eintragen
      Err_global_flag = True

   End If                                                   ' RF Kommunikationsfehler

   ' Prüfen ob ein RF-Datenauswertungsproblem aufgetreten
   If Rf_rx_errorflag = True Then
      ' JA

      ' ggf. Trace auf RS232 ausgeben
      #if Error_testmodus
         Print #3 , "[9] Error(8): RF Unplausible Daten empfangen"
      #endif

      ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
      ' ## Error ##
      Error_flags(8) = True                                 ' Fehler in Matrix eintragen
      Err_global_flag = True

      ' Fehlerflag wieder zurücksetzen
      Rf_rx_errorflag = False

   End If                                                   ' RF Kommunikationsfehler

Return
'-- End Scart_receive_check ---------------------------------------------------

' ****************************
' * DS1820: Temperatursensor *
' ****************************

'------------------------------------------------------------------------------
' Ds1820 - Gosub-Routine: Ds1820_konfig
' Funktion konfiguriert den Ds1820 temperatursensor bzw. ermittelt für globale
' Variaben die relevanten Arbeitswerte
'------------------------------------------------------------------------------
Ds1820_konfig:

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

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Temp_testmodus
      Print #3 , "Enter Ds1820_konfig"
   #endif

   ' Auslesen  der Anzahl aller am 1Wire-Bus vorhandenen Devices
   Ds1820_device_count = 1wirecount()

   ' Auslesen des 64-Bit breiten ROM Codes für gefundenes Device in Array
   Ds1820_rom_code(1) = 1wsearchfirst()

Return
'-- End Ds1820_konfig ---------------------------------------------------------

'------------------------------------------------------------------------------
' DS1820 - Gosub-Routine: Ds1820_start_measurement
' Funktion startet globale Temperaturmessung für alle Sensoren
'------------------------------------------------------------------------------
Ds1820_start_measurement:

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

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Temp_testmodus
      Print #3 , "Enter Ds1820_start_measurement"
   #endif

   ' Gobales Fehlerflag zurücksetzen
   Ds1820_error_flag = 0

   1wreset                                                  ' 1Wire Master fährt RESET

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Temp_testmodus
      Ds1820_error_flag = Err                               ' Fehlerflag übergeben
      Print #3 , "Ds1820_start_measurement: Reset-ERR : " ; Ds1820_error_flag
   #endif

   ' Alle angeschlossenen DS18S20 zum Messen veranlassen
   1wwrite Ds1820_skip_rom_command                          ' Senden von Skip ROM command
   1wwrite Ds1820_convert_t_command                         ' Convert T

Return
'-- End Ds1820_start_measurement ----------------------------------------------

'------------------------------------------------------------------------------
' DS1820 - Gosub-Routine: Ds1820_measurement
' Funktion startet globale Temperaturmessung für alle Sensoren und macht
' Auswertung auf aktiven Sensor
'------------------------------------------------------------------------------
Ds1820_measurement:

   ' Achtung:
   ' Aus dieser Routine wurde die Funktion zum Starten der Messung entfernt.
   ' Zwischen Start und Auswertung benötigt der Chip eine Zeit von ca. 750 ms
   ' Diese Zeit wir bei normalem Systemstart durch den Scheduler eingehalten.
   ' Der erste Messwert der Temperatur nach Systemstart ist erst nach Scheduleraufruf
   ' ca. 5 Sekunden später vorhanden.

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

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Temp_testmodus
      Print #3 , "Enter Ds1820_measurement"
   #endif

   ' Measurement starten
   Gosub Ds1820_start_measurement

   ' Den Sensor auswählen
   1wverify Ds1820_rom_code(1)

   ' Kommando Scratch-Pad aus Sensor auslesen
   1wwrite Ds1820_scratchpad_command                        ' Senden des Lesekommandos

   ' Scratchpad aus Sensor auslesen
   Ds1820_scratchpad(1) = 1wread(9)

   ' CRC Überprüfung und Messert berechnen
   If Ds1820_scratchpad(9) = Crc8(ds1820_scratchpad(1) , 8) Then

      ' Messung war erfolgreich
      Ds1820_messwert = Makeint(ds1820_scratchpad(1) , Ds1820_scratchpad(2))

      ' In Abhängigkeit der Konstante Traceausgabe schreiben
      #if Temp_testmodus
         Print #3 , "Ds1820_measurement: CRC OK, Messwert plausibel"
         Print #3 , "Ds1820_measurement: Integerwert : " ; Ds1820_messwert
      #endif
   Else                                                     ' Messwert erfassen
      ' Es ist ein CRC Fehler aufgetreten

      ' In Abhängigkeit der Konstante Traceausgabe schreiben
      #if Temp_testmodus
         Print #3 , "Ds1820_measurement: CRC Fehler bei Messwert aufgetreten"
      #endif

      Ds1820_messwert = &HFFCE                              ' Temperaturwert auf -25°C als Fehlerkennzeichnung
   End If                                                   ' Fehlerbehandlung

   Temp_single_1 = Ds1820_messwert                          ' Temperatur auslesen und aufrunden
   Temp_single_1 = Temp_single_1 * 0.5

   Ds1820_temperatur = Temp_single_1                        ' Temperatur auf Byte casten

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Temp_testmodus
      Print #3 , "Ds1820_measurement: Temperatur : " ; Ds1820_temperatur
   #endif

Return
'-- End Ds1820_measurement ----------------------------------------------------

'------------------------------------------------------------------------------
' DS1820 - Gosub-Routine: Ds1820_konfig_detect
' Funktion liest alle relevanten und verfügbaren 1-Wire Konfigurationsinfor-
' mationen aus und gibt diese aus
'------------------------------------------------------------------------------
Ds1820_konfig_detect:

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

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Temp_testmodus
      Print #3 , "Enter Ds1820_konfig_detect"
   #endif

   ' Ausgabe der Anzahl aller am 1Wire-Bus vorhandenen Devices
   Print #3 , "Ds1820_konfig_detect: Anzahl 1Wire-Devices: " ; Ds1820_device_count

   ' Überprüfen ob empfangener Code gemäß CRC korrekt
   Temp_byte_1 = Crc8(ds1820_rom_code(1) , 7 )
   If Ds1820_rom_code(8) = Temp_byte_1 Then

      Print #3 , "Ds1820_konfig_detect: CRC des empfangenen ROM-Codes OK"
      ' Empfangenen Bytes in Hex ausgeben
      Print #3 , "Ds1820_konfig_detect: ROM-Code : " ;

      For Temp_byte_2 = 8 To 1 Step -1
         Print #3 , Hex(ds1820_rom_code(temp_byte_2)) ; " " ;
      Next Temp_byte_2

      Print #3 , ""
   Else                                                     ' Konfiguration ausgeben
      Print #3 , "Ds1820_konfig_detect: CRC des empfangenen ROM-Codes FALSCH"
   End If                                                   ' Fehlerbehandlung

Return
'-- End Ds1820_konfig_detect --------------------------------------------------

' *******************
' * RS485 Systembus *
' *******************

'------------------------------------------------------------------------------
' Gosub-Routine: Rs485_receive_check
' Routine überprüft ob im Empfangsbuffer Zeichen vorliegen, liest diese und
' baut die Empfangsstruktur auf. Danach wird ein Flag gesetzt, dass eine
' Botschafft erfolgreich empfangen wurde.
' Das Empfangen neuer Botschaften ist über eine Sempahore verriegelt. Erst
' wenn die Empfangene Botschaft verarbeitet ist, wird der Empfang einer neuen
' Botschaft zugelassen.
'------------------------------------------------------------------------------
Rs485_receive_check:

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

   ' Prüfen ob eib Zeichen im Empfangsbuffer wartet
   If Ischarwaiting(#1) <> 0 Then
      ' JA, es wartet ein Zeichen

      Rx_buffer(rx_bufferindex) = Inkey(#1)
      #if Rs485_testmodus
         Print #3 , Hex(rx_buffer(rx_bufferindex)) ; " ";
      #endif

      Incr Rx_bufferindex

      ' Prüfen ob alle Datenfelder korrekt empfangen
      If Rx_bufferindex > Nachrichtenlaenge Then
         'JA, Alle Datenfelder komplett empfangen

         #if Rs485_testmodus
            Print #3 , " "
         #endif

         Rx_bufferindex = 1                                 'Index zurücksetzen

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Rs485_testmodus
            Print #3 , "Rs485_receive_check:"
            Print #3 , "Rx_zieladresse  : " ; Hex(rx_zieladresse)
            Print #3 , "Rx_quelladresse : " ; Hex(rx_quelladresse)
            Print #3 , "Rx_framelength  : " ; Hex(rx_framelength)
            Print #3 , "Rx_kommando     : " ; Hex(rx_kommando)
            Print #3 , "Rx_licht        : " ; Hex(rx_licht)
            Print #3 , "Rx_dimmstufe    : " ; Hex(rx_dimmstufe)
            Print #3 , "Rx_temperatur   : " ; Hex(rx_temperatur)
            Print #3 , "Rx_sound        : " ; Hex(rx_sound)
            Print #3 , "Rx_checksumme   : " ; Hex(rx_checksumme)
            Print #3 , " "
         #endif

         ' Prüfung ob Checksumme gültig
         Temp_word_1 = Crc16(rx_buffer(1) , 8)
         If Temp_word_1 = Rx_checksumme Then
            ' JA, Checksumme ist korrekt

            ' In Abhängigkeit der Konstante Traceausgabe schreiben
            #if Rs485_testmodus
               Print #3 , "Rs485_receive_check: CRC korrekt!"
            #endif

            ' Prüfung ob empfangenes Datenpaket auch für "mich"
            If Rx_zieladresse = Rs485_slaveadresse Then
               ' JA, ich bin gemeint

               ' In Abhängigkeit der Konstante Traceausgabe schreiben
               #if Rs485_testmodus
                  Print #3 , "Rs485_receive_check: Message für mich!"
               #endif

               ' In Abhängigkeit der Konstante Traceausgabe schreiben
               #if Rs485_testmodus
                  Print #3 , "Rs485_receive_check: Rx " ; Hex(rx_zieladresse) ; " " ; Hex(rx_quelladresse) ; " " ; Hex(rx_framelength) ; " " ; Hex(rx_kommando) ; " " ; Hex(rx_licht) ; " " ; Hex(rx_dimmstufe) ; " " ; Hex(rx_temperatur) ; " " ; Hex(rx_sound) ; " " ; Hex(rx_checksumme)
               #endif

               ' Flag setzen dass Datenpaket empfangen wurde
               Rs485_data_received = True
            Else                                            ' Ich war nicht gemeint
               ' In Abhängigkeit der Konstante Traceausgabe schreiben
               #if Rs485_testmodus
                  Print #3 , "Rs485_receive_check: Message für NICHT mich!"
                  Print #3 , "[4] Error(5): RS485 Kommunikationsfehler im ReceiveCheck"
               #endif

               ' ## Error ##
               ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
               Error_flags(5) = True                        ' Fehler in Matrix eintragen
               Err_global_flag = True

            End If                                          ' Prüfung ob ich gemeint bin
         Else                                               ' Checksummenprüfung
            ' In Abhängigkeit der Konstante Traceausgabe schreiben
            #if Rs485_testmodus
               Print #3 , "Rs485_receive_check: CRC falsch!"
               Print #3 , "Rs485_receive_check: Soll : " ; Hex(temp_word_1)
               Print #3 , "Rs485_receive_check: Ist  : " ; Hex(rx_checksumme)
            #endif

            ' Eingangsbuffer und Ausgangsbuffer löschen
            ' Clear Serialin
            ' Clear Serialout

            ' RS485 Checksummenfehler in Fehlerstruktur eintragen

            ' ggf. Trace auf RS232 ausgeben
            #if Error_testmodus
               Print #3 , "[5] Error(5): RS485 Kommunikationsfehler im ReceiveCheck"
            #endif

            ' ## Error ##
            ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
            Error_flags(5) = True                           ' Fehler in Matrix eintragen
            Err_global_flag = True

         End If                                             ' Checksummenprüfung
      End If                                                ' Botschaft vollständig
   End If                                                   ' Wartet ein Zeichen?

Return
'-- End Rs485_receive_check ---------------------------------------------------

'------------------------------------------------------------------------------
' Gosub-Routine: Rs485_send
' Die Routine sendet die in der Sendestruktur stehenden Daten über RS485
'------------------------------------------------------------------------------
Rs485_send:

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

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_send"
   #endif

   ' Checksumme setzen
   Tx_checksumme = Crc16(tx_buffer(1) , 8)

   ' Empfangsbuffer leeren
   Clear Serialin

   ' Bytes übertragen
   Printbin #1 , Tx_buffer(1)

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_send: Tx: " ;
      For Temp_byte_1 = 1 To Nachrichtenlaenge
         Print #3 , Hex(tx_buffer(temp_byte_1)) ; " " ;
      Next Temp_byte_1
      Print #3 , " *"
      Print #3 , ""                                         ' Leerzeile

   #endif

Return
'-- End Rs485_send -----------------------------------------------------------

'------------------------------------------------------------------------------
' Gosub-Routine: Rs485_demomode
' Die Routine steuert den Demomodus für die Dimmermodule
'------------------------------------------------------------------------------
Rs485_demomode:

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

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Rs485_testmodus
      Print #3 , "Enter Rs485_demomode"
   #endif

   ' In dieser Funktion ist der Demo Sweep-Modus implementiert

   Temp_byte_5 = 9                                          ' Sekunden für Wartezeit

   ' Alle Dimmer Dimmwert auf NULL setzen und dimmer einschalten
   Temp_byte_6 = Rs485_licht_dimmer_schalten(broadcastadresse , Licht_ein , 1 , Soundflag)
   Wait 2

   ' Dimmer 1 hoch                                                  -> 0000 0001
   Temp_byte_6 = Rs485_sweep_mode(slave_1_adresse , Sweep_up)
   Wait Temp_byte_5

   ' Dimmer 2 hoch                                                  -> 0000 0011
   Temp_byte_6 = Rs485_sweep_mode(slave_2_adresse , Sweep_up)
   Wait Temp_byte_2

   ' Dimmer 3 hoch und 1 runter                                     -> 0000 0110
   Temp_byte_6 = Rs485_sweep_mode(slave_3_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_1_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 4 hoch und 2 runter                                     -> 0000 1100
   Temp_byte_6 = Rs485_sweep_mode(slave_4_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_2_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 5 hoch und 3 runter                                     -> 0001 1000
   Temp_byte_6 = Rs485_sweep_mode(slave_5_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_3_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 6 hoch und 4 runter                                     -> 0011 0000
   Temp_byte_6 = Rs485_sweep_mode(slave_6_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_4_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 7 hoch und 5 runter                                     -> 0110 0000
   Temp_byte_6 = Rs485_sweep_mode(slave_7_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_5_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 8 hoch und 6 runter                                     -> 1100 0000
   Temp_byte_6 = Rs485_sweep_mode(slave_8_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_6_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 7 runter                                                -> 1000 0000
   Temp_byte_6 = Rs485_sweep_mode(slave_7_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 8 runter                                                -> 0000 0000
   Temp_byte_6 = Rs485_sweep_mode(slave_8_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 1 und 8 hoch                                            -> 1000 0001
   Temp_byte_6 = Rs485_sweep_mode(slave_1_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_8_adresse , Sweep_up)
   Wait Temp_byte_5

   ' Dimmer 2 und 7 hoch                                            -> 1100 0011
   Temp_byte_6 = Rs485_sweep_mode(slave_2_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_7_adresse , Sweep_up)
   Wait Temp_byte_5

   ' Dimmer 3 hoch und 1 runter                                     -> 1100 0110
   Temp_byte_6 = Rs485_sweep_mode(slave_3_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_1_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 4 hoch und 2 runter                                     -> 1100 1100
   Temp_byte_6 = Rs485_sweep_mode(slave_4_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_2_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 5 und 6 hoch und 7 und 8 runter                         -> 0011 1100
   Temp_byte_6 = Rs485_sweep_mode(slave_5_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_6_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_7_adresse , Sweep_down)
   Temp_byte_6 = Rs485_sweep_mode(slave_8_adresse , Sweep_down)
   Wait Temp_byte_5

   ' Dimmer 1 und 2 hoch                                            -> 0011 1111
   Temp_byte_6 = Rs485_sweep_mode(slave_1_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_2_adresse , Sweep_up)
   Wait Temp_byte_5

   ' Dimmer 7 und 8 hoch                                            -> 1111 1111
   Temp_byte_6 = Rs485_sweep_mode(slave_7_adresse , Sweep_up)
   Temp_byte_6 = Rs485_sweep_mode(slave_8_adresse , Sweep_up)
   Wait Temp_byte_5

   ' Alle Dimmer runter                                             -> 0000 0000
   Temp_byte_6 = Rs485_sweep_mode(broadcastadresse , Sweep_down)
   Wait Temp_byte_5

Return
'-- End Rs485_demomode --------------------------------------------------------

' *********
' * Sound *
' *********

'------------------------------------------------------------------------------
' Sound - Gosub-Routine: Sound_one_beep
' Routine gibt einen einzelnen Beep aus
'------------------------------------------------------------------------------
Sound_one_beep:

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

   ' 1x Peep ausgeben. Peepdauer wird über Konstante gesteuert
   Piezo = Sound_ein
   Waitms Sound_ein_delay
   Piezo = Sound_aus

Return
'-- End Sound_one_beep --------------------------------------------------------

'------------------------------------------------------------------------------
' Sound - Gosub-Routine: Sound_double_beep
' Routine gibt einen zwei Beep's aus
'------------------------------------------------------------------------------
Sound_double_beep:

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

   ' 2x Peep ausgeben. Peepdauer wird über Konstante gesteuert
   Piezo = Sound_ein
   Waitms Sound_ein_delay
   Piezo = Sound_aus
   Waitms Sound_pause_delay
   Piezo = Sound_ein
   Waitms Sound_ein_delay
   Piezo = Sound_aus

Return
'-- End Sound_double_beep -----------------------------------------------------

' *******
' * LCD *
' *******

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_beleuchtung_an
' Routine schaltet die Beleuchtung ein
'------------------------------------------------------------------------------
Lcd_beleuchtung_an:

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

   #if Lcd_testmodus
      Print #3 , "Enter Lcd_beleuchtung_an"
   #endif

   Lcd_light = Licht_ein

Return
'-- End Lcd_beleuchtung_an ----------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_beleuchtung_aus
' Routine schaltet die Beleuchtung aus
'------------------------------------------------------------------------------
Lcd_beleuchtung_aus:

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

   #if Lcd_testmodus
      Print #3 , "Enter Lcd_beleuchtung_aus"
   #endif
   Lcd_light = Licht_aus

Return
'-- End Lcd_beleuchtung_aus ---------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_display_aus
' Routine schaltet die Spannungsversorgung für das Display aus
'------------------------------------------------------------------------------
Lcd_display_aus:

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

   #if Lcd_testmodus
      Print #3 , "Enter Lcd_display_aus"
   #endif

   ' Instruction Display ON/OFF gemäß LCD Befehlskatalog
   _temp1 = &B00001000
   !Call _Lcd_control

Return
'-- End Lcd_display_aus -------------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_display_an
' Routine schaltet die Spannungsversorgung für das Display an
'------------------------------------------------------------------------------
Lcd_display_an:

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

   #if Lcd_testmodus
      Print #3 , "Enter Lcd_display_an"
   #endif

   ' Instruction Display ON/OFF gemäß LCD Befehlskatalog
   _temp1 = &B00001100
   !Call _Lcd_control

Return
'-- End Lcd_display_an --------------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_contrastset
' Routine berechnen neue Kontrastwerte und steuert direkt den
' Kontroller des Display an.
'------------------------------------------------------------------------------
Lcd_kontrastset:                                            ' Kontrasteinstellung Display

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

   #if Lcd_testmodus
      Print #3 , "Enter Lcd_kontrastset" ; Kontrastwert
   #endif

   ' Verarbeitung des Kontrastwertes für High-Byte und Low-Byte
   Temp_byte_1 = Kontrastwert And &B00001111
   Temp_byte_1 = Temp_byte_1 + &B01110000

   Temp_byte_2 = Kontrastwert
   Shift Temp_byte_2 , Right , 4
   Temp_byte_2 = Temp_byte_2 And &B00000011
   Temp_byte_2 = Temp_byte_2 + &B01010100

   ' Instruction Table 1 einstellen [0,1]
   _temp1 = &B00101001
   '!rCall _Lcd_control
   !Call _Lcd_control

   ' Tempvar_1 = &B0111xxxx für Kontrast Set Instruction Table 1 - Low Byte
   _temp1 = Temp_byte_1
   '!rCall _Lcd_control
   !Call _Lcd_control

   ' Temovar_2 = &B010101xx für Kontrast Set Instruction Table 1 - High Byte
   _temp1 = Temp_byte_2
   '!rCall _Lcd_control
   !Call _Lcd_control

   ' Zurückschalten auf Instruction Table 0 [0,0]
   _temp1 = &B00101000
   '!rCall _Lcd_control
   !Call _Lcd_control

Return
'-- End Lcd_kontrastset -------------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_print
' Die Routine gibt den Lcd_textbuffer für das Menü auf dem LCD-Display aus
'Result:     LCD
'------------------------------------------------------------------------------
Lcd_print:

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

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Lcd_testmodus                                        ' Trace
      Print #3 , "Enter Lcd_print"
      Print #3 , "  Menue_ausgabeflags : " ; Menue_ausgabeflags
      Print #3 , "  Linie 1            : " ; Menue_lcd_textbuffer(1)
      Print #3 , "  Linie 2            : " ; Menue_lcd_textbuffer(2)
      Print #3 , "  Linie 3            : " ; Menue_lcd_textbuffer(3)
   #endif                                                   ' Trace

   Cls                                                      ' Clear Screen

   Select Case Menue_ausgabeflags
      Case 1:
         ' Nur 1. Zeile ausgaben
         ' Locate 1 , 1 : Lcd Menue_lcd_textbuffer(1)
         Call Lcd_writesingleline(1 , Menue_lcd_textbuffer(1))
      Case 2:
         ' Nur 2. Zeile ausgaben
         ' Locate 2 , 1 : Lcd Menue_lcd_textbuffer(2)
         Call Lcd_writesingleline(2 , Menue_lcd_textbuffer(2))
      Case 4:
         ' Nur 3. Zeile ausgaben
         ' Locate 3 , 1 : Lcd Menue_lcd_textbuffer(3)
         Call Lcd_writesingleline(3 , Menue_lcd_textbuffer(3))
      Case 3:
         ' 1. und 2. Zeile ausgeben
         ' Locate 1 , 1 : Lcd Menue_Lcd_textbuffer(1)
         ' Locate 2 , 1 : Lcd Menue_Lcd_textbuffer(2)
         Call Lcd_writedoubleline(1 , 2 , Menue_lcd_textbuffer(1) , Menue_lcd_textbuffer(2) )
      Case 5:
         ' 1. und 3. Zeile ausgeben
         ' Locate 1 , 1 : Lcd Menue_Lcd_textbuffer(1)
         ' Locate 3 , 1 : Lcd Menue_Lcd_textbuffer(3)
         Call Lcd_writedoubleline(1 , 3 , Menue_lcd_textbuffer(1) , Menue_lcd_textbuffer(3) )
      Case 6:
         ' 2. und 3. Zeile ausgeben
         ' Locate 2 , 1 : Lcd Menue_Lcd_textbuffer(2)
         ' Locate 3 , 1 : Lcd Menue_Lcd_textbuffer(3)
         Call Lcd_writedoubleline(2 , 3 , Menue_lcd_textbuffer(2) , Menue_lcd_textbuffer(3) )
      Case 7:
         ' Alle Zeilen ausgeben
         ' Locate 1 , 1 : Lcd Menue_Lcd_textbuffer(1)
         ' Locate 2 , 1 : Lcd Menue_Lcd_textbuffer(2)
         ' Locate 3 , 1 : Lcd Menue_Lcd_textbuffer(3)
         Call Lcd_writetrippleline(menue_lcd_textbuffer(1) , Menue_lcd_textbuffer(2) , Menue_lcd_textbuffer(3) )
   End Select                                               ' Menüausgabeflag

   Menue_state_renew = 0

Return
'-- End Lcd_print -------------------------------------------------------------

' ***********
' * EEPROM  *
' ***********

'------------------------------------------------------------------------------
' EE-Gosubroutine: Ee_init_internal_eeprom
' Subroutine überprüft die Datenkonsitenz aufgrund des verwendeten Versions-
' Index und führt ggf. eine Grundinitialisierung der Datenstrukturen durch.
'------------------------------------------------------------------------------
Ee_init_internal_eeprom:

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

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Eeprom_testmodus                                     ' Trace
      Print #3 , "Enter Ee_init_internal_eeprom"
   #endif                                                   ' Trace

   ' Zur Vollständigkeit hier nochmals die Datenstruktur der internen Daten
   ' EE: EEPROM Datenstruktur internes EEPROM - Setting-Daten
   ' Dim Ee_data_version_intern As Eram Byte At &H0000           ' Speicherstelle für Datenversion
   ' Dim Ee_data_temperature As Eram Byte At &H0001              ' Speicherstelle für Temperaturschwelle

   ' Aktuelle Datenversion des internen EEPROM lesen
   Temp_byte_1 = Ee_data_version_intern

   ' Ist die Datenversion korrekt
   If Temp_byte_1 <> Akt_internal_ee_version Then

      ' NEIN, aktuelle Daten neu speichern

      ' Wenn Konstante gesetzt Trace Output schreiben
      #if Eeprom_testmodus                                  ' Trace
         Print #3 , "Ee_init_internal_eeprom: Datenversion intern stimmt nicht"
         Print #3 , "Ee_init_internal_eeprom: Initialisiere internes EEPROM neu!"
      #endif                                                ' Trace

      ' Datenstruktur internes EEPROM entspricht nicht dem aktuellen Stand
      ' => Datenstruktur neu anlegen bzw. neue Defaultwerte setzen.
      Ee_data_version_intern = Akt_internal_ee_version
      Ee_data_temperature = Uebertemperatur_default
      Ee_data_sound = Sound_default
   End If                                                   ' Datenversion?

   ' Übergabe der Daten in globale Arbeitsvariablen
   Uebertemperatur = Ee_data_temperature
   Soundflag = Ee_data_sound

   ' Gelesene Daten auf Plausibilität prüfen
   ' Bemerkung:
   ' Prüfung könnt bereits vor Übergabe der Daten in globale Arbeitsvariablen erfolgen.
   ' BASCOM lässt aber nicht alle bzw. nur wenige Operationen direkt auf EEPROM-Inhalte
   ' zu. Damit müsste sowieso mit Varaiblen gearbeitet werden. Ergo ist es egal
   ' dass an dieser Stelle nochmals die globalen Arbeitsvariablen verändert werden.

      ' Sound: darf Sound_aus = 0 oder Sound_ein = 1 haben
      If Soundflag > Sound_ein Then
         #if Eeprom_testmodus                               ' Trace
            Print #3 , "Ee_init_internal_eeprom: Soundflag OUT OF RANGE"
            Print #3 , "Soundflag wird auf DEFAULT zurückgesetzt"
         #endif                                             ' Trace
         Ee_data_sound = Sound_default                      ' Default in EEPROM schreiben
         Soundflag = Ee_data_sound                          ' Arbeitsvariable initialisieren
      End If                                                ' Sound ausserhalb Range

      ' Uebertemperatur: darf nicht größer sein als 100 °C
      If Uebertemperatur > 100 Then
         #if Eeprom_testmodus                               ' Trace
            Print #3 , "Ee_init_internal_eeprom: Uebertemperatur OUT OF RANGE"
            Print #3 , "Uebertemperatur wird auf DEFAULT zurückgesetzt"
         #endif                                             ' Trace
         Ee_data_temperature = Uebertemperatur_default      ' Default in EEPROM schreiben
         Uebertemperatur = Ee_data_temperature              ' Arbeitsvariable initialisieren
      End If                                                ' Übertemperatur out of Range

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Eeprom_testmodus                                     ' Trace

      Print #3 , "Ee_init_internal_eeprom: Setting-Daten internes EEPROM:"

      ' Wert 01
      Temp_byte_1 = Ee_data_version_intern
      Print #3 , "Version Datenstruktur       : " ; Hex(temp_byte_1)

      ' Wert 02
      Temp_byte_1 = Ee_data_temperature
      Print #3 , "Einstellung Uebertemperatur : " ; Hex(temp_byte_1)

      ' Wert 03
      Print #3 , "Einstellung Sound           : " ; Hex(soundflag)

   #endif                                                   ' Trace

Return
'-- End Ee_init_internal_eeprom -----------------------------------------------

'------------------------------------------------------------------------------
' GOSubroutine: Ee_init_external_eeprom
' Subroutine überprüft die Datenkonsitenz aufgrund des verwendeten Versions-
' Index und führt ggf. eine Grundinitialisierung der Datenstrukturen durch.
' Die für die Settings notwendigen Basisdaten werden in globale Variablen
' geladen
'------------------------------------------------------------------------------
Ee_init_external_eeprom:

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

   #if Eeprom_testmodus
      Print #3 , "Enter Ee_init_external_eeprom"
   #endif

   ' Datenversion aus EEPROM lesen
   Ee_data_version_extern = Ee_read_eeprom_byte(ee_data_version_extern_adress)

   #if Eeprom_testmodus
      Temp_byte_1 = Akt_external_ee_version
      Print #3 , "Ee_init_external_eeprom: gelesene Datenversion : " ; Hex(ee_data_version_extern)
      Print #3 , "Ee_init_external_eeprom: soll Datenversion     : " ; Hex(temp_byte_1)
   #endif

   ' Prüfen ob Datenversion korrekt ist
   If Ee_data_version_extern <> Akt_external_ee_version Then
      ' NEIN Datenversion ist nicht korrekt

      #if Eeprom_testmodus
         Print #3 , "Ee_init_external_eeprom: Datenversion stimmt nicht"
         Print #3 , "Ee_init_external_eeprom: Initialisiere externes EEPROM neu!"
      #endif

      ' Datenstruktur externes EEPROM entspricht nicht dem aktuellen Stand
      ' => Datenstruktur neu anlegen bzw. neue Defaultwerte setzen.

      ' Datenversion schreiben
      Call Ee_write_eeprom_byte(ee_data_version_extern_adress , Akt_external_ee_version)
      Ee_data_version_extern = Akt_external_ee_version      ' Übernahme in Arbeitsvariable

      ' Data-Block-Counter schreiben
      Call Ee_write_eeprom_word(ee_data_block_count_adress , Data_block_count_init)
      Ee_data_block_count = Data_block_count_init           ' Übernahme in Arbeitsvariable

      ' Systemsetting auf Default setzen und schreiben
      Ee_data_block_write_count = Blockwritecounter_init    ' Counter
      Ee_data_lightning_struct(1) = Licht_default           ' Licht Modul 1
      Ee_data_lightning_struct(2) = Dimmer_default          ' Dimmer Module 1
      Ee_data_lightning_struct(3) = Licht_default           ' Licht Modul 2
      Ee_data_lightning_struct(4) = Dimmer_default          ' Dimmer Module 2
      Ee_data_lightning_struct(5) = Licht_default           ' Licht Modul 3
      Ee_data_lightning_struct(6) = Dimmer_default          ' Dimmer Module 3
      Ee_data_lightning_struct(7) = Licht_default           ' Licht Modul 4
      Ee_data_lightning_struct(8) = Dimmer_default          ' Dimmer Module 4
      Ee_data_lightning_struct(9) = Licht_default           ' Licht Modul 5
      Ee_data_lightning_struct(10) = Dimmer_default         ' Dimmer Module 5
      Ee_data_lightning_struct(11) = Licht_default          ' Licht Modul 6
      Ee_data_lightning_struct(12) = Dimmer_default         ' Dimmer Module 6
      Ee_data_lightning_struct(13) = Licht_default          ' Licht Modul 7
      Ee_data_lightning_struct(14) = Dimmer_default         ' Dimmer Module 7
      Ee_data_lightning_struct(15) = Licht_default          ' Licht Modul 8
      Ee_data_lightning_struct(16) = Dimmer_default         ' Dimmer Module 8

      ' Struct in EEPROM schreiben
      Gosub Ee_write_eeprom_struct

   Else
      #if Eeprom_testmodus
         Print #3 , "Ee_init_external_eeprom: Datenversion stimmt"
      #endif
   End If                                                   ' Überprüfung Datenversion

   ' Unabhängig von Flash-Urinitialisierung, aktuelle Daten nochmals laden

   #if Eeprom_testmodus
      Print #3 , "Ee_init_external_eeprom: Setting-Daten externes EEPROM:"
   #endif

   ' Datenversion laden
   Ee_data_version_extern = Ee_read_eeprom_byte(ee_data_version_extern_adress)
   #if Eeprom_testmodus
      Print #3 , "Version Datenstruktur : " ; Hex(ee_data_version_extern)
   #endif

   ' Data-Block-Counter laden
   Ee_data_block_count = Ee_read_eeprom_word(ee_data_block_count_adress)
   #if Eeprom_testmodus
      Print #3 , "Daten-Block-Counter   : " ; Hex(ee_data_block_count)
   #endif

   ' Aktuellen EEPROM-Block auslesen und und Variablen übernehmen
   Gosub Ee_read_eeprom_struct

Return
'-- End Ee_init_external_eeprom -----------------------------------------------

'------------------------------------------------------------------------------
' EE - Goubroutine: Ee_write_eeprom_settingstruct
' Subroutine schreibt die 16 Byte Settingdaten an die übergebene Adresse
'------------------------------------------------------------------------------
Ee_write_eeprom_struct:

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

   #if Eeprom_testmodus
      Print #3 , "Enter Ee_write_eeprom_struct"
   #endif

   ' Schreibcounter erhöhen, da geschrieben wird
   Incr Ee_data_block_write_count
   #if Eeprom_testmodus
      Print #3 , "Ee_write_eeprom_struct: erhöhe Schreibcounter : " ; Hex(ee_data_block_write_count)
   #endif

   ' Prüfen ob Schreibcounter über Grenze
   If Ee_data_block_write_count > Blockwritecounter_limit Then
      'JA Grenzwert überschritten

      #if Eeprom_testmodus
         Print #3 , "Ee_write_eeprom_struct: !! Schreibcounter-Grenze 1.000.000 erreicht"
      #endif

      ' Schreib-Counter in Block auf NULL setzen
      Ee_data_block_write_count = Blockwritecounter_init

      ' Block-Counter weiterschalten
      Incr Ee_data_block_count
      ' Data-Block-Counter schreiben
      Call Ee_write_eeprom_word(ee_data_block_count_adress , Ee_data_block_count)
   End If                                                   ' Schreibcounter über Grenze

   ' Adresse berechnen
   Temp_word_1 = Ee_data_block_count * Ee_data_blocklength

   #if Eeprom_testmodus
      Print #3 , "Ee_write_eeprom_struct: EE-write Adresse " ; Hex(temp_word_1)
   #endif

   ' Adresse in High-Byte und Low-Byte zerlegen
   Ee_adrl_temp = Low(temp_word_1)
   Ee_adrh_temp = High(temp_word_1)
   #if Eeprom_testmodus
      Print #3 , "Ee_write_eeprom_struct: EE-write low  Adresse " ; Hex(ee_adrl_temp)
      Print #3 , "Ee_write_eeprom_struct: EE-write high Adresse " ; Hex(ee_adrh_temp)
      Print #3 , "Ee_write_eeprom_struct: Daten-Struct : " ;

      For Temp_byte_1 = 1 To Ee_data_struct_length
         Print #3 , Hex(ee_data_struct(temp_byte_1)) ; " " ;
      Next Temp_byte_1
      Print #3 , " "                                        ' Print abschließen
   #endif

   ' Kommunikation über I2C-Bus
   I2cstart                                                 ' START-Sequenze senden
   I2cwbyte Address_write                                   ' Daten schreiben initiieren
   I2cwbyte Ee_adrh_temp                                    ' High-Byte der Adresse übertragen
   I2cwbyte Ee_adrl_temp                                    ' Low-Byte der Adresse übertragen

   For Temp_byte_1 = 1 To Ee_data_struct_length
      I2cwbyte Ee_data_struct(temp_byte_1)                  ' Bytes übertragen
   Next Temp_byte_1

   I2cstop                                                  ' STOP-Sequenz

Return
'-- End Ee_write_eeprom_struct ------------------------------------------------

'------------------------------------------------------------------------------
' EE - Gosubroutine: Ee_read_eeprom_struct
' Subroutine liest die 20 Byte Daten von der übergebene Adresse
'------------------------------------------------------------------------------
Ee_read_eeprom_struct:

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

   #if Eeprom_testmodus
      Print #3 , "Enter Ee_read_eeprom_struct"
   #endif

   ' Adresse berechnen
   Temp_word_1 = Ee_data_block_count * Ee_data_blocklength

   #if Eeprom_testmodus
      Print #3 , "Ee_read_eeprom_struct: EE-read Adresse " ; Hex(temp_word_1)
   #endif

   ' Adresse in High-Byte und Low-Byte zerlegen
   Ee_adrl_temp = Low(temp_word_1)
   Ee_adrh_temp = High(temp_word_1)

   ' Kommunikation über I2C-Bus
   Temp_byte_2 = Ee_data_struct_length - 1                  ' Wegen Nack 1 Byte weniger lesen

   I2cstart                                                 ' START-Sequenz senden
   I2cwbyte Address_write                                   ' Daten schreiben initiieren
   I2cwbyte Ee_adrh_temp                                    ' High-Byte der Adresse übertragen
   I2cwbyte Ee_adrl_temp                                    ' Low-Byte der Adresse übertragen

   I2cstart                                                 ' START-Sequenz erneut senden
   I2cwbyte Address_read                                    ' Daten lesen initiieren

   For Temp_byte_1 = 1 To Temp_byte_2
      I2crbyte Ee_data_struct(temp_byte_1) , Ack            ' Byte's 1-19 lesen
   Next Temp_byte_1

   I2crbyte Ee_data_struct(20) , Nack                       ' Byte 20 lesen

   I2cstop                                                  ' STOP-Sequenz

   #if Eeprom_testmodus
      Print #3 , "Ee_read_eeprom_struct: EE-read low  Adresse " ; Hex(ee_adrl_temp)
      Print #3 , "Ee_read_eeprom_struct: EE-read high Adresse " ; Hex(ee_adrh_temp)
      Print #3 , "Ee_read_eeprom_struct: Daten-Struct : " ;

      For Temp_byte_1 = 1 To Ee_data_struct_length
         Print #3 , Hex(ee_data_struct(temp_byte_1)) ; " " ;
      Next Temp_byte_1
      Print #3 , " "                                        ' Print abschließen
   #endif

Return
'-- End Ee_write_eeprom_struct -----------------------------------------------

'------------------------------------------------------------------------------
' EE - Gosubroutine: Ee_data_update
' Subroutine überprüft welche Daten neu geschrieben werden müssen und speichert
' diese an den aktuellen Positionen im EEPROM ab.
'------------------------------------------------------------------------------
Ee_data_update:

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

   ' ggf. Trace auf RS232 ausgeben
   #if Eeprom_testmodus
      Print #3 , "Enter Ee_data_update"
   #endif

   Temp_byte_2 = False

   ' Schleife über alle 8 Dimmer-Stati
   For Temp_byte_1 = 1 To 8
      ' Prüfen ob Update vorliegt
      If Ee_dimmer_update(temp_byte_1) = True Then
         ' JA

         ' ggf. Trace auf RS232 ausgeben
         #if Eeprom_testmodus
            Print #3 , Hex(ee_dimmer_update(temp_byte_1)) ; " ";
         #endif

         Temp_byte_2 = True                                 ' Update vorbereiten
         Ee_dimmer_update(temp_byte_1) = False              ' Flag zurücksetzen
      End If
   Next Temp_byte_1                                         ' Schleife über Dimmer

   ' Müssen Daten gesichert werden?
   If Temp_byte_2 = True Then
      ' JA

      ' ggf. Trace auf RS232 ausgeben
      #if Eeprom_testmodus
         Print #3 , "EEPROM-Update wurde angefordert und ausgefuehrt"
      #endif

      ' EEPROM-Datenstruktur in EEPROM schreiben
      Gosub Ee_write_eeprom_struct

   End If                                                   ' Update?

Return
'-- End Ee_data_update --------------------------------------------------------

' ********************
' * MENUE:  Menue    *
' ********************

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_change_state
' Routine stellt den Status der Menue-State-Machine fest und führt ggf. Wechsel
' durch. Hierbei werden die Pointer auf die States neu befüllt und die notwen-
' digen Variablen neu gesetzt.
'------------------------------------------------------------------------------
Menue_change_state:

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

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_change_state"
      Print #3 , "MenueState : " ; Hex(menue_state)
   #endif                                                   ' Trace

   ' 16-Bit-Adresse des aktuellen Labels / Menüzustandes laden
   lds R8, {Menue_State}
   lds R9, {Menue_State + 1}

   ' Mittels Schleife über das Tastatur-Array Verzweigung prüfen
   For Temp_byte_1 = 1 To Key_buttons
      ' Ansprungsadresse laden
      Read Temp_word_1
      ' Prüfen ob zugehörige Taste betätigt
      If Key_taste = Key_codes(temp_byte_1) Then
         ' Wenn Taste betätigt dann prüfen ob Ansprungziel gültig
         If Temp_word_1 <> Loadlabel(null) Then
            ' Menü muss erneuert werden - Flag setzen
            Menue_state_renew = 1
            ' Tastenstatus zurücksetzen um Einfluss von GOSUBs zu verhindern
            Key_taste = Key_null
            ' Neuer Menüstatus in Zustandsmaschine laden
            Menue_state = Temp_word_1
         End If                                             ' Ansprungziel
      End If                                                ' gültige Taste
   Next Tempb_byte_1                                        ' Array mit Tasten-Codes

   ' Adresse des anzuspringenden Unterprogramms einlesen
   Read Menue_state_gosub

   ' Ausgabeflags einlesen
   Read Menue_ausgabeflags

   ' Textzeilen für LCD-Ausgabe einlesen
   Read Menue_lcd_textbuffer(1)                             'read LCD text
   Read Menue_lcd_textbuffer(2)                             'read LCD text
   Read Menue_lcd_textbuffer(3)                             'read LCD text

Return
'-- End Menue_chane_state -----------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_changes_state_by_sub
' Routine wird von Subroutinen aufgerufen falls eine Menüänderungen händisch
' erzwungen werden soll.
' Hier wird die Statemachine auf einen neuen Zustand umgeschaltet. Der Zustand
' kann in der Variablen Menue_state hinterlegt werden.
'------------------------------------------------------------------------------
Menue_change_state_by_sub:

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

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_change_state_by_sub"
   #endif                                                   ' Trace

   ' Menü muss erneuert werden - Flag setzen
   Menue_state_renew = 1

   ' Eigentliche Menüänderung durchführen
   Gosub Menue_change_state

Return
'-- End Menue_chane_state_by_sub ----------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_call_subroutine
' Routine liest aus aktuellem Menue-State den Sprungadresse und springt angege-
' benes Ziel an.
'------------------------------------------------------------------------------
Menue_call_subroutine:

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

   LDS R31, {Menue_State_gosub+1}                           'High see Bascom-Doc Mixing ASM and BASIC
   LDS R30, {Menue_State_gosub}                             'Low
   LSR R31                                                  'Division durch 2 (Alternativ ADR verwenden)
   ROR R30
   'Call zum Sub
   ICALL

Return
'-- End Menue_call_subroutine -------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men11 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men11:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men11"
   #endif                                                   ' Trace

   ' ggf. Zeitwerte aus Unterfunktion übernehmen - Öffnungszeiten

   If Menue_datenuebernahme_flag = True Then

      ' Flag zurücksetzen
      Menue_datenuebernahme_flag = False

      ' Daten üebernehmen

      ' Byte(1) Dimmermodul 1 - Schaltzustand
      Ee_data_mod1_light = Menue_dimmer_status              ' Interner Dimmerstatus

      ' Byte(2) Dimmermodul 1 - Dimmerstufe
      Ee_data_mod1_dimm = Menue_dimmer_dimmwert             ' Interner Dimmwert

      ' Update für EEPROM-Wert setzen
      Ee_dimmer_update(1) = True

   End If                                                   ' Datenübernahme?

   ' Slave-Temperatur auf LCD ausgeben
   Locate 3 , 7 : Lcd Slave_temperatur(1)

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 14
   Select Case Ee_data_mod1_light
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select
   Temp_byte_1 = Makebcd(ee_data_mod1_dimm)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

Return
'-- End Menue_men11 -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men111 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men111:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men111"
   #endif                                                   ' Trace

   ' Einstellen der Dimmereinstellungen vorbereiten und relevante Variablen laden

   ' Dimmereinstellung laden wurde von Menü MEN11 aufgerufen.

   ' Hilfvariablen für Dimmer-Menü laden

   ' Dimmer
   Menue_dimmer = 1                                         ' Dimmer 1

   ' Byte(1) Dimmermodul 1 - Schaltzustand
   Menue_dimmer_status = Ee_data_mod1_light                 ' Interner Dimmerstatus

   ' Byte(2) Dimmermodul 1 - Dimmerstufe
   Menue_dimmer_dimmwert = Ee_data_mod1_dimm                ' Interner Dimmwert

   ' Rücksprung-Ziel festlegen
   Menue_state_buffer = Loadlabel(men11)                    ' Dimmer einstellen

   ' Menü neu laden und einspringen
   Menue_state = Loadlabel(dim1)                            ' Einsprung in erstes Einstellfenster
   Gosub Menue_change_state_by_sub
   Gosub Lcd_print
   Menue_state_renew = 0
   Gosub Menue_dim1                                         ' zugehörige Unterfunktiona anspringen

Return
'-- End Menue_men111 ----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men12 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men12:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men12"
   #endif                                                   ' Trace

   ' ggf. Zeitwerte aus Unterfunktion übernehmen - Öffnungszeiten

   If Menue_datenuebernahme_flag = True Then

      ' Flag zurücksetzen
      Menue_datenuebernahme_flag = False

      ' Daten üebernehmen

      ' Byte(1) Dimmermodul 2 - Schaltzustand
      Ee_data_mod2_light = Menue_dimmer_status              ' Interner Dimmerstatus

      ' Byte(2) Dimmermodul 2 - Dimmerstufe
      Ee_data_mod2_dimm = Menue_dimmer_dimmwert             ' Interner Dimmwert

      ' Update für EEPROM-Wert setzen
      Ee_dimmer_update(2) = True

   End If                                                   ' Datenübernahme?

   ' Slave-Temperatur auf LCD ausgeben
   Locate 3 , 7 : Lcd Slave_temperatur(2)

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 14
   Select Case Ee_data_mod2_light
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select
   Temp_byte_1 = Makebcd(ee_data_mod2_dimm)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

Return
'-- End Menue_men12 -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men121 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men121:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men121"
   #endif                                                   ' Trace

   ' Einstellen der Dimmereinstellungen vorbereiten und relevante Variablen laden

   ' Dimmereinstellung laden wurde von Menü MEN12 aufgerufen.

   ' Hilfvariablen für Dimmer-Menü laden

   ' Dimmer
   Menue_dimmer = 2                                         ' Dimmer 2

   ' Byte(1) Dimmermodul 2 - Schaltzustand
   Menue_dimmer_status = Ee_data_mod2_light                 ' Interner Dimmerstatus

   ' Byte(2) Dimmermodul 2 - Dimmerstufe
   Menue_dimmer_dimmwert = Ee_data_mod2_dimm                ' Interner Dimmwert

   ' Rücksprung-Ziel festlegen
   Menue_state_buffer = Loadlabel(men12)                    ' Dimmer einstellen

   ' Menü neu laden und einspringen
   Menue_state = Loadlabel(dim1)                            ' Einsprung in erstes Einstellfenster
   Gosub Menue_change_state_by_sub
   Gosub Lcd_print
   Menue_state_renew = 0
   Gosub Menue_dim1                                         ' zugehörige Unterfunktiona anspringen

Return
'-- End Menue_men121 ----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men13 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men13:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men13"
   #endif                                                   ' Trace

   ' ggf. Zeitwerte aus Unterfunktion übernehmen - Öffnungszeiten

   If Menue_datenuebernahme_flag = True Then

      ' Flag zurücksetzen
      Menue_datenuebernahme_flag = False

      ' Daten üebernehmen

      ' Byte(1) Dimmermodul 3 - Schaltzustand
      Ee_data_mod3_light = Menue_dimmer_status              ' Interner Dimmerstatus

      ' Byte(2) Dimmermodul 3 - Dimmerstufe
      Ee_data_mod3_dimm = Menue_dimmer_dimmwert             ' Interner Dimmwert

      ' Update für EEPROM-Wert setzen
      Ee_dimmer_update(3) = True

   End If                                                   ' Datenübernahme?

   ' Slave-Temperatur auf LCD ausgeben
   Locate 3 , 7 : Lcd Slave_temperatur(3)

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 14
   Select Case Ee_data_mod3_light
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select
   Temp_byte_1 = Makebcd(ee_data_mod3_dimm)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

Return
'-- End Menue_men13 -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men131 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men131:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men131"
   #endif                                                   ' Trace

   ' Einstellen der Dimmereinstellungen vorbereiten und relevante Variablen laden

   ' Dimmereinstellung laden wurde von Menü MEN13 aufgerufen.

   ' Hilfvariablen für Dimmer-Menü laden

   ' Dimmer
   Menue_dimmer = 3                                         ' Dimmer 3

   ' Byte(1) Dimmermodul 3 - Schaltzustand
   Menue_dimmer_status = Ee_data_mod3_light                 ' Interner Dimmerstatus

   ' Byte(2) Dimmermodul 3 - Dimmerstufe
   Menue_dimmer_dimmwert = Ee_data_mod3_dimm                ' Interner Dimmwert

   ' Rücksprung-Ziel festlegen
   Menue_state_buffer = Loadlabel(men13)                    ' Dimmer einstellen

   ' Menü neu laden und einspringen
   Menue_state = Loadlabel(dim1)                            ' Einsprung in erstes Einstellfenster
   Gosub Menue_change_state_by_sub
   Gosub Lcd_print
   Menue_state_renew = 0
   Gosub Menue_dim1                                         ' zugehörige Unterfunktiona anspringen

Return
'-- End Menue_men131 ----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men14 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men14:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men14"
   #endif                                                   ' Trace

   ' ggf. Zeitwerte aus Unterfunktion übernehmen - Öffnungszeiten

   If Menue_datenuebernahme_flag = True Then

      ' Flag zurücksetzen
      Menue_datenuebernahme_flag = False

      ' Daten üebernehmen

      ' Byte(1) Dimmermodul 4 - Schaltzustand
      Ee_data_mod4_light = Menue_dimmer_status              ' Interner Dimmerstatus

      ' Byte(2) Dimmermodul 4 - Dimmerstufe
      Ee_data_mod4_dimm = Menue_dimmer_dimmwert             ' Interner Dimmwert

      ' Update für EEPROM-Wert setzen
      Ee_dimmer_update(4) = True

   End If                                                   ' Datenübernahme?

   ' Slave-Temperatur auf LCD ausgeben
   Locate 3 , 7 : Lcd Slave_temperatur(4)

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 14
   Select Case Ee_data_mod4_light
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select
   Temp_byte_1 = Makebcd(ee_data_mod4_dimm)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

Return
'-- End Menue_men14 -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men141 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men141:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men141"
   #endif                                                   ' Trace

   ' Einstellen der Dimmereinstellungen vorbereiten und relevante Variablen laden

   ' Dimmereinstellung laden wurde von Menü MEN14 aufgerufen.

   ' Hilfvariablen für Dimmer-Menü laden

   ' Dimmer
   Menue_dimmer = 4                                         ' Dimmer 4

   ' Byte(1) Dimmermodul 4 - Schaltzustand
   Menue_dimmer_status = Ee_data_mod4_light                 ' Interner Dimmerstatus

   ' Byte(2) Dimmermodul 4 - Dimmerstufe
   Menue_dimmer_dimmwert = Ee_data_mod4_dimm                ' Interner Dimmwert

   ' Rücksprung-Ziel festlegen
   Menue_state_buffer = Loadlabel(men14)                    ' Dimmer einstellen

   ' Menü neu laden und einspringen
   Menue_state = Loadlabel(dim1)                            ' Einsprung in erstes Einstellfenster
   Gosub Menue_change_state_by_sub
   Gosub Lcd_print
   Menue_state_renew = 0
   Gosub Menue_dim1                                         ' zugehörige Unterfunktiona anspringen

Return
'-- End Menue_men141 ----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men15 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men15:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men15"
   #endif                                                   ' Trace

   ' ggf. Zeitwerte aus Unterfunktion übernehmen - Öffnungszeiten

   If Menue_datenuebernahme_flag = True Then

      ' Flag zurücksetzen
      Menue_datenuebernahme_flag = False

      ' Daten üebernehmen

      ' Byte(1) Dimmermodul 5 - Schaltzustand
      Ee_data_mod5_light = Menue_dimmer_status              ' Interner Dimmerstatus

      ' Byte(2) Dimmermodul 5 - Dimmerstufe
      Ee_data_mod5_dimm = Menue_dimmer_dimmwert             ' Interner Dimmwert

      ' Update für EEPROM-Wert setzen
      Ee_dimmer_update(5) = True

   End If                                                   ' Datenübernahme?

   ' Slave-Temperatur auf LCD ausgeben
   Locate 3 , 7 : Lcd Slave_temperatur(5)

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 14
   Select Case Ee_data_mod5_light
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select
   Temp_byte_1 = Makebcd(ee_data_mod5_dimm)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

Return
'-- End Menue_men15 -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men151 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men151:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men151"
   #endif                                                   ' Trace

   ' Einstellen der Dimmereinstellungen vorbereiten und relevante Variablen laden

   ' Dimmereinstellung laden wurde von Menü MEN15 aufgerufen.

   ' Hilfvariablen für Dimmer-Menü laden

   ' Dimmer
   Menue_dimmer = 5                                         ' Dimmer 5

   ' Byte(1) Dimmermodul 5 - Schaltzustand
   Menue_dimmer_status = Ee_data_mod5_light                 ' Interner Dimmerstatus

   ' Byte(2) Dimmermodul 5 - Dimmerstufe
   Menue_dimmer_dimmwert = Ee_data_mod5_dimm                ' Interner Dimmwert

   ' Rücksprung-Ziel festlegen
   Menue_state_buffer = Loadlabel(men15)                    ' Dimmer einstellen

   ' Menü neu laden und einspringen
   Menue_state = Loadlabel(dim1)                            ' Einsprung in erstes Einstellfenster
   Gosub Menue_change_state_by_sub
   Gosub Lcd_print
   Menue_state_renew = 0
   Gosub Menue_dim1                                         ' zugehörige Unterfunktiona anspringen

Return
'-- End Menue_men151 ----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men16 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men16:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men16"
   #endif                                                   ' Trace

   ' ggf. Zeitwerte aus Unterfunktion übernehmen - Öffnungszeiten

   If Menue_datenuebernahme_flag = True Then

      ' Flag zurücksetzen
      Menue_datenuebernahme_flag = False

      ' Daten üebernehmen

      ' Byte(1) Dimmermodul 6 - Schaltzustand
      Ee_data_mod6_light = Menue_dimmer_status              ' Interner Dimmerstatus

      ' Byte(2) Dimmermodul 6 - Dimmerstufe
      Ee_data_mod6_dimm = Menue_dimmer_dimmwert             ' Interner Dimmwert

      ' Update für EEPROM-Wert setzen
      Ee_dimmer_update(6) = True

   End If                                                   ' Datenübernahme?

   ' Slave-Temperatur auf LCD ausgeben
   Locate 3 , 7 : Lcd Slave_temperatur(6)

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 14
   Select Case Ee_data_mod6_light
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select
   Temp_byte_1 = Makebcd(ee_data_mod1_dimm)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

Return
'-- End Menue_men16 -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men161 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men161:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men161"
   #endif                                                   ' Trace

   ' Einstellen der Dimmereinstellungen vorbereiten und relevante Variablen laden

   ' Dimmereinstellung laden wurde von Menü MEN16 aufgerufen.

   ' Hilfvariablen für Dimmer-Menü laden

   ' Dimmer
   Menue_dimmer = 6                                         ' Dimmer 6

   ' Byte(1) Dimmermodul 6 - Schaltzustand
   Menue_dimmer_status = Ee_data_mod6_light                 ' Interner Dimmerstatus

   ' Byte(2) Dimmermodul 6 - Dimmerstufe
   Menue_dimmer_dimmwert = Ee_data_mod6_dimm                ' Interner Dimmwert

   ' Rücksprung-Ziel festlegen
   Menue_state_buffer = Loadlabel(men16)                    ' Dimmer einstellen

   ' Menü neu laden und einspringen
   Menue_state = Loadlabel(dim1)                            ' Einsprung in erstes Einstellfenster
   Gosub Menue_change_state_by_sub
   Gosub Lcd_print
   Menue_state_renew = 0
   Gosub Menue_dim1                                         ' zugehörige Unterfunktiona anspringen

Return
'-- End Menue_men161 ----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men17 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men17:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men17"
   #endif                                                   ' Trace

   ' ggf. Zeitwerte aus Unterfunktion übernehmen - Öffnungszeiten

   If Menue_datenuebernahme_flag = True Then

      ' Flag zurücksetzen
      Menue_datenuebernahme_flag = False

      ' Daten üebernehmen

      ' Byte(1) Dimmermodul 7 - Schaltzustand
      Ee_data_mod7_light = Menue_dimmer_status              ' Interner Dimmerstatus

      ' Byte(2) Dimmermodul 7 - Dimmerstufe
      Ee_data_mod7_dimm = Menue_dimmer_dimmwert             ' Interner Dimmwert

      ' Update für EEPROM-Wert setzen
      Ee_dimmer_update(7) = True

   End If                                                   ' Datenübernahme?

   ' Slave-Temperatur auf LCD ausgeben
   Locate 3 , 7 : Lcd Slave_temperatur(7)

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 14
   Select Case Ee_data_mod7_light
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select
   Temp_byte_1 = Makebcd(ee_data_mod7_dimm)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

Return
'-- End Menue_men17 -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men171 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men171:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men171"
   #endif                                                   ' Trace

   ' Einstellen der Dimmereinstellungen vorbereiten und relevante Variablen laden

   ' Dimmereinstellung laden wurde von Menü MEN17 aufgerufen.

   ' Hilfvariablen für Dimmer-Menü laden

   ' Dimmer
   Menue_dimmer = 7                                         ' Dimmer 7

   ' Byte(1) Dimmermodul 7 - Schaltzustand
   Menue_dimmer_status = Ee_data_mod7_light                 ' Interner Dimmerstatus

   ' Byte(2) Dimmermodul 7 - Dimmerstufe
   Menue_dimmer_dimmwert = Ee_data_mod7_dimm                ' Interner Dimmwert

   ' Rücksprung-Ziel festlegen
   Menue_state_buffer = Loadlabel(men17)                    ' Dimmer einstellen

   ' Menü neu laden und einspringen
   Menue_state = Loadlabel(dim1)                            ' Einsprung in erstes Einstellfenster
   Gosub Menue_change_state_by_sub
   Gosub Lcd_print
   Menue_state_renew = 0
   Gosub Menue_dim1                                         ' zugehörige Unterfunktiona anspringen

Return
'-- End Menue_men171 ----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men14 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men18:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men18"
   #endif                                                   ' Trace

   ' ggf. Zeitwerte aus Unterfunktion übernehmen - Öffnungszeiten

   If Menue_datenuebernahme_flag = True Then

      ' Flag zurücksetzen
      Menue_datenuebernahme_flag = False

      ' Daten üebernehmen

      ' Byte(1) Dimmermodul 8 - Schaltzustand
      Ee_data_mod8_light = Menue_dimmer_status              ' Interner Dimmerstatus

      ' Byte(2) Dimmermodul 8 - Dimmerstufe
      Ee_data_mod8_dimm = Menue_dimmer_dimmwert             ' Interner Dimmwert

      ' Update für EEPROM-Wert setzen
      Ee_dimmer_update(8) = True

   End If                                                   ' Datenübernahme?

   ' Slave-Temperatur auf LCD ausgeben
   Locate 3 , 7 : Lcd Slave_temperatur(8)

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 14
   Select Case Ee_data_mod8_light
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select
   Temp_byte_1 = Makebcd(ee_data_mod8_dimm)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

Return
'-- End Menue_men18 -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men181 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei Eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men181:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men181"
   #endif                                                   ' Trace

   ' Einstellen der Dimmereinstellungen vorbereiten und relevante Variablen laden

   ' Dimmereinstellung laden wurde von Menü MEN18 aufgerufen.

   ' Hilfvariablen für Dimmer-Menü laden

   ' Dimmer
   Menue_dimmer = 8                                         ' Dimmer 8

   ' Byte(1) Dimmermodul 8 - Schaltzustand
   Menue_dimmer_status = Ee_data_mod8_light                 ' Interner Dimmerstatus

   ' Byte(2) Dimmermodul 8 - Dimmerstufe
   Menue_dimmer_dimmwert = Ee_data_mod8_dimm                ' Interner Dimmwert

   ' Rücksprung-Ziel festlegen
   Menue_state_buffer = Loadlabel(men18)                    ' Dimmer einstellen

   ' Menü neu laden und einspringen
   Menue_state = Loadlabel(dim1)                            ' Einsprung in erstes Einstellfenster
   Gosub Menue_change_state_by_sub
   Gosub Lcd_print
   Menue_state_renew = 0
   Gosub Menue_dim1                                         ' zugehörige Unterfunktiona anspringen

Return
'-- End Menue_men181 ----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_dim1 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_dim1:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_dim1"
   #endif                                                   ' Trace

   ' Dimmerwerte ausgeben

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 9 : Lcd Menue_dimmer

   Locate 2 , 12 : Lcd "{004}"

   Locate 2 , 14
   Select Case Menue_dimmer_status
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select

   Temp_byte_1 = Makebcd(menue_dimmer_dimmwert)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

Return
'-- End Menue_dim1  -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_dim11 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_dim11:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_dim11"
   #endif                                                   ' Trace

   ' Status Dimmer umschalten und Dimmerwerte ausgeben

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 9 : Lcd Menue_dimmer

   Locate 2 , 12 : Lcd "{004}"

   Locate 2 , 14
   Select Case Menue_dimmer_status
      Case True
         Menue_dimmer_status = False
         Lcd "AUS"
      Case False
         Menue_dimmer_status = True
         Lcd "EIN"
   End Select

   Temp_byte_1 = Makebcd(menue_dimmer_dimmwert)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

   ' Dimmer auch schalten
   Temp_byte_1 = Rs485_licht_schalten(menue_dimmer , Menue_dimmer_status)

Return
'-- End Menue_dim11  -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_dim12 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_dim12:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_dim12"
   #endif                                                   ' Trace

   ' Status Dimmer umschalten und Dimmerwerte ausgeben

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 9 : Lcd Menue_dimmer

   Locate 2 , 12 : Lcd "{004}"

   Locate 2 , 14
   Select Case Menue_dimmer_status
      Case True
         Menue_dimmer_status = False
         Lcd "AUS"
      Case False
         Menue_dimmer_status = True
         Lcd "EIN"
   End Select

   Temp_byte_1 = Makebcd(menue_dimmer_dimmwert)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

   ' Dimmer auch schalten
   Temp_byte_1 = Rs485_licht_schalten(menue_dimmer , Menue_dimmer_status)

Return
'-- End Menue_dim12  -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_dim2 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_dim2:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_dim2"
   #endif                                                   ' Trace

   ' Dimmerwerte ausgeben

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 9 : Lcd Menue_dimmer

   Locate 3 , 12 : Lcd "{004}"

   Locate 2 , 14
   Select Case Menue_dimmer_status
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select

   Temp_byte_1 = Makebcd(menue_dimmer_dimmwert)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

Return
'-- End Menue_dim2  -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_dim21 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_dim21:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_dim21"
   #endif                                                   ' Trace

   ' Dimmerwerte berechnen und ausgeben

   If Menue_dimmer_dimmwert < Max_dimmer Then
      Incr Menue_dimmer_dimmwert
   End If                                                   ' Dimmwer erhöhen

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 9 : Lcd Menue_dimmer

   Locate 3 , 12 : Lcd "{004}"

   Locate 2 , 14
   Select Case Menue_dimmer_status
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select

   ' Datum zum Umformatieren vorbereiten
   Temp_byte_1 = Makebcd(menue_dimmer_dimmwert)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

   ' Dimmwert auch setzen
   Temp_byte_1 = Rs485_dimmwert_setzen(menue_dimmer , Menue_dimmer_dimmwert)

Return
'-- End Menue_dim21  -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_dim22 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_dim22:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_dim22"
   #endif                                                   ' Trace

   ' Dimmerwerte berechnen und ausgeben

   If Menue_dimmer_dimmwert > Min_dimmer Then
      Decr Menue_dimmer_dimmwert
   End If                                                   ' Dimmwer verkleinern

   ' Dimmerstatus und Dimmerstufe auf LCD ausgeben
   Locate 2 , 9 : Lcd Menue_dimmer

   Locate 3 , 12 : Lcd "{004}"

   Locate 2 , 14
   Select Case Menue_dimmer_status
      Case True : Lcd "EIN"
      Case False : Lcd "AUS"
   End Select

   ' Datum zum Umformatieren vorbereiten
   Temp_byte_1 = Makebcd(menue_dimmer_dimmwert)
   Locate 3 , 15 : Lcd Bcd(temp_byte_1)

   ' Dimmwert auch setzen
   Temp_byte_1 = Rs485_dimmwert_setzen(menue_dimmer , Menue_dimmer_dimmwert)

Return
'-- End Menue_dim22  -----------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_dim_ende (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_dim_ende:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_dim_ende"
   #endif                                                   ' Trace

   ' Rücksprung in relevantes Menü
   Menue_datenuebernahme_flag = True

   ' Menüstatus zurückschalten
   Menue_state = Menue_state_buffer

   Gosub Menue_change_state_by_sub
   Gosub Lcd_print
   Menue_state_renew = 0
   Gosub Menue_call_subroutine

Return
'-- End Menue_time_ende -------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men211 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men211:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men211"
   #endif                                                   ' Trace

   Select Case Key_taste_buffer

      Case 1:
         ' hoch = erhöhen

         If Uebertemperatur < Max_temperatur Then
            #if Menue_testmodus                             ' Trace
               Print #3 , "Menue_men211: Inkrementiere Übertemperatur"
            #endif                                          ' Trace
            Incr Uebertemperatur
         End If                                             ' Obergrenze

      Case 2:
         ' runter = erniedrigen
         If Uebertemperatur > Min_temperatur Then
            #if Menue_testmodus                             ' Trace
               Print #3 , "Menue_men211: Dekrementiere Übertemperatur"
            #endif                                          ' Trace
            Decr Uebertemperatur
         End If                                             ' untergrenze
   End Select

   Select Case Key_taste_buffer

      Case 1 To 2:

         #if Menue_testmodus                                ' Trace
            Print #3 , "Menue_men211: Temperatur zurück im EEPROM speichern"
         #endif                                             ' Trace

         ' Veränderte Temperatur zurück in EEPROM schreiben
         Ee_data_temperature = Uebertemperatur

         #if Menue_testmodus                                ' Trace
            Print #3 , "Menue_men211: Temperatur als Broadcaste senden"
         #endif                                             ' Trace

         ' Slaves auch wirklich einstellen
         Temp_byte_1 = Rs485_temperatur_setzen(broadcastadresse , Uebertemperatur)

   End Select                                               ' Tastenauswertung

   ' Temperatur auf Display ausgeben
   Temp_byte_1 = Makebcd(uebertemperatur)
   Locate 2 , 7 : Lcd Bcd(temp_byte_1) ; "{223}C"

Return
'-- Menue_men211 ---------------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men221 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men221:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men221"
   #endif                                                   ' Trace

   Select Case Key_taste_buffer

      Case 1 To 2:
         ' hoch = erhöhen

         #if Menue_testmodus                                ' Trace
            Print #3 , "Menue_men221: Soundflag toggeln"
         #endif                                             ' Trace

         If Soundflag = True Then
            Soundflag = False
         Else                                               ' True
            If Soundflag = False Then
               Soundflag = True
            End If                                          ' False
         End If

         ' Verändertes Soundflag zurück in EEPROM schreiben
         Ee_data_sound = Soundflag

         #if Menue_testmodus                                ' Trace
            Print #3 , "Menue_men221: Broadcast senden"
         #endif                                             ' Trace

         ' Slaves auch wirklich einstellen
         Temp_byte_1 = Rs485_sound_schalten(broadcastadresse , Soundflag)

   End Select                                               ' Tastenauswertung

   ' Soundstatus ausgeben
   Locate 2 , 7
   Select Case Soundflag
      Case True:
         Lcd "EIN"
      Case False:
         Lcd "AUS"
   End Select

Return
'-- Menue_men221 ---------------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men3 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men3:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men3"
   #endif                                                   ' Trace

   ' Flag für zeitlich upzudatendes Menue zurücksetzen
   Menue_menueupdate_flag = 0

   ' Prüfen ob überhaupt Fehlertexte vorliegen
   Error_index = 10                                         ' Index auf kein Fehler
   Error_show_flag = False                                  ' kein Fehler

   For Temp_byte_1 = 1 To 10
      If Error_flags(temp_byte_1) = True Then
         Error_show_flag = True                             ' Fehler anzeigen
         Error_index = 1                                    ' Text-Index auf 1 setzen
      End If                                                ' Anzeige_Flag setzen
   Next Temp_byte_1                                         ' Schleife über Flags

   ' ggf. Trace ausgeben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Menue_men31: Error_show_flag : " ; Error_show_flag
   #endif                                                   ' Trace

Return
'-- Menue_men3 ----------------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men31 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men31:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men31"
   #endif                                                   ' Trace

   ' Zeitüberwachung aus Untermenüs einschalten damit Menüs zyklisch
   ' aufgerufen werden.

   Menue_update_counter = Timercounter + Menue_update_time

   ' Fehlertexte ausgeben

   ' ggf. Trace ausgeben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Menue_men31: Error_show_flag : " ; Error_show_flag
   #endif                                                   ' Trace

   ' Prüfen ob Fehlertexte angezeigt werden müssen
   If Error_show_flag = False Then
      ' Nein

      Locate 2 , 1 : Lcd Error_msg_1(error_index)           ' Zeile 1 ausgeben
      Locate 3 , 1 : Lcd Error_msg_2(error_index)           ' Zeile 2 ausgeben
   Else
      'JA

      ' Flag für zeitlich upzudatendes Menue setzen
      Menue_menueupdate_flag = 1

      ' So lange weiterschalten bis Index auf Text trifft der ausgegeben werden
      ' kann
      While Error_flags(error_index) <> True
         Incr Error_index                                   ' Zähler erhöhen
         If Error_index > 9 Then                            ' Überlauf abfangen
            Error_index = 1
         End If                                             ' Überlauf
      Wend                                                  ' Durchlauf

      ' ggf. Trace ausgeben
      #if Menue_testmodus                                   ' Trace
         Print #3 , "Menue_men31: Error_index : " ; Error_index
      #endif                                                ' Trace

      Locate 2 , 1 : Lcd Error_msg_1(error_index)           ' Zeile 1 ausgeben
      Locate 3 , 1 : Lcd Error_msg_2(error_index)           ' Zeile 2 ausgeben

      ' Prüfen ob Zusatzinfo ausgegeben werden muss
      If Error_index = 6 Then
         Locate 3 , 8 : Lcd Bin(slave_temp_bitfeld)
      End If                                                ' Zusatzinfo ausgeben

      Incr Error_index                                      ' nächster Fehler

   End If                                                   ' Anzeige Fehlertexte

   ' Anmerkungen:
   ' Es gibt die Möglichkeit, dass keine Fehler vorhanden sind. In diesem Fall
   ' soll der definierte texta su Position 10 auf dem Display ausgegeben
   ' werden.
   ' Wenn Fehler vorhanden sind dann sollen syklisch alle Texte auf dem Display
   ' erscheinen.

Return
'-- Menue_men31 ---------------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men41 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men41:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men41"
   #endif                                                   ' Trace

   ' Temperatur ausgeben - Ds1820_temperatur

   ' Temperatur auf Display ausgeben
   Temp_byte_1 = Makebcd(ds1820_temperatur)
   Locate 3 , 1 : Lcd Bcd(temp_byte_1) ; " {223}C"

Return
'-- Menue_men41 ---------------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men42 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men42:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men42"
   #endif                                                   ' Trace

   ' Zustand Relais ausgeben
   Locate 3 , 1
   Select Case Lichtflag
      Case Dauerlicht_ein : Lcd "AUS"
      Case Dauerlicht_aus : Lcd "EIN"
      Case Else : Lcd "---"
   End Select

Return
'-- Menue_men42 ---------------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men43 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men43:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men43"
   #endif                                                   ' Trace

   ' Zustand Sound ausgeben
   Locate 3 , 1
   Select Case Soundflag
      Case Sound_ein : Lcd "EIN"
      Case Sound_aus : Lcd "AUS"
      Case Else : Lcd "---"
   End Select

Return
'-- Menue_men43 ---------------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men44 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men44:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men44"
   #endif                                                   ' Trace

   ' Block-Count und Block-Write-Count ausgeben
   Locate 3 , 1 : Lcd "B: " ; Ee_data_block_count ; " W: " ; Ee_data_block_write_count

Return
'-- Menue_men44 ---------------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men45 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men45:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men45"
   #endif                                                   ' Trace

   ' Einstellungswert für Übertemperatur ausgeben
   Temp_byte_1 = Makebcd(uebertemperatur)
   Locate 3 , 1 : Lcd Bcd(temp_byte_1) ; " {223}C"

Return
'-- Menue_men44 ---------------------------------------------------------------

'------------------------------------------------------------------------------
' MENUE - Gosub-Routine: Menue_men5111 (Menue-Unterstützung-Routine)
' Routine wird von Menue-State-Machine bei eintritt in Menue aufgerufen.
' Funktion dient zum Errechnen von Werten, Ausgeben von Informationsn usw. die
' ergänzend zum jeweiligen Menueschritt benötigt werden.
'------------------------------------------------------------------------------
Menue_men5111:

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

   ' Trace Output schreiben
   #if Menue_testmodus                                      ' Trace
      Print #3 , "Enter Menue_men5111"
   #endif                                                   ' Trace

   ' Demomodus ausführen
   Gosub Rs485_demomode

   ' Normalmodus herstellen

   ' Gesamtsystem in LUM schalten
   Temp_byte_1 = Rs485_last_used_mode()

   ' Überprüfen ob LUM einen Fehler ausgelöst hat
   If Temp_byte_1 = True Then
      ' JA

      ' ggf. Trace auf RS232 ausgeben
      #if Error_testmodus
         Print #3 , "[6] Error(4): Fehler bei Ausführung von LUM"
      #endif

      ' ## Error ##
      ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
      Error_flags(4) = True                                 ' Fehler in Matrix eintragen
      Err_global_flag = True

   End If

   ' Menü zurück auf Hauptmenü schalten
   Menue_state = Loadlabel(men5)                            ' Startbildschirm
   Gosub Menue_change_state
   Gosub Lcd_print

Return
'-- Menue_men5111 -------------------------------------------------------------

' ********************
' * COMMON Routines  *
' ********************

'------------------------------------------------------------------------------
' Gosub-Routine: Slave_verarbeitung
' Hier werden die via RS485 empfangenen Daten verarbeitet
'------------------------------------------------------------------------------
'Slave_verarbeitung:

'   ' In Abhängigkeit der Konstante Traceausgabe schreiben
'   #if Rs485_testmodus
'      Print #3 , "Slave_verarbeitung"
'   #endif

'   Select Case Rx_kommando

'      Case Resp_ack:

'   End Select

'   ' Semaphore wieder auf False setzen um nächstes Datenpaket zu empfangen
'   Rs485_data_received = False

'Return
'-- End Slave_verarbeitung ----------------------------------------------------

'------------------------------------------------------------------------------
' Gosub-Routine: Scheduler
' Subroutine Abprüfen der in RUNNING befindlichen SW-Timer
'------------------------------------------------------------------------------
Scheduler:

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

  ' *** Sequence [01] - Temperaturmessung ***

   ' Überprüfung ob Temperatur gemessen werden kann und soll
   If Timercounter >= Ds1820_erfassungs_counter Then

      Gosub Ds1820_measurement

      ' Scheduler erneut setzen
      Ds1820_erfassungs_counter = Timercounter + Ds1820_auswertung

      ' Prüfung auf Übertemperatur
      If Ds1820_temperatur >= Uebertemperatur Then

         ' JA; Übertemperatur

         Flag_uebertemperatur = True

         ' Wenn Flag Übertemperatur = True dann auf jeden Fall im Sekundetack Peep

         ' ggf. Trace auf RS232 ausgeben
         #if Error_testmodus
            Print #3 , "[7] Error(2): Master hat Übertemperatur"
         #endif

         ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
         ' ## Error ##
         Error_flags(2) = True                              ' Fehler in Matrix eintragen
         Err_global_flag = True

      Else                                                  ' Übertemperatur

         ' Nein, keine Übertemperatur -> Flag auf jeden Fall zurücksetzen

         ' Prüfen ob System aus Übertemperatur in Normalmodus wechselt
         If Flag_uebertemperatur = True Then

            ' JA, Zustand wird umgeschaltet

            Flag_uebertemperatur = False
            Temp_led = Led_aus
            Piezo = Sound_aus

            ' Anmerkung:
            ' Temp_led wird gleichzeitig als Indikator über Abschaltung Gesamtsystem
            ' verwendet. Würde man hier nicht den Systemübergang überprüfen und aus-
            ' werten, dann würde Routine automatisch LED abschalten.

         End If                                             ' Zustandswechsel
      End If                                                ' Übertemperatur
   End If                                                   ' Ende Temperaturmessung

   ' *** Sequence [02] - Update der EEPROM-Daten *****

   ' Prüfen ob EEPROM-Daten gespeichert werden müssen
   If Timercounter >= Ee_update_counter Then

      'JA

      ' Ggf. EEPROM updaten
      #if Scheduler_testmodus                               ' Trace
         Print #3 , "[02] EEPROM Update"
      #endif                                                ' Trace

      Gosub Ee_data_update

      ' Scheduler erneut setzen
      Ee_update_counter = Timercounter + Ee_data_update_timer_value

   End If                                                   ' EEPROM Daten-Update

   ' *** Sequence [03] - Screensaver ***

   ' Überprüfung ob Screensaver eigeschaltet
   If Lcd_screensaver = True Then
      ' JA, Screensaver ist eingeschaltet

      ' Prüfen ob der Screen bereits aktiv ist
      If Lcd_screensaver_aktiv = False Then
         ' Nein, Screensaver ist noch nicht abgelaufen

         ' Ist es Zeit für den Screensaver zu handeln?
         If Timercounter >= Lcd_screensaver_counterthen
            ' JA, Zeit abgelaufen

            ' Traceausgabe wenn Sequencer Aufgabe [03] ausführt
            #if Scheduler_testmodus                         ' Trace
               Print #3 , "[03] Screensaver"
            #endif                                          ' Trace

            ' Display Hintergrundbeleuchtung ausschalten
            Gosub Lcd_beleuchtung_aus
            ' Display ausschalten
            Gosub Lcd_display_aus

            ' Flag setzen
            Lcd_screensaver_aktiv = True

            ' Ggf. Trace ausgeben
            #if Screensaver_testmodus                       ' Trace
               Print #3 , "Scheduler: LCD Screensaver aktiv"
            #endif                                          ' Trace

         End If                                             ' Timer abgelaufen
      End If                                                ' Screensaver aktiv
   End If                                                   ' Screensaver eingeschaltet

   ' *** Sequence [04] -  Menü-Updates ***

   ' Prüfen ob Menü-Update gemacht werden soll
   If Timercounter >= Menue_update_counter Then
      ' JA

      ' Überprüfung ob ein Menüinhalt upgedated werden muss
      If Menue_menueupdate_flag <> 0 Then

         ' Traceausgabe wenn Sequencer Aufgabe [10] ausführt
         #if Scheduler_testmodus                            ' Trace
            Print #3 , "[04] Menü-Updates"
         #endif                                             ' Trace

         ' JA, es gibt einen aktiven Inhalt => Inhalt anzeigen durch Aufruf Subroutine
         Gosub Menue_call_subroutine

      End If                                                ' Menü-Update

      ' Scheduler erneut setzen
      Menue_update_counter = Timercounter + Menue_update_time
   End If                                                   ' Menue-Update

   ' *** Sequence [05] -  Prüfung der Slaves auf Übertemperatur ***

   ' Prüfung ob Abfrage überhaupt notwendig. Wenn Anlage abgeschaltet dann auch keine Prüfung
   If Anlagenflag = True Then

      ' JA, Anlage ist eingeschaltet und kann geprüft werden

      ' Prüfung ob Auswertung gemacht werden soll
      If Timercounter >= Slave_temp_counter Then
         'JA

         ' Scheduler erneut setzen
         Slave_temp_counter = Timercounter + Slave_temp_auswertung

         ' Schleife über alle Slaves
         For Temp_byte_4 = 1 To 8

            ' Prüfen ob einer der Slaves Übertemperatur hat
            Temp_byte_5 = Rs485_status_abfragen(temp_byte_4)

            ' Traceausgabe wenn Sequencer Aufgabe [10] ausführt
            #if Scheduler_testmodus                         ' Trace
               Print #3 , "Scheduler: Abfrage Slave " ; Temp_byte_4 ; " - Ergebnis " ; Temp_byte_5
            #endif                                          ' Trace

            ' Prüfen ob Kommunikationsfehler

            ' Rückgabewert:  Bytevariable
            '                TRUE  = Slave hat geantwortet bzw. Ausführung OK
            '                FALSE = Es ist ein Fehler aufgetreten

            If Temp_byte_5 = False Then
               ' JA

               ' ggf. Trace auf RS232 ausgeben
               #if Error_testmodus
                  Print #3 , "[8] Error(4): Kummunikationsfehler mit Slave im Scheduler"
               #endif

               ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
               Error_flags(4) = True                        ' Fehler in Matrix eintragen
               Err_global_flag = True

            Else                                            ' Kommunikationsfehler

               ' NEIN

               ' Traceausgabe wenn Sequencer Aufgabe [10] ausführt
               #if Scheduler_testmodus                      ' Trace
                  Print #3 , "Scheduler: Temperatur Slave " ; Slave_temperatur(temp_byte_4)
               #endif                                       ' Trace

               ' Prüfen auf Übertemperatur
               If Slave_temperatur(temp_byte_4 ) > Uebertemperatur Then

                  ' JA

                  ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
                  Error_flags(6) = True                     ' Fehler in Matrix eintragen
                  Err_global_flag = True

                  ' Bite setzen
                  Temp_byte_6 = Temp_byte_4 - 1
                  Set Slave_temp_bitfeld.temp_byte_6        ' Bit setzen

                  ' ggf. Trace auf RS232 ausgeben
                  #if Error_testmodus
                     Print #3 , "Error(6): Einer der Slaves hat Übertemperatur - " ; Bin(slave_temp_bitfeld)
                  #endif

               End If                                       ' Übertemperatur

            End If                                          ' Kein Komunikationsfehler
         Next Temp_byte_4                                   ' Schleife über alle Slaves
      End If                                                ' Temperaturauswertung Slaves
   End If                                                   ' Anlagenstatus

   ' *** Sequence [06] -  Receive-Timeout-Überwachung ***

   ' Prüfen, ob Überwachung gemacht werden muss
   If Receive_timeout_flag = True Then

      ' JA

      ' Prüfen ob Timeout abgelaufen
      If Timercounter > Receive_timeout_counter Then

         ' JA, Timeout abgelaufen

         ' ggf. Trace ausgeben
         #if Empfangsueberwachung_testmodus
            Print #3 , "Scheduler: Loeschen aller Buffer und Datenstrukturen"
         #endif

         ' Timeoutflag zurücksetzen
         Receive_timeout_flag = False

         ' ----- RS485 -----

         ' Sende- und Empfangsstrukturen neu initialisieren
         Rx_bufferindex = 1                                 ' Index auf 1
         Tx_bufferindex = 1                                 ' Index auf 1

         Rs485_data_received = False                        ' Receive-Status

         ' RS485 Empfangbuffer und Sendebuffer löschen
         Clear Serialin                                     ' RxD
         Clear Serialout                                    ' TxD

         ' ----- SCART -----

         ' Sende- und Empfangsstrukturen neu initialisieren
         Rf_rx_bufferindex = 1
         Rf_tx_bufferindex = 1
         Rf_rx_errorflag = False
         Rf_tx_errorflag = True

         ' SCART Empfangsbuffer und Sendebuffer löschen
         Clear Serialin1                                    ' RxD
         Clear Serialout1                                   ' TxD

         ' ----- Fehlerflags und Fehlereintrag -----

         ' ggf. Trace auf RS232 ausgeben
         #if Error_testmodus
            Print #3 , "[12] Error(9): Fehler in Receive-Timeout-Ueberwachung"
         #endif

         ' ## Error ##
         ' Fehler auch in Fehlermatrix zur Ausgabe von Fehlertext eintragen
         Error_flags(9) = True                              ' Fehler in Matrix eintragen
         Err_global_flag = True

      End If                                                ' Timer abgelaufen
   End If                                                   ' Timeourüberwachung aktiv

Return
'-- End Scheduler -------------------------------------------------------------

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

Close #4                                                    ' RS232 Kanal 4 schließen
Close #3                                                    ' RS232 Kanal 3 schließen
Close #2                                                    ' RS232 Kanal 2 schließen
Close #1                                                    ' RS232 Kanal 1 schließen

End                                                         'end program

'------------------------------------------------------------------------------
' DATA:           Bedatung der Menue-State-Machine
' Rückgabewerte:  Zeiger auf Zustände , Unterprogramme, Displaytexte, usw.
' Beschreibung:   1. Zeile: für jede Taste genau eine Verzeigung ADR2
'                           (siehe auch Anzahl der Tasten (Key_buttons = xx))
'                           Reihenfolge der Tasten in Zeile 1:
'                                Hoch | Runter | Links | Rechts | Enter
'                 2. Zeile: Sprunglabel als ADR2 für ein ggf. anzuspringendes
'                           Unterprogramm
'                 3. Zeile: Binaermuster für Ausgabeflag von LCD-Zeile 1-3
'                 4. Zeile: Displaytext für LCD-Zeile 1 des akt. Status als DATA Feld
'                 5. Zeile: Displaytext für LCD-Zeile 2 des akt. Status als DATA Feld
'                 6. Zeile: Displaytext für LCD-Zeile 3 des akt. Status als DATA Feld
' Hinweis:        wenn nichts passieren soll wird das Label NULL eingetragen
'------------------------------------------------------------------------------

' Null ist ein Dummy-Flag für Zustand und Gosub -> tue nichts
Null:
         Return

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

' Menü MEN1 - Dimmerstatus und Einstellen
Men1:
         ' Hoch       Runter      Links       Rechts
         Adr2 Men5 : Adr2 Men2 : Adr2 Null : Adr2 Men11
         Adr2 Null
         Data &B00000111
         '     1234567890123456
         Data "2            2/5"
         Data " Dimmer  Status"
         Data " und einstellen"

Men11:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men18 : Adr2 Men12 : Adr2 Men1 : Adr2 Men111
         Adr2 Menue_men11
         Data &B00000111
         '     1234567890123456
         Data "2-1          1/8"
         Data "Dimmer: 1"
         Data "Temp:    Dim:"

Men111:
         ' Hoch      Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Null : Adr2 Null
         Adr2 Menue_men111
         Data &B00000000
         '     1234567890123456
         Data ""
         Data ""
         Data ""

Men12:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men11 : Adr2 Men13 : Adr2 Men1 : Adr2 Men121
         Adr2 Menue_men12
         Data &B00000111
         '     1234567890123456
         Data "2-2          2/8"
         Data "Dimmer: 2"
         Data "Temp:    Dim:"

Men121:
         ' Hoch      Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Null : Adr2 Null
         Adr2 Menue_men121
         Data &B00000000
         '     1234567890123456
         Data ""
         Data ""
         Data ""

Men13:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men12 : Adr2 Men14 : Adr2 Men1 : Adr2 Men131
         Adr2 Menue_men13
         Data &B00000111
         '     1234567890123456
         Data "2-3          3/8"
         Data "Dimmer: 3"
         Data "Temp:    Dim:"

Men131:
         ' Hoch      Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Null : Adr2 Null
         Adr2 Menue_men131
         Data &B00000000
         '     1234567890123456
         Data ""
         Data ""
         Data ""

Men14:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men13 : Adr2 Men15 : Adr2 Men1 : Adr2 Men141
         Adr2 Menue_men14
         Data &B00000111
         '     1234567890123456
         Data "2-4          4/8"
         Data "Dimmer: 4"
         Data "Temp:    Dim:"

Men141:
         ' Hoch      Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Null : Adr2 Null
         Adr2 Menue_men141
         Data &B00000000
         '     1234567890123456
         Data ""
         Data ""
         Data ""

Men15:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men14 : Adr2 Men16 : Adr2 Men1 : Adr2 Men151
         Adr2 Menue_men15
         Data &B00000111
         '     1234567890123456
         Data "2-5          5/8"
         Data "Dimmer: 5"
         Data "Temp:    Dim:"

Men151:
         ' Hoch      Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Null : Adr2 Null
         Adr2 Menue_men151
         Data &B00000000
         '     1234567890123456
         Data ""
         Data ""
         Data ""

Men16:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men15 : Adr2 Men17 : Adr2 Men1 : Adr2 Men161
         Adr2 Menue_men16
         Data &B00000111
         '     1234567890123456
         Data "2-6          6/8"
         Data "Dimmer: 6"
         Data "Temp:    Dim:"

Men161:
         ' Hoch      Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Null : Adr2 Null
         Adr2 Menue_men161
         Data &B00000000
         '     1234567890123456
         Data ""
         Data ""
         Data ""

Men17:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men16 : Adr2 Men18 : Adr2 Men1 : Adr2 Men171
         Adr2 Menue_men17
         Data &B00000111
         '     1234567890123456
         Data "2-7          7/8"
         Data "Dimmer: 7"
         Data "Temp:    Dim:"

Men171:
         ' Hoch      Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Null : Adr2 Null
         Adr2 Menue_men171
         Data &B00000000
         '     1234567890123456
         Data ""
         Data ""
         Data ""

Men18:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men17 : Adr2 Men11 : Adr2 Men1 : Adr2 Men181
         Adr2 Menue_men18
         Data &B00000111
         '     1234567890123456
         Data "2-8          8/8"
         Data "Dimmer: 8"
         Data "Temp:    Dim:"

Men181:
         ' Hoch      Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Null : Adr2 Null
         Adr2 Menue_men181
         Data &B00000000
         '     1234567890123456
         Data ""
         Data ""
         Data ""

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

' Menü MEN2 - Einstellen
Men2:
         ' Hoch       Runter      Links       Rechts
         Adr2 Men1 : Adr2 Men3 : Adr2 Null : Adr2 Men21
         Adr2 Null
         Data &B00000111
         '     1234567890123456
         Data "3            3/5"
         Data " Einstellungen"
         Data "   System"

Men21:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men22 : Adr2 Men22 : Adr2 Men2 : Adr2 Men211
         Adr2 Null
         Data &B00000111
         '     1234567890123456
         Data "3-1          1/2"
         Data "Temperaturalarm"
         Data " Schwellenwert"

Men211:
         ' Hoch      Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Men21 : Adr2 Null
         Adr2 Menue_men211
         Data &B00000001
         '     1234567890123456
         Data "   Temperatur"
         Data ""
         Data ""

Men22:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men21 : Adr2 Men21 : Adr2 Men2 : Adr2 Men221
         Adr2 Null
         Data &B00000011
         '     1234567890123456
         Data "3-2          2/2"
         Data "  Soundausgabe"
         Data ""

Men221:
         ' Hoch        Runter        Links       Rechts
         Adr2 Men221 : Adr2 Men221 : Adr2 Men22 : Adr2 Null
         Adr2 Menue_men221
         Data &B00000001
         '     1234567890123456
         Data "     Sound"
         Data ""
         Data ""

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

' Menü MEN3 - Fehlermeldungen
Men3:
         ' Hoch       Runter      Links       Rechts
         Adr2 Men2 : Adr2 Men4 : Adr2 Null : Adr2 Men31
         'Adr2 Menue_men3
         Adr2 Menue_men3
         Data &B00000011
         '     1234567890123456
         Data "4            4/5"
         Data "Fehlermeldungen"
         Data ""

Men31:
         ' Hoch      Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Men3 : Adr2 Null
         Adr2 Menue_men31
         Data &B00000001
         '     1234567890123456
         Data "Fehler:"
         Data ""
         Data ""

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

' Menü MEN4 - Systemstatus
Men4:
         ' Hoch      Runter      Links       Rechts
         Adr2 Men3 : Adr2 Men5 : Adr2 Null : Adr2 Men41
         Adr2 Null
         Data &B00000011
         '     1234567890123456
         Data "5            5/5"
         Data "  Systemstatus"
         Data ""

Men41:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men44 : Adr2 Men42 : Adr2 Men4 : Adr2 Men42
         Adr2 Menue_men41
         Data &B00000011
         '     1234567890123456
         Data "5-1          1/5"
         Data "Temperatur:"
         Data ""

Men42:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men41 : Adr2 Men43 : Adr2 Men4 : Adr2 Men43
         Adr2 Menue_men42
         Data &B00000011
         '     1234567890123456
         Data "5-2          2/5"
         Data "Relais:"
         Data ""

Men43:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men42 : Adr2 Men44 : Adr2 Men4 : Adr2 Men44
         Adr2 Menue_men43
         Data &B00000011
         '     1234567890123456
         Data "5-3          3/5"
         Data "Sound:"
         Data ""

Men44:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men43 : Adr2 Men45 : Adr2 Men4 : Adr2 Men45
         Adr2 Menue_men44
         Data &B00000011
         '     1234567890123456
         Data "5-4          4/5"
         Data "EEPROM-Status:"
         Data ""

Men45:
         ' Hoch       Runter       Links       Rechts
         Adr2 Men43 : Adr2 Men41 : Adr2 Men4 : Adr2 Men41
         Adr2 Menue_men45
         Data &B00000011
         '     1234567890123456
         Data "5-5          5/5"
         Data "UeberTempGrenze:"
         Data ""

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

' Menü MEN5 - Hauptmenue StarLight
Men5:
         ' Hoch       Runter      Links       Rechts
         Adr2 Men4 : Adr2 Men1 : Adr2 Null : Adr2 Men51
         Adr2 Null
         Data &B00000111
         '     1234567890123456
         Data "1            1/5"
         Data "   Hauptmenue"
         Data "   StarLight"

Men51:
            ' Hoch       Runter      Links       Rechts
            Adr2 Null : Adr2 Null : Adr2 Men5 : Adr2 Men511
            Adr2 Null
            Data &B00000111
            '     1234567890123456
            Data "1-1"
            Data "StarLight   V1.2"
            Data "(C) M.Fulde 2011"

Men511:
            ' Hoch       Runter      Links       Rechts
            Adr2 Null : Adr2 Null : Adr2 Men51 : Adr2 Men5111
            Adr2 Null
            Data &B00000010
            '     1234567890123456
            Data ""
            Data "   Demo-Modus"
            Data ""

Men5111:
            ' Hoch       Runter      Links       Rechts
            Adr2 Null : Adr2 Null : Adr2 Men511 : Adr2 Null
            Adr2 Menue_men5111
            Data &B00000010
            '     1234567890123456
            Data ""
            Data "Demo-Mode aktiv!"
            Data ""

'-- Bedatung von wiederverwendbaren Spezialmenüs ------------------------------

' Statemachine für universelle Dimmereinstellung
Dim1:
         ' Hoch       Runter       Links           Rechts
         Adr2 Dim11 : Adr2 Dim12 : Adr2 Dim_ende : Adr2 Dim2
         Adr2 Menue_dim1
         Data &B00000111
         '     1234567890123456
         Data "  Einstellung"
         Data "Dimmer:"
         Data "Dimmstufe:"

Dim11:
         ' Hoch       Runter       Links           Rechts
         Adr2 Dim11 : Adr2 Dim12 : Adr2 Dim_ende : Adr2 Dim2
         Adr2 Menue_dim11
         Data &B00000111
         '     1234567890123456
         Data "  Einstellung"
         Data "Dimmer:"
         Data "Dimmstufe:"

Dim12:
         ' Hoch       Runter       Links           Rechts
         Adr2 Dim11 : Adr2 Dim12 : Adr2 Dim_ende : Adr2 Dim2
         Adr2 Menue_dim12
         Data &B00000111
         '     1234567890123456
         Data "  Einstellung"
         Data "Dimmer:"
         Data "Dimmstufe:"

Dim2:
         ' Hoch       Runter       Links       Rechts
         Adr2 Dim21 : Adr2 Dim22 : Adr2 Dim1 : Adr2 Null
         Adr2 Menue_dim2
         Data &B00000111
         '     1234567890123456
         Data "  Einstellung"
         Data "Dimmer:"
         Data "Dimmstufe:"

Dim21:
         ' Hoch       Runter       Links       Rechts
         Adr2 Dim21 : Adr2 Dim22 : Adr2 Dim1 : Adr2 Null
         Adr2 Menue_dim21
         Data &B00000111
         '     1234567890123456
         Data "  Einstellung"
         Data "Dimmer:"
         Data "Dimmstufe:"

Dim22:
         ' Hoch       Runter       Links       Rechts
         Adr2 Dim21 : Adr2 Dim22 : Adr2 Dim1 : Adr2 Null
         Adr2 Menue_dim22
         Data &B00000111
         '     1234567890123456
         Data "  Einstellung"
         Data "Dimmer:"
         Data "Dimmstufe:"

Dim_ende:
         ' Hoch       Runter      Links       Rechts
         Adr2 Null : Adr2 Null : Adr2 Null : Adr2 Null
         Adr2 Menue_dim_ende
         Data &B00000000
         '     1234567890123456
         Data ""
         Data ""
         Data ""

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

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

'################################### Historie #################################
' 01.08.2010 : Version 0.0
'              Beginn der Implementierungen für StarLight
' 13.02.2011 : Version 1.0
'              Erste inbetriebgenommene Gesamtversion
' 17.02.2011 : Version 1.1
'              Übertemperaturwert in ACK-Botschaft eingebaut als Info für Betty
' 07.03.2011 : Version 1.2
'              - Relaisstufen für Tischbeleuchtung werden nach LUM geschaltet
'              - Verschiedene Funktionen speichern Daten sofort in EEPROM
'##############################################################################