;===================================================================================================
;===================================================================================================

	LIST P=18F4550
#include p18F4550.inc

;===================================================================================================
;                                      CO
;===================================================================================================

	CONFIG FOSC = HSPLL_HS, PLLDIV = 1,CPUDIV = OSC1_PLL2,USBDIV = 2,PWRT = ON,BOR = SOFT, VREGEN = OFF
	CONFIG WDT = OFF ,WDTPS = 1,MCLRE = ON,PBADEN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF

;===================================================================================================
;                                   variables
;===================================================================================================

LCD_E      EQU 2 ;Bit del puerto D para control de E.
LCD_RW     EQU 1 ;Bit del puerto D para control de R/W.
LCD_RS     EQU 0 ;Bit del puerto D para control de RS.
Emcoder    EQU 0X00 ;Constante del temporizador 1
EmcoderH   EQU 0X01;Constante del temporizador 2
EmcoderU   EQU 0x02;constantes BCD A1 (200)
TMR0_TEM   EQU 0x03;constante altura o grado de pertenencia
TMR0_TEM_H EQU 0x04 ;Reserva un Byte para la Variable CONT1
TECLA      EQU 0x05 ;Reserva un Byte para la Variable CONT2
BUCLE1     EQU 0x06
BUCLE2     EQU 0x07
DIG1       EQU 0x08
REGCOM     EQU 0x09
REGCOM1	   EQU 0x0A;constante 450 parte baja      grado de pertenencia a conjunto
regdes	   EQU 0x0B;registro de desplasamiento

var0       EQU 0x0C;variables para guardar
var1       EQU 0x0D;el Nun. devueltas
var2       EQU 0x0E


conta2     EQU 0x0F;variables para guardar
CONTA3     EQU 0x10;el Nun. devueltas

Reg_S      EQU 0x11
Reg_W      EQU 0x12

reg1     EQU 0x13
reg2      EQU 0x14
reg3      EQU 0x15

CTL      EQU 0x16
CTH      EQU 0x17

cont_low    EQU 0x18
cont_hig    EQU 0x19

des_final_0 EQU 0x1A


Dato_B_L    EQU 0x1B
Dato_B_H    EQU 0x1C
Dato_B_U    EQU 0x1D
Dato_A_L    EQU 0x1E
Dato_A_H    EQU 0x1F
Dato_A_U    EQU 0x20
Resultado_L EQU 0x21
Resultado_H EQU 0x22
Resultado_U EQU 0x23
Res_Var     EQU 0x24

BINLM     EQU 0x25
BINHM     EQU 0x26;variables para guardar

tem.imp.lcd0  EQU 0x27;la posicon actual conbertido a binario
tem.imp.lcd1  EQU 0x28;variables para guardar
var.com       EQU 0x29;la posicon a ir
var.num.mm    EQU 0x2A

binpospaL EQU 0x2B;variable para guardar la posicon a ir conbertido a binario
binpospaH EQU 0x2C;variable para guardar la posicon a ir conbertido a binario

MILES     EQU 0x2D
CENTENAS  EQU 0x2E
DECENAS   EQU 0x2F
UNIDADES  EQU 0x30
MILESM    EQU 0x31
CENTENASM EQU 0x32
DECENASM  EQU 0x33
UNIDADESM EQU 0x34
BINL      EQU 0x35;\_Registros en donde va la RPM en Binario del USUARIO
BINH      EQU 0x36
;BINLM     EQU 0x37;\_ Registros en donde se almacena la RPM del MOTOR en binario
;BINHM     EQU 0x38
TEMP      EQU 0x39
var3      EQU 0x3A
ci_100    EQU 0x3B
cu_4      EQU 0x3C
gua_erroL EQU 0x3D;variables para guardar error parte baja
gua_erroH EQU 0x3E;variables para guardar error parte alta
seis_6    EQU 0x3F;variables para guardar resultado (b-x)parte baja

tem_var0 EQU 0x40
tem_var1 EQU 0x41
tem_var2 EQU 0x42

error_l EQU 0x43
error_h EQU 0x44

ARG1L EQU 0x45
ARG1H EQU 0x46
ARG2L EQU 0x47
ARG2H EQU 0x48
RES0 EQU 0x49
RES1 EQU 0x4A
RES2 EQU 0x4B
RES3 EQU 0x4C

or_0      EQU 0x5F;variables para guardar resultado (b-x)parte alta

reg_X     EQU 0x60;variables para guardar
DECENAS_MIL  EQU 0x61;variables para guardar las decenas de mil
DECENAS_MILM EQU 0x62;variables para guardar las decenas de mil
R_D2L	  EQU 0x63;variables para guardar distancia 2 parte baja de forrmula P1*(X-D1)
R_x 	  EQU 0x64;variables para guardar distancia 2 parte alta                 D1

;===================================================================================================
;                            variables banco1
;===================================================================================================

btmH     EQU 0xA0
btmL     EQU 0xA1
count    EQU 0xA2
index    EQU 0xA3
qH       EQU 0xA4;variable para guardar resultado division parte alta
qL       EQU 0xA5;variable para guardar resultado division parte baja
topH     EQU 0xA6
topL     EQU 0xA7
mulcH    EQU 0xA8
mulcL    EQU 0xA9
mulpH    EQU 0xAA
mulpL    EQU 0xAB
prodL    EQU 0xAC
prodH    EQU 0xAD
Reg_W1   EQU 0xAE
Reg_S1   EQU 0xAF
ven_27   EQU .27

;===================================================================================================
;===================================================================================================

regdes1   set b'00000001'
regdes2   set b'00000010'
regdes3   set b'00000100'
regdes4   set b'00001000'
K_0       set b'00000000';constante cero

;===================================================================================================

RST org 0x00
	goto INICIO
	org 0x08
	goto ISR
	org 0x20
;INICIO org 0x9E
;BIN_A_BCD org

;===================================================================================================
;                  RUTINA PARA CONVERSION DE VELOCIDAD
;===================================================================================================
	
TABLA_CONV
	rlncf TECLA,W
	addwf PCL,1
	nop
	retlw '1' ;Tecla nº1 = 1
	retlw '2' ;Tecla nº2 = 2
	retlw '3' ;Tecla nº3 = 3
	retlw b'00001010' ;Tecla nº4 = A
	retlw '4' ;Tecla nº5 = 4
	retlw '5' ;Tecla nº6 = 5
	retlw '6' ;Tecla nº7 = 6
	retlw b'00001011' ;Tecla nº8 = B
	retlw '7' ;Tecla nº9 = 7
	retlw '8' ;Tecla nº10 = 8
	retlw '9' ;Tecla nº11 = 9
	retlw b'00001100' ;Tecla nº12 = C
	retlw b'00001101' ;Tecla nº13 = *
	retlw '0'         ;Tecla nº14 = 0
	retlw b'00001111' ;Tecla nº15 = #
	retlw b'00001101' ;Tecla nº16 = D

;===================================================================================================
;                  RUTINA PARA CARGA DE VELOCIDAD
;===================================================================================================

con_vel
	rlncf WREG,0
	addwf PCL,1
	nop
	retlw d'12'
	retlw d'14'
	retlw d'20'
	retlw d'25'
	retlw d'30'
	retlw d'35'
	retlw d'46'
	retlw d'60'
	retlw d'75'

;=====================================================================================
;                        PROGRAMA PRINCIPAL
;=====================================================================================

INICIO
	clrf MILES
	clrf CENTENAS
	clrf DECENAS
	clrf UNIDADES
	clrf MILESM
	clrf CENTENASM
	clrf DECENASM
	clrf UNIDADESM
	clrf DECENAS_MIL
	clrf DECENAS_MILM

	clrf tem_var0
	clrf tem_var1
	clrf tem_var2
	clrf Resultado_L
	clrf Resultado_H
	clrf Resultado_U
;	BINL
;	BINH
;	BINLM
;	BINHM
;	TEMP
	clrf Emcoder
	clrf EmcoderH
