'**********************************************************************************
'            Funkuhr mit 60 Sekundenanzeige und LED-Segmente +Datum
'**********************************************************************************
' Ansteuerung  74HC595 und SAA 1064
' Programm für Open Micro
' Progammsprache OC-Basic
' 05.01. 2007  Senderoutine HC 595 Basic Compiler
' Lichtsensor 06.01.07
' 12 Stunden LEDs gedimmt  08.01.2007
' 14.01.2007 Senderoutine SAA auf Maschinencode
' 22.01.2007 Führende Null Stunden entfernt, alle 5 sec Helligkeitreglung
' 27.02.2007 Version wird im Datum abgelegt day month year, neueres datum neuere Version
' 01.03.2007 Helligkeit nur noch 1 x pro Minute
' 22.03.2007 ab 22 uhr bis 8 uhr nur eine Sekunde anzeigen
' 24.04.2007 Pinbelegung
' 16.05.2007 Zeit manuell stellen
' 23.06.2007 Temperaturanzeige Innen
' 14.09.2007 Temperatur Aussen
' 05.11.2007 Datum Temperatur wechsel alle 5 sec. Minuszeichen variabel.
' 08.12.2007 Für Uhr 06
'**********************************************************************************
'
' Nach der Aktivierung wird das DCF77-Signal von den DCF77-Empfangsroutinen
' im Hintergrund, waehrend der normalen Programmausfuehrung, dekodiert und
' die interne Uhr (RTC) der OM gestellt.

' Es muss der invertierte Ausgang des preiswerten DCF77-Empfangsmoduls mit
' der Conrad-Bestellnummer 641138 an PORT[4] angeschlossen werden. Sicher-
' heitshalber sollte ein Pull-Up-Widerstand 10 kOhm zwischen Ausgang und
' +5 Volt geschaltet werden.


'        Die Pinbelegung der
'        Open-Mini (QY4)
'         ______________
'        |              |         P  3 wird bei der Programmübertragung auf 0 V gelegt (Jumper)
'       [  P  3    P  4  ]        P  4 Signal vom DCF Empfänger, Auswertung über Interrupt
'        |              |         P 12 Taster Zeiteinstellung manuell, Stellen
'       [  P 12    P 13  ]        P 13
'        |              |         P 11 Taster Zeiteinstellung manuell, Set
'       [  P 11    P 14  ]        P 14 Strobe 74 HC 595
'        |              |         P  2 PWM für Helligkeitsregelung 74 HC 595
'       [  P  2    P  5  ]        P  5 AD 5 Temperatur innen
'        |              |         P  1 Serielle Schnittstelle, über Jamper AD 1 Temperatur außen
'       [  P  1    P  6  ]        P  6 wird als AD 6 verwendet, Fotowiderstand
'        |              |         P 10 SCL I2C Bus
'       [  P 10    P 15  ]        P 15 Clock 74 HC 595
'        |              |         P  9 SDA I2C Bus
'       [  P  9    P 16  ]        P 16 Daten 74 HC 595
'        |              |
'       [  VSS     VDD   ]         VDD = 4.6 bis 5.5 Volt
'        |_____/  \_____|          Vss = Gnd, Masse
'



' ---------------------------------------------------------------------------

INCLUDE "om.def"              'Definitionen fuer Open-Micro und Open-Mini



define Tasterzeit port[12]
define Tasterset  port[11]
define TempI ad[5]
define TempA ad[1]
define Helligkeit ad[6]         'Fotowiderstand
define Clock    port[15]	' Pin 11 an 74HC595  Takt
define Strobe   port[14]	' Pin 12 an 74HC595  Daten Übernahme
define Daten    port[16]	' Pin 14 an 74HC595  Daten


define data       byte              'Variable für Datenausgabe 595
define databit bit[8] of data       'das höchstwertige Bit von Data

define i          byte        'Variable
define ii         byte

