/***************************************************************************/
/*  Name             : P.H. Seerden                                        */
/*  Description      : ADC driver for the LPC13xx / LPC11xx                */
/*                                                                         */
/*                  (C) Copyright 2012 NXP Semiconductors                  */
/*                                                                         */
/***************************************************************************/

#include <LPC13Uxx.h>                              // LPC13xx definitions
#include "adc.h"

WORD AD1result;
WORD AD2result;
BYTE ADCIntDone = 0;


#if ADC_IRQ_MODE
void ADC_IRQHandler(void) 
{
    AD1result = (LPC_ADC->DR[1]>>6) & 0x3FF;       // read ADDR1 will clear the interrupt
    AD2result = (LPC_ADC->DR[2]>>6) & 0x3FF;       // read ADDR2 will clear the interrupt
    LPC_ADC->CR &= 0xF8FFFFFF;                     // stop ADC
    ADCIntDone = 1;
}

#endif

WORD ADC_ReadCH1(void)                             // read ADC channel AD1
{
    LPC_ADC->CR |= 0x02 | (1 << 24);               // start AD1 conversion

#if ADC_IRQ_MODE
    while (!ADCIntDone) ;                          // wait until irq shows end of conversion
    ADCIntDone = 0;
    return AD1result;                              // return A/D conversion value
#else
    while (!(LPC_ADC->DR1 & ADC_DONE)) ;           // wait until end of A/D conversion
    LPC_ADC->CR &= 0xF8FFFFFF;                     // stop ADC
    return (LPC_ADC->DR1 >> 6) & 0x3FF;            // return A/D conversion value
#endif
}

WORD ADC_ReadCH2(void)                             // read ADC channel AD2
{
    LPC_ADC->CR |= 0x04 | (1 << 24);               // start AD2 conversion

#if ADC_IRQ_MODE
    while (!ADCIntDone) ;                          // wait until irq shows end of conversion
    ADCIntDone = 0;
    return AD2result;                              // return A/D conversion value
#else
    while (!(LPC_ADC->DR2 & ADC_DONE)) ;           // wait until end of A/D conversion
    LPC_ADC->CR &= 0xF8FFFFFF;                     // stop ADC
    return (LPC_ADC->DR1 >> 6) & 0x3FF;            // return A/D conversion value
#endif
}

void ADC_Init(LONG clk)
{
    LPC_SYSCON->PDRUNCFG      &= ~(1<<4);          // disable power-down bit to the ADC block
    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<13);          // enable AHB clock to the ADC
    LPC_IOCON->TMS_PIO0_12 = 2;                    // selects P0.12 = AD1
    LPC_IOCON->TDO_PIO0_13 = 2;                    // selects P0.13 = AD2

    LPC_ADC->CR = (SystemCoreClock/clk-1)<<8;      // CLKDIV = Fpclk / 1000000 - 1

#if ADC_IRQ_MODE                                   // If POLLING, no need to do the following
    NVIC_EnableIRQ(ADC_IRQn);
    LPC_ADC->INTEN = (1<<1) | (1<<2);              // enable AD1 and AD2 interrupt
#endif
}
