﻿;	PROGRAMA: OLFDCCP.ASM
;	DESCRIPCIÓN: SISTEMA PROBADOR DE DCC.
;	REALIZACIÓN: VÍCTOR ALBERTO SALINAS REYES.
;	EMPRESA: OLFRAM ESPECIALIDADES S.A. DE C.V.
;	VERSIÓN: 1.00
;	DIAGRAMA: DCCP0.
;
.NOLIST
.INCLUDE "..\AVRASM\APPNOTES\4414DEF.INC"
.INCLUDE "..\AVRASM\USERINC\ASCII.INC"
.LIST

.EQU	TOPSTK	= RAMEND;DEFINE TOPE DE LA PILA.
.EQU	BUBR	= 12	;BAUD=19200@4MHz.
.EQU	SGRC	= $3A	;PROMPT ":".
.EQU	PNTYCM	= $3B	;";".

.DEF	RSIS	= R1	;ALM. DE SREG EN RSI.
.DEF	UDTL	= R2	;ALM. DE TRANSMISIÓN DE UART.
.DEF	UDTH	= R3
.DEF	GPTA	= R4	;GENERAL TEMPORAL DE PROGRAMA A.
.DEF	GPTB	= R5	;GENERAL TEMPORAL DE PROGRAMA B.
.DEF	GPTL	= R6	;GENERAL TEMPORAL DE 2 BYTES PROGRAMA.
.DEF	GPTH	= R7
.DEF	GITL	= R8	;GENERAL TEMPORAL DE 2 BYTES INTERRUPCIÓN.
.DEF	GITH	= R9
.DEF	K0L	= R10	;CONSTANTE DE SUMA.
.DEF	K0H	= R11
.DEF	CSF	= R12	;CONTADOR DE SIMULACIÓN DE FALLA MCE???.
.DEF	CSEG	= R14	;CONTADOR DE CENTÉSIMAS DE SEGUNDO.
.DEF	DCERR	= R15	;ALM. NÚMERO ERROR DE LA DCC.
.DEF	PT	= R16	;TEMPORAL DE PROGRAMA.
.DEF	IT	= R17	;TEMPORAL DE INTERRUPCIÓN.
.DEF	PTA	= R18	;TEMPORAL DE PROGRAMA A.
.DEF	PTB	= R19	;TEMPORAL DE PROGRAMA B.
.DEF	PTC	= R20	;TEMPORAL DE PROGRAMA C.
.DEF	PTD	= R21	;TEMPORAL DE PROGRAMA D.
.DEF	ITL	= R22	;TEMPORAL DE 2 BYTES PARA INTERRUPCIÓN.
.DEF	ITH	= R23
.DEF	PTL	= R24	;TEMPORAL DE 2 BYTES PARA PROGRAMA.
.DEF	PTH	= R25
	;R0 ALMACENAMIENTO DE <-(Z).
	;X APUNTADOR EXCLUSIVO DE LÍNEA DE ENTRADA.
	;Z APUNTADOR VARIABLE DE ACCESO A TABLAS.

.DSEG
UBUF:	.BYTE	$0C	;BUFFER DE ENTRADA UART (NO MÁS DE $7F).
FUBUF:	;NOTA: DENTRO DEL INTERVALO DEL UBUF NO DEBE DE CAMBIAR DE PÁGINA.
ITOV0:	.BYTE	1	;ALM. SOBREFLUJO DE TC0.
SRTA:	.BYTE	1	;TEMPORAL EN SRAM.
SRTB:	.BYTE	1	;TEMPORAL EN SRAM.
SRTL:	.BYTE	1	;TEMPORAL EN SRAM.
SRTH:	.BYTE	1	;TEMPORAL EN SRAM.
NDC:	.BYTE	1	;ALM. NÚMERO DE CILINDROS DEL MOTOR.
CPZ:	.BYTE	1	;ALM. CÓDIGO DE NÚMERO DE CHISPAS.
BBATL:	.BYTE	1	;ALM. INT. BOBINA ACTIVA.
BBATH:	.BYTE	1
DCFLL:	.BYTE	1	;ALM. FALLA DE DCC EN LA SALIDA.
DCFLH:	.BYTE	1
CMDCBA:	.BYTE	2	;ALM. ERROR CIRCUITO DE SALIDA ABIERTO.
CMDCBC:	.BYTE	2	;ALM. ERROR CIRCUITO DE SALIDA EN CORTO.


.CSEG
.ORG 0
	RJMP	RESET
	RJMP	EXT_INT0
	RJMP	EXT_INT1
	RJMP	TIM1_CAPT
	RJMP	TIM1_COMPA
	RJMP	TIM1_COMPB
	RJMP	TIM1_OVF
	RJMP	TIM0_OVF
	RJMP	SPI_STC
	RJMP	UART_RXC
	RJMP	UART_DRE
	RJMP	UART_TXC
	RJMP	ANA_COMP

;***	RUTINAS DE SERVICIO DE INTERRUPCIÓN.
EXT_INT0:
	RETI

EXT_INT1:
	RETI

TIM1_CAPT:
	;UTILIZA: RSIS IT ITL ITH.
	IN	RSIS,SREG	;SALVAR SREG.
	RCALL	SRSIAB		;ACTIVAR BOBINA.
	LDI	IT,0B1010	;OMISIÓN; CÓDIGO DE TRES CHISPAS.
	IN	ITL,TIFR
	TST	ITL		;¿HA HABIDO SOBREFLUJO TOV1?.
	BRMI	IC6		;SI, SALTA.
	IN	ITL,ICR1L	;CALCULAR LAPSO DE 5ms DE TOC A IC
	IN	ITH,ICR1H
	SUBI	ITL,LOW(5000*4)	;¿MENOR A 5ms?
	SBCI	ITH,HIGH(5000*4)
	BRSH	IC6		;SI, SALTA.
	LDI	IT,0B0		;CÓDIGO DE UNA CHISPA.