;	gua_erroL
;	gua_erroH

	clrf var0
	clrf var1
	clrf var2
	clrf var3
	clrf PORTA
	clrf PORTB
	clrf PORTC
	clrf PORTD

	movlw .132
	movwf cu_4
	movlw .100
	movwf ci_100
	movlw .3
	movwf seis_6
	movlw .62
	movwf or_0

	movlw b'00001110'
	movwf REGCOM1
	
	movlw .15
	movwf ADCON1,0
	
	MOVLW 07h ;Configurar los comparadores
	MOVWF CMCON
	

	
	
	MOVLW b'00000000'
	MOVWF TRISD ;Configura todo el puerto D como salida.
	MOVLW b'00000001'
	MOVWF TRISC ;Configura todo el puerto B como salida
	movlw b'00010000'
	movwf TRISA ; Puero A como salidas
	movlw b'00001110' ; PB4-PB7 como entradas
	movwf TRISB ; PB0-PB3 como salidas
	movlw b'00000111'
	movwf TRISE	
	
	movlw b'00101000'
	movwf T0CON
	MOVLW 0x95 ;carga periodo
	MOVWF PR2 ;lo establece para el PWM
	MOVLW 0x05 ;configura Timer 2
	MOVWF T2CON ;preescalador 1/1, habilita Timer 2
	MOVLW .12
	MOVWF CCP2CON
;	BCF CCP1CON,CCP1X
;	BCF CCP1CON,CCP1Y
;	BSF CCP1CON,CCP1M3 ;Configura el modulo CCP1 para operación PWM
;	BSF CCP1CON,CCP1M2
	clrf CCPR2L

	clrf regdes

;	movlw b'00000001'
;	movwf regdes

	bsf PORTA,5,0
	call LCD_INI

	movlw .60
	movwf tem.imp.lcd1,0


;===================================================================================================
;                                      RUTINA DE PRUEBA
;===================================================================================================

	

;=====================================================================================



;=====================================================================================
;                             SUBRUTINA PARA POSISIONAR EN 0
;=====================================================================================
	
	

;===========================================================================================
;                         DEMORA PARA ESPERAR QE EL MOTOR PARE
;===========================================================================================

	call RETARDO00
	movlw .48
	movwf var0,0
	movlw .48
	movwf var1,0
	movlw .48
	movwf var2,0
	movlw .48
	movwf var3,0

;===========================================================================================
;          leer dato de la eepron para guardar en variable var.num.mm
;===========================================================================================

	MOVLW .0
	MOVWF EEADR ;Bits bajos de la dirección de memoria a leer
	BCF EECON1,EEPGD ;Puntero a la memoria de datos
	BCF EECON1,CFGS ;Acceso a la memoria EEPROM
	BSF EECON1,RD ;Lectura en EEPROM
	MOVFF EEDATA,var.num.mm ;W=EEDATA
;	movwf var.num.mm
	
;===========================================================================================
;===========================================================================================

	bsf T0CON,7
	movlw b'11111111'
	movwf TMR1H
	movff var.num.mm,TMR1L
	movlw b'10000111'
	movwf T1CON
	movlw b'11111111'
	movwf TMR0H
	movff var.num.mm,TMR0L
;	clrf TMR0L
	movlw b'01100000'
	movwf INTCON
	bsf INTCON,7
	bsf PIE1,0
	goto TECLAD; Inicia el programa teclado

;===========================================================================================
;                  SUBRUTINA PARA ACTUALISAR POSICION ACTUAL
; ======== Inicio - Rutina de Servicio de Interrupción =========
; ========== Guardando W y el Registro de Estado ==========
;===========================================================================================

ISR

b_0
	bsf PORTC,7 ;señalisador de interrupciones
;	btfsc INTCON,4
;	goto Inv.Giro
	btfsc INTCON,2 ;se a producido una interrupcion por tmr0
	goto INT_Tmr0


; ==========
	bcf var.com,0,0
	movf TMR0L,W
	movwf TMR0_TEM
;	movf TMR0H,W
;	movwf TMR0_TEM_H
	movlw b'11111111'
	movwf TMR0H
	movff var.num.mm,TMR0L


	movf var.num.mm,0,0
	cpfsgt TMR0_TEM,0
;	tstfsz TMR0_TEM;mira si in virtio giro antes de completar un mm
	goto no_no_in_g
	goto ad_tm0

no_no_in_g
	movlw b'11111111'
	movwf TMR1H
	movff var.num.mm,TMR1L
	goto T_F1_IN0
	
ad_tm0
	movlw b'11111111'
	movwf TMR1H
;	movf TMR0_TEM,W; si

;	tstfsz TMR1L,0
;	goto no_com_1_mm_tmr1
	movlw 0FF
	movwf TMR1L,0
	movf TMR0_TEM,W
	subwf TMR1L,1,0
	movf var.num.mm,0,0
	addwf TMR1L,1,0


;	movwf TMR1L,0
;	addwf TMR1L,F;   suma lo recorrido a avance actual
	
;	bcf PIR1,0
;	bcf INTCON,2
	goto sal.def


;no_com_1_mm_tmr1
;	movf TMR1L,0,0
;	cpfsgt TMR0_TEM,0
	
; TMR0_TEM_H     variable disponible para uso de calculos

INT_Tmr0
	bsf var.com,0,0
;	bcf PIR1,0
;	bcf INTCON,2
;	bcf T1CON,0
	movf TMR1L,W
	MOVWF cont_low
;	movf TMR1H,W
;	MOVWF cont_hig
;	bsf T1CON,0

	movlw b'11111111'
	movwf TMR1H
	movff var.num.mm,TMR1L

	movf var.num.mm,0,0
	cpfsgt cont_low,0
;	tstfsz cont_low ;mira si invirtio giro antes de completar un mm
	goto no_no_in_g_tmr0
	goto ad_tm1

no_no_in_g_tmr0
	movlw b'11111111'
	movwf TMR0H
	movff var.num.mm,TMR0L ;no comiensa conteo de 0
	goto Inc.mm ;salta a rutina de incrementos
	
ad_tm1
	movlw b'11111111'
	movwf TMR0H
;	movf cont_low,W; si 

	
	movlw 0FF
	movwf TMR0L,0
	movf cont_low,W
	subwf TMR0L,1,0
	movf var.num.mm,0,0
	addwf TMR0L,1,0
	goto sal.def
	
	
	
;	movwf TMR0L,0
;	addwf TMR0L,F;   suma lo recorrido a avance actual


Inc.mm
	btfsc des_final_0,7,0 ;maraca increnento negativo
	goto dec_E_mm

inc_mm_dec
	movf Emcoder,W
	sublw b'11111111'
	btfsc  STATUS,Z
 	goto HE
	incf Emcoder,F
	goto sal.def
	
HE
	incf EmcoderH,F
	clrf Emcoder
	goto sal.def


comiensa_positivo
	bcf des_final_0,7,0
	goto Inc.mm

;==========================================================================================

dec_E
	;btfsc INTCON,2
	;goto T_F1_IN0

T_F1_IN0
	btfsc des_final_0,7,0 ;maraca increnento negativo
	goto inc_mm_dec

dec_E_mm
	movlw K_0
	cpfseq EmcoderH

	;movf EmcoderH,W
	;sublw .0
	;btfss STATUS,Z
 	goto HE1

	movlw .0
	cpfseq Emcoder
	
	goto dec_enco
	
	
	btfsc var.com,0,0
	goto comiensa_positivo
	bsf des_final_0,7,0 ;maraca increnento negativo
;	tstfsz Emcoder

	;movf Emcoder,W
	;sublw .0
	;btfsc STATUS,Z
 	;goto sa_le

	goto inc_mm_dec
	goto sal.def

dec_enco
	decf Emcoder,F
	goto sal.def

HE1
	tstfsz Emcoder,0
	goto encoder_no0

	decf EmcoderH,F
;	tstfsz EmcoderH,0
;	goto encoder_no0_h
	movlw 0FF
	movwf Emcoder
	goto sal.def
	
encoder_no0
	decf Emcoder,1,0
	goto sal.def
	
;encoder_no0_h
	



sa_le01
	btfss PIR1,0
	goto salt.revin.2
	movlw b'11111111'
	movwf TMR1H
	movff var.num.mm,TMR0L
	goto sal.def

salt.revin.2
	btfss INTCON,2
	goto sal.def
	movlw b'11111111'
	movwf TMR0H
	movff var.num.mm,TMR0L

sal.def
	bcf PIR1,0
	bcf INTCON,2



	bcf PORTC,7 ;señalisador de interrupciones
	retfie FAST


