;*********************************************************************************************************
;************************************   MEDIDOR DE BATERIAS   ********************************************
;************************************   CON DISPLAY 4 x 20    ********************************************
;*********************************************************************************************************

	list p=16f876A
	include "p16f876A.inc"
	errorlevel -302 ; supress "register not in bank0, check page bits" message
	__CONFIG _PWRTE_OFF & _BODEN_OFF &_HS_OSC & _WDT_OFF & _LVP_OFF & _CPD_OFF

#DEFINE ANAIN		PORTA, 0		;RA0 Entrada analógica
#DEFINE lcd_DAT		PORTB
#DEFINE lcd_RS		PORTC, 0		;LCD Register Select
#DEFINE lcd_RW		PORTC, 1		;LCD Read/Write
#DEFINE lcd_E		PORTC, 2		;LCD Enable
#DEFINE buzz		PORTC, 3		;Buzzer se activa a 1 log
#DEFINE relay		PORTC, 5		;Buzzer se activa a 1 log

Same    equ     1

wrADR   equ 0x21	;Direccion de la EEPROM para escribir
wrDAT   equ 0x22	;Dato a escribir en la EEPROM
rdADR   equ 0x23	;Direccion de la EEPROM para leer
rdDAT   equ 0x24	;Dato a leer de la EEPROM

PDel0	equ	0x25
PDel1	equ	0x26
PDel2	equ	0x27
PDel3	equ	0x28
PDel4	equ	0x29
PDel5	equ	0x2A
PDel6	equ	0x2B
PDel7	equ	0x2C
PDel8	equ	0x2D
PDel9	equ	0x2E
POSI	equ	0x2F
VIN		equ	0x30
TEMP1	equ	0x31
mulcnd  equ 0x32      ; 8 bit multiplicand
mulplr  equ 0x33      ; 8 bit multiplier
H_byte  equ 0x34      ; High byte of the 16 bit result
L_byte  equ 0x35      ; Low byte of the 16 bit result
count	equ	0x36
TenK    equ 0x37	;Decenas de millar del numero de la conversion BIN2BCD
Thou    equ 0x38	;Unidades de millar del numero de la conversion BIN2BCD
Hund    equ 0x39	;Centenas del numero de la conversion BIN2BCD
Tens    equ 0x3A	;Decenas del numero de la conversion BIN2BCD
Ones    equ 0x3B	;Unidades del numero de la conversion BIN2BCD
Uni	    equ 0x3C	;Unidades del numero de bateria
Dec	    equ 0x3D	;Unidades del numero de bateria
Cen	    equ 0x3E	;Unidades del numero de bateria

		org		0x00		;Program start
		goto	INICIO

;*****************************************************************************************
;Main program
;*****************************************************************************************
INICIO:
;		clrf	STATUS
;		clrf	T1CON
		banksel	ADCON1		;Cambia a Bank 1
	    movlw   0x4E		;RA0 como analogica
		movwf	ADCON1		;RA1,RA5 como digitales
							;A/D Conversion Clock = Fosc/16
							;A/D Result Format = Left justified
	    movlw   0x3F		;Pone a RA0:RA5 como entradas
    	movwf   PORTA  		;
	    movlw   0x00    	;Pone a w = 00000000
    	movwf   PORTB  		;Pone a PORTB & PORTC como salidas
	    movlw   0x10    	;Pone a RC4 como entrada
    	movwf   PORTC		;y a RC3:RC0 como salidas
		banksel	ADCON0		;Cambia a Bank 0
	    movlw   0x40		;ADC Clock Fosc/16
		movwf   ADCON0		;
		bsf		ADCON0,0	;Enciende el ADC

		call	Delay_500ms

		bsf		buzz		;enciende el buzzer
		call	Delay_50ms
		bcf		buzz		;apaga el buzzer
		call	Delay_50ms
		bsf		buzz		;enciende el buzzer
		call	Delay_50ms
		bcf		buzz		;apaga el buzzer
		call	Delay_50ms

		call	LCD_INI