IC6:	STS	CPZ,IT		;ESTABLECER CÓDIGO DE CHISPA.
	IN	ITL,ICR1L	;CALCULA OC1B PARA 0.8ms
	IN	ITH,ICR1H
	ADD	ITL,K0L			;K0 = 0.8ms
	ADC	ITH,K0H
	OUT	OCR1BH,ITH
	OUT	OCR1BL,ITL
	LDI	IT,EXP2(OCF1B)	;BORRA OCF1B
	OUT	TIFR,IT
	IN	IT,TIMSK	;ACTIVA OCR1B
	ORI	IT,EXP2(OCIE1B)
	OUT	TIMSK,IT
	OUT	SREG,RSIS	;RECUPERAR SREG.
	RETI

TIM1_COMPA:
	RETI

TIM1_COMPB:
	;UTILIZA: RSIS IT ITL ITH.
	IN	RSIS,SREG	;SALVA SREG.
	LDS	IT,CPZ		;CARGAR CÓDIGO DE CHISPAS.
	TST	IT		;¿FIN DE CÓDIGO?.
	BREQ	OC1B3		;SI, SALTA.
	LSR	IT		;OBTENER SIGUIENTE ESTADO.
	STS	CPZ,IT		;ACTUALIZAR CÓDIGO.
	BRCC	OC1B1		;¿CÓDIGO DE DESACTIVAR?. SI, SALTA.
	RCALL	SRSIFB		;ACTIVAR BOBINA.
	RJMP	OC1B2
OC1B1:	RCALL	SRSIFD		;ACTUALIZAR EDO. DE FALLAS.
	RCALL	SRSIDB		;DESACTIVAR BOBINA.
OC1B2:	IN	ITL,OCR1BL	;CALCULA OC1B PARA 0.8ms.
	IN	ITH,OCR1BH
	ADD	ITL,K0L			;K0 = 0.8ms
	ADC	ITH,K0H
	OUT	OCR1BH,ITH
	OUT	OCR1BL,ITL
	RJMP	OC1B4
OC1B3:	RCALL	SRSIFD		;ACTUALIZAR EDO. DE FALLAS.
	RCALL	SRSIDB		;DESACTIVAR BOBINA.
	IN	IT,TIMSK	;DESACTIVA OCR1B
	ANDI	IT,~EXP2(OCIE1B)
	OUT	TIMSK,IT
	CLR	IT		;BORRAR TIM1
	OUT	TCNT1H,IT
	OUT	TCNT1L,IT
	LDI	IT,EXP2(TOV1)	;BORRAR SOBREFLUJO DE TIM1
	OUT	TIFR,IT
	RCALL	SRSISB		;CALCULAR Y ACTUALIZAR BBAT.
OC1B4:	OUT	SREG,RSIS	;RECUPERAR SREG.
	RETI

TIM1_OVF:
	RETI

TIM0_OVF:		;RSI TIMER0. (156 * 64us = 9.984ms).
	;UTILIZA: RSIS IT.
	IN	RSIS,SREG	;SALVAR SREG.
	LDS	IT,ITOV0
	DEC	IT		;ACTUALIZAR CUENTA.
	BRNE	OVF01		;¿HA FINALIZADO?.
	INC	CSEG		;SI, INCREMENTAR CENTÉSIMA SEGUNDO.
	LDI	IT,156		;CARGAR UNA CENTÉSIMA SEGUNDO.
OVF01:	STS	ITOV0,IT
	OUT	SREG,RSIS	;RECUPERAR SREG.
	RETI

SPI_STC:
	RETI

UART_RXC:		;RSI DE UART RCX.
	;UTILIZA: X RSIS IT.
	IN	RSIS,SREG	;SALVAR SREG.
	IN	IT,UDR		;CARGAR DATO.
	ST	X+,IT		;ALMACENAR Y ACTUALIZAR APUNTADOR.
	CPI	XL,LOW(FUBUF)	;BUFFER LLENO?
	BRNE	RCX1		;NO, SALTA.
	LDI	XL,LOW(FUBUF)-1	;SI, LIMITAR.
RCX1:	OUT	SREG,RSIS	;RECUPERAR SREG.
	RETI

UART_DRE:		;RSI DE UART UDRE.
	;UTILIZA: R0 RSIS ITL ITH UDTL UDTH.
	IN	RSIS,SREG	;SALVAR SREG.
	MOV	ITL,ZL		;SALVAR Z DE PROGRAMA
	MOV	ITH,ZH
	MOV	ZL,UDTL		;RECUPERAR Z DE INTERRUPCIÓN
	MOV	ZH,UDTH
	LPM			;CARGAR SIGUIENTE CARACTER.
	OUT	UDR,R0		;ENVIAR A BUFFER DE UART.
	ADIW	ZL,1		;APUNTAR A SIGUIENTE CARACTER.
	MOV	IT,R0
	CPI	IT,EOT		;¿FIN TRANSMISIÓN?.
	BRNE	UDRE1		;NO, SALTA.
	CBI	UCR,UDRIE	;SI, DESACTIVAR INTERRUPCIÓN.
UDRE1:	MOV	UDTL,ZL		;SALVAR Z DE INTERUPCIÓN
	MOV	UDTH,ZH
	MOV	ZL,ITL		;RECUPERAR Z DE PROGRAMA.
	MOV	ZH,ITH
	OUT	SREG,RSIS	;RECUPERAR SREG.
	RETI

UART_TXC:
	RETI

ANA_COMP:
	RETI

;***	SUBRUTINAS DE RUTINAS DE SERVICIO DE INTERRUPCIÓN.
SRSIFB:			;SIMULA FALLA DE IGNICIÓN,
	;UTILIZA: IT ITL ITH.
	;ENTRADA: NINGUNA.
	;SALIDA: NINGUNA.
	LDS	ITL,BBATL	;OMISIÓN, CÓDIGO DE ACTIVACIÓN.
	LDS	ITH,BBATH
	DEC	CSF		;¿YA SIMULAR FALLA DE IGNICIÓN?.
	BRNE	SRSIAB1		;NO, SALIDA NORMAL.
	SER	ITL		;CARGA FALLA.
	SER	ITH
	LDI	IT,47		;REINICIAR CONTADOR (47 PRIMO).
	MOV	CSF,IT
	RJMP	SRSIAB1		;CONTINÚA CON SRSIAB1:

SRSIAB:			;ACTIVAR BOBINA (PUERT0).
	;UTILIZA: ITL ITH IT.
	;ENTRADA: NINGUNA.
	;SALIDA; ITH:TIL <- BOBINA ACTIVADA.
	LDS	ITL,BBATL	;OMISIÓN, CÓDIGO DE ACTIVACIÓN.
	LDS	ITH,BBATH
