////////////////////////////////////////////////////////////////////////////////
//                         MAX144 2-Channel ADC
//                         Hardware SPI Example
//
// Filename     : 18F2550 MAX144 SPI.c
// Programmer   : Steven Cholewiak, www.semifluid.com
// Version      : Version 1.0 - 04/23/2006
// Remarks      : This example compares the read speed for a hardware SPI
//                implimentation with the MAX144 to the internal ADC of the PIC.
//                It is important to use the same analog source for all three
//                analog inputs to gauge the accuracy of each.  Please note that
//                the SETUP_SPI() command disables the internal USART, so it is
//                necessary to restart the PIC to re-upload the source.
//                
//                More information on the circuit can be found at:
//                http://www.semifluid.com/PIC18F2550_MAX144.html
////////////////////////////////////////////////////////////////////////////////

/*
PIC18F2550 Pinout

                  --------------
    MCLR Pullup -|1           28|-
  Analog Source -|2           27|-
                -|3           26|-
                -|4           25|-
                -|5           24|-
                -|6           23|--------------------------
                -|7           22|---------------------     |
         Ground -|8           21|----------------     |    |
           OSC1 -|9           20|- +5V           |    |    |
           OSC2 -|10          19|- Ground        |    |    |
                -|11          18|- RS232 RX      |    |    |
                -|12          17|- RS232 TX      |    |    |
                -|13          16|-               |    |    |
                -|14          15|-               |    |    |
                  --------------                 |    |    |
                                                 |    |    |
                                                 |    |    |
                  --------------                 |    |    |
            +5V -|1       SCLK 8|----------------|----     |
Analog Source 1 -|2 CH0   DOUT 7|----------------          |
Analog Source 2 -|3 CH1     CS 6|--------------------------
         Ground -|4        REF 5|- +5V
                  --------------
*/

#include <18F2550.h>
#device ADC=10
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)

#build(reset=0x1, interrupt=0x8)          // Necessary for Bootloader
#ORG 0x0F00,0x0FFF {}                     // Necessary for Bootloader

#use rs232(stream=PC, baud=115200, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define MAX144_DOUT    PIN_B0
#define MAX144_SCLK    PIN_B1
#define MAX144_CS      PIN_B2

#inline
int16 readMAX144( int1 theChannel ) {
   int16 tempVolt;

   OUTPUT_LOW(MAX144_CS);
   WHILE (!INPUT(MAX144_DOUT));
   tempVolt = make16(spi_read(0),spi_read(0));
   if (BIT_TEST(tempVolt,12)!=theChannel) {
      OUTPUT_HIGH(MAX144_CS);
      #ASM nop #ENDASM
      OUTPUT_LOW(MAX144_CS);
      WHILE (!INPUT(MAX144_DOUT));
      tempVolt = make16(spi_read(0),spi_read(0));
   }
   OUTPUT_HIGH(MAX144_CS);

   tempVolt = (tempVolt << 4) >> 4;
   return tempVolt;
}

void main() {
   int8 theCount;
   int16 tempVolt, period, i;
   float tempFloat;
   int16 voltageMeasure[512];

   SETUP_ADC_PORTS(AN0);
   SETUP_ADC(ADC_CLOCK_DIV_64);
   SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_1);
   SETUP_TIMER_1(T1_DISABLED);
   SETUP_TIMER_2(T2_DISABLED, 127, 1);
   SETUP_TIMER_3(T3_INTERNAL | T3_DIV_BY_1);
   SETUP_CCP1(CCP_OFF);
   SETUP_CCP2(CCP_OFF);
   SETUP_SPI(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 | SPI_SS_DISABLED);

   OUTPUT_HIGH(MAX144_CS);
   OUTPUT_LOW(MAX144_SCLK);

   set_adc_channel(0);
   delay_ms(1);

   i = 0;

   delay_ms(500);
   printf("OK\n\r");
   delay_ms(200);

   while (TRUE) {
      set_timer3(0);
      tempVolt = readMAX144(0);
      voltageMeasure[i] = tempVolt;
      period = get_timer3();   // 1000/((clock/4)/1) for ms

      tempFloat = (float) 5/4096;
      tempFloat = tempVolt * tempFloat;
      printf("%lu\n\rMAX144 CH0: %lu, %f, %lu\n\r", i, tempVolt, tempFloat, period);

      set_timer3(0);
      tempVolt = readMAX144(1);
      voltageMeasure[i] = tempVolt;
      period = get_timer3();   // 1000/((clock/4)/1) for ms

      tempFloat = (float) 5/4096;
      tempFloat = tempVolt * tempFloat;
      printf("MAX144 CH1: %lu, %f, %lu\n\r", tempVolt, tempFloat, period);

      set_timer3(0);
      tempVolt = READ_ADC();
      voltageMeasure[i] = tempVolt;
      period = get_timer3();   // 1000/((clock/4)/1) for ms

      tempFloat = (float) 5/1024;
      tempFloat = tempVolt * tempFloat;
      printf("ADC: %lu, %f, %lu\n\r\n\r", tempVolt, tempFloat, period);

      i++;
      if (i >= 512) i=0;

      delay_ms(1000);
   }
}
