;---------------------------------------------------;
;
;	RUTINAS DE MANEJO PARA MODULO LCD CON
;	CONTROLADOR KS0066 (O EQUIVALENTE)
;	PARA USAR EN MODO 4 U 8 BITS.
;
;	POR JUAN MARTIN FERRARI, AÑO 2010.
;
;	LAS RUTINAS DE RETARDO FUERON GENERADAS
;	CON EL PROGRAMA PDEL, DE PIER PAOLO
;	MESSAGGIO.
;
;---------------------------------------------------;
;
; LA FRECUENCIA DEL CRISTAL, RESONADOR O FUENTE
; EXTERNA DE OSCILACION DEBE SER DE 4 MHZ. CASO
; CONTRARIO, AJUSTAR TANTO LAS RUTINAS DE RETARDO
; COMO LAS DEMORAS NECESARIAS EN LOS CICLOS DE
; LECTURA Y ESCRITURA (VER HOJA DE DATOS KS0066).
;
; - MODO 4 BITS HIGH:
;
; SE SELECCIONA DEFINIENDO LA ETIQUETA
; "LCD_4BITS_HIGH" CON LA SENTENCIA:
;	#DEFINE	LCD_4BITS_HIGH
; EL LCD DEBE ESTAR CONECTADO A LOS PINES <4:7> DEL
; PUERTO B (DEBEN SER CONFIGURADOS COMO SALIDA 
; PREVIAMENTE) DE LA FORMA:
; DB4 -> PORTB,4
; DB5 -> PORTB,5
; DB6 -> PORTB,6
; DB7 -> PORTB,7
;
;
; - MODO 4 BITS LOW:
;
; SE SELECCIONA DEFINIENDO LA ETIQUETA
; "LCD_4BITS_LOW" CON LA SENTENCIA:
;	#DEFINE	LCD_4BITS_LOW
; EL LCD DEBE ESTAR CONECTADO A LOS PINES <0:3> DEL
; PUERTO B (DEBEN SER CONFIGURADOS COMO SALIDA 
; PREVIAMENTE) DE LA FORMA:
; DB4 -> PORTB,0
; DB5 -> PORTB,1
; DB6 -> PORTB,2
; DB7 -> PORTB,3
;
;
; - MODO 8 BITS:
;
; SE SELECCIONA DEFINIENDO LA ETIQUETA
; "LCD_8BITS" CON LA SENTENCIA:
;	#DEFINE	LCD_8BITS
; EL LCD DEBE ESTAR CONECTADO AL PUERTO B, EL CUAL
; DEBE SER CONFIGURADO COMO SALIDA PREVIAMENTE:
; DB0 -> PORTB,0
; DB1 -> PORTB,1
; DB2 -> PORTB,2
; DB3 -> PORTB,3
; DB4 -> PORTB,4
; DB5 -> PORTB,5
; DB6 -> PORTB,6
; DB7 -> PORTB,7
;
; LAS LINEAS E, RS Y RW DEBERAN CONECTARSE A ALGUN 
; PIN DEL PUERTO A, PREVIAMENTE CONFIGURADOS COMO SALIDA.
;
;
; ES NECESARIO/A:
;
; - LA DECLARACION DE: RS, E Y RW (CON LA DIRECTIVA EQU).
;   POR EJEMPLO:
;	E	EQU	0
;	RS	EQU	1
;	RW	EQU	2
;   QUEDA CONFIGURADO COMO:
;	E  -> PORTA,0
;	RS -> PORTA,1
;	RW -> PORTA,2
;
; - EL USO DE LA DIRECTIVA CBLOCK PREVIO A LA INCLUSIÓN DE
;   ESTE ARCHIVO, PARA INDICAR LA DIRECCION DE R_E_T_1,
;   R_E_T_2 Y LCD_AUX (VER ARCHIVO DE AYUDA DEL MPASM PARA
;   MAS INFORMACION).
;
; - LA INCLUSION DEL ARCHIVO PXXX.INC (DEL PIC USADO).
;
; - UN MINIMO DE 3 REGISTROS DE RAM SIN USAR.
;
;------------------------------------------------