SRSIAB1:OUT	PORTA,ITL	;DIRECTO.
	IN	IT,PORTB
	BST	ITH,0		;CILINDRO NUEVE
	BLD	IT,6
	BST	ITH,1		;CILINDRO DIEZ
	BLD	IT,7
	OUT	PORTB,IT
	RET

SRSIDB:			;DESACTIVAR BOBINAS (SOLO PUERTO).
	;UTILIZA: IT.
	;ENTRADA: NINGUNA.
	;SALIDA: NINGUNA.
	CLR	IT		;DESACTIVA TODAS LAS BOBINAS.
	OUT	PORTA,IT	;DIRECTO.
	CBI	PORTB,6		;CILINDRO NUEVE Y DIEZ
	CBI	PORTB,7
	RET

SRSIEB:			;LEER ESTADO DE BOBINAS.
	;UTILIZA: ITL ITH.
	;ENTRADA: NINGUNA.
	;SALIDA: ITH:ITL <- CÓDIGO DE ESTADO DE BOBINAS.
	IN	ITL,PINC	;DIRECTO.
	CLR	ITH
	SBIC	PIND,6		;CILINDRO NUEVE
	SBR	ITH,0B00000001
	SBIC	PIND,7		;CILINDRO DIEZ
	SBR	ITH,0B00000010
	RET

SRSISB:			;CALCULAR Y ACTUALIZAR SIGUIENTE CILINDRO (BBAT).
	;UTILIZA: ITL ITH IT.
	;ENTRADA: NINGUNA.
	;SALIDA: NINGUNA.
	LDS	ITL,BBATL	;CARGA ESTADO DE CILINDROS.
	LDS	ITH,BBATH
	LSL	ITL
	ROL	ITH
	LDS	IT,NDC		;CARGA NÚMERO DE CILINDROS.
	CPI	IT,$36		;¿"6"?.
	BRNE	SRSISB1		;NO, SALTA.
	BST	ITL,6		;¿FIN DE CICLO DE 6?.
	BRTC	SRSISB4		;NO, SALTA.
	RJMP	SRSISB5		;SI, REINICIAR.
SRSISB1:CPI	IT,$38		;¿"8"?.
	BRNE	SRSISB2		;NO, SALTA.
	BST	ITH,0		;¿FIN DE CICLO DE 8?.
	BRTC	SRSISB4		;NO, SALTA.
	RJMP	SRSISB5		;SI, REINICIAR.
SRSISB2:CPI	IT,$30		;¿"0"?.
	BRNE	SRSISB3		;NO, SALTA.
	BST	ITH,2		;¿FIN DE CICLO DE 10?.
	BRTC	SRSISB4		;NO, SALTA.
	RJMP	SRSISB5		;SI, REINICIAR.
SRSISB5:LDI	ITL,1		;REINICIAR CICLO
	LDI	ITH,0
SRSISB4:STS	BBATL,ITL	;ACTUALIZAR SIGUIENTE CILINDRO
	STS	BBATH,ITH
SRSISB3:RET

SRSIFD:			;ALMACENA FALLAS DE ENCENDIDO DE LA DCC.
	;UTILIZA: ITL ITH GITL GITH.
	;ENTRADA: NINGUNA.
	;SALIDA: NINGUNA.
	RCALL	SRSIEB		;LEER ESTADO DE DCC.
	MOV	GITL,ITL	;SALVAR
	MOV	GITH,ITH
	LDS	ITL,BBATL	;CARGA ESTADO ASIGNADO
	LDS	ITH,BBATH
	CP	GITL,ITL	;¿FALLA EN LA DCC?
	CPC	GITH,ITH
	BREQ	SRSIFD1		;NO, SALTA.
	LDS	GITL,DCFLL	;GUARDAR FALLA.
	LDS	GITH,DCFLH
	OR	GITL,ITL
	OR	GITH,ITH
	STS	DCFLL,GITL
	STS	DCFLH,GITH
SRSIFD1:RET

;***	RESET.
RESET:			;INICIALIZACIÓN BÁSICA.
	LDI	PT,HIGH(TOPSTK)	;INICIALIZAR APUNTADOR DE PILA
	OUT	SPH,PT
	LDI	PT,LOW(TOPSTK)
	OUT	SPL,PT
	LDI	PT,0B11111111	;CONFIG. PUERTO A.
	OUT	DDRA,PT
	LDI	PT,0B00000000
	OUT	PORTA,PT
	LDI	PT,0B11110100	;CONFIG. PUERTO B.
	OUT	DDRB,PT
	LDI	PT,0B00000000
	OUT	PORTB,PT
	LDI	PT,0B00000000	;CONFIG. PUERTO C.
	OUT	DDRC,PT
	LDI	PT,0B00000000
	OUT	PORTC,PT
	LDI	PT,0B00110000	;CONFIG. PUERTO D.
	OUT	DDRD,PT
	LDI	PT,0B00000000
	OUT	PORTD,PT
	LDI	XH,HIGH(UBUF)	;INICIAR APUNTADOR DE BUFFER DE ENTRADA
	LDI	XL,LOW(UBUF)
	LDI	PT,LOW(800*4)	;0.8ms ANCHO DEL PULSO.
	MOV	K0L,PT
	LDI	PT,HIGH(800*4)
	MOV	K0H,PT
	CLR	PT		;INICIA NÚMERO DE CILINDROS (NO VÁLIDO)
	STS	NDC,PT
	STS	BBATH,PT	;INICIA BOBINA 1 PARA INTERRUPCIÓN.
	INC	PT
	STS	BBATL,PT
	LDI	PT,BUBR		;INICIALIZAR UART
	OUT	UBRR,PT
	LDI	PT,0B10011000	;CONFIGURA UART
	OUT	UCR,PT
	LDI	PT,0B10000001	;CONFIGURA TCNT1 E IC
	OUT	TCCR1B,PT
	LDI	PT,0B00000001	;INICIALIZAR TC0 PARA CENTISEGUNDOS
	OUT	TCCR0,PT
	LDI	PT,0B00001010	;CONFIGURA INTERRUCIONES DE TC0 Y TC1
	OUT	TIMSK,PT
	SEI			;HABILITAR INTERRUPCIONES

