#include <pic.h> 
#include "serial.h" 
#include "globals.h" 

#undef ADCDEBUG 


void adc_init() {
   ADCON0   =  0b01000000;    // Fosc/8, channel 0, A/D off
   ADCON1   =  0x80;          // right justified, all analog, vref+ = vdd, vref- = vss

   ADIE     =  0;             // no A/D interrupt since A/D is usually fast enough anyway.
}   

/* 
 * function blocks until it is able to return a valid A/D conversion
 * does not use interrupts
 * ADCON1 must be set externally to choose source vdd and vss, etc.
 * Fosc must be set externally for ADCON0, only channel is chosen automatically here.
 */
unsigned int get_ad_immediate(unsigned char channel) {
   unsigned int adresult;
   unsigned int timewaster;
   
   ADIE     =  0;             // no A/D interrupts for now.
   ADIF     =  0;

   ADRESH   =  0x00;
   ADRESL   =  0x00;

   ADCON0 = ADCON0 & 0b11000000;    // clear channel selection

   switch(channel) {
      case 0:  RA0 = 1;
               break;
      case 1:  ADCON0 = ADCON0 | 0b00001000;
               RA1 = 1;
               break;
      case 2:  ADCON0 = ADCON0 | 0b00010000;
               RA2 = 1;
               break;
      case 3:  ADCON0 = ADCON0 | 0b00011000;
               RA3 = 1;
               break;
      case 4:  ADCON0 = ADCON0 | 0b00100000;
               RA5 = 1;
               break;
      case 5:  ADCON0 = ADCON0 | 0b00101000;
               RE0 = 1;
               break;
      case 6:  ADCON0 = ADCON0 | 0b00110000;
               RE1 = 1;
               break;
      case 7:  ADCON0 = ADCON0 | 0b00111000;
               RE2 = 1;
   }
   
   ADON     =  1;
   for (timewaster = 0; timewaster < 50; timewaster++);  // waste 50 us for charging cap
   ADGO     =  1;

   for(;;) {
#ifdef ADCDEBUG 
      putch('a');
#endif 
      if (ADIF) {
         adresult  = ADRESH;
         adresult  = adresult << 8;
         adresult += ADRESL;
         ADIF = 0;
         break;
      }
   }
   ADON     =  0;
#ifdef ADCDEBUG 
   putdec(adresult, 'h');
#endif 

   return adresult;
}

#ifdef ADCDEBUG 
main() {
   serial_init();
   setup_interrupts();
   ad_init();
   putdec(get_ad_immediate(0), 'h');
   putdec(get_ad_immediate(1), 'h');
   putdec(get_ad_immediate(2), 'h');
}
#endif