;Inv.Giro
;	btfsc PORTB,0
;	goto adelan.0
;	movlw b'11111111'
;	movwf TMR0H
;	movff TMR1L,TMR0L
;	movlw b'11111111'
;	movwf TMR1H
;	clrf TMR1L
;	goto rev.direc

;adelan.0
;	movlw b'11111111'
;	movwf TMR1H
;	movff TMR0L,TMR1L
;	movlw b'11111111'
;	movwf TMR0H
;	clrf TMR0L


;rev.direc
;	btfss PORTB,0
;	goto pon.1
;	bcf INTCON2,6
;	bcf INTCON,1
;	retfie FAST

;pon.1
;	bsf INTCON2,6

;	bcf INTCON,1
;	retfie FAST


;==========================================================================================
;                               SUBRRUTINA LCD_Comando
;==========================================================================================

LCD_Comando
	BCF PORTA,0    ;RS
	nop
	BSF PORTA,1    ;E
	nop
	MOVWF PORTD	; Se enviara Comando.-
	CALL Demora_5Us
	BCF PORTA,1 ; Envio Comando.-
	CALL Demora_100Us
	RETURN

;============================================================================================
;                      SUBRRUTINA LCDC: ( ESCRIBIR UN DATO O CARACTER )
;============================================================================================

LCDC
	BSF PORTA,0    ;RS
	nop
	BSF PORTA,1    ;E
	nop
	MOVWF PORTD
	CALL Demora_5Us
	BCF PORTA,1 ; Se enviara Caracter.-
	CALL Demora_100Us
	RETURN

;============================================================================================
;                      SUBRRUTINA LCDC: CARACTER modificando registro
;============================================================================================

LCDC_Mod
	BSF WREG,4
	BSF WREG,5

	BSF PORTA,0    ;RS
	nop
	BSF PORTA,1    ;E
	nop
	MOVWF PORTD
	CALL Demora_5Us
	BCF PORTA,1 ; Se enviara Caracter.-
	CALL Demora_100Us
	RETURN

;============================================================================================
;                   ARCHIVO RETARDO.INC
;============================================================================================

RETARDO00
	   movlw .255
	   movwf BUCLE1

TOP10  movlw .255
	   movwf BUCLE2

TOP20  movlw .10
	   movwf conta2

TOP30  decfsz conta2,1
	   goto   TOP30
	   decfsz BUCLE2,1
	   goto   TOP20
	   decfsz BUCLE1,1
	   goto   TOP10
	   return

;============================================================================================
;                   ARCHIVO RETARDO.INC
;============================================================================================

RETARDO0
	movlw .255
	   movwf BUCLE1

TOP1   movlw .255
	   movwf BUCLE2

TOP2
	   decfsz BUCLE2,1
	   goto   TOP2
	   decfsz BUCLE1,1
	   goto   TOP1
	   return

;========================================================================================================================================
;========================================================================================================================================
;                                              ARCHIVO TECLAD.INC
;========================================================================================================================================
;========================================================================================================================================

TECLAD
TECL_SCAN ; Escanea el teclado

	   clrf   TECLA ;Borra Tecla y
	   incf   TECLA,F ;prepara Tecla para primer código.
;	   incf   TECLA,F
	   movlw  b'01110000' ;Saca 0 a la primera fila
	   movwf  PORTB ;de la Puerta B
	   nop ;No operar para estabilizaci¢n de señal.
CHEQ_COLUM ;Chequeamos columnas
	   btfss  PORTB,3 ;Primera columna = 0
	   goto   ANTIREBOTES ;Sale si se ha pulsado tecla.
	   incf   TECLA,F ;Si no tecla pulsada, incrementa tecla.
	   btfss  PORTB,2 ;Segunda columna = 0
	   goto   ANTIREBOTES ;Sale si se ha pulsado tecla.
	   incf   TECLA,F ;Si no tecla pulsada, incrementa tecla.
	   btfss  PORTB,1 ;Tercera columna = 0
	   goto   ANTIREBOTES ;Sale si se ha pulsado tecla.
	   incf   TECLA,F ;Si no tecla pulsada, incrementa tecla.
	   incf   TECLA,F ;Si no tecla pulsada,incrementa Tecla.
	
CAMBIO movlw d'17' ; Carga W con de Teclas + 1.
	   subwf  TECLA,W ; y lo compara con el valor actual 
	   btfsc  STATUS,Z ;No salta si no se ha pulsado ninguna
	   goto   TECL_SCAN ;No ha sido pulsada ninguna tecla.
	   bsf    STATUS,C ;Pone a 1 el bit de carry.
	   rrcf  PORTB,1 ;Rota para escaneo a otra fila.




	btfss PORTE,2 ; mira si apaga puente H
	goto apaga.p.h

accce.dec


	incfsz tem.imp.lcd0

	goto CHEQ_COLUM ;Vuelve a revisar columnas

	incfsz tem.imp.lcd1

	goto CHEQ_COLUM ;Vuelve a revisar columnas

	movlw .60
	movwf tem.imp.lcd1,0


	
	btfsc PORTC,7
	goto en_led
	bsf PORTC,7
	goto salt_led

en_led	
	bcf PORTC,7

salt_led
	
	
	
	
	
	movff Emcoder,BINLM
	movff EmcoderH,BINHM
	call BIN_A_BCD


	btfss des_final_0,7,0; mira si ya es 0 si es 0 maraca incremento negativo
	goto in_negativo_con_teclado

	
	movlw  b'11000000'
	CALL LCD_Comando
	movlw '-' ;Coloca el carácter ASCII en W
	call LCDC
	goto salata_pos_0_teclado

	
	
in_negativo_con_teclado

	movlw  b'11000000'
	call LCD_Comando

salata_pos_0_teclado
;	movf MILESM,W
;	call LCDC_Mod
	movf CENTENASM,W
	call LCDC_Mod
	movf DECENASM,W
	call LCDC_Mod
	movf UNIDADESM,W
	call LCDC_Mod

	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC

;	btfss var.com,0
;	goto time_1
;	movff TMR0L,BINLM
;	goto sale_imp

;time_1
;	movff TMR1L,BINLM

;sale_imp
	movff TMR0L,BINLM
	clrf BINHM
	call BIN_A_BCD
	movlw  b'10001011'
	CALL LCD_Comando

	movlw 'A'
	call LCDC
	movlw ' '
	call LCDC

;	movf MILESM,W
;	call LCDC_Mod
	movf CENTENASM,W
	call LCDC_Mod
	movf DECENASM,W
	call LCDC_Mod
	movf UNIDADESM,W
	call LCDC_Mod
	movlw  b'10001010'
	CALL LCD_Comando
	
	movff TMR1L,BINLM
	clrf BINHM
	call BIN_A_BCD
	movlw  b'11001011'
	CALL LCD_Comando

	movlw  'B'
	call LCDC
	movlw ' '
	call LCDC

;	movf MILESM,W
;	call LCDC_Mod
	movf CENTENASM,W
	call LCDC_Mod
	movf DECENASM,W
	call LCDC_Mod
	movf UNIDADESM,W
	call LCDC_Mod
	movlw  b'10001010'
	CALL LCD_Comando


	goto CHEQ_COLUM ;Vuelve a revisar columnas


ANTIREBOTES ; ahora se espera a que la tecla sea soltada para evitar rebotes
	   call   RETARDO0
	   movf   TECLA,0
	   call   TABLA_CONV ;llama a la tabla de conversión y retorna
	   movwf  DIG1
	   call   CARGA_DIG1
FALSE  movf  PORTB,0
	   andlw b'00001110'
	   
	   subwf  REGCOM1,0
       btfsc  STATUS,Z
       goto   TRUE
	   goto   FALSE

TRUE   
	   call   RETARDO0
	   goto   TECL_SCAN ;vuelve al inicio del programa principal.

;====================================================================
;                 rutina PWM
;====================================================================

PWM
	movf CTH,W ;si no se ha presionado obtiene copia de CT parte baja
	movwf CCPR2L ;actualiza parte baja del CT real
;**** a continuación actualiza la parte alta del CT real
	MOVLW 0xCF ;máscara
	ANDWF CCP2CON,1 ;limpia los dos msbits del CT real
	SWAPF CTL,W ;copia los 2 bits bajos de CTH en el nibble alto de W
	IORWF CCP2CON,1 ;pone bits que deben ser 1 en los dos msb del CT real
