;***********************************************************************************
; MANEJO DEL SENSOR PING))) DE PARALLAX - Programa Básico 1
; PRUEBA QUE ENTREGA DATOS A UNA PC POR EL PUERTO SERIAL O USB
; Por Eduardo J. Carletti, Robots Argentina, 2008
;***********************************************************************************

	list      p=16F628A	; definir procesador

#include <p16F628A.inc>		; definiciones de variables específicas del procesador

	ERRORLEVEL 1;-302	; para evitar los mensajes de cambio de
				; banco en el resultado del compilador

	__CONFIG   _CP_OFF & _WDT_OFF & _LVP_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF

;***** VARIABLES

	CBLOCK 0x20
	contador		; variable momentánea
	comando			; byte recibido por serie
	bajo			; byte bajo del resultado
	alto			; byte alto del resultado
	uni			; unidad
	dec			; decena
	cen			; centena
	datopr			; momentáneo
	ENDC

;***********************************************************************************

		org	0x000
		goto	principal

;***********************************************************************************
; INICIALIZA
;***********************************************************************************

principal	movlw b'00000111' 	; deshabilita comparadores. Esto es
		movwf CMCON		; algo importante en el PIC16F628A

		clrf PORTA		; inicia valor en puertos
		clrf PORTB		; inicia valor en puertos

		bsf STATUS,RP0		; apunta a banco 1

		movlw b'11111110' 	; PORTA 
		movwf	TRISA		; todas entradas excepto 0 que es salida

		MOVLW b'11111011' 	; PORTB 
		movwf	TRISB		; entradas, menos TB2 que es TX

;***********************************************************************************
; BAUD RATE para la comunicación serie y otras definiciones para USART
;***********************************************************************************
; Baud Rate = 9600, No Parity, 1 Stop Bit

	        movlw 0x19              ; 0x19=9600 bps (0x0C=19200 bps)
	        movwf SPBRG
	        movlw b'00100100'       ; BRGH en alto (2)
	        movwf TXSTA             ; habilita transmisión asincrónica, BRGH a 1
	        bcf STATUS,RP0          ; apunta a banco 0
	        movlw b'10010000'       ; habilita recepción asincrónica
	        movwf RCSTA

;***********************************************************************************
; MENSAJE DE BIENVENIDA
;***********************************************************************************

		call bienvenida        	; envía mensaje de bienvenida
		clrf comando		; limpia el byte de comando recibido

;***********************************************************************************
; LAZO PRINCIPAL
;***********************************************************************************

lazo		clrf comando
		btfsc PIR1,RCIF         ; (5) se fija si hay dato RS232
		call recibeRS232	; sí, hay

		; chequeo del comando comando
		movlw 'd'		; chequea comando "d"
		xorwf comando,w
		btfsc STATUS,Z
		call distancia		; mide la distancia

		goto lazo

;***********************************************************************************
; TABLA DE DATOS PARA MENSAJE
;***********************************************************************************

msgbienv	ADDWF PCL, F
		DT "Sensor PING))), Robots Argentina, 2008", 0x0D, 0x0A, 0x00

;***********************************************************************************
; SUBRUTINA DISTANCIA
;***********************************************************************************

distancia	clrf contador

		; pulso de arranque
		bsf PORTA,0		; pulso de arranque de unos uS
		nop
		nop
		nop
		bcf PORTA,0		; apaga pulso de arranque

		; cambia el pin del sensor a entrada
		bsf STATUS,RP0		; apunta a banco 1
		bsf TRISA,0		; PORTA bit0 a entrada
		bcf STATUS,RP0		; Apunta a banco 0

		; espera unos 750 uS para dar tiempo a la salida y regreso del pulso
		clrf bajo
atras		decf bajo,f
		bnz atras

		clrf alto		; prepara para el conteo en alto y bajo

		; espera contando el tiempo en alto y bajo, 
		; que serán los valores de salida
espera		incf bajo,f		; lo hacemos con un lazo simple
		btfsc STATUS,Z		; aunque se puede utilizar un timer
		incf alto,f
		btfsc PORTA,0
		goto espera

		; cambia el pin sensor a salida
		bsf STATUS,RP0		; apunta a banco 1
		bcf TRISA,0		; PORTA bit0 a salida
		bcf STATUS,RP0		; apunta a banco 0

		; muestra el valor en la PC
		movlw '='
		call enviaRS232
		movlw ' '
		call enviaRS232
		movf alto,w		; envía el byte alto
		call print_hexa
		movf bajo,w		; envía el byte bajo
		call print_hexa
		goto msgCR		; envía salto de línea y sale

;***********************************************************************************
; COMUNICACION RS232
;***********************************************************************************

recibeRS232	;recibir de PC
		movf RCREG,W            ; guarda comando en comando
		movwf comando		; guarda
		call enviaRS232		; eco a la PC
		return

enviaRS232	movwf TXREG             ; enviar dato en W
TransWt		bsf STATUS,RP0		; apunta a banco 1
WtHere		btfss TXSTA,TRMT        ; (1) transmision completa si es alto
		goto WtHere
		bcf STATUS,RP0          ; apunta a banco 0
		return

;***********************************************************************************
; MENSAJES
;***********************************************************************************

bienvenida	clrf contador		; limpia el puntero de caracter
b1		movf contador, W
		call msgbienv		; apunta el index hacia un caracter
		addlw 0			; se hace para chequear el flag Z
		btfsc STATUS, Z
		return			; el caracter fue 00, termina el mensaje
		call enviaRS232		; envía el caracter al puerto serie
		incf contador, F	; siguiente caracter
		goto b1

msgCR		movlw 0x0D		; caracter RETURN
		call enviaRS232		; envía el caracter al puerto serie
		movlw 0x0A		; caracter LINE FEED
		goto enviaRS232		; envía el caracter al puerto serie

;***********************************************************************************
; SUBRUTINA PARA MOSTRAR DATOS POR LINEA SERIE
;***********************************************************************************

print_hexa	movwf datopr
		swapf datopr,w		; toma parte alta
		call ph_pr		; imprime
		movf datopr,w		; toma parte baja
		call ph_pr		; imprime
		return
ph_pr		andlw 0x0F		; limpia lo que no sirve
		movwf uni		; la salva momentaneamente
		sublw 0x09		; hace literal - w
		btfsc STATUS,C
		goto ph_0a9		; es 0 a 9
		movf uni,w		; es mayor que 9, rescata valor
		addlw 0x37		;
		goto enviaRS232
ph_0a9		movf uni,w		; es 0 a 9, rescata valor
		addlw 0x30
		goto enviaRS232

		END
