/***********************************************/
/* Demo Program For ET-BASE PIC40/1939(ICSP)   */
/* MCU Control : PIC16F1939                    */
/*             : Run 32MHz(Internal 8MHz+4PLL) */
/* Compiler    : Hitech C Version 9.83         */
/* Function    : ADC Adjust Delay Blink LED    */
/***********************************************/
#include <htc.h>					// Required to interface with delay routines

//Config Run Internal Oscillator 32MHz (Internal 8MHz + 4xPLL)
__CONFIG(FOSC_INTOSC & 				// FOSC = Internal Oscillator
         WDTE_OFF &					// WDT disabled
         PWRTE_ON &     			// Power-up Timer Enable
         MCLRE_ON &					// MCLR pin function is MCLR
         CP_OFF &					// Code Protection Disable
         CPD_OFF &					// Data Protection Disable
         BOREN_OFF &				// Brown-out Reset Disable
         CLKOUTEN_OFF &				// CLKOUT Function Disabled
         IESO_ON &					// Internal/External Switchover mode is enabled
         FCMEN_ON &					// Fail-Safe Clock Monitor is enabled

         //Config2
         WRT_OFF &      			// Write protection off
         VCAPEN_OFF &   			// No capacitor on VCAP pin
         PLLEN_ON &					// 4x PLL enabled
         STVREN_ON &				// Stack Overflow or Underflow will cause a Reset
         BORV_HI &    				// Brown-out Reset Voltage (VBOR) set to 2.5 V       
         LVP_OFF);					// Low-voltage programming Disable        
#define  _XTAL_FREQ 	32000000	// Run 32.00 MHz

/** VR1(RA0): Analog Input ****************************************/
#define InitVR1()         	{ANSELAbits.ANSA0=1;TRISAbits.TRISA0=1;}

/** SW1(RA1): Digital Input ***************************************/
#define InitSW1()     		{ANSELAbits.ANSA1=0;TRISAbits.TRISA1=1;}
#define sw1                	PORTAbits.RA1

/** LED(RA2): Digital Output **************************************/
#define InitLED1()        	{ANSELAbits.ANSA2=0;LATAbits.LATA2=0; TRISAbits.TRISA2=0;}	
#define LED1               	LATAbits.LATA2    
#define LED1_TRIS			TRISA2
#define LED1_On()         	LED1 = 1;    
#define LED1_Off()         	LED1 = 0;
#define LED1_Toggle()      	LED1 = !LED1;

/** RS232(Hardware UART1)*******************************************/
#define UART1_TRISTx   	  	TRISCbits.TRISC6
#define UART1_Tx       	   	PORTCbits.RC6 
#define UART1_TRISRx   	   	TRISCbits.TRISC7
#define UART1_Rx       	   	PORTCbits.RC7    

const unsigned char LED_Level[8] = {0b00000001,0b00000011,0b00000111,0b00001111,
								    0b00011111,0b00111111,0b01111111,0b11111111};

/** PRIVATE PROTOTYPES *********************************************/
void ADC_Init(void);
unsigned char ADC_Convert(void);

/** demonstration of various built-in delay mechanisms */
void main(void)
{
  unsigned char delay_led;

  //Config PIC16F1939 Oscillator : Run 32MHz from Internal 8MHz + PLL(4)
  OSCCONbits.SPLLEN = 1;				// 4x PLL is always enabled
  OSCCONbits.IRCF = 14;					// Internal Oscillator Frequency = 8MHz HF
  OSCCONbits.SCS = 0;					// HF-INTOSC with PLL. Defined by the FOSC<3:0> Configuration bits, CONFIG1H<3:0>.)
  OSCTUNEbits.TUN = 0;  				// Factory-calibrated frequency 

  InitVR1(); 							// VR1 = Analog Input
  InitSW1(); 							// SW1 = Digital Input
  InitLED1();							// LED = Digital Output
  ADC_Init();							// Init ADC	
  
  //BarGraph LED Display ADC Level
  TRISD = 0b00000000;     	            // PORTD bits 7:0 are all outputs (0)

  while (1)
  {
    LED1_Toggle();						// Toggle LED    
    delay_led = ADC_Convert();			// Get ADC Result to Delay LED Blink Value
    LATD = ~LED_Level[delay_led/32];    // RD[7...0] Display BarGraph LED Level   

    if(delay_led==0)					// Minimum Delay = 1 
    { 
      delay_led=1;
    }

    //Blink Delay = [50mS] + [1..255mS]
    __delay_ms(50);						// delay for 50 millisecond
    while(delay_led--)
    {
      __delay_ms(1);
    }
  }	
}

// initialize the Analog-To-Digital converter.
void ADC_Init(void)
{ 
  ADCON1bits.ADFM = 0;					// ADC Result = Left justified
  ADCON1bits.ADCS = 6;					// ADC Conversion Clock=Fosc/64
  ADCON1bits.ADNREF = 0;				// ADC VREF- connected to internal signal, AVSS             
  ADCON1bits.ADPREF = 0;				// ADC VREF+ connected to internal signal, AVDD
 
  ADCON0bits.CHS = 0;					// Select ADC Channel = AN0
  ADCON0bits.ADON = 1;					// Start ADC 
}

// start an ADC conversion and return the 8 most-significant bits of the result
unsigned char ADC_Convert(void)
{ 
  ADCON0bits.GO = 1;              		// Start Conversion  
  while (ADCON0bits.nDONE == 1);   		// wait for it to complete
  return ADRESH;              	 		// return high byte of result
}
