;*******************************************************************************
;*
;*      Titel:  Unterprogramme zur Nutzung der I2C-Schnittstelle (TWI)
;*              (SR_I2C.asm)
;*
;*      Datum:  01/10/09        Version:        0.4 (2012)
;*      Autor:  WEIGU
;*
;*      Informationen zur Beschaltung:
;*      Prozessor:      ATmega32A        Quarzfrequenz:  16MHz
;*      Eingaenge:
;*      Ausgaenge:
;*
;*      Informationen zur Funktionsweise:
;*
;*      Betrieb im normal mode oder fast mode (100 kHz bzw. 400kHz)
;*      2 Pull-Up-Widerstaende von 4,7k (5V) oder 3,3k (3,3V)
;*      Daten werden mit r24 uebergeben. Der Status nach dem Ausfuehren
;*      einer Funktion befindet sich in r25
;*      
;*      Copyright (c) 2011   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.
;*
;*******************************************************************************

;///////////////////////////////////////////////////////////////////////////////
;	Makros 
;	siehe http://www.mikrocontroller.net/articles/AVR_Assembler_Makros
;///////////////////////////////////////////////////////////////////////////////
;Bei neuen Chips liegen viele SF-Register ueber den 64 Adressen die mit den 
;Befehlen "in" und "out" zu erreichen sind. Fuer sie muessen "sts" und "lds"
;verwendet werden. Dies wird mit den folgenden beiden Makros erledigt. Statt der
;Befehle "in" und "out" werden in der Bibliothek die Makros "input" und "output"
;verwendet.

;Einlesen eines Ports mit input Arbeitsregister,SF-Register
.IFNDEF MACROINPUT
.SET	MACROINPUT = 1
  .MACRO input
    .IF @1 < 64
	in	@0, @1
    .ELSE
	lds	@0, @1
    .ENDIF
  .ENDM
.ENDIF

;Schreiben eines Ports mit output SF-Register,Arbeitsregister
.IFNDEF MACROOUTPUT
.SET	MACROOUTPUT = 1
  .MACRO output
    .IF @0 < 64
	out	@0, @1
    .ELSE
  	sts	@0, @1
    .ENDIF
  .ENDM
.ENDIF

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;       Zuweisungen
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.EQU    I2C_Clock = 100000      ;I2C Geschwindigkeit (nur 100000 oder 400000)
.IFNDEF CPU_Clock
.EQU    CPU_Clock = 16000000    ;Systemtakt
                                ;Achtung! Je nach Systemtakt muss der Vorteiler
                                ;und die Formel im UP I2CINI angepasst werden
.ENDIF                                
;-------------------------------------------------------------------------------
;       I2C (TWI) initialisieren 
;-------------------------------------------------------------------------------
I2CINI: push	r16
	clr     r16             ;TWPS = 0 (Vorteiler = 1)
        output  TWSR,r16        ;TWBR=((Systemtakt/I2C Takt)-16)/(2*Vorteiler)
        ldi     r16,((CPU_Clock/I2C_Clock)-16)/2
        output  TWBR,r16        ;das Einschalten der Baugruppe (TWEN in TWCR)
        pop	r16
        ret                     ;erfolgt jeweils beim Ansteuern
        
;-------------------------------------------------------------------------------
;       Startbit senden
;-------------------------------------------------------------------------------
I2CSTA: push	r24
	ldi     r24,0xA4        ;TWCR=0b10100100 TWINT,TWSTA u. TWEN setzen
        output  TWCR,r24
I2CST1: input   r24,TWCR        ;warten bis TWINT wieder 1
        sbrs    r24,TWINT       ;Operation beendet
        rjmp    I2CST1
        input   r25,TWSR        ;Status-Code in r25
        andi    r25,0xF8
        pop	r24
        ret

;-------------------------------------------------------------------------------
;       Daten senden
;-------------------------------------------------------------------------------
I2CSND: push	r24
	output  TWDR,r24        ;r24 (Daten) ins Datenregister
        ldi     r24,0x84        ;TWCR=0b10000100 TWINT u. TWEN setzen TWSTA
        output  TWCR,r24		;ruecksetzen
I2CSN1: input   r24,TWCR        ;warten bis TWINT wieder 1
        sbrs    r24,TWINT       ;Operation beendet
        rjmp    I2CSN1
        input   r25,TWSR        ;Status-Code in r25
        andi    r25,0xF8       
        pop	r24
        ret

;-------------------------------------------------------------------------------
;       Daten empfangen mit ACK
;-------------------------------------------------------------------------------
I2CRAK: ldi     r24,0xC4        ;TWCR=0b11000100 TWINT, TWEA u. TWEN setzen
        output  TWCR,r24
I2CRA1: input   r24,TWCR        ;warten bis TWINT wieder 1
        sbrs    r24,TWINT       ;(Start-Operation beendet)
        rjmp    I2CRA1
        input   r24,TWDR        ;Daten in r24
        input   r25,TWSR        ;Status-Code in r25
        andi    r25,0xF8
        ret

;-------------------------------------------------------------------------------
;       Daten empfangen ohne ACK (NACK)
;-------------------------------------------------------------------------------
I2CRNA: ldi     r24,0x84        ;TWCR=0b10000100 TWINT u. TWEN setzen
        output  TWCR,r24
I2CRN1: input   r24,TWCR        ;warten bis TWINT wieder 1
        sbrs    r24,TWINT       ;(Start-Operation beendet)
        rjmp    I2CRN1
        input   r24,TWDR        ;Daten in r24
        input   r25,TWSR        ;Status-Code in r25
        andi    r25,0xF8
        ret

;-------------------------------------------------------------------------------
;       Stoppbit senden
;-------------------------------------------------------------------------------
I2CSTO: push	r16
	ldi     r16,0x94         ;TWCR=0b10010100 TWINT, TWSTO u. TWEN setzen
        output  TWCR,r16
        pop	r16
        ret