define Digit1      byte       ' Sekundenleds
define Digit2      byte
define Digit3      byte
define Digit4      byte
define DIGIT5      byte
define DIGIT6      byte
define DIGIT7      byte
define DIGIT8      byte
define d1          byte
define d2          byte
define d3          byte
define d4          byte
define d7          byte
define d8          byte

define sek         byte       'Sekunde merken
define hell        byte       'Helligkeit für PWM
define hell1       byte

DEFINE temp        BYTE
define iii         byte	  'Variable
define iicdata     byte


'-------------------------
define Adresse    &B01110000  'Adresse SAA 1064 bei 0V


define BRIGHT  &B00000111    '&H07     0 mA   ' Helligkeit = aus
define BRIGHT1 &B00010111    '&H17     3 mA     +16
define BRIGHT2 &B00100111    '&H27     6 mA     +32
define BRIGHT3 &B00110111    '&H37     9 mA     +48
define BRIGHT4 &B01000111    '&H47    12 mA     +64
define BRIGHT5 &B01010111    '&H57    15 mA     +80
define BRIGHT6 &B01100111    '&H67    18 mA     +96
define BRIGHT7 &B01110111    '&H77    21 mA     +112

' ---------------------------- Hauptprogramm ---------------------------------------
'

' ---------------------------------------------------------------------------
' Die Empfangsroutinen fuer DCF77 einbinden
' ---------------------------------------------------------------------------

INCLUDE "dcf778.iia"

' ---------------------------------------------------------------------------
' Das Hauptprogramm
' ---------------------------------------------------------------------------

 #main
 ' Print Freq2            'Wert des internen Taktgebers auslesen

 'freq2 =  freq2 +1               'Internen Taktgeber trimmen
 'pause 100                       'das ist nur bei großer Gangungenauigkeit der Uhr nötig,
 'print freq2                     'besser mit dem Programm osctrim.exe den Prozessor neu trimmen.
                         ' Auszug aus der Dokumentation:
                         ' Auf der OM läßt sich mit dieser internen Variable der Systemtakt von 3,2 MHz justieren
                         ' FREQ2 entspricht dem Kontroller-Register OSCTRIM auf Adresse $38.
                         ' Mit diesem Register wird die Größe des internen Kondensators verändert,
                         ' der Verwendung im internen Oszillator findet.
                         ' Durch Erhöhen des FREQ2-Werts um eins wird auch die Periodendauer um rund 0,2% erhöht.
                         ' Die Taktfrequenz wird also niedriger. Die interne Uhr geht langsamer.

 UIRTofl = ON              ' Die Assembler Routine aufrufen
 gosub ini
 day =    08                'wird als Versionsnummer interpretiert
 month =  12
 year =   07
 minute = 59
 hour   = 08
 second = 50
  gosub digit_ini
    PWM2_ein                   ' PWM-Routine Port2 einschalten
  hell = 220
    PWM2 hell
    hell = 5

#loop

  if hour = 24 then              'Wenn Mitternacht kein Empfang
   hour = 0
   day = day +1                 'Pech wenn der Monatsletzte
  end if
   if second = sek then loop ' wartet bis eine Sekunde um ist
 sek = second

'--------------------------------------------------------------------------------------
' Sekunden anzeigen
'--------------------------------------------------------------------------------------

if (hour < 8) or (hour > 21)  then
 gosub alle60

 else
   if minute > 30 then
     gosub  vorwaerts
   else
     gosub alle60
   end if
 end if

gosub zeit
'--------------------------------------------------------------------------------------