;***	PROGRAMA PRINCIPAL.
MAIN:			;INICIA PROGRAMA PRINCIPAL.
	LDI	PTH,HIGH(2*MENS0);ENVIAR MENSAJE DE PRESENTACIÓN
	LDI	PTL,LOW(2*MENS0)
	RCALL	MENS
	LDI	PTH,HIGH(2*MENS1);ENVIAR MENSAJE DE OPERACIÓN
	LDI	PTL,LOW(2*MENS1)
	RCALL	MENS
	LDI	PTH,HIGH(2*MENS2);ENVIAR MENSAJE DE ATENTO
	LDI	PTL,LOW(2*MENS2)
	RCALL	MENS
MAIN1:	RCALL	EVSGR		;ENVIAR PROMPT
MAIN0:	RCALL	UENT		;ENTRADA DE UN CARACTER
	CLR	PTH		;REINICIA DESPLAZAMIENTO DE TABLA.
	CLR	PTL
	LDI	ZH,HIGH(2*CMDCRT);APUNTAR A TABLA DE CARACTERES
	LDI	ZL,LOW(2*CMDCRT)
MAIN4:	LPM			;EXTRAER CARACTER DE LA TABLA.
	TST	R0		;¿FIN DE TABLA DE CARACTERES?.
	BREQ	MAIN2		;SI, FIN DE BUSQUEDA.
	CP	PT,R0		;NO, ¿CARACTER ENCONTRADO?.
	BREQ	MAIN3		;SI, SALTA A EJECUTAR.
	ADIW	ZL,1		;APUNTAR A SIGUIENTE CARACTER.
	ADIW	PTL,1		;DESPLAZAR A SIGUIENTE SALTO.
	RJMP	MAIN4
MAIN3:	LDI	ZH,HIGH(CMDSLT)	;APUNTAR A TABLA DE SALTO DE COMANDOS
	LDI	ZL,LOW(CMDSLT)
	ADD	ZL,PTL		;APUNTAR A DIRECCIÓN DE COMANDO
	ADC	ZH,PTH
	RCALL	DCRST		;RESET Y ALIMENTAR DCC.
	ICALL			;LLAMAR A COMANDO.
	CBI	PORTB,PB4	;QUITAR ALIMENTACIÓN A DCC.
	RJMP	MAIN1		;FIN DE EJECUCIÓN DE COMANDO.
MAIN2:	RJMP	MAIN0		;FIN DE BUSQUEDA DE COMANDO.

			;TABLAS DE CARACTERES Y SALTOS DE COMANDOS.
CMDCRT:	.DB "?CANSD680",CR,"XRP",NUL	;¡¡¡CUIDADO EL ENS. TRABAJA MAL!!!.
CMDSLT:	RJMP	CMDAY
	RJMP	CMDC
	RJMP	CMDA
	RJMP	CMDN
	RJMP	CMDS
	RJMP	CMDD
	RJMP	CMD6
	RJMP	CMD8
	RJMP	CMD0
	RJMP	CMDCR
	RJMP	CMDX
	RJMP	CMDR
	RJMP	CMDP

;***	RUTINAS DE COMANDOS.
CMDAY:			;COMANDO: AYUDA.
	LDI	PTH,HIGH(2*MSJAY);ENVIAR MENSAJE DE AYUDA
	LDI	PTL,LOW(2*MSJAY)
	RJMP	MENS

CMDC:			;COMANDO: CONDUCCION ESTÁTICA.
	LDI	PTH,HIGH(2*MSJC1);ENVIAR MENSAJE DE COMANDO.
	LDI	PTL,LOW(2*MSJC1)
	RCALL	MENS
	RCALL	CILEHB
	BRHC	CMDC8
	RET
CMDC8:	SBI	PORTB,PB5	;ACTIVAR MODO SOND EN DCC
	RCALL	DCRST		;RESET DE DCC.
	CBI	PORTB,PB5	;RESTAURAR TERMINAL (SOND ACTIVADO).
	LDI	PTH,HIGH(2*MSJC2);ENVIAR MENSAJE # DE CILINDRO.
	LDI	PTL,LOW(2*MSJC2)
	RCALL	MENS
	CLR	DCERR		;INICIAR; NINGÚN ERROR.
	LDI	PTL,1		;INICIAR PARA EL CONTROL DE PUERTO
	CLR	PTH
	STS	CMDCBA,PTH	;LIMPIA REGISTROS DE ERRORES.
	STS	CMDCBA+1,PTH
	STS	CMDCBC,PTH
	STS	CMDCBC+1,PTH
	LDI	PTB,$31		;CILINDRO NÚMERO "1".
	RCALL	CILNUM
	MOV	PTA,PT		;NÚMERO DE CILINDROS.
	MOV	GPTB,PTA	;COPIA DE RESGUARDO.
CMDC1:	MOV	PT,PTB		;TRANSMITIR NÚMERO DE CILINDRO
	RCALL	USALC
	LDI	PT,$20
	RCALL	USALC
	MOV	GPTA,GPTB	;REALIZAR VARIOS PARPADEOS.
CMDC2:	RCALL	DCBJE		;ACTIVAR BOBINA.
	LDI	PT,10		;ESPERAR 0.1s.
	RCALL	RTNTPC
	RCALL	DCBJL		;LEER ESTADO DE LA BOBINA.
	CP	GPTL,PTL	;¿ERROR EN LA DCC?
	CPC	GPTH,PTH
	BREQ	CMDC3		;NO, CONTINUAR.
			;SALIDA EN CIRCUITO ABIERTO = !BJL·BJE.
	COM	GPTL		;!BJL
	COM	GPTH
	STS	SRTL,GPTL	;GUARDAR
	STS	SRTH,GPTH
	AND	GPTL,PTL	;!BJL·BJE
	AND	GPTH,PTH
	LDS	PTC,CMDCBA	;AGREGA A OTRAS EN REGISTRO.
	LDS	PTD,CMDCBA+1
	OR	PTC,GPTL
	OR	PTD,GPTH
	STS	CMDCBA,PTC	;ALM. PARA REFERENCIA FUTURA.
	STS	CMDCBA+1,PTD
			;SALIDA EN CORTOCIRCUITO = !(!BJL+BJE).
	LDS	GPTL,SRTL	;RECUPERA !BJL
	LDS	GPTH,SRTH
	OR	GPTL,PTL	;!BJL+BJE
	OR	GPTH,PTH
	COM	GPTL		;!(!BJL+BJE)
	COM	GPTH
	LDS	PTC,CMDCBC	;AGREGA A OTRAS EN REGISTRO.
	LDS	PTD,CMDCBC+1
	OR	PTC,GPTL
	OR	PTD,GPTH
	STS	CMDCBC,PTC	;ALM. PARA REFERENCIA FUTURA.
	STS	CMDCBC+1,PTD
			;.
	LDI	PT,2		;'!FALLA EN SALIDA.'
	MOV	DCERR,PT