;*****************************************************************************************
;ESCANEO DE INTERRUPTOR PRESIONADO
;	SW2 = LEER Y GUARDAR EN EEPROM
;	SW3 = AVANZAR PAGINA (LECTURA DE EEPROM)
;	SW4 = REGRESAR PAGINA (LECTURA DE EEPROM)
;*****************************************************************************************

		clrf	Uni
		clrf	Dec
		clrf	Cen
		movlw	0x00
		movwf	wrADR
		movwf	rdADR

SWscan	call	Delay_50ms
		btfsc	PORTC,4
		goto	sw3
;		bcf		relay		;activa el relay de lectura de medicion
		goto	leerADC

sw3		call	Delay_50ms
		btfsc	PORTA,2
		goto	sw4
		goto	AVpag

sw4		call	Delay_50ms
		btfsc	PORTA,5
		goto	SWscan
		goto	REpag

		call	Delay_500ms

leerADC	call	LEER_ADC
		movf	VIN,0
		movwf	wrDAT

		bsf		buzz		;enciende el buzzer
		call	Delay_500ms
		bcf		buzz		;apaga el buzzer
;		bsf		relay		;Desactiva el relay de lectura de medicion

		call	wrEEP

		call	conv_ADC

		call	letSW2

		incf	wrADR,1

		goto	SWscan

AVpag	bsf		buzz		;enciende el buzzer
		call	Delay_500ms
		bcf		buzz		;apaga el buzzer

		call	letSW3

		goto	SWscan

REpag	bsf		buzz		;enciende el buzzer
		call	Delay_500ms
		bcf		buzz		;apaga el buzzer

		movlw	0x80
		movwf	POSI
		call	letSW3

		movlw	0x8A
		movwf	POSI
		call	letSW3

		goto	SWscan

;*****************************************************************************************
;Subroutines
;*****************************************************************************************
LCD_INI:
	clrf	PORTB		;PORTB = w = 00000000
	clrf	PORTC		;PORTB = w = 00000000

	call	Delay_32ms

	movlw   0x38		;Function Set
	call	LCD_CMD

	call	Delay_40us

	movlw   0x0C		;Display ON/OFF Control
	call	LCD_CMD

	call	Delay_40us

	movlw   0x01		;Clear Display
	call	LCD_CMD

	call	Delay_2ms

	movlw   0x06		;Entry Mode Set
	call	LCD_CMD

	call	Delay_50ms

	return

LCD_E:
	bsf		lcd_E		;LCD Enable=1
	nop
	bcf		lcd_E		;LCD Enable=0
	return

LCD_CMD:
	bcf		lcd_E		;LCD Enable=0
	bcf		lcd_RW		;Activate Write operation RW=0
	bcf		lcd_RS		;RS=0
	movwf	PORTB
	bsf		lcd_E		;LCD Enable=1
	bcf		lcd_E		;LCD Enable=0
	return

LCD_DAT:
	bcf		lcd_E		;LCD Enable=0
	bcf		lcd_RW		;Activate Write operation RW=0
	bsf		lcd_RS		;RS=1
	movwf	PORTB
	bsf		lcd_E		;LCD Enable=1
	bcf		lcd_E		;LCD Enable=0
	return

ADDRESS:
	INCF    POSI, 1		;Incrementa posicion del cursor
	movlw   POSI		;Set DDRAM Address
	call	LCD_CMD

	call	Delay_50ms

	return

;*****************************************************************************************
;SUBRUTINA PARA LEER EL CONVERSOR A/D
;*****************************************************************************************
LEER_ADC:
		bsf		ADCON0,2	;Inicia la conversion ADC

		call	Delay_40us
		call	Delay_5us
		call	Delay_5us

Lloop	btfss	PIR1,6
		goto	Lloop

		movf	ADRESH,0
		movwf	VIN

		bcf		PIR1,6

		return