;**** con esto queda actualizada la parte alta del CT real
	return

;====================================================================
;                      RETARDO DE 1.7 ms
;====================================================================


RETAR_1.7_MS
	movlw   .55
	movwf   conta2
LOOP02 movlw .10
	movwf   CONTA3	
LOOP01 nop
	nop
	nop
	decfsz  CONTA3,1
	goto    LOOP01
	decfsz  conta2,1
	goto    LOOP02
	return
 
;====================================================================
;====================================================================

Demora_100Us
	MOVLW .240
	MOVWF reg1

dos2
	DECFSZ reg1,1
	GOTO dos2 ; cuando reg1 llegue a 0
	return

;====================================================================
;====================================================================

Demora_5Us
	MOVLW .19
	MOVWF reg1

dosA0
	DECFSZ reg1,1
	GOTO dosA0 ; cuando reg1 llegue a 0
	return

;=====================================================================================================
;=====================================================================================================
;                               subrutina para cargar dijitos en display
;=====================================================================================================
;=====================================================================================================

CARGA_DIG1
	movlw .48
	cpfseq DIG1,0
	goto cont_car_dig
	call RETARDO00
	btfsc PORTB,2,0
;	movlw .48
;	cpfseq DIG1,0
	goto cont_car_dig
	call RETARDO00
	btfsc PORTB,2,0
;	movlw .48
;	cpfseq DIG1,0
	goto cont_car_dig
	call RETARDO00
	btfsc PORTB,2,0
;	movlw .48
;	cpfseq DIG1,0
	goto cont_car_dig
	call RETARDO00
	btfsc PORTB,2,0
;	movlw  .48
;	cpfseq DIG1,0
	goto cont_car_dig
	call RETARDO00
	btfsc PORTB,2,0
;	movlw  .48
;	cpfseq DIG1,0
	goto cont_car_dig

	clrf EmcoderH
	clrf Emcoder
	movlw b'11111111'
	movwf TMR0H
	movff var.num.mm,TMR0L
	movlw b'11111111'
	movwf TMR1H
	movff var.num.mm,TMR1L
	return

cont_car_dig
	MOVF  DIG1,W   ;Coloca el carácter ASCII en W
	SUBLW .13      ;verificar si es enter si es actualisar pantalla
	BTFSC STATUS,Z ;con los datos de las variables varx-varx
	goto  ax01      ;si no cargamos las variables corespondients
	
	MOVF  DIG1,W   ;Coloca el carácter ASCII en W
	SUBLW .15      ;verificar si es enter si es actualisar pantalla
	BTFSC STATUS,Z ;con los datos de las variables varx-varx
	goto  ax0      ;si no cargamos las variables corespondients
	
	movlw b'10000011';b'10000101'
;	subwf regdes,0,0
;	movf regdes,0,0
;	sublw b'10000101'
	addwf regdes,0,0
	CALL LCD_Comando
	
	MOVf  DIG1,W
	CALL  LCDC
	
;=====================================================================================================

	movlw K_0
;	movf  regdes,W
	cpfseq regdes,0
;	sublw K_0
;	btfss STATUS,Z
	goto  SIG
	movf  DIG1,W
	movwf var0
	goto  SALIR
	
;=====================================================================================================

SIG
	movf  regdes,W
	sublw regdes1
	btfss STATUS,Z
	goto  SIG1
	movf  DIG1,W
	movwf var1
	goto  SALIR
	
;=====================================================================================================

SIG1
	movf regdes,W
	sublw regdes2
	btfss STATUS,Z
	goto  SIG2
	movf  DIG1,W
	movwf var2
	goto SALIR1
	
;=====================================================================================================

SIG2
	movf regdes,W
	sublw regdes3
	btfss STATUS,Z
	goto SALIR1
	movf  DIG1,W
	movwf var3
	
SALIR1
	movlw K_0
	movwf regdes,0
;	goto sal_salir1

;	movlw  b'10000101'
;	CALL LCD_Comando
	return
	
;=====================================================================================================

SALIR
	incf regdes,1,0
;	rlncf regdes,1

	return

;===================================================================================================================
;===================================================================================================================
;                                     RUTINA DE CALCULOS E INTEGRACION DIFUSA
;===================================================================================================================
;===================================================================================================================

ax0
	bsf des_final_0,0,0
	bsf PORTA,2 ;invierte giro adelante disminuye tamaño papel a cortar


	movf var0,0,0
	cpfseq tem_var0,0
	goto control_fus
	movf var1,0,0
	cpfseq tem_var1,0
	goto control_fus
	movf var2,0,0
	cpfseq tem_var2,0
	goto control_fus

;	tstfsz EmcoderH ;testea variable parte alta si llego a 0
;	goto fun_moto

;	tstfsz Emcoder ;si testea variable parte baja si llego a 0
;	goto fun_moto
;	return ;si sale de subrutina

fun_moto
	movf var0,0,0
	movwf tem_var0,0
	movf var1,0,0
	movwf tem_var1,0
	movf var2,0,0
	movwf tem_var2,0

;	MOVF var0,W
;	ANDLW b'00001111'
;	call con_vel
;	MOVWF CTH
;	call PWM




	call acelera.progre

	
	
ter.ace.adelante


sal_a0
;	tstfsz Emcoder ;si testea variable parte baja si llego a 0
;	goto no.c
;	clrf CCPR2L
;	goto sal_ade ;si sale de subrutina

no.c
	btfsc PORTB,1
	goto sal_ade


	movff Emcoder,BINLM
	movff EmcoderH,BINHM
	call BIN_A_BCD


	btfss des_final_0,7,0; mira si ya es 0 si es 0 maraca incremento negativo
	goto in_negativo_con

	
	movlw  b'11000000'
	CALL LCD_Comando
	movlw '-' ;Coloca el carácter ASCII en W
	call LCDC
	goto salata_pos_0

	
	
in_negativo_con	
	
	
	
	movlw  b'11000000'
	CALL LCD_Comando
	
salata_pos_0
;	movf MILESM,W
;	call LCDC_Mod
	movf CENTENASM,W
	call LCDC_Mod
	movf DECENASM,W
	call LCDC_Mod
	movf UNIDADESM,W
	call LCDC_Mod

	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC

	btfss PORTB,1
	goto sal_a0

sal_ade
	clrf CCPR2L


	call RETARDO0
	call RETARDO0
	call RETARDO0
	
	movff Emcoder,BINLM
	movff EmcoderH,BINHM
	call BIN_A_BCD



	btfss des_final_0,7,0; mira si ya es 0 si es 0 maraca incremento negativo
	goto in_negativo

	
	movlw  b'11000000'
	CALL LCD_Comando
	movlw '-' ;Coloca el carácter ASCII en W
	call LCDC
	goto salata_pos_0_con

	
	
in_negativo



	movlw  b'11000000'
	CALL LCD_Comando

salata_pos_0_con
;	movf MILESM,W
;	call LCDC_Mod
	movf CENTENASM,W
	call LCDC_Mod
	movf DECENASM,W
	call LCDC_Mod
	movf UNIDADESM,W
	call LCDC_Mod

	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC

	call RETAR_1.7_MS
	movff TMR1L,BINLM

	clrf BINHM
	call BIN_A_BCD

	movlw b'11001011'
	CALL LCD_Comando

	movlw 'X'
	call LCDC
	movlw ' '
	call LCDC

;	movf MILESM,W
;	call LCDC_Mod
	movf CENTENASM,W
	call LCDC_Mod
	movf DECENASM,W
	call LCDC_Mod
	movf UNIDADESM,W
	call LCDC_Mod
	movlw  b'10001000'
	CALL LCD_Comando

	return

;========================================================================================================
;                                        RUTINA CONTROL VELOCIDAD
;========================================================================================================

ax01
	bcf des_final_0,0,0
	bcf PORTA,2;invierte giro atras aumenta tamaño papel a cortar

	movf var0,0,0
	cpfseq tem_var0,0
	goto control_fus
	movf var1,0,0
	cpfseq tem_var1,0
	goto control_fus
	movf var2,0,0
	cpfseq tem_var2,0
	goto control_fus

;	movlw .4
;	cpfseq EmcoderH
;	goto sigue
;	movlw .176
;	cpfseq Emcoder
;	goto sigue
;	return

