
;ORDEN DE LOS DISPLAYS:
;
;
; DIG5  DIG4  DIG3  DIG2   DIG1  DIG0
;  U6    U3    U5    U7     U8    U9
;  PC0   PC1   PC2   PC3    PC4   PC5
;
;ORDEN FILAS TECLAS:
;
;	D7 D6 D5 D4 D3 D2 D1 D0
; 
;PB0: 	DU LO PC GO -  + DA  AD
;PB1:   F  E  D  C  B  A  9  8
;PB2:   7  6  5  4  3  2  1  0
;
;
;LA EMISION-RECEPCION POR EL 8251 SE HACE A 19200 BPS SIN PARIDAD Y CON DOS BITS DE STOP
;
;
;
;
PA_8255		.EQU	000H		;PUERTA A DEL 8255
PB_8255		.EQU	001H		;PUERTA B DEL 8255
PC_8255		.EQU	002H		;PUERTA C DEL 8255
PCON_8255	.EQU	003H		;PUERTA DE CONTROL DEL 8255

RCON_8251	.EQU	009H		;REGISTRO CONTROL 8251
RDAT_8251	.EQU	008H		;REGISTRO DATOS 8251

PCON_LE		.EQU	090H		;PALABRA CONTROL 8255 PARA LEER TECLADO  (PA:IN  PB:OUT PC:OUT) OLD 010H 
PCON_DI		.EQU	082H		;PALABRA CONTROL 8255 PARA ENCENDER LEDS (PA:OUT PB:OUT PC:OUT) OLD 080H

MODO_DA		.EQU	000H		;PALABRA MODO DE DATOS
MODO_AD		.EQU	0FFH		;PALABRA MODO DE DIRECCIONES

TECLA_AD	.EQU	010H
TECLA_DA	.EQU	011H
TECLA_PL	.EQU	012H
TECLA_MI	.EQU	013H
TECLA_GO	.EQU	014H
TECLA_PC	.EQU	015H
TECLA_LO	.EQU	016H
TECLA_DU	.EQU	017H

RES_OK		.EQU	000H		;RESULTADO OK
RES_NOK		.EQU	0FFH		;RESULTADO ERRONEO




		.ORG	8000H		;COMIENZO RAM



REG.A		.BLOCK	1		;PSW LSB (ACUM)
REG.PSW		.BLOCK	1		;PSW MSB (STATUS)
REG.C		.BLOCK	1		;BC LSB
REG.B		.BLOCK	1		;BC MSB
REG.E		.BLOCK	1		;DE LSB
REG.D		.BLOCK	1		;DE MSB
REG.L		.BLOCK	1		;HL LSB
REG.H		.BLOCK	1		;HL MSB
REG.PCL		.BLOCK	1		;PROGRAM COUNTER LSB
REG.PCH		.BLOCK	1		;PROGRAM COUNTER MSB
REG.SPL		.BLOCK	1		;STACK POINTER LSB
REG.SPH		.BLOCK	1		;STACK POINTER MSB


DATO		.BLOCK	1		;DIRECC DE LA MEMORIA MSB
MEML		.BLOCK	1		;DIRECCION DE LA MEMORIA LSB
MEMH		.BLOCK	1		;DIRECCION DE LA MEMORIA MSB

DIG0		.BLOCK	1
DIG1		.BLOCK	1
DIG2		.BLOCK	1
DIG3		.BLOCK	1
DIG4		.BLOCK	1
DIG5		.BLOCK	1

MODO		.BLOCK	1		;PUEDE SER: MODO_AD o MODO_DA
DIG_ACT		.BLOCK	1		;DIGITO ACTIVO EN DISPLAY 0->DIG0...5->DIG5
TIEMPO		.BLOCK	2		;TIEMPO DE PRESENTACION EN CADA DISPLAY

KEY_ACT		.BLOCK	1		;
KEY_TMP		.BLOCK	1		;
KEY_LAST	.BLOCK	1		;ULTIMA TECLA PULSADA
KEY_CFIL	.BLOCK	1		;CONTADOR DE FILTRADO LECTURA TECLADO

RST1		.BLOCK	3		;SALTO RST.1
RST2		.BLOCK	3		;SALTO RST.2
RST3		.BLOCK	3		;SALTO RST.3
RST4		.BLOCK	3		;SALTO RST.4
RST5		.BLOCK	3		;SALTO RST.5
RST6		.BLOCK	3		;SALTO RST.6
RST7		.BLOCK	3		;SALTO RST.7

INT.TRAP	.BLOCK	3		;INT TRAP
INT.5.5		.BLOCK	3		;
INT.6.5		.BLOCK	3		;
INT.7.5		.BLOCK	3		;


;RECEPCION DATOS

DATO_RX		.BLOCK	1		;DATO RECIBIDO DE LA UART
DATO_PR		.BLOCK	1		;DATO PROCESADO
R_TMP		.BLOCK	1
TYPE		.BLOCK	1
PUNL		.BLOCK	1
PUNH		.BLOCK	1
N		.BLOCK	1
LON		.BLOCK	1
N_TRA_OK	.BLOCK	1
N_TRA_ERR	.BLOCK	1
CHK		.BLOCK	1
MITAD		.BLOCK	1

;EMISION DATOS