;*****************************************************************************************
;SUBRUTINA PARA CONVERTIR LA LECTURA DEL A/D
;*****************************************************************************************
conv_ADC:
		movlw	.121
		movwf	mulcnd
		movf	VIN,0
		movwf	mulplr

		call	multiplica

		call	BIN2BCD

		addlw	0x30

		addwf	Ones,1
		addwf	Tens,1
		addwf	Hund,1
		addwf	Thou,1
		addwf	TenK,1

		sublw	0x30

		addwf	Ones,1
		addwf	Tens,1
		addwf	Hund,1
		addwf	Thou,1
		addwf	TenK,1

		return

;*****************************************************************************************
;SUBRUTINA PARA ESCRIBIR EN EEPROM
;*****************************************************************************************
wrEEP:
		clrf	INTCON
		banksel	EEADR
		movf	wrADR,0			;Address Memory
		movwf	EEADR			;Address to write
		movf	wrDAT,0			;Data Memory Value
		movwf	EEDATA			;Data to write
		banksel	EECON1
		bcf		EECON1,EEPGD	;Point to DATA memory
		bsf		EECON1,WREN		;Enable writes
		movlw	0x55			;
		movwf	EECON2			;Write 55h
		movlw	0xAA			;
		movwf	EECON2			;Write AAh
		bsf		EECON1,WR		;Set WR bit to begin write
		banksel	PIR2
wrchk	btfss	PIR2,EEIF		;Wait for write
		goto 	wrchk			;to complete
		bcf		PIR2,EEIF		;
		bcf		EECON1,WREN		;Disable writes
		return

;*****************************************************************************************
;SUBRUTINA PARA ESCRIBIR EN EEPROM
;*****************************************************************************************
rdEEP:
	banksel	EEADR
	movf	rdADR,0			;Data Memory
	movwf	EEADR			;Address to read
	banksel	EECON1
	bsf		EECON1,RD		;EE Read
	banksel	EEDATA
	movf	EEDATA,0 		;W = EEDATA
	return

;*****************************************************************************************
;SUBRUTINA BUENA DE MULTIPLICACION DE 2 x 8 BITS
;*****************************************************************************************
multiplica:
		clrf	H_byte
		clrf	L_byte
		movlw	8
		movwf	count
		movf	mulcnd,W
		bcf		STATUS,C ; Clear the carry bit in the status Reg.
loop	rrf		mulplr, F
		btfsc	STATUS,C
		addwf	H_byte,Same
		rrf		H_byte,Same
		rrf		L_byte,Same
		decfsz	count, F
		goto	loop

		retlw 0

;*****************************************************************************************
;SUBRUTINA DE BINARIO A BCD TOMADA DE PIC MICROCONTROLLER
;         http://www.piclist.org/techref/microchip/math/radix/b2bu-16b5d.htm
;*****************************************************************************************
BIN2BCD:
;Takes hex number in NumH:NumL  Returns decimal in ;TenK:Thou:Hund:Tens:Ones

;input
;=A3*163 + A2*162 + A1*161 + A0*160
;=A3*4096 + A2*256 + A1*16 + A0

;NumH            EQU H_byte	;AD3M   ;A3*16+A2
;NumL            EQU L_byte	;AD3L	;A1*16+A0

