'-----------------------------------------------------------------------------------------
'Titel                    : HexadezimalUhr
'Name                     : HexadezimalUhr
'Datei                    : FFFUhr.bas
'Autor                    : Arno Schweißinger
'Datum                    : 04.11.2012
'Version                  : 0.03
'Compiler                 : Bascom 1.11.8.7
'MicroController          : 1x AtMega8 1MHz interner Takt
'Hardware                 : 1x Uhrenquarz 32768Hz an TOSC1/2 - Pin 9/10
'                           3x MOS 4094
'                           3x 7Segmentanaeige
'
'                           Pind.0 an Data   alle MOS 4094
'                           Pind.1 an Clock  alle MOS 4094
'                           Pind.2 an Strobe1 IC1 MOS 4094
'                           Pind.3 an Strobe2 IC2 MOS 4094
'                           Pind.4 an Strobe3 IC3 MOS 4094
'
'                           Pinb.1 Lsp für Stundensignal
'                           Taster1 Alias Portd.6  Minuten
'                           Taster2 Alias Portd.7  Stunden
'
'
'
'Stromversorgung:         : 5V
'Besonderes               :
'Letzte Änderung          :V0.01: 04.11.2012
'                          V0.02: 18.11.2012 Datum und Uhrzeit wird jede Stunde EEPROM gespeicher
'                                            und bei einem Neustart aus dem EEPROM gelesen
'                          V0.03  24.11.2012 Änderung in Sub Zeitsichern
'
'-----------------------------------------------------------------------------------------

$regfile = "m8def.dat"
$crystal = 1000000
$hwstack = 32                                               ' default use 32 for the hardware stack
$swstack = 32                                               ' default use 32 for the SW stack
$framesize = 40

'Config Portd = Output
Ddrd = &B00111111                                           ' Pin PD6 PD7 auf Eingang
Portd = &B1100000                                           ' Pin PD6 PD7 Pullup aktivieren
Dat Alias Portd.0                                           ' Datenübertragung an MOS4094
Cl Alias Portd.1                                            ' Clock  Signal an MOS4094
Strobe1 Alias Portd.2                                       ' Strobe Signal U1 MOS4094
Strobe2 Alias Portd.3                                       ' Strobe Signal U2 MOS4094
Strobe3 Alias Portd.4                                       ' Strobe Signal U3 MOS4094
Taster1 Alias Pind.6                                        ' Minuten stellen
Taster2 Alias Pind.7                                        ' Stunden stellen
Soundpin Alias Pinb.1

'configure clock
Config Date = Dmy , Separator = .                           ' ANSI-Format
Config Clock = Soft                                         ' this is how simple it is
Enable Interrupts


Declare Sub Init_prog
Declare Sub Tastatur
Declare Sub Sende4094
Declare Sub Stundensignal
Declare Sub Korrektur
Declare Sub Ausgabe
Declare Sub Ausgabe_stellen
Declare Sub Zahlout
Declare Sub Hexadezimalzeit
Declare Sub Datenkonsistent
Declare Sub Error
Declare Sub Zeitsichern

Const Zeitkorrektur = 0                                     ' plus/minus x Sekunden am Tag, Max 30 Sek je Tag

Dim E_time As Eram String * 8                               ' Zeit im EEPROM
Dim E_date As Eram String * 8
Dim E_temp As String * 8                                    ' Zwischenspeicher  Sub Zeitsichern

Dim Segmente(3) As Byte                                     ' 3 * 8bit für LED, gesendet an 4093
Dim Old_sec As Byte                                         ' Hauptprogramm
Dim I As Byte                                               ' Registerloeschen; Uebertragen;  Zählschleifen
Dim J As Byte                                               ' Registerloeschen; Uebertragen
Dim Korrekturflag As Byte                                   ' Sub Korrektur  einmal am Tag korrigieren
Dim Sekunden As Long                                        ' Sub Dezimalzeit
Dim Temp As Byte                                            ' Zwischenspeicher
                                                             ' Sub Tastatur; Sub Ausgabe_stellen