FROML		.BLOCK	1		;DIRECCION INICIAL LSB PARA ENVIAR DATOS
FROMH		.BLOCK	1		;ID.ID. MSB
TOL		.BLOCK	1		;DIRECCION FINAL LSB PARA ENVIAR DATOS
TOH		.BLOCK	1		;ID.ID. MSB
INDL		.BLOCK	1		;DIRECCION DE DESCARGA EN CURSO LSB
INDH		.BLOCK	1		;DIRECCION DE DESCARGA EN CURSO MSB
DISTL		.BLOCK	1		;DISTANCIA ENTRE IND Y TO LSB
DISTH		.BLOCK	1		;DISTANCIA ENTRE IND Y TO MSB
DISTHH		.BLOCK	1		;DISTANCIA ENTRE IND Y TO PLUS
CBT		.BLOCK	1		
FASET		.BLOCK	1		;ESTADO DE LA TX DE LA TRAMA	



		.ORG	0000H

		JMP	INIC		;RST 0 Y RESET SISTEMA

		.ORG	0008H
		JMP	RST1		;RST 1

		.ORG	0010H
		JMP	RST2		;RST 2

		.ORG	0018H
		JMP	RST3		;RST 3

		.ORG	0020H
		JMP	RST4		;RST 4

		.ORG	0028H
		JMP	RST5		;RST 5

		.ORG	0030H
		JMP	RST6		;RST 6

		.ORG	0038H
		JMP	RST7		;RST 7

;INTERRUPCIONES HARDWARE

		.ORG	0024H
		JMP	INT.TRAP	;INTERRUPCION TRAP

		.ORG	002CH
		JMP	INT.5.5		;RST.5.5

		.ORG	0034H
		JMP	INT.6.5		;RST.6.5

		.ORG	003CH
		JMP	INT.7.5		;RST.7.5
;
;
;	
;
;
;		LA ENTRADA MONITOR ES UTILIZADA PARA ENTRAR EN EL PROGRAMA MONITOR DESDE
;		LA INTERRUPCION RST 7 (FF)
;
;
MONITOR		SHLD	REG.L		;SALVA HL

		PUSH	PSW		;PUSH ACUM + STATUS
		POP	H		;
		SHLD	REG.A		;SALVA ACUM+STATUS

		LXI	H,000H
		DAD	B
		SHLD	REG.C		;SALVA BC

		LXI	H,000H
		DAD	D
		SHLD	REG.E		;SALVA DE

		LXI	H,000H
		DAD	SP
		SHLD	REG.SPL		;SALVA SP

		POP	H		;RECUPERA PC
		SHLD	REG.PCL
		SHLD	MEML		
		JMP	BUCLEF
;
;
;
;
;
;
INIC		LXI	SP,0FFFFH	;STACK APUNTA MAX RAM
		DI	

		MVI	A,0EFH		;8251 MODE INSTRUCTION AS ASYNCRONOUS MODE
		OUT	RCON_8251	; 8 BIT + 2 BITS STOP + SIN PARIDAD + 64X (a 307200 hz ->4800bps)
		;
		LXI	H,0
		SHLD	FROML
		SHLD	TOL		;FROM, TO Y MEM <-0000
		SHLD	MEML

		MVI	A,0FFH
		STA	KEY_ACT		;INICIALIZA LECT. DEL TECLADO

		MVI	A,0
		STA	DIG_ACT		;DIG_ACT <- 0 (es decir, DIG0)
		;
		MVI	A,MODO_AD
		STA	MODO

		LXI	H,RST7		;ESTABLECEMO DIRECCION DE SALTO PARA RST7 PARA SALTAR A MONITOR
		MVI	A,0C3H		;JMP
		MOV	M,A
		INX	H
		MVI	A,MONITOR		;
		MOV	M,A
		INX	H
		MVI	A,MONITOR/256
		MOV	M,A

		JMP	BUCLEF		;REFRESCA DATO Y EL DISPLAY
;
;
BUCLE		CALL	PRES		;VISUALIZA EL DISPLAY
		CALL	LEE		;LEE EL TECLADO
		LDA	KEY_ACT
		CPI	0FFH
		JZ	BUCLE
		;
		CPI	TECLA_DA	;TECLA DA?
		JNZ	BUCLE1
		MVI	A,MODO_DA
		STA	MODO
		JMP	BUCLES
		;
		;
BUCLE1		CPI	TECLA_AD	;TECLA AD?
		JNZ	BUCLE2
		MVI	A,MODO_AD
		STA	MODO
		JMP	BUCLES
		;
		;
BUCLE2		CPI	TECLA_PL	;TECLA +?
		JNZ	BUCLE3
		LHLD	MEML
		INX	H		;(MEMH,MEML) <- (MEMH,MEML) +1
		SHLD	MEML
		;
		JMP	BUCLEF		;REFRESCA DATO Y EL DISPLAY
		;
		;
BUCLE3		CPI	TECLA_MI	;TECLA -?
		JNZ	BUCLE4
		LHLD	MEML
		DCX	H		;(MEMH,MEML) <- (MEMH,MEML) -1
		SHLD	MEML
		;
		JMP	BUCLEF		;REFRESCA DATO Y EL DISPLAY
		;
		;
BUCLE4		CPI	TECLA_PC	;TECLA PC?
		JNZ	BUCLE5
		LHLD	REG.PCL
		SHLD	MEML
		JMP	BUCLEF