sigue_atras
	movf var0,0,0
	movwf tem_var0,0
	movf var1,0,0
	movwf tem_var1,0
	movf var2,0,0
	movwf tem_var2,0


	call acelera.progre
	
	
ter.ace.atras	
	
sal_a1
;	movlw .4
;	cpfseq EmcoderH
;	goto no.176
;	movlw .176
;	cpfseq Emcoder
;	goto no.176
;	clrf CCPR2L
;	goto sal_f

;no.176
	btfsc PORTB,3
	goto sal_f


	movff Emcoder,BINLM
	movff EmcoderH,BINHM
	call BIN_A_BCD

	
	movlw  b'11000000'
	CALL LCD_Comando
	
;	movf MILESM,W
;	call LCDC_Mod
	movf CENTENASM,W
	call LCDC_Mod
	movf DECENASM,W
	call LCDC_Mod
	movf UNIDADESM,W
	call LCDC_Mod

	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC

	btfss PORTB,3
	goto sal_a1

sal_f	
	clrf CCPR2L

	call RETARDO0
	call RETARDO0
	call RETARDO0
	
	movff Emcoder,BINLM
	movff EmcoderH,BINHM
	call BIN_A_BCD



	movlw  b'11000000'
	CALL LCD_Comando
	
;	movf MILESM,W
;	call LCDC_Mod
	movf CENTENASM,W
	call LCDC_Mod
	movf DECENASM,W
	call LCDC_Mod
	movf UNIDADESM,W
	call LCDC_Mod

	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC

	movff TMR0L,BINLM
	clrf BINHM
	call BIN_A_BCD
	
	movlw b'11001011'
	CALL LCD_Comando

	movlw 'X'
	call LCDC
	movlw ' '
	call LCDC

;	movf MILESM,W
;	call LCDC_Mod
	movf CENTENASM,W
	call LCDC_Mod
	movf DECENASM,W
	call LCDC_Mod
	movf UNIDADESM,W
	call LCDC_Mod
	movlw  b'10001000'
	CALL LCD_Comando

	return


;========================================================================================================
;                                           RUTINA LCD PAG1
;========================================================================================================

LCD_INI 
	CALL Demora_15ms
	
	CALL Demora_15ms
	
	MOVLW 0x30
	MOVWF PORTD
	CALL Demora_5ms
	
	CALL Demora_5ms
	
	MOVLW 0x30
	MOVWF PORTD
	
	CALL Demora_2ms
	
	CALL Demora_2ms
	MOVLW 0x30
	MOVWF PORTD
	CALL Demora_100Us
	
	CALL Demora_100Us
	
	MOVLW b'00111000'
	CALL LCD_Comando
	
	CALL Demora_100Us
	
	CALL Demora_100Us
	MOVLW b'00001110'
	CALL LCD_Comando
	
	CALL Demora_100Us
	
	CALL Demora_100Us
	MOVLW b'00000110'
	CALL LCD_Comando
	
	CALL Demora_100Us
	
	CALL Demora_100Us
	MOVLW  b'00000001'
	CALL LCD_Comando
	
	CALL Demora_2ms
	
	CALL Demora_2ms
	MOVLW  b'10000000';195
	CALL LCD_Comando
	CALL Demora_100Us
	
	CALL Demora_100Us

;======================================================================================================
;======================================================================================================
;                  rutina de inicio modo normal o modo programacion
;======================================================================================================
;======================================================================================================

	MOVLW 'n' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'o' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'r' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'a' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'l' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	
	movlw  b'10001001'
	CALL LCD_Comando

	MOVLW 'p' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'r' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'o' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'g' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'r' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'a' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.

	movlw  b'11000011'
	CALL LCD_Comando

	MOVLW '3' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.

	movlw  b'11001101'
	CALL LCD_Comando

	MOVLW '1' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.

	bcf PORTB,7


	   movlw .255
	   movwf BUCLE1

TTOP10
	   movlw .255
	   movwf BUCLE2

TTOP20
	   btfss PORTB,1;modo programacion 1
	   goto modo.normal
	   btfss PORTB,3;modo normal 3
	   goto modo.programacion
	   movlw .100
	   movwf conta2

TTOP30
	   decfsz conta2,1
	   goto   TTOP30
	   decfsz BUCLE2,1
	   goto   TTOP20
	   decfsz BUCLE1,1
	   goto   TTOP10
	
modo.normal
	   MOVLW  b'00000001'
	   CALL LCD_Comando
	   CALL Demora_5ms


;======================================================================================================
;======================================================================================================


	MOVLW  b'10000000';195
	CALL LCD_Comando
	MOVLW 'I' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'r' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC


;	movlw  b'10001000'
;	CALL LCD_Comando

;	MOVLW '1' ;Coloca el carácter ASCII en W
;	CALL LCDC ;Rutina para escribir un carácter en el LCD.

	movlw  b'11000101'
	CALL LCD_Comando


	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'm' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	movlw  b'10000011'
	CALL LCD_Comando
	
	
	
	
	RETURN
	
;======================================================================================================
;                                          RETARDO DE 15 ms
;======================================================================================================

Demora_15ms
	MOVLW .80 ; Aquí se cargan los registros
	MOVWF reg1 ; reg1, reg2 y reg3
; con los valores 10, 20 y 30
tres0 MOVLW .30 ; respectivamente
	MOVWF reg2
dos0 MOVLW .26
	MOVWF reg3
uno0 DECFSZ reg3,1 ; Aquí se comienza a decrementar
	GOTO uno0 ; Cuando reg3 llegue a 0
	DECFSZ reg2,1 ; le quitare 1 a reg2
	GOTO dos0 ; cuando reg2 llegue a 0
	DECFSZ reg1,1 ; le quitare 1 a reg1
	GOTO tres0 ; cuando reg1 llegue a 0
	RETURN

;===================================================================================================
;                                          RETARDO DE 5 ms
;===================================================================================================

Demora_5ms
	MOVLW .172 ; Aquí se cargan los registros
	MOVWF reg1 ; reg1, reg2 y reg3
; con los valores 10, 20 y 30
dos MOVLW .116 ; respectivamente
	MOVWF reg2
uno	DECFSZ reg2,1 ; le quitare 1 a reg2
	GOTO uno ; cuando reg2 llegue a 0
	DECFSZ reg1,1 ; le quitare 1 a reg1
	GOTO dos ; cuando reg1 llegue a 0
	RETURN ; regresare al lugar

;===================================================================================================
;                                      RETARDO DE 5 ms
;===================================================================================================

Demora_2ms
	MOVLW .80 ; Aquí se cargan los registros
	MOVWF reg1 ; reg1, reg2 y reg3
; con los valores 10, 20 y 30
dos1 MOVLW .99 ; respectivamente
	MOVWF reg2
uno1	DECFSZ reg2,1 ; le quitare 1 a reg2
	GOTO uno1 ; cuando reg2 llegue a 0
	DECFSZ reg1,1 ; le quitare 1 a reg1
	GOTO dos1 ; cuando reg1 llegue a 0
	RETURN ; regresare al lugar

;==================================================================================================
;                                     resta de 24bits
;==================================================================================================

res_24B
	movf	Dato_B_L,W	;Carga menos peso del dato B (sustraendo)
	subwf	Dato_A_L,W	;Resta menos peso del dato A (minuendo)
	movwf	Resultado_L	;Almacena el resultado
	movf	Dato_B_H,W	;Carga más peso del dato B (sustraendo)
	btfsc	STATUS,C	;Hubo acarreo (CARRY = 0) anterior ??
	goto	AA_00
	addlw	1	;Si, añade 1 al acumulador (sustraendo)
	btfsc	STATUS,C
	bsf Res_Var,0

AA_00
	subwf	Dato_A_H,W	;Resta más peso del dato A (minuendo)
	movwf	Resultado_H	;Guarda el resultado
	

	
	movf	Dato_B_U,W
	btfss	STATUS,C
	addlw	1
	btfsc	Res_Var,0
	addlw	1
	subwf	Dato_A_U,W
	movwf	Resultado_U
	clrf	Res_Var
	return

;==================================================================================================
;                                    suma de 24bits
;==================================================================================================

