;*******************************************************************************
;*
;*      Titel:  Unterprogramm zur Nutzung des RTC DS1307 ueber I2C
;*              (SR_RTC_DS1307.asm)
;*
;*      Datum:  10/04/10        Version:        0.6 (23/11/12)
;*      Autor:  WEIGU
;*
;*      Informationen zur Beschaltung:
;*      Prozessor:      ATmega32A/644p/32u4	Quarzfrequenz:  
;*      Eingaenge:
;*      Ausgaenge:
;*
;*      Informationen zur Funktionsweise:     
;*      
;*      Unterprogramme:
;*      RTCSND:	Daten zum DS1307 senden (8 Datenbyte)
;*      RTCRCV:	Daten vom DS1307 empfangen (8 Datenbyte)
;*      RTCASC:	Datum und Zeit in ASCII SRAM Tabelle Abspeichern
;*      	(RTCASCT1 19 Byte: dd.mm.yy hh:MM:ss + Space + NullByte)
;*      	(RTCASCT2 16 Byte: hh:MM:ss  dd/mm + NullByte 2 Leerzeichen)
;*      	(RTCASCT3 13 Byte: hhMMssddmmyy + NullByte)
;*      	Unterprogramm BCD2A2 muss existieren (SR_RECODE.asm)
;*      RTCEIA:	Datum und Zeit zur seriellen Schnittstelle senden (ASCII)
;*      	(Unterprogramm E232SND muss existieren (SR_EIA232.asm)).
;*	RTCINI:	Datum und Zeit initialisieren
;*	RTCSQW:	SQW-Ausgang freischalten (1Hz, Pull-Up z.B. 10k dazuschalten!)
;*      
;*      Copyright (c) 2012   Guy WEILER         weigu[at]weigu[dot]lu
;*
;*      Hiermit wird unentgeltlich, jeder Person, die eine Kopie der Software
;*      und der zugehoerigen Dokumentationen (die "Software") erhaelt, die
;*      Erlaubnis erteilt, uneingeschraenkt zu benutzen, inklusive und ohne
;*      Ausnahme, dem Recht, sie zu verwenden, kopieren, aendern, fusionieren,
;*      verlegen, verbreiten, unterlizenzieren und/oder zu verkaufen, und
;*      Personen, die diese Software erhalten, diese Rechte zu geben, unter den
;*      folgenden Bedingungen:
;*
;*      ;Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in alle
;*      ;Kopien oder Teilkopien der Software beizulegen.
;*      ;
;*      ;DIE SOFTWARE WIRD OHNE JEDE AUSDRUECKLICHE ODER IMPLIZIERTE GARANTIE
;*      ;BEREITGESTELLT, EINSCHLIESSLICH DER GARANTIE ZUR BENUTZUNG FUER DEN
;*      ;VORGESEHENEN ODER EINEM BESTIMMTEN ZWECK SOWIE JEGLICHER RECHTS-
;*      ;VERLETZUNG, JEDOCH NICHT DARAUF BESCHRAENKT. IN KEINEM FALL SIND DIE
;*      ;AUTOREN ODER COPYRIGHTINHABER FUER JEGLICHEN SCHADEN ODER SONSTIGE
;*      ;ANSPRUECHE HAFTBAR ZU MACHEN, OB INFOLGE DER ERFUELLUNG EINES
;*      ;VERTRAGES, EINES DELIKTES ODER ANDERS IM ZUSAMMENHANG MIT DER SOFTWARE
;*      ;ODER SONSTIGER VERWENDUNG DER SOFTWARE ENTSTANDEN.
;*
;*******************************************************************************
;Damit der Code im Flash gering bleibt werden ausschliesslich die benutzten
;Unterprogramme freigeschaltet (Flag = 1)
.EQU    Flag_RTCSND  = 1	;Daten zum DS1307 senden (8 Datenbyte)	
.EQU    Flag_RTCRCV  = 1	;Daten vom DS1307 empfangen (8 Datenbyte)
.EQU    Flag_RTCASC  = 1	;Datum und Zeit als ASCII in SRAM-Tabelle
.EQU    Flag_RTCEIA  = 0	;Datum und Zeit zur EIA232 senden (ASCII)
.EQU	Flag_RTCINI  = 0	;Datum und Zeit initialisieren
.EQU	Flag_RTCSQW  = 1	;SQW-Ausgang freischalten (1Hz, Pull-Up 10k!)

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;       Reservierungen und Zuweisungen
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.DSEG                           	;was ab hier folgt kommt in den SRAM-Speicher
RTCTAB:	  .BYTE 8		;8 Byte grosse Tabelle fuer die Echtzeituhr
RTCASCT1: .BYTE 19              	;dd.mm.yy hh:MM:ss+Space + NullByte  19 Byte
RTCASCT2: .BYTE 16              	;hh:MM:ss  dd/mm + NullByte 2 Leerzeichen 16 Byte
RTCASCT3: .BYTE 13		;hhMMssddmmyy + Nullbyte
.CSEG