;
BUCLE5		CPI	TECLA_GO	;TECLA GO?
		JNZ	BUCLE6
		;
		MVI	A,0FFH
		STA	KEY_ACT

		LHLD	MEML		;(PCH,PCL) <- (MEMH,MEML)
		PCHL			;GO!!!
		;
		;
BUCLE6		CPI	TECLA_LO	;TECLA LOAD?
		JNZ	BUCLE7
		;
		MVI	A,0FFH
		STA	KEY_ACT		;DEJA LIMPIA LA LECTURA DEL TECLADO
		CALL	RECIBIR
		JMP	BUCLEF
		;
		;
BUCLE7		CPI	TECLA_DU	;TECLA DUMP?
		JNZ	BUCLE8
		;
		MVI	A,0FFH
		STA	KEY_ACT		;DEJA LIMPIA LA LECTURA DEL TECLADO
		CALL	EMITIR	
		JMP	BUCLEF
		;
		;
BUCLE8		CPI	000H		;
		JM	BUCLE9
		CPI	010H
		JP	BUCLE9
		;
		MOV	B,A		;ES TECLA 0..F GUARDALA EN B
		LDA	MODO
		CPI	MODO_DA
		JZ	D_DAT
		;
D_ADR		LXI	H,MEML
		LXI	D,MEMH
		CALL	DES_ADR		;DESPLAZA (MEMH,MEML)
		JMP	BUCLEF		;REFRESCA DATO Y EL DISPLAY
		;
D_DAT		LHLD	MEML		;DESPLAZAMOS DATO (MEMH,MEML) <--
		MOV	A,M
		ANI	00FH
		RLC
		RLC
		RLC
		RLC
		ORA	B
		MOV	M,A

		JMP	BUCLEF		;REFRESCA DATO Y EL DISPLAY
		;
		;
BUCLE9		JMP	BUCLES		;NO HAY OPCIONES, SEGUIR
;
;
BUCLEF		CALL	REF_DATO	;REFRESCA DATO
		CALL	REF_DISP	;CARGA DISPLAY
;
BUCLES		MVI	A,0FFH
		STA	KEY_ACT
		JMP	BUCLE
;
;
;
;
;
;DESPLAZA UNA PALABRA APUNTADA
;HL->LSB
;DE->MSB
;B CONTIENE DATO
;
;
DES_ADR		MVI	C,004H		;DESPLAZAMOS DIRECCIONES MEMH,MEML <--

DES_ADR1	STC
		CMC			;CARRY=0
		MOV	A,M
		RAL
		MOV	M,A		;ACTUA CON LSB
		LDAX	D		;AHORA CON MSB
		RAL
		STAX	D
		DCR	C
		JNZ	DES_ADR1
		MOV	A,M
		ORA	B
		MOV	M,A
		RET
;
;
;
;
;
;EL CONTENIDO APUNTADO POR (MEMH,MEML) SE CARGA EN DATO
;
REF_DATO	LHLD	MEML
		MOV	A,M
		STA	DATO
		RET
;
;
;
;
;REFRESCAMOS DIG0...DIG5 CON MEMH,MEML
;
REF_DISP	LXI	H,DIG0		;HL <- DIG0 
		LDA	DATO
		CALL	DEC_BYTE	;DIG1 y DIG0 CARGADO CON DATO
		LDA	MEML
		CALL	DEC_BYTE	;DIG3 y DIG2 CARGADO CON MEML
		LDA	MEMH
		CALL	DEC_BYTE	;DIG5 y DIG4 CARGADO CON MEMH
		RET
;
;
;
;
;OBTIENE TABLA DE DISPLAY PARA EL BYTE CONTENIDO EN ACUM
;ENTRADA:
;A:  BYTE A DECODIFICAR
;HL: APUNTA ADDR. DONDE GUARDAR RESULTADO
;
;
DEC_BYTE	MOV	D,A		;SALVA EN D
		CALL	DEC_DIG		;PRIMERO ACTUA CON PARTE LSB
		MOV	M,A
		INX	H		;HL <- HL+1		
		MOV	A,D
		RRC
		RRC
		RRC
		RRC
		CALL	DEC_DIG		;AHORA CON PARTE MSB
		MOV	M,A
		INX	H		;HL <- HL+1
		RET
;
;
;
;
;DECODIFICAMOS PARA SALIR A DISPLAY
;ENTRADA:
;A: DATO A DECODIFICAR
;SALIDA:
;A: RESULTADO
;
DEC_DIG		PUSH	H
		;	
		ANI	00FH		;A <- A .AND. 00FH
		MOV	C,A
		MVI	B,0		;BC <- DATO
		LXI	H,TABLA
		DAD	B		;HL <- HL+BC
		MOV	A,M		;COGE RESULTADO
		;
		POP	H		;RECUPERA HL
		RET
;
;
;
TABLA		.DB	03FH,006H,05BH,04FH,066H,06DH,07CH,007H	;0..7
		.DB	07FH,06FH,077H,07CH,039H,05EH,079H,071H	;8..F
;
;
;
;
;RUTINA DE EMITIR HACIA EL PC EN FORMATO INTEL
;
;
EMITIR		MVI	A,011H		;COMMAND INSTRUCTION FOR 8251 
		OUT	RCON_8251	;RESET ALL ERRORS, DISABLE RECEIVE, ENABLE TRANSMIT

		LXI	H,MES_FROM
		CALL	LOAD_DISP	;"F="