suma_24B
	movf	Dato_B_L,W	;Carga menos peso del dato B (sustraendo)
	addwf	Dato_A_L,W	;Resta menos peso del dato A (minuendo)
	movwf	Resultado_L	;Almacena el resultado
	movf	Dato_B_H,W	;Carga más peso del dato B (sustraendo)
	btfss	STATUS,C	;Hubo acarreo (CARRY = 0) anterior ??
	goto	AA_A00
	addlw	1	;Si, añade 1 al acumulador (sustraendo)
	btfsc	STATUS,C
	bsf Res_Var,0

AA_A00
	addwf	Dato_A_H,W	;Resta más peso del dato A (minuendo)
	movwf	Resultado_H	;Guarda el resultado

	movf	Dato_B_U,W
	btfsc	STATUS,C
	addlw	1
	btfsc	Res_Var,0
	addlw	1
	addwf	Dato_A_U,W
	movwf	Resultado_U
	clrf	Res_Var
	return

;================================================================================================================
;         macros de suma y resta de un valor de 8 bits a una palabra de 16 bits
;================================================================================================================
; Argumentos: v =valor a sumar/restar
; MSB: LSB = direcciones de la palabra de 16 BITS
; d =destino (w/f)
; Esta macro SUMA W al par de registros de 16 bits BINH: BINL

SUMA MACRO v, LSB, MSB, d
	movlw v
	addwf LSB,d
	;addwfc LSB,d ; LSB = LSB + w
	btfsc STATUS,C
	incf MSB,d ; MSB++ si hay CARRY (directiva de MPLAB)
	ENDM
; Esta macro RESTA W al par de registros de 16 bits BINH:BINL
RESTA MACRO v, LSB, MSB, d
	movlw v ; Carga Argumento en W
	subwf LSB,d ; LSB = LSB - w
	btfss STATUS,C ; Hay BORROW?
	decf MSB,d ; MSB-- si hay BORROW
	ENDM

;===================================================================================================
; RUTINA PARA CONVERSION DE BINARIO A BCD
;===================================================================================================

;Recibe la cantidad Binaria BINH:BINL y entrega los dígitos BCD en UNIDADES, DECENAS, ;CENTENAS, MILES. Su capacidad es de 0d a 9999d
BIN_A_BCD
	clrf MILESM ;borra registros de trabajo
	clrf CENTENASM
	clrf DECENASM
	clrf UNIDADESM
RESTAR_MIL
	movf BINHM,w
	movwf TEMP ;Guarda MSB en TEMP
	
	movlw	0E8		;Carga menos peso del dato B (sustraendo)
	subwf	BINLM,1		;Resta menos peso del dato A (minuendo) Almacena el resultado		;
	movlw	3		;Carga más peso del dato B (sustraendo)
	btfss	STATUS,C		                ;Hubo acarreo (CARRY = 0) anterior ??
	addlw	1		                ;Si, añade 1 al acumulador (sustraendo)
	subwf	BINHM,1		;Resta más peso del dato A (minuendo)Guarda el resultado
	
;	RESTA .250,BINLM,BINHM,f
;	RESTA .250,BINLM,BINHM,f ;Para restar 1000, resto 250
;	RESTA .250,BINLM,BINHM,f ;4 veces a BINHM:BINLM
;	RESTA .250,BINLM,BINHM,f ;
	movf BINHM,w
	subwf TEMP,f ;Hace TEMP = TEMP - W = TEMP - BINHM.
;Si al restar 1k hicimos BINHM<0, TEMP<0.
	btfss STATUS,C ;Salta si no hubo BORROW al restar esto
	goto FIN_1000S ;Hubo borrow, se restaron 1000 de más.
	incf MILESM,f ;No hubo borrow, incremente MILESM.
	goto RESTAR_MIL ;Sube a volver a restar 1000 y revisar...
FIN_1000S
	movlw	0E8		;Carga menos peso del dato A
	addwf	BINLM,1		;Suma menos peso del dato B Almacena el resultado	
    	movlw	3		;Carga más peso del dato A
    	btfsc	STATUS,C	;Hubo acarreo anterior ??
    	addlw	1		;Si, suma 1 al acumulador
    	addwf	BINHM,1	;Suma más peso del dato B Guarda el resultado

;	SUMA .250,BINLM,BINHM,f ;Sumamos 1000 para compensar
;	SUMA .250,BINLM,BINHM,f ;que se restaron.
;	SUMA .250,BINLM,BINHM,f ;
;	SUMA .250,BINLM,BINHM,f ;

RESTAR_CIEN
	movf BINHM,w
	movwf TEMP ;Guarda LSB en TEMP
	RESTA .100,BINLM,BINHM,f ;Resta 100 a la palabra BINHM:BINLM
	movf BINHM,w
	subwf TEMP,f ;Hace TEMP=TEMP- W = TEMP - BINLM.
;Si al restar 100 hicimos BINLM<0, TEMP<0.
	btfss STATUS,C ;Salta si no hubo BORROW al restar esto
	goto FIN_100S ;Hubo borrow, se restaron 100 de más.
	incf CENTENASM,f ;No hubo borrow, incremente CENTENASM.
	goto RESTAR_CIEN ;Sube a volver a restar 100 y revisar...
FIN_100S
	SUMA .100,BINLM,BINHM,f ;+100 para compensar los -100 de más
RESTAR_DIEZ
	movlw .10 ;No se usa la macro, la cantidad de DECENASM
	subwf BINLM,f ;máxima (100) nunca provocaría un acarreo.
	btfss STATUS,C ;Salta si no hubo BORROW al restar 10
	goto FIN_10S ;Hubo borrow, se restaron 10 de más.
	incf DECENASM,f ;No hubo borrow, incremente DECENASM.
	goto RESTAR_DIEZ
FIN_10S
	addwf BINLM,W ;+10 para compensar los -10 de más
	movwf UNIDADESM ;Lo que queda en w Son las UNIDADESM
	clrf BINLM ;Limpia LSB
	return


;========================================================================================================
; RUTINA PARA CONVERSIÓN DE BCD A BINARIO
;========================================================================================================

; Convierte los registros de UNIDADES, DECENAS, CENTENAS y MILES (codificados en BCD)
; Recibe la cantidad binaria en los registros MILES, CENTENAS, DECENAS y UNIDADES.
; Devuelve la cantidad codificada en binario, en dos registros: BINH y BINL.
; Su capacidad es de 0000d a 9999d.
;REGISTROS DE TRABAJO NECESARIOS: (definidos en el archivo principal)
; BINL: LSB de la cantidad en binario
; BINH: MSB de la cantidad en binario
; MILES: Unidades de Mil
; CENTENAS: ...
; DECENAS: ...
; UNIDADES: ....
BCD_A_BIN
	
	movf UNIDADESM,w ;Carga las UNIDADES en W,
	clrf UNIDADESM ;las borra del registro
	movwf BINLM ;y las guarda en el LSB
	clrf BINHM ;Limpia el MSB

SUMAR_DEC
	clrf WREG
	xorwf DECENASM,w ;Compara las DECENAS con 0 y deja resul. en w
	btfsc STATUS,Z ;Salta una linea si las decenas no son cero
	goto SUMAR_CENT ;Pasa a si no hay DECENAS (son 0)
	movlw .10 ;Carga 10 -decimal- en w
	addwf BINLM,f ;suma 10 al LSB
	decfsz DECENASM,F ;Decrementa decenas, salta si se sumaron todas
	goto $-4 ;Vuelve para sumar la siguiente decena

SUMAR_CENT
	clrf WREG
	xorwf CENTENASM,w ;Compara las CENTENAS con 0
	btfsc STATUS,Z ;Salta una linea si las CENTENAS no son cero
	return ;Pasa si no hay CENTENAS (son 0)

SUMAR100
	SUMA .100,BINLM,BINHM,f ;Suma 100 al par BINH:BINL
	decfsz CENTENASM,F
	goto SUMAR100 ;Vuelve para la siguiente centena
	return

;===================================================================================================
;===================================================================================================

apaga.p.h
	CALL Demora_15ms
	CALL Demora_15ms
	btfsc PORTE,2
	goto accce.dec
	bcf PORTA,3
	bcf PORTA,5
	MOVLW b'00001010'
	CALL LCD_Comando

des
	btfss PORTE,2
	goto des
	CALL Demora_15ms
	CALL Demora_15ms
	btfss PORTE,2
	goto des
	bsf PORTA,5
	MOVLW b'00001110'
	CALL LCD_Comando
	bsf PORTA,3
	goto accce.dec


