.nolist
.include "2313def.inc"

; Obsluga wyswietlacza DM157 oraz watchdog podlaczony przes RS232 do komputera
; (C) 2005 Marek Wodzinski majek@mamy.to

; ***** rejestry *****
; r16	temp
; r17	znak
; r18	temp2
; r19	licznik
; r20	itemp2
; r21	itemp
; r22	watchdog
; r23	f1ok
.def		temp=r16	;zwykly rejestr tymczasowy
.def		temp2=r18	;drugi temp
.def		itemp=r21	;jw. ale do wykorzystania w przerwaniach
.def		itemp2=r20
.def		licznik=r19	;
.def		watchdog=r22

;linie sterujace wyswietlacza
.equ		RS=4
.equ		E=3
.equ		RW=2

;diodki
.equ		ZIEL=5
.equ		CZER=5

;reset
.equ		RES=6

; dane wyswietlacza: port B
; linie sterujace wyswietlacza: port D
; diodki: port D

;razem port D:
; x OUT OUT OUT OUT OUT OUT IN
; x RES LED E   RS  RW  TxD RxD

;czas dla watchdoga (sekundy)
.equ		WATCHTIME=180



; ***** makra *****

; 10x nop = 1us
.macro		nop10
		nop
		nop
		nop
		nop
		nop
		nop
		nop
		nop
		nop
		nop
.endmacro


;puls E
.macro		pulse
		sbi	PORTD,E		;E
		nop10
		cbi	PORTD,E		;-E
		nop10
.endmacro


;wyslanie rozkazu do wyswietlacza (rejestr,rozkaz)
.macro		rozkaz
		cbi	PORTD,RW		;write
		cbi	PORTD,RS		;-RS
		ldi	@0,@1
		out	PORTB,@0
		sbi	PORTD,E		;E
		nop10
		cbi	PORTD,E		;-E
		nop10
		ldi	@0,0
		out	DDRB,@0		;przestaw PORTB na wejscie
		out	PORTB,@0	;wylaczyc pull-up resistors
		sbi	PORTD,RW	;read
aa%:		sbi	PORTD,E		;E
		nop10
		in	@0,PINB		;odczytaj status
		bst	@0,7		;sprawdz busy
		cbi	PORTD,E		;-E
		nop10
		brts	aa%		;krec sie tak dlugo az busy zniknie
		sbi	PORTD,RS		;RS
		sbi	PORTD,RW		;write
		ldi	@0,255
		out	DDRB,@0		;przestaw porty z powrotem na wyjscie
.endmacro


;wyslanie znaku do wyswietlacza - (rejestr)
.macro		wyslij
		cbi	PORTD,RW	;write
		sbi	PORTD,RS	;RS
		out	PORTB,@0
		pulse
.endmacro


;punkt kontrolny - wyslanie znaku po rs-ie
.macro		kontrol
		ldi	temp,@0+48
		out	UDR,temp
.endmacro

;laduje do Z adres napisu
		
;*****Dane do eeproma******************************
.eseg					;EEPROM segment
.org 0



;****Source code***************************************************
.list
.cseg					;CODE segment
.org 0
		rjmp	reset
		reti		;INT0
		reti		;INT1
		reti		;Input Capture1 Interrupt Vector Address
		rjmp	diodka	;Output Compare1A Interrupt Vector Address
		reti		;Output Compare1B Interrupt Vector Address
		reti		;Overflow1 Interrupt Vector Address
		rjmp	odbior	;UART Receive Complete Interrupt Vector Address
		reti		;UART Data Register Empty Interrupt Vector Address
		reti		;UART Transmit Complete Interrupt Vector Address
		reti		;Analog Comparator Interrupt Vector Address


; Set stack pointer to last internal RAM location
reset:
		ldi	temp,RAMEND
		out	SPL,temp
;		ldi	temp,high(RAMEND)
;		out	SPH,temp

;inicjalizacja zmiennych
		ldi	watchdog,0

;przepisanie stalej z eepromu do ramu
		ldi	temp,0
		ldi	xl,low(f1cont)	
		ldi	xh,high(f1cont)
		ldi	zl,low(f1ee<<1)
		ldi	zh,high(f1ee<<1)
init0:		lpm
		inc	zl
		adc	zh,temp
		st	X+,r0
		cpse	r0,temp
		rjmp	init0

		ldi	yl,low(f1echo)	
		ldi	yh,high(f1echo)
		ldi	zl,low(f1ec<<1)
		ldi	zh,high(f1ec<<1)
init1:		lpm
		inc	zl
		adc	zh,temp
		st	Y+,r0
		cpse	r0,temp
		rjmp	init1
		
;inicjalizacja f1
		ldi	xl,low(f1cont)	
		ldi	xh,high(f1cont)
		
		
		
;ustawiamy uarta
		ldi	temp,0b10011000	;odblokowanie przerwan i uarta
		out	UCR,temp
		ldi	temp,12		;ustawianie na 38400 (dla zegara 8MHz)
		out	UBRR,temp

;programuje timer
		ldi	temp,0b00000000	;odlaczony od zewnetrznego wyjscia, pwm wylaczony
		out	TCCR1A,temp
		
		ldi	temp,0b00001101	;reset on compareA match, prescaler=1024
		out	TCCR1B,temp
		
		ldi	temp,30		;przerwanie co 1s (CLK=8MHz)
		out	OCR1AH,temp
		ldi	temp,132
		out	OCR1AL,temp
		
		ldi	temp,0b01000000	;odblokowanie przerwania od compareA
		out	TIMSK,temp
		
		