.IFNDEF ERRLED
.EQU    ERRLED   = 0            ;1 falls Fehler LED erwuenscht sonst 0
.EQU    ERRDDR   = DDRD         ;LED zur Anzeige eines Uebetragungsfehler
.EQU    ERRPORT  = PORTD
.EQU    ERRPNr   = 7
.ENDIF

;-------------------------------------------------------------------------------
;	Daten zum DS1307 senden (8 Datenbyte aus SRAM-Tabelle RTCTAB)
;-------------------------------------------------------------------------------
.IF Flag_RTCSND == 1
RTCSND: rcall	I2CSTA		;Startbit senden + Kontrolle
        cpi     r25,0x08
        brne    RTCSNE
        ldi	r24,0xD0		;Adresse des RTC DS1307 (Maxim 1101000) senden
	rcall	I2CSND		;(Bit 2^0 = 0 schreiben) + Kontrolle
        cpi     r25,0x18
        brne    RTCSNE
	ldi	r24,0x00		;Adresszeiger = 0 senden + Kontrolle
	rcall	I2CSND
        cpi     r25,0x28        
        brne    RTCSNE
        ;8 Datenbyte senden + Kontrolle
        lds     r24,RTCTAB+0    ;Sekunden
        rcall   I2CSND
        cpi     r25,0x28        
        brne    RTCSNE
        lds     r24,RTCTAB+1    ;Minuten
        rcall   I2CSND
        cpi     r25,0x28
        brne    RTCSNE
        lds     r24,RTCTAB+2    ;Stunden
        rcall   I2CSND
        cpi     r25,0x28
        brne    RTCSNE
        lds     r24,RTCTAB+3    ;Wochentag
        rcall   I2CSND
        cpi     r25,0x28
        brne    RTCSNE
        lds     r24,RTCTAB+4    ;Tag
        rcall   I2CSND
        cpi     r25,0x28
        brne    RTCSNE
        lds     r24,RTCTAB+5    ;Monat
        rcall   I2CSND
        cpi     r25,0x28
        brne    RTCSNE
        lds     r24,RTCTAB+6    ;Jahr
        rcall   I2CSND
        cpi     r25,0x28
        brne    RTCSNE
        lds     r24,RTCTAB+7    ;Kontrollregister
        rcall   I2CSND
        cpi     r25,0x28
        brne    RTCSNE
        rjmp    RTCSNR
RTCSNE: .IF (ERRLED == 1)
        sbi     ERRDDR,ERRPNr   ;Ausgang fuer Fehler LED initialisieren
        sbi     ERRPORT,ERRPNr  ;Fehler LED ein
        .ENDIF
RTCSNR: rcall   I2CSTO          ;Stoppbit senden
        ret
.ENDIF

;-------------------------------------------------------------------------------
;	Daten vom DS1307 empfangen (8 Datenbyte in SRAM-Tabelle RTCTAB)
;-------------------------------------------------------------------------------
.IF Flag_RTCRCV == 1
RTCRCV: rcall	I2CSTA		;Startbit senden + Kontrolle
        cpi     r25,0x08        
        breq    RTCRC1
        cpi     r25,0x10        ;(repeated start falls zu schnell fuer Stoppbit)
        brne    RTCRCE
