'############################################################################## ' Objekt 8 "mocolock" ' LED-Platine (Rotor) ' ' Layout und Programmierung by HELLMARS (C) Helmar Müller ' Stand 15.10.2009 ' HW: 2.1 ' - ATMega32, 16MHz Quarz extern ' - Erfassung der Drehbewegung über Hall-Sensor ' - erweiterte Resetschaltung analog Ray ' ' SW: 3.0 ' - Darstellung von Bild- und Textdaten aus Flash-Speicher ' - Umwandlung von Uhrzeit in Text und Darstellung als Text ' - Steuerung der LED´s über SPI mittels 74HC59581 Latch ' - Empfang serieller Daten von Spannungsversorgung-Platine über USART ' - Auswertung von Steuerbefehlen über USART (Befehle siehe Const) ' - Auswertung von Uhrzeit/Datum über USART ' - Steuerung über automat. Programmablauf ' - Ablauf eines Intro bei Reset ' - Freigabe/Sperrung des Displays für Darstellung ueber Drehzahl ' ' ' Pinbelegung: ' ' Atmega32 Peripherie ' ' Pin 9 = Reset ==> SPI Pin5 = RST ' Pin14 = PD0 = RXD ==> CON Master Pin3 = USART ' Pin16 = PD2 = INT0 <== CON Hall Pin3 = Signal ' Pin17 = PD3 = INT1 <== Remote Pin1 = Signal ' Pin 5 = PB4 = SS ==> über R auf Vcc ==> CON Latch Pin3 ' Pin 6 = PB5 = MOSI ==> SPI Pin1 = MOSI ==> CON Latch Pin4 ' Pin 7 = PB6 = MISO <== SPI Pin9 = MISO ' Pin 8 = PB7 = SCK ==> SPI Pin7 = SCK ==> CON Latch Pin6 ' '############################################################################## '------------------------------------------------------------------------------ ' Fuse- und Lockbits '------------------------------------------------------------------------------ '$prog &HFF , &HFF , &HDA , &HFD ' mega324p '$prog &HFF , &HFF , &HDA , &H00 ' mega32 '------------------------------------------------------------------------------ ' Compilerinstruktionen und Compilerdirektiven '------------------------------------------------------------------------------ $regfile = "m32def.dat" $hwstack = 32 'hardware stack $swstack = 10 'software stack $framesize = 40 'frame space $crystal = 16000000 'Quarzfrequenz '------------------------------------------------------------------------------ ' Einbinden benötigter Libraries '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ ' Definition der Unterprogramme und Funktionen '------------------------------------------------------------------------------ Declare Sub Init_variablen() Declare Sub Init_seriell() Declare Sub Serielle_daten_empfangen() Declare Sub Serielle_daten_zuweisen() Declare Sub Sprungadresse_ermitteln() Declare Sub Steuerung_ablauf() Declare Sub Text_array_loeschen() Declare Sub Text_in_zeichen() Declare Sub Zeichen_aus_tabelle() Declare Sub Zeit_in_text() Declare Sub Anzeige_display() Declare Sub Darstellung_zeugs() Declare Sub Zeit_in_rotorposition() '------------------------------------------------------------------------------ ' Definition von Konstanten '------------------------------------------------------------------------------ Const On = 1 Const Off = 0 Const X_mal_empfangen = 3 ' serielle bytes werden soviel mal gesendet Const Anzahl_rotorstellungen = 360 '= aufloesung ; daraus errechnet sich groesse des datensatzes Const Bytes_pro_rotorstellung = 4 Const Groesse_datensatz = 1440 '= 360 * 4 (bytes) = 1440 ! Const Anzahl_grafiken = 9 'incl. 0 d.h. tatsächliche anzahl datensaetze - 1 (10 - 1 = 9) Const Anzahl_texte = 6 'incl. 0 d.h. tatsächliche anzahl datensaetze - 1 ( Const Pos_texte_mocolock = 3 'ab position 3 fangen texte zur leuchte an Const Abschalten = 2 ' ----- Modi und IR-Befehle----- Const Anzeige_grafik = &H11 ' 0001 0001 Const Anzeige_text = &H12 ' 0001 0010 Const Anzeige_uhr_digital = &H15 ' 0001 0101 Const Anzeige_uhr_analog = &H16 ' 0001 0110 ' ----- Befehle und IR-Befehle----- Const Anzeige_uhr = &H14 ' 0001 0100 Const Daten_uhr = &H18 ' 0010 0001 Const Datensatz_vor = &H21 ' 0010 0001 Const Datensatz_zurueck = &H22 ' 0010 0010 Const Programm_vor = &H24 ' 0010 0100 Const Programm_zurueck = &H28 ' 0010 1000 Const Motor_an = &H09 ' 0000 1001 Const Motor_aus = &H06 ' 0000 0110 ' ----- Programme ----- Const Programm_1 = &H01 ' = start sequenz Const Programm_2 = &H02 ' = programm moccafe: gafik, text und uhr im loop Const Programm_3 = &H03 ' = programm mocolock: grafik, text und uhr im loop Const Programm_x = &H04 ' = programm grafiken: grafiken im loop '------------------------------------------------------------------------------ ' Definition von Ressourcen '------------------------------------------------------------------------------ ' ----- Zuweisungen ----- In_hall Alias Portd.2 ' ----- Konfiguration der Port's ----- Config Pind.2 = Input 'Interrupt über HAll-Sensor In_hall = On 'Pull-up einschalten '------------------------------------------------------------------------------ ' Konfiguration der Schnittstellen '------------------------------------------------------------------------------ ' ----- Hardware-SPI zur Ansteuerung der LED's ----- ' CONFIG SPI = HARD, INTERRUPT=ON|OFF, DATA ORDER = LSB|MSB , MASTER = YES|NO , POLARITY = HIGH|LOW , PHASE = 0|1, CLOCKRATE = 4|16|64|128 , NOSS=1|0 ' Hardware-SPI einstellen, SPI Bus initialisieren, setzt das DDR Register entsprechend ' *** folgende Einstellung hat sich bewährt *** Config Spi = Hard , Master = Yes , Clockrate = 4 , Noss = 0 ' , Polarity = Low , Phase = 0 , Data Order = Lsb , Spiinit ' ----- Hardware-UART (RS232) zur Kommunikation mit Master ----- ' CONFIG COM1 = baud , synchrone=0|1,parity=none|disabled|even|odd,stopbits=1|2,databits=4|6|7|8|9,clockpol=0|1 ' *** Baud-Rate in Versuchen anpassen *** Config Com1 = 19200 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0 Config Serialin = Buffered , Size = 20 '------------------------------------------------------------------------------ ' Konfiguration der Interrupts und Timer '------------------------------------------------------------------------------ ' ----- Interrupt0 (Hall-Sensor) mit fallender Flanke ------ ' Definition der Sprungmarke bei aktivem Interrupt Config Int0 = Falling Enable Int0 On Int0 Interrupt_hall ' Timer PRESCALE= 1|8|64|256|1024 ' ' ----- Config Timer1 (16 Bit = 65536), Takt = 16 Mhz => 0,0625 us ----- ' Interrupt nach 4,096 ms (65536 * 0,0625 us * 1) bei Prescale 1 ' 32,768 ms (65536 * 0,0625 us * 8) 8 ' 262,144 ms ( * 64) 64 ' 1,048 s ( * 256) ' 4,194 s ( *1024) Config Timer1 = Timer , Prescale = 64 Enable Timer1 On Timer1 Tim1_isr ' ----- Config Timer0 (8 Bit = 256), Takt = 16Mhz = 0,0625 us ----- ' Interrupt nach 16 us (256 * 0,0625 us * 1) bei Prescale 1 ' 128 us (256 * 0,0625 us * 8) bei Prescale 8 ' 1,024 ms ( * 64) ' 4,096 ms ( * 256) ' 16,384 ms ( *1024) Config Timer0 = Timer , Prescale = 64 Enable Timer0 On Timer0 Tim0_isr ' ----- Config Timer2(8 Bit = 256) , Takt = 16mhz = 0 , 0625 Us ----- ' Interrupt nach 16 us (256 * 0,0625 us * 1) bei Prescale 1 ' 128 us (256 * 0,0625 us * 8) bei Prescale 8 ' 1,024 ms ( * 64) ' 4,096 ms ( * 256) ' 16,384 ms ( *1024) Config Timer2 = Timer , Prescale = 1024 ' Sekundentimer: Timer2 = 0 ' ==> 1s / 16,384 ms = 61,035156 Enable Timer2 ' ==> d.h Sekundentakt nach 61mal Timer2 Interrupt On Timer2 Tim2_isr Enable Interrupts ' Interrupts aktivieren '------------------------------------------------------------------------------ ' Definition der Hauptvariablen '------------------------------------------------------------------------------ Dim Flag_seriell_empfangen As Bit ' wird gesetzt wenn serielle daten empfangen wurden Dim Flag_sprungadresse_ermitteln As Bit ' wird gesetzt wenn sprungadresse in abh. des entspr. zählers ermittelt werden soll Dim Flag_sec_blinken As Bit ' wird gesetzt um blinken zu realisieren Dim Flag_uhr_aktuell As Bit ' wird gesetzt wenn uhrzeit aktualisiert wird Dim Flag_anzeige_programm As Bit ' wird gesetzt wenn programm und modus angezeigt werden sollen Dim Flag_intro_sequenz As Bit ' wird gesetzt bei wake up und rueckgesetzt bei erster ir-anforderung Dim Flag_text_umwandeln As Bit ' text zur anzeige im daplay in rotor daten umwandeln Dim Flag_text_nr As Bit ' zur unterscheidung von text oben und unten Dim Flag_array_loeschen As Bit Dim Flag_motor_aus As Bit ' wird gesetzt wenn nachricht erhalten wird Dim Flag_rotor_dreht As Bit ' Dim Flag_rotor_langsam As Bit ' Dim Flag_1_sekunde As Bit 'flag wird jede sekunde gesetzt Dim Flag_1_minute As Bit Dim Count_ovf0 As Byte 'überlaufzähler Dim Count_ovf1 As Byte Dim Count_ovf2 As Byte Dim Var_sekunde As Byte 'wird jede sekunde hochgezählt und variabel für steuerung 'für random und startsequenz benutzt Dim Sekunde As Byte Dim Minute As Byte Dim Stunde As Byte 'div. zähler für interne generierung der zeit Dim Tag As Byte 'und aktualisierung mit dcf Dim Monat As Byte Dim Jahr As Byte Dim Wochentag As Byte Dim Wochentag_string As String * 5 'variabel für in string umgewandelten wochentag Dim Zeit_string As String * 20 'variable für in string umgewandelte uhrzeit Dim Datum_string As String * 20 Dim Rotor_stellung As Integer 'zähler für rotorstellung, 1...360 entspricht einem Winkel Dim Position_stunde As Integer Dim Position_minute As Integer Dim Position_sekunde As Integer Dim Modus As Byte 'Variablen zur Steuerung der Ablaeufe Dim Befehl As Byte Dim Programm As Byte Dim Programm_old As Byte Dim Zeit_pro_umdrehung As Long 'zeit zwischen zwei hall-sensor-signalen Dim Zeit_pro_darstellung As Word 'zeit zwischen zwei hall-sensor-signalen / 360 Dim Ser_inbyte(3) As Byte 'variable für steuerung der seriell empfangenen daten Dim Zaehler_bytes_erhalten As Byte Dim Zaehler_datenpaket As Integer Dim Sprungadresse_grafik As Word 'startadresse für einen bestimmten datensatz Dim Sprungadresse_relativ As Word 'hilfsvariable zur ermittlung von sprungadresse (start und rotor) Dim Sprungadresse_absolut As Word 'sprungadresse in best. datensatz in abhängigkeit der rotor_stellung Dim Sprungadresse_text As Word 'startadresse für bestimmten text Dim Sprungadresse_zeichen As Word Dim Zaehler_grafik As Byte 'zähler zur steuerung der grafik-datensätze Dim Zaehler_text As Byte ' text-datensätze Dim Text_oben As String * 50 'variable zur übernahme der information aus bestimmter Dim Text_unten As String * 50 'text-sprungadresse Dim Text_daten(anzahl_rotorstellungen) As Byte 'in led-muster umgewandelter text in abh. der rotor-position Dim Daten_zu_latch(4) As Byte 'variablen zur ansteuerung der led´s Dim Latch As Byte 'variable zur ansteuerung des latcs Dim Laenge_text As Word Dim Datensatz_position As Integer 'variable zur ermittlung rotor-position, wo text beginnen soll Dim Zeichen As String * 1 Dim Zeichen_in_text As Byte 'variablen zur umwandlung von text in darstellbare led-muster Dim Asciwert As Byte Dim Zaehler_klein As Byte Dim Zaehler_gross As Integer '------------------------------------------------------------------------------ ' Initialisierungen von Variablen nach Reset '------------------------------------------------------------------------------ Zeit_string = "kein" 'vordefinition, da noch keine uhrzeit vorhanden Datum_string = "Signal" Zaehler_grafik = 0 'heißt 1-ter datensatz Zaehler_text = 0 Sprungadresse_text = 1 '1-ter text im datensatz des textbereichs Sprungadresse_grafik = Loadlabel(startsequenz) 'startbereich fuer betriebs-grafiken laden Modus = Anzeige_grafik 'start-modus Programm = Programm_1 Set Flag_intro_sequenz '------------------------------------------------------------------------------ ' Initialisierungen von Timer, Variablen und Array '------------------------------------------------------------------------------ Beginn: Call Init_variablen() Call Init_seriell 'serielle variablen initialisieren '############################################################################## ' Hauptprogramm '############################################################################## Do Call Serielle_daten_empfangen() Call Serielle_daten_zuweisen() Call Steuerung_ablauf() ' Call Sprungadresse_ermitteln() Call Zeit_in_text() Call Zeit_in_rotorposition() Call Text_array_loeschen() Call Text_in_zeichen() Call Zeichen_aus_tabelle() Call Anzeige_display() Call Darstellung_zeugs() Loop 'Until Flag_rotor_dreht = 0 And Flag_rotor_langsam = 0 Goto Beginn End '## End Hauptprogramm ######################################################### '****************************************************************************** ' Interruptroutinen '****************************************************************************** '------------------------------------------------------------------------------ ' Interrupt0 bei fallender Flanke = Hall-Sensor ' Routine wird nach jeder Umdrehung des Rotor aufgerufen, wenn dabei timer1 ' nicht uebergelaufen war, wird die zeitbasis fuer die anzeigesteuerung ' berechnet '------------------------------------------------------------------------------ Interrupt_hall: If Count_ovf1 < 2 Then Reset Flag_rotor_langsam 'rotor dreht langsam Else Rotor_stellung = 999 'rotor steht End If Zeit_pro_umdrehung = Timer1 Timer1 = 0 If Flag_rotor_langsam = 0 And Flag_rotor_dreht = 1 Then 'nur wenn Rotor dreht und schnell laeuft Zeit_pro_darstellung = Zeit_pro_umdrehung / Anzahl_rotorstellungen Load Timer0 , Zeit_pro_darstellung Rotor_stellung = 0 'entspricht dem Datensatz der 0° Stellung End If Count_ovf1 = 0 Set Flag_rotor_dreht If Flag_motor_aus = 1 Then Rotor_stellung = 999 Return '------------------------------------------------------------------------------ ' Interrupt Timer1 - 16 bit ' Routine wird bei jedem Ueberlauf von timer1 (= 256 ms) während Motorhochlauf/ ' und -auslauf ausgefuehrt, dann wird die Rotor_stellung = 0 gesetz, d.h. keine ' Anzeige mehr '------------------------------------------------------------------------------ Tim1_isr: Incr Count_ovf1 Set Flag_rotor_langsam 'immer wenn overflow erfolgt -> rotor noch langsam If Flag_rotor_dreht = 1 Then Reset Flag_rotor_dreht End If If Count_ovf1 = 100 Then Reset Flag_motor_aus Return '------------------------------------------------------------------------------ ' Interrupt Timer0 - 8 bit ' Routine wird ausgeführt wenn timer0 ueberlauft (nachdem er mit der Variablen ' Zeit_pro_darstellung geladen wurde. Überlauf erfolgt nach ca. 1 Grad des Rotors ' Wenn Motor seine Drehzahl erreicht hat (count_ovf1 = 0) dann dann soll die ' Rotor_stellung hochgezaehlt und der Timer neu geladen werden '------------------------------------------------------------------------------ Tim0_isr: If Flag_rotor_langsam = 0 And Flag_rotor_dreht = 1 Then 'nur wenn Rotor dreht und schnell laeuft Load Timer0 , Zeit_pro_darstellung Incr Rotor_stellung 'und bei naechstem hall-sensor interrupt wieder auf 1 gesetzt If Rotor_stellung = Anzahl_rotorstellungen Then Decr Rotor_stellung 'wenn rotor_stellung vor hall-interrupt 'auf 359 stellungen gefahren ist bleibt sie hier End If If Flag_motor_aus = 1 Then Rotor_stellung = 999 Return '------------------------------------------------------------------------------ ' Interrupt Timer2 - 8 bit ' Routine wird alle 16 ms ausgeführt, daraus erzeugung des sekundentaktes ' und der eigenen zeit '------------------------------------------------------------------------------ Tim2_isr: Incr Count_ovf2 Timer2 = 0 If Count_ovf2 = 61 Then ' 61 x 16 ms = 1 sec Count_ovf2 = 0 Incr Sekunde Incr Var_sekunde Set Flag_1_sekunde If Sekunde = 60 Then Sekunde = 0 Incr Minute Set Flag_1_minute End If If Minute = 60 Then Minute = 0 Incr Stunde End If If Stunde = 24 Then Stunde = 0 Incr Tag End If End If Return '****************************************************************************** ' Subroutinen '****************************************************************************** '------------------------------------------------------------------------------ ' Initialisierung nach Reset '------------------------------------------------------------------------------ Sub Init_variablen() Reset Flag_array_loeschen 'Variablen fuer Textkonvertierung Reset Flag_text_umwandeln Sprungadresse_zeichen = 0 Count_ovf1 = 0 ' Timer0 = 0 Timer1 = 0 Var_sekunde = 0 Sekunde = 0 Minute = 0 Stunde = 0 Rotor_stellung = 999 'anzeige deaktiviert, blinkender sekundenpunkt End Sub '------------------------------------------------------------------------------ ' Serielle Variablen initialisieren ' Routine wird zu beginn mit der initialisierung und nach jedem seriellen ' empfang ausgeführt '------------------------------------------------------------------------------ Sub Init_seriell() Reset Flag_seriell_empfangen 'Flags ruecksetzen Zaehler_bytes_erhalten = 1 'Zaehler ruecksetzen Zaehler_datenpaket = 0 'erstes datenbyte = initialisierungsbyte Ser_inbyte(1) = 0 Ser_inbyte(2) = 0 Ser_inbyte(3) = 0 End Sub '------------------------------------------------------------------------------ ' Serielles Byte empfangen und prüfen ' routine wird ausgeführt wenn im seriellen speicher ein byte empfangen wurde ' ein gueltiges byte zur weiteren auswertung wird erst nach drei aufeinanderfol- ' genden bytes generiert '------------------------------------------------------------------------------ Sub Serielle_daten_empfangen() If Ischarwaiting() = 1 Then 'Byte im Buffer? Ser_inbyte(zaehler_bytes_erhalten) = Inkey() 'Byte in Variable einlesen If Zaehler_bytes_erhalten = 3 Then Zaehler_bytes_erhalten = 1 '3 bytes empfangen? zaehler fuer zu empfangende bytes rücksetzen If Ser_inbyte(1) <> Ser_inbyte(2) Then 'min 2 von drei bytes müssen identisch sein If Ser_inbyte(1) <> Ser_inbyte(3) Then 'sonst wird der befehl nicht angenommen If Ser_inbyte(2) <> Ser_inbyte(3) Then Ser_inbyte(1) = 0 'keine übereinstimmung der empfangenen bytes Else Ser_inbyte(1) = Ser_inbyte(2) End If End If End If 'in Datenbyte(1) steht der "richtige" code Set Flag_seriell_empfangen Else Incr Zaehler_bytes_erhalten End If End If End Sub '------------------------------------------------------------------------------ ' Auswertung der seriellen Befehle ' routine wird ausgeführt wenn das entsprechende flag nach empfang eines bytes ' gesetzt wurde. ueber den wert der variablen serinbyte und befehl wird gesteuert ' wie das empfangene byte zugeordnet wird. '------------------------------------------------------------------------------ Sub Serielle_daten_zuweisen() If Flag_seriell_empfangen = 1 Then 'serielle daten wurden empfangen aber noch nicht 'verarbeitet If Befehl = Daten_uhr Then Select Case Zaehler_datenpaket 'welches byte aus dem datensatz wurde empfangen Case 0 : Minute = Ser_inbyte(1) '_min Case 1 : Stunde = Ser_inbyte(1) '_hour Case 2 : Tag = Ser_inbyte(1) '_day Case 3 : Monat = Ser_inbyte(1) '_month Case 4 : Jahr = Ser_inbyte(1) '_year Case 5 : Wochentag = Ser_inbyte(1) '_dayofweek = letztes byte Befehl = 0 Set Flag_1_minute Set Flag_uhr_aktuell End Select Reset Flag_seriell_empfangen 'rücksetzen der routine Zaehler_bytes_erhalten = 1 'Zaehler ruecksetzen Incr Zaehler_datenpaket 'hochzählen der nummer des bytes aus dem datensatz Ser_inbyte(1) = 0 'damit folgende abfragen nicht stattfinden End If Select Case Ser_inbyte(1) Case Programm_zurueck : If Programm > &H0F Then 'statische anzeige Modus = Programm Programm = Programm_old End If If Programm > 1 And Programm < &H0F Then Decr Programm Else Programm = Programm_x End If Case Programm_vor : If Programm > &H0F Then Modus = Programm Programm = Programm_old End If If Programm < Programm_x Then Incr Programm Else Programm = Programm_1 End If Case Daten_uhr : Befehl = Daten_uhr Reset Flag_seriell_empfangen 'somit is wieder seriell empfang aktiv ... für uhr daten Zaehler_bytes_erhalten = 1 'Zaehler ruecksetzen Zaehler_datenpaket = 0 'erstes datenbyte fuer daten = minute Case Datensatz_vor : Befehl = Datensatz_vor Set Flag_sprungadresse_ermitteln Case Datensatz_zurueck : Befehl = Datensatz_zurueck Set Flag_sprungadresse_ermitteln Case Anzeige_grafik : Modus = Anzeige_grafik Case Anzeige_text : Modus = Anzeige_text Case Anzeige_uhr : If Modus = Anzeige_uhr_digital Then Modus = Anzeige_uhr_analog Else Modus = Anzeige_uhr_digital Set Flag_1_minute End If Case Motor_an : Reset Flag_motor_aus Case Motor_aus : Set Flag_motor_aus End Select If Ser_inbyte(1) = Anzeige_grafik Or Ser_inbyte(1) = Anzeige_text Or Ser_inbyte(1) = Anzeige_uhr Then If Programm < &H0F Then Programm_old = Programm 'nur wenn programm nicht bereits im statischen modus ist Programm = Modus '= &H11, &H12, &H15, &H16 Var_sekunde = 0 Count_ovf2 = 0 Set Flag_anzeige_programm Reset Flag_intro_sequenz End If If Ser_inbyte(1) = Programm_vor Or Ser_inbyte(1) = Programm_zurueck Then Var_sekunde = 0 Count_ovf2 = 0 Set Flag_anzeige_programm Reset Flag_intro_sequenz End If If Befehl <> Daten_uhr Then 'immer wenn nicht daten_uhr Call Init_seriell End If End If End Sub '------------------------------------------------------------------------------ ' ermittlung einer neuen sprungadresse für grafiken, die dann auch sofort zur ' darstellung verwendet wird (entspr. rotorstellung) und laden von text_oben ' und _unten von der neuen sprungadresse fuer texte ' beide sprungadressen werden in abhängigkeit der befehle datensatz_vor und ' _zuruec und der variablen zaehler_grafik und zaehler_text ermittelt '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ ' Steuerung der Programmablaeufe '------------------------------------------------------------------------------ Sub Steuerung_ablauf() If Rotor_stellung <> 999 Then If Flag_anzeige_programm = 1 Then Select Case Var_sekunde Case 0 : Modus = Anzeige_text Text_oben = "Programm " + Str(programm) 'text fuer regulaeren programmmodus 1, 2,..., x Select Case Programm Case Anzeige_grafik : Text_oben = "Grafik" 'text wenn kein programmmodus sondern statische Case Anzeige_text : Text_oben = "Text" 'anzeige von grafik, text und uhr Case Anzeige_uhr_analog : Text_oben = "Uhr" Case Anzeige_uhr_digital : Text_oben = "Uhr" End Select Text_unten = " " Set Flag_array_loeschen 'initialisierung der umwandlungsvariablen Zaehler_gross = 0 Reset Flag_text_umwandeln Sprungadresse_zeichen = 0 Incr Var_sekunde Case 2 : Var_sekunde = 0 Count_ovf2 = 0 Reset Flag_anzeige_programm If Programm > &H0F Then Modus = Programm Set Flag_sprungadresse_ermitteln End If End Select End If If Programm = Programm_1 And Flag_anzeige_programm = 0 Then ' programm 3, 2, 1 If Var_sekunde < 249 Then Var_sekunde = 249 Modus = Anzeige_grafik Select Case Var_sekunde Case 249 : Zaehler_grafik = 0 'entspricht "... 3" Set Flag_sprungadresse_ermitteln Case 252 : Zaehler_grafik = 1 'entspricht "... 2" Set Flag_sprungadresse_ermitteln Case 254 : Zaehler_grafik = 2 'entspricht "... 1" Set Flag_sprungadresse_ermitteln Case 255 : If Flag_intro_sequenz = 1 Then Programm = Programm_2 'Wechsel des Programm-Modus End Select End If If Programm = Programm_2 And Flag_anzeige_programm = 0 Then '= programm moccafee Select Case Var_sekunde Case 0 : Modus = Anzeige_grafik Zaehler_grafik = 0 '= colibri Set Flag_sprungadresse_ermitteln Case 9 : Modus = Anzeige_text Zaehler_text = 0 '= moccafe, im herzen heilbronns Set Flag_sprungadresse_ermitteln Incr Var_sekunde Case 16 : Modus = Anzeige_grafik Zaehler_grafik = 4 '= herz Set Flag_sprungadresse_ermitteln Case 23 : Modus = Anzeige_grafik Zaehler_grafik = 1 '= colibri im herz Set Flag_sprungadresse_ermitteln Case 32 : Modus = Anzeige_text Zaehler_text = 1 '= moccafe, nur echt ... Set Flag_sprungadresse_ermitteln Incr Var_sekunde Case 39 : Modus = Anzeige_grafik Zaehler_grafik = 2 '= tasse Set Flag_sprungadresse_ermitteln Case 48 : Modus = Anzeige_grafik Zaehler_grafik = 3 '= buddha Set Flag_sprungadresse_ermitteln Case 57 : Modus = Anzeige_text Zaehler_text = 2 '= moccafe, kaffee und mehr Set Flag_sprungadresse_ermitteln Incr Var_sekunde Case 64 : Modus = Anzeige_uhr_analog 'zeit in analog Set Flag_sprungadresse_ermitteln Case 71 : If Flag_uhr_aktuell = 1 Then 'zeit in digital Modus = Anzeige_uhr_digital Set Flag_1_minute Var_sekunde = 248 Else Var_sekunde = 255 End If If Flag_intro_sequenz = 1 Then Programm = Programm_3 End Select End If If Programm = Programm_3 And Flag_anzeige_programm = 0 Then 'programm mocolock Select Case Var_sekunde Case 0 : Modus = Anzeige_text Zaehler_text = Pos_texte_mocolock '= mocolock, die andere leuchte Set Flag_sprungadresse_ermitteln Incr Var_sekunde Case 7 : Modus = Anzeige_grafik Zaehler_grafik = 8 '= mars Set Flag_sprungadresse_ermitteln Case 16 : Modus = Anzeige_text Zaehler_text = Pos_texte_mocolock + 2 '= mocolock, mit photos Set Flag_sprungadresse_ermitteln Incr Var_sekunde Case 23 : Modus = Anzeige_grafik Zaehler_grafik = 5 '= schaf Set Flag_sprungadresse_ermitteln Case 32 : Modus = Anzeige_grafik Zaehler_grafik = 6 '= spinne Set Flag_sprungadresse_ermitteln Case 41 : Modus = Anzeige_text Zaehler_text = Pos_texte_mocolock + 1 '= mocolock, ... mit uhr Set Flag_sprungadresse_ermitteln Incr Var_sekunde Case 48 : Modus = Anzeige_uhr_analog 'zei in analog Set Flag_sprungadresse_ermitteln Case 55 : If Flag_uhr_aktuell = 1 Then 'zeit in digital Modus = Anzeige_uhr_digital Set Flag_1_minute Else Var_sekunde = 62 End If Case 62 : Modus = Anzeige_text Zaehler_text = Pos_texte_mocolock + 3 '= made by Set Flag_sprungadresse_ermitteln Incr Var_sekunde Case 69 : Modus = Anzeige_grafik Zaehler_grafik = 9 '= creator Set Flag_sprungadresse_ermitteln Var_sekunde = 248 If Flag_intro_sequenz = 1 Then Programm = Programm_2 Reset Flag_intro_sequenz End If End Select End If If Programm = Programm_x And Flag_anzeige_programm = 0 Then '= programm grafiken Select Case Var_sekunde Case 0 : Modus = Anzeige_grafik Zaehler_grafik = 5 '= schaf Set Flag_sprungadresse_ermitteln Case 9 : Modus = Anzeige_grafik Zaehler_grafik = 3 '= buddha Set Flag_sprungadresse_ermitteln Case 18 : Modus = Anzeige_grafik Zaehler_grafik = 4 '= herz Set Flag_sprungadresse_ermitteln Case 27 : Modus = Anzeige_uhr_analog 'zeit in analog Set Flag_sprungadresse_ermitteln Case 36 : If Flag_uhr_aktuell = 1 Then 'zeit in digital Modus = Anzeige_uhr_digital Set Flag_1_minute Else Var_sekunde = 45 End If Case 45 : Modus = Anzeige_grafik Zaehler_grafik = 0 '= colibri Set Flag_sprungadresse_ermitteln Case 54 : Modus = Anzeige_grafik Zaehler_grafik = 1 '= colibri im herz Set Flag_sprungadresse_ermitteln Case 63 : Modus = Anzeige_grafik Zaehler_grafik = 2 '= tasse Set Flag_sprungadresse_ermitteln Case 70 : Modus = Anzeige_grafik Zaehler_grafik = 6 '= spinne Set Flag_sprungadresse_ermitteln Var_sekunde = 247 End Select End If End If End Sub '------------------------------------------------------------------------------ ' Darstellung von Grafik bzw. Text '------------------------------------------------------------------------------ Sub Anzeige_display() If Rotor_stellung = 999 Then Daten_zu_latch(1) = 0 Daten_zu_latch(2) = 0 Daten_zu_latch(3) = 0 If Flag_1_sekunde = 1 Then Reset Flag_1_sekunde If Flag_sec_blinken = 0 Then Set Flag_sec_blinken Daten_zu_latch(4) = &B10000000 ' blinkender Sekundenpunkt Else Reset Flag_sec_blinken Daten_zu_latch(4) = &B00000000 End If End If Else 'If Rotor_stellung < Anzahl_rotorstellungen Then 'gültigkeitsbereich Select Case Modus Case Anzeige_grafik: Sprungadresse_relativ = Rotor_stellung * 4 ' LED_muster im datensatz entsprechend der rotorposition Sprungadresse_absolut = Sprungadresse_grafik + Sprungadresse_relativ 'mal 4 da immer 4 bytes geladen und somit 'zeiger um 4 weitergesetzt werden muss Daten_zu_latch(4) = Cpeek(sprungadresse_absolut) 'je ein datenbyte laden Incr Sprungadresse_absolut Daten_zu_latch(3) = Cpeek(sprungadresse_absolut) Incr Sprungadresse_absolut Daten_zu_latch(2) = Cpeek(sprungadresse_absolut) Incr Sprungadresse_absolut Daten_zu_latch(1) = Cpeek(sprungadresse_absolut) Incr Sprungadresse_absolut Case Anzeige_uhr_analog: Sprungadresse_relativ = Rotor_stellung * 4 Sprungadresse_absolut = Sprungadresse_grafik + Sprungadresse_relativ Sprungadresse_absolut = Sprungadresse_absolut + 3 'nur aeusseren ring laden! Daten_zu_latch(1) = Cpeek(sprungadresse_absolut) Incr Sprungadresse_absolut Daten_zu_latch(4) = &B00000000 Daten_zu_latch(3) = &B00000000 Daten_zu_latch(2) = &B00000000 If Rotor_stellung = Position_stunde Then Daten_zu_latch(4) = &B11111111 Daten_zu_latch(3) = &B11111000 Daten_zu_latch(2) = &B00000000 End If If Rotor_stellung = Position_minute Then Daten_zu_latch(4) = &B11111111 Daten_zu_latch(3) = &B11111111 Daten_zu_latch(2) = &B11111000 End If If Rotor_stellung = Position_sekunde Then Daten_zu_latch(4) = &B11111111 Daten_zu_latch(3) = &B11111111 Daten_zu_latch(2) = &B11111111 End If Case Anzeige_uhr_digital : Daten_zu_latch(3) = 0 If Flag_1_sekunde = 1 Then Reset Flag_1_sekunde If Flag_sec_blinken = 0 Then Set Flag_sec_blinken Daten_zu_latch(4) = &B10000000 ' blinkender Sekundenring Else Reset Flag_sec_blinken Daten_zu_latch(4) = &B00000000 End If End If Daten_zu_latch(2) = Text_daten(rotor_stellung + 1) 'text-daten muessen wegen aufteilung zwei mal Daten_zu_latch(1) = Text_daten(rotor_stellung + 1) 'geladen werden For Zaehler_klein = 1 To 5 'Anzeige von Text erfolgt ueber zwei Schieberegister Shift Daten_zu_latch(2) , Right 'ueber Nr. 2 wird Bit 1,2,3 angezeigt Next Zaehler_klein For Zaehler_klein = 1 To 3 'Anzeige von Text erfolgt ueber zwei Schieberegister Shift Daten_zu_latch(1) , Left 'ueber Nr. 1 wird Bit 8,7,6,5,4 angezeigt Next Zaehler_klein Case Anzeige_text: Daten_zu_latch(4) = 0 Daten_zu_latch(3) = 0 Daten_zu_latch(2) = Text_daten(rotor_stellung + 1) 'text-daten werden wegen folgender aufteilung zwei mal Daten_zu_latch(1) = Text_daten(rotor_stellung + 1) 'geladen For Zaehler_klein = 1 To 5 'Anzeige von Text erfolgt ueber zwei Schieberegister Shift Daten_zu_latch(2) , Right 'ueber Nr. 2 wird Bit 1,2,3 angezeigt Next Zaehler_klein For Zaehler_klein = 1 To 3 'Anzeige von Text erfolgt ueber zwei Schieberegister Shift Daten_zu_latch(1) , Left 'ueber Nr. 1 wird Bit 8,7,6,5,4 angezeigt Next Zaehler_klein End Select End If Spiout Daten_zu_latch(1) , 4 End Sub '------------------------------------------------------------------------------ ' Loeschen des Daten-Text-Arrays zur Anzeige ' routine wird durchgeführt wenn ein neuer text zur umwandlung bereit steht. ' das array wird feldweise bei jedem durchlauf um ein feld gelöscht, wenn das ' gesamte array gelöscht ist, wird die initialisierung zur umwandlung des textes ' durchgefuehrt. '------------------------------------------------------------------------------ Sub Text_array_loeschen() If Flag_array_loeschen = 1 Then 'flag wird gesetzt wenn neuer text umgewandelt werden soll Incr Zaehler_gross '1 bis 360 Text_daten(zaehler_gross) = 0 If Zaehler_gross = Anzahl_rotorstellungen Then 'array ist initialisiert d.h alles 0 Reset Flag_array_loeschen Set Flag_text_umwandeln 'text laut zeichentabelle in darstellbares muster umwandeln Reset Flag_text_nr Laenge_text = Len(text_oben) 'Ermittlung der textlänge in zeichen Datensatz_position = Laenge_text * 7 'Ermittlung der textlänge in rotor-positionen Datensatz_position = Datensatz_position / 2 '5 Positionen pro Buchstabe plus 2 Leerpositionen = 7 Positionen Datensatz_position = 270 - Datensatz_position '1-te Rotor-Position bei Darstellung oben Zeichen_in_text = 0 End If End If End Sub '------------------------------------------------------------------------------ ' Steuerung zur Erstellung des Daten-Text-Arrays ' routine wird bei jedem durchlauf durchgeführt wenn flag zur umwandlung gesetzt ' wurde. bei jedem durchlauf wird ein zeichen aus dem entsprechenden text (oben ' oder unten umgewandelt bzw. zur umwandlung in der folgenden routine freigegeben ' wenn ein text umgewandelt wurde, dann wird auf den naechsten umgeschaltet. '------------------------------------------------------------------------------ Sub Text_in_zeichen() If Flag_text_umwandeln = 1 Then 'flag wird gesetzt wenn neuer text umgewandelt werden soll If Flag_text_nr = 0 And Zeichen_in_text = Laenge_text Then 'erster text ist umgewandelt Set Flag_text_nr Laenge_text = Len(text_unten) Datensatz_position = Laenge_text * 7 'Ermittlung der textlänge in rotor-positionen Datensatz_position = Datensatz_position / 2 '5 Positionen pro Buchstabe plus 2 Leerpositionen = 7 Positionen Datensatz_position = 90 + Datensatz_position '1-te Rotor-Position bei Darstellung unten Zeichen_in_text = 0 End If '= 90° + x° wegen Drehrichtung im Uhrzeigersinn Incr Zeichen_in_text 'zeichen = 1 ... laenge_text If Flag_text_nr = 0 Then Zeichen = Mid(text_oben , Zeichen_in_text , 1) 'Zeichen sequentiell aus dem text lösen Else Zeichen = Mid(text_unten , Zeichen_in_text , 1) 'Zeichen sequentiell aus dem text lösen End If Asciwert = Asc(zeichen) 'ASCII-Wert des Zeichens ermitteln If Asciwert = 32 Then 'Zeichen = Leerzeichen, dann 7 Positionen nichts For Zaehler_klein = 1 To 7 Text_daten(datensatz_position) = 0 If Flag_text_nr = 0 Then 'in Abhängigkeit der Text-Position (oben/unten) Incr Datensatz_position 'wenn oben, dann Tabellenposition hochzaehlen Else Decr Datensatz_position 'wenn unten, dann Tabellenposition runterzaehlen End If Next Zaehler_klein End If If Asciwert = 58 Then 'Zeichen = doppelpunkt, dann muster 2 mal laden For Zaehler_klein = 1 To 2 Text_daten(datensatz_position) = &B00100100 If Flag_text_nr = 0 Then 'Tabellenposition hoch-/runterzaehlen Incr Datensatz_position Else Decr Datensatz_position End If Next Zaehler_klein End If If Asciwert = 46 Then 'Zeichen = punkt , Dann Muster 2 mal Laden For Zaehler_klein = 1 To 2 If Flag_text_nr = 0 Then Text_daten(datensatz_position) = &B10000000 Incr Datensatz_position Else Text_daten(datensatz_position) = &B00000001 Decr Datensatz_position End If Next Zaehler_klein End If Sprungadresse_zeichen = 0 Select Case Asciwert Case 48 To 57 : Sprungadresse_zeichen = Loadlabel(123) Sprungadresse_relativ = Asciwert - 48 Case 65 To 90 : Sprungadresse_zeichen = Loadlabel(abc_gross) ' Programmadresse für abc_gross in Datenadresse laden Sprungadresse_relativ = Asciwert - 65 'position im jeweiligen datensatz A-Z, a-z oder 123 Case 97 To 122 : Sprungadresse_zeichen = Loadlabel(abc_klein) Sprungadresse_relativ = Asciwert - 97 End Select If Flag_text_nr = 1 And Zeichen_in_text = Laenge_text Then 'zweiter text text ist umgewandelt Reset Flag_text_umwandeln End If End If End Sub '------------------------------------------------------------------------------ ' Uebernahme von Zeichen aus Tabelle ' routine wird ausgeführt wenn eine sprung-adresse eines gueltigen asciwertes in ' die variable geladen worden ist. dieses zeichen wird dann in der routine in ' ein entsprechendes led-muster (laut tabelle) umgewandelt und an der derzeit ' aktuellen position in das daten-text-array geschrieben '------------------------------------------------------------------------------ Sub Zeichen_aus_tabelle() If Sprungadresse_zeichen <> 0 Then Sprungadresse_relativ = Sprungadresse_relativ * 5 ' wegen 5 bytes pro zeichen Sprungadresse_zeichen = Sprungadresse_zeichen + Sprungadresse_relativ ' If Flag_text_nr = 1 Then For Zaehler_klein = 1 To 5 'umwandlung des untern textes: zeichen besteht aus 5 rotorpositionen Text_daten(datensatz_position) = Cpeek(sprungadresse_zeichen) 'hole Daten aus datenbereich an der pos. sprungadresse Daten_zu_latch(1) = Not Text_daten(datensatz_position) 'invertiere ueber hilfsvariable fuer richtige darstellung Text_daten(datensatz_position) = Daten_zu_latch(1) Incr Sprungadresse_zeichen 'sprungadresse hochzaehlen Decr Datensatz_position 'da text unten, werden die zeichen in der tabelle absteigend gespeicher If Datensatz_position = 0 Then Datensatz_position = Anzahl_rotorstellungen 'wenn letzte position erreicht dann hoechste Next Zaehler_klein ' Else For Zaehler_klein = 1 To 5 'umwandlung des oberen textes: zeichen besteht aus 5 rotorpositionen Text_daten(datensatz_position) = Cpeek(sprungadresse_zeichen) 'hole Daten aus datenbereich an der pos. sprungadresse Daten_zu_latch(1) = Not Text_daten(datensatz_position) 'invertiere fuer richtige darstellung Daten_zu_latch(2) = &B00000001 'ab hier folgt "spiegelung" des bytes für darstellung oben Daten_zu_latch(4) = &B00000000 'hilfsvariablen For Zaehler_gross = 1 To 8 '8 mal das ganze wegen 8 bits Daten_zu_latch(3) = Daten_zu_latch(1) And Daten_zu_latch(2) 'ueber hilfsvariable(2) wird BITx "bewertet" Select Case Daten_zu_latch(3) Case &B10000000 : Daten_zu_latch(3) = &B00000001 'wenn BIT8 = 1 dann wird BIT2 = 1 Case &B01000000 : Daten_zu_latch(3) = &B00000010 'wenn BIT7 = 1 dann wird BIT3 = 1 Case &B00100000 : Daten_zu_latch(3) = &B00000100 'usw. Case &B00010000 : Daten_zu_latch(3) = &B00001000 Case &B00001000 : Daten_zu_latch(3) = &B00010000 Case &B00000100 : Daten_zu_latch(3) = &B00100000 Case &B00000010 : Daten_zu_latch(3) = &B01000000 Case &B00000001 : Daten_zu_latch(3) = &B10000000 End Select Daten_zu_latch(4) = Daten_zu_latch(4) Or Daten_zu_latch(3) 'Hilfsvar(4) wird ueber 8 schleifen zum Spiegle von (1) Shift Daten_zu_latch(2) , Left 'wird somit 2, 4, 8, 16, 32, 64, 128 Next Zaehler_gross Text_daten(datensatz_position) = Daten_zu_latch(4) Incr Sprungadresse_zeichen If Datensatz_position = Anzahl_rotorstellungen Then Datensatz_position = 0 'hier 0 weil 1 weiter hochzaehlung Incr Datensatz_position Next Zaehler_klein End If If Flag_text_nr = 1 Then Decr Datensatz_position Text_daten(datensatz_position) = 0 'zwei Leerpositionen Decr Datensatz_position Text_daten(datensatz_position) = 0 Else Incr Datensatz_position Text_daten(datensatz_position) = 0 'zwei Leerpositionen Incr Datensatz_position Text_daten(datensatz_position) = 0 End If Sprungadresse_zeichen = 0 End If End Sub '------------------------------------------------------------------------------ ' Umwandlung Uhrzeit und Datum in Text ' routine wird im modus "digitaluhr" jede minute durchgeführt und wenn die ' uhrzeit einmal über dcf aktualisiert wurde, entsprechend in text umgewandelt '------------------------------------------------------------------------------ Sub Zeit_in_text() If Modus = Anzeige_uhr_digital Then If Flag_1_minute = 1 Then 'jede minute wird anzeige aktualisiert Reset Flag_1_minute If Flag_uhr_aktuell = 1 Then 'zeit wurde über dcf aktualisiert, sonst ist jahr = 0 'und soll nicht umgewandelt werden If Stunde < 10 Then Zeit_string = "0" + Str(stunde) Else Zeit_string = Str(stunde) End If If Minute < 10 Then Zeit_string = Zeit_string + " : 0" + Str(minute) Else Zeit_string = Zeit_string + " : " + Str(minute) End If If Tag < 10 Then Datum_string = "0" + Str(tag) Else Datum_string = Str(tag) End If If Monat < 10 Then Datum_string = Datum_string + " . 0" + Str(monat) Else Datum_string = Datum_string + " . " + Str(monat) End If If Jahr < 10 Then Datum_string = Datum_string + " . 0" + Str(jahr) Else Datum_string = Datum_string + " . " + Str(jahr) End If Wochentag_string = Lookupstr(wochentag , Wochentage) Datum_string = Wochentag_string + " " + Datum_string End If Text_oben = Zeit_string Text_unten = Datum_string Set Flag_array_loeschen 'initialisierung der umwandlungsvariablen Zaehler_gross = 0 Reset Flag_text_umwandeln Sprungadresse_zeichen = 0 End If End If End Sub '------------------------------------------------------------------------------ ' Umwandlung Uhrzeit in Rotorposition ' routine wird im modus "analoguhr" bei jedem durchlauf durchgeführt und die ' entsprechenden rotorpositionen zur darstellung der uhrzeit errechnet '------------------------------------------------------------------------------ Sub Zeit_in_rotorposition() If Modus = Anzeige_uhr_analog Then If Stunde > 12 Then Position_stunde = Stunde - 12 Position_stunde = Position_stunde * 360 Else Position_stunde = Stunde * 360 End If If Stunde = 0 Then Position_stunde = 12 * 360 Position_stunde = Position_stunde / 12 If Stunde > 0 And Stunde < 3 Then Position_stunde = Position_stunde + 270 Else Position_stunde = Position_stunde - 90 End If Position_minute = Minute * 360 Position_minute = Position_minute / 60 If Minute < 15 Then Position_minute = Position_minute + 270 Else Position_minute = Position_minute - 90 End If Position_sekunde = Sekunde * 360 Position_sekunde = Position_sekunde / 60 If Sekunde < 15 Then Position_sekunde = Position_sekunde + 270 Else Position_sekunde = Position_sekunde - 90 End If End If End Sub '------------------------------------------------------------------------------ ' '------------------------------------------------------------------------------ Sub Darstellung_zeugs() 'Anzeige von Informationen ueber LED oder Print-Befehl waehrend Entwicklung End Sub '############################################################################## '------------------------------------------------------------------------------ ' Definition von globalen Konstantenfeldern '------------------------------------------------------------------------------ ''---------------------- Daten für Wochentag -------------------------------- Wochentage: Data " " , "Mo" , "Di" , "Mi" , "Do" , "Fr" , "Sa" , "So" '----------------------- Daten für LED-Muster --------------------------------- ' jede zeile = 4 byte = eine rotorposition ' *** WICHTIG: MSB(bit links) = Innere LED, LSB(bit rechts) = Äussere LED Grafikbereich: '$include "grafiken.bas" Textbereich: '$include "texte.bas" Zeichensatz: $include "zeichensatz.bas" Startsequenz: '$include "intro.bas" '###################################### END ###################################