;****Encabezado****

	LIST 	P=16F887
	INCLUDE	P16F887.INC

;El reset se hace mediante el pin MCLR hay que activarlo en la configuracion MCLR_ON

__CONFIG _INTOSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOR_OFF & _IESO_ON & _FCMEN_ON & _LVP_ON

;**** Definicion de variables ****


Usuario		equ	0x30	;preseleccion de potencia
Contador	equ	0x31	;Contador para detectar 256 periodos de onda
Contador1	equ	0x32	;contador para contar 48 desbordes de contador (220ms)
Contador2	equ	0x33	;contador para el reposo( seleccion de potencia)
NTecla		equ	0x34	;numero de tecla presionada
LED_rojo	equ	2		;define el bit de un registro (parado)
LED_verde	equ	3		;bit de un registro (funcionamiento)
W_Temp		equ	0x20	;Registro para guardar temporalmente W.-
STATUS_Temp	equ	0x21	;Registro para guardar temporalmente STATUS
PORTB_Temp	equ	0x22	;registro temporal de puerto B
PORTA_Temp	equ	0x23	;regustro temporal de puerto A


;**** Inicio del Micro ****
			org		0x00
			goto	INICIO
;**** Vector de Interrupcion ****
			org		0x04			; Atiendo Interrupcion.-
			goto	ISR
;**** Programa Principal ****

;**** Configuracion de puertos ***
			org	0x05				; Origen del código de programa.-
INICIO								;sabemos que PR2 se inicia a 256
			bsf		STATUS,5 		;elegimos banco 1
			movlw	b'11110001'		;puerto B 0=salidas 1=entradas 
			movwf	TRISB			;RB0/INT=PARAR
			movlw	b'00000011'		;puerto A entradas = MARCHA y REINICIO
			movwf	TRISA			;entradas
			movlw	b'00000000'		;habilitamos interrupcion por RB0/INT
			movwf	OPTION_REG		;(INTEDG) y resistencias pull up activadas
									;es decir entradas reposo=1
			movlw	b'10011000'		;habilitamos GIE INTE RBIE
			movwf	INTCON
			movlw	b'11110000'		;1=entrada 0=salida
			movwf	TRISC
			movlw	b'00111111'		;ponemos dislpay a 0
			movwf	TRISD
			
			bcf		STATUS,5		;elegimos banco 0
			clrf	PORTA
			clrf	PORTC
			clrf	PORTB		
			clrf	PORTD
			clrf	Contador		;iniciamos a 0 contador
			clrf	NTecla			;borramos nº de tecla
			movlw	.208			;precargamos el contador1 (48 ciclos=220ms)
			movwf	Contador1		;iniciamos a 208
		
								
			bsf		PORTA,LED_rojo	;prendemos led rojo
	


EMPIEZA		btfss	PORTA,0			;se pulso INICIO? saltasi 1 pulsador reposo=0
									;al pulsarlo entrada=1 ------>salta
			goto	EMPIEZA			;NO, esperamos
			bcf		PORTA,LED_rojo	;SI, rojo=off
			bsf		PORTA,LED_verde	;verde=on

;**** Bucle ****		

DOS_ONDAS	bsf		PORTB,1			;señal del mos0 en alta (5v)
			bcf		PORTB,2			;señal del mos1 en baja  (0v)
			call	DELAY_6_07US	;llamamos a la subrrutina de 6.07us
			
			bcf		PORTB,1			;señal del mos0 en baja (0v)
			bcf		PORTB,2			;señal del mos1 en baja  (0v)
			call	DELAY_2_88US	;llamamos a la subrrutina de 2.88us
	
			bcf		PORTB,1			;señal del mos0 en baja  (0v)
			bsf		PORTB,2			;señal del mos1 en alta  (5v)
			call	DELAY_6_07US	;llamamos a la subrrutina de 6.07us

			bcf		PORTB,1			;señal del mos0 en baja (0v)
			bcf		PORTB,2			;señal del mos1 en baja  (0v)
			call	DELAY_2_88US	;llamamos a la subrrutina de 2.88us

			incfsz	Contador,1		;incrementamos contador salto si 0
			goto   	DOS_ONDAS		;bucle
			incfsz	Contador1;1		;incrementamos contador1 hasta 48 salto si 0
			goto	DOS_ONDAS		;reiniciamos si es menor de 48
									;se han cumplido los 220ms (contador1=48)
			movlw	.208			;precargamos el contador1 (48 ciclos)
			movwf	Contador1		;iniciamos a 208						
			bsf		PORTB,3			;Si,(5v)señal laser
			bcf		PORTB,1			;señal del mos0 en baja (0v)
			bcf		PORTB,2			;señal del mos1 en baja  (0v)

SELECPOT	movf	Usuario,0		; Consultamos si se han producido X desbordes
			subwf	Contador2,0		; contador-X ------>contador
			btfss	STATUS,Z		;Z=0? salto si 1 Z=1 si contador=17
			goto	Actualizo_TMR2	;No,Actualizo TMR2  y reinicio bucle
			clrf	Contador2		;Si,limpiamos contador2
			bcf		PORTB,3			;limpiamos la señal laser
			goto	DOS_ONDAS		;termina el paron y continuamos	
			