EMITF		MVI	A,0FFH
		STA	KEY_ACT		;DEJA LIMPIA LA LECTURA DEL TECLADO

		LXI	H,DIG0		;HL <- DIG0 
		LDA	FROML
		CALL	DEC_BYTE	;DIG1 y DIG0 CARGADO CON FROML
		LDA	FROMH
		CALL	DEC_BYTE	;DIG3 y DIG2 CARGADO CON FROMH

EMITF1		CALL	PRES		;PRESENTA MENSAJE
		CALL	LEE
		LDA	KEY_ACT
		CPI	0FFH
		JZ	EMITF1			
		CPI	TECLA_DU
		JZ	EMITT		;SI TECLA DUMP OTRA VEZ PASA A CONSEGUIR EL TO

		CPI	000H		;CUALQUIER OTRA TECLA QUE NO SEA NUMERICA
		JM	FEMI		;IMPLICARA SALIR
		CPI	010H
		JP	FEMI
		;
		MOV	B,A		;ES TECLA 0..F
		LXI	H,FROML
		LXI	D,FROMH
		CALL	DES_ADR
		JMP	EMITF
		;
EMITT		LXI	H,MES_TO
		CALL	LOAD_DISP	;"T="

EMITT0		MVI	A,0FFH
		STA	KEY_ACT		;DEJA LIMPIA LA LECTURA DEL TECLADO

		LXI	H,DIG0		;HL <- DIG0 
		LDA	TOL
		CALL	DEC_BYTE	;DIG1 y DIG0 CARGADO CON TOL
		LDA	TOH
		CALL	DEC_BYTE	;DIG3 y DIG2 CARGADO CON TOH

EMITT1		CALL	PRES		;PRESENTA MENSAJE
		CALL	LEE
		LDA	KEY_ACT
		CPI	0FFH
		JZ	EMITT1			
		CPI	TECLA_DU
		JZ	EMIT3		;SI TECLA DUMP OTRA VEZ PASA A LA EMISION

		CPI	000H		;CUALQUIER OTRA TECLA QUE NO SEA NUMERICA
		JM	FEMI		;IMPLICARA SALIR
		CPI	010H
		JP	FEMI
		;
		MOV	B,A		;ES TECLA 0..F
		LXI	H,TOL
		LXI	D,TOH
		CALL	DES_ADR
		JMP	EMITT0

EMIT3		LDA	FROML	
		STA	INDL		;IND <- FROM
		LDA	FROMH	
		STA	INDH	

		CALL	DIST		;PRIMERO CALCULAMOS DISTANCIA ENTRE FROM Y TO		

		LDA	DISTHH
		CPI	0
		JNZ	EMITT0		;SI FROM>TO PEDIR DE NUEVO TO

		MVI	A,0FFH
		STA	KEY_ACT		;DEJA LIMPIA LA LECTURA DEL TECLADO

		CALL	SENDT		;EMITE UNA TRAMA CON LON=10H

FEMI		RET
;
;
;
;
;
;
;
;DEL ACUMULADOR SACA MITAD MSB
;
GET_HA		ANI	0F0H
		RLC
		RLC
		RLC
		RLC
		RET
;
;
;
;
;DEL ACUMULADOR SACA MITAD LSB
;
;
GET_LA		ANI	00FH
		RET
;
;
;
;
;
;	ESTA RUTINA DEVUELVE CODIGO ASCII DEL CONTENIDO DEL ACUM.
;	ENTRADA: 0..9, A..F)
;	SALIDA: 30H..39H 41H..46H 
;
GET_ASCII	CPI	00AH
		JM	GET_ASC1
		ADI	037H	
		JMP	GET_ASCS

GET_ASC1	ADI	030H
		
GET_ASCS	RET
;
;
;
;
;
;
SENDT		CALL	DIST
		MVI	A,1
		CALL	COMPARA		;POR LO MENOS SE ENVIA UN DATO?
		JM	SENDT8		;SI MENOR; SALTA Y ENVIA TRAMA FINAL

		MVI	A,0		;BUENO, ALMENOS TENEMOS QUE ENVIAR UNA TRAM REGULAR
		STA	FASET		;FASE DE TX <- 0
		STA	TYPE		;TIPO<-0 (TRAMA NORMAL)

SENDT1		LDA	FASET
		CPI	000H
		JNZ	SENDT2

		CALL	WAIT_TX		
		MVI	A,':'
		OUT	RDAT_8251	;TRANSMITE INICIO DE TRAMA :
		MVI	A,001H
		STA	FASET
		JMP	SENDT1

SENDT2		CPI	001H		;FASE 1: HAY QUE TRASNMITIR LONGITUD TRAMA
		JNZ	SENDT3

		CALL	WAIT_TX		;ESPERA TX LIBRE
		LDA	LON
		CALL	GET_HA		;CONSIGUE PARTE ALTA
		CALL	GET_ASCII	;CONSIGUE ASCII
		OUT	RDAT_8251	;TRANSMITELO

		CALL	WAIT_TX		;ESPERA TX LIBRE
		LDA	LON
		CALL	GET_LA		;CONSIGUE PARTE ALTA
		CALL	GET_ASCII	;CONSIGUE ASCII
		OUT	RDAT_8251	;TRANSMITELO

		MVI	A,002H
		STA	FASET
		JMP	SENDT1		;SIGUE

