; AT90S8515

.include "8515def.inc"
.def    ICPHelp =r0
.def    PData   =r1                     ; Int1-Register fr Parallel-Data-Leitungen
.def    Counter =r2	                ; tempor„rer Counter
.def    SPITemp =r3                     ; SPI-Interrupt temporäres Register
.def    ITemp   =r4                     ; temporary register
.def    OCRTemp =r5                     ; tempor„res Register
.def    TOVTemp1=r6                     ; tempor„res Register
.def    ReadAdr =r7                     ; Int1-Register fr Lese-Adresse
.def    TastTemp=r8                     ; Entprellen Tasteneingabe
.def    DrehTemp=r9                     ; Entprellen Drehknopf

.def    Puffer_RC5Dat  =r10             ; Read-Puffer fr RC5-Daten
.def    Puffer_RC5Adr  =r11             ; Read-Puffer fr RC5-Adresse
.def    RC5_SollAdr    =r12             ; Gewünschte RC5-Adresse
.def    Puffer_Tasten  =r13             ; Read-Puffer fr Tasten - Eingabe
.def    DrehCount      =r14             ; Drehknopf-Counter
.def    RC5Adr  =r16                    ; 1.Byte RC5-Empfang
.def    RC5Dat  =r15                    ; 2.Byte RC5-Empfang
.def    RC5Cnt  =r17                    ; RC5-Bit-Counter/Status

.def    Status  =r18                    ; Status
.def    Status2 =r19
.def    Temp    =r20                    ;temporary register

.def    Puffer  =r21
.def    TOVTemp =r22                    ;temporary register
.def    ICPTime =r23
.def    ICPTemp =r24
.def    PCtrl   =r25                    ; Int1-Register fr Parallel-Ctrl-Leitungen

.equ    PUFFER0 =7
.equ    LEER    =6
.equ    DREH    =5                      ;Bit 5 in Status
.equ    EMPFANG =4                      ;Bit 4 in Status
.equ    TASTEN  =3                      ;Bit 3 in Status
.equ    RUN_SPI =2                      ;Bit 2 in Status
.equ    SDREH1  =1                      ;Bit 1 in Status
.equ    SDREH0  =0                      ;Bit 0 in Status

.equ    DISABLED=5                      ;Bit 5 in Status2
.equ    ENHANCED=4                      ;Bit 4 in Status2

.equ    PufferEnde=$0CF
.equ    PufferVoll=$0BE
.equ    PufferLeer=$080

;SRAM-Register
.equ    TastBuf = $200
.equ    Dat0    = $208
.equ    Dat1    = $209
.equ    Kontrast= $20a
.equ    Licht   = $20b
.equ    Adresse = $20c



.equ	SCLP	= 4			; SCL Pin number (port D)
.equ	SDAP	= 1			; SDA Pin number (port D)
.equ	b_dir	= 0			; transfer direction bit in i2cadr
.equ	i2crd	= 1
.equ	i2cwr	= 0
.def	i2cdelay= r26			; Delay loop variable
.def	i2cdata	= r27			; I2C data transfer register
.def	i2cadr	= r28			; I2C address and direction register
.def	i2cstat	= r29			; I2C bus status register



.CSEG

                rjmp    Patch
.org INT0addr
                rjmp    Int0_Int
.org INT1addr
                rjmp    Int1_Int
.org ICP1addr
                rjmp    ICP_Int
.org OC1Aaddr
                reti
.org OC1Baddr
                reti
.org OVF1addr
                rjmp    OVF1_Int
.org OVF0addr
                reti
.org SPIaddr
                rjmp    SPI_Int
.org URXCaddr
                reti
.org UDREaddr
                reti
.org UTXCaddr
                reti
.org ACIaddr
                reti
.org $010

JumpTab:        rjmp    Int1_Write0              ;  0 Write MAS-Daten
                rjmp    Int1_Read0               ;  1 Read  Status
                rjmp    Int1_Write1              ;  2 Write Command
                rjmp    Int1_Read1               ;  3 Read  Command
                rjmp    Int1_WriteLCD0           ;  4 Write LCD0
                rjmp    Int1_WriteDat0           ;  5 Write Dat0
                rjmp    Int1_WriteLCD1           ;  6 Write LCD1
                rjmp    Int1_WriteDat1           ;  7 Write Dat1

ReadTab:        rjmp    Read_IRDAT               ;  0 IR-Daten lesen
                rjmp    Read_IRADR               ;  1 IR-Adresse lesen
                rjmp    Read_TASTEN              ;  2 Tasten lesen
                rjmp    Read_PUFFER              ;  3 Puffer lesen
                rjmp    Read_DREHCOUNT           ;  4 Drehknopf-Counter lesen
                rjmp    Read_EEprom              ;  5 EEData lesen
                rjmp    Read_EEpromINC           ;  6 EEData lesen + Inc Adr
                rjmp    Read_KONTRAST            ;  7 Einstellung Kontrast lesen
                rjmp    Read_LICHT               ;  8 Einstellung Kontrast lesen
                rjmp    Read_ENDE                ;  9 nicht benutzt
                rjmp    Read_ENDE                ; 10 nicht benutzt
                rjmp    Read_ENDE                ; 11 nicht benutzt
                rjmp    Read_ENDE                ; 12 nicht benutzt
                rjmp    Read_VERSION             ; 13 Software-Versionsnummer
                rjmp    Read_LCD0                ; 14 nicht benutzt
                rjmp    Read_LCD1                ; 15 nicht benutzt