;share variables
;=B4*104 + B3*103 + B2*102 + B1*101 + B0*100
;=B4*10000 + B3*1000 + B2*100 + B1*10 + B0

	swapf	H_byte,w	;w  = A2*16+A3
	andlw   0x0F    ;w  = A3		*** PERSONALLY, I'D REPLACE THESE 2
	addlw   0xF0	;w  = A3-16	*** LINES WITH "IORLW b'11110000B' " -AW
	movwf   Thou	;B3 = A3-16
	addwf   Thou,f	;B3 = 2*(A3-16) = 2A3 - 32
	addlw   .226	;w  = A3-16 - 30 = A3-46
	movwf   Hund	;B2 = A3-46
	addlw   .50	;w  = A3-46 + 50 = A3+4
	movwf   Ones	;B0 = A3+4

	movf    H_byte,w	;w  = A3*16+A2
	andlw   0x0F	;w  = A2
	addwf   Hund,f	;B2 = A3-46 + A2 = A3+A2-46
	addwf   Hund,f	;B2 = A3+A2-46  + A2 = A3+2A2-46
	addwf   Ones,f	;B0 = A3+4 + A2 = A3+A2+4
	addlw   .233	;w  = A2 - 23
	movwf   Tens	;B1 = A2-23
	addwf   Tens,f	;B1 = 2*(A2-23)
	addwf   Tens,f	;B1 = 3*(A2-23) = 3A2-69 (Doh! thanks NG)

	swapf   L_byte,w	;w  = A0*16+A1
	andlw   0x0F	;w  = A1
	addwf   Tens,f	;B1 = 3A2-69 + A1 = 3A2+A1-69 range -69...-9
	addwf   Ones,f	;B0 = A3+A2+4 + A1 = A3+A2+A1+4 and Carry = 0 (thanks NG)

	rlf     Tens,f	;B1 = 2*(3A2+A1-69) + C = 6A2+2A1-138 and Carry is now 1 as tens register had to be negitive
	rlf     Ones,f	;B0 = 2*(A3+A2+A1+4) + C = 2A3+2A2+2A1+9 (+9 not +8 due to the carry from prev line, Thanks NG)
	comf    Ones,f	;B0 = ~(2A3+2A2+2A1+9) = -2A3-2A2-2A1-10 (ones complement plus 1 is twos complement. Thanks SD)

;;Nikolai Golovchenko [golovchenko at MAIL.RU] says: comf can be regarded like:
;;      comf Ones, f
;;      incf Ones, f
;;      decf Ones, f
;;First two instructions make up negation. So,
;;Ones  = -1 * Ones - 1 
;;      = - 2 * (A3 + A2 + A1) - 9 - 1 
;;      = - 2 * (A3 + A2 + A1) - 10

	rlf     Ones,f	;B0 = 2*(-2A3-2A2-2A1-10) = -4A3-4A2-4A1-20

	movf    L_byte,w	;w  = A1*16+A0
	andlw   0x0F	;w  = A0
	addwf   Ones,f	;B0 = -4A3-4A2-4A1-20 + A0 = A0-4(A3+A2+A1)-20 range -215...-5 Carry=0
	rlf     Thou,f	;B3 = 2*(2A3 - 32) = 4A3 - 64

	movlw   0x07	;w  = 7
	movwf   TenK	;B4 = 7

;B0 = A0-4(A3+A2+A1)-20	;-5...-200
;B1 = 6A2+2A1-138	;-18...-138
;B2 = A3+2A2-46		;-1...-46
;B3 = 4A3-64		;-4...-64
;B4 = 7			;7
; At this point, the original number is equal to TenK*10000+Thou*1000+Hund*100+Tens*10+Ones 
; if those entities are regarded as two's compliment binary.  To be precise, all of them are negative 
; except TenK.  Now the number needs to be normalized, but this can all be done with simple byte 
; arithmetic.

        movlw   .10	;w  = 10
Lb1:			;do
        addwf   Ones,f	; B0 += 10
        decf    Tens,f	; B1 -= 1
        btfss   3,0
	;skip no carry
         goto   Lb1	; while B0 < 0
	;jmp carry
Lb2:			;do
        addwf   Tens,f	; B1 += 10
        decf    Hund,f	; B2 -= 1
        btfss   3,0
         goto   Lb2	; while B1 < 0
Lb3:			;do
        addwf   Hund,f	; B2 += 10
        decf    Thou,f	; B3 -= 1
        btfss   3,0
         goto   Lb3	; while B2 < 0
Lb4:			;do
        addwf   Thou,f	; B3 += 10
        decf    TenK,f	; B4 -= 1
        btfss   3,0
         goto   Lb4	; while B3 < 0

	return

