;*********************************************************************************************************
;************************************   Xiamen DISPLAY   *************************************************
;*********************************************************************************************************

	list p=16f76
	include "p16f76.inc"
	errorlevel -302 ; supress "register not in bank0, check page bits" message
	__CONFIG _PWRTE_OFF & _BODEN_OFF &_HS_OSC & _WDT_OFF

#DEFINE ANAIN		PORTA, 0		;Entrada analógica
#DEFINE lcd_DAT		PORTB
#DEFINE lcd_RS		PORTC, 0		;LCD Register Select
#DEFINE lcd_RW		PORTC, 1		;LCD Read/Write
#DEFINE lcd_E		PORTC, 2		;LCD Enable

Same    equ     1
J		equ	0x20
K		equ	0x21
PDel0	equ	0x22
PDel1	equ	0x23
PDel2	equ	0x24
PDel3	equ	0x25
PDel4	equ	0x26
PDel5	equ	0x27
PDel6	equ	0x28
POSI	equ	0x29
VIN		equ	0x2A
TEMP1	equ	0x2D
mulcnd  equ 0x2E      ; 8 bit multiplicand
mulplr  equ 0x2F      ; 8 bit multiplier
H_byte  equ 0x30      ; High byte of the 16 bit result
L_byte  equ 0x31      ; Low byte of the 16 bit result
count	equ	0x32
;count	equ	0x33
temp	equ 0x34
R0      equ 0x35              ; RAM Assignments
R1      equ 0x36
R2      equ 0x37

		org		0x00		;Program start
		goto	INICIO

;*****************************************************************************************
;Main program
;*****************************************************************************************
INICIO:
		clrf	STATUS
		bsf		STATUS,RP0	;Cambia a Bank 1
		clrf	ADCON1		;RA0 a RA5 todos Analógicos
	    movlw   0x01		;Pone a w = 00100000
    	movwf   PORTA  		;Pone PORTA como entradas
		bcf		STATUS,RP0	;Cambia a Bank 0

		call	Delay_500ms

		call	LEER_ADC

		movlw	0x75
		movwf	mulcnd
		movf	VIN,0
		movwf	mulplr

		call	multiplica
		call	B2_BCD

;	    movlw   0xC0		;
;		movwf   ADCON0		;
;		bsf		ADCON0,0	;
;		bsf		ADCON0,2	;
;loop	btfss	PIR1,6
;		goto	loop
;		movf	ADRES,0
;		movwf	VIN
;		bcf		PIR1,6

		clrf	STATUS
		bsf		STATUS,RP0	;Cambia a Bank 1
	    movlw   0x00    	;Pone a w = 00000000
    	movwf   PORTB  		;Pone a PORTB & PORTC como salidas
    	movwf   PORTC
		bcf		STATUS,RP0	;Cambia a Bank 0

		call	LCD_INI

;DIRECCIONES DDRAM
; 0x80 LINEA 1 POSICION 1
; 0xC0 LINEA 2 POSICION 1
; 0x94 LINEA 3 POSICION 1
; 0xD4 LINEA 4 POSICION 1
;
;   1    2    3    4    5    6    7    8    9    10   11   12   13   14   15   16   17   18   19   20
;  ___________________________________________________________________________________________________
; | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 8A | 8B | 8C | 8D | 8E | 8F | 90 | 91 | 92 | 93 |
; |---------------------------------------------------------------------------------------------------|
; | C0 | C1 | C2 | C3 | C4 | C5 | C6 | C7 | C8 | C9 | CA | CB | CC | CD | CE | CF | D0 | D1 | D2 | D3 |
; |---------------------------------------------------------------------------------------------------|
; | 94 | 95 | 96 | 97 | 98 | 99 | 9A | 9B | 9C | 9D | 9E | 9F | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 |
; |---------------------------------------------------------------------------------------------------|
; | D4 | D5 | D6 | D7 | D8 | D9 | DA | DB | DC | DD | DE | DF | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7 |
; |___________________________________________________________________________________________________|
;

		movlw   0x80		;Set DDRAM Address
		movwf   POSI
		call	LCD_CMD

		call	Delay_50ms

