;-----------------------------------------------------------------
; Name:			128 TWI.asm
; Description:	ATMega128 Two Wire Interface (IC2) Test Program
;				Interfaces SRF09 Sonar Range Finder to IC2 Bus

; Author:		Max Koessick
; Class:		EEL5666C, Intelligent Machine Design Lab
; Date:			June 28, 2003
; Revision		1.a
; Changes to Date:
;				6/28/03 First Revision
;-----------------------------------------------------------------

.nolist								; Do not include in .lst file
.include "m128def.inc"				; Standard ATMega128 Include File
.list
; Interrupt service vectors

.org $0000
	rjmp Reset						; Reset vector
;.org INT0addr
;	rjmp IntV0						; INT0 vector (ext. interrupt from pin D0)	
;.org INT1addr	
;	rjmp IntV1						; INT1 vector (ext. interrupt from pin D1)
;.org INT2addr		
;	rjmp IntV2						; INT2 vector (ext. interrupt from pin D2)


	
;-----------------------------------------------------------------
; Register defines for main loop
;-----------------------------------------------------------------


.def		mpr		=r16			; defines multipurpose register
.def		mpr2	=r17			; multipurpose register 2
.def		ECHOL	=r18
.def		ECHOH	=r19


; Equate statements
.equ		start		= $08		; Start Condition 
.equ		Rep_start	= $10		; Repeated Start Condition Message
.equ		MT_SLA_ACK	= $18		; Master Transmitter Slave Address Acknowledge
.equ		MT_DATA_ACK = $28		; Master Transmitter Data Acknowledge
.equ		MR_SLA_ACK	= $40		; Master Receiver Slave Address Acknowledge
.equ		MR_DATA_ACK = $50		; Master Receiver Data Acknowlede
.equ		MR_DATA_NACK= $58		; Master Receiver Data Not Acknowledge
.equ		W			= 0			; Write Bit
.equ		R			= 1			; Read Bit
.equ		SLA			= $E0		; Slave Address of Sonar Ranger SRF08
.equ		Inches		= $50		; Return result in Inches
.equ		CommandReg	= $00		; SRF08 Command Register
;-----------------------------------------------------------------
; Reset vector
;-----------------------------------------------------------------

Reset:
;-----Setting Stackpointer----------------------------------------
	ldi		MPR,low(RAMEND)			; Set stackptr to ram end
	out		SPL,MPR
	ldi 	MPR, high(RAMEND)
	out 	SPH, MPR

;-----Set Port Directions-----------------------------------------
	ser		mpr						; Set TEMP to $FF to...

	out 	DDRC,mpr
	ser		mpr
	out		PORTC,mpr				; Lights off

	clr		mpr
	ldi		mpr2,(1<<PD0)+(1<<PD1)
									; Define pull ups on the input pins of PORTD
	out 	DDRD,mpr				; Set 'D' as input
	out		PORTD,mpr2
;-----------------------------------------------------------------


	

	clr		XH						; Set TWI precaler for fclk=16Mhz

	ldi		XL,TWBR
	ldi		mpr,$ff
	st		X,mpr

; Set offset for acess to 3 main TWI Registers: 
;									TWCR: Control Register-> X Pointer
;									TWDR: Data Register	  -> Y Pointer
;									TWSR: Status Register -> Z Pointer
; Load these pointers once, so don't have to repeately initialize
	clr		YH
	clr		ZH
	ldi		XL,TWCR
	ldi		YL,TWDR
	ldi		ZL,TWSR

;	sei								; set interrupts active
			
; **MASTER TRANSMITTER*****

; The Slave being addressed has address 0xE0. 



	ldi 		MPR, (1<<TWSTA) | (1<<TWEN)
	st	 		X,MPR 				; Send START condition


wait1: 
	ld 			MPR,X 				; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; the START condition has been transmitted
	rjmp 		wait1

	ld 			MPR,Z 				; Check value of TWI Status Register.
	cpi 		MPR,START 			; If status different from START go to ERROR
	breq		NEXT1
	jmp			ERROR	
next1:
	ldi 		MPR,SLA+W			; Load SLA+W into TWDR Register
	st	 		Y,MPR
	ldi 		MPR,(1<<TWINT) | (1<<TWEN)
	st	 		X,MPR 				; Clear TWINT bit in TWCR to start transmission
									; of address
wait2: 
	ld 			MPR,X 				; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; SLA+W has been transmitted, and ACK/NACK has
	rjmp 		wait2 				; been received

	ld 			MPR,Z 				; Check value of TWI Status Register. If status
	cpi 		MPR,MT_SLA_ACK 		; different from MT_SLA_ACK, go to ERROR
	breq		NEXT2
	jmp			ERROR
next2:
	ldi 		MPR,CommandReg 		; Load data (CommandReg Address) into TWDR
									; Register
	st 			Y,MPR
	ldi 		MPR,(1<<TWINT) | (1<<TWEN)
	st 			X,MPR 				; Clear TWINT bit in TWCR to start transmission
									; of data
wait3: 

	ld 			MPR,X 				; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; data has been transmitted, and ACK/NACK has
	rjmp 		wait3 				; been received

	ld 			MPR,Z 				; Check value of TWI Status Register. If status
	cpi 		MPR,MT_DATA_ACK 	; different from MT_DATA_ACK, go to ERROR
	breq		NEXT3
	jmp			ERROR