CMDC3:	RCALL	DCBJA		;DESACTIVAR BOBINA.
	LDI	PT,10		;ESPERAR 0.1s.
	RCALL	RTNTPC
	DEC	GPTA		;¿ÚLTIMO PARPADEO?.
	BRNE	CMDC2		;NO, REPETIR.
	LSL	PTL		;SIGUIENTE CILINDRO (PUERTO).
	ROL	PTH
	INC	PTB		;SIGUIENTE CILINDRO (ASCII).
	DEC	PTA		;SIGUIENTE CILINDRO (CONTADOR).
	BRNE	CMDC1		;¿ÚLTIMO CILINDRO?. SI, SALTA.
	RCALL	USALCRLF
	RCALL	EVERR		;ENVIAR MENSAJE DE ERROR.
	TST	DCERR		;¿NO HAY ERROR?.
	BREQ	CMDC4		;SI, FINALIZAR.
	LDI	PTH,HIGH(2*MSJC3)
	LDI	PTL,LOW(2*MSJC3)
	RCALL	MENS
	LDS	PTL,CMDCBC	;CARGA SALIDA EN CORTO.
	LDS	PTH,CMDCBC+1
	RCALL	CMDC5
	RCALL	USALCRLF
	LDI	PTH,HIGH(2*MSJC4)
	LDI	PTL,LOW(2*MSJC4)
	RCALL	MENS
	LDS	PTL,CMDCBA	;CARGA SALIDA EN ABIERTO.
	LDS	PTH,CMDCBA+1
	RCALL	CMDC5
	RCALL	USALCRLF
	RCALL	MENS
CMDC4:	RET
			;SUBRUTINA DESPLIEGA INFORMACIÓN.
CMDC5:	LDI	PTC,$31		;CARGA "1".
	LDI	PTD,10		;NÚMERO DE CILINDROS
CMDC7:	LSR	PTH		;EXTRAER INFORMACIÓN.
	ROR	PTL
	BRCC	CMDC6		;¿FALLA EN SALIDA?.
	MOV	PT,PTC		;SI, MOSTRAR.
	RCALL	USALC
	LDI	PT,$20
	RCALL	USALC
CMDC6:	INC	PTC		;SIGUIENTE NÚMERO.
	DEC	PTD		;¿FIN?
	BRNE	CMDC7		;NO, CONTINUAR.
	RET

CMDA:			;COMANDO: ARRANQUE VELOCIDAD MARCHA.
	LDI	PTH,HIGH(2*MSJA1);ENVIAR MENSAJE DE COMANDO.
	LDI	PTL,LOW(2*MSJA1)
	RCALL	MENS
	RCALL	CILEHB
	BRHS	CMDA1
	SBI	PORTD,PD5	;ACTIVAR MOTOR EN MARCHA
	CBI	PORTD,PD4
	RCALL	DCCPD		;REALIZAR PRUEBA DINÁMICA.
	SBI	PORTD,PD4	;PARAR MOTOR, VELOCIDAD 0
	SBI	PORTD,PD5
CMDA1:	RET

CMDN:			;COMANDO: VELOCIDAD RALENTI.
	LDI	PTH,HIGH(2*MSJN1);ENVIAR MENSAJE DE COMANDO.
	LDI	PTL,LOW(2*MSJN1)
	RCALL	MENS
	RCALL	CILEHB
	BRHS	CMDN1
	SBI	PORTD,PD4	;ACTIVAR MOTOR EN RALENTI
	CBI	PORTD,PD5
	RCALL	DCCPD		;REALIZAR PRUEBA DINÁMICA.
	SBI	PORTD,PD4	;PARAR MOTOR, VELOCIDAD 0
	SBI	PORTD,PD5
CMDN1:	RET

CMDS:			;COMANDO: VELOCIDAD CRUZERO.
	LDI	PTH,HIGH(2*MSJS1);ENVIAR MENSAJE DE COMANDO.
	LDI	PTL,LOW(2*MSJS1)
	RCALL	MENS
	RCALL	CILEHB
	BRHS	CMDS1
	CBI	PORTD,PD5	;ACTIVAR MOTOR EN CRUZERO
	CBI	PORTD,PD4
	RCALL	DCCPD		;REALIZAR PRUEBA DINÁMICA.
	SBI	PORTD,PD4	;PARAR MOTOR, VELOCIDAD 0
	SBI	PORTD,PD5
CMDS1:	RET

CMDD:
	RJMP	CMDCR		;***** PROVICIONAL.

CMD6:			;COMANDO: DCC PARA MOTOR DE 6 CILINDROS.
	LDI	PTH,HIGH(2*MSJ61);ENVIAR MENSAJE DE COMANDO.
	LDI	PTL,LOW(2*MSJ61)
	RCALL	MENS
	LDI	PT,$36		;"6".
	STS	NDC,PT
	LDI	PTL,1		;REINICIAR CICLO
	LDI	PTH,0
	STS	BBATL,PTL
	STS	BBATH,PTH
	RCALL	CILEHB
	RET

CMD8:			;COMANDO: DCC PARA MOTOR DE 8 CILINDROS.
	LDI	PTH,HIGH(2*MSJ81);ENVIAR MENSAJE DE COMANDO.
	LDI	PTL,LOW(2*MSJ81)
	RCALL	MENS
	LDI	PT,$38		;"8".
	STS	NDC,PT
	LDI	PTL,1		;REINICIAR CICLO
	LDI	PTH,0
	STS	BBATL,PTL
	STS	BBATH,PTH
	RCALL	CILEHB
	RET