;		movlw   0x56		;"V"
		movf	VIN,0
		call	LCD_DAT
		call	ADDRESS

;		movlw   0x69		;"i"
		movf	H_byte,0
		call	LCD_DAT
		call	ADDRESS

;		movlw   0x6E		;"n"
		movf	L_byte,0
		call	LCD_DAT
		call	ADDRESS

;		movlw   0x3D		;"="
;		call	LCD_DAT
;		call	ADDRESS

		movlw   0xC0		;Set DDRAM Address
		movwf   POSI
		call	LCD_CMD

		movf	R0,0
		call	LCD_DAT
		call	ADDRESS

		movf	R1,0
		call	LCD_DAT
		call	ADDRESS

		movf	R2,0
		call	LCD_DAT

acabar	nop
		goto	acabar		;Buclee infinito

;*****************************************************************************************
;Subroutines
;*****************************************************************************************
LCD_INI:
	clrf	PORTB		;PORTA = w = 00000000
	clrf	PORTC		;PORTB = w = 00000000

	call	Delay_32ms

	movlw   0x38		;Function Set
	call	LCD_CMD

	call	Delay_40us

	movlw   0x0C		;Display ON/OFF Control
	call	LCD_CMD

	call	Delay_40us

	movlw   0x01		;Clear Display
	call	LCD_CMD

	call	Delay_2ms

	movlw   0x06		;Entry Mode Set
	call	LCD_CMD

	call	Delay_50ms

	return

LCD_E:
	bsf		lcd_E		;LCD Enable=1
	nop
	bcf		lcd_E		;LCD Enable=0
	return

LCD_CMD:
	bcf		lcd_E		;LCD Enable=0
	bcf		lcd_RW		;Activate Write operation RW=0
	bcf		lcd_RS		;RS=0
	movwf	PORTB
	bsf		lcd_E		;LCD Enable=1
	bcf		lcd_E		;LCD Enable=0
	return

LCD_DAT:
	bcf		lcd_E		;LCD Enable=0
	bcf		lcd_RW		;Activate Write operation RW=0
	bsf		lcd_RS		;RS=1
	movwf	PORTB
	bsf		lcd_E		;LCD Enable=1
	bcf		lcd_E		;LCD Enable=0
	return

ADDRESS:
	INCF    POSI, 1		;Incrementa posicion del cursor
	movlw   POSI		;Set DDRAM Address
	call	LCD_CMD

	call	Delay_50ms

	return

LEER_ADC:
	movlw	b'11000001'
	movwf	ADCON0

	movlw 	.20
	movwf	TEMP1
	decfsz	TEMP1,F
	goto	$-1

  	bsf		ADCON0,GO_DONE

  	movlw 	.20
	movwf	TEMP1
	decfsz	TEMP1,F
	goto	$-1

	btfsc	ADCON0,GO_DONE

	goto	$-1

	movf	ADRES,0
	movwf	VIN

	return

multiplica:
		clrf	H_byte
		clrf	L_byte
		movlw	8
		movwf	count
		movf	mulcnd,W
		bcf		STATUS,C ; Clear the carry bit in the status Reg.
loop	rrf		mulplr, F
		btfsc	STATUS,C
		addwf	H_byte,Same
		rrf		H_byte,Same
		rrf		L_byte,Same
		decfsz	count, F
		goto	loop

		retlw 0

;SUBRUTINA DE BINARIO A BCD

B2_BCD:
	bcf     STATUS,0                ; clear the carry bit
	movlw   .16
	movwf   count
	clrf    R0
	clrf    R1
	clrf    R2
loop16  rlf     L_byte, F
	rlf     H_byte, F
	rlf     R2, F
	rlf     R1, F
	rlf     R0, F

	decfsz  count, F
	goto    adjDEC
	RETLW   0

adjDEC  movlw   R2
	movwf   FSR
	call    adjBCD

	movlw   R1
	movwf   FSR
	call    adjBCD

	movlw   R0
	movwf   FSR
	call    adjBCD

	goto    loop16

adjBCD	movlw   3
	addwf   0,W
	movwf   temp
	btfsc   temp,3          ; test if result > 7
	movwf   0
	movlw   30
	subwf   0,W
	movwf   temp
	btfsc   temp,7          ; test if result > 7
	movwf   0               ; save as MSD
	RETLW   0