;*****************************************************************************************
;SUBRUTINA PARA OBTENER LOS DIGITOS CONSECUTIVOS DE LOS NOS DE BATERIAS
;*****************************************************************************************
digitos:
			incf	Uni,1		;incremento unidades
			movlw	.10			;cargo 10 en W para comparar
			xorwf	Uni,W		;Si Uni XOR 10 da 0, entonces es hora de incrementar decenas
			btfss	STATUS,Z	;Dió cero?
			goto	Muestra		;No. Entonces listo el cálculo. Mostrar

			clrf	Uni			;Si. Dió cero y es hora de poner a cero las unidades e
			incf	Dec,F		;incrementar las decenas
			movlw	.10			;Ahora cargo 10 en W para comparar
			xorwf	Dec,W		;Si Dec XOR 10 da cero, entonces es hora de incrementar decenas
			btfss	STATUS,Z	;Dió cero?
			goto	Muestra		;No. Entonces fin cálculos

			clrf	Dec			;Si. Dió cero. Entonces poner Decenas a cero e
			incf	Cen,F		;incrementar centenas

Muestra		movf	Cen,w		;copiar Cen en W(la instruccion movf afecta al flag Z, por lo que si Cen vale cero, Z se pone en alto)
			btfsc	STATUS,Z	;Z en bajo?(Hay al menos una centena?)
			goto	MuestraDec	;No. entonces pasar a mostrar decenas

			addlw	0x30		;Si. Entonces mostrar centenas
			call	LCD_DAT
			call	ADDRESS

			movf	Dec,w		;Cargar decenas(arregla error previo)
			goto	HayDecenas	;Línea para arreglar el error previo. Si al menos exíste una Centena, obligar a mostrar decenas

MuestraDec	movf	Dec,w		;copiar Dec en W(la instruccion movf afecta al flag Z, por lo que si Dec vale cero, Z se pone en alto)
			btfsc	STATUS,Z	;Al menos una decena?
			goto	MuestraUni	;No. Entonces pasar a mostrar unidades

HayDecenas
			addlw	0x30		;Si. Mostrar Decenas
			call	LCD_DAT
			call	ADDRESS

MuestraUni	movf	Uni,w		;Mostrar unidades(no es necesario verificarlas. Al menos siempre hay una medición)
			addlw	0x30
			call	LCD_DAT
			call	ADDRESS

			return

;*****************************************************************************************
;SUBRUTINA PARA MOSTRAR LOS DATOS DE LAS LECTURAS ACTUALES
;*****************************************************************************************
letSW2:
;DIRECCIONES DDRAM
; 0x80 LINEA 1 POSICION 1
; 0xC0 LINEA 2 POSICION 1
; 0x94 LINEA 3 POSICION 1
; 0xD4 LINEA 4 POSICION 1
;
;   1    2    3    4    5    6    7    8    9    10   11   12   13   14   15   16   17   18   19   20
;  ___________________________________________________________________________________________________
; | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 8A | 8B | 8C | 8D | 8E | 8F | 90 | 91 | 92 | 93 |
; |---------------------------------------------------------------------------------------------------|
; | C0 | C1 | C2 | C3 | C4 | C5 | C6 | C7 | C8 | C9 | CA | CB | CC | CD | CE | CF | D0 | D1 | D2 | D3 |
; |---------------------------------------------------------------------------------------------------|
; | 94 | 95 | 96 | 97 | 98 | 99 | 9A | 9B | 9C | 9D | 9E | 9F | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 |
; |---------------------------------------------------------------------------------------------------|
; | D4 | D5 | D6 | D7 | D8 | D9 | DA | DB | DC | DD | DE | DF | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7 |
; |___________________________________________________________________________________________________|
;

		movlw   0x80		;Set DDRAM Address
		movwf   POSI
		call	LCD_CMD

		call	Delay_50ms

		movlw   0x4C		;"L"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x45		;"E"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x43		;"C"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x54		;"T"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x55		;"U"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x52		;"R"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x41		;"A"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x53		;"S"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x20		;" "
		call	LCD_DAT
		call	ADDRESS

		movlw   0x44		;"D"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x45		;"E"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x20		;" "
		call	LCD_DAT
		call	ADDRESS

		movlw   0x42		;"B"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x41		;"A"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x54		;"T"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x45		;"E"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x52		;"R"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x49		;"I"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x41		;"A"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x53		;"S"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x98		;Set DDRAM Address
		movwf   POSI
		call	LCD_CMD

		call	Delay_50ms

		movlw   0x42		;"B"
		call	LCD_DAT
		call	ADDRESS

		call	digitos

		movlw   0x3D		;"="
		call	LCD_DAT
		call	ADDRESS

		movf	TenK,0
		call	LCD_DAT
		call	ADDRESS

		movf	Thou,0
		call	LCD_DAT
		call	ADDRESS

		movlw   0x2E		;"."
		call	LCD_DAT
		call	ADDRESS

		movf	Hund,0
		call	LCD_DAT
		call	ADDRESS

		movf	Tens,0
		call	LCD_DAT
		call	ADDRESS

		movlw   0x56		;"V"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x64		;"d"
		call	LCD_DAT
		call	ADDRESS

		movlw   0x63		;"c"
		call	LCD_DAT

		return