CMD0:			;COMANDO: DCC PARA MOTOR DE 10 CILINDROS.
	LDI	PTH,HIGH(2*MSJ01);ENVIAR MENSAJE DE COMANDO.
	LDI	PTL,LOW(2*MSJ01)
	RCALL	MENS
	LDI	PT,$30		;"0".
	STS	NDC,PT
	LDI	PTL,1		;REINICIAR CICLO
	LDI	PTH,0
	STS	BBATL,PTL
	STS	BBATH,PTH
	RCALL	CILEHB
	RET

CMDCR:
CMDX:
CMDR:
CMDP:
	LDI	PTH,HIGH(2*MSJ)	;ENVIAR MENSAJE PROVICIONAL.
	LDI	PTL,LOW(2*MSJ)
	RCALL	MENS
	RET

;***	RUTINAS GENERALES PARA COMANDOS.
CILEHB:			;EXHIBE NÚMERO DE CILINDROS.
	;UTILIZA: PT.
	;ENTRADA: NINGUNA.
	;SALIDA; H <- ERROR.
	LDS	PT,NDC		;CARGA NÚMERO DE CILINDROS.
	CPI	PT,$36		;¿"6"?.
	BREQ	CILEHB1		;SI, SALTA.
	CPI	PT,$38		;¿"8"?.
	BREQ	CILEHB1		;SI, SALTA.
	CPI	PT,$30		;¿"0"?.
	BREQ	CILEHB1		;SI, SALTA.
	LDI	PT,3		;"!NUM DE CIL. NO ESTABL."
	MOV	DCERR,PT
	RCALL	EVERR
	SEH			;ERROR.
	RET			;TERMINAR.
CILEHB1:LDI	PTH,HIGH(2*MSJGC1);"NUMERO DE CILINDROS"
	LDI	PTL,LOW(2*MSJGC1)
	RCALL	MENS
	CPI	PT,$30		;¿"0"?
	BRNE	CILEHB2		;NO, SALTA IMPRIME DIRECTAMENTE.
	INC	PT
	RCALL	USALC		;SI, IMPRIME "1".
	DEC	PT
CILEHB2:RCALL	USALC		;IMPRIME NÚMERO.
	RCALL	USALCRLF
	CLH			;NO ERROR.
	RET

CILNUM:			;NÚMERO DE CILINDROS.
	;UTILIZA: PT.
	;ENTRADA: NINGUNA.
	;SALIDA: PT <- NÚMERO DE CILINDROS ($) H <- ERROR.
	LDS	PT,NDC		;CARGA NÚMERO DE CILINDROS ASCII.
	CPI	PT,$36		;¿SEIS CILINDROS?.
	BREQ	CILNUM1		;SI, SALTA.
	CPI	PT,$38		;¿OCHO CILINDROS?.
	BREQ	CILNUM1		;SI, SALTA.
	CPI	PT,$30		;¿DIEZ CILINDROS?.
	BREQ	CILNUM2		;SI, SALTA.
	LDI	PT,3		;"!NUM DE CIL. NO ESTABL."
	MOV	DCERR,PT
	RCALL	EVERR
	SEH			;ERROR.
	RET			;TERMINAR.
CILNUM1:ANDI	PT,$0F		;ENMASCARAR.
	CLH			;NO ERROR.
	RET			;TERMINAR.
CILNUM2:LDI	PT,$0A		;DIEZ CILINDROS.
	CLH			;NO ERROR.
	RET			;TERMINAR.

DCCPD:			;PRUEBA DINÁMICA DE DCC.
	;UTILIZA: PT PTL PTH PTA PTB PTC PTD GPTA.
	;ENTRADA: NINGUNA.
	;SALIDA: H <- ERROR.
	LDI	PTA,3		;ESPERAR 3 SEGUNDOS
	RCALL	RTNTPN
	CLR	PT		;BORRAR ESTADO DE FALLAS
	STS	DCFLL,PT
	STS	DCFLH,PT
	LDI	PT,8		;8 EXHIBICIONES.
	MOV	GPTA,PT
	LDI	PTH,HIGH(2*MSJGC2);'DCC INICIANDO PRUEBA.'.
	LDI	PTL,LOW(2*MSJGC2)
	RCALL	MENS
DCCPD1:	LDI	PTA,250		;3		;ESPERAR 3 SEGUNDOS **************************************
	RCALL	RTNTPN
	RCALL	DCCFE		;EXHIBIR RESULTADO.
	DEC	GPTA		;¿TODOS LOS RESULTADOS?.
	BRNE	DCCPD1		;NO, REGRESAR.
	RJMP	DCCFF		;EXHIBIR ERROR.

DCCFE:			;EXHIBE ESTADO DE FALLAS DE DCC.
	;UTILIZA: PT PTL PTH PTA PTB PTC PTD.
	;ENTRADA: NINGUNA.
	;SALIDA: NINGUNA.
	LDI	PTH,HIGH(2*MSJGC3);'DCC SALIDA'.
	LDI	PTL,LOW(2*MSJGC3)
	RCALL	MENS
	LDI	PTA,$30		;CARGAR '0' '1' ' '.
	LDI	PTB,$31
	LDI	PTC,$20
	RCALL	CILNUM		;PTD CONTADOR DE NÚMERO DE CILINDROS
	MOV	PTD,PT
	LDS	PTL,DCFLL	;CARGAR ESTADO DE FALLAS
	LDS	PTH,DCFLH
DCCFE2:	LSR	PTH		;LEER FALLA.
	ROR	PTL
	MOV	PT,PTA		;¿'0' NO FALLA?.
	BRCC	DCCFE1		;SI, SALTA.
	MOV	PT,PTB		;'1' FALLA.
DCCFE1:	RCALL	USALC		;ENVIAR ASCII.
	MOV	PT,PTC		;' '
	RCALL	USALC
	DEC	PTD		;¿TODOS LOS CILINDROS?.
	BRNE	DCCFE2		;AÚN NO, SALTA.
	RCALL	USALCRLF
	RET

