/**
 * Simple voltage-reference example.
 *
 * Enables the voltage reference on PORTA pin 2 and checks if PORTA pin 
 * 3 is high or low.  If high, it sets VREF as high as it will go;  if 
 * low, it sets it as low as it will go.  It checks continuously, in a 
 * loop.
 *
 * Only for the PIC16f628a, and possibly other PICs with a built-in 
 * voltage reference.
 */
#define __16f628a
#include "pic/pic16f628a.h"

typedef unsigned int Uint16;
// Set the __CONFIG word:
Uint16 at 0x2007  __CONFIG = CONFIG_WORD;

#define OUTPUT_PIN	0	// Pin 0 of Port A.  Arbitrary.
#define VREF_PIN	2	// Pin 2 of Port A.  Hardwired.
#define INPUT_PIN	3	// Pin 3 of Port A.  Arbitrary.

#define GET_BIT(X)		(1<<(X))
#define MASK_BIT(X)		~GET_BIT(X)
#define SET_BIT(PORT,BIT)	PORT|=GET_BIT(BIT)
#define CLEAR_BIT(PORT,BIT)	PORT&=~GET_BIT(BIT)

#define IS_SET(PORT,BIT)	((PORT)&GET_BIT(BIT))
#define NOT_SET(PORT,BIT)	(!IS_SET(PORT,BIT))

void main(void)
{
	PORTA=0x00;
	CMCON = 0x07;	/** Disable comparators.  NEEDED FOR NORMAL PORTA 
			 *  BEHAVIOR ON PIC16f628a!
			 */
	TRISA=GET_BIT(VREF_PIN)|
		GET_BIT(INPUT_PIN);	// These two are inputs.

	VREN=1;		// Enable voltage reference
	VROE=1;		// Output on PORTA RA2

	while(1)	// Loop forever:
	{
		if(PORTA & GET_BIT(INPUT_PIN))	// If RA0 high
		{
			SET_BIT(PORTA,OUTPUT_PIN);
			VRR=1;	// Low range
			VR3=1;	// Zero value	MSB
			VR2=1;	// ...
			VR1=1;	// ...
			VR0=1;	// Zero value	LSB
		}
		else
		{
			CLEAR_BIT(PORTA,OUTPUT_PIN);
			VRR=0;	// Low range
			VR3=0;	// Zero value	MSB
			VR2=0;	// ...
			VR1=0;	// ...
			VR0=0;	// Zero value	LSB
		}
	}
}
