st7/

;------------------------------------------------------------------------------
; PROGRAM REALIZUJACY KOMUNIKACJE "PC => MIKROSTEROWNIK"
; Z OBSLUGA EKRANU LCD
;------------------------------------------------------------------------------

	.NOLIST
	#INCLUDE "ST7FLITE25.inc"
	.LIST

	MOTOROLA           	

; Przypisania pinow --------------------
; RxD => PB6
; SPK <= PB1
; LD0 <= PB0
;---------------------------------------

	#define	RxD			$6			; port do odbioru danych
	
	#define	BW			$0			; bajt odebrany?
	#define START_ERR 	$1			; blad bitu startu
	#define STOP_ERR 	$2			; blad bitu stopu
	#define DATA_ERR 	$3			; blad probkowania danych


    	segment byte at 80-FF		'ram0'
    	segment byte at 100-1FF		'stack'
    	segment byte at 200-27F		'ram1'
    	segment byte at FC00-FFDF	'rom'
    	segment byte at FFE0-FFFF	'vectit'
    
        BYTES
        segment 'ram0'

.bajt    	DS.B    1		; odbierany bajt
.odczyt		DS.B	1		; odczyt z probkowania
.licznik	DS.B	1		; licznik timera
.licznik4	DS.B	1		; licznik 2-bitowy
.status		DS.B	1		; status transmisji
.czekaj     DS.B    1 		; opoznienie LCD

        WORDS
        segment 'rom'
          

;------------------------------------------------------------------------------
; START PROGRAMU
;------------------------------------------------------------------------------
.main
	ld		A, #$80			; poczatkowa dokladnosc oscylatora 
	ld		RCCR, A			; równa polowie przedzialu
	call 	sci_init		; inicjalizacja ukladu
	
.loop
	clr		status			; wyczysc status transmisji
	call	odbierz			; odbierz dane
	call	Init_lcd		; zainicjalizuj i wyczysc LCD
	
	ld		A, bajt			; odczytaj otrzymany bajt
	call	Send_lcd_data	; wyswietl znak i pojedyncza spacje
	ld		A, #' '
	call	Send_lcd_data

; wyswietlanie formatu ramki na LCD

	btjt	status, #START_ERR, blad_st		; wyswietl bit startu
	ld 		A, #'0'
	jra ddata

blad_st
	ld 		A, #'1'
	
ddata
	call	Send_lcd_data
	ld		X, #8			; wyswietl bajt od LSB
loopdata
	rrc		bajt
	jrc		s1
	ld 		A, #'0'
	jp		dd
s1
	ld 		A, #'1'
dd
	call	Send_lcd_data
	dec		X
	jrne	loopdata
	
	btjt status, #STOP_ERR, blad_stop		; wyswietl bit stopu
	ld 		A, #'1'
	jra dstop

blad_stop
	ld 		A, #'0'
	
dstop
	call	Send_lcd_data

	jp 		loop			; zapetl w nieskonczonosc

;------------------------------------------------------------------------------
; INICJALIZACJA PORTÓW
;------------------------------------------------------------------------------
.sci_init
	
	ld      A,#$FF			; Port A - zarezerwowany dla LCD
	ld      PADDR,A
	ld      PAOR,A
	ld		A,#$00
	ld		PADR,A
	
	bres	PBOR,#RxD       ; PB6 = RxD; input; floating
	bres	PBDDR,#RxD  
	
	bset	PBDDR,#1        ; PB1 = SPK; output; push-pull
    bset	PBOR,#1
	bset	PBDR,#1
	
	bset	PBDDR,#0        ; PB0 = LED; output; push-pull
    bset	PBOR,#0
	bset	PBDR,#0
			
	bset	PBOR,#2       	; PB2 = SW3; input; pull-up; with interrupt
    bset	PBDDR,#2
 
	ret