SENDT3		CPI	002H		;FASE 2: HAY QUE TRASNMITIR MSB START ADDRES TRAMA
		JNZ	SENDT4

		CALL	WAIT_TX		;ESPERA TX LIBRE
		LDA	INDH
		CALL	GET_HA		;CONSIGUE PARTE ALTA
		CALL	GET_ASCII	;CONSIGUE ASCII
		OUT	RDAT_8251	;TRANSMITELO

		CALL	WAIT_TX		;ESPERA TX LIBRE
		LDA	INDH
		CALL	GET_LA		;CONSIGUE PARTE BAJA
		CALL	GET_ASCII	;CONSIGUE ASCII
		OUT	RDAT_8251	;TRANSMITELO

		CALL	WAIT_TX		;ESPERA TX LIBRE
		LDA	INDL
		CALL	GET_HA		;CONSIGUE PARTE ALTA
		CALL	GET_ASCII	;CONSIGUE ASCII
		OUT	RDAT_8251	;TRANSMITELO

		CALL	WAIT_TX		;ESPERA TX LIBRE
		LDA	INDL
		CALL	GET_LA		;CONSIGUE PARTE BAJA
		CALL	GET_ASCII	;CONSIGUE ASCII
		OUT	RDAT_8251	;TRANSMITELO

		MVI	A,003H
		STA	FASET
		JMP	SENDT1		;SIGUE
		
SENDT4		CPI	003H		;FASE 3: HAY QUE TRASNMITIR TIPO DE TRAMA
		JNZ	SENDT5

		CALL	WAIT_TX		;ESPERA TX LIBRE
		LDA	TYPE
		CALL	GET_HA		;CONSIGUE PARTE ALTA
		CALL	GET_ASCII	;CONSIGUE ASCII
		OUT	RDAT_8251	;TRANSMITELO

		CALL	WAIT_TX		;ESPERA TX LIBRE
		LDA	TYPE
		CALL	GET_LA		;CONSIGUE PARTE BAJA
		CALL	GET_ASCII	;CONSIGUE ASCII
		OUT	RDAT_8251	;TRANSMITELO

		MVI	A,004H
		STA	FASET
		JMP	SENDT1		;SIGUE


SENDT5		MVI	A,010H		
		STA	LON		;EN PRINCIPIO LON=010H

		CALL	DIST		;CALCULAMOS DISTANCIA ENTRE IND Y TO
		MVI	A,010H		;Y LA COMPARAMOS CON 10H
		CALL	COMPARA		;POR LO MENOS SE ENVIA UN DATO?
		JP	SENDT6		;SI ES MAYOR SALTA

		LDA	DISTL
		CPI	0
		JZ	SENDT8		;SI DIST FUERA CERO IR A TRAMA FINAL
		STA	LON


SENDT6		MVI	A,0
		STA	CBT		;CONTADOR DE BYTES TRANSMITIDOS=0
		MVI	A,0
		STA	CHK		;CHECKSUM <- 0

SENDT7		LHLD	INDL		;HL APUNTA A BYTE A TRANSMITIR

		LDA	CHK
		ADD	M
		STA	CHK

		CALL	WAIT_TX
		MOV	A,M
		CALL	GET_HA
		CALL	GET_ASCII
		OUT	RDAT_8251	;TX PARTE MSB BYTE	

		CALL	WAIT_TX
		MOV	A,M
		CALL	GET_LA
		CALL	GET_ASCII
		OUT	RDAT_8251	;TX PARTE LSB BYTE

		INX	H
		SHLD	INDL		;IND <- IND+1
		LDA	CBT
		ADI	1	
		STA	CBT		;CBT <- CBT+1

		LDA	CBT
		MOV	B,A
		LDA	LON
		CMP	B
		JNZ	SENDT7		;SIGUE HASTA ACABAR TRAMA EN CURSO

		CALL	WAIT_TX
		LDA	CHK
		CALL	GET_HA
		CALL	GET_ASCII
		OUT	RDAT_8251	;TX PARTE MSB CHK	

		CALL	WAIT_TX
		LDA	CHK
		CALL	GET_LA
		CALL	GET_ASCII
		OUT	RDAT_8251	;TX PARTE LSB CHK

		CALL	WAIT_TX
		MVI	A,00DH
		OUT	RDAT_8251	;TRANSMITE CR
		JMP	SENDT		;VUELVE A TRANSMITIR UNA NUEVA TRAMA		


SENDT8		LXI	H,T_FINAL	;ENVIAMOS TRAMA FINAL ":00000001FF"
		MVI	B,11
		CALL	ENVIA

		RET
;
;
;
;
;
;ESTA RUTINA ENVIA UNA TABLA POR UART
;HL	->COMIENZO MEMORIA
;B	->NUMERO DATOS A TRANSMITIR
;
;
ENVIA		CALL	WAIT_TX		;ESPERA TX LIBRE	
		MOV	A,M		;COGE DATO
		OUT	RDAT_8251	;TRANSMITELO
		INX	H
		DCR	B
		JNZ	ENVIA
		RET		

;
;
T_FINAL		.DB ":00000001FF"
;
;
;
;
;
;
;ESPERA AL TX LIBRE	
;
WAIT_TX		IN	RCON_8251	;LEE CONTROL 8251
		ANI	001H		;TX LIBRE?
		JZ	WAIT_TX
		RET
