;ATmega88.asm
;version 1.00 Feb 23, 2010
;author: W8DIZ Dieter (Diz) Gentzow
;email: w8diz@tampabay.rr.com

;http://designtools.analog.com/dt/ad98334/ad9834.html
;http://designtools.analog.com/dt/ad98325/ad9835.html

;1. open Terminal and run "cd public_html/w8diz.com/qq-fc-project/ATmega48"
;2. to assemble code, run "avra ATmega48.asm" in the directory that holds ATmega48
;3. if using a USB ARVISPmkII run "avrdude -P usb -p m48 -c avrispv2 -U ATmega48.hex -B 10 -v"

;read fuse bits execute avrdude -P usb -p m48 -c avrispv2 -U lfuse:r:filename [this does not work]
;read fuse bits execute avrdude -P usb -p m48 -c avrispv2 -v [this does work]
;write fuse bits execute avrdude -P usb -p m48 -c avrispv2 -U lfuse:w:0xFF:m

.include "m48def.inc"

.equ DRS	= 0
.equ E		=	1
.equ CP		=	2
.equ LED	=	3

.def temp1 =r16
.def temp2 =r17
.def temp3 =r18
.def temp4 =r19
.def temp5 =r20
.def temp6 =r21
.def temp7 =r22
.def temp8 =r23
.def temp9 =r24
.def delay =r25
.def	XL	= r26
.def	XH	= r27
.def	YL	= r28
.def	YH	= r29
.def	ZL	= r30
.def	ZH	= r31

.cseg ;This tells the assembler that what follows is code, and goes in ROMspace
.org $000
	rjmp	RESET
	reti ; INT0	; External Interrupt Request 0
	reti ; INT1	; External Interrupt Request 1
	reti ; PCI0	; Pin Change Interrupt Request 0
	reti ; PCI1	; Pin Change Interrupt Request 1
	reti ; PCI2	; Pin Change Interrupt Request 1
	reti ; WDT		; Watchdog Time-out Interrupt
	reti ; OC2A	; Timer/Counter2 Compare Match A
	reti ; OC2B	; Timer/Counter2 Compare Match A
	reti ; OVF2	; Timer/Counter2 Overflow
	reti ; ICP1	; Timer/Counter1 Capture Event
	reti ; OC1A	; Timer/Counter1 Compare Match A
	reti ; OC1B	; Timer/Counter1 Compare Match B
	reti ; OVF1	; Timer/Counter1 Overflow
	reti ; OC0A	; TimerCounter0 Compare Match A
	reti ; OC0B	; TimerCounter0 Compare Match B
	rjmp	OVF0		; Timer/Couner0 Overflow
	reti ; SPI		; SPI Serial Transfer Complete
	reti ; URXC	; USART Rx Complete
	reti ; UDRE	; USART, Data Register Empty
	reti ; UTXC	; USART TxRSD Complete
	reti ; ADCC	; ADC Conversion Complete
	reti ; ERDY	; EEPROM Ready
	reti ; ACI		; Analog Comparator
	reti ; TWI		; Two-wire Serial Interface
	reti ; SPMR	; Store Program Memory Read

RESET: ;init everything here
	ldi		temp1,low(RAMEND)
	out		SPL,temp1			; Set stack pointer to last internal RAM location
	ldi		temp1,high(RAMEND)
	out		SPH,temp1

;init ports
	ldi		temp1,$0F
	out		DDRC,temp1		;make all 4 PC0-PC3 pins an output
	cbi		PORTC,E				;set E low
 	cbi		PORTC,CP			;set CP low
	sbi		PORTC,LED			;turn LED off

;init misc
	ldi		delay,250			;250 mSec

	ldi		temp1,$05			;set timer0 prescale divisor to 1024
	out		TCCR0B,temp1	;using 20.48 XTAL = 50uS
 
	ldi		temp1,$01
	sts		TIMSK0,temp1	;enable TIMER0 overflow interrupts

	sei 								;global all interrupt enable

	rcall	INIT_LCD
	
	ldi		temp1,2				;blink twice to show system is working
	rcall BLINK_LED
	
	ldi		ZH,high(2*msg2)
	ldi		ZL,low(2*msg2)
	ldi		temp1,$C0			;display on line 2
	rcall	LCDCMD
	rcall	DISPLAY_LINE

	ldi		ZH,high(2*msg1)
	ldi		ZL,low(2*msg1)
	ldi		temp1,$80			;display on line 1
	rcall	LCDCMD
	rcall	DISPLAY_LINE
	