WriteTab:       rjmp    Int1_WriteEnd            ;  0 nicht benutzt
                rjmp    Write_RC5Adr             ;  1 RC5-Solladresse speichern
                rjmp    Write_Adr_Tab            ;  2 Adresse Tabelle speichern
                rjmp    Write_Adr_lo             ;  3 EE-Low -Adr speichern
                rjmp    Write_Adr_hi             ;  4 EE-High-Adr speichern
                rjmp    Write_EEprom             ;  5 EEprom beschreiben
                rjmp    Write_EEpromInc          ;  6 EEprom beschreiben + Inc Adr
                rjmp    Write_Kontrast           ;  7 Kontrast einstellen
                rjmp    Write_Licht              ;  8 Licht einstellen
                rjmp    Int1_WriteEnd            ;  9 nicht benutzt
                rjmp    Int1_WriteEnd            ; 10 nicht benutzt
                rjmp    Int1_WriteEnd            ; 11 nicht benutzt
                rjmp    Int1_WriteEnd            ; 12 nicht benutzt
                rjmp    Int1_WriteEnd            ; 13 nicht benutzt
                rjmp    Int1_WriteEnd            ; 14 nicht benutzt
                rjmp    Int1_WriteEnd            ; 15 nicht benutzt


.include "VER10.inc"

;*********************************************************************
;  Interruptanforderung setzen/loeschen
;*********************************************************************
Set_INT:        cli
                push    Status
;                andi    Status,(1<<LEER)+(1<<DREH)+(1<<EMPFANG)+(1<<TASTEN)
;                sbrc    Status2,DISABLED
;                andi    Status,(1<<DREH)+(1<<EMPFANG)+(1<<TASTEN)
;                sbrs    Status2,ENHANCED
                andi    Status,(1<<LEER)
                breq    Set_INT1                 ; Alles bearbeitet ?
                sbi     P_INT,INT                ; INT weiterhin aktiv
                pop     Status
                ret
Set_INT1:       cbi     P_INT,INT                ; INT deaktivieren
                pop     Status
                ret

;*********************************************************************
;  Interruptroutine  SPI-Daten-Übertragung fertig
;*********************************************************************
SPI_Int :       rcall   SPI_Out
                reti

SPI_Out:        sbis    PIN_DEM,DEMAND           ; DEMAND Low ?
                rjmp    SPI_Stop                 ; Wenn kein DEMAND -> Ende
                cpse    XH,YH                    ; Vergleich Zeiger_in/Zeiger_out
                rjmp    SPI_Write                ; Zeiger ungleich -> Zeichen im Puffer
                cpse    XL,YL                    ; Vergleich Zeiger_in/Zeiger_out
                rjmp    SPI_Write                ; Zeiger ungleich -> Zeichen im Puffer
SPI_Stop:       in      SPITemp,SREG             ; SREG sichern
                cbi     SPCR,SPE                 ; serielle šbertragung sperren
                cbi     SPCR,MSTR                ; serielle šbertragung sperren
                cbr     Status,(1<<RUN_SPI)      ; Status : SPI ist leer
                out     SREG,SPITemp             ; SREG restoren
                ret

SPI_Write:      sbi     SPCR,MSTR                ; als Master
                sbi     SPCR,SPE                 ; serielle šbertragung freigeben
                ld      SPITemp,X+               ; Zeichen aus Puffer holen
                out     SPDR,SPITemp             ; Zeichen auf SPI ausgeben
                in      SPITemp,SREG             ; SREG sichern
                sbr     Status,(1<<RUN_SPI)      ; Status : SPI l„uft
                sbrc    XH,1                     ; Zeiger-šberlauf (128-255) ? wenn nein skip
                ldi     XL,$060                  ; Zeiger auf Puffer-Anfang
                andi    XH,$001                  ; High-Byte immer 0/1

                sbrc    Status,PUFFER0
                rjmp    SPI_Write01
                sbr     Status,(1<<PUFFER0)
                dec     Puffer                   ; ein Zeichen weniger im Puffer
                cpi     Puffer,PufferLeer
                brsh    SPI_Write02
                sbr     Status,(1<<LEER)
                rcall   Set_INT
                rjmp    SPI_Write02
SPI_Write01:    cbr     Status,(1<<PUFFER0)
SPI_Write02:    out     SREG,SPITemp             ; SREG restoren
                ret


;*********************************************************************
;  Interruptroutine  Externer Interrupt 0 ( DEMAND Low-Flanke )
;*********************************************************************
Int0_Int:       sbrc    Status,RUN_SPI           ; l„uft SPI ?
                reti                             ; ja -> Ende
                rcall   SPI_Out
                reti


;*********************************************************************
;  Interruptroutine  Externer Interrupt 1 ( STROBE High/Low Flanke )
;*********************************************************************
Int1_Int:       in      ITemp,SREG               ; SREG sichern
                rcall   Get_INT_Param
                breq    Int1_Write0
                ldi     ZH,$000
                ldi     ZL,$000
                bst     PCtrl,CTRL0
                bld     ZL,0
                bst     PCtrl,CTRL1
                bld     ZL,1
                bst     PCtrl,CTRL2
                bld     ZL,2
                adiw    ZL,JumpTab               ; Offset JumpTab addieren
                ijmp                             ; indirekter Sprung ber JumpTab


Int1_Write0:    cbi     P_BUSY,BUSY              ; BUSY ršcksetzen -> BUSY
                cpi     Puffer,PufferEnde
                breq    Int1_Write02

                st      Y+,PData                 ; Daten ins SRAM (Y-Speicher-Zeiger)
                sbrc    YH,1                     ; Zeiger-šberlauf (128-255) ? wenn nein skip
                ldi     YL,$060                  ; Zeiger auf Puffer-Anfang
                andi    YH,$001                  ; High-Byte immer 0

                sbrs    Status,PUFFER0
                rjmp    Int1_Write01
                cbr     Status,(1<<PUFFER0)
                inc     Puffer                   ; ein Zeichen mehr im Puffer
                rjmp    Int1_Write02