NEXT3:
	ldi			MPR,Inches 			; Load data (Inches = $50) into TWDR
									; Register
	st	 		Y,MPR

	ldi 		MPR,(1<<TWINT) | (1<<TWEN)
	st	 		X,MPR 				; Clear TWINT bit in TWCR to start transmission
									; of data

wait4: 

	ld 			MPR,X 				; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; data has been transmitted, and ACK/NACK has
	rjmp 		wait4 				; been received

	ld 			MPR,Z 				; Check value of TWI Status Register. If status
	cpi 		MPR,MT_DATA_ACK 	; different from MT_DATA_ACK, go to ERROR
	brne 		ERROR
	ldi			MPR,$03 			; Load data (Register 2, Echo 1, low byte) into TWDR
									; Register
	st	 		Y,MPR

	ldi 		MPR,(1<<TWINT) | (1<<TWEN)
	st	 		X,MPR 				; Clear TWINT bit in TWCR to start transmission
									; of data
wait5a:
	ld 			MPR,X 				; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; data has been transmitted, and ACK/NACK has
	rjmp 		wait5a				; been received

	ld 			MPR,Z 				; Check value of TWI Status Register. If status
	cpi 		MPR,MT_DATA_ACK 	; different from MT_DATA_ACK, go to ERROR
	brne 		ERROR
	ldi 		MPR,(1<<TWINT) | (1<<TWSTO) | (1<<TWEN)
	st	 		X,MPR 				; Transmit STOP condition

;	call		delay65ms			; 65ms Delay while Sonar process data

;***Master Receiver Mode***

	ldi 		MPR,(1<<TWINT) | (1<<TWSTA) | (1<<TWEN); | (0<<TWSTO)
	st	 		X,MPR 				; Send START condition
wait5:
	ld 			MPR,X 				; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; the START condition has been transmitted
	rjmp 		wait5
	nop
	
	ld 			MPR,Z 				; Check value of TWI Status Register. If status
	cpi 		MPR,REP_START 			; different from START, go to ERROR
	brne 		ERROR

	ldi 		MPR,SLA+R 			; Load SLA+R into TWDR Register

	st	 		Y,MPR
	ldi 		MPR,(1<<TWINT) | (1<<TWEN)
	st	 		X,MPR 				; Clear TWINT bit in TWCR to start transmission
									; of SLA+R
wait6:
	ld 			MPR,X 				; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; SLA+R has been transmitted, and ACK/NACK has
	rjmp 		wait6 				; been received

	ld 			MPR,Z				; Check value of TWI Status Register. If status
	cpi 		MPR,MR_SLA_ACK 		; different from MR_SLA_ACK, go to ERROR
	brne 		ERROR

	ldi 		MPR,(1<<TWINT) | (1<<TWEA) | (1<<TWEN)
	st	 		X,MPR 				; Clear TWINT bit in TWCR to start reception of
									; data. Setting TWEA causes ACK to be returned
									; after reception of data byte
wait7:
	ld 			MPR,X 				; Wait for TWINT Flag set. This indicates that
	sbrs		MPR,TWINT 			; data has been received and ACK returned
	rjmp 		wait7

	ld 			MPR,Z 				; Check value of TWI Status Register. If status
	cpi 		MPR,MR_DATA_ACK 	; different from MR_DATA_ACK, go to ERROR
	brne 		ERROR

	ld 			ECHOH,Y 				; Input received data from TWDR.

;	com			ECHOH
;	out			PORTC,ECHOH			;<do something with received data>

	ldi			MPR,(1<<TWINT) | (1<<TWEN)
	st	 		X,MPR 				; Clear TWINT bit in TWCR to start reception of
									; data. Not setting TWEA causes NACK to be
									; returned after reception of next data byte
									; receive last data byte. Signal this to Slave
									; by returning NACK

wait9:
	ld 			MPR,X 				; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; data has been received and NACK returned
	rjmp 		wait9
	ld 			MPR,Z 				; Check value of TWI Status Register. If status
	cpi 		MPR,MR_DATA_NACK 	; different from MR_DATA_NACK, go to ERROR
	brne 		ERROR

	ld			ECHOL,Y 			; Input received data from TWDR.

;	com			ECHOL
;	out			PORTC,ECHOL			;<do something with received data>

	ldi 		MPR,(1<<TWINT) | (1<<TWSTO) | (1<<TWEN)
	st	 		X,MPR 				; Send STOP signal
mainloop:
	rjmp		mainloop

ERROR:

; Load Contents of TWI Status Register and display on Port C (LEDs)

	ld 			mpr2,Z				; Load the TWSR for Error display
	com			mpr2				; Change to active low LEDs
	out			PORTC,mpr2			; Display to LED's Error message
	break
; *** 65ms delay while Sonar process data
;---------------------------------------------------------------------
Delay65ms:

	push  		XH
	push		XL

	ldi			XH,$ff
	ldi			XL,$ff
	ldi			mpr2,$0f

loop:
	sbiw		XH:XL,1
	brne		loop
	dec			mpr2
	brne		loop

	pop			XL
	pop			XH

	ret

;---------------------------------------------------------------------

		ldi			mpr2,$aa
	out			portC,mpr2