;*****************************************************************************************
;SUBRUTINA PARA MOSTRAR LOS DATOS DE LA EEPROM POR PAGINAS
;*****************************************************************************************
letSW3:
;DIRECCIONES DDRAM
; 0x80 LINEA 1 POSICION 1
; 0xC0 LINEA 2 POSICION 1
; 0x94 LINEA 3 POSICION 1
; 0xD4 LINEA 4 POSICION 1
;
;   1    2    3    4    5    6    7    8    9    10   11   12   13   14   15   16   17   18   19   20
;  ___________________________________________________________________________________________________
; | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 8A | 8B | 8C | 8D | 8E | 8F | 90 | 91 | 92 | 93 |
; |---------------------------------------------------------------------------------------------------|
; | C0 | C1 | C2 | C3 | C4 | C5 | C6 | C7 | C8 | C9 | CA | CB | CC | CD | CE | CF | D0 | D1 | D2 | D3 |
; |---------------------------------------------------------------------------------------------------|
; | 94 | 95 | 96 | 97 | 98 | 99 | 9A | 9B | 9C | 9D | 9E | 9F | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 |
; |---------------------------------------------------------------------------------------------------|
; | D4 | D5 | D6 | D7 | D8 | D9 | DA | DB | DC | DD | DE | DF | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7 |
; |___________________________________________________________________________________________________|
;

		call	rdEEP

		movwf	VIN

		call	conv_ADC

		movlw   0x80		;Set DDRAM Address
		movwf   POSI
		call	LCD_CMD

		call	Delay_50ms

		movlw   0x42		;"B"
		call	LCD_DAT
		call	ADDRESS

		call	digitos

		movlw   0x3D		;"="
		call	LCD_DAT
		call	ADDRESS

		movf	TenK,0
		call	LCD_DAT
		call	ADDRESS

		movf	Thou,0
		call	LCD_DAT
		call	ADDRESS

		movlw   0x2E		;"."
		call	LCD_DAT
		call	ADDRESS

		movf	Hund,0
		call	LCD_DAT
		call	ADDRESS

		movf	Tens,0
		call	LCD_DAT

		return

;*****************************************************************************************
;Delay 5 useg subroutine
;*****************************************************************************************
Delay_5us:
	goto D1         ; 2 ciclos delay
D1  goto D2         ; 2 ciclos delay
D2  goto D3         ; 2 ciclos delay
D3  goto D4         ; 2 ciclos delay
D4  goto D5         ; 2 ciclos delay
D5  				; 1 ciclo delay
	return			; 2+2 Fin.

;*****************************************************************************************
;Delay 40 useg subroutine
;*****************************************************************************************
Delay_40us:
		movlw	.18			; 1 set numero de repeticion 
		movwf	PDel0		; 1 |