DCCFF:			;EXHIBE RESULTADO DE PRUEBA DCFL.
	;UTILIZA PT PTL PTH.
	;ENTRADA: NINGUNA.
	;SALIDA: H <- ERROR.
	CLR	PT
	LDS	PTL,DCFLL	;CARGAR ESTADO DE FALLAS.
	LDS	PTH,DCFLH
	CP	PTL,PT		;¿NO FALLAS?.
	CPC	PTH,PT
	BREQ	DCCFE3		;NO FALLA, SALTA.
	LDI	PT,4		;"FALLA DE DCC EN OPERACIÓN."
	MOV	DCERR,PT
	RCALL	EVERR
	SEH
	RET
DCCFE3:	CLR	DCERR		;"NO ERROR."
	RCALL	EVERR
	CLH			;NO FALLA.
	RET

;***	RUTINAS DE ENTRADA SALIDA.
USALCRLF:		;ENVÍA CR + LF.
	;UTILIZA: PTH PTL {MENS}.
	;ENTRADA: NINGUNA.
	;SALIDA: NINGUNA.
	LDI	PTH,HIGH(2*MENSCL)
	LDI	PTL,LOW(2*MENSCL)

MENS:			;ENVÍA MENSAJES DEL SITEMA.
	;UTILIZA: PTH PTL.
	;ENTRADA: PTH PTL <- (DIRECCIÓN DE CADENA)*2.
	;SALIDA: NINGUNA.
	SBIC	UCR,UDRIE	;¿UART OCUPADO?.
	RJMP	MENS		;SI, ESPERAR.
	MOV	UDTH,PTH
	MOV	UDTL,PTL
	SBI	UCR,UDRIE	;ACTIVAR ENVÍO.
	RET

EVSGR:			;ENVÍA PROMPT.
	;UTILIZA; PT {USALC}.
	;ENTRADA: NINGUNA.
	;SALIDA: NINGUNA.
	LDI	PT,SGRC
	RJMP	USALC

EVERR:			;ENVÍA ERROR.
	;UTILIZA: Z R0 PT PTL PTH DCERR {MENS}.
	;ENTRADA: DCERR.
	;SALIDA: NINGUNA.
	LDI	ZL,LOW(2*MSJERT);APUNTAR A TABLA DE LOCALIZACIÓN
	LDI	ZH,HIGH(2*MSJERT)
	MOV	PT,DCERR	;DESPLAZAR A NÚMERO DE ERROR
	LSL	PT		;NOTA: LÍMITE 128 MENSAJES DE ERROR.
	ADD	ZL,PT
	LDI	PT,0
	ADC	ZH,PT
	LPM			;APUNTA A LA CADENA DE ERROR
	MOV	PTL,R0
	ADIW	ZL,1
	LPM
	MOV	PTH,R0
	RJMP	MENS		;ENVÍA ERROR

UENT:			;LÍNEA DE ENTRADA A TRAVÉS DE UART.
	;UTILIZA: X Z PT PTL {USALC}.
	;ENTRADA: NINGUNA.
	;SALIDA: PT <- CÓDIGO ASCII DE ENTRADA.
	CLR	PT		;LIMPIA BASURA.
	CPI	XL,LOW(UBUF)+1	;¿BUFFER VACIO?.
	BRSH	UENT1		;NO, PROSEGUIR.
	RET			;SI, SALIR.
UENT1:	LDS	PT,UBUF		;CARGAR CARACTER.
	SBIW	XL,1		;ACTUALIZA APUNTADOR.
	CPI	XL,LOW(UBUF)	;¿UN SOLO CARACTER EN EL BUFFER?.
	BREQ	USALC		;SI, PROSEGUIR A MOSTRAR.
	LDI	ZL,LOW(UBUF)	;ACTUALIZAR BUFFER (FIFO)
	LDI	ZH,HIGH(UBUF)		;APUNTAR A LA BASE.
UENT2:	LDD	PTL,Z+1			;COPIAR Y
	ST	Z+,PTL			;ACTUALIZAR APUNTADOR.
	CPSE	ZL,XL			;¿FIN DE COPIA?.
	RJMP	UENT2			;NO, PROSEGUIR.
	;CONTINÚA CON {USALC}.

USALC:			;SALIDA DE UN CARACTER.
	;UTILIZA: PT.
	;ENTRADA: PT <- CÓDIGO ASCII DE SALIDA.
	;SALIDA: PT.
	SBIC	UCR,UDRIE	;ESPERAR BUFFER DE TRANSMISIÓN LIBRE.
	RJMP	USALC
USALC1:	SBIS	USR,UDRE
	RJMP	USALC1
	OUT	UDR,PT		;SALIDA DEL CARACTER.
	RET

;***	TABLAS DE DATOS Y CADENAS.
;*** 	¡¡¡ATENCIÓN!!!: LOS DATOS CON .DB DEBEN SER PARES POR CADA .DB;
;	PARA EVITAR UN ERROR EN EL ENSAMBLADOR VERSIÓN 1.30
MENSCL:	.DB " ",CR,LF,EOT
MENS0:	.DB CR,LF," *** OLFRAM ESPECIALIDADES S.A. DE C.V. *** ",CR,LF
	.DB " *  PROBADOR DE COMPUTADORAS DCC VER. 1.0  * ",CR,LF,EOT
MENS1:	.DB "'OPERACION CABAL.",CR,LF,EOT
MENS2:	.DB "'PRESIONE ? PARA AYUDA.",CR,LF,EOT
MENS4:	.DB "'FIN DE PRUEBA, DCC APROVADA.",CR,LF,EOT
MENS5:	.DB "'FIN DE PRUEBA, DCC DEFECTUOSA.",CR,LF,EOT
MENS6:	.DB "'",CR,LF,EOT
MSJAY:	.DB CR,LF,"'* AYUDA, COMANDOS DE PROBADOR DE DCC. * ",CR,LF,LF
	.DB " ? - AYUDA, EXHIBE ESTA INFORMACION.",CR,LF
	.DB " C - CONDUCCION ESTATICA. ",CR,LF
	.DB " A - VELOCIDAD ARRANQUE (MARCHA). ",CR,LF
	.DB " N - VELOCIDAD RALENTI. ",CR,LF
	.DB " S - VELOCIDAD CRUZERO. ",CR,LF
	.DB " D - DETONACION (FORZANDO MAQUINA). ",CR,LF
	.DB " 6 - SEIS CILINDROS.",CR,LF
	.DB " 8 - OCHO CILINDROS.",CR,LF
	.DB " 0 - DIEZ CILINDROS.",CR,LF
	.DB " INTRO - PRUEBA AUTOMATICA. ",CR,LF
	.DB " X - CONFIGURAR PRUEBA AUTOMATICA.",CR,LF
	.DB " R - REPORTE DE LA PRUEBA ANTERIOR. ",CR,LF
	.DB " P - PROGRAMACION ESPECIAL.",CR,LF,CR,LF,EOT