if (sek mod 5) = 0  then gosub datum  ' Datum
'--------------------------------------------------------------------------------------
 if sek = 30 then             ' nur einmal pro Minute anzeigen
                                ' wenn man alle Sekunde anzeigt ist die Anzeige zu unruhig.
 hell = helligkeit -10             'damit die Anzeige bei Dunkelheit noch leuchtet
     'if hell > 248 then hell = 248  'nicht ganz dunkel

  PWM2 hell                  'für Minuten und Stundenanzeige (Große Anzeige) sowie die 12 StundenLeds

   hell = Helligkeit  / 30       ' für SekundenLeds
     if hell > 6 then hell = 6
  'print  freq2


 end if

 '--------------------------------------------------------------------------------------
 'Zeitkorektur Feineinstellung

  if (sek =40 ) and (minute mod 6 = 0 ) then gosub korrektur  ' bei Störung Funksignal
                                                              ' alle x Minuten eine Sekunde zurück

'--------------------------------------------------------------------------------------


if tasterset = off then goto zeiteinstellen
goto loop
end


' ---------------------------------------------------------------------------

'------------------------------------------------------------------------------------------------------
 'Anzeigen
'------------------------------------------------------------------------------------------------------
 #Zeit
  '--------------------------------------------------------------------------------------
'Minuten und Stunden
'--------------------------------------------------------------------------------------

ii = minute mod 10  : Data = looktab (dec595, ii)
schreiben
 
 temp = 1
   if  (DCF_OK = 0) and (sek mod 5 = 0) then temp = 0
ii =  minute /10    : Data = looktab (dec595, ii)+ temp   ' kein Funksignal dann blinkt der Doppelpunkt
schreiben

ii = hour mod 10    : Data = looktab (dec595, ii)
 schreiben
ii = hour /10
if ii = 0 then   ' Null bei Stundenanzeige unterdrücken
Data = 1
else
Data = looktab (dec595, ii)+1    ' +1 = Helligkeit der 12 Stunden LEDs
end if
schreiben
pulse strobe
return


 #korrektur
 if dcfmerk <> minute then
   second = second -1
   dcfmerk = minute
 end if
 return


#datum
d1 = Digit1          ' wert merken
d2 = Digit2
d3 = Digit3
d4 = Digit4
d7 = Digit7
d8 = Digit8
if (sek = 0)or (sek = 15) or (sek = 30)or (sek = 45)then
  Digit3= month / 10:   DIGIT3 = looktab (decoder, Digit3)
  Digit4= day / 10: DIGIT4 = looktab (decoder, digit4)
  Digit2= day mod 10:   DIGIT2 = looktab (decoder, Digit2) +128
  Digit1= month mod 10:     DIGIT1 = looktab (decoder, digit1) +128
  'Digit6= Year / 10:    DIGIT6 = looktab (decoder, Digit6)
  'Digit5= Year mod 10:  DIGIT5 = looktab (decoder, digit5)
  Digit8= Year / 10:    DIGIT8 = looktab (decoder, Digit8)
  Digit7= Year mod 10:  DIGIT7 = looktab (decoder, digit7)
else
  pullupA=&B00101110

  if(sek = 5) or (sek = 20)or (sek = 35)or (sek = 50) then          'Innentemperatur
    temp = looktab (temptab, TempI -100)
    digit4 = &B01001000  'I innen
   else
    temp = looktab (temptab, TempA -100)     'Justieren -100 = Orginal  -102 = Temperatur um ca. 1 Grad erhöhen
    digit4 = &B01011111  'A außen
  end if

  if temp > 100 then
    temp = temp -100
    Digit2 = &B00000001 '= -   bei Minus Temperaturen
   else
    digit2 = 0  ' nicht anzeigen
  end if

      Digit3 = temp/ 10
     if DIGIT3 >0 then Digit3 = looktab (decoder, Digit3)           'nur anzeigen wenn größer 0
      Digit1=  temp mod 10: DIGIT1 = looktab (decoder, digit1)

     if (Digit2 = &B00000001) and (Digit3 = 0) then                  'Minuszeichen eine Stelle vor
      digit3 = 1
      digit2 = 0
     end if


   digit8 = &B00001111   '=°
   digit7 = &B00110110   '=C
end if

i = 2                                                    'Adresse
ii = 4
hell1 = helligkeit / 40
     on hell1 gosub null, eins,zwei,drei,vier,fuenf,sechs

 sendbuf
 UIRTofl = ON