'-------------------------
'      Hauptprogramm
'-------------------------
'Begin
Call Init_prog
  Do
   If _sec <> Old_sec Then                                  ' Sekundentakt
      Old_sec = _sec
      Call Hexadezimalzeit
      Call Ausgabe                                          ' umrechnen in die Hexadezimalzeit
      Call Stundensignal                                    ' 7Segmentanzeige
      Call Tastatur                                         ' Taster auslesen
      Call Korrektur                                        ' wird einmal am Tag ausgeführt
      Call Zeitsichern                                      ' einmal in der Stunde
   End If
  Loop
End                                                         ' ende Hauptprogramm

'-----------------------------------------------------------------------------------------
Sub Init_prog
  Segmente(1) = Lookup(, Balken)                          ' Balken in der Mitte -Seg7
  Segmente(2) = Lookup(, Balken)                          ' Balken in der Mitte -Seg7
  Segmente(3) = Lookup(, Balken)                          ' Balken in der Mitte -Seg7
  Call Sende4094
  Sound Soundpin , 40 , 40                                  ' Bestätigungston
  Waitms 100                                                ' warte kurz
  Sound Soundpin , 40 , 40                                  ' Bestätigungston
  Time= E_time
  Date= E_date
  Call Datenkonsistent                                      '
End Sub


'-----------------------------------------------------------------------------------------
Sub Datenkonsistent
  If _hour > 23 Then Call Error
  If _min > 59 Then Call Error
  If _sec > 59 Then Call Error
  If _day > 31 Then Call Error
  If _month > 12 Then Call Error
End Sub

'-----------------------------------------------------------------------------------------
Sub Error                                                   ' Neustart
  E_time = "00:00:00"
  E_date = "01.01.00"
  Waitms 500
    $asm
      jmp 0000                                              ' cpu reset
    $end Asm
End Sub

'-----------------------------------------------------------------------------------------
Sub Hexadezimalzeit
   Sekunden = Secofday()                                    ' Vergangene Sekunden des Tages
  ' Umrechnen ins HexaDezimalsystem
   Sekunden = Sekunden * 512                                ' HexaDezimaltag hat FFFF Sekunden 2°16 65536=2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
   '512 = 2°9
   Sekunden = Sekunden / 675                                ' ein Tag hat 86400 Sekunden            86400=2*2*2*2*2*2*2                  *3*3*3  *5*5
   '675 = 3*3*3*5*5
'   Hextime = Hexval(sekunden )                              ' ERROR 42 ????

   Sekunden = Sekunden / 16
   Segmente(1) = Sekunden Mod 16                            ' 1er
   Sekunden = Sekunden / 16
   Segmente(2) = Sekunden Mod 16                            ' 10er
   Sekunden = Sekunden / 16
   Segmente(3) = Sekunden                                   ' 100er
End Sub


'-----------------------------------------------------------------------------------------
Sub Ausgabe
    Segmente(1) = Lookup(segmente(1) , Zahlen)              ' Zahl in Segmente wandeln     0-9
    Segmente(1).= _sec.0                                  ' Dezimalpunkt blinkt im Sekundertakt
    Segmente(2) = Lookup(segmente(2) , Zahlen)
    Segmente(3) = Lookup(segmente(3) , Zahlen)
    Call Sende4094                                          ' Bits an Latch MOS4094 senden
End Sub


'-----------------------------------------------------------------------------------------
Sub Ausgabe_stellen
    Sound Soundpin , 10 , 20                                ' Bestätigungston
    Segmente(2) = Temp / 10                                 ' Zehener Stellen
    Segmente(1) = Temp Mod 10                               ' Einer Stellen
    Segmente(1) = Lookup(segmente(1) , Zahlen)              ' Zahl in Segmente wandeln     0-9
    Segmente(2) = Lookup(segmente(2) , Zahlen)
    Segmente(3) = Lookup(, Balken)
    Call Sende4094                                          ' Bits an Latch MOS4094 senden
    Waitms 400
End Sub


'-----------------------------------------------------------------------------------------
Sub Tastatur
'------------------ Minuten stellen ------------------------
If Taster1 = 0 Then
  _sec = 00                                                 ' Sekunden löschen
  _min = _min + 1
  If _min = 60 Then _min = 0
  Temp = _min
  Call Ausgabe_stellen
  Waitms 500                                                ' 1/2 Sekunde warten
  While Taster1 = 0                                         ' Taster gehalten, dann scheller Vorlauf
    _min = _min + 1
    If _min = 60 Then _min = 0
    Temp = _min
    Call Ausgabe_stellen
  Wend
