;-----------------------------------------------------------------
; Name:			MicroChip323.asm
; Description:	ATMega323 Two Wire Interface (IC2) Test Program
;				Interfaces Microchip 24AA256K Memory to IC2 Bus

; Author:		Max Koessick
; Class:		EEL5666C, Intelligent Machine Design Lab
; Date:			June 28, 2003
; Revision		1.a
; Changes to Date:
;				7/2/03 First Revision
;				7/6/03 Working
;-----------------------------------------------------------------

.nolist								; Do not include in .lst file
.include "m323def.inc"				; Standard ATMega323 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		ECHOL	=r18
.def		ECHOH	=r19
.def		ErrorReg=r20
.def		mpr3	=r21


; Equate statements
.equ		W			= 0			; Write Bit
.equ		R			= 1			; Read Bit
.equ		SLA			= $A0		; Slave Address of 24AA256
.equ		Addr		= $ff		; Random address
.equ		AddrHigh	= $00		; SRF08 Command Register
.equ		Data		= $ef
;-----------------------------------------------------------------
; 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 	DDRB,mpr
;-----------------------------------------------------------------

	clr 	ErrorReg				; For Debug purposes
					
	
; Set TWIBitRate for fclk=3.69Mhz

	ldi			mpr,11				;100Khz=3.69MHz/(16+2*12) See Datasheet Pg202
	out			TWBR,mpr


; Initialize TWCR Register

	ldi 		MPR,(1<<TWEN);
	out	 		TWCR,MPR 			; Initialize TW Control Register

	ldi			mpr,$01
	out			TWAR,mpr
	
	sei								; set interrupts active
	
;***MASTER TRANSMITTER*****

	ldi 		MPR,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
	out	 		TWCR,MPR 			; Send START condition

WAIT1: 
	in 			MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; the START condition has been transmitted
	rjmp 		WAIT1


	in 			MPR,TWSR 			; Check value of TWI Status Register.
	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
	out	 		TWDR,MPR

	ldi 		MPR,(1<<TWINT)|(1<<TWEN)
	out	 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of address
WAIT2: 
	in 			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

	in 			MPR,TWSR 			; Check value of TWI Status Register. If status
	cpi 		MPR,MT_SLA_ACK 		; different from MT_SLA_ACK, go to ERROR
	breq		NEXT2
	jmp			ERROR2

;***Send Address Byte***

NEXT2:

	ldi 		MPR,Addr			; Load data (Address Byte) into TWDR
	out 		TWDR,MPR			; Register

	ldi			MPR,(1<<TWINT)|(1<<TWEN)
	out 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of data
WAIT3: 

	in 			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

	in 			MPR,TWSR 			; Check value of TWI Status Register. If status
	cpi 		MPR,MT_DATA_ACK		; different from MT_DATA_ACK, go to ERROR
 	breq		NEXT4
	jmp			ERROR3

;***Send Data Byte***

NEXT4:
	ldi 		MPR,Data	 		; Load data (Data Byte) into TWDR
	out 		TWDR,MPR			; Register

	ldi			MPR,(1<<TWINT)|(1<<TWEN)
	out 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of data
WAIT5: 
	in 			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

	in 			MPR,TWSR 			; Check value of TWI Status Register. If status
									; different from MT_DATA_ACK, go to ERROR
	cpi 		MPR,MT_DATA_ACK 	
	breq		NEXT5
	jmp			ERROR5
;Send Stop Condition-24AA256 Writes to memory after Stop condition
NEXT5:
	ldi 		mpr,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
	out			TWCR,mpr

check:
	in			mpr,TWCR
	andi		mpr,0b00010000
	brne		check

;	call		delay65ms

;*****Random READ Operation*****

;Send Start Condition
NEXT7:
	ldi			MPR,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
	out	 		TWCR,MPR 			; Send START condition
WAIT8:
	in 			MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; the START condition has been transmitted
	rjmp 		WAIT8
	
	in 			MPR,TWSR 			; Check value of TWI Status Register. If status
									; different from START, go to ERROR
	cpi 		MPR,START 		
	breq 		NEXT8
	JMP			ERROR6