;===================================================================================================
;===================================================================================================
;                              SUBRUTINA ACELERACION PROGRESIVA
;===================================================================================================
;===================================================================================================

acelera.progre
;	MOVF var0,W
;	ANDLW b'00001111'
;	MOVWF CTH
;	call con_vel

	movlw .75
	MOVWF CTH


	movlw .6 ;carga velocidad mas baja para acer aceleracion progresiva
	movwf reg3


mira
	cpfseq CTH
	goto ace.pro
	goto ter.ace

ace.pro
	movwf CCPR2L
	call RETARDO0
	call RETARDO0
	btfsc PORTB,1,0
	goto tes_si_ade

nosale_ac_p
	btfsc PORTB,3,0
	goto tes_si_atras

no_sale_ac_p
	incf reg3,1
	movf reg3,0
	goto mira
	
ter.ace
	movff CTH,CCPR2L
	return
	
tes_si_ade
	btfss des_final_0,0,0
	goto nosale_ac_p
	return

tes_si_atras
	btfsc des_final_0,0,0
	goto no_sale_ac_p
	return

;===================================================================================================
;===================================================================================================
;                                rutina modo programacion
;===================================================================================================
;===================================================================================================

modo.programacion
	btfss PORTB,3
	goto modo.programacion
	call RETARDO00
	call RETARDO00
	MOVLW  b'00000001'
	CALL LCD_Comando
	CALL Demora_2ms


	MOVLW 'i' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'n' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'g' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'r' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'e' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'c' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'e' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW ' ' ;Coloca el carácter ASCII en W
	CALL LCDC
	MOVLW 'd' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 'a' ;Coloca el carácter ASCII en W
	CALL LCDC ;Rutina para escribir un carácter en el LCD.
	MOVLW 't' ;Coloca el carácter ASCII en W
	CALL LCDC
	MOVLW 'o' ;Coloca el carácter ASCII en W
	CALL LCDC

	movlw  b'11000000'
	CALL LCD_Comando

;===================================================================================================
;===================================================================================================


escanea.teclado ; Escanea el teclado

	   clrf   TECLA ;Borra Tecla y
	   incf   TECLA,F ;prepara Tecla para primer código.
;	   incf   TECLA,F
	   movlw  b'01110000' ;Saca 0 a la primera fila
	   movwf  PORTB ;de la Puerta B
	   nop ;No operar para estabilizaci¢n de señal.
mira.columna ;Chequeamos columnas
	   btfss  PORTB,3 ;Primera columna = 0
	   goto   anti.ruido ;Sale si se ha pulsado tecla.
	   incf   TECLA,F ;Si no tecla pulsada, incrementa tecla.
	   btfss  PORTB,2 ;Segunda columna = 0
	   goto   anti.ruido ;Sale si se ha pulsado tecla.
	   incf   TECLA,F ;Si no tecla pulsada, incrementa tecla.
	   btfss  PORTB,1 ;Tercera columna = 0
	   goto   anti.ruido ;Sale si se ha pulsado tecla.
	   incf   TECLA,F ;Si no tecla pulsada, incrementa tecla.
	   incf   TECLA,F ;Si no tecla pulsada,incrementa Tecla.
	
	   movlw d'17' ; Carga W con de Teclas + 1.
	   subwf  TECLA,W ; y lo compara con el valor actual 
	   btfsc  STATUS,Z ;No salta si no se ha pulsado ninguna
	   goto   escanea.teclado ;No ha sido pulsada ninguna tecla.
	   bsf    STATUS,C ;Pone a 1 el bit de carry.
	   rrcf  PORTB,1 ;Rota para escaneo a otra fila.


	   goto mira.columna ;Vuelve a revisar columnas


anti.ruido ; ahora se espera a que la tecla sea soltada para evitar rebotes
	   call   RETARDO0
	   movf   TECLA,0
	   call   TABLA_CONV ;llama a la tabla de conversión y retorna
	   movwf  DIG1
	   goto   carga.dato.ee

falso
	   movf  PORTB,0
	   andlw b'00001110'
	   
	   subwf  REGCOM1,0
       btfsc  STATUS,Z
       goto   verdadero
	   goto   falso

verdadero   
	   call   RETARDO0
	   goto   escanea.teclado ;vuelve al inicio del programa principal.

;=====================================================================================================
;=====================================================================================================
;             subrutina para cargar dijitos en display el dato a guardar en la eepron
;=====================================================================================================
;=====================================================================================================

carga.dato.ee
	MOVF  DIG1,W   ;Coloca el carácter ASCII en W
	SUBLW .13      ;verificar si es enter si es actualisar pantalla
	BTFSC STATUS,Z ;con los datos de las variables varx-varx
	goto  guarda.eepron      ;si no cargamos las variables corespondients
	
	MOVF  DIG1,W   ;Coloca el carácter ASCII en W
	SUBLW .15      ;verificar si es enter si es actualisar pantalla
	BTFSC STATUS,Z ;con los datos de las variables varx-varx
	goto  guarda.eepron      ;si no cargamos las variables corespondients
	MOVf  DIG1,W
	CALL  LCDC
	
;=====================================================================================================

	movf  regdes,W
	SUBLW regdes1
	btfss STATUS,Z
	goto  SIG.E
	movf  DIG1,W
	movwf var0
	goto  SALIR.E
	
;=====================================================================================================

SIG.E
	movf  regdes,W
	SUBLW regdes2
	btfss STATUS,Z
	goto  SIG1.E
	movf  DIG1,W
	movwf var1
	goto  SALIR.E
	
;=====================================================================================================

SIG1.E
	movf regdes,W
	SUBLW regdes3
	btfss STATUS,Z
	goto  SIG2.E
	movf  DIG1,W
	movwf var2
	goto SALIR.E
	
;=====================================================================================================

SIG2.E
	movf regdes,W
	SUBLW regdes4
	btfss STATUS,Z
	goto SALIR1.E
	movf  DIG1,W
	movwf var3
	
SALIR1.E
	movlw regdes1
	movwf regdes
	movlw  b'11000000'
	CALL LCD_Comando
	goto falso
	
;=====================================================================================================

SALIR.E
	rlncf regdes,1

	goto falso

;===================================================================================================
;===================================================================================================

guarda.eepron
;	MOVF var0,W
;	ANDLW b'00001111'
;	MOVWF MILESM
	MOVF var1,W
	ANDLW b'00001111'
	MOVWF CENTENASM
	MOVF var2,W
	ANDLW b'00001111'
	MOVWF DECENASM
	MOVF var3,W
	ANDLW b'00001111'
	MOVWF UNIDADESM
	CALL BCD_A_BIN

	MOVLW .0
	MOVWF EEADR ;Bits bajos de la dirección de memoria a escribir
;	MOVLW DATA_EE_DATA
	MOVFF BINLM,EEDATA ;Valor de la memoria de datos a escribir
	BCF EECON1,EEPGD ;Puntero a la memoria de datos
	BCF EECON1,CFGS ;Acceso a la EEPROM
	BSF EECON1,WREN ;Activa escritura
	BCF INTCON,GIE ;Desactivación de las interrupciones
	MOVLW 55h
	MOVWF EECON2
	MOVLW 0AAh
	MOVWF EECON2
	BSF EECON1,WR ;Activa WR para empezar a escribir
;	BSF INTCON,GIE ;Activa las interrupciones

no.ter
	btfss PIR2,EEIF
	goto no.ter
	BCF EECON1,WREN ;Desactiva la escritura cuando se complete


	MOVLW .0
	MOVWF EEADR ;Bits bajos de la dirección de memoria a leer
	BCF EECON1,EEPGD ;Puntero a la memoria de datos
	BCF EECON1,CFGS ;Acceso a la memoria EEPROM
	BSF EECON1,RD ;Lectura en EEPROM
	MOVFF EEDATA,BINLM ;W=EEDATA

	call BIN_A_BCD
	


	movlw  b'11001101'
	CALL LCD_Comando
	
;	movf MILESM,W
;	call LCDC_Mod
	movf CENTENASM,W
	call LCDC_Mod
	movf DECENASM,W
	call LCDC_Mod
	movf UNIDADESM,W
	call LCDC_Mod

	call RETARDO00
	call RETARDO00
	call RETARDO00
	call RETARDO00

	goto modo.normal
	   