; CONTROL DE ETIQUETAS;


	IFDEF	LCD_8BITS

	IFDEF	LCD_4BITS_LOW
	ERROR	"Mas de una etiqueta definida para seleccion de modo del LCD"
	ENDIF
	IFDEF	LCD_4BITS_HIGH
	ERROR	"Mas de una etiqueta definida para seleccion de modo del LCD"
	ENDIF

	ENDIF


	IFDEF	LCD_4BITS_LOW

	IFDEF	LCD_4BITS_HIGH
	ERROR	"Mas de una etiqueta definida para seleccion de modo del LCD"
	ENDIF

	ENDIF


	IFNDEF	LCD_8BITS
	IFNDEF	LCD_4BITS_HIGH
	IFNDEF	LCD_4BITS_HIGH
	ERROR	"No hay una etiqueta definida para seleccion de modo del LCD"
	ENDIF
	ENDIF
	ENDIF

;------------------------------------------------

	CBLOCK
R_E_T_1
R_E_T_2
LCD_AUX
	ENDC

;------------------------------------------------
; RETARDO DE 50 MILISEGUNDOS.

retardo50ms
	MOVLW	D'55'
	MOVWF	R_E_T_1
	MOVLW	D'181'
	MOVWF	R_E_T_2
	CLRWDT
	CLRWDT
	DECFSZ	R_E_T_2,F
	GOTO	$-3
	DECFSZ	R_E_T_1,F
	GOTO	$-7
	RETURN

;------------------------------------------------
; RETARDO DE 2 MILISEGUNDOS.

retardo2ms
	MOVLW	D'249'
	MOVWF	R_E_T_1
	CLRWDT
	GOTO	$+1
	GOTO	$+1
	DECFSZ	R_E_T_1,F
	GOTO	$-4
	GOTO	$+1
	CLRWDT
	RETURN

;------------------------------------------------
; RETARDO DE 45 MICROSEGUNDOS.

retardo45us
	MOVLW	D'10'
	MOVWF	R_E_T_1
	CLRWDT
	DECFSZ	R_E_T_1,F
	GOTO	$-2
	RETURN

;------------------------------------------------
; ENVIA UNA INSTRUCCION O UN CARACTER AL LCD.
; EL BYTE A ENVIAR DEBE ESTAR GUARDADO EN W AL
; MOMENTO DE LLAMAR A LA RUTINA.

instruccion
	BCF		PORTA,RS
	GOTO	$+2

caracter
	BSF		PORTA,RS


	IFDEF	LCD_4BITS_HIGH
	; RUTINA PARA 4 BITS (NIBBLE ALTO):

	MOVWF	LCD_AUX
	MOVLW	0x0F		; PREPARO EL PUERTO B
	ANDWF	PORTB,F
	BSF		PORTA,E
	MOVLW	0xF0		; PREPARO LCD_AUX
	ANDWF	LCD_AUX,W
	IORWF	PORTB,F		; ENVIO AL PUERTO B
	NOP
	BCF		PORTA,E

	CALL	retardo45us

	MOVLW	0x0F		; PREPARO EL PUERTO B
	ANDWF	PORTB,F
	BSF		PORTA,E
	SWAPF	LCD_AUX,F	; PREPARO LCD_AUX
	MOVLW	0xF0
	ANDWF	LCD_AUX,W
	IORWF	PORTB,F		; ENVIO AL PUERTO B
	NOP
	BCF		PORTA,E

	ENDIF


	IFDEF	LCD_4BITS_LOW
	; RUTINA PARA 4 BITS (NIBBLE BAJO):

	MOVWF	LCD_AUX
	MOVLW	0xF0		; PREPARO EL PUERTO B
	ANDWF	PORTB,F
	BSF		PORTA,E
	SWAPF	LCD_AUX,F	; PREPARO LCD_AUX
	MOVLW	0x0F
	ANDWF	LCD_AUX,W
	IORWF	PORTB,F		; ENVIO AL PUERTO B
	NOP
	BCF		PORTA,E

	CALL	retardo45us

	MOVLW	0xF0		; PREPARO EL PUERTO B
	ANDWF	PORTB,F
	BSF		PORTA,E
	SWAPF	LCD_AUX,F	; PREPARO LCD_AUX
	MOVLW	0x0F
	ANDWF	LCD_AUX,W
	IORWF	PORTB,F		; ENVIO AL PUERTO B
	NOP
	BCF		PORTA,E

	ENDIF


	IFDEF	LCD_8BITS
	; RUTINA PARA 8 BITS:

	NOP
	BSF		PORTA,E
	NOP
	MOVWF	PORTB
	NOP
	BCF		PORTA,E

	ENDIF


	RETURN

