	list 	p=18f4620, R=DEC
	include "p18f4620.inc"
 	
	config	WDT = OFF,	MCLRE = OFF, OSC = INTIO67, LVP = OFF, FCMEN = OFF
	config	IESO = OFF,	PWRT = ON, PBADEN = OFF, LPT1OSC = OFF


#define		RS			PORTD,2
#define		E			PORTD,1
#define		LCD_PORT	PORTD


	cblock	0x20
	TMP0
	TMP1
	TMP2
	TMP3
	ZNAK
	IN
	endc


;NASTAVENI A promenne pro LCD + MACRa
     CONSTANT  LCDL1 = 0x80
     CONSTANT  LCDL2 = 0xC0
     CONSTANT  LCDL3 = 0x94
     CONSTANT  LCDL4 = 0xD4

; base frequency
XTAL_FREQ   EQU   40000000   ; OSC freq in Hz
; used for I2C calculations
#define  I2CClock    D'400000'           ; define I2C bite rate
#define  I2C_ClockValue  (((XTAL_FREQ/I2CClock)/4) -1) ;  

 

;****************************************************************************
;* 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
;********************************************************************	
;* 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

INIT
	banksel	OSCCON
	movlw	b'01100010'
	movwf	OSCCON

	CLRF    LATA         ; vynulovat PORTA jako OUT
    MOVLW   b'00000000'    ; A/D 
    MOVWF   ADCON1        ; digital inputs
    MOVLW   b'10111110'    ; 
    MOVWF   ADCON2        ; vlevo,20 TAD,FOSC/64
    MOVLW   b'00000000'    ; 
    MOVWF   ADCON0        ; A/D ON 

	MOVLW    b'00100111'    ; 0 out, 1 in
	MOVWF	TRISA        ; 
	MOVlw    b'00000111'    ; Comparators OFF
    MOVWF    CMCON        ; digital input

;nastaveni PORTA;	CLRF	PORTA		; vynulovat PORTA
;	CLRF	LATA 		; vynulovat PORTA jako OUT
;	MOVLW	b'00001101'	; A/D 
;	MOVWF	ADCON1		; digital inputs
;	MOVLW	b'10000010'	; 
;	MOVWF	ADCON2		; vlevo,20 TAD,FOSC/64
;	MOVLW	b'00000001'	; 
;	MOVWF	ADCON0		; A/D ON 
;	
;	MOVLW	b'11101111'	; 0 out, 1 in
;	MOVWF	TRISA		; 
;	MOVlw	b'00000111'	; Comparators OFF
;	MOVWF	CMCON		; digital input
;nastaveni PORTB
	CLRF 	PORTB 		; vynulovat PORTB 
	CLRF 	LATB 		; vynulovat PORTB jako OUT
;	MOVLW	b'00001111'	; A/D 
;	MOVWF	ADCON1		; digital inputs PBADEN nastavit v cofigU
	MOVLW	b'00000001'	; 0 out, 1 in
	MOVWF	TRISB 	
;nastaveni PORTC
	CLRF 	PORTC 		; vynulovat PORTC 
	CLRF 	LATC 		; vynulovat PORTC jako OUT
	MOVLW	b'00011000'	; 0 out, 1 in
	MOVWF	TRISC 	
;nastaveni PORTD
	CLRF 	PORTD 		; vynulovat PORTD 
	CLRF 	LATD 		; vynulovat PORTD jako OUT
	MOVLW	b'00000000'	; 0 out, 1 in
	MOVWF	TRISD	
;nastaveni PORTE
	CLRF 	PORTE 		; vynulovat PORTC 
	CLRF 	LATE 		; vynulovat PORTC jako OUT
	MOVLW	b'00000000'	; 0 out, 1 in
	MOVWF	TRISE 	

	call	INI_LCD
	LCDc
	call	INIT_SPI
	
MAIN


	banksel	0

	


	LCDline	.2
	LCDout	'S'
	LCDout	'S'
	LCDout	'P'
	LCDout	'S'
	LCDout	'T'
	LCDout	'A'
	LCDout	'T'
	LCDout	' '
	lfsr	0,SSPSTAT
	movlw	'1'
	btfss	INDF0,7
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,6
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,5
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,4
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,3
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,2
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,1
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,0
	movlw	'0'
	LCDw	

	LCDline	.3
	LCDout	'S'
	LCDout	'S'
	LCDout	'P'
	LCDout	'C'
	LCDout	'O'
	LCDout	'N'
	LCDout	' '
	LCDout	' '
	lfsr	0,SSPCON1
	movlw	'1'
	btfss	INDF0,7
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,6
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,5
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,4
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,3
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,2
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,1
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,0
	movlw	'0'
	LCDw	
	
	LCDline	1
	LCDout	'P'
	LCDout	'r'
	LCDout	'i'
	LCDout	'j'
	LCDout	'e'
	LCDout	'm'
	LCDout	' '
	BANKSEL	SSPSTAT
	btfss	SSPSTAT,BF
	bra		MAIN
	banksel	SSPBUF
	movf	SSPBUF,w
	banksel	IN
	movwf	IN
	LCDw

	LCDcmd	LCDL1+10
	lfsr	0,IN
	movlw	'1'
	btfss	INDF0,7
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,6
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,5
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,4
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,3
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,2
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,1
	movlw	'0'
	LCDw	
	movlw	'1'
	btfss	INDF0,0
	movlw	'0'
	LCDw	
	goto	MAIN

INIT_SPI
;slave
	movlw	b'00000101'
	movwf	SSPCON1

	movlw	b'00000000'
	movwf	SSPSTAT

	bsf		SSPCON1,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