#include <p18f452.h>
#pragma config OSC=HSPLL, WDT=OFF, BOR=OFF, PWRT=ON

//This function delays for 14 us (micro-seconds)
//Assumes a 10 MHz crystal in HSPLL mode
//Overall, Fosc = 40 MHz
void delay(void)
{
  int x = 3;
  while (x--);
}

void main(void)
{
  //long int = 4 bytes = 32 bits
  unsigned long int i, d0, d1;
  signed long int average;
  unsigned long int values;
  unsigned long int scaleFactor = 130944;
  //130944 = 1023 (max ADC value) * 128 (number of samples)

  //initialize the ADC registers:
  ADCON0 = 0b10000001;
  ADCON1 = 0b11000000;

  //initialize PORTC and PORTD:
  PORTC = 0;
  TRISC = 0;

  PORTD = 0;
  TRISD = 0;

  while(1)
  {
    values = 0;
    average = 0;

    for (i = 0; i < 128; i++)
    {
      delay(); //wait 14 us for acquisition
      ADCON0bits.GO = 1; //start AD conversion
      while (ADCON0bits.GO); //wait for AD to finish
      values += ADRES;
    }

    //calculate bargraph values:
    average = (values * 20) / (scaleFactor);
    average -= 10;

    if (average < 0)
    {
      PORTDbits.RD0 = 0; // turn off positive
      PORTDbits.RD1 = 1; // turn on negative
    }
    else if (average > 0)
    {

      PORTDbits.RD0 = 1; // turn on positive
      PORTDbits.RD1 = 0; // turn off negative
    }
    else
    {
      PORTDbits.RD0 = 0; // turn off positive
      PORTDbits.RD1 = 0; // turn off negative
    }

    PORTDbits.RD2 = 0;
    PORTDbits.RD3 = 0;
    switch (average)
    {
      case -10:
      case +10:
        PORTC = 0b00000000;
        break;
      case -9:
      case +9:
        PORTC = 0b10000000;
        break;
      case -8:
      case +8:
        PORTC = 0b11000000;
        break;
      case -7:
      case +7:
        PORTC = 0b11100000;
        break;
      case -6:
      case +6:
        PORTC = 0b11110000;
        break;
      case -5:
      case +5:
        PORTC = 0b11111000;
        break;
      case -4:
      case +4:
        PORTC = 0b11111100;
        break;
      case -3:
      case +3:
        PORTC = 0b11111110;
        break;
      case -2:
      case +2:
        PORTC = 0b11111111;
        //RD2 = RD3 = 0;
        break;
      case -1:
      case +1:
        PORTC = 0b11111111;
        PORTDbits.RD2 = 1;
        //PORTDbits.RD3 = 0;
        break;
      case 0:
      default:
        PORTC = 0b11111111;
        PORTDbits.RD2 = 1;
        PORTDbits.RD3 = 1;
        break;
    }
  }
}
