;
;					EJEMPLO 2.17
;
;				Autor: Mikel Etxebarria
;			(c) Microsystems Engineering (Bilbao)
;
;Ejemplo para simulación y/o MicroPIC Trainer
;
;Generación de números aleatorios. El dado electrónico
;
;Se trata de generar un número aleatorio entre 1 y 6. Cuando RA0 está a "1", sobre el
;dsiplay 7 segmentos conectado a la puerta B, se van visualizando de forma secuecial 
;los números del 1 al 6, con intervalos de 0.05". Al pasar RA0 a nivel "0", se visualiza
;el número aleatorio obtenido durante un tiempo de 3". Luego el display se apaga y la 
;secuencia se repite.
	
		List	p=16F84		;Tipo de procesador
		include	"P16F84.INC"	;Definiciones de registros internos
                    
Numero		equ	0x0c		;Número aleatorio
Delay_Cont	equ	0x0d		;Contador de intervalos
Temporal	equ	0x0e		;Variable temporal
		
		org	0x00		;Vector de Reset
		goto	Inicio
		org	0x05		;Salva vector de interrupción

;**********************************************************************************
;Tabla: Esta rutina convierte el código binario presente en los 4 bits de menos peso
;del reg. W en su equivalente a 7 segmentos. El código 7 segmentos retorna también
;en el reg. W

Tabla:		addwf	PCL,F		;Desplazamiento sobre la tabla
		retlw	b'00111111'	;Dígito 0
		retlw	b'00000110'	;Dígito 1
		retlw	b'01011011'	;Dígito 2
		retlw	b'01001111'	;Dígito 3
		retlw	b'01100110'	;Dígito 4
		retlw	b'01101101'	;Dígito 5
		retlw	b'01111101'	;Dígito 6
		
;*********************************************************************************
;Delay_20_ms: Esta rutina de temporización tiene por objeto eleiminar el "efecto
;rebote" de los periféricos electromecánicos. Realiza un delay de 20 mS. Si el PIC
;trabaja a una frecuencia de 4MHz, el TMR0 evoluciona cada uS. Si queremos tempori-
;zar 20000 uS (20 mS) con un preescaler de 256, el TMR0 deberá contar 78 eventos
;(78 * 256). El valor 78 equivale a 0x4e hex. y como el TMR0 es ascedente habrá que
;cargar su complemento a 1 (0xb1 hex.).

Delay_20_ms:	bcf	INTCON,T0IF	;Desconecta el flag de rebosamiento
		movlw	0xb1		;Complemento hex. de 78
		movwf	TMR0		;carga el TMR0
Delay_20_ms_1	clrwdt			;Refrescar el WDT
		btfss	INTCON,T0IF	;Rebasamiento del TMR0 ??
		goto	Delay_20_ms_1	;Todavía no
		return

					
;*********************************************************************************
;Delay_var: Esta rutina de propósito general realiza una temporización variable
;entre 50 mS y 12.8". Se emplea un preescaler de 256 y al TMR0 se le carga con 195. 
;La velocidad de trabajo es de 4Mhz y por tanto el TMR0 se incrementa cada uS. De 
;esta forma, el TMR0 debe contar 195 eventos que, con un preescaler de 128 hace una
;intervalo total de 50000 uS/50 mS (195 * 256). El valor 195 hay que expresarlo
;en Hex. (c3) y como el TMR0 es ascendente habrá que cargar su complemento (3C hex.)
;Dicho intervalo de 50 mS se repite tantes veces como indique la variable "Delay_cont",
;es por ello que el delay mínimo es de 50 mS ("Delay_cont=1) y el máxima de 12.8" 
;(Delay_cont=255).

Delay_var:	bcf	INTCON,T0IF	;Desconecta el flag de rebosamiento
		movlw	0x3c		;Complemento hex. de 195
		movwf	TMR0		;carga el TMR0
Intervalo	clrwdt			;Refrescar el WDT
		btfss	INTCON,T0IF	;Rebasamiento del TMR0 ??
		goto	Intervalo	;Todavía no		
		decfsz	Delay_Cont,F	;Decrementa contador de intervalos
		goto	Delay_var	;Repite el intervalo de 50 mS
		return	

Inicio	        clrf 	PORTB		;Borra los latch de salida
		bsf	STATUS,RP0	;Selecciona banco 1
		clrf	TRISB		;Puerta B se configura como salida
		movlw	b'00011111'		
		movwf	TRISA		;Puerta A se configura como entrada		
		movlw	b'00000111'
		movwf	OPTION_REG	;Preescaler de 256 para el TMR0
		bcf	STATUS,RP0	;Selecciona banco 0			                                                                         					

Loop		clrwdt			;Refrescar el WDT		
		btfss	PORTA,0		;Activado RA0 ??
		goto	Loop		;Todavía No
		movf	TMR0,W		;Ahora si.
		movwf	Numero		;Captura el valor del TMR0 (Nº aleatorio)		
		call	Delay_20_ms	;Elimina rebotes
					
;El número aleatorio es, mediante restas consecutivas, dividido entre 6. De esta forma
;el último resto será entre 0 y 5 que será incrementado en una unidad para que defini-
;tivamente de un número entre 1 y 6

Divide:		movlw	d'6'
		subwf	Numero,W	;Resta 6 al número aleatorio
		movwf	Numero          ;lo guarda
	    	sublw	d'5'			
		btfss	STATUS,C	;Mira si es menor de 5
		goto	Divide		;No
		incf	Numero,F	;El número queda entre 1 y 6

;Esta secuencia de instrucciones tiene por misión presentar sobre el display los números
;del 1 al 6 a intervalos de 0.05" con objeto de dar una sensación de movimiento del dado.
;Dicho movimiento se mantiene mientras RA0 esté a "1". Al ponerse a "0" se presenta el
;número aleatorio capturado previamente desde el TMR0

Dado:		movlw	d'6'
		movwf	Temporal	;Inicia el contador del dado
RA0_1		clrwdt			;Refresco del WDT
		btfss	PORTA,0		;Mira si RA0 está a 1
		goto	Salida		;No, visualiza el aleatorio
		movf	Temporal,W	;Número a visualizar
		call	Tabla           ;Conversión a BCD
		movwf	PORTB		;Visualiza sobre el display
		movlw	d'1'
		movwf	Delay_Cont	;Variable de temporización
		call	Delay_var	;temporiza 0.05"
		decfsz	Temporal,F	;Siguiente número
		goto	RA0_1
		goto 	Dado
					
		call	Delay_20_ms	;Elimina rebotes
					
Salida:		movf	Numero,W	;Recoge el aleatorio
		call	Tabla		;Lo convierte en 7 segmentos
		movwf	PORTB		;Salida a Display
		movlw	d'60'
		movwf	Delay_Cont	;Inicia variable de temporización
		call	Delay_var	;Temporiza 3"
		clrf	PORTB		;Desconecta la salida
		
		goto	Loop

		end			;Fin del programa fuente