;------------------------------------------------
; ESPERA A QUE EL BUSY FLAG ESTE EN BAJO.

busy_flag

	IFDEF	LCD_4BITS_HIGH
	; RUTINA PARA 4 BITS (NIBBLE ALTO):
	
	BSF		STATUS,RP0
	MOVLW	0xF0
	IORWF	TRISB,F
	BCF		STATUS,RP0

	BCF		PORTA,RS
	BSF		PORTA,RW
	NOP
	BSF		PORTA,E
	NOP
	BTFSC	PORTB,7
	GOTO	$-1
	NOP
	BCF		PORTA,E

	NOP
	BSF		PORTA,E
	NOP
	NOP
	BCF		PORTA,E
	NOP
	BCF		PORTA,RW

	BSF		STATUS,RP0
	MOVLW	0x0F
	ANDWF	TRISB,F
	BCF		STATUS,RP0

	ENDIF


	IFDEF	LCD_4BITS_LOW
	; RUTINA PARA 4 BITS (NIBBLE BAJO):

	; ¡¡¡PONER RUTINA!!!

	ENDIF


	IFDEF	LCD_8BITS
	; RUTINA PARA 8 BITS:

	BSF		STATUS,RP0
	MOVLW	0xFF
	MOVWF	TRISB
	BCF		STATUS,RP0
	BCF		PORTA,RS
	BSF		PORTA,RW
	NOP
	BSF		PORTA,E
	NOP
	BTFSC	PORTB,7
	GOTO	$-1
	NOP
	BCF		PORTA,E
	NOP
	BCF		PORTA,RW
	BSF		STATUS,RP0
	CLRF	TRISB
	BCF		STATUS,RP0

	ENDIF


	RETURN

;------------------------------------------------
; MACRO DE INICIALIZACION DEL LCD:

lcd_init	MACRO	ARG1, ARG2, ARG3


; MODO 4 BITS (HIGH O LOW):
; ARG1 -> 0010NFxx
; ARG2 -> 00001DCB
; ARG3 -> 000001(I/D)(SH)
; (x: PUEDE SER CUALQUIERA)
;
; EJEMPLO: 
; lcd_init	B'00100000', B'00001111', B'00000110'
;
;
; MODO 8 BITS:
; ARG1 -> 0011NFxx
; ARG2 -> 00001DCB
; ARG3 -> 000001(I/D)(SH)
; (x: PUEDE SER CUALQUIERA)
;
; EJEMPLO: 
; lcd_init	B'00110000', B'00001111', B'00000110'


	IFDEF	LCD_4BITS_HIGH
	; RUTINA PARA 4 BITS (NIBBLE ALTO):

	CALL	retardo50ms

	BCF		PORTA,RS
	MOVLW	0x0F		; PREPARO EL PUERTO B
	ANDWF	PORTB,F
	BSF		PORTA,E
	MOVLW	B'00100000'
	IORWF	PORTB,F		; ENVIO AL PUERTO B
	NOP
	BCF		PORTA,E
	CALL	retardo45us

	MOVLW	ARG1
	CALL	instruccion
	CALL	retardo45us

	MOVLW	ARG2
	CALL	instruccion
	CALL	retardo45us

	MOVLW	0x01
	CALL	instruccion
	CALL	retardo2ms

	MOVLW	ARG3
	CALL	instruccion
	CALL	retardo45us

	BCF	PORTA,E
	BCF	PORTA,RW

	ENDM

	ENDIF


	IFDEF	LCD_4BITS_LOW
	; RUTINA PARA 4 BITS (NIBBLE BAJO):

	; ¡¡PONER RUTINA!!

	ENDIF


	IFDEF	LCD_8BITS
	; RUTINA PARA 8 BITS:

	CALL	retardo50ms

	MOVLW	ARG1
	CALL	instruccion
	CALL	retardo45us

	MOVLW	ARG2
	CALL	instruccion
	CALL	retardo45us

	MOVLW	0x01
	CALL	instruccion
	CALL	retardo2ms

	MOVLW	ARG3
	CALL	instruccion
	CALL	retardo45us

	ENDM

	ENDIF

;------------------------------------------------