Main_Menu:
	rjmp Main_Menu
	
DISPLAY_LINE:
	lpm
	tst		r0
	breq	DISPLAY_LINE_FINIS
	mov		temp1,r0
	rcall	LCDCHR
	adiw	ZL,1
	rjmp	DISPLAY_LINE
DISPLAY_LINE_FINIS:
 ret
 


;************************************
;* INIT_LCD
;* uses temp1 
;************************************
INIT_LCD:
	ldi		delay,20			;wait 20 milliseconds for system to stabilize
	rcall	WAIT
	ldi		temp1,$30
	rcall LCDCMD
	ldi		delay,4				;wait 4 milliseconds
	rcall	WAIT
	;ldi		temp1,$30
	;rcall LCDCMD
	;ldi		temp1,$30
	;rcall LCDCMD
	ldi		temp1,$38			;set for 8 bits, 2 lines, default font
	rcall LCDCMD
	ldi		temp1,$08			;Display off, cursor off, blink off
	rcall LCDCMD
	ldi		temp1,$01			;Clear screen, cursor home
	rcall LCDCMD
	ldi		temp1,$06			;Increment cursor to the right when writing, don't shift screen
	rcall LCDCMD
	ldi		temp1,$0C			;Display on, cursor off, blink off
	rcall LCDCMD
	ret

;************************************
;* WAIT
;* temp1 = WAIT time in milliseconds
;************************************
WAIT:
	tst		delay
	brne	WAIT
	ret

;************************************
;* BLINK_LED
;* temp1 = number of times LED BLINKS
;************************************
BLINK_LED:
	cbi		PORTC,LED				;turn LED on
	ldi		delay,250				;250 mSec
	rcall WAIT
	sbi		PORTC,LED				;turn LED off		
	ldi		delay,250				;250 mSec
	rcall	WAIT
	dec		temp1
	brne	BLINK_LED
	ret
	
;************************************
;* LCDCMD - Send a command to the LCD
;* temp1 = cmd
;************************************
LCDCMD: 
	rcall	SENDBYTE
	cbi		PORTC,DRS			;set RS low
	sbi		PORTC,E				;E clocks on rising edge
	cbi		PORTC,E				;set E low
	ldi		delay,2				;wait 2 milliseconds
	rcall	WAIT
	ret

;*****************************************
;* LCDCHR - Display a character on the LCD
;* temp1 = data
;*****************************************
LCDCHR:
	rcall	SENDBYTE
	sbi		PORTC,DRS			;set RS High
	sbi		PORTC,E				;E clocks on rising edge
	cbi		PORTC,E				;set E low
	ldi		delay,2				;wait 2 milliseconds
	rcall	WAIT
	ret
	
;**********************************
;* SENDBYTE clock byte into 74hc164
;* temp1 = data
;* temp2 = bitcounter
;***********************************
SENDBYTE:
	ldi		temp2,8					;bit counter
ShiftBits:
	cbi		PORTC,DRS   		;set LCD Data bit to 0
	lsl		temp1						;shift bits in AReg into carry
	brcc	ClockBit				;if zero, clock it out
	sbi		PORTC,DRS   		;if 1, set LCD Data bit to 1
ClockBit: 
	sbi		PORTC,CP				;bit clocks on rising edge
	cbi		PORTC,CP				;bring clock back to 0
	dec		temp2						;shift out 8 bits
	brne	ShiftBits
	ret      	
   
;**********************************
;* Timer 0 Overflow
;* gets here every 1 millisecond
;* decrements the DELAY counter
;***********************************     	
OVF0:
	push	temp1
	in		temp1,SREG
	push	temp1
	ldi		temp1,256-20		;1 ms using a 20.48 MHz Xtal
	out		TCNT0,temp1			;set for next overflow
	tst		delay
	breq	OVF_EXIT
	dec		delay
OVF_EXIT:
	pop		temp1
	out		SREG,temp1
	pop		temp1
	reti

msg1:
;    1234567890123456789012345678901234567890
.db "DDS Dev Kit V2.0",0,0
msg2:
;    1234567890123456789012345678901234567890
.db "kitsandparts.com",0,0