Int1_Write01:   sbr     Status,(1<<PUFFER0)
                cpi     Puffer,PufferVoll
                brlo    Int1_Write02
                cbr     Status,(1<<LEER)
                rcall   Set_INT
Int1_Write02:   sbrc    Status,RUN_SPI           ; MAS-Senderoutine aktiv ?
                rjmp    Int1_WriteEnd            ; ja, dann Ende
                rcall   SPI_Out                  ; ja, dann Zeichen ausgeben
                rjmp    Int1_WriteEnd            ; Ende


Int1_Write1:    cbi     P_BUSY,BUSY              ; BUSY rcksetzen -> BUSY
                sbrc    PData,7                  ; Bit 7 gesetzt ?
                rjmp    Int1_Start               ; ja, dann zur Startsequenz
                sbrc    PData,6                  ; Bit 6 gesetzt ?
                rjmp    Int1_WriteEnd            ; ja, frei
                sbrc    PData,5                  ; Bit 5 gesetzt ?
                rjmp    Int1_Command             ; ja, Write-Commando
                sbrc    PData,4                  ; Bit 4 gesetzt ?
                rjmp    Int1_Adresse             ; ja, LeseAdresse speichern
                sbrc    PData,3                  ; Bit 3 gesetzt ?
                rjmp    Int1_Display             ; ja, Display / Enhanced-Int-Mode
                sbrc    PData,2                  ; Write 1 - Reset_ Software-reset ?
                rjmp    Patch         ; ja, ausführen
                sbrs    PData,1                  ; I2C-Clock l”schen ?
                cbi     P_I2CC,I2CC              ; I2C-Clock l”schen
                sbrs    PData,1                  ; I2C-Clock l”schen ?
                sbi     DDR_I2CC,I2CC            ; I2C-Clock l”schen
                sbrc    PData,1                  ; I2C-Clock setzen ?
                cbi     DDR_I2CC,I2CC            ; I2C-Clock setzen
                sbrc    PData,1                  ; I2C-Clock setzen ?
                sbi     P_I2CC,I2CC              ; I2C-Clock setzen

                sbrs    PData,0                  ; I2C-Daten l”schen ?
                cbi     P_I2CD,I2CD              ; I2C-Daten low
                sbrs    PData,0                  ; I2C-Daten l”schen ?
                sbi     DDR_I2CD,I2CD            ; TRI-State aufheben
                sbrc    PData,0                  ; I2C-Daten setzen ?
                cbi     DDR_I2CD,I2CD            ; TRI-State I2C-Daten
                sbrc    PData,0                  ; I2C-Daten setzen ?
                sbi     P_I2CD,I2CD              ; I2C-Daten high (Pull-Up)
                rjmp    Int1_WriteEnd            ; Ende



Int1_Start:     rjmp    Int1_WriteEnd            ; noch nicht implementiert

Int1_Command:   ldi     ZH,$000
                mov     ZL,PData
                andi    ZL,$00F
                adiw    ZL,WriteTab              ; Offset WriteTab addieren
                lds     PData,Dat0
                ijmp                             ; indirekter Sprung ber WriteTab

Write_RC5Adr:   mov     RC5_SollAdr,PData        ; RC5-Default-Adresse setzen
                rjmp    Int1_WriteEnd            ; Ende
Write_Adr_Tab:  sts     Adresse,PData            ; Tabellen-Adresse speichern
                rjmp    Int1_WriteEnd            ; Ende
Write_Adr_lo:   out     EEARL,PData
                rjmp    Int1_WriteEnd            ; Ende
Write_Adr_hi:   out     EEARH,PData
                rjmp    Int1_WriteEnd            ; Ende
Write_EEprom:   out     EEDR,PData
                rcall   EE_Write
                rjmp    Int1_WriteEnd            ; Ende
Write_EEpromInc:out     EEDR,PData
                rcall   EE_WriteInc
                rjmp    Int1_WriteEnd            ; Ende
Write_Kontrast: sts     Kontrast,PData
                ldi     ZL,$00
                clc
                sbrc    PData,7
                sec
                rol     PData
                rol     ZL
                out     OCR1AH,ZL
                out     OCR1AL,PData
                rjmp    Int1_WriteEnd            ; Ende
Write_Licht:    sts     Licht,PData              ; Licht einstellen
                ldi     ZL,$00
                clc
                sbrc    PData,7
                sec
                rol     PData
                rol     ZL
                out     OCR1BH,ZL
                out     OCR1BL,PData
                rjmp    Int1_WriteEnd            ; Ende



Int1_Adresse:   mov     ReadAdr,PData            ; LeseAdresse speichen
                rjmp    Int1_WriteEnd            ; Ende

Int1_Display:   ldi     ZL,$000
                sbrc    PData,0                  ; Beleuchtung ausschalten ?
                ldi     ZL,$FF
                ldi     ZH,$000
                sbrc    PData,0                  ; Beleuchtung ausschalten ?
                ldi     ZH,$001
                sts     Licht,ZL                 ; Licht einstellen
                out     OCR1BH,ZH
                out     OCR1BL,ZL
                bst     PData,1                  ; Enhanced-Int-Mode ?
                bld     Status2,ENHANCED
                bst     PData,2                  ; Kein Demand-Int ?
                bld     Status2,DISABLED
                rcall   Set_INT
                rjmp    Int1_WriteEnd            ; Ende

Int1_WriteLCD0: cbi     P_BUSY,BUSY              ; BUSY rcksetzen -> BUSY
                mov     Temp,PData
                rcall   WriteLCD0
                rjmp    Int1_WriteEnd            ; Ende
Int1_WriteLCD1: cbi     P_BUSY,BUSY              ; BUSY rcksetzen -> BUSY
                mov     Temp,PData
                rcall   WriteLCD1
                rjmp    Int1_WriteEnd            ; Ende