;------------------------------------------------------------------------------
; PROCEDURA RXD
;------------------------------------------------------------------------------
.odbierz
	
	clr		licznik			; zeruj licznik wyslanych bitow
	clr		status			; wyczysc status transmisji
	clr		bajt			; wyczysc przesylany bajt

	ld 		A, #$10			; wlacz licznik, ale bez przerwania
	ld		ATCSR, A		; F = F_cpu
	ld		A, #$2F			; zaladuj wartosc wyliczona jako:
	ld		ATRL, A			; 8000000 MHz / 9600 bps / 4 = D0h
	ld		A, #$0F			; FFF - DOh = F2F
	ld		ATRH, A
		
	; start przerwania portu P7
	
	ld		A, #$20 
	ld		EICR, A			; ustaw opadajace zbocze
	ld		A, #$30
	ld		EISR, A			; ustaw PB6
	bset	PBOR, #RxD		; PB6 = input; pull-up; with interrupt
	bres	PBDDR, #RxD        
	
	rim						; odblokuj przerwania
	
.loop_transm
	wfi						; wfi - wait for interrupt
	btjf 	status, #BW, loop_transm	; sprawdz czy skonczylo sie odbieranie
	
	ld 		A, #$00
	ld		ATCSR, A		; wylacz licznik
	ld		A,#$00     		
	ld		LTCSR1,A
	
	sim						; zablokuj przerwania
	
	bset	PBDR, #0		; zgas diode
	ret

;------------------------------------------------------------------------------
; PRZERWANIE TIMERA
;------------------------------------------------------------------------------
.timer
	ld		A, ATCSR		; wyczysc flage przerwania OVFIE

	bres	PBDR,#1			; wlacz buzzer
	ld		A, licznik		; wczytaj licznik (*)
	
	; stany licznika odpowiadajace zdarzeniom w transmisji:
	; 0 - omin
	; 1 - bit startu
	; 5, 9, 13, 17, 21, 25, 29, 33 - dane
	; 37 - stop
	; 41 - koniec
	
not_null
	cp 		A, #00			; (*) jesli jest zerem to zaczekaj cykl
	jreq	poczatek
	cp 		A, #01			; jesli jest jedynka to odbierz bit startu,
	jreq	bit_startu
	cp 		A, #37			; jesli jest rowny 37 to odbierz bit stopu
	jreq	bit_stopu
	cp 		A, #41			; jesli jest rowny 41 to zakoncz odbior
	jreq	koniec_transmisji
	ld		A, licznik4		; w co czwartym przebiegu licznika odbierz dane
	cp		A, #3
	jreq	dane
	
	inc		licznik4		; zwieksz licznik liczacy od 0 do 3
	jp		koncz

dane						; odbierz dane
	clr		licznik4		; wyzeruj licznik czworek
	call 	pobierz_probki	; odczytaj 3 razy pod rzad zawartosc portu
	rrc		bajt			; obroc bajt w prawo
	btjt	odczyt, #0, dod1	; ustaw najstarszy bit bajtu
	bres	bajt, #7
	jp		koncz
dod1
	bset	bajt, #7
	jp		koncz

poczatek					; pierwszy przebieg licznika
	clr		licznik4		; tylko zwieksz licznik, nie rob nic wiecej
	jp		koncz
	
bit_startu					; odbior bitu startu
	clr		licznik4
	call 	pobierz_probki
	btjf	odczyt, #0, koncz	; sprawdz czy bit startu jest zerem
	bset	status, #START_ERR	; blad! ustaw status
	jp		koncz

bit_stopu					; odbior bitu stopu
	clr		licznik4
	call 	pobierz_probki
	btjt	odczyt, #0, koncz	; sprawdz czy bit stopu jest jedynka
	bset	status, #STOP_ERR	; blad! ustaw status
	jp		koncz

koniec_transmisji
	bset	status, #BW		; ustaw zmienna "status"

koncz
	inc		licznik			; zwieksz i zapisz licznik
	bset	PBDR,#1			; wylacz buzzer
	iret