;ustawiam bity portu D na wyjscie dla ledow
		sbi	DDRD,ZIEL	;zielony
		sbi	PORTD,ZIEL	;zapalam zielona
;		sbi	DDRD,CZER	;czerwony
;		cbi	PORTD,CZER	;gasze czerwona

		sei			;odblokowanie przerwan

;reset na wysoki stan w open collector
		cbi	DDRD,RES	;wejscie
		cbi	PORTD,RES	;0 - bez pull up rezystora

;ustawienia dla lcd
		sbi	DDRD,RS		;RS,E,R/W sa wyjsciami
		sbi	DDRD,E
		sbi	DDRD,RW
		ldi	temp,0xff	;caly port B na wyjscie danych
		out	DDRB,temp
		
;inicjalizacja lcd
		cbi	PORTD,E		;-E

		;musimy poczekac z 1s
		sbi	PORTD,ZIEL	;zapalam zielona
		in	temp2,PORTD
p1:		in	temp,PORTD	;czekam na zmiane stanu diodki - powinna mignac po ok. 1s
		cp	temp,temp2
		breq	p1
		cbi	PORTB,CZER	;gasze czewona

		rozkaz	temp,0b00111000	;8 bit,2 linie,5x8
		rozkaz	temp,0b00001111	;display on,cursor on, cursor blink
		rozkaz	temp,0b00000110	;inc address, shift cursor
		rozkaz	temp,0b00000001	;cls
		ldi	licznik,0
		
;		sbi	PORTD,CZER	;zaswiec czerwona

;glowna petla programu
kolko:	
		ld	temp,Y
		cpi	temp,0
		breq	kolko

		out	UDR,temp		
		inc	yl
		adc	yh,temp

		ldi	temp2,7
		ldi	temp,0
k1:		nop10
		dec	temp
		brne	k1
		dec	temp2
		brne	k1

;		cbi	PORTD,ZIEL
;		ldi	temp,255
;		ldi	temp2,255
;k2:		nop10
;		dec	temp
;		brne	k2
;		dec	temp2
;		brne	k2
;		sbi	PORTD,ZIEL
		
		rjmp	kolko		;nic nie robi, bo od teraz wszystko jest na przerwaniach


;*** obsluga przerwan ***

;odbior znaku z uarta
.def	znak=r17
odbior:
		in	znak,UDR	;odczyt bajtu
		;out	UDR,znak	;wyslanie echa
		
;sprawdzamy <F1=continue
		ld	itemp,X+
		cpi	itemp,0		;ostatni bajt?
		brne	f1_1
		ld	itemp,Y		;jest F1, sprawdzenie czy cos teraz wysylamy
		cpi	itemp,0
		brne	f1_2
		ldi	yl,low(f1echo)	;nie wysylamy: odpowiadamy
		ldi	yh,high(f1echo)
		;ldi	itemp,'!'
		;out	UDR,itemp
		rjmp	f1_2
f1_1:		cp	itemp,znak	;odebrany znak to nastepny?
		breq	odb1
f1_2:		ldi	xl,low(f1cont)	;znaki sie nie zgadzaja - reset wskaznika
		ldi	xh,high(f1cont)
		;ldi	itemp,'-'
		;out	UDR,itemp
;koniec F1
		
odb1:		cpi	licznik,74	;sprawdzenie czy to juz 74 znak (pierwszy poza ekranem)
		brne	dalej
		cpi	znak,35		;sprawdzenie czy to nie #
		brne	dalej
		ldi	watchdog,WATCHTIME	;wlaczenie watchdoga
		
dalej:
		cpi	znak,13		;sprawdzenie czy to entery
		breq	enter
		cpi	znak,10
		breq	enter
		wyslij	znak
		inc	licznik
		rjmp	migaj
enter:		rozkaz	itemp,0b00000010	;return home
		ldi	licznik,0
migaj:		in	itemp,PORTD
		ldi	itemp2,32		;mrugaj czerwona
		eor	itemp,itemp2
		out	PORTD,itemp
		
		cpi	watchdog,0	;watchdog wlaczony?
		breq	odbiorend
		ldi	watchdog,WATCHTIME
odbiorend:	reti


;obsluga przerwan z timera
diodka:		
		in	itemp,PORTD	;miganie diodka
		ldi	itemp2,32	;2^5
		eor	itemp,itemp2
		out	PORTD,itemp
;		cbi	PORTD,ZIEL
		
		cbi	DDRD,RES	;ustawienie RES na wejscie - zdjecie reseta
		
		cpi	watchdog,0	;sprawdzenie czy watchdog jest wlaczony
		breq	diodka1
		dec	watchdog
		brne	diodka1
		
		;tutaj dziala watchdog!
		sbi	DDRD,RES	;ustawiam na wyjscie RES - reset (bo jest 0 na wyjsciu)		
		;rozkaz  temp,0b00000001 ;cls
diodka1:	reti
		
;dane
f1ee:		.db	"<F1= Continue>",0,0
;f1ec:		.db	"dupa jasiu karuzela!",0,0
f1ec:		.db	27,'O','P',0,0,0

;segment danych		
.dseg
f1cont:		.byte	20
f1echo:		.byte	50
