;
;					ESEMPIO 2.23
;
;				Autore: Mikel Etxebarria
;			(c) Microsystems Engineering (Bilbao)
;
;Esempio per simulazione e/o MicroPIC Trainer
;
;L'uso dello schermo LCD. Un semplice generatore di messaggi.
;
;Questo esempio vuole realizzare un generatore di messaggi per l'LCD. Con RA4 a "1", il
;sistema è nel modo di programmazione. In questo modo il messaggio è registrato nella EEPROM
;di dati. Con RA4 a "0" entriamo nel modo di riproduzione. Il messaggio registrato nella
;EEPROM viene visualizzato sull'LCD.
; 
;Quando l'interruttore RA3 è a livello "1", nella posizione attuale del cursore appaio-
;no sequenzialmente i distinti caratteri disponibili. Mettendolo a "0" si sele-
;ziona l'attuale e si registra nella EEPROM. Ritornando di nuovo a "1" si seleziona il se-
;guente carattere.
;
;Va ricordato che le linee RA0-RA2 ora agiscono come uscita di segnali di controllo verso 
;l'LCD. Essendo connesse ai propri interruttori nel MicroPIC Trainer, questi devono
;essere permanentemente a livello logico "1" .

		List	p=16F84		;Tipo di processore
		include	"P16F84.INC"	;Definizioni di registri interni
                    		
Lcd_var		equ	0x0c		;Variabili (2) delle procedure d'uso dell'LCD
Delay_Cont	equ	0x0e		;Variabile per la temporizzazione
Temporale_1	equ	0x0f		;Variabile temporale
Temporale_2	equ	0x10		;Variabile temporale
Cur_Pos		equ	0x11		;Posizione del cursore

		org	0x00		;Vettore di Reset
		goto	Inizio
		org	0x05		;Salva vettore di interrupt

		include	"LCD_Cxx.inc"	;Include le procedure d'uso dell'LCD

;*********************************************************************************
;Delay_20_ms: Questa procedura di temporizzazione ha per scopo di eliminare l'"effetto
;rimbalzo" delle periferiche elettromeccaniche. Realizza un delay di 20 mS. Se il PIC
;lavora a una frequenza di 4MHz, il TMR0 cambia ogni uS. Se vogliamo temporiz-
;zare 20000 uS (20 mS) con un prescaler di 128, il TMR0 dovrà contare 156 eventi
;(156 * 128). Il valore 156 equivale a 9c hex. e poiché il TMR0 è ascedente bisognerà
;caricare il suo complemento a 1 (63 hex.).

Delay_20_ms:	bcf	INTCON,T0IF	;Disconnetti il flag di overflow
		movlw	0x63		;Complemento hex. di 156
		movwf	TMR0		;carica il TMR0
Delay_20_ms_1	clrwdt			;Aggiornare il WDT
		btfss	INTCON,T0IF	;Overflow del TMR0 ??
		goto	Delay_20_ms_1	;Ancora no
		bcf	INTCON,T0IF	;Adesso sì, rimettere il flag
		return

