
	list p=16f887, R=DEC
	include "p16f887.inc"
 	

	__CONFIG _CONFIG1 ,_INTRC_OSC_NOCLKOUT & _PWRTE_ON & _WDT_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF &  _DEBUG_OFF
	__CONFIG _CONFIG2 ,_BOR40V & _WRT_OFF;	errorlevel -302 ; Register in operand not in bank 0.  Ensure that bank bits are correct.

;	errorlevel -306 ; Crossing page boundary -- ensure page bits are set.
;	errorlevel -202 ; Argument out of range.  Least significant bits used.


	cblock	0x20
	TMP0
	TMP1
	TMP2
	TMP3
	ZNAK
	SPI_IN
	SPI_OUT
	
	endc

#DEFINE		LCD_PORT	PORTD
#DEFINE		E		PORTD,3
#DEFINE		RS		PORTD,2
#DEFINE		PIN_SS	PORTD,0
;****************************************************************************
;* Definice vlastnich maker													*
;********************************************************************	
;* LCDout		zobrazeni znaku na LCD display
;* LCDw			zobrazeni znaku co je v registru W
;* LCDline		na kterem radku se ma zobrazit text
;* LCDc			smaze LCD
;NASTAVENI A promenne pro LCD + MACRa
     CONSTANT  LCDL1 = 0x80
     CONSTANT  LCDL2 = 0xC0
     CONSTANT  LCDL3 = 0x94
     CONSTANT  LCDL4 = 0xD4
;********************************************************************	
;* Zobrazi znak 'a' na LCD display									*
;* LCDout	'a'														*
;********************************************************************
LCDout   macro   _LCDout
   movlw   _LCDout
   call   WR_LCD
   endm

;********************************************************************
;* Zobrazi znak co je v registru W									*
;* MOVLW	0x02													*
;* LCDw																*
;********************************************************************
LCDw   macro
   call   WR_LCD
   endm

;********************************************************************
;* Zapis prikazu do LCD display										*
;********************************************************************
LCDcmd   macro   _LCDcmd
   movlw   _LCDcmd
   call   WR_CMD
   endm
;********************************************************************
;* Zapis prikazu do LCD display										*
;********************************************************************
LCDc   macro
   movlw   .1
   call   WR_CMD
   endm
;********************************************************************
;* Na kterem radku se ma zobrazit text								*
;* LCDline	.1				; text se zobrazi na 1 radku			*
;* LCDline	.2				; text se zobrazi na 2 radku			*
;* LCDline	.3				; text se zobrazi na 3 radku			*
;* LCDline	.4				; text se zobrazi na 4 radku			*
;********************************************************************
LCDline   macro   line_num
   IF (line_num == 1)
     LCDcmd LCDL1      ; first line
   ELSE
     IF (line_num == 2)
       LCDcmd LCDL2   ; second line
     ELSE
       IF (line_num == 3)
         LCDcmd LCDL3   ; third line
       ELSE
         IF (line_num == 4)
           LCDcmd LCDL4   ; fourth line
          ELSE
           ERROR "Za LCDLINE nasleduje cislo 1 - 4!!"
         ENDIF
       ENDIF
     ENDIF
   ENDIF
   endm
	org		0x000
	goto	INIT

;************************ Inicializace procesoru  *************************
INIT
	banksel	OSCCON
	movlw	b'01100001'
	movwf	OSCCON

;portA
	banksel	TRISA		; vyber banky
	movlw	b'00000000'	; 0 vstup, 1 vystup
	movwf	TRISA		; sup do TRISu
;PORTB
	banksel	ANSELH
	movlw	b'00000000'
	movwf	ANSELH
	banksel	TRISB		; vyber banky
	movlw	b'11111111'	; 0 vstup, 1 vystup
	movwf	TRISB		; sup do TRISu
	banksel	WPUB
	movlw	b'11111111'	; 
	movwf	WPUB		; 
;vypnuti AD	
	banksel	ADCON0		; vyber banky
	movlw	b'00000000'	; FRC,ADC is OFF			
	movwf	ADCON0		
	
	banksel	ADCON1		; vyber banky
	movlw	b'00000000'	; 
	movwf	ADCON1		; 

;PORTC
	banksel	TRISC		; vyber banky
	movlw	b'00010000'	; 0 vstup, 1 vystup
	movwf	TRISC		; sup do TRISu
;PORTD
	banksel	TRISD		; vyber banky
	movlw	b'00000000'	; 0 vstup, 1 vystup
	movwf	TRISD		; sup do TRISu