;------------------------------------------------------------------------------
; POBRANIE PROBEK
;------------------------------------------------------------------------------
pobierz_probki
	clr		odczyt			; wyczysc odczyt
	ld		A, PBDR			; pobierz wartosci portu A
	rlc		A				; przestaw bit 7 na pozycje 0
	rlc		A
	rlc		A
	and		A, #1			; uwzglednij tylko pin 7
	ld		odczyt, A		; zaladuj do zmiennej "odczyt"
	
	ld		A, PBDR			; pobierz wartosci portu A
	rlc		A				; przestaw bit 7 na pozycje 0
	rlc		A
	rlc		A
	and		A, #1			; uwzglednij tylko pin 7
	add 	A, odczyt
	ld		odczyt, A
	
	ld		A, PBDR			; pobierz wartosci portu A
	rlc		A				; przestaw bit 7 na pozycje 0
	rlc		A
	rlc		A
	and		A, #1			; uwzglednij tylko pin 7
	add 	A, odczyt
	ld		odczyt, A
	
	cp		A, #0			; jesli odczyt == 0 to OK
	jrne	spr_1
	jra		koniec_pob

spr_1
	cp		A, #3			; jesli odczyt == 3 to tez OK
	jrne	blad
	jra		koniec_pob
	
blad
	bset	status, #DATA_ERR	; w przeciwnym wypadku blad probkowania!

koniec_pob
	ret

;------------------------------------------------------------------------------
; PRZERWANIE PORTU B6
;------------------------------------------------------------------------------
.p7int

	bres	PBDR, #0		; zapal diode
	ld 		A, #$12
	ld		ATCSR, A		; OVFIE enabled, F = F_cpu
	bres	PBOR, #RxD      ; wylacz przerwanie P7

	iret

;------------------------------------------------------------------------------
; PROCEDURY OBSLUGI LCD
;------------------------------------------------------------------------------

.Send_lcd_reg  				; argument (data) in A
        
	push	X 
	push	Y
	ld		X,#2            ; counter        
	ld		Y,A             
	srl		A               
	srl		A		

sekcja_1                	; write to LCD 4 most important bits of 8-bit data

	and		A,#$FC          ; RS=0, E=0
	ld		PADR,A          
	nop
	nop
	push	A		
	or		A,#$02          ; RS=0, E=1
	ld		PADR,A          

	nop
	nop
	
	pop		A				; RS=0, E=0
	ld		PADR,A          
	
	nop
	nop
	
	ld		A,Y             
	sll		A               
	sll		A              
	dec		X
	jrne	sekcja_1    	; write to LCD 4 least important bits of 8-bit data

	pop		Y
	pop		X
        
    ld		A,#10
	ld		czekaj,A  	
	call	Delay
        
	ret
	
;---------------------------------------------------------------------------------

.Send_lcd_data  			; argument (data) in A
	
	push	X 
	push	Y
	ld		X,#2            ; counter
	ld		Y,A		
	srl		A               
	srl		A               
	
sekcja_2               		; write to LCD 4 most important bits of 8-bit data
        
        and		A,#$FC         
        push	A        	
        or		A,#$01      ; RS=1, E=0
        ld		PADR,A          

        nop
        nop
        
        pop		A
        push	A        	
        
        or		A,#$03      ; RS=1, E=1
        ld		PADR,A          

        nop
        nop

        pop		A        	

        or		A,#$01      ; RS=1, E=0
        ld		PADR,A          

        nop
        nop
        
        ld		A,Y             
        sll		A               
        sll		A               
        dec		X
        jrne	sekcja_2    ; write to LCD 4 least important bits of 8-bit data
        
        pop		Y
        pop		X
        
       	ld		A,#10
        ld		czekaj,A  	
	call	Delay
 
        ret         
;--------------------------------------------------------------------------------

.Init_lcd
        
        ld		A,#50		; wait for 65 ms
        ld      czekaj,A 
        call	Delay 
        
        ld		Y,#3
        