RTCRC1:	ldi	r24,0xD0		;Adresse des RTC DS1307 (Maxim 1101000) senden
	rcall	I2CSND		;(Bit 2^0 = 0 schreiben) + Kontrolle
        cpi     r25,0x18        
        brne    RTCRCE
	ldi	r24,0x00		;Adresszeiger = 0 senden + Kontrolle
	rcall	I2CSND
        cpi     r25,0x28        
        brne    RTCRCE
       	rcall	I2CSTA		;Repeated Startbit senden + Kontrolle
        cpi     r25,0x10
        brne    RTCRCE
	ldi	r24,0xD1		;Adresse des RTC DS1307 (Maxim 1101000) senden
	rcall	I2CSND		;(Bit 2^0 = 1 lesen) + Kontrolle
        cpi     r25,0x40
        brne    RTCRCE
        ;8 Datenbyte lesen + Kontrolle
	rcall	I2CRAK          ;Sekunden
        sts     RTCTAB+0,r24
        cpi     r25,0x50
        brne    RTCRCE
        rcall   I2CRAK          ;Minuten
        sts     RTCTAB+1,r24
        cpi     r25,0x50
        brne    RTCRCE
        rcall   I2CRAK          ;Stunden
        sts     RTCTAB+2,r24
        cpi     r25,0x50
        brne    RTCRCE
        rcall   I2CRAK          ;Wochentag
        sts     RTCTAB+3,r24
        cpi     r25,0x50
        brne    RTCRCE
        rcall   I2CRAK          ;Tag
        sts     RTCTAB+4,r24
        cpi     r25,0x50
        brne    RTCRCE
        rcall   I2CRAK          ;Monat
        sts     RTCTAB+5,r24
        cpi     r25,0x50
        brne    RTCRCE
        rcall   I2CRAK          ;Jahr
        sts     RTCTAB+6,r24
        cpi     r25,0x50
        brne    RTCRCE
        rcall   I2CRNA          ;Kontrollregister Achtung! mit NAK abschliessen
        sts     RTCTAB+7,r24
        cpi     r25,0x58
        brne    RTCRCE
        rjmp    RTCRCR
RTCRCE: .IF (ERRLED == 1)
        sbi     ERRDDR,ERRPNr   ;Ausgang fuer Fehler LED initialisieren
        sbi     ERRPORT,ERRPNr  ;Fehler LED ein
        .ENDIF
RTCRCR: rcall   I2CSTO          ;Stoppbit senden
        ret
.ENDIF        

;-------------------------------------------------------------------------------
;	Datum und Zeit in ASCII SRAM Tabellev abspeichern
;	(RTCASCT1 19 Byte: dd.mm.yy hh:MM:ss+Space+NullByte)
;	(RTCASCT2 16 Byte: hh:MM:ss  dd/mm+NullByte (2 Leerzeichen))
;*      	(RTCASCT3 13 Byte: hhMMssddmmyy + NullByte)
;	Unterprogramm BCD2A2 muss existieren (SR_RECODE.asm)
;-------------------------------------------------------------------------------
.IF Flag_RTCASC == 1
RTCASC: push	r24
	push	r25
	lds     r24,RTCTAB+4    ;Tag
	rcall	BCD2A2
	sts	RTCASCT1+0,r25
	sts	RTCASCT1+1,r24
	sts	RTCASCT2+10,r25
	sts	RTCASCT2+11,r24
	sts	RTCASCT3+6,r25
	sts	RTCASCT3+7,r24
	ldi	r24,'.'	
	sts	RTCASCT1+2,r24
	ldi	r24,'/'
	sts	RTCASCT2+12,r24
	lds     r24,RTCTAB+5    ;Monat
	rcall	BCD2A2
	sts	RTCASCT1+3,r25
	sts	RTCASCT1+4,r24
	sts	RTCASCT2+13,r25
	sts	RTCASCT2+14,r24
	sts	RTCASCT3+8,r25
	sts	RTCASCT3+9,r24
	ldi	r24,'.'
	sts	RTCASCT1+5,r24
	lds     r24,RTCTAB+6    ;Jahr
	rcall 	BCD2A2
	sts	RTCASCT1+6,r25
	sts	RTCASCT1+7,r24
	sts	RTCASCT3+10,r25
	sts	RTCASCT3+11,r24
	ldi	r24,' '
	sts	RTCASCT1+8,r24
	lds     r24,RTCTAB+2    ;Stunden
	rcall 	BCD2A2
	sts	RTCASCT1+9,r25
	sts	RTCASCT1+10,r24
	sts	RTCASCT2+0,r25
	sts	RTCASCT2+1,r24
	sts	RTCASCT3+0,r25
	sts	RTCASCT3+1,r24
	ldi	r24,':'
	sts	RTCASCT1+11,r24
	sts	RTCASCT2+2,r24
	lds     r24,RTCTAB+1    ;Minuten
	rcall 	BCD2A2
	sts	RTCASCT1+12,r25
	sts	RTCASCT1+13,r24
	sts	RTCASCT2+3,r25
	sts	RTCASCT2+4,r24
	sts	RTCASCT3+2,r25
	sts	RTCASCT3+3,r24
	ldi	r24,':'
	sts	RTCASCT1+14,r24
	sts	RTCASCT2+5,r24
	lds     r24,RTCTAB+0	;Sekunden
	rcall 	BCD2A2
	sts	RTCASCT1+15,r25
	sts	RTCASCT1+16,r24
	sts	RTCASCT2+6,r25
	sts	RTCASCT2+7,r24
	sts	RTCASCT3+4,r25
	sts	RTCASCT3+5,r24
	ldi	r24,' '
	sts	RTCASCT1+17,r24
	sts	RTCASCT2+8,r24
	sts	RTCASCT2+9,r24
	clr	r24		;Nullbyte
	sts	RTCASCT1+18,r24
	sts	RTCASCT2+15,r24
	sts	RTCASCT3+12,r24
	pop	r25
	pop	r24
	ret