PLoop0	clrwdt				; 1 clear watchdog
		decfsz	PDel0, 1	; 1 + (1) es el tiempo 0  ?
		goto	PLoop0		; 2 no, loop
PDelL1	goto	PDelL2		; 2 ciclos delay
PDelL2	clrwdt				; 1 ciclo delay
		return				; 2+2 Fin.

;*****************************************************************************************
;Delay 2 mseg subroutine
;*****************************************************************************************
Delay_2ms:
		movlw	.5			; 1 set numero de repeticion  (B)
        movwf	PDel1		; 1 |
PLoop1  movlw	.159		; 1 set numero de repeticion  (A)
        movwf	PDel2		; 1 |
PLoop2  clrwdt				; 1 clear watchdog
        clrwdt				; 1 ciclo delay
        decfsz	PDel2, 1	; 1 + (1) es el tiempo 0  ? (A)
        goto	PLoop2		; 2 no, loop
        decfsz	PDel1, 1	; 1 + (1) es el tiempo 0  ? (B)
        goto	PLoop1		; 2 no, loop
        return				; 2+2 Fin.

;*****************************************************************************************
;Delay 32 mseg subroutine
;*****************************************************************************************
Delay_32ms:
		movlw	.89			; 1 set numero de repeticion  (B)
		movwf	PDel3		; 1 |
PLoop3  movlw	.143		; 1 set numero de repeticion  (A)
        movwf	PDel4		; 1 |
PLoop4  clrwdt				; 1 clear watchdog
        clrwdt				; 1 ciclo delay
        decfsz	PDel4, 1	; 1 + (1) es el tiempo 0  ? (A)
        goto	PLoop4		; 2 no, loop
        decfsz	PDel3, 1	; 1 + (1) es el tiempo 0  ? (B)
        goto	PLoop3		; 2 no, loop
PDelL3  goto	PDelL4		; 2 ciclos delay
PDelL4  goto	PDelL5		; 2 ciclos delay
PDelL5						; 1 ciclo delay
        return				; 2+2 Fin.

;*****************************************************************************************
;Delay 50 mseg subroutine
;*****************************************************************************************
Delay_50ms:
		movlw	.110		; 1 set numero de repeticion  (B)
        movwf	PDel5		; 1 |
PLoop5  movlw	.181		; 1 set numero de repeticion  (A)
        movwf	PDel6		; 1 |
PLoop6  clrwdt				; 1 clear watchdog
        clrwdt				; 1 ciclo delay
        decfsz	PDel6, 1	; 1 + (1) es el tiempo 0  ? (A)
        goto	PLoop6		; 2 no, loop
        decfsz	PDel5, 1	; 1 + (1) es el tiempo 0  ? (B)
        goto	PLoop5		; 2 no, loop
PDelL6  goto	PDelL7		; 2 ciclos delay
PDelL7  goto	PDelL8		; 2 ciclos delay
PDelL8  clrwdt				; 1 ciclo delay
        return				; 2+2 Fin.

;*****************************************************************************************
;Delay 500 mseg subroutine
;*****************************************************************************************
Delay_500ms:
		movlw	.14			; 1 set numero de repeticion  (C)
		movwf	PDel7		; 1 |
PLoop7	movlw	.72			; 1 set numero de repeticion  (B)
		movwf	PDel8		; 1 |
PLoop8	movlw	.247		; 1 set numero de repeticion  (A)
		movwf	PDel9		; 1 |
PLoop9	clrwdt				; 1 clear watchdog
		decfsz	PDel9, 1	; 1 + (1) es el tiempo 0  ? (A)
		goto	PLoop9		; 2 no, loop
		decfsz	PDel8,  1	; 1 + (1) es el tiempo 0  ? (B)
		goto	PLoop8		; 2 no, loop
		decfsz	PDel7,  1	; 1 + (1) es el tiempo 0  ? (C)
		goto	PLoop7		; 2 no, loop
PDelL9	goto	PDelLA		; 2 ciclos delay
PDelLA	clrwdt				; 1 ciclo delay
		return				; 2+2 Fin.

	end
