#include <p24fxxxx.h>
#include "adc.h"
#include "spi2.h"

/** Number of input channels on the ADC */
#define ADC_MAX_CHANNELS 8

/** Start bit of the control byte */
#define ADC_CON_S      0b10000000
/** Channel select MSB of the control byte */
#define ADC_CON_A2     0b01000000
/** Channel select middle bit of the control byte */
#define ADC_CON_A1     0b00100000
/** Channel select LSB of the control byte */
#define ADC_CON_A0 4   0b00010000
/** Single-Ended/Differential Select Bit of the control byte */
#define ADC_CON_SGLDIF 0b00000100
/** Power-down mode MSB of the control byte */
#define ADC_CON_PD1    0b00000010
/** Power-down mode LSB of the control byte */
#define ADC_CON_PD0    0b00000001

#define ADC_TYPE_WORD   0
#define ADC_TYPE_VOLT   1
#define ADC_TYPE_ACTUAL 2

double adcRead(unsigned int channel) {
    /* Return value */
    double ret = 0.0;
    
    /* Control byte for the ADC */
    unsigned int ctrlByte = 0;
    
    unsigned int input1, input2, input3;
    unsigned int output1, output2, output3;
    
    if (channel >= 8) {
        return ret;
    }
    
    /* Construct control byte */
    ctrlByte |= ADC_CON_S |      /* Asserts start bit */
                ADC_CON_SGLDIF | /* Use single-ended mode (measurements
                                    relative to COM */
                ADC_CON_PD1;     /* PD = 10; internal clock mode */
    
    ctrlByte |= channel << 6;    /* Shift the channel number into the byte */

    SPI2STATbits.SPIROV = 1;
    Nop();
    
    spiReadWrite2(ctrlByte); /* Send control byte */
    Nop();                   /* Wait a cycle */
    input1 = spiReadWrite2(0);
    input2 = spiReadWrite2(0);
    input3 = spiReadWrite2(0);
    
    output1 = input1;
    output1 <<= 8;
    output1 |= input2 & 0xFF;
    
    return 0.0;   
}