Actualizo_TMR2		
			movlw	b'01111111'		;habilitamos el TMR2 y escalamos
			bsf		T2CON,2         ;predivisor 1:16 postdivisor 1:16 en el TMR2
			movlw   0x00 	 		;movemos a w cero
			movwf	TMR2			;cargamos el temporizador tmr2=0
			bcf		PIR1,1			;borramos la bandera TMR2IF	
REPOSO		btfss	PIR1,1			;saltamos si 1 = overflow
			goto	REPOSO			;no=bucle
			incf	Contador2,1		;incrementamos el contador2
			goto	SELECPOT		;volvemos a comparar contador2
		

;**** Subrrutina de retardo señal alta ****

DELAY_6_07US	movlw	b'0000100'	;habilitamos el TMR2 y escalamos
			bsf		T2CON,2         ;predivisor 1:1 en el TMR2
			movlw	.226 			;movemos a w 226 que son 30 ciclos
			movwf	TMR2			;cargamos el temporizador tmr2
			bcf		PIR1,1			;borramos la bandera TMR2IF	
ESPERA		btfss	PIR1,1			;saltamos si 1 = overflow
			goto	ESPERA			;no=bucle
			return					;si=salimos de la subrrutina

;**** Subrrutina de retardo señal baja ****

DELAY_2_88US	movlw	b'0000100'	;habilitamos el TMR2 y escalamos
			bsf		T2CON,2         ;predivisor 1:1 en el TMR2
			movlw	.242 			;movemos a w 242 que son 14 ciclos
			movwf	TMR2			;cargamos el temporizador tmr2
			bcf		PIR1,1			;borramos la bandera TMR2IF	
ESPERA1		btfss	PIR1,1			;saltamos si 1 = overflow
			goto	ESPERA1			;no=bucle
			return					;si=salimos de la subrrutina


;**** Subrrutina nº tecla seleccionada ****

;Configuraremos RC0 a RC3 como salida y 
;las colocaremos a nivel bajo. RC4 y RC7 configuradas como entradas, 
;y en estado normal (sin presión de teclas) estarán a nivel alto.
;RBPU=0 de OPTION_REG
;conectamos tambien las entradas a RB4:RB6 para detectar que se toca la tecla

Tecla_Presionada
			clrf	NTecla          ; Borra Numero de Tecla y
			incf	NTecla,1        ; prepara NTecla para primer codigo.
			movlw	b'00001110'     ; Saca 0 a la primera fila
			movwf	PORTC           ; de la Puerta C
			nop                     ; Para estabilizacion de señal.  
Test_Columnas        
			btfss	PORTC,4         ; Primera columna = 0        
			goto	Suelta_tecla    ; Sale si se ha pulsado tecla.
			incf	NTecla,1        ; Si no tecla pulsada, incrementa nº tecla.
			btfss	PORTC,5         ; Segunda columna = 0
			goto	Suelta_tecla    ; Sale si se ha pulsado tecla.
			incf 	NTecla,1        ; Si no tecla pulsada, incrementa nº tecla.
			btfss	PORTC,6         ; Tercera columna = 0
			goto	Suelta_tecla    ; Sale si se ha pulsado tecla.
			incf	NTecla,1        ; Si no tecla pulsada, incrementa nº tecla.
									;	En este caso se Usa teclado 3x4.-
			;	btfss	PORTC,7         ; Cuarta columna = 0
			;	goto	Suelta_tecla    ; Sale si se ha pulsado tecla.
			;	incf	NTecla,1        ; Si no tecla pulsada,incrementa nº Tecla.
                            
Ultima_tecla    
			btfss	PORTC,3			; Ya se revisaron todas las filas?
			goto	Null_tecla		; Si, Falsa alarma, no se ha presionado ninguna.-
			bsf		STATUS,C        ; No, seguimos con la siguiente.Pone a 1 Bit C    
			rlf		PORTC,1     	; asi la Fila 1 pasa a 1 con la rotaci¢n a izqda.
			goto	Test_Columnas	                                             
                                                            
Null_tecla         
			clrf	NTecla          ; Coloca variable Tecla a 0 (Ninguna)
			bcf	INTCON,RBIF			; Borramos bandera de Interrupcion.-
			clrf	PORTC			; Dejamos Puerto para recibir otra tecla.-
			return                  ; y regresa.         
                                                            
Suelta_tecla	

; Ahora se espera a que la tecla sea soltada para evitar rebotes
; y reactivaciones de tecla
Espera1         
			btfss	PORTC,4         ; Si no se suelta la tecla FILA 1
			goto	Espera1         ; vuelve a esperar. 
Espera2         
			btfss	PORTC,5         ; Si no se suelta la tecla FILA 2
			goto	Espera2         ; vuelve a esperar.
Espera3 
			btfss	PORTC,6         ; Si no se suelta la tecla FILA 3
			goto	Espera3         ; vuelve a esperar.              
