; TWI I2C SLAVE
; 10/2005
; Bernhard.Erfurt@gmx.de
;
; TAKT=1.0 MHZ
;
.include "m8def.inc"
; TWI Slave Receiver Codes
.equ TW_SR_SLA_ACK = 0x60; x60 01100000 (SLA+W wurde empfangen-ACK wurde zurückgesendet)
.equ TW_SR_ARB_LOST_SLA_ACK = 0x68; x68 01101000 (Arbitration verloren in SLA+R/W als MASTER; SLA+W wurde empfangen; ACK wurde zurückgesendet
.equ TW_SR_GCALL_ACK = 0x70; x70 01110000 (General call address wurde empfangen; ACK wurde zurückgesendet
.equ TW_SR_ARB_LOST_GCALL_ACK = 0x78; x78 01111000 (Arbitration verloren in SLA+R/W als MASTER;General call address wurde empfangen; ACK wurde zurückgesendet
.equ TW_SR_DATA_ACK = 0x80; x80 10000000 (die vorher adressierten (SLA+W) Daten wurden empfangen; ACK wurde zurückgesendet
.equ TW_SR_DATA_NACK = 0x88; x88 10001000 (die vorher adressierten (SLA+W) Daten wurden empfangen; ACK wurde nicht zurückgesedet
.equ TW_SR_GCALL_DATA_ACK = 0x90; x90 10010000 (die vorher adressierten (General call) Daten wurden empfangen; ACK wurde zurückgesendet
.equ TW_SR_GCALL_DATA_NACK = 0x98; x98 10011000 (die vorher adressierten (General call) Daten wurden empfangen; ACK wurde nicht zurückgesendet
.equ TW_SR_STOP = 0xA0; xA0 10100000 (STOP wurde empfangen, oder wiederholter Start)
; TWI Slave Transmitter Codes
.equ TW_ST_SLA_ACK = 0xA8; xA8 10101000 (SLA+R wurde empfangen; ACK wurde zurückgesendet)
.equ TW_ST_ARB_LOST_SLA_ACK = 0xB0; xB0 10110000 (Arbitration verlor SLA+R/W als MASTER, ACK wurde zurückgesendet)
.equ TW_ST_DATA_ACK = 0xB8; xB8 10111000 (TWDR ist übertragen worden; ACK ist empfangen worden
.equ TW_ST_DATA_NACK = 0xC0; xC0 11000000 (TWDR ist übertragen worden; ACK ist NICHT empfangen worden
.equ TW_ST_LAST_DATA = 0xC8; xC8 11001000 (Letztes Datenbyte in TWDR ist übertragen worden (TWEA = "0"); Ack ist empfangen worden
.equ TW_NO_INFO = 0xF8; xF8 11111000 (Keine relevanten Zustandinformationen vorhanden; TWINT = "0" keine TWDR-Tätigkeit
.equ TW_BUS_ERROR = 0x00; x00 00000000 (Bus-Error wegen ungültige STARToder STOP BEDIgung; keine TWDR-Tätigkeit
; TWI SLAVE EINSTELLUNGEN
.equ TWI_SLAVE_ADRESSE = 0x40; eigene SLAVE ADRESSE 1...127
.equ TWI_GENERAL_CALL_enable = 1 ; 1=General Call enabled / 0=disabled
; REGISTER
.def DATA=R15
.def TEMP = R16
.def TEMP1= R17
.def TEMP2= R18
.def TEMP3= R19
.def TEMP4= R20
.cseg ;Beginn eines Code-Segmentes
.org 0 ;Startadresse=0
rjmp RESET ; Reset Handler
reti ;rjmp EXT_INT0 ; IRQ0 Handler
reti ;rjmp EXT_INT1 ; IRQ1 Handler
reti ;rjmp TIM2_COMP ; Timer2 Compare Handler
reti ;rjmp TIM2_OVF ; Timer2 Overflow Handler
reti ;rjmp TIM1_CAPT ; Timer1 Capture Handler
reti ;rjmp TIM1_COMPA ; Timer1 CompareA Handler
reti ;rjmp TIM1_COMPB ; Timer1 CompareB Handler
reti ;rjmp TIM1_OVF ; Timer1 Overflow Handler
reti ;rjmp TIM0_OVF ; Timer0 Overflow Handler
reti ;rjmp SPI_STC ; SPI Transfer Complete Handler
reti ;rjmp USART_RXC ; USART RX Complete Handler
reti ;rjmp USART_UDRE ; UDR Empty Handler
reti ;rjmp USART_TXC ; USART TX Complete Handler
reti ;rjmp ADC ; ADC Conversion Complete Handler
reti ;rjmp EE_RDY ; EEPROM Ready Handler
reti ;rjmp ANA_COMP ; Analog Comparator Handler
rjmp TWSI ; Two-wire Serial Interface Handler
reti ;rjmp SPM_RDY ; Store Program Memory Ready Handler
RESET:
;STACK initialisieren
ldi temp, LOW(RAMEND)
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
; PORT D all Output
ldi temp, 0b11111111
out DDRD, temp
out PORTD,temp
; PORT C all input, except C3 (=Error Indicator)
ldi temp, 0b00001000
out DDRC,temp
sbi PORTC,3
; TWI INITIALISIERUNG
rcall TWI_INI
; STARTWERTE
clr DATA
; alle Interrupts freigeben
sei
LOOP:
rjmp LOOP
; #############################################################################
; TWI INTERRUPT-Routine
TWSI:
push temp ; temp auf dem Stack sichern
in TEMP,SREG ; Einlesen des SREG
push TEMP ; Schreiben von SREG im Stack (KOPIE)
;-------
in temp, TWSR ; Status-Register abfragen
andi temp, 0xF8 ; mask Bit0...2 (Prescaler und Reserve-Bit)
ldi temp1, 170
out PORTD,temp1 ; show start pattern (10101010)
rcall wait_1s
out PORTD,temp ; show TWSR
rcall wait_1s
rcall wait_1s
rcall wait_1s
ldi temp1, 255
out PORTD,temp1 ; turn off all LED
cpi temp, TW_SR_SLA_ACK ; x60
breq TWSI_TW_SR_SLA_ACK
cpi temp, TW_SR_ARB_LOST_SLA_ACK ; x68
breq TWSI_TW_SR_ARB_LOST_SLA_ACK
cpi temp, TW_SR_GCALL_ACK ; x70
breq TWSI_TW_SR_GCALL_ACK
cpi temp, TW_SR_ARB_LOST_GCALL_ACK ; x78
breq TWSI_TW_SR_ARB_LOST_GCALL_ACK
cpi temp, TW_SR_DATA_ACK ; x80
breq TWSI_TW_SR_DATA_ACK
cpi temp, TW_SR_DATA_NACK ; x88
breq TWSI_TW_SR_DATA_NACK
cpi temp, TW_SR_GCALL_DATA_ACK ; x90
breq TWSI_TW_SR_GCALL_DATA_ACK
cpi temp, TW_SR_GCALL_DATA_NACK ; x98
breq TWSI_TW_SR_GCALL_DATA_NACK
cpi temp, TW_SR_STOP ; xA0
breq TWSI_TW_SR_STOP
;
ldi temp1, 85
out PORTD,temp1 ; show transmitter pattern (01010101)
rcall wait_1s
ldi temp1, 255
out PORTD,temp1 ; turn off all LED
cpi temp, TW_ST_SLA_ACK ; 0xA8
breq TWSI_TW_ST_SLA_ACK
cpi temp, TW_ST_ARB_LOST_SLA_ACK ; 0xB0
breq TWSI_TW_ST_ARB_LOST_SLA_ACK
cpi temp, TW_ST_DATA_ACK ; 0xB8
breq TWSI_TW_ST_DATA_ACK
cpi temp, TW_ST_DATA_NACK ; 0xC0
breq TWSI_TW_ST_DATA_NACK
cpi temp, TW_ST_LAST_DATA ; 0xC8
breq TWSI_TW_ST_LAST_DATA
cpi temp, TW_NO_INFO ; 0xF8
breq TWSI_TW_NO_INFO
cpi temp, TW_BUS_ERROR ; 0x00
breq TWSI_TW_BUS_ERROR
rjmp TWSI_TW_BUS_ERROR ; nicht behandelte Status-Zustände
; SLAVE RECEIVER
TWSI_TW_SR_SLA_ACK: ; x60 01100000 (SLA+W wurde empfangen-ACK wurde zurückgesendet)
cbi PORTD,0
rjmp TWSI_w
TWSI_TW_SR_ARB_LOST_SLA_ACK: ; x68 01101000 (Arbitration verloren in SLA+R/W als MASTER; SLA+W wurde empfangen; ACK wurde zurückgesendet
cbi PORTD,1
rjmp TWSI_w
TWSI_TW_SR_GCALL_ACK: ; x70 01110000 (General call address wurde empfangen; ACK wurde zurückgesendet
cbi PORTD,2
rjmp TWSI_w
TWSI_TW_SR_ARB_LOST_GCALL_ACK: ; x78 01111000 (Arbitration verloren in SLA+R/W als MASTER;General call address wurde empfangen; ACK wurde zurückgesendet
cbi PORTD,3
rjmp TWSI_w
TWSI_TW_SR_DATA_ACK: ; x80 10000000 (die vorher adressierten (SLA+W) Daten wurden empfangen; ACK wurde zurückgesendet
cbi PORTD,4
in DATA, TWDR ; DATA
rjmp TWSI_w
TWSI_TW_SR_DATA_NACK: ; x88 10001000 (die vorher adressierten (SLA+W) Daten wurden empfangen; ACK wurde nicht zurückgesedet
cbi PORTD,5
rjmp TWSI_w
TWSI_TW_SR_GCALL_DATA_ACK: ; x90 10010000 (die vorher adressierten (General call) Daten wurden empfangen; ACK wurde zurückgesendet
cbi PORTD,6
rjmp TWSI_w
TWSI_TW_SR_GCALL_DATA_NACK: ; x98 10011000 (die vorher adressierten (General call) Daten wurden empfangen; ACK wurde nicht zurückgesendet
cbi PORTD,7
rjmp TWSI_w
TWSI_TW_SR_STOP: ; xA0 10100000 (STOP wurde empfangen, oder wiederholter Start)
cbi PORTD,0
cbi PORTD,1
rjmp TWSI_w
; SLAVE TRANSMITTER
TWSI_TW_ST_SLA_ACK: ; xA8 10101000 (SLA+R wurde empfangen; ACK wurde zurückgesendet)
cbi PORTD,0
OUT TWDR, DATA ; DATA
rjmp TWSI_w
TWSI_TW_ST_ARB_LOST_SLA_ACK: ; xB0 10110000 (Arbitration verlor SLA+R/W als MASTER, ACK wurde zurückgesendet)
cbi PORTD,1
rjmp TWSI_w
TWSI_TW_ST_DATA_ACK: ; xB8 10111000 (TWDR ist übertragen worden; ACK ist empfangen worden
cbi PORTD,2
OUT TWDR, DATA ; DATA
rjmp TWSI_w
TWSI_TW_ST_DATA_NACK: ; xC0 11000000 (TWDR ist übertragen worden; ACK ist NICHT empfangen worden
cbi PORTD,3
OUT TWDR, DATA ; DATA
rjmp TWSI_w
TWSI_TW_ST_LAST_DATA: ; xC8 11001000 (Letztes Datenbyte in TWDR ist übertragen worden (TWEA = "0"); Ack ist empfangen worden
cbi PORTD,4
rjmp TWSI_w
TWSI_TW_NO_INFO: ; xF8 11111000 (Keine relevanten Zustandinformationen vorhanden; TWINT = "0" keine TWDR-Tätigkeit
cbi PORTD,5
rjmp TWSI_w
TWSI_TW_BUS_ERROR: ; x00 00000000 (Bus-Error wegen ungültige STARToder STOP BEDIgung; keine TWDR-Tätigkeit
rcall TWI_ERROR
rjmp TWSI_w
;-------
TWSI_w:
;clear TWINT-Flag ((logisch 1)
ldi temp, 1<<TWINT|1<<TWEA|1<<TWEN|1<<TWIE
out TWCR,temp
pop TEMP ; LESEN von SREG vom STACK (KOPIE)
out SREG,TEMP ; Wiederherstellen von SREG
pop temp ; temp wiederherstellen
reti
; #############################################################################
TWI_INI:
; TWI TWAR (nur SLAVE) Adress-Register
ldi temp,(TWI_SLAVE_ADRESSE<<TWA0 | TWI_GENERAL_CALL_ENABLE<<TWGCE)
out TWAR,temp
; TWI TWCR Control-REGISTER
ldi temp,(1<<TWINT|1<<TWEA|0<<TWSTA|0<<TWSTO|0<<TWWC|1<<TWEN|1<<TWIE)
out TWCR,temp
ret
; #############################################################################
TWI_ERROR:
cbi PORTC,3
; TWI STOP
ldi r16, (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
out TWCR, r16
; TWI aus
ldi r16, (0<<TWEN)
out TWCR, r16
; TWI INITIALISIERUNG
rcall TWI_INI
rcall wait_1s
sbi PORTC,3
ret
; #############################################################################
; Wait for TWINT Flag set.
TWI_TWINT_wait:
in temp, TWCR
sbrs temp, TWINT
rjmp TWI_TWINT_wait
ret
; #############################################################################
WAIT_1s:
push temp1 ; temp1 auf dem Stack sichern
push temp2 ; temp2 auf dem Stack sichern
push temp3 ; temp3 auf dem Stack sichern
;------------
ldi temp3,31 ;1MHz=5, 6=31, 8=41
clr temp2
clr temp1
wait1s_w:
dec temp1
brne wait1s_w
dec temp2
brne wait1s_w
dec temp3
brne wait1s_w
;------------
pop temp3 ; temp3 wiederherstellen
pop temp2 ; temp2 wiederherstellen
pop temp1 ; temp1 wiederherstellen
ret