;
;
;
;
;
;
;CALCULA DISTANCIA ENTRE IND Y TO. LO HACE EN 24 BITS (DISTHH,DISTH,DISTL)
;
;
DIST		LDA	INDL
		MOV	C,A
		LDA	INDH
		MOV	B,A		;(B,C) <- 0,INDH,INDL

		LDA	TOL
		SUB	C
		STA	DISTL
		LDA	TOH
		SBB	B
		STA	DISTH
		MVI	A,0
		SBI	0
		STA	DISTHH
		RET
;
;
;
;MODIFICA FLAGS STATUS COMPARANDO DIST CON ACUM
;
COMPARA		MOV	B,A		;GUARDA VALOR EN B
		LDA	DISTL
		SUB	B
		LDA	DISTH
		SBI	0
		LDA	DISTHH
		SBI	0
		RET		
;
;
;
;
;RUTINA DE RECIBIR DESDE LA UART UN FICHERO EN FORMATO INTEL
;
;
RECIBIR		MVI	A,014H		;COMMAND INSTRUCTION FOR 8251 
		OUT	RCON_8251	;RESET ALL ERRORS, DISABLE TRANSMIT, ENABLE RECEIVE

		MVI	A,000H
		STA	N_TRA_OK
		STA	N_TRA_ERR
		STA	PUNL
		STA	PUNH

		MVI	A,050H
		STA	DIG5
		MVI	A,0
		STA	DIG4		;Vamos a visualizar "R XXXX"

REC_INI		MVI	A,0		;COMIENZO RECEPCION UNA TRAM
		STA	N
		STA	CHK
		STA	MITAD

REC_B		LXI	H,DIG0		;HL <- DIG0 
		LDA	PUNL
		CALL	DEC_BYTE	;DIG1 y DIG0 CARGADO CON PUNL
		LDA	PUNH
		CALL	DEC_BYTE	;DIG3 y DIG2 CARGADO CON PUNH	

		CALL	PRES		;VISUALIZA R+(PUNH,PUNL)	

		IN	RCON_8251	;LEE CONTROL 8251

		MOV	B,A
		ANI	002H		;DATO RECIBIDO?
		JZ	REC_B		;SI NO, SIGUE ESPERANDO
		MOV	A,B
		ANI	038H		;HA HABIDO ERROR?
		JZ	REC_B0
		MVI	A,014H		;
		OUT	RCON_8251	;RESET ALL ERRORS, DISABLE TRANSMIT, ENABLE RECEIVE
		JMP	REC_B

REC_B0		IN	RDAT_8251	;COGE EL DATO RECIBIDO?
		STA	DATO_RX		;Y GUARDALO	

		LDA	N
		INR	A		
		STA	N		;N <- N+1

		CPI	1		;PRIMER DATO RECIBIDO?
		JNZ	REC_B1

		LDA	DATO_RX
		CPI	':'		;CABECERA CORRECTA?	
		JZ	REC_B		;OK, SIGUE RECIBIENDO
		JMP	REC_INI		;SI NO, INICIALIZA DE NUEVO
		;
REC_B1		LDA	DATO_RX		;CARGA DATO RECIBIDO
		CALL	IS_D_ASC	;ES VALIDO; ES DECIR, ASCII 0..F?
		STA	DATO_RX		;ALMACENA RESULTADO

		MOV	A,B		;Y COMPRUEBA SI ERA VALIDO
		CPI	RES_OK		;
		JNZ	REC_INI		;SI EL DATO NO ERA BUENO, INICIALIZAR

		LDA	MITAD
		CPI	0
		JNZ	REC_B2
		LDA	DATO_RX		
		RAL			;ES PRIMERA PARTE
		RAL
		RAL
		RAL
		STA	R_TMP
		MVI	A,1
		STA	MITAD
		JMP	REC_B		;CONTINUA RECIBIENDO

REC_B2		LDA	DATO_RX
		MOV	B,A
		LDA	R_TMP
		ORA	B
		STA	DATO_PR		;DATO_PR <- DATO RECIBIDO
		CALL	ACT_CHK		;ACTUALIZA CHECK_SUM
		MVI	A,0
		STA	MITAD		;

		LDA	N
		CPI	3		;RECIBIDO SEGUNDO DATO?
		JNZ	REC_B3		

		LDA	DATO_PR		;PUES YA HEMOS RECIBIDO LONGITUD
		STA	LON
		JMP	REC_B		;CONTINUA RECIBIENDO

REC_B3		LDA	N
		CPI	5		;RECIBIDO CUARTO DATO?
		JNZ	REC_B4

		LDA	DATO_PR
		STA	PUNH		;PUES YA HEMOS RECIBIDO PARTE MSB DE LA DIRECCION
		JMP	REC_B

REC_B4		CPI	7
		JNZ	REC_B5		;RECIBIDO SEXTO DATO?

		LDA	DATO_PR
		STA	PUNL		;PUES YA HEMOS RECIBIDO PARTE LSB DE LA DIRECCION
		JMP	REC_B

