;
;					ESEMPIO 2.24
;
;				Autore: Mikel Etxebarria
;			(c) Microsystems Engineering (Bilbao)
;
;Esempio per simulazione e/o MicroPIC Trainer
;
;La memoria EEPROM di dati e l'LCD.La macchina "SUO TURNO", versione migliorata.
;
;Si tratta di simulare il funzionamento delle macchine tipo "SUO TURNO" comuni in molteplici
;attività. Sull'LCD verrà visualizzato il numero del turno attuale (2 cifre). Questo  
;aumenta a ogni impulso applicato da RA4. Nella memoria EEPROM del PIC16F84 viene immagazzinato 
;l'ultimo numero visualizzato, in modo che, davanti a un difetto di alimentazione (p.e.), si riprenda 
;il conto dall'ultimo numero.
;
;Se si inizia utilizzando il sistema per la prima volta, verrà visualizzto lo 00
;
;Va ricordato che le linee RA0-RA2 agiscono come uscita di segnali di controllo verso il
;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) per procedure d'uso dell'LCD
Contatore_L	equ	0x0e		;Variabile per il contatore parte bassa
Contatore_H	equ	0x0f		;Variabile per il contatore parte alta
Temporale_1	equ	0x10		;Variabile temporale
Temporale_2	equ	0x11		;Variabile temporale

		org	0x00		;Vettore di Reset
		goto	Inizio
		org	0x05		;Salva vettore di interrupt
		
		include	"LCD_Cxx.inc"	;Include le procedure d'uso dell'LCD

;****************************************************************************************
;EE_Write: Registra un byte nella EEPROM di dati. L'indirizzo sarà quello contenuto in EEADR e si suppone
;che il dato 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	;Selezione banco 0
                return

;**************************************************************************************
;EE_Read: Leggere un byte della EEPROM. Si suppone che il registro EEADR sia caricato con l'indi-
;rizzo 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

;**********************************************************************************
;Secondo il valore contenuto nel registro W, si restituisce il carattere ASCII da visualiz-
;zare nell'LCD

Tabella_Mess:	movwf	PCL			;Spostamento sulla tabella

;**********************************************************************************
;La direttiva dt genera tante istruzioni retlw quanti bytes o caratteri contiene
;chiusi tra "

Mess_0		equ	$			;Mess_0 punta al primo carattere
		dt	"Suo TURNO : ",0x00

;*********************************************************************************
;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 valor 156 equivale a 9c hex. e poiché il TMR0 è ascendente bisognerà
;caricare il suo complemento a 1 (63 hex.).

Delay_20_ms:	bcf	INTCON,T0IF	;Disconnetti il flag di overflow
		movlw	0x63		;Complemento hex. de 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

;*************************************************************************************
;Messaggio: Questa procedura visualizza sull'LCD il messaggio il cui inizio è indicato 
;nell'accumulatore. La fine di un messaggio si determina mediante il codice 0x00

Messagg         movwf   Temporale_1     ;Salva posizione della tabella
Messagg_1       movf    Temporale_1,W   ;Recupera posizione della tabella
                call    Tabella_Mess    ;Cerca carattere di uscita
                movwf   Temporale_2     ;Conserva il carattere
                movf    Temporale_2,F
                btfss   STATUS,Z        ;Guarda se è l'ultimo
                goto    No_è_ultimo
                return
No_è_ultimo    	call    LCD_DATO        ;Visualizza sull'LCD
                incf    Temporale_1,F   ;Seguente carattere
                goto    Messagg_1

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 entrate, resto entrate		
		movlw	b'00000110'
		movwf	OPTION_REG	;Prescaler di 128 per il TMR0
		bcf	STATUS,RP0	;Seleziona banco 0			                                                                         					

		call	LCD_INI		;Sequenza di inizio del LCD
		movlw	b'00001100'
		call	LCD_REG		;Invia istruzione LCD ON, Cursore OFF e Blink OFF

		movlw	Mess_0
		call	Messagg		;Visualizza Mess_0 (Suo TURNO è: )

		clrf	EEADR		;Seleziona indirizzo 00 di EEPROM				
		call	EE_Read		;Leggi byte della EEPROM
		movlw	0x09
		subwf	EEDATA,W
		btfsc	STATUS,C	;Contatore_H maggiore di 9 ??		
		goto	Ini_0		;Sì, mettere a 0 il contatore
		goto	Ini_1		;No
Ini_0		clrf	Contatore_L
		clrf	Contatore_H	;Mettere a 0 il contatore
		goto	Loop

Ini_1		movf	EEDATA,W
		movwf	Contatore_H	;Aggiorna Contatore_H
		incf	EEADR,F		;Seguente posizione della EEPROM
		call	EE_Read		;Leggi il byte della EEPROM
		movlw	0x09
		subwf	EEDATA,W
		btfsc	STATUS,C	;Contatore_L maggiore di 9 ??
		goto	Ini_0		;Sì, mettere a 0 il contatore
		movf	EEDATA,W
		movwf	Contatore_L	;Aggiorna Contatore_L

Loop		movlw	0x8d
		call	LCD_REG		;Posiziona il cursore dell'LCD
		movf	Contatore_H,W
		iorlw	0x30		;Converti in ASCII Contatore_H
		call	LCD_DATO	;Visualizza Contatore_H
		movf	Contatore_L,W
		iorlw	0x30		;Converti in ASCII Contatore_L
		call	LCD_DATO	;Visualizza contatore_L		
		
Wait_0		clrwdt			;Aggiorna il WDT
		btfss	PORTA,4		;RA4 è a "1" ??
		goto	Wait_0		;No, aspettare
		call	Delay_20_ms	;Eliminare rimbalzi

Wait_1		clrwdt			;Aggiornare il WDT
		btfsc	PORTA,4		;RA4 è a "0" ??
		goto	Wait_1		;No, aspettare
		call	Delay_20_ms	;Eliminare rimbalzi. C'è stata un impulso

		incf	Contatore_L,F	;Aumenta contatore_L
		movlw	.10
		subwf	Contatore_L,W
		btfss	STATUS,Z	;Contatore maggiore di 9 ??
		goto	Write		;No, aggiornare EEPROM
		clrf	Contatore_L	;Si, Contatore_L passa a 0
		incf	Contatore_H,F	;Aumenta Contatore_H
		movlw	.10
		subwf	Contatore_H,W
		btfss	STATUS,Z	;Contatore_H maggiore di 9
		goto	Write		;No, aggiornare EEPROM
		clrf	Contatore_H	;Si, Contatore_H passa a 0

Write		clrf	EEADR		;Seleziona indirizzo 00 della EEPROM
		movf	Contatore_H,W
		movwf	EEDATA
		call	EE_Write	;Registra Contatore_H nella EEPROM
		incf	EEADR,F		;Indirizzo 01 della EEPROM
		movf	Contatore_L,W
		movwf	EEDATA
		call	EE_Write	;Registra Contatore_L nella EEPROM
		goto	Loop


	
		end			;Fine del programma principale