;PORTE
	banksel	TRISE		; vyber banky
	movlw	b'00000000'	; 0 vstup, 1 vystup
	movwf	TRISE		; sup do TRISu

	banksel	OPTION_REG
	bcf		OPTION_REG,7

	banksel 0
	CALL	CEK1s
	CALL	CEK1s
	CALL	CEK1s
	movlw	'0'
	movwf	SPI_OUT


	bcf		PIN_SS
	call	INI_LCD 
	call	SPI_MASTER
	LCDc
	LCDline	.1
	LCDout	'S'
	LCDout	'e'
	LCDout	'n'
	LCDout	'd'
MAIN
	banksel	0
	incf	SPI_OUT

	banksel	SSPSTAT
	movlw	PORTB
	movwf	FSR
	btfsc	INDF,0
	bsf		SSPSTAT,CKE

	banksel	SSPCON
	movlw	PORTB
	movwf	FSR
	btfsc	INDF,1
	bsf		SSPCON,CKP

	bsf		SSPCON,SSPEN


	banksel	SSPBUF
	movf	SSPBUF,w
	
	LCDline	.4
	LCDout	'P'
	LCDout	'O'
	LCDout	'R'
	LCDout	'T'
	LCDout	' '
	LCDout	' '
	LCDout	' '
	LCDout	' '
	movlw	PORTB
	movwf	FSR
	movlw	'1'
	btfss	INDF,7
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,6
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,5
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,4
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,3
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,2
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,1
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,0
	movlw	'0'
	LCDw

	LCDline	.2
	LCDout	'S'
	LCDout	'S'
	LCDout	'P'
	LCDout	'S'
	LCDout	'T'
	LCDout	'A'
	LCDout	'T'
	LCDout	' '
	movlw	SSPSTAT
	movwf	FSR
	movlw	'1'
	btfss	INDF,7
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,6
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,5
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,4
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,3
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,2
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,1
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,0
	movlw	'0'
	LCDw

	LCDline	.3
	LCDout	'S'
	LCDout	'S'
	LCDout	'P'
	LCDout	'C'
	LCDout	'O'
	LCDout	'N'
	LCDout	' '
	LCDout	' '
	movlw	SSPCON
	movwf	FSR
	movlw	'1'
	btfss	INDF,7
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,6
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,5
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,4
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,3
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,2
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,1
	movlw	'0'
	LCDw
	movlw	'1'
	btfss	INDF,0
	movlw	'0'
	LCDw


	


	banksel	0
	call	CEK1s



	banksel	SSPBUF
	movf	SPI_OUT,w
	movwf	SSPBUF

	banksel	0
	LCDcmd	LCDL1+5

	movf	SPI_OUT,w
	LCDw
	goto	MAIN

SPI_MASTER
	banksel	SSPCON
	movlw	b'00000010'
	movwf	SSPCON

	banksel	SSPSTAT
	movlw	b'00000000'
	movwf	SSPSTAT
	


	bsf		SSPCON,SSPEN
	return

;**************************************************************************
; Podprogram na obsluhu LCD
;**************************************************************************
WR_CMD
   banksel   0
   bcf      RS            ; RS=0, zápis instrukcí do LCD
   goto  	WR_LCD1
;-------------------------------
WR_LCD   
   banksel   0
   bsf      RS            ; RS=1, zápis dat do LCD
;       ------------------------
WR_LCD1
   movwf   ZNAK         ; ulozit W do ZNAK   !!! data v registru W !!!
   bsf      E            ; nastav Enable
;       ------------------------
   movf   LCD_PORT,W      ; zapamatovat stav PORTuD
;   iorlw   0x0F         ; !!! poslat na PORTD 0-3 !!! (vysledek je xxxx1111)
   iorlw   0xF0         ; !!! poslat na PORTD 4-7 !!! (vysledek je 1111xxxx)
   movwf   TMP1         ; zapise W do TMP1
;-------------------------------
;   swapf   ZNAK,W         ; !!! poslat na PORTD 0-3 !!!
;   iorlw   0xF0         ; zamaskuje horní bity (vysledek je 1111xxxx)

   movf   ZNAK,W         ; !!! poslat na PORTD 4-7 !!!
   iorlw   0x0F         ; zamaskuje dolní bity (vysledek je xxxx1111)

   andwf   TMP1,W         ; pošle vyšší 4 bity na PORTD
   movwf   LCD_PORT
   bcf      E            ; zapíše do LCD
;-------------------------------
   bsf      E            ; nastav Enable

