;-----------------------------------------------------------------
; Name:			SRF08No2.asm
; Description:	ATMega128 Two Wire Interface (IC2) Test Program
;				Interfaces Daventech SRF08 Range Finder to I2C Bus

; Author:		Max Koessick
; Class:		EEL5666C, Intelligent Machine Design Lab
; Date:			June 28, 2003
; Revision		1.a
; Changes to Date:
;				7/6/03 First Revision
;				7/7/03 Added LCD Interface
;						Still need to work on proper LCD readout
;						HEX->ASCII Conversion
;-----------------------------------------------------------------

.nolist								; Do not include in .lst file
.include "m128def.inc"				; Standard ATMega128 Include File
.include "TWI.inc"					; Two Wire Interface Error code definitions
.list
; Interrupt service vectors

.org $0000
	rjmp Reset						; Reset vector
	
;-----------------------------------------------------------------
; Register defines for main loop
;-----------------------------------------------------------------


.def		mpr			=r16		; defines multipurpose register
.def		MPR2		=r17		; multipurpose register 2
.def		ECHO1L		=r18
.def		ECHO1H		=r19
.def		ErrorReg	=r20
.def		mpr3		=r21


; Equate statements
.equ		W			= 0			; Write Bit
.equ		R			= 1			; Read Bit
.equ		SLA			= $E0		; Slave Address of SRF08
.equ		CommandReg	= $00		; Random address
.equ		Inches		= $50		; Ranging Mode returns results in inches
.equ		EchoReg2	= $02
.equ		EchoReg3	= $03
;-----------------------------------------------------------------
; 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...
;LEDs
	out 	DDRC,mpr
	out		PORTC,mpr				; Lights off
;LCD
	out		DDRB,mpr				; ...set data direction to "out"
									; = DataBus DB[7..0]
	out 	DDRE,mpr				; Set 'E' as output
									; control Bits


;-----------------------------------------------------------------

	clr 	ErrorReg
					
	
; Set TWIBitRate for fclk=16Mhz

	ldi			mpr,12				; 400Khz=16MHz/(16+2*12) See Datasheet Pg202
	sts			TWBR,mpr

	ldi			mpr,$00
	sts			TWSR,mpr

; Initialize TWCR Register
	clr			mpr
	ldi 		MPR,(1<<TWEN);
	sts	 		TWCR,MPR 			; Initialize Two Wire Control Register

	ldi			mpr,$01
	sts			TWAR,mpr

	sei								; set interrupts active
			
;***MASTER TRANSMITTER*****

	lds			mpr,TWCR
	sbr 		MPR,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
	sts	 		TWCR,MPR 			; Send START condition

WAIT1: 
	lds 		MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; the START condition has been transmitted
	rjmp 		WAIT1


	lds 		MPR,TWSR 			; Check value of TWI Status Register.
	andi		MPR,$F8				; Mask Prescaler Bits
	cpi 		MPR,START 			; If status different from START go to ERROR
	breq		NEXT1
	jmp			ERROR1
		
;***SLAVE ADDRESS + Write***

NEXT1:
	ldi 		MPR,SLA+W			; Load SLA+W into TWDR Register
	sts	 		TWDR,MPR

	clr			mpr
	sbr 		MPR,(1<<TWINT)|(1<<TWEN)
	sts	 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of address
WAIT2: 
	lds 		MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; SLA+W has been transmitted, and ACK/NACK has
	rjmp 		WAIT2 				; been received

	lds 		MPR,TWSR 			; Check value of TWI Status Register. If status
	andi		MPR,$F8				; Mask Prescaler Bits
	cpi 		MPR,MT_SLA_ACK 		; different from MT_SLA_ACK, go to ERROR
	breq		NEXT2
	jmp			ERROR2

;***Send Command Register Address Byte***

NEXT2:
	ldi 		MPR,CommandReg		; Load data (Address Byte) into TWDR
	sts 		TWDR,MPR			; Register

	clr			mpr
	sbr			MPR,(1<<TWINT)|(1<<TWEN)
	sts 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of data
WAIT3: 

	lds 		MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; data has been transmitted, and ACK/NACK has
	rjmp 		WAIT3 				; been received

	lds 		MPR,TWSR 			; Check value of TWI Status Register. If status
									; different from MT_DATA_ACK, go to ERROR
	andi		MPR,$F8				; Mask Prescaler Bits
	cpi 		MPR,MT_DATA_ACK 	
	breq		NEXT4
	jmp			ERROR3

;***Send Ranging Mode Byte***