.ENDIF	

;-------------------------------------------------------------------------------
;	Datum und Zeit zur seriellen Schnittstelle senden (ASCII)
;	Unterprogramm E232SND muss existieren (SR_EIA232.asm)
;-------------------------------------------------------------------------------
.IF Flag_RTCEIA == 1
RTCEIA: push	r18
	push	r24
	push	XL
	push	XH

	rcall	RTCASC
   	ldi	XL,LOW(RTCASCT1)	
        ldi	XH,HIGH(RTCASCT1)
        ldi	r18,18
RTCEIL: ld	r24,X+
	rcall	E232SND
        dec	r18
        brne	RTCEIL

	pop	XH
	pop	XL
	pop	r24
	pop	r18
	ret	
.ENDIF	

;-------------------------------------------------------------------------------
;	RTC mit Datum und Uhrzeit initialisieren
;-------------------------------------------------------------------------------
.IF Flag_RTCINI == 1
RTCINI: push	r16
	ldi	r16,0x00		;Sekunden (alles BCD!)
	sts	RTCTAB+0,r16
	ldi	r16,0x30		;Minuten
	sts	RTCTAB+1,r16
	ldi	r16,0x12		;Stunden
	sts	RTCTAB+2,r16
	ldi	r16,0x02		;Wochentag (1 = Montag)
	sts	RTCTAB+3,r16
	ldi	r16,0x01		;Tag
	sts	RTCTAB+4,r16
	ldi	r16,0x05		;Monat
	sts	RTCTAB+5,r16
	ldi	r16,0x12		;Jahr
	sts	RTCTAB+6,r16
	ldi	r16,0x00		;Kontrollbyte
	sts	RTCTAB+7,r16
	rcall	RTCSND
	pop	r16
        ret
.ENDIF


;-------------------------------------------------------------------------------
;	SQW Ausgang freischalten (Rechteck mit 1 Hz, Pull-Up Widerstand 10k)
;-------------------------------------------------------------------------------
.IF Flag_RTCSQW == 1
RTCSQW:	rcall	I2CSTA		;Startbit senden + Kontrolle
        cpi     r25,0x08
        brne    RTCSQE
        ldi	r24,0xD0		;Adresse des RTC DS1307 (Maxim 1101000) senden
	rcall	I2CSND		;(Bit 2^0 = 0 schreiben) + Kontrolle
        cpi     r25,0x18
        brne    RTCSQE
	ldi	r24,0x07		;Adresszeiger = 7 senden + Kontrolle
	rcall	I2CSND
        cpi     r25,0x28
        brne    RTCSQE
        ldi     r24,0x10		;Kontrollregister 
        rcall   I2CSND
        cpi     r25,0x28
        brne    RTCSQE
        rjmp    RTCSQR
RTCSQE: .IF (ERRLED == 1)
        sbi     ERRDDR,ERRPNr   ;Ausgang fuer Fehler LED initialisieren
        sbi     ERRPORT,ERRPNr  ;Fehler LED ein
        .ENDIF
RTCSQR: rcall   I2CSTO          ;Stoppbit senden
        ret
.ENDIF