REC_B5		CPI	9
		JNZ	REC_B6		;RECIBIDO OCTAVO DATO?

		LDA	DATO_PR		;YA TENEMOS TIPO DE TRAMA
		STA	TYPE
		CPI	0		;TRAMA TIPO 0 (TRAMA NORMAL)?
		JZ	REC_B		;PUES OK Y SIGUE RECIBIENDO
		CPI	1		;TRAMA TIPO 1 (ULTIMA TRAMA)?		
		JZ	REC_B		;TAMBIEN OK Y SIGUE RECIBIENDO

		LDA	N_TRA_ERR	;SI TYPE<>0 .OR. TYPE<>1, ES TRAMA ERRONEA
		INR	A
		STA	N_TRA_ERR	;
		JMP	REC_INI		;Y REINICIAR

REC_B6		CPI	011		;RECIBIDO DECIMO DATO O MAYOR?
		JM	REC_B		

		LDA	LON
		CPI	0
		JZ	REC_B7		;SI ULTIMO DATO YA ALMACENADO, SALTA

		LHLD	PUNL
		LDA	DATO_PR
		MOV	M,A		;GUARDA DATO EN (PUNH,PUNL)
		INX	H
		SHLD	PUNL		;(PUNH,PUNL) <- (PUNH,PUNL) +1

		LDA	LON		;UN DATO MENOS
		DCR	A
		STA	LON		;LON <- LON-1

		JMP	REC_B		;Y SIGUE RECIBIENDO

REC_B7		LDA	CHK
		CPI	0		;CHK =0?
		JZ	REC_B8

		LDA	N_TRA_ERR	;SI CHK<>0 ES TRAMA ERRONEA!
		INR	A
		STA	N_TRA_ERR	
		JMP	REC_INI

REC_B8		LDA	N_TRA_OK
		INR	A		;UNA TRAM OK MAS!
		STA	N_TRA_OK

		LDA	TYPE
		CPI	1		;ERA ULTIMA TRAMA RECIBIDA?
		JZ	REC_FIN
		JMP	REC_INI		;A RECIBIR OTRA TRAMA

REC_FIN		LDA	N_TRA_ERR
		CPI	0
		JNZ	REC_FIN1

		LXI	H,MES_GOOD
		CALL	LOAD_DISP	;"GOOD"
		JMP	REC_FIN2

REC_FIN1	LXI	H,MES_ERR
		CALL	LOAD_DISP	;"ERR"

REC_FIN2	CALL	PRES		;PRESENTA MENSAJE DE TERMINACION
		CALL	LEE
		LDA	KEY_ACT
		CPI	0FFH
		JZ	REC_FIN2	;SI SE PULSA UNA TECLA SE SALE
		RET			;SALIR

;
;
MES_ERR		.DB	079H,050H,050H,0,0,0	;ERR

MES_GOOD	.DB	06FH,05CH,05CH,05EH,0,0	;GOOD

MES_FROM	.DB	071H,048H,0,0,0,0	;FROM

MES_TO		.DB	078H,048H,0,0,0,0	;TO

;
;
;CARGA LOS DGI0..DIG5 CON EL CONTENIDO APUNTADO POR HL
;HL->TABLA DIG5...DIG0
;
;
LOAD_DISP	MVI	B,06		;NUMERO DE DIGITOS A CARGAR
		LXI	D,DIG5

LOAD_D1		MOV	A,M
		STAX	D
		INX	H
		DCX	D
		DCR	B
		JNZ	LOAD_D1	
		RET
;
;
;
;
;ACTUALIZAMOS CHECK SUM DATO RECIBIDO EN EL ACUMULADO
;
ACT_CHK		MOV	B,A		;SALVA DATO EN B
		LDA	CHK
		ADD	B
		STA	CHK
		RET


;
;
;	ESTA RUTINA COMPRUEBA SI ACUMULADOR CONTIENE UN CODIGO ASCII
;	HEXADECIMAL VALIDO 30H..39H 41H..46H (ES DECIR, 0..9, A..F)
;	SALIDA: 
;		REG.B=00 ASCII OK   ACUM = 0X CON DATO
;		REG.B=FF ASCII NO!
;
IS_D_ASC	MVI	B,RES_OK	;EN PRINCIPIO SERA SALIDA OK

		CPI	030H
		JM	IS_D_MAL
		CPI	047H
		JP	IS_D_MAL
		CPI	03AH
		JM	IS_D_OK				
		CPI	041H
		JM	IS_D_MAL

IS_D_OK		SUI	030H
		CPI	00AH
		JM	IS_D_S	
		SUI	007H
		JMP	IS_D_S

IS_D_MAL	MVI	B,RES_NOK	;SALIDA ERRONEA

IS_D_S		RET
;
;
;
;
;LECTURA DEL TECLADO FILTRANDO PARA EVITAR REBOTES
;
;
LEE		CALL	LEI		;HAZ LECT. INST. DEL TECLADO
		MOV	B,A
		LDA	KEY_TMP
		CMP	B		;COINCIDE CON LECT. ANTERIOR?
		JZ	LEE1
		;
		MOV	A,B
		STA	KEY_TMP
		JMP	LEE3
		;
LEE1		LDA	KEY_CFIL
		DCR	A
		STA	KEY_CFIL
		JNZ	LEES
		;
		LDA	KEY_TMP
		CPI	0FFH
		JNZ	LEE2
		LDA	KEY_LAST	;
		CPI	0FFH
		JZ	LEE2
		;
		LDA	KEY_LAST
		STA	KEY_ACT
		LDA	KEY_TMP
		STA	KEY_LAST
		JMP	LEE3
		;