Digit1 = d1
Digit2 = d2
Digit3 = d3
Digit4 = d4
Digit7 = d7
Digit8 = d8

return

#alle60

temp = second
  gosub anzeigen
  if second = 0 then goto rueck
  return

#rueck

 dbnzctr= 60            ' das gleiche rückwärts
#loop1
   temp = dbnzctr
   gosub anzeigen
dbnz loop1
return

#Anzeigen
   i = temp/ 8
  ii = temp mod 8
  gosub digit_ini
   add ii, 16
    on i gosub  erste, zweite, dritte, vierte, fuenfte, sechste, siebente, achte
    i = 0                                                             'adresse
    ii = 6
    on hell gosub null, eins,zwei,drei,vier,fuenf,sechs

    sendbuf
   return

  #null
   iii = bright7
    return
  #eins
    iii = bright6
      return
  #zwei
   iii = bright5
     return
  #drei
   iii = bright4
     return
  #vier
   iii = bright3
     return
  #fuenf
   iii = bright2
     return
  #sechs
   iii = bright1
     return


  '--------------------------------------------------------------------------------------
  'Sekundenleds alle 60 anschalten, danach alle ausschalten.
  '--------------------------------------------------------------------------------------

 #Vorwaerts
   i = sek / 8
  ii = sek mod 8
  if minute mod 2 = 1 then add ii, 8

 on i gosub  erste, zweite, dritte, vierte, fuenfte, sechste, siebente, achte
  i = 0
  ii = 6
      on hell gosub null, eins,zwei,drei,vier,fuenf,sechs


   sendbuf
  return


' ----------------------------- Initialisierung--------------------------------------
#ini
Clock =    off				'pin 11  (shift Register clock input)
Strobe=    off				'pin 12  (Daten Übernahme)
Daten =    off				'pin 14  (serieller Daten input)
data = 0
 schreiben
data = 0
schreiben
data = 0
 schreiben
data = 0
 schreiben
pulse strobe

Return

' ----------------------------- Ausgabe--------------------------------------


procedure schreiben compile

for temp = 1 to 8
daten = databit
pulse clock
data = data shl 1
next

return
end procedure
'--------------------------------- Sekundenanzeige---------------------------------

'--------------------------------------------------------
'----    TREIBER LED-DISPLAY MIT IIC-BUS SAA1064
'--------------------------------------------------------

#erste
          Digit1 = looktab (reihe,ii)
  Return

#zweite
     Digit2 = looktab (reihe,ii)
  Return

#dritte
     Digit3 = looktab (reihe,ii)
  Return

#vierte

      Digit4 = looktab (reihe,ii)
  Return
  
  #fuenfte
          Digit5 = looktab (reihe,ii)
  Return

#sechste
     Digit6 = looktab (reihe,ii)
  Return

#siebente
     Digit7 = looktab (reihe,ii)
  Return

#achte
     Digit8 = looktab (reihe,ii)
  Return

   #digit_ini
  Digit1 = 0
  Digit2 = 0
  Digit3 = 0
  Digit4 = 0
  Digit5 = 0
  Digit6 = 0
  Digit7 = 0
  Digit8 = 0
   Return




 '------------------------------------------------------
'IIIIIIIIIII Sende-Routine in Maschinensprache aufrufen
'------------------------------------------------------
#SENDBUF
I2C_START                              'Start
i2c_write(Adresse + i)                  'Adresse
i2c_write(0)                           'INSTRUCTION
i2c_write(iii)                         'CONTROL Helligkeit
i2c_write(DIGIT1)
i2c_write(DIGIT3)
i2c_write(DIGIT2)
i2c_write(DIGIT4)
I2C_stop 

I2C_START
i2c_write(Adresse + ii)
i2c_write(0)
i2c_write(iii)
i2c_write(DIGIT5)
i2c_write(DIGIT7)
i2c_write(DIGIT6)
i2c_write(DIGIT8)
I2C_stop
return

 #zeiteinstellen