Int1_WriteDat0: cbi     P_BUSY,BUSY              ; BUSY rcksetzen -> BUSY
                sts     Dat0,PData
                rjmp    Int1_WriteEnd            ; Ende

Int1_WriteDat1: cbi     P_BUSY,BUSY              ; BUSY rcksetzen -> BUSY
                sts     Dat1,PData
                rjmp    Int1_WriteEnd            ; Ende


Int1_WriteEnd:  sei
Int1_BusyLoop:  sbis    PIN_STR,STROBE           ; STROBE wieder high ?
                rjmp    Int1_BusyLoop            ; nein -> warten
                out     SREG,ITemp               ; SREG restoren
                sbi     P_BUSY,BUSY              ; BUSY rcksetzen
                reti

; Lesen
Int1_Read0:     set
                sbis    PIN_I2CD,I2CD            ; I2Data nach T
                clt
                bld     PData,0                  ; und ab ins AusgabeByte
                bst     Status,LEER              ; DEMAND nach T
                bld     PData,1                  ; und ab ins AusgabeByte
                bst     Status,SDREH0            ; Drehknopf0 nach T
                bld     PData,2                  ; und ab ins AusgabeByte
                bst     Status,SDREH1            ; Drehknopf1 nach T
                bld     PData,3                  ; und ab ins AusgabeByte
                bst     Status,EMPFANG           ; IR-Empfangen nach T
                bld     PData,4                  ; und ab ins AusgabeByte
                bst     Status,TASTEN            ; Taste gedrckt nach T
                bld     PData,5                  ; und ab ins AusgabeByte
                bst     Status,DREH              ; Drehknopf gedreht nach T
                bld     PData,6                  ; und ab ins AusgabeByte
                clt                              ; T-Flag l”schen
                bld     PData,7                  ; und ab ins AusgabeByte
                rjmp    Int1_ReadEnd

Int1_Read1:     ldi     ZH,$000
                mov     ZL,ReadAdr               ; ReadAdr als Zeiger
                andi    ZL,$00f                  ; Maskieren
                adiw    ZL,ReadTab               ; Offset ReadTab addieren
                ijmp                             ; indirekter Sprung ber ReadTab


Read_ENDE:      clr     PData
                rjmp    Int1_ReadEnd
Read_IRDAT:     mov     PData,Puffer_RC5Dat      ; RC5-Daten ausgeben (Adrok,Toggle,D5-D0)
                cbr     Status,(1<<EMPFANG)      ; Empfangs-Flag rücksetzen
                rcall   Set_INT
                rjmp    Int1_ReadEnd
Read_IRADR:     mov     PData,Puffer_RC5Adr      ; RC5-Adresse ausgeben (0,0,0,Adr4-Adr0)
                cbr     Status,(1<<EMPFANG)      ; Empfangs-Flag rcksetzen
                rcall   Set_INT
                rjmp    Int1_ReadEnd
Read_TASTEN:
;   mov     PData,Puffer_Tasten      ; Tastenpuffer ausgeben
                lds     PData,TastBuf
                mov     ZL,Status2
                andi    ZL,$00F
                breq    Read_TASTEN0
                dec     Status2
                cpi     ZL,$001
                breq    Read_TASTEN0
                lds     ZL,TastBuf+1
                sts     TastBuf+0,ZL
                lds     ZL,TastBuf+2
                sts     TastBuf+1,ZL
                lds     ZL,TastBuf+3
                sts     TastBuf+2,ZL
                lds     ZL,TastBuf+4
                sts     TastBuf+3,ZL
                lds     ZL,TastBuf+5
                sts     TastBuf+4,ZL
                lds     ZL,TastBuf+6
                sts     TastBuf+5,ZL
                lds     ZL,TastBuf+7
                sts     TastBuf+6,ZL
                rjmp    Int1_ReadEnd
Read_TASTEN0:   cbr     Status,(1<<TASTEN)       ; Tasten-Flag rcksetzen
                rcall   Set_INT
                rjmp    Int1_ReadEnd
Read_PUFFER:    mov     PData,Puffer             ; Pufferstand/2 ausgeben
                rjmp    Int1_ReadEnd
Read_DREHCOUNT: mov     PData,DrehCount          ; Drehknopf-Counter ausgeben
                cbr     Status,(1<<DREH)         ; Drehknopf-Flag rcksetzen
                clr     DrehCount                ; Drehknopf-Counter rcksetzen
                rcall   Set_INT
                rjmp    Int1_ReadEnd
Read_EEprom:    rcall   EE_Read
                rjmp    Int1_ReadEnd
Read_EEpromInc: rcall   EE_ReadInc
                rjmp    Int1_ReadEnd

Read_LCD0:      rcall   ReadLCD0
                mov     PData,Temp
                rjmp    Int1_ReadEnd             ; Ende
Read_LCD1:      rcall   ReadLCD1
                mov     PData,Temp
                rjmp    Int1_ReadEnd             ; Ende
Read_KONTRAST:  lds     PData,Kontrast           ; Kontast ausgeben
                rjmp    Int1_ReadEnd
Read_LICHT:     lds     PData,Licht              ; Licht ausgeben
                rjmp    Int1_ReadEnd
Read_VERSION:   lds     PData,VERSION            ; Versionsnummer ausgeben
                rjmp    Int1_ReadEnd


Int1_ReadEnd:   push    ITemp
                clr     ITemp
                com     ITemp                    ; alles Ausg„nge
                out     DDR_BUS,ITemp            ; auf Port C (Daten)
                out     P_BUS,PData              ; Daten ausgeben
                rcall   Set_Data
                rcall   OutPut
                cbi     P_BUSY,BUSY              ; ATMEL ist Busy
                sei