End If
'------------------ Stunden stellen ------------------------
If Taster2 = 0 Then
  _hour = _hour + 1
  If _hour = 24 Then _hour = 0
  Temp = _hour
  Call Ausgabe_stellen
  Waitms 500                                                ' 1/2 Sekunde warten
  While Taster2 = 0                                         ' scheller Vorlauf
    _hour = _hour + 1
    If _hour = 24 Then _hour = 0
    Temp = _hour
    Call Ausgabe_stellen
  Wend
End If
End Sub


'-----------------------------------------------------------------------------------------
Sub Sende4094
  For J = 2 To 4                                            ' Portd.2 bis Portd.4
    For I = 7 To 0 Step -1
      Dat = Segmente(- 1).i
      Set Cl
      Waitus 10
      Reset Cl                                              ' Clocksignal am 4093 erzeugen
    Next I
    Set Portd.j
    Waitus 100                                              ' 4093 Ausgänge setzen
    Reset Portd.j
  Next J
End Sub


'-----------------------------------------------------------------------------------------
Sub Korrektur                                               ' Zeit Korrektur einmal am Tag, wenn der Quarz etwas abweicht
  If Korrekturflag = 0 Then                                 ' Korrekturbit setzen
    If _sec = 0 Then
     If _min = 0 Then
       If _hour = 23 Then
        Korrekturflag = 1
       End If
     End If
    End If
  End If

  If Korrekturflag = 1 Then                                 ' Korrektur vornehmen
    If _sec = 30 Then
     If _min = 30 Then                                      ' es ist wo weit
       If _hour = 23 Then
        _sec = _sec + Zeitkorrektur
        Korrekturflag = 0
       End If
     End If
    End If
  End If
End Sub


'-----------------------------------------------------------------------------------------
Sub Stundensignal
  If _sec = 0 Then
     If _min = 0 Then
       If _hour > 6 Then                                    ' nachts nicht Pipsen 23-6 Uhr
         If _hour < 23 Then
           Sound Soundpin , 20 , 40
           Sound Soundpin , 40 , 40
         End If
       End If
     End If
  End If
End Sub


'-----------------------------------------------------------------------------------------
Sub Zeitsichern
  If _sec = 30 Then
     If _min = 0 Then
       Wait 1
       E_temp = Time$                                       ' verhindert laden und scheiben beim reset
       E_time = E_temp                                      ' Zeit sichern
       E_temp = Date$
       E_date = E_temp                                      ' einmal in der Stunde
       Sound Soundpin , 40 , 10                             ' Bestätigungston
     End If
  End If
End Sub


'-----------------------------------------------------------------------------------------
Zahlen:
'Segm   gfe_dcba
Data &B0011_1111                                            ' 0
Data &B0000_0110                                            ' 1
Data &B0101_1011                                            ' 2
Data &B0100_1111                                            ' 3
Data &B0110_0110                                            ' 4
Data &B0110_1101                                            ' 5
Data &B0111_1101                                            ' 6
Data &B0000_0111                                            ' 7
Data &B0111_1111                                            ' 8
Data &B0110_1111                                            ' 9
Data &B1111_0111                                            ' A dp
Data &B1111_1100                                            ' B dp
Data &B1011_1001                                            ' C dp
Data &B1101_1110                                            ' D dp
Data &B1111_1001                                            ' E dp
Data &B1111_0001                                            ' F dp


Balken:
Data &B00000000                                             ' 0 alles aus
Data &B00000001                                             ' 1 Seg  1
Data &B00000010                                             ' 2 Seg  2
Data &B00000100                                             ' 3 Seg  3
Data &B00001000                                             ' 4 Seg  4
Data &B00010000                                             ' 5 Seg  5
Data &B00100000                                             ' 6 Seg  6
Data &B01000000                                             ' 7 Seg  7
Data &B10000000                                             ' 8 DezPunkt