/****************************************************************************
ADC1.C

This is an example of a DVM using PIC 16F876 or 16F873.
It reads 0-5V at pin 2 every 10mS, and writes the 10-sample averaged result
to a 9600 baud terminal screen.

Analog input at A0 (pin 2)
9600 baud output as B0 (pin 21)
Pulse output at B1 (pin 22)    this provides a pulse every 10mS (for test)

External crystal oscillator = 4MHz
Cycle time = 1uS

Jon Fick  10/24/99

***************************************************************************/

#include < 16F876.h >

/* Set configuration bits in the PIC processor */
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT

#use delay (clock=4000000)      /* sets appropriate compiler constants */
#use standard_io ( a )
#use standard_io ( b )
#use standard_io ( c )
#use rs232 ( baud = 9600, XMIT = PIN_B0, BITS=8 )

static char cADCflag;       /* global variable */

void main( void )
    {
    char cCnt;          /* 8-bit variables */
    long cADCtotal, cADCval;    /* 16-bit variables */

    setup_adc_ports ( RA0_ANALOG );  /* these three statements set up the ADC */
    setup_adc ( ADC_CLOCK_INTERNAL );
    set_adc_channel ( 0 );

    /* SET THE COUNTER TO ROLL EVERY 10mS */
    setup_counters ( RTCC_INTERNAL, RTCC_DIV_64 ); /* timer increments every 64uS */
    enable_interrupts ( INT_RTCC );                /* enable timer interrupt */
    enable_interrupts ( GLOBAL );                  /* enable global interrupts */
    set_rtcc ( 100 );      /* start counter at 256-100 = 156 counts until wrap */

    cADCtotal = 0;
    cCnt = 0;                   /* count the number of ADC measurements */

    while ( 1 )                             /* do forever */
        {
        if ( cADCflag == 1 )            /* if interrupt turned flag on */
            {
            cADCflag = 0;                   /* turn flag off */

            cADCval = read_adc();           /* read the ADC */
            cADCtotal += cADCval;           /* add it to total, for later averaging */

            if ( cCnt++ == 9 )              /* increment count, is it ten counts yet? */
                {
            disable_interrupts ( INT_RTCC );    /* don't allow interrupts during display */
                cCnt = 0;           /* restart count */
                cADCtotal /= 10;    /* divide by 10 samples to get average */

                // 0 to 5V input at pin 2 will display 0 - 1023.
                // If you want to scale it to read 0.00 to 5.00 volts, the variable
                // must be type FLOAT, such as fX in the three lines below...
                //
                // fX = read_adc();               /* read the ADC here */
                // fX = fX / 1024 * 5.00;         /* scale it to 5V */
                // printf ( "%1.2f volts", fX );  /* print it to the screen */

                printf ( "\n\rMeasurement = %lu", cADCtotal );     /* send to RS232 */
                cADCtotal = 0;      /* restart total */
                enable_interrupts ( INT_RTCC );   /* allow interrupts again */
                }
            }
        }
    }

/*****************************************************************************************************/
#INT_RTCC void TIMER_INTERRUPT ( void )
    {
    /*
    This interrupt occurs every 10mS (timer increments every 64uS, timer is
    preset to 100 so it wraps 156 counts later at 256.)  Adjust the restart
    count to get the 10mS exactly.
    */

    OUTPUT_HIGH ( PIN_B1 ); /* test pulse */
    OUTPUT_LOW ( PIN_B1 );
    set_rtcc ( 100 );        /* restart count */
    cADCflag = 1;            /* set flag to alert main program to read ADC */
    }