LEE2		LDA	KEY_TMP
		STA	KEY_LAST
		;
LEE3		MVI	A,050		;NUM. ITERACIONES PARA FILTRAR LECTURA DEL TECLADO
		STA	KEY_CFIL
		;
LEES		RET
;
;
;
;
;RUTINA DE LEER INSTANTANEAMENTE EL TECLADO
;SALIDA: 	A=FF       SI NADA PULSADO
;		A=00..17H EN FUNCION DELA TECLA LEIDA
;
LEI		MVI	A,PCON_LE	;
		OUT	PCON_8255	;8255 LISTO PARA LEER TECLAS
		MVI	A,0
		OUT	PC_8255		;APAGA DISPLAYS
		MVI	A,0FEH
		OUT	PB_8255		;PB0=0 (SELECCIONA FILA 3)
		IN	PA_8255		;LEELA
		XRI	0FFH		;
		JZ	LEI1
		LXI	H,FILA3
		CALL	GETKEY
		JMP	LEIS

LEI1		MVI	A,0FDH
		OUT	PB_8255		;PB1=0 (SELECCIONA FILA 2)
		IN	PA_8255		;LEELA
		XRI	0FFH		;			
		JZ	LEI2
		LXI	H,FILA2
		CALL	GETKEY
		JMP	LEIS

LEI2		MVI	A,0FBH
		OUT	PB_8255		;PB2=0 (SELECCIONA FILA 0)
		IN	PA_8255		;LEELA
		XRI	0FFH		;			
		JZ	LEI3
		LXI	H,FILA1
		CALL	GETKEY
		JMP	LEIS

LEI3		MVI	A,0FFH		;NINGUNA TECLA PULSADA!

LEIS		RET
;
;
;
;
;
;
GETKEY		MVI	B,0
		MVI	C,0		;BC=0
		MVI	D,08
		;
GETK1		RRC
		JC	GETK2
		INR	C
		DCR	D
		JNZ	GETK1
		MVI	A,0FFH		;NO VALIDO!
		JMP	GETKS
		;
GETK2		DAD	B		;HL <- HL+BC	
		MOV	A,M
		;
GETKS		RET
;
;
;
;
;
FILA1		.DB 	007H,006H,005H,004H,003H,002H,001H,000H
FILA2		.DB	00FH,00EH,00DH,00CH,00BH,00AH,009H,008H
FILA3		.DB	TECLA_DU,TECLA_LO,TECLA_PC,TECLA_GO,TECLA_MI,TECLA_PL,TECLA_DA,TECLA_AD
;
;
;
;
;
;
;
;RUTINA DE PRESENTAR EL DIG_ACT EN EL DISPLAY
;
;
PRES		MVI	A,PCON_DI	;
		OUT	PCON_8255	;8255 LISTO PARA ILUMINAR

		LXI	H,DIG0		;HL <- DIG0
		MVI	B,0
		LDA	DIG_ACT
		MOV	C,A		;BC <- DIG_ACT
		DAD	B		;HL <- HL+BC
		MOV	A,M		;LEE CONTENIDO DIGITO EN CURSO
		OUT	PA_8255		;PONLO EN EL DISPLAY
		;
		CALL	GET_PINC	;OBTEN PINC PARA DIG_ACT
		OUT	PC_8255		;ACTIVA PIN PCx DE DIGITO EN CURSO
		;
		LXI	H,006FH		;TIEMPO DE ILUMINACION DEL DISPLAY
		SHLD	TIEMPO
		CALL	TEMP		;VISUALIZALO UN TIEMPO
		;
		MVI	A,PCON_LE	;
		OUT	PCON_8255	;AHORA 8255 LISTO PARA LEER
		MVI	A,000H
		OUT	PC_8255		;APAGA ALIMENTACION DISPLAYS
		;
		LDA 	DIG_ACT
		ADI	001H		;DIG_ACT <- DIG_ACT + 1
		CPI	006H
		JM	PRES1		;SI ENTRE 0 y 5 SALIR
		MVI	A,0
PRES1		STA	DIG_ACT
		RET
;
;
;
;
;
;
GET_PINC	MVI	B,0
		LDA	DIG_ACT
		MOV	C,A		;BC <- DIG_ACT		
		LXI	H,TABLA_PINC	;HL <. TABLA_PINC
		DAD	B		;HL <- HL+BC
		MOV	A,M		;COGE RESULTADO
		RET

;
;
;
;
;ASIGNCION DE PUERTOS C A DIGITOS DEL DISPLAY
;
;
TABLA_PINC	.DB	020H		;DIG0 -> U9 (PC5)
		.DB	010H		;DIG1 -> U8 (PC4)
		.DB	008H		;DIG2 -> U7 (PC3)
		.DB	001H		;DIG3 -> U6 (PC0)
		.DB	004H		;DIG4 -> U5 (PC2)
		.DB	002H		;DIG5 -> U3 (PC1)
;
;
;
;
;
;
;RUTINA DE TEMPORIZAR
;
;
TEMP		LHLD	TIEMPO
		;
TEMP1		DCX	H		;DECREMENTA HL
		MOV	A,H
		ORA	L
		JNZ	TEMP1
		RET
;
;
;
;
;
;
;
		.END








