;*************************************************************************** ; ; File Name :'twi.asm" ; Title : I2C (TWI) Hardware ; Date :2003.04.29. Lastmod.:[2003.04.29.] ; Version :1.0.0 ; Support telephone :+36-70-333-4034, Old: +36-30-9541-658 VFX ; Support fax : ; Support Email :info@vfx.hu ; Target MCU :ATmaga8 ; ;*************************************************************************** ; D E S C R I P T I O N ; ; ; ;*************************************************************************** ; M O D I F I C A T I O N H I S T O R Y ; ; ; rev. date who why ; ---- ---------- --- -------------------------------------------- ; 0.01 2003.04.29 VFX Creation ; ;*************************************************************************** ; ; ; ;Hardware ;*************************************************************************** ;* ;************************************************************************** ;* Const Def ; ;Bit Rate Generator in Master Mode ;TWBR = Value of the TWI Bit Rate Register ;TWPS = Value of the prescaler bits in the TWI Status Register ; ;Note: TWBR should be 10 or higher if the TWI operates in Master mode. ; If TWBR is lower than 10, the master may produce an incorrect output on SDA ; and SCL for the reminder of the byte. ; ; SCL = SYSCLK/(16+2*TWBR*4^TWPS) , TWPS= 0..3, TWBR= 0..255 ; ; we use 100kHz I2C Bus & TWPS = 0, always for LOW Power .EQU SCL_Freq = 100000 ;Hz .EQU TWI_SlaveAddress = 0xFE ;Slave Address is FECO :) .equ TWI_WriteByte = 0x00 ;Send Byte .equ TWI_WriteRAW = 0x01 ;Send Blokk of data .equ TWI_ReadByte = 0x02 ;Read Byte .equ TWI_ReadRAW = 0x03 ;Read Block of data ;*************************************************************************** .DSEG TWI_CTL: .byte 2 ;Address of TWI IO Control Blokk TWI_Count: .byte 1 ;Byte counter for TWI TWI_Slave: .byte 1 ;Slave Address TWI_ADR: .byte 1 ;Slave internal Address TWI_Flag: .byte 1 ;0. = 1 TWI in use TWI_SADR: .byte 2 ;TWI State Machin Address ;************************************************************************* ;* Code ;* .CSEG ;************************************************************************* ;* Init TWI Device, Clear TWI_CTL ; TWI_Init: ldi R16,Low(TWIRET) sts TWI_SADR+0,R16 ldi R16,High(TWIRET) sts TWI_SADR+1,R16 ldi R16,SYSCLK/(2*SCL_Freq)-8 ;TWI Bit Rate Register - TWBR out TWBR,R16 ldi R16,0b00000101 ;TWI Control Register – TWCR out TWCR,R16 ;7 – TWINT: TWI Interrupt Flag ;6 – TWEA: TWI Enable Acknowledge ;5 – TWSTA: TWI START Condition ;4 – TWSTO: TWI STOP Condition ;3 - TWWC: TWI Write Collision Flag ;2 – TWEN: TWI Enable ;1 – Res: Reserved Bit ;0 – TWIE: TWI Interrupt Enable ldi R16,0b11111000 ;TWI Status Register – TWSR out TWSR,R16 ;7..3 – TWS: TWI Status ;2 – Res: Reserved Bit ;1..0 – TWPS: TWI Prescaler Bits ldi R16,TWI_SlaveAddress ;TWI (Slave) Address Register out TWAR,R16 clr R16 sts TWI_Flag,R16 ret ;************************************************************************* ;* Start TWI Comunication in Master Mode ; In: X - Address of IO_CTR Block ; ; R17 - count of byte ; R18 - Slave Address ; R19 - Internal Address of Slave ; Out: c = 1 error ; TWI_StartRead: rcall WaitToTWI ldi R16,Low(RBlock0) sts TWI_SADR+0,R16 ldi R16,High(RBlock0) sts TWI_SADR+1,R16 TWI_Common: sts TWI_CTL+0,XL sts TWI_CTL+1,XH sts TWI_Count,R17 sts TWI_Slave,R18 sts TWI_ADR,R19 lds R16,TWI_Flag ori R16,1 ;TWI in use! andi R16,0b11111101 ;TWI no error sts TWI_Flag,R16 ldi R16,0b11100101 out TWCR,R16 ;7 – TWINT: TWI Interrupt Flag ;6 – TWEA: TWI Enable Acknowledge ;5 – TWSTA: TWI START Condition ;4 – TWSTO: TWI STOP Condition ;3 – TWWC: TWI Write Collision ;2 – TWEN: TWI Enable ;1 – Res: Reserved ;0 – TWIE: TWI Interrupt Enable TWIRET: ret ;************************************************************************* ;* Start TWI Comunication in Master Mode - Write! ; In: X - Address of IO_CTR Block ; R17 - count of byte ; R18 - Slave Address ; R19 - Internal Address of Slave ; Out: c = 1 error ; TWI_StartWrite: rcall WaitToTWI ldi R16,Low(WBlock0) sts TWI_SADR+0,R16 ldi R16,High(WBlock0) sts TWI_SADR+1,R16 rjmp TWI_Common ;************************************************************************* ;* TWI interrupt ;* TWI: ; Two-wire Serial Interface Interrupt Handler push ZL push ZH in ZL,SREG ;preserve main OS status reg. push ZL push R16 push R0 push R17 ; cbi GreenLED_PORT,GreenLED ;LED in R16,TWSR ;Load TWI Status andi R16,0b11111000 ;csak a status marad lds ZL,TWI_SADR+0 lds ZH,TWI_SADR+1 icall pop R17 POP R0 POP R16 POP ZL OUT SREG,ZL POP ZH POP ZL RETI ;************************************************************************************************************ ;*** R E A D B L O C K ;*** ; ;*********************** ; Read Block of data - State 0 ; Start bit sended RBlock0: cpi R16,0x08 ;A START condition has been transmitted breq Rbl0 cpi R16,0x10 ;A Repeated START condition has been transmitted breq Rbl0 rjmp TWI_ReadError Rbl0: lds R16,TWI_Slave andi R16,0b11111110 ;Write SLA out TWDR,R16 ;Send Slave Address ldi R16,Low(RBlock1) sts TWI_SADR+0,R16 ldi R16,High(RBlock1) sts TWI_SADR+1,R16 ldi R16,(1< Send slave internal address RBlock1: cpi R16,0x18 ;SLA+W has been transmitted breq RBl1 rjmp TWI_ReadError RBl1: lds R16,TWI_ADR out TWDR,R16 ;Send Slave Internal Address ldi R16,Low(RBlock2) sts TWI_SADR+0,R16 ldi R16,High(RBlock2) sts TWI_SADR+1,R16 ldi R16,(1< Repeated Satrt send RBlock2: cpi R16,0x28 ;SlaveAddress sended + ACK received breq Rbl21 rjmp TWI_ReadError Rbl21: ldi R16,Low(RBlock3) sts TWI_SADR+0,R16 ldi R16,High(RBlock3) sts TWI_SADR+1,R16 ldi R16,(1< Send SLA+R RBlock3: cpi R16,0x10 ;Repeated Start sended + ACK received breq RBl31 rjmp TWI_ReadError RBl31: lds R16,TWI_Slave ori R16,1 ;Write SLA+R out TWDR,R16 ;Send Slave Address ldi R16,Low(RBlock4) sts TWI_SADR+0,R16 ldi R16,High(RBlock4) sts TWI_SADR+1,R16 ldi R16,(1< Read data byte RBlock4: cpi R16,0x40 ;SLA+R send + ACK received brne TWI_ReadError lds R16,TWI_Count cpi R16,1 breq TWILAstByte ldi R16,Low(RBlock5) sts TWI_SADR+0,R16 ldi R16,High(RBlock5) sts TWI_SADR+1,R16 ldi R16,(1< Send slave internal address WBlock1: cpi R16,0x18 ;SLA+W has been transmitted breq WBl1 rjmp TWI_WriteError WBl1: lds R16,TWI_ADR out TWDR,R16 ;Send Slave Internal Address ldi R16,Low(WBlock2) sts TWI_SADR+0,R16 ldi R16,High(WBlock2) sts TWI_SADR+1,R16 ldi R16,(1< Write data WBlock2: cpi R16,0x28 ;Data byte has been transmitted + ACK received breq WB12 rjmp TWI_WriteError WB12: ;Send data byte continous lds ZL,TWI_CTL+0 lds ZH,TWI_CTL+1 ld R0,Z+ out TWDR,R0 ;next data byte sts TWI_CTL+0,ZL sts TWI_CTL+1,ZH lds R16,TWI_Count cpi R16,1 breq TWI_WriteLastByte dec R16 sts TWI_Count,R16 ldi R16,(1<