;***SLAVE ADDRESS + Write*** Setting Address for READ

NEXT8:

	ldi 		MPR,SLA+W			; Load SLA+W into TWDR Register
	out	 		TWDR,MPR

	ldi			MPR,(1<<TWINT)|(1<<TWEN);
	out	 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of address
WAIT9: 
	in 			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

	in 			MPR,TWSR 			; Check value of TWI Status Register. If status
	cpi 		MPR,MT_SLA_ACK		; different from MT_SLA_ACK, go to ERROR
	breq		NEXT9
	jmp			ERROR7


;***Send Address High Byte***Setting Address for READ

NEXT9:
	ldi 		MPR,Addr 			; Load data (Address Byte) into TWDR
	out 		TWDR,MPR			; Register

	ldi 		MPR,(1<<TWINT)|(1<<TWEN)
	out 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of data
WAIT10: 
	in 			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

	in 			MPR,TWSR 			; Check value of TWI Status Register. If status
	cpi 		MPR,MT_DATA_ACK 	; different from MT_DATA_ACK, go to ERROR
	breq		NEXT10
	jmp			ERROR8

;***Send Repeated Start Condition***
NEXT10:
	ldi			MPR,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
	out	 		TWCR,MPR 			; Send REP_START condition

WAIT11:
	in 			MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; the START condition has been transmitted
	rjmp 		WAIT11
	
	in			MPR,TWSR 			; Check value of TWI Status Register. If status
	cpi 		MPR,rep_START 		; different from START, go to ERROR
	breq 		NEXT11
	JMP			ERRORa

;***SLAVE ADDRESS+READ*** (Random Read)

NEXT11:
	ldi 		MPR,SLA+R 			; Load SLA+W into TWDR Register
	out	 		TWDR,MPR

	ldi 		MPR,(1<<TWINT)|(1<<TWEN)
	out	 		TWCR,MPR 			; Clear TWINT bit in TWCR to start transmission
									; of SLA+R, enable TWI and generate an ACK, TWEA=1
WAIT12:
	in 			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

	in	 		MPR,TWSR			; Check value of TWI Status Register. If status
	cpi 		MPR,MR_SLA_ACK		; different from MR_SLA_ACK, go to ERROR
 	breq		NEXT12
	jmp			ERRORb

NEXT12:
;Get last data Byte
	ldi			MPR,(1<<TWINT)|(1<<TWEN)
	out	 		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:
	in 			MPR,TWCR			; Wait for TWINT Flag set. This indicates that
	sbrs 		MPR,TWINT 			; data has been received and NACK returned
	rjmp 		WAIT13
	
	in 			MPR,TWSR 			; Check value of TWI Status Register. If status
	cpi 		MPR,MR_DATA_NACK 	; different from MR_DATA_NACK, go to ERROR
	breq 		NEXT13
	jmp			ERRORc

NEXT13:
	in			ECHOL,TWDR 			; Input received data from TWDR.
	com			ECHOL				; Invert to put onto LEDs
	out			PORTB,ECHOL
;Issue Stop 

	ldi 		MPR,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
	out	 		TWCR,MPR 			; Send STOP signal

MAINLOOP:

	rjmp		mainloop

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)

	in 			mpr2,TWCR			; Load the TWSR for Error display
 	or			mpr2,errorreg
	com			mpr2				; Change to active low LEDs
	out			PORTB,mpr2
LOOP1:
	rjmp		loop1
; *** 65ms delay while Sonar process data
;---------------------------------------------------------------------
Delay65ms:

	push  		XH
	push		XL
	push		mpr2

	ldi			XH,$ff
	ldi			XL,$00
	ldi			mpr2,$00

loop:
	sbiw		XH:XL,1
	brne		loop

	pop 		mpr2

	pop			XL
	pop			XH

	ret

Test:
	ldi		mpr3,$aa
	out		PORTB,mpr3
loop2:
	rjmp	loop2
	ret

test2:
	in		mpr3,twsr
	com		mpr3
	out		PORTB,mpr3
loop3:
	rjmp	loop3