NEXT4:
	ldi 		MPR,Inches	 		; Load data (Data Byte) into TWDR
									; Register
	sts 		TWDR,MPR

	clr			MPR
	sbr 		MPR,(1<<TWINT)|(1<<TWEN)
	sts 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of data
WAIT5: 

	lds 		MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; data has been transmitted, and ACK/NACK has
	rjmp 		WAIT5 				; been received

	lds 		MPR,TWSR 			; Check value of TWI Status Register. If status
									; different from MT_DATA_ACK, go to ERROR
	andi		MPR,$F8				; Mask Prescaler Bits
	cpi 		MPR,MT_DATA_ACK 	
	breq		NEXT5
	jmp			ERROR5
;Send Stop Condition-24AA256 Writes to memory after Stop condition
NEXT5:


	call		Delay70ms

;*****Random READ Operation*****

;Send Start Condition
NEXT7:
	clr			mpr
	sbr			MPR,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
	sts	 		TWCR,MPR 			; Send START condition
WAIT8:
	lds 		MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; the START condition has been transmitted
	rjmp 		WAIT8
	
	lds 		MPR,TWSR 			; Check value of TWI Status Register. If status
									; different from START, go to ERROR
	andi		MPR,$F8				; Mask Prescaler Bits
	cpi 		MPR,rep_START 		
	breq 		NEXT8
	JMP			ERROR6


;***SLAVE ADDRESS + Write*** Setting Address for READ

NEXT8:

	ldi 		MPR,SLA+W			; Load SLA+W into TWDR Register
	sts	 		TWDR,MPR

	clr			mpr
	sbr			MPR,(1<<TWINT)|(1<<TWEN);
	sts	 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of address
WAIT9: 
	lds 		MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; SLA+W has been transmitted, and ACK/NACK has
	rjmp 		WAIT9 				; been received

	lds 		MPR,TWSR 			; Check value of TWI Status Register. If status
									; different from MT_SLA_ACK, go to ERROR
	andi		MPR,$F8				; Mask Prescaler Bits
	cpi 		MPR,MT_SLA_ACK	
	breq		NEXT9

	jmp			ERROR7


;***Send Echo Register 3 Address (low Byte)***Setting Address for READ

NEXT9:
	ldi 		MPR,EchoReg3		; Load data (Address Byte) into TWDR
									; Register
	sts 		TWDR,MPR

	clr			mpr
	sbr 		MPR,(1<<TWINT) | (1<<TWEN)
	sts 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of data
WAIT10: 

	lds 		MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; data has been transmitted, and ACK/NACK has
	rjmp 		WAIT10 				; been received

	lds 		MPR,TWSR 			; Check value of TWI Status Register. If status
									; different from MT_DATA_ACK, go to ERROR
	andi		MPR,$F8				; Mask Prescaler Bits
	cpi 		MPR,MT_DATA_ACK 	
	breq		NEXT10
	jmp			ERROR8

;Send Repeated Start Condition

NEXT10:

	clr			mpr
	sbr			MPR,(1<<TWINT)|(1<<TWSTA)|(1<<TWEA)|(1<<TWEN)
	sts	 		TWCR,MPR 			; Send REP_START condition
WAIT11:
	lds 		MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; the START condition has been transmitted
	rjmp 		WAIT11
	
	lds 		MPR,TWSR 			; Check value of TWI Status Register. If status
									; different from START, go to ERROR
	andi		MPR,$F8				; Mask Prescaler Bits
	cpi 		MPR,rep_START 		
	breq 		NEXT11
	JMP			ERRORa

;***SLAVE ADDRESS+READ*** 

NEXT11:
	ldi 		MPR,SLA+R 			; Load SLA+R into TWDR Register
	sts	 		TWDR,MPR

	clr			mpr
	sbr 		MPR,(1<<TWINT)|(1<<TWEN)
	sts	 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of SLA+R, enable TWI and generate an ACK, TWEA=1
WAIT12:
	lds 		MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; SLA+R has been transmitted, and ACK/NACK has
	rjmp 		WAIT12 				; been received

	lds 		MPR,TWSR			; Check value of TWI Status Register. If status
									; different from MR_SLA_ACK, go to ERROR
	andi		MPR,$F8				; Mask Prescaler Bits
	cpi 		MPR,MR_SLA_ACK 		
	breq		NEXT12
	jmp			ERRORb

NEXT12:
;Get EchoRegister 3 data
	clr			mpr
	sbr			MPR,(1<<TWINT)|(1<<TWEN)
	sts	 		TWCR,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