Int1_BusyWait1: sbic    PIN_STR,STROBE           ; STROBE wieder high ?
                rjmp    Int1_BusyEnd             ; nein -> warten
                sbic    PIN_CTRL,CTRL0
                rjmp    Int1_BusyWait1

                sbi     P_BUSY,BUSY              ; ATMEL ist Busy
Int1_BusyWait0: sbic    PIN_STR,STROBE           ; STROBE wieder high ?
                rjmp    Int1_BusyEnd             ; nein -> warten
                sbis    PIN_CTRL,CTRL0
                rjmp    Int1_BusyWait0

                lsr     PData
                rcall   Set_Data
                cbi     P_BUSY,BUSY              ; ATMEL ist Busy
                rjmp    Int1_BusyWait1

Int1_BusyEnd:   rcall   Input
                clr     ITemp
                out     DDR_BUS,ITemp            ; Daten alles Eing„nge
                out     P_BUS,ITemp              ; Pull-Up's aus
                pop     ITemp
                out     SREG,ITemp               ; SREG restoren
                sbi     P_BUSY,BUSY              ; BUSY rcksetzen
                reti





;*********************************************************************
;  Interruptroutine  Timer-šberlauf -> Tasten einlesen
;*********************************************************************
OVF1_Int:       in      TOVTemp1,SREG
                rcall   Tasten_Input
                cpse    TOVTemp,TastTemp
                clr     counter
                mov     TastTemp,TOVTemp
                rcall   Dreh_Input
                cpse    TOVTemp,DrehTemp
                clr     counter
                mov     DrehTemp,TOVTemp

                sbrs    Counter,7
                inc     Counter
                ldi     TOVTemp,$004
                out     SREG,TOVTemp1
                cpse    TOVTemp,Counter
                reti

;*********************************************************************
;  jetzt entprellt -> anders als Puffer ?
;*********************************************************************
TestTasten:     mov     TOVTemp,TastTemp
                cp      TOVTemp,Puffer_Tasten
                breq    TestDreh
                mov     Puffer_Tasten,TOVTemp    ; im Puffer eintragen
                mov     ZL,Status2
                andi    ZL,$00F
                sbrs    ZL,3
                inc     Status2
                sbrc    ZL,3
                dec     ZL
                ldi     ZH,HIGH(TastBuf)
                st      Z,TOVTemp
                sbr     Status,(1<<TASTEN)       ; Flag neue Taste setzen
                rcall   Set_INT                  ; Im ENHANCED-INT-MODE Int setzen
TestDreh:       sei
                mov     TOVTemp,DrehTemp
                eor     TOVTemp,Status
                andi    TOVTemp,(1<<SDREH0) + (1<<SDREH1)
                brne    TestRichtung
                out     SREG,TOVTemp1
                reti

;*********************************************************************
;  Drehkopfcounter-Richtung feststellen
;*********************************************************************
TestRichtung:   mov     TOVTemp,DrehTemp
                lsl     TOVTemp
                lsl     TOVTemp
                or      TOVTemp,Status
                andi    TOVTemp,(5<<SDREH0) + (5<<SDREH1)
                andi    Status,$FF-(1<<SDREH0)-(1<<SDREH1)
                or      Status,DrehTemp

                cpi     TOVTemp,$02
                breq    Drehrechts
                cpi     TOVTemp,$04
                breq    Drehrechts
                cpi     TOVTemp,$0D
                breq    Drehrechts
                cpi     TOVTemp,$0B
                breq    Drehrechts
                cpi     TOVTemp,$01
                breq    Drehlinks
                cpi     TOVTemp,$07
                breq    Drehlinks
                cpi     TOVTemp,$0E
                breq    Drehlinks
                cpi     TOVTemp,$08
                breq    Drehlinks
                out     SREG,TOVTemp1
                reti
;*********************************************************************
;  Drehkopfcounter-Richtung war links -> neuer Counter + Flag
;*********************************************************************
Drehlinks:      dec     DrehCount
                sbr     Status,(1<<DREH)
                rcall   Set_INT                  ; Im ENHANCED-INT-MODE Int setzen
                out     SREG,TOVTemp1
                reti
;*********************************************************************
;  Drehkopfcounter-Richtung war rechts -> neuer Counter + Flag
;*********************************************************************
Drehrechts:     inc     DrehCount
                sbr     Status,(1<<DREH)
                rcall   Set_INT                  ; Im ENHANCED-INT-MODE Int setzen
                out     SREG,TOVTemp1
                reti

;*********************************************************************
;  Interruptroutine  Comparator -> RC5-Flanke
;*********************************************************************
ICP_Int:        in      ICPHelp,SREG             ; Flags sichern
                in      ICPTemp,TCCR1B           ; Int-Edge-Richtung feststellen
                ldi     ICPTime,(1<<ICES1)       ; nächster Int : falling Edge
                eor     ICPTime,ICPTemp          ; andere Flanke
                out     TCCR1B,ICPTime           ; Edge-Richtung setzen

                in      ICPTime,TCNT0            ; Timer-Stand sichern
                ldi     ICPTemp,$000
                out     TCNT0,ICPTemp            ; Timer nullen
                sei                              ; Interupt wieder freigeben
                in      ICPTemp,TIFR
                sbrs    ICPTemp,TOV0             ; šberlauf erfolgt ?
                rjmp    ICP_Int1                 ; nein, dann normal weiter
; RC5 zurücksetzen,wegen Zeitüberschreitung
                clr     RC5Adr                   ; RC5-Adresse=0
                clr     RC5Dat                   ; RC5-Datum  =0
                clr     RC5Cnt                   ; RC5-Counter=0 -> neustart Empfang
                ldi     ICPTemp,(1<<TOV0)        ; TOV0-Flag
                out     TIFR,ICPTemp             ; TOV0-Flag l”schen
                ldi     ICPTime,25               ; Zeit=1 Halbbit