Espera4
			btfss	PORTC,7         ; Si no se suelta la tecla FILA 4
			goto	Espera4         ; vuelve a esperar.          
 
			bcf	INTCON,RBIF			; Borramos bandera de Interrupcion.-  
			clrf	PORTC			; Dejamos Puerto para recibir otra tecla.-              
			return       			; vuelve al programa principal que hizo la llamada.

;**** Tabla preseleccion de potencia ****

TABLAPOTENCIA
			addwf	PCL,f
			retlw 	.1				;600w (1)
			retlw	.5				;500w (2)
			retlw	.11				;400w (3)
			retlw	.20				;300w (4)
			retlw	.38				;200w (5)
			retlw	.93				;100w (6)

;**** Tabla display catodo comun ****

BCD7SEG:							
			addwf	PCL,1			
			retlw	b'0000110'	; 1	
			retlw	b'1011011'	; 2	
			retlw	b'1001111'	; 3	
			retlw	b'1100110'	; 4	
			retlw	b'1101101'	; 5	
			retlw	b'1111101'	; 6	
								;	retlw	b'0000111'	; 7	
								;	retlw	b'1111111'	; 8	
								;	retlw	b'1101111'	; 9	


;**** Rutina de servicio de Interrupcion ****
 

;**** Interrupcion por RB4:RB7 ****
ISR		
			bcf		INTCON,GIE		;deshabilitamos las interrupciones
			btfss	INTCON,RBIF		;RBIF=1?
			goto	SALIR			;no,salimos
;---> Aqui haremos copia de respaldo -  Guardado de registro W y STATUS.-
Inicio_ISR
			movwf	W_Temp			; Copiamos W a un registro Temporario.-
			swapf	STATUS, W		;Invertimos los nibles del registro STATUS.-
			movwf	STATUS_Temp		; Guardamos STATUS en un registro temporal.-
			movf	PORTB,0			;puertoB---->W
			movwf	PORTB_Temp		;guardamos puertob
			movf	PORTA,0			;puertoA---->W
			movwf	PORTA_Temp		;guardamos puertoA

;**** Introducimos potencia deseada por teclado Matricial ****

			call	Tecla_Presionada; Se detecta que tecla fue presionada
			movfw	NTecla			;cargamos en W el nº de tecla presionada
			call	TABLAPOTENCIA	;pedimos a la tabla que nos devuelva valor
			movwf	Usuario			;cargamos la potencia desada en nuesto registro
			movfw	NTecla			;volvemos a cargar el valor de NTecla en W
			call	BCD7SEG			;decodificador 7 seg
			movwf	PORTD			; Mostarmos en diplay tecla Presionada.-

		
									; Restauramos los valores de W y STATUS.-
Fin_ISR
			movf	PORTA_Temp,0
			movwf	PORTA
			movf	PORTB_Temp,0
			movwf	PORTB
			swapf	STATUS_Temp,W	; Invertimos lo nibles de STATUS_Temp.-
			movwf	STATUS
			swapf	W_Temp, f		; Invertimos los nibles y lo guardamos en el mismo registro.-
			swapf 	W_Temp,W		; Invertimos los nibles nuevamente y lo guardamos en W.-
SALIR		bsf		INTCON,GIE		;habilitamos las interrupciones		
			retfie					; Salimos de interrupción.

;**** Rutina de servicio de Interrupcion ****
 

;**** Interrupcion por RB0/INT ****
ISR		
			bcf		INTCON,GIE		;deshabilitamos las interrupciones
			btfss	INTCON,INTF		;INTF=1?
			goto	SALIR			;no,salimos
;---> Aqui haremos copia de respaldo -  Guardado de registro W y STATUS.-
Inicio_ISR
			movwf	W_Temp			; Copiamos W a un registro Temporario.-
			swapf	STATUS, W		;Invertimos los nibles del registro STATUS.-
			movwf	STATUS_Temp		; Guardamos STATUS en un registro temporal.-
			movf	PORTB,0			;puertoB---->W
			movwf	PORTB_Temp		;guardamos puertob
			movf	PORTA,0			;puertoA---->W
			movwf	PORTA_Temp		;guardamos puertoA


			movlw	b'0000000'		;salidas = 0
			movwf	PORTB
			bsf		PORTA,2
REINICIO	btfss	PORTA,1			;sepulso REINICIO?? salta si 1 , entradas reposo=1
									;luego pulsador en reposo =0 al presionarle=1
			goto 	REINICIO		;NO, bucle
			bcf		INTCON,INTF
; Restauramos los valores de W y STATUS.-
Fin_ISR
			movf	PORTA_Temp,0
			movwf	PORTA
			movf	PORTB_Temp,0
			movwf	PORTB
			swapf	STATUS_Temp,W	; Invertimos lo nibles de STATUS_Temp.-
			movwf	STATUS
			swapf	W_Temp, f		; Invertimos los nibles y lo guardamos en el mismo registro.-
			swapf 	W_Temp,W		; Invertimos los nibles nuevamente y lo guardamos en W.-
SALIR		bsf		INTCON,GIE		;habilitamos las interrupciones		
			retfie					; Salimos de interrupción.




end