;   movf   ZNAK,W         ; !!! poslat na PORTD 0-3 !!!
;   iorlw   0xF0         ; zamaskuje horní bity (vysledek je 1111xxxx)

   swapf   ZNAK,W         ; !!! poslat na PORTD 4-7 !!!
   iorlw   0x0F         ; zamaskuje dolní bity (vysledek je xxxx1111)

   andwf   TMP1,W         ; pošle nižší 4 bity na PORTD
   movwf   LCD_PORT
   bcf      E            ; zapíše do LCD
;-------------------------------
   btfsc   RS
   goto   CEK40         ; RS=1, zápis dat - čekej 40 us
;       ------------------------
   movlw   04h            ; instrukce 1, 2 a 3 - čekej 1,64 ms
   subwf   ZNAK,W
   btfss   STATUS,C
   goto   CEK1m6         ; C=0, instrukce CLEAR - čekej 1,64 ms
   goto   CEK40         ; C=1, zápis dat - čekej 40 us
;**************************************************************************
;**************************************************************************
INI_LCD   
   call   CEK15m         ; cekej 15ms
   bcf      RS            ; zapis ridicich instrukci do LCD
;-------------------------------
   movlw   30h            ; !!! poslat 03h na PORTD 4-7 (vstupy LCD DB4-DB7) !!!
;   movlw   03h            ; !!! poslat 03h na PORTD 0-3 (vstupy LCD DB4-DB7) !!!
   movwf   LCD_PORT
;       ------------------------
   bsf      E
   bcf      E
   call   CEK4m         ; cekej 4,1ms
;       ------------------------
   bsf      E
   bcf      E
   call   CEK100         ; cekej 100us
;       ------------------------
   bsf      E
   bcf      E
   call   CEK40         ; cekej 40us
;-------------------------------
   movlw   20h            ; !!! poslat 03h na PORTB 4-7 (vstupy LCD DB4-DB7) !!!
;   movlw   02h            ; !!! poslat 03h na PORTB 0-3 (vstupy LCD DB4-DB7) !!!
   movwf   LCD_PORT      ; nastavena 4-bitova komunikace
;       ------------------------
   bsf   E
   bcf   E
   call   CEK40         ; cekej 40us
;-------------------------------
   movlw   28h            ; 00101000 - počet bitů, 2 řádky, 5x7 znaky
   call   WR_CMD
   movlw   0Ch            ; 00001100 - display ON, kurzor OFF, blikání OFF
   call   WR_CMD
   movlw   01h            ; 00000001 - smaže displej, kurzor na pozici 0
   call   WR_CMD
   movlw   06h            ; 00000110 - směr kurzoru, posunu displeje
   call   WR_CMD
;       ------------------------
   return
;**************************************************************************


;**************************************************************************
; časy pro frekvenci krystalu 4,00Mhz
; časy jsou spočítané od call CEKxxm do návratu na volání CEKxxm
; celkový výpočet  = 2+6+(2+(TMP0-1)*3+2)+3)*TMP1-1+2
; zkrácený výpočet = 8+((TMP0-1)*3+7)*TMP1+1
; malá smyčka = (TMP2-1)*3+2
;-------------------------------
CEK2s	movlw	.20		; TMP2 = 20  cekej 2 sekundu
	movwf	TMP3
	goto	SMYCKA2
;-------------------------------
CEK1s	movlw	.10		; TMP2 = 10  cekej 1 sekundu
	movwf	TMP3
	goto	SMYCKA2
;-------------------------------
CEK100m	movlw	0CFh		; cas = 100,009 ms
	movwf	TMP0
	movlw	0A0h
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
CEK15m	movlw	0ABh		; cas = 15,002 ms
	movwf	TMP0
	movlw	01Dh
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
CEK4m	movlw	0A5h		; cas = 4,001 ms
	movwf	TMP0
	movlw	008h
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
CEK1m6	movlw	041h		; cas = 1,601 ms
	movwf	TMP0
	movlw	008h
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
CEK100	movlw 	01Dh		; cas = 100 mikrosekund
	movwf	TMP0
	movlw	001h
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
CEK40	movlw	009h		; cas = 40 mikrosekund
	movwf	TMP0
	movlw	001h
	movwf	TMP1
	goto	SMYCKA
;-------------------------------
SMYCKA2	call	CEK100m
	decfsz	TMP3,F		; největší smyčka
	goto	SMYCKA2
	retlw	00h
;-------------------------------
SMYCKA	movf	TMP0,W
	movwf	TMP2
;       ------------------------
SMYCKA1	decfsz	TMP2,F		; malá smyčka
	goto	SMYCKA1
;       ------------------------
	decfsz	TMP1,F		; velká smyčka
	goto	SMYCKA
;       ------------------------
	retlw	00h
;**************************************************************************

	END