ICP_Int1:       out     SREG,ICPHelp             ; Flags restoren
                sbrc    RC5Cnt,7                 ; RC5-Empfang gestoppt ?
                reti                             ; ja -> Ende

                cpi     ICPTime,20               ; Zeit < 1 Halbbit ?
                brlo    ICP_IntError             ; ja -> Fehler bei Halbbitlänge
                cpi     ICPTime,33               ; Zeit > 1 Halbbit ?
                brge    ICP_Int2                 ; ja -> 2 Bit möglich
; 1 Halbbit eintragen
                rcall   Save_Bit                 ; Halbbit eintragen
                brcs    ICP_IntError             ; Protokollfehler ?
                out     SREG,ICPHelp             ; Flags restoren
                reti

ICP_Int2:       cpi     ICPTime,41               ; Zeit < 2 Halbbit ?
                brlo    ICP_IntError             ; ja -> Fehler bei Halbbitlänge
                cpi     ICPTime,62               ; Zeit > 2 Halbbit ?
                brge    ICP_IntError             ; ja -> Fehler bei Halbbitlänge
; 2 Halbbits eintragen
                rcall   Save_Bit                 ; Halbbit eintragen
                brcs    ICP_IntError             ; Protokollfehler ?
                rcall   Save_Bit                 ; Halbbit eintragen
                brcs    ICP_IntError             ; Protokollfehler ?
                out     SREG,ICPHelp             ; Flags restoren
                reti

ICP_IntError:   ldi     RC5Cnt,$0FF              ; RC5-Empfang stoppen
                out     SREG,ICPHelp             ; Flags restoren
                reti

Save_Bit:       in      ICPTemp,TCCR1B           ; High/Low Bit - IR-Leitung puffern
                com     ICPTemp                  ; richtige Polung
                bst     ICPTemp,ICES1            ; IR-Leitung ins T-Flag
                inc     RC5Cnt                   ; ein Halbbit mehr
                sbrc    RC5Cnt,0                 ; ungerader Count ? -> neues Bit
                rjmp    Store_Bit                ; nur Halbbit -> speichern im Counter
                bld     ICPTemp,6                ; IR-Leitung nach Bit 6
                eor     ICPTemp,RC5Cnt           ; sind Halbbits verschieden ?
                andi    ICPTemp,(1<<6)           ; nur Ergebnis
                breq    RC5_Error                ; Fehler : Halbbits waren gleich
                cpi     RC5Cnt,$042              ; Startbit 1 nicht high ?
                breq    RC5_Error                ; Fehler : Startbit 1 falsch
                cpi     RC5Cnt,$044              ; Startbit 2 nicht high ?
                breq    RC5_Error                ; Fehler : Startbit 2 falsch
                bld     ICPTemp,7                ; Halbbit nach Bit 7
                rol     ICPTemp                  ; ins Carry rollen
                rol     RC5Dat                   ; ins Datum rollen
                rol     RC5Adr                   ; šbertrag rollen
                cpi     RC5Cnt,$01c              ; RC5_Code komplett ? (01 am Ende)
                breq    RC5_Ende1
                cpi     RC5Cnt,$05c              ; RC5_Code zu lang ?
                breq    RC5_Error
                clc                              ; kein Fehler aufgetreten
                ret

Store_Bit:      bld     RC5Cnt,6                 ; Halbbit im Counter Bit 6 ablegen
                cpi     RC5Cnt,$05b              ; RC5_Code komplett ? (10 am Ende)
                breq    RC5_Ende0
                cpi     RC5Cnt,$01d              ; RC5_Code zu lang ?
                breq    RC5_Error
                cpi     RC5Cnt,$05d              ; RC5_Code zu lang ?
                breq    RC5_Error
                clc                              ; kein Fehler aufgetreten
                ret

RC5_Error:      sec                              ; Protokollfehler
                ret

RC5_Ende0:      clc                              ; BIT ist 0 ins Carry
                rol     RC5Dat                   ; ins Datum rollen
                rol     RC5Adr                   ; šbertrag rollen
RC5_Ende1:      mov     Puffer_RC5Dat,RC5Dat     ; ja -> Empfang signalisieren + Puffern
                rol     RC5Dat
                rol     RC5Adr
                rol     RC5Dat
                rol     RC5Adr
                bst     RC5Adr,5
                bld     Puffer_RC5Dat,6
                andi    RC5Adr,$01f
                mov     Puffer_RC5Adr,RC5Adr
                set
                cpse    Puffer_RC5Adr,RC5_SollAdr
                clt
                bld     Puffer_RC5Dat,7
                sbr     Status,(1<<EMPFANG)
                rcall   Set_INT                  ; Im ENHANCED-INT-MODE Int setzen
                sec                              ; RC5-Empfang komplett -> stoppen
                ret

;*********************************************************************
;  Initialisierungsroutine
;*********************************************************************

i2c_hp_delay:
		     push i2cdelay
                     ldi i2cdelay,2
i2c_hp_delay_loop:
	             dec i2cdelay
                     brne i2c_hp_delay_loop
		     pop i2cdelay
                     ret
i2c_qp_delay:
		     push i2cdelay
                     ldi i2cdelay,1	
                     i2c_qp_delay_loop:
	             dec i2cdelay
	             brne i2c_qp_delay_loop
		     pop i2cdelay
	             ret

i2c_start:				
	             mov i2cdata,i2cadr		; copy address to transmitt register
		     cbi PORTD,SDAP
	             sbi DDRD,SDAP		; force SDA low
	             rcall i2c_qp_delay		; quarter period delay
i2c_write:
                     sec			; set carry flag
	             rol i2cdata		; shift in carry and out bit one
	             rjmp i2c_write_first
i2c_write_bit:
                     lsl i2cdata		; if transmit register empty