wait tasterset = on
second = 1
 while tasterset = on
 if tasterzeit = off then
 hour = hour +1
 if hour > 23 Then hour = 0
 gosub zeit
 wait tasterzeit = on
 end if
wend
wait tasterset = on

 while tasterset = on
 if tasterzeit = off then
 minute = minute +1
 if minute > 59 Then minute = 0
 gosub zeit
 wait tasterzeit = on
 end if
wend
wait tasterset = on
second = 1
 goto loop


' ---------------------------------------------------------------------------
' ---------------------------------------------------------------------------
' --- PWM-Routinen für Port2 ------------------------------------------------
' ---------------------------------------------------------------------------
TABLE pwm2_ein byte    ' PWM Port2 einschalten
  &h12 &h06
  &h1a &h20 &h18 &h20 &h3f &h29 &h3f &h2a &ha6 &h1a &hb7 &h28 &h1b &h20 &h81
TABEND
' ---------------------------------------------------------------------------
TABLE pwm2 byte        ' PWM Port2 setzten - Uebergabe als Argument
  &h12 &h06
  &had &h13 &ha1 &hfa &h25 &h03 &h10 &h28 &h81 &h5f &h48 &h59 &h48 &h59 &hbf &h29
  &hb7 &h2a &h11 &h28 &h81 &hae &h01 &h83
TABEND

 INCLUDE "om_i2cx.pro" 'Routinen fuer I2C-Bus einbinden von Dietmar Harlos
INCLUDE "om_fw.pro"  'Firmwareroutinen einbinden



 Table dec595 byte  'für große 7 Seg Leds  Min und Stunden
    ' Bits sind von 1 bis 7 durchnummeriert
    'z.B. die "1" wird durch das 4 und 6 Bit dargestellt.(&01001000)
    'das 0te bit wird für die Helligkeitsregelung  benötigt.
    '
    '       3
    '     2   4
    '       5
    '     1   6
    '       7
 
 

  '    0          1          2             3         4          5            6         7            8          9
   &B11011110,&B01010000,&B10111010, &B11111000, &B01110100, &B11101100, &B11100110,&B01011000, &B11111110,&B01111100
 tabend

 table reihe byte  'für den 60 Sekundenring
1, 3, 7, 15, 31, 63, 127, 255, 254, 252, 248, 240, 224, 192, 128, 0, 1, 2, 4, 8, 16, 32, 64, 128

tabend


    Table Decoder byte   ' für kleine 7 Seg_Anzeige Datum
    ' Bits sind von 0 bis 7 durchnummeriert
    'z.B. die "1" wird durch das 3 und 6 Bit dargestellt.(&01001000)
    'das 7te bit wird nicht benötigt.
    '
    '       2
    '     1   3
    '       0
    '     4   6
    '       5
   '  0            1         2          3         4          5           6          7         8           9
  &B01111110,&B01001000,&B00111101 ,&B01101101,&B01001011,&B01100111,&B01110011,&B01001100,&B01111111,&B01001111
   tabend


table TempTab byte  'Temperatur von 37 Grad +  bis  27 Grad -
 99
 '1   2   3   4   5   6   7   8   9

 37  37  36  36  35  35  34  34  33  33
 32  32  31  31  30  30  29  29  28  28
 27  27  26  26  25  25  24  24  24  23
 23  23  22  22  22  21  21  21  20  20
 20  19  19  18  18  17  17  17  16  16  '150
 15  15  14  14  14  13  13  12  12  11
 11  11  10  10   9   9   8   8   7   7
  6   6   5   5   4   4   3   3   2   2
  1   1   1   0   0   0   0   0 101 101
101 102 102 103 103 104 104 105 105 106  '200
106 107 107 108 108 109 110 110 111 111
112 113 113 114 115 116 116 117 117 118
119 119 120 121 122 123 124 125 126 127

tabend