WAIT13:
	lds 		MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; data has been received and NACK returned
	rjmp 		WAIT13
	
	lds 		MPR,TWSR 			; Check value of TWI Status Register. If status
	andi		MPR,$F8				; Mask Prescaler Bits
	cpi 		MPR,MR_DATA_NACK 	; different from MR_DATA_NACK, go to ERROR
	breq 		NEXT13
	jmp			ERRORc

NEXT13:

	lds			ECHO1L,TWDR 			; Input received data from TWDR.
	com			ECHO1L				; Prepare for LED output
	out			PORTC,ECHO1L
	;	jmp			test
;Issue Stop 

	clr			MPR
	sbr 		MPR,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
	sts	 		TWCR,MPR 			; Send STOP signal


;***Out to LCD***

;	call	LCDInit
	
;	ldi		mpr,0b10000000			; Activate Data Register
;	out		PORTE,mpr

;	ldi		ZH,high(varlist*2)		; Initialize Z Pointer for LPM command
;	ldi		ZL,low(varlist*2)

NextChar:
;	lpm		mpr,Z+					; Get first/next character

;	cpi		mpr,$ff					; Is this the string terminator?
									; No, then get next; Yes, then end
;	breq	Load

;	out		PORTB,mpr

;	ldi		mpr,0b11000000			; Activate LCD Enable
;	out		PORTE,mpr

;	ldi		mpr,0b10000000
;	out		PORTE,mpr				; Deactivate LCD Enable

;	call	delay40us

;	rjmp	NextChar				; Repeat Loop until string Terminator

Load:
;	ldi		mpr2,$31
;	ldi		mpr,EchoReg3
;	andi	mpr,$f0					; Mask low Byte
;	add		mpr,mpr2
;	out		PORTB,mpr

;	ldi		mpr,0b11000000			; Activate LCD Enable
;	out		PORTE,mpr

;	ldi		mpr,0b10000000
;	out		PORTE,mpr				; Deactivate LCD Enable

;	call	delay40us

;	ldi		mpr,EchoReg3
;	andi	mpr,$0f					; Mask high Byte
;	add		mpr,mpr2
;	out		PORTB,mpr

;	ldi		mpr,0b11000000			; Activate LCD Enable
;	out		PORTE,mpr

;	ldi		mpr,0b10000000
;	out		PORTE,mpr				; Deactivate LCD Enable

;	call	delay40us


mainloop:

	rjmp 	mainloop

;.org $100

;varlist:
;.dw $6152,$676e,$3A65,$00FF 		; "Range:" in ASCII (Hex)

;.org $110
;.nolist								; turn listing off
;.include "LCD_Init.inc"
;.list

;***Error Detection Routine***
;Error will be presented as a or'ed pair of the step in which
; the program broke and the TWSR
ERROR1:
	ldi			ErrorReg,$01
	rjmp		output
ERROR2:
	ldi			ErrorReg,$02
	rjmp		output
ERROR3:
	ldi			ErrorReg,$03
	rjmp		output
ERROR4:
	ldi			ErrorReg,$04
	rjmp		output
ERROR5:
	ldi			ErrorReg,$05
	rjmp		output
ERROR6:
	ldi			ErrorReg,$06
	rjmp		output
ERROR7:
	ldi			ErrorReg,$07
	rjmp		output
ERROR8:
	ldi			ErrorReg,$08
	RJMP		output
ERROR9:
	ldi			ErrorReg,$09
	RJMP		output
ERRORa:
	ldi			ErrorReg,$0A
	RJMP		output
ERRORb:
	ldi			ErrorReg,$0B
	RJMP		output
ERRORc:
	ldi			ErrorReg,$0c
	RJMP		output
ERRORd:
	ldi			ErrorReg,$0d
	RJMP		output
Output:

; Load Contents of TWI Status Register and display on Port C (LEDs)

	lds 		MPR,TWSR			; Load the TWSR for Error display
 	or			MPR,errorreg
	com			MPR				; Change to active low LEDs
	out			PORTC,MPR
LOOP1:
	rjmp		loop1

;---------------------------------------------------------------------
; There must be delay loop between reading and writing to the Memory chip
Delay70ms:

	push  		XH
	push		XL
	push		mpr

	ldi			XH,$17
	ldi			XL,$00
	ldi			mpr,$11
loop4:
	sbiw		XH:XL,1
	brne		loop4
	dec			mpr
	brne		loop4

	pop			mpr
	pop			XL
	pop			XH
	ret

; Test subroutines for debugging
Test:
	ldi		mpr3,$11
	out		portc,mpr3
loop2:
	rjmp	loop2
	ret

test2:
	lds		mpr3,twsr
	com		mpr3
	out		portc,mpr3
loop3:
	rjmp	loop3