i2c_write_first:
	             breq i2c_get_ack		; goto get acknowledge
		     cbi PORTD,SCLP	
                     sbi DDRD,SCLP		; force SCL low
                     brcc i2c_write_low		; if bit high
	             nop			; (equalize number o
                     cbi DDRD,SDAP		; release SDA
		     sbi PORTD,SDAP
                     rjmp i2c_write_high
i2c_write_low:					; else
		     cbi PORTD,SDAP
                     sbi DDRD,SDAP		; force SDA low
                     rjmp i2c_write_high        ;  (equalize number of cycles)
i2c_write_high:
                     rcall i2c_hp_delay		; half period delay
	             cbi DDRD,SCLP		; release SCL
		     sbi PORTD,SCLP
                     rcall i2c_hp_delay		; half period delay
                     rjmp i2c_write_bit

i2c_get_ack:
		     cbi PORTD,SCLP
                     sbi DDRD,SCLP		; force SCL low
		     cbi DDRD,SDAP              ; release SDA
		     sbi PORTD,SDAP
	             rcall i2c_hp_delay		; half period delay
                     cbi DDRD,SCLP		; release SCL
		     sbi PORTD,SCLP

i2c_get_ack_wait:
                     sbis PIND,SCLP		; wait SCL high 
		     rjmp i2c_get_ack_wait
                     clc			; clear carry flag
	             sbic PIND,SDAP		; if SDA is high
                     sec                        ; set carry flag
                     rcall i2c_hp_delay		; half period delay
                     ret

i2c_do_transfer:
                     rjmp i2c_write		; goto write data
                     
i2c_stop:
		     cbi PORTD,SCLP
                     sbi DDRD,SCLP		; force SCL low
		     cbi PORTD,SDAP
                     sbi DDRD,SDAP		; force SDA low
                     rcall i2c_hp_delay		; half period delay
                     cbi DDRD,SCLP		; release SCL
		     sbi PORTD,SCLP
                     rcall i2c_qp_delay		; quarter period delay
                     cbi DDRD,SDAP		; release SDA
		     sbi PORTD,SDAP
                     rcall i2c_hp_delay		; half period delay
                     ret


i2c_init:
                   ; clr i2cstat		; clear I2C status register (used
                                              	; as a temporary register)
                   ; out PORTD,i2cstat		; set I2C pins to open colector
	           ; out DDRD,i2cstat
								
                     cbi DDRD, SCLP
		     cbi DDRD, SDAP
                     sbi PORTD, SCLP
		     sbi PORTD, SDAP
	             ret

Patch:                                                                                
		
                ldi     Temp,RAMEND & $FF
                out     SPL,Temp
                ldi     Temp,(RAMEND>>8)
                out     SPH,Temp
		rcall Port_Setting
		
            


 

;*********************************************************************
;  Interrupt - Settings
;*********************************************************************
; Puffer-MAS
                ldi     XL,$060                  ; Zeiger auf Puffer-Anfang
                clr     XH                       ; High-Byte immer 0
                ldi     YL,$060                  ; Zeiger auf Puffer-Anfang
                clr     YH                       ; High-Byte immer 0
                clr     Puffer

; SPI ( MAS-Datensendung )
                ldi     Temp,(1<<SPIE) + (1<<SPR0) + (1<<CPOL)
                out     SPCR,Temp                ; SPI initialisieren
                in      Temp,SPSR                ; Clear Flags

; Int0 / Int1 ( Demand / Strobe )
                ldi     Temp,(1<<ISC00) + (1<<ISC01) + (1<<ISC11)
                out     MCUCR,Temp               ; Falling Edge DEMAND / STROBE
                ldi     Temp,(1<<INT0) + (1<<INT1)         ; Int0 / Int1 Enable
                out     GIMSK,Temp

; Timer 0 / Tastatur

                ldi     Temp,(1<<CS12)
                out     TCCR0,Temp               ; 256-Teiler

; Timer 1 / ICP( RC5-Empfang )
                ldi     RC5Cnt,$0FF              ; RC5-gestoppt

                ldi     Temp,(1<<CS10)
                out     TCCR1B,Temp              ; Int falling ICP-Pin / Kein Teiler
                ldi     Temp,(1<<TICIE1)+(1<<TOIE1)
                out     TIMSK,Temp               ; Int on ICP-Pin

                clr     Puffer_RC5Adr
                clr     Puffer_RC5Dat
                clr     RC5_SollAdr
                clr     Puffer_Tasten
                clr     DrehCount
                clr     ReadAdr
                clr     Status2


;   ldi Temp,$003
;   out UBRR,Temp ; 115200 Baud
;   ldi Temp,$008
;   out UCR,Temp  ; TX-Enable
;   ldi Temp,$041
;   rcall Senden

;*********************************************************************
;  Dislay-Init
;*********************************************************************
                sbi     EEARH,0
                ldi     Temp,$fd
                out     EEARL,Temp

                rcall   EE_ReadInit              ; Kontrast
                ldi     ZL,$00
                out     OCR1AH,ZL                ; $000=dunkel
                out     OCR1AL,Temp              ;>$080=kein

                rcall   EE_ReadInit              ; Licht
                ldi     ZL,$00
                clc
                sbrc    Temp,7
                sec
                rol     Temp
                rol     ZL
                out     OCR1BH,ZL                ; $1FF=an
                out     OCR1BL,Temp              ; $000=aus

                rcall   EE_ReadInit              ; Display-Init
                cpi     Temp,$00
                breq    InitEnde

                ldi     Temp,255    ; 4 ms + 11 ms TOUT = 15 ms Startup
                rcall   WaitInit
                ldi     Temp,118    ; 4.1 ms Startup
                rcall   WaitInit
                ldi     Temp,3      ; 100 us Startup
                rcall   WaitInit
                ldi     Temp,$038
                rcall   WriteLCD0
                ldi     Temp,$038
                rcall   WriteLCD0
                ldi     Temp,$006
                rcall   WriteLCD0
                ldi     Temp,$00C
                rcall   WriteLCD0
                ldi     Temp,$001
                rcall   WriteLCD0

                in      Temp,EEDR
                cpi     Temp,$0FF
                breq    InitEnde

                ldi     Temp,$000
                out     EEARH,Temp
                out     EEARL,Temp
                ldi     Temp,$040                ; CG-RAM
                rcall   WriteLCD0
                ldi     Temp,$040                ; 8 Sonderzeichen (64 Byte)
                rcall   SendDisplay
                ldi     Temp,$080                ; 1.Zeile
                rcall   WriteLCD0
                ldi     Temp,$010                ; 16 Zeichen
                rcall   SendDisplay
                ldi     Temp,$0C0                ; 2.Zeile
                rcall   WriteLCD0
                ldi     Temp,$010                ; 16 Zeichen
                rcall   SendDisplay
                ldi     Temp,$090                ; 3.Zeile
                rcall   WriteLCD0
                ldi     Temp,$010                ; 16 Zeichen
                rcall   SendDisplay
                ldi     Temp,$0D0                ; 4.Zeile
                rcall   WriteLCD0
                ldi     Temp,$010                ; 16 Zeichen
                rcall   SendDisplay

InitEnde:       ldi     Temp,$000
                mov     TastTemp,Temp
                rcall   Dreh_Input
                mov     DrehTemp,TOVTemp
                mov     Status,DrehTemp
                sbr     Status,(1<<LEER)         ; Puffer ist leer
                sbi     P_CLR,CLR                ; MAS-Reset Ende (high)
                

  


			push i2cadr
			push i2cdata						
			

                        cbi PortB,SCLK 

                        rcall     i2c_init		; initialize I2C interface
			
                        ldi       i2cadr,$3a+i2cwr	; Set device address and write
	                rcall	   i2c_start		; Send start condition and address
			ldi       i2cdata,$68		; Write word address (0x00)
	                rcall     i2c_do_transfer		; Execute transfer
                        ldi	   i2cdata,$93		; Set write data to 01010101b
	                rcall	   i2c_do_transfer		; Execute transfer
                        ldi	   i2cdata,$b0
                        rcall	   i2c_do_transfer
                        ldi	   i2cdata,$00
                        rcall     i2c_do_transfer
                        ldi       i2cdata,$02		; Set write data to 01010101b
	                rcall     i2c_do_transfer		; Execute transfer
                        rcall     i2c_stop		; Send stop condition

	

	

                        ldi       i2cadr,$3a+i2cwr	;
                        rcall     i2c_start		
                        ldi       i2cdata,$68		
                        rcall     i2c_do_transfer
                        ldi       i2cdata,$00		
	                rcall     i2c_do_transfer		
                        ldi       i2cdata,$01
	                rcall	   i2c_do_transfer
                        rcall     i2c_stop		; Send stop condition
	                

			sbi PortB,SCLK
 
                     
                	pop i2cdata
			pop i2cadr
                        
                     
		sei
                sbi     P_BUSY,BUSY
                sbi     P_INT,INT                ; Daten anfordern auf INT (low)




















;*********************************************************************
;  Hauptschleife - nix mehr
;*********************************************************************
Endlos:         rjmp    Endlos                   ; Warten bis schwarz geworden



;Senden:    sbis  USR,UDRE
;           rjmp  Senden
;           out   UDR,Temp
;           ret

;*********************************************************************
;  Display-Routinen
;*********************************************************************
Wait:           neg     Temp
                out     TCNT0,Temp
                ldi     Temp,(1<<TOV0)
                out     TIFR,Temp
Waiting:        in      Temp,TIFR
                sbrs    Temp,TOV0
                rjmp    Waiting
                ret


WaitInit:       rcall   Wait
                ldi     Temp,$38
                rjmp    WriteLCDinit

SendDisplay:    push    Temp
                rcall   EE_ReadInit
                rcall   WriteLCD1
                pop     Temp
                dec     Temp
                brne    SendDisplay
                ret

;*********************************************************************
;  EEprom-Routinen
;*********************************************************************
EE_Write:       sbi     EECR,EEMWE               ; Master Write Enable
                sbi     EECR,EEWE                ; Write Enable
EE_WriteWait:   sbic    EECR,EEWE
                rjmp    EE_WriteWait             ; warten
                ret

EE_WriteInc:    sbi     EECR,EEMWE               ; Master Write Enable
                sbi     EECR,EEWE                ; Write Enable
EE_WriteIncWait:sbic    EECR,EEWE
                rjmp    EE_WriteIncWait          ; warten
                rjmp    EE_IncAdr

EE_Read:        sbi     EECR,EERE                ; Read Enable
                in      PData,EEDR               ; Daten lesen
                ret
EE_ReadInc:     sbi     EECR,EERE                ; Read Enable
                in      PData,EEDR               ; Daten lesen
                rjmp    EE_IncAdr

EE_ReadInit:    sbi     EECR,EERE                ; Read Enable
                in      Temp,EEDR                ; Daten lesen
                rjmp    EE_IncAdr

EE_IncAdr:      in      ZL,EEARL                 ; Adresse laden
                in      ZH,EEARH                 ; Adresse laden
                adiw    ZL,$001                  ; increment
                out     EEARL,ZL                 ; Adresse setzen
                out     EEARH,ZH                 ; Adresse setzen
                ret

EE_DecAdr:      in      ZL,EEARL                 ; Adresse laden
                in      ZH,EEARH                 ; Adresse laden
                sbiw    ZL,$001                  ; decrement
                out     EEARL,ZL                 ; Adresse setzen
                out     EEARH,ZH                 ; Adresse setzen
                ret