sekcja_3                	; initialization of LCD display
	ld	A,#$0C	
	ld	PADR,A
	
	nop
	nop
	
	or	A,#$02 
        ld		PADR,A
        
        nop
        nop
        
        ld		A,#$0C
        ld		PADR,A
        ld		A,#5
        ld		czekaj,A
        call	Delay         	; wait for 6.5ms
        dec	Y
        jrne	sekcja_3 

; configuration of LCD

		ld		A,#$08
        ld		PADR,A
	
	nop
	nop
	
	or		A,#$02 
	ld		PADR,A

	nop
	nop
	
	ld		A,#$08
	ld		PADR,A
    ld		A,#5
	ld		czekaj,A
	call	Delay
	ld		A,#$28			; 2 lines, 4 bits
	call	Send_lcd_reg
	ld		A,#2          
	ld      czekaj,A 
	call	Delay			; wait for 2.6ms
	ld		A,#$0C			; cursor: on, LCD: on
	call	Send_lcd_reg
	ld		A,#2          
	ld      czekaj,A 
	call	Delay
	ld		A,#$06			; inc.
	call	Send_lcd_reg
	ld		A,#2
	ld      czekaj,A       
	call	Delay
	ld		A,#$01			; clear LCD
	call	Send_lcd_reg
	ld		A,#2            
	ld      czekaj,A 
	call	Delay
    ld		A,#$02			; cursor home
    call	Send_lcd_reg
	ld		A,#2            
	ld      czekaj,A 
	call	Delay

	ret

;------------------------------------------------------------------------------
; PRZERWANIE LICZNIKA "LITE TIMER 1"
;------------------------------------------------------------------------------
.opoznienie
	ld		A, LTCSR1			; wyczysc flage przerwania
	ld		A, czekaj
	and		A, #$FF
	jreq	kon4  				; if czekaj==0 (Z=1) then jump to koniec
	dec	A               
	ld	czekaj,A
	
kon4	
	iret

;------------------------------------------------------------------------------
; PROCEDURA OPOZNIAJACA
;------------------------------------------------------------------------------
.Delay
	push	A 
	ld		A, #$30		; f_timer=f_CPU/64, czas miedzy OV ok. 2 ms
	ld		LTCSR1,A		        
	rim
	
petla	
	ld		A,czekaj
	and		A,#$FF
	jreq	koniec_1	; if czekaj==0 (Z=1) then jump to koniec_1  
	JP	petla
	
koniec_1       
	clr		LTCSR1
	sim
	pop	A

	ret
	
;------------------------------------------------------------------------------
; PRZERWANIA
;------------------------------------------------------------------------------
.dummy   iret           	; pusta funkcja obslugi przerwania

        segment 'vectit'

                DC.W    dummy          	;FFE0-FFE1h location 
                DC.W    dummy           ;FFE2-FFE3h location
                DC.W    opoznienie      ;FFE4-FFE5h location  
.sci_it         DC.W    dummy           ;FFE6-FFE7h location  
.timb_it        DC.W    timer	       	;FFE8-FFE9h location  
.tima_it        DC.W    dummy           ;FFEA-FFEBh location  
.spi_it         DC.W    dummy           ;FFEC-FFEDh location               
                DC.W    dummy           ;FFEE-FFEFh location
                DC.W    dummy           ;FFF0-FFF1h location                 
.ext3_it        DC.W    dummy           ;FFF2-FFF3h location                       
.ext2_it        DC.W    p7int           ;FFF4-FFF5h location  
.ext1_it        DC.W    dummy           ;FFF6-FFF7h location             
.ext0_it        DC.W    dummy           ;FFF8-FFF9h location 
                DC.W    dummy           ;FFFA-FFFBh location                      
.softit         DC.W    dummy           ;FFFC-FFFDh location                       
.reset          DC.W    main            ;FFFE-FFFFh location


	END