;===================================================================================================
;===================================================================================================
;                                rutinas math
;===================================================================================================
;===================================================================================================

multiplica
	movf ARG1L, W
	mulwf ARG2L ; ARG1L * ARG2L->
	movff PRODH, RES1 ;
	movff PRODL, RES0 ;
	movf ARG1H, W
	mulwf ARG2H ; ARG1H * ARG2H->
	movff PRODH, RES3 ;
	movff PRODL, RES2 ;
	movf ARG1L, W
	mulwf ARG2H ; ARG1L * ARG2H->
	movf PRODL, W ;
	addwf RES1, F ; Add cross
	movf PRODH, W ; products
	addwfc RES2, F ;
	clrf WREG ;
	addwfc RES3, F ;
	movf ARG1H, W ;
	mulwf ARG2L ; ARG1H * ARG2L->
	movf PRODL, W ;
	addwf RES1, F ; Add cross
	movf PRODH, W ; products
	addwfc RES2, F ;
	clrf WREG ;
	addwfc RES3, F
	return

;===================================================================================================
	
divide_24
DIV24_16u
        movlw   .24             ; for 24 shifts
        movwf   count            ;

        clrf    Resultado_L,0        ; clear remainder.
        clrf    Resultado_H,0        ;

d2416lp
        rlcf    RES0,f        ; build up remainder.
        rlcf    RES1,f        ;
        rlcf    RES2,f        ;
        rlcf    Resultado_L,f        ;
        rlcf    Resultado_H,f        ;

; remainder is 16-bit, but may have spilled over into carry.

        btfss   STATUS,C        ; check for remainder spill into carry.
        goto    d2416s          ;

        movf   ARG1L,0     ;
        subwfb  Resultado_L,f        ; Carry bit is the 17th bit of this
subtract
        movf   ARG1H,0     ;
        subwfb  Resultado_H,f        ;
        bsf     STATUS,C        ; bit is known to be zero here.
        goto    d2416ns         ;

d2416s 
        movf   ARG1L,0     ; Compare remainder with divisor.
        subwf   Resultado_L,w        ;
        movf   ARG1H,0     ;
        subwfb  Resultado_H,w        ;
        btfss   STATUS,C        ;
        goto    d2416ns         ; (remainder < divisor), shift in a '0'
        movf   ARG1L,0     ; The remainder is larger, so subtract
the
        subwf   Resultado_L,f        ; ... divisor FROM the remainder and
        movf   ARG1H,0     ; ... shift a '1' into the quot.
        subwfb  Resultado_H,f        ;

d2416ns
        decfsz  count,f          ; check all bits
        goto    d2416lp         ;
        rlcf    RES0,f        ; shift in final quotient bit.
        rlcf    RES1,f        ;
        rlcf    RES2,f        ;

        return

;===================================================================================================
;===================================================================================================
;                                rutina control logica difusa
;===================================================================================================
;===================================================================================================

control_fus
	bsf des_final_0,1,0

	movf var0,0,0
	movwf tem_var0,0
	movf var1,0,0
	movwf tem_var1,0
	movf var2,0,0
	movwf tem_var2,0

control_lf
	btfss PORTB,2,0
	goto sale_emer_lf
	movf var0,0,0
	ANDLW b'00001111'
	MOVWF CENTENASM,0
	movf var1,0,0
	ANDLW b'00001111'
	MOVWF DECENASM,W
	movf var2,0,0
	ANDLW b'00001111'
	MOVWF UNIDADESM,W
	CALL BCD_A_BIN
	movff BINLM,binpospaL
	movff BINHM,binpospaH
	movf EmcoderH,0,0
	cpfseq binpospaH
	goto bin_emc_no_igu
	movf Emcoder,0,0
	cpfseq binpospaL
	goto no_er_0_lf
	goto error0_l_f

no_er_0_lf
	cpfsgt binpospaL
	goto negativo_con_fus

posi_con_fus
	bcf PORTA,2;invierte giro atras aumenta tamaño papel a cortar
	movf Emcoder,0,0
	subwf binpospaL,0,0
	movwf gua_erroL,0
	movf EmcoderH,0,0
	btfss	STATUS,C		                ;Hubo acarreo (CARRY = 0) anterior ??
	addlw	1
	subwf binpospaH,0,0
	movwf gua_erroH,0
	goto h_error

bin_emc_no_igu	
	cpfslt binpospaH
	goto posi_con_fus

negativo_con_fus
	bsf PORTA,2 ;invierte giro adelante disminuye tamaño papel a cortar
	movf binpospaL,0,0
	subwf Emcoder,0,0
	movwf gua_erroL,0
	movf binpospaH,0,0
	btfss	STATUS,C		                ;Hubo acarreo (CARRY = 0) anterior ??
	addlw	1
	subwf EmcoderH,0,0
	movwf gua_erroH,0

h_error
	movf gua_erroL,0,0
	subwf cu_4,0,0
	movwf gua_erroL,0
	movf gua_erroH,0,0
	btfss STATUS,C		                ;Hubo acarreo (CARRY = 0) anterior ??
	addlw 1
	subwf seis_6,0,0
	movwf gua_erroH,0

	movwf ARG1H,0
	movff gua_erroL,ARG1L    
;	movff gua_erroH,ARG1H
	movlw .100
	movwf ARG2L,0
	clrf ARG2H,0
	call multiplica

	movlw .132
	movwf ARG1L,0
	movlw .3
	movwf ARG1H,0
	call divide_24

;	movlw .100
	movf RES0,0,0
	subwf ci_100,0,0

	movwf ARG1L,0
	clrf ARG1H,0

;	movlw .45
	cpfslt or_0,0
	goto mul_450

	movlw .90
	movwf ARG2L,0
	clrf ARG2H,0
	call multiplica
	goto div_100_lf

mul_450
	movlw .16;si 23 o mayor carga datos y sale
	cpfsgt ARG1L,0
	goto men_ca0
	movlw .55
	goto ac_pro_lf

men_ca0
	movlw .11
	cpfsgt ARG1L,0
	goto men_ca1
	movlw .48
	goto ac_pro_lf

men_ca1
	movlw .5
	cpfsgt ARG1L,0
	goto men_ca2
	movlw .33
	goto ac_pro_lf

men_ca2
	movlw .1
	cpfsgt ARG1L,0
	goto men_ca3
	movlw .26
	goto ac_pro_lf

men_ca3
;	movlw .4
;	cpfsgt ARG1L,0
;	goto men_ca3
	movlw .23
	goto ac_pro_lf


div_100_lf
	movlw .100
	movwf ARG1L,0
	clrf ARG1H,0
	call divide_24
	movf RES0,0,0

ac_pro_lf
	btfss des_final_0,1,0
	goto ter.ace_lf

;	movlw .75

	MOVWF CTH,0

	bcf des_final_0,1,0
	movlw .6 ;carga velocidad mas baja para acer aceleracion progresiva :cambiando datos para pruebas dato 10
	movwf reg3

mira_lf
	cpfseq CTH
	goto ace.pro_lf
	goto ter.ace_lf

ace.pro_lf
	movwf CCPR2L
	CALL RETARDO0;Demora_100Us dato anterior

	incf reg3,1
	movf reg3,0
	
	goto mira_lf
	
ter.ace_lf
;	movf RES0,0,0
	MOVWF CCPR2L,0
	goto control_lf


	return
	
;===================================================================================================
;      en prueva
;===================================================================================================

error0_l_f
	clrf CCPR2L,0
	bsf des_final_0,1,0
	call RETARDO0

	movf var0,0,0
	ANDLW b'00001111'
	MOVWF CENTENASM,0
	movf var1,0,0
	ANDLW b'00001111'
	MOVWF DECENASM,W
	movf var2,0,0
	ANDLW b'00001111'
	MOVWF UNIDADESM,W
	CALL BCD_A_BIN
	movff BINLM,binpospaL
	movff BINHM,binpospaH
	movf EmcoderH,0,0
	cpfseq binpospaH
	goto bin_emc_no_igu
	movf Emcoder,0,0
	cpfseq binpospaL
	goto no_er_0_lf

	return

;===================================================================================================
;                                salida forsosa de lf
;===================================================================================================

sale_emer_lf
	clrf CCPR2L,0
	bsf des_final_0,1,0
	return

;===================================================================================================
;===================================================================================================

	END