MSJA1:	.DB CR,LF,"'* VELOCIDAD ARRANQUE: PROBANDO. * ",CR,LF,EOT
MSJN1:	.DB CR,LF,"'* VELOCIDAD RALENTI: PROBANDO. *",CR,LF,EOT
MSJS1:	.DB CR,LF,"'* VELOCIDAD CRUZERO: PROBANDO. *",CR,LF,EOT
MSJC1:	.DB CR,LF,"'* CONDUCCION ESTATICA: PROBANDO. *",CR,LF,EOT
MSJC2:	.DB "'PROBANDO SALIDA NUMERO: ",EOT
MSJC3:	.DB "'SALIDA EN CORTO CIRCUITO: ",EOT
MSJC4:	.DB "'SALIDA EN CIRCUITO ABIERTO: ",EOT
MSJ61:	.DB CR,LF,"'* DCC PARA MOTOR DE 6 CILINDROS. *",CR,LF,EOT
MSJ81:	.DB CR,LF,"'* DCC PARA MOTOR DE 8 CILINDROS. *",CR,LF,EOT
MSJ01:	.DB CR,LF,"'* DCC PARA MOTOR DE 10 CILINDROS. * ",CR,LF,EOT
MSJGC1:	.DB "'DCC NUMERO DE CILINDROS:  ",EOT
MSJGC2:	.DB "'DCC INICIANDO PRUEBA. ",CR,LF,EOT
MSJGC3:	.DB "'DCC SALIDA (0=BIEN 1=FALLA):  ",EOT
MSJ:	.DB CR,LF,"'LO SENTIMOS: POR EL MOMENTO ESTE ",CR,LF
	.DB " COMANDO NO ESTA DISPONIBLE. GRACIAS.",CR,LF,EOT
MSJERT:	.DW 2*MSJER0,2*MSJER1,2*MSJER2,2*MSJER3,2*MSJER4,2*MSJER5,2*MSJER6
MSJER0:	.DB "!ERROR #00: NO HAY ERROR.",CR,LF,EOT
MSJER1:	.DB "!ERROR #01: PROBADOR DE DCC NO OPERANDO ADECUADAMENTE. ",CR,LF,EOT
MSJER2:	.DB "!ERROR #02: SALIDA EN CORTO CIRCUITO O CIRCUITO ABIERTO. ",CR,LF,EOT
MSJER3:	.DB "!ERROR #03: NO SE HA ESTABLECIDO EL NUMERO DE CILINDROS. ",CR,LF,EOT
MSJER4:	.DB "!ERROR #04: FALLA DE DCC EN PRUEBA DINAMICA. ",CR,LF,EOT
MSJER5: .DB "!ERROR #05: .",CR,LF,EOT
MSJER6:	.DB "!ERROR #06: .",CR,LF,EOT

;***	RUTINAS RESPECTIVAS A LA DCC.
DCRST:			;RESET DE DCC.
	;UTILIZA: PT {RTNPC}
	;ENTRADA: NINGUNA.
	;SALIDA: NINGUNA.
	CBI	PORTB,PB4	;DESACTIVAR ALIMENTACIÓN DE DCC.
	LDI	PT,20
	RCALL	RTNTPC		;ESPERAR.
	SBI	PORTB,PB4	;ACTIVAR ALIMENTACIÓN DE DCC.
	LDI	PT,30		;ESPERAR INCIACIÓN DE DCC.
	RJMP	RTNTPC

DCBJA:			;APAGAR BOBINAS (TODAS).
	;UTILIZA: PT.
	;ENTRADA: NINGUNA.
	;SALIDA: NINGUNA.
	CLR	PT
	OUT	PORTA,PT	;DIRECTO.
	CBI	PORTB,6		;CILINDRO NUEVE Y DIEZ
	CBI	PORTB,7
	RET

DCBJE:			;ENERGIZAR BOBINA.
	;UTILIZA: PT PTL PTH.
	;ENTRADA: PTH:PTL <- CÓDIGO DE ESTADO ASIGNADO DE BOBINAS.
	;SALIDA: NINGUNA. 
	OUT	PORTA,PTL	;DIRECTO.
	IN	PT,PORTB
	BST	PTH,0		;CILINDRO NUEVE
	BLD	PT,6
	BST	PTH,1		;CILINDRO DIEZ
	BLD	PT,7
	OUT	PORTB,PT
	RET

DCBJL:			;LEER ESTADO DE BOBINAS.
	;UTILIZA: GPTH GPTL PT.
	;ENTRADA: NINGUNA.
	;SALIDA: GPTH:GPTL <- CÓDIGO DE ESTADO LEIDO DE BOBINAS.
	CLR	GPTH
	IN	GPTL,PINC	;DIRECTO.
	IN	PT,PIND
	BST	PT,6		;CILINDRO NUEVE
	BLD	GPTH,0
	BST	PT,7		;CILINDRO DIEZ
	BLD	GPTH,1
	RET

;***	RUTINAS MISCELÁNEAS.
RTNTPN:			;RUTINA DE ESPERA DE VARIOS SEGUNDOS.
	;UTILIZA: PT PTA.
	;ENTRADA: PTA <- NÚMERO DE SEGUNDOS.
	;SALIDA: NINGUNA.
	RCALL	RTNTP
	DEC	PTA
	BRNE	RTNTPN
	RET

RTNTP:			;RUTINA DE ESPERA 1s.
	;UTILIZA: PT.
	;ENTRADA: NINGUNA.
	;SALIDA: NINGUNA.
	LDI	PT,100
	;CONTINÚA CON {RTNPC}

RTNTPC:			;RUTINA DE ESPERA DE PT*1cs.
	;UTILIZA: PT.
	;ENTRADA: PT <- NÚMERO DE 1cs.
	;SALIDA: NINGUNA.
	CLR	CSEG
RTNTP1:	CPSE	PT,CSEG
	RJMP	RTNTP1
	RET