;*********************************************************************************
;Delay_var: Questa procedura a scopo generico realizza una temporizzazione variabile
;tra 50 mS e 12.8". Si impiega un prescaler di 256 e il TMR0 viene caricato con 195. 
;La velocità di lavoro è di 4Mhz e quindi il TMR0 aumenta ogni uS. In 
;questo modo, il TMR0 deve contare 195 eventi che, con un prescaler di 256 fa un
;intervallo totale di 50000 uS/50 mS (195 * 256). Il valore 195 deve essere espresso
;in Hex. (c3) e poiché il TMR0 è ascendente bisognerà caricare il suo complemento (3C hex.)
;Tale intervallo di 50 mS si ripete tante volte quante ne indica la variabile "Delay_cont",
;è per questo che il delay minimo è di 50 mS ("Delay_cont=1) e il massimo di 12.8" 
;(Delay_cont=255).

Delay_var:	bcf	INTCON,T0IF	;Disconnetti il flag di overflow
		movlw	0x3c		;Complemento hex. di 195
		movwf	TMR0		;carica il TMR0
Intervallo	clrwdt			;Aggiornare il WDT
		btfss	INTCON,T0IF	;Overflow del TMR0 ??
		goto	Intervallo	;Ancora no		
		decfsz	Delay_Cont,F	;Diminuisci contatore di intervalli
		goto	Delay_var	;Ripeti l'intervallo di 50 mS
		return	

;****************************************************************************************
;EE_Write: Registra un byte nella EEPROM di dati. L'indirizzo sarà quello contenuto in EEADR e
;il dato si suppone sia stato precedentemente messo in EEDATA

EE_Write        bsf     STATUS,RP0	;Seleziona banco 1
                bsf     EECON1,WREN	;Permesso di scrittura
                movlw   b'01010101'
                movwf   EECON2
                movlw   b'10101010'
                movwf   EECON2		;Sequenza stabilita da Microchip
                bsf     EECON1,WR	;Ordine di scrittura
                bcf     EECON1,WREN	;Disconnetti permesso di scrittura
Wait            btfss   EECON1,EEIF	;Testare flag di fine scrittura
                goto    Wait
                bcf     EECON1,EEIF	;Rimettere flag di fine scrittura
                bcf     STATUS,RP0	;Seleziona banco 0
                return

;**************************************************************************************
;EE_Read: Leggere un byte della EEPROM. Si suppone che il registro EEADR sia caricato con l'indiriz-
;zo da leggere. In EEDATA apparirà il dato letto.

EE_Read         bsf     STATUS,RP0	;Selezione di banco 1
                bsf     EECON1,RD	;Ordine di lettura
                bcf     STATUS,RP0	;Selezione di banco 0
                return

;**********************************************************************************
;
Inizio	        clrf 	PORTB		;Cancella i latch di uscita
		bsf	STATUS,RP0	;Seleziona banco 1
		clrf	TRISB		;Porta B si configura come uscita
		movlw	b'00011000'		
		movwf	TRISA		;RA0-RA2 uscite, RA3-RA4 entrate				
		movlw	b'00000111'
		movwf	OPTION_REG	;Prescaler di 256 per il TMR0
		bcf	STATUS,RP0	;Seleziona banco 0	
		movlw	0x80
		movwf	Cur_Pos		;Posizione iniziale del cursore
		call	LCD_INI		;Sequenza di inizio dell'LCD
		movlw	b'00000001'
		call	LCD_REG		;Cancella LCD e Home
		movlw	b'00001110'
		call	LCD_REG		;Invia istruzione: LCD ON, Cursore ON e blink OFF
		clrf	EEADR		;Indirizzo iniziale della EEPROM

Loop		btfss	PORTA,4		;Modo programmazione ??
		goto	Riprodurre	;No, modo di riproduzione

Programmare	movlw	0x20
		movwf	Temporale_1	;Primo carattere ASCII		
Program_1	btfss	PORTA,3		;Registrare il byte in EEPROM ??
		goto	Registrare		;Sì
		movf	Cur_Pos,W
		call	LCD_REG		;Colloca il cursore
		movf	Temporale_1,W
		call	LCD_DATO	;Visualizza il carattere
		movlw	.10
		movwf	Delay_Cont
		call	Delay_var	;Temporizza 0.5 secondi
		incf	Temporale_1,F	;Seguente carattere ASCII
		btfss	Temporale_1,7	;E' l'ultimo carattere ASCII ??
		goto	Program_1	;No
		goto	Programmare	;Sì, iniziare dal primo

Registrare	call	Delay_20_ms	;Elimina rimbalzi
		decf	Temporale_1,W
		movwf	EEDATA		;Dato da registrare nella EEPROM
		call	EE_Write	;Registra il carattere
		incf	EEADR,F		;Seguente indirizzo EEPROM
		clrf	EEDATA
		call	EE_Write	;Registra 0x00
		incf	Cur_Pos,F	;Seguente posizione del cursore
Registr_1	clrwdt			;Aggiornare il WDT
		btfss	PORTA,3		;Aspettare che RA3 torni a "1"
		goto	Registr_1
		call	Delay_20_ms	;Eliminare rimbalzi
		goto	Loop		;Seguente carattere del messaggio

Riprodurre	movlw	b'00000001'
		call	LCD_REG		;Cancella LCD e Home
		movlw	b'00001100'
		call	LCD_REG		;LCD = ON, cursore = OFF
		clrf	EEADR		;Indirizzo iniziale EEPROM

Riprodurre_0	clrwdt			;Aggiornamento del WDT		
		call	EE_Read		;Leggi carattere della EEPROM
		movf	EEDATA,F
		btfsc	STATUS,Z	;E' l'ultimo del messaggio ?? (0x00)
		goto	Riprodurre_1	;Sì
		movf	EEDATA,W
		call	LCD_DATO	;Visualizza il carattere
		incf	EEADR,F		;Seguente carattere
		goto	Riprodurre_0

Riprodurre_1	movlw	.40
		movwf	Delay_Cont
		call	Delay_var	;Mantieni il messaggio 2 secondi

;**************************** SEQUENZA DI INTERMITTENZA **********************************
Blink		movlw	.6
		movwf	Temporale_2	;Avvia contatore di intermittenze
Blink_1		movlw	b'00001100'
		call	LCD_REG		;LCD in ON
		movlw	.5
		movwf	Delay_Cont
		call	Delay_var	;Temporizza 0.25 secondi
		movlw	b'00001000'
		call	LCD_REG		;LCD in OFF
		movlw	.5
		movwf	Delay_Cont
		call	Delay_var	;Temporizza 0.25 secondi
		decfsz	Temporale_2,F
		goto	Blink_1		;Ripeti l'intermittenza
		movlw	.20
		movwf	Delay_Cont
		call	Delay_var	;Temporizza 1 secondo
		goto	Loop
	
		end			;Fine del programma principale