;	return

;*****************************************************************************************
;Delay 5 useg subroutine
;*****************************************************************************************
Delay_5us:
	goto D1         ; 2 ciclos delay
D1  goto D2         ; 2 ciclos delay
D2  goto D3         ; 2 ciclos delay
D3  goto D4         ; 2 ciclos delay
D4  goto D5         ; 2 ciclos delay
D5  				; 1 ciclo delay
	return			; 2+2 Fin.

;*****************************************************************************************
;Delay 40 useg subroutine
;*****************************************************************************************
Delay_40us:
		movlw	.18			; 1 set numero de repeticion 
		movwf	PDel0		; 1 |
PLoop0	clrwdt				; 1 clear watchdog
		decfsz	PDel0, 1	; 1 + (1) es el tiempo 0  ?
		goto	PLoop0		; 2 no, loop
PDelL1	goto	PDelL2		; 2 ciclos delay
PDelL2	clrwdt				; 1 ciclo delay
		return				; 2+2 Fin.

;*****************************************************************************************
;Delay 2 mseg subroutine
;*****************************************************************************************
Delay_2ms:
		movlw	.5			; 1 set numero de repeticion  (B)
        movwf	PDel1		; 1 |
PLoop1  movlw	.159		; 1 set numero de repeticion  (A)
        movwf	PDel2		; 1 |
PLoop2  clrwdt				; 1 clear watchdog
        clrwdt				; 1 ciclo delay
        decfsz	PDel2, 1	; 1 + (1) es el tiempo 0  ? (A)
        goto	PLoop2		; 2 no, loop
        decfsz	PDel1, 1	; 1 + (1) es el tiempo 0  ? (B)
        goto	PLoop1		; 2 no, loop
        return				; 2+2 Fin.

;*****************************************************************************************
;Delay 32 mseg subroutine
;*****************************************************************************************
Delay_32ms:
		movlw	.89			; 1 set numero de repeticion  (B)
		movwf	PDel3		; 1 |
PLoop3  movlw	.143		; 1 set numero de repeticion  (A)
        movwf	PDel4		; 1 |
PLoop4  clrwdt				; 1 clear watchdog
        clrwdt				; 1 ciclo delay
        decfsz	PDel4, 1	; 1 + (1) es el tiempo 0  ? (A)
        goto	PLoop4		; 2 no, loop
        decfsz	PDel3, 1	; 1 + (1) es el tiempo 0  ? (B)
        goto	PLoop3		; 2 no, loop
PDelL3  goto	PDelL4		; 2 ciclos delay
PDelL4  goto	PDelL5		; 2 ciclos delay
PDelL5						; 1 ciclo delay
        return				; 2+2 Fin.

;*****************************************************************************************
;Delay 50 mseg subroutine
;*****************************************************************************************
Delay_50ms:
		movlw	.110		; 1 set numero de repeticion  (B)
        movwf	PDel5		; 1 |
PLoop5  movlw	.181		; 1 set numero de repeticion  (A)
        movwf	PDel6		; 1 |
PLoop6  clrwdt				; 1 clear watchdog
        clrwdt				; 1 ciclo delay
        decfsz	PDel6, 1	; 1 + (1) es el tiempo 0  ? (A)
        goto	PLoop6		; 2 no, loop
        decfsz	PDel5, 1	; 1 + (1) es el tiempo 0  ? (B)
        goto	PLoop5		; 2 no, loop
PDelL6  goto	PDelL7		; 2 ciclos delay
PDelL7  goto	PDelL8		; 2 ciclos delay
PDelL8  clrwdt				; 1 ciclo delay
        return				; 2+2 Fin.

;*****************************************************************************************
;Delay 500 mseg subroutine
;*****************************************************************************************
Delay_500ms:
		call	Delay_50ms
		call	Delay_50ms
		call	Delay_50ms
		call	Delay_50ms
		call	Delay_50ms
		call	Delay_50ms
		call	Delay_50ms
		call	Delay_50ms
		call	Delay_50ms
		call	Delay_50ms
        return

	end
