;
;					ESEMPIO 2.17
;
;				Autore: Mikel Etxebarria
;			(c) Microsystems Engineering (Bilbao)
;
;Esempio per simulazione e/o MicroPIC Trainer
;
;Generazione di numeri aleatori. Il dado elettronico
;
;Si tratta di generare un numero aleatorio tra 1 e 6. Quando RA0 è a "1", sul
;display a 7 segmenti connesso alla porta B, si visualizzano in forma sequeziale 
;i numeri dall'1 al 6, con intervalli di 0.05". Quando RA0 passa a livello "0", si visualizza
;il numero aleatorio ottenuto in un tempo di 3". Poi il display si spegne e la 
;sequenza si ripete.
	
		List	p=16F84		;Tipo di processore
		include	"P16F84.INC"	;Definizioni di registri interni
                    
Numero		equ	0x0c		;Numero aleatorio
Delay_Cont	equ	0x0d		;Contatore di intervalli
Temporale	equ	0x0e		;Variabile temporale
		
		org	0x00		;Vettore di Reset
		goto	Inizio
		org	0x05		;Salva vettore di interrupt

;**********************************************************************************
;Tabella: Questa procedura converte il codice binario presente nei 4 bits di minor peso
;del reg. W nel suo equivalente a 7 segmenti. Il codice a 7 segmenti ritorna anche
;nel reg. W

Tabella:		addwf	PCL,F		;Spostamento sulla tabella
		retlw	b'00111111'	;Cifra 0
		retlw	b'00000110'	;Cifra 1
		retlw	b'01011011'	;Cifra 2
		retlw	b'01001111'	;Cifra 3
		retlw	b'01100110'	;Cifra 4
		retlw	b'01101101'	;Cifra 5
		retlw	b'01111101'	;Cifra 6
		
;*********************************************************************************
;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 tempori-
;zzare 20000 uS (20 mS) con un prescaler di 256, i TMR0 dovrà contare 78 eventi
;(78 * 256). Il valore 78 equivale a 0x4e hex. e poiché il TMR0 è ascendente bisognerà
;caricare il suo complemento a 1 (0xb1 hex.).

Delay_20_ms:	bcf	INTCON,T0IF	;Disconnetti il flag di overflow
		movlw	0xb1		;Complemento hex. de 78
		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
		return

					
;*********************************************************************************
;Delay_var: Questa pocedura a scopo generale 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 preescaler di 128 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. de 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	

Inizio	        clrf 	PORTB		;Cancella i latch di uscita
		bsf	STATUS,RP0	;Seleziona banco 1
		clrf	TRISB		;Porta B si configura come uscita
		movlw	b'00011111'		
		movwf	TRISA		;Porta A si configura come entrata		
		movlw	b'00000111'
		movwf	OPTION_REG	;Prescaler di 256 per il TMR0
		bcf	STATUS,RP0	;Seleziona banco 0			                                                                         					

Loop		clrwdt			;Aggiornare il WDT		
		btfss	PORTA,0		;Attivato RA0 ??
		goto	Loop		;Ancora No
		movf	TMR0,W		;Adesso sì.
		movwf	Numero		;Cattura il valore del TMR0 (Nº aleatorio)		
		call	Delay_20_ms	;Elimina rimbalzi
					
;Il numero aleatorio viene, mediante sottrazioni consecutive, diviso in 6. In questo modo
;l'ultimo resto sarà tra 0 e 5 che verrà incrementato di una unità affinché si abbia  defini-
;tivamente un numero tra 1 e 6

Dividi:		movlw	d'6'
		subwf	Numero,W	;Sottrai 6 al numero aleatorio
		movwf	Numero          ;conservalo
	    	sublw	d'5'			
		btfss	STATUS,C	;Guarda se è minore de 5
		goto	Dividi		;No
		incf	Numero,F	;Il numero è tra 1 e 6

;Questa procedura di istruzioni ha per scopo di mostrare sul display i numeri
;dall'1 al 6 a intervalli di 0.05" per dare una sensazione di movimento del dado.
;Tale movimento viene mantenuto mentre RA0 é a "1". Andando a "0" si presenta il
;numero aleatorio precedentemente catturato dal TMR0

Dado:		movlw	d'6'
		movwf	Temporale	;Avvia il contatore del dado
RA0_1		clrwdt			;Aggiornamento del WDT
		btfss	PORTA,0		;Guarda se RA0 è a 1
		goto	Uscita		;No, visualizza l'aleatorio
		movf	Temporale,W	;Numero da visualizzare
		call	Tabella         ;Conversione in BCD
		movwf	PORTB		;Visualizza sul display
		movlw	d'1'
		movwf	Delay_Cont	;Variabile di temporizzazione
		call	Delay_var	;temporizza 0.05"
		decfsz	Temporale,F	;Numero seguente
		goto	RA0_1
		goto 	Dado
					
		call	Delay_20_ms	;Elimina rimbalzi
					
Uscita:		movf	Numero,W	;Riprendi l'aleatorio
		call	Tabella		;Lo converte in 7 segmenti
		movwf	PORTB		;Uscita sul Display
		movlw	d'60'
		movwf	Delay_Cont	;avvia variabile di temporizzazione
		call	Delay_var	;Temporizza 3"
		clrf	PORTB		;Disconnetti l'uscita
		
		goto	Loop

		end			;Fine del programma principale 

