#if defined(__dsPIC33E__)
#include "p33exxxx.h"
#elif defined(__PIC24E__)
#include "p24exxxx.h"
#endif
#include "hardware.h"
#include <libpic30.h> // for __delay_us FCY must be defined!
#include "adc1.h"
// User Defines
#define NUMSAMP 256
//int BufferA[NUMSAMP] __attribute__((space(dma)));
//int BufferB[NUMSAMP] __attribute__((space(dma)));
#ifdef _HAS_DMA_
__eds__ int BufferA[NUMSAMP] __attribute__((eds,space(dma)));
__eds__ int BufferB[NUMSAMP] __attribute__((eds,space(dma)));
#else
int BufferA[NUMSAMP] __attribute__((space(xmemory)));
int BufferB[NUMSAMP] __attribute__((space(xmemory)));
#endif
void ProcessADCSamples(__eds__ int * AdcBuffer);
//Functions:
//initAdc1() is used to configure A/D to convert ANchannel in 12bit mode
//at 500Ksamples/second throughput rate. ADC clock is configured at Tad=150
// assuming an FCY of 60MIPS
void initAdc1(int ANchannel)
{
AD1CON1bits.FORM = 0; // Data Output Format: integer
AD1CON1bits.SSRC = 7; // Interan Counter (SAMC) ends sampling and starts convertion
AD1CON1bits.ASAM = 0; // ADC Sample Control: Sampling begins immediately after conversion
AD1CON1bits.AD12B = 1; // 12-bit ADC operation
AD1CON2bits.CHPS = 0; // Converts CH0
AD1CON3bits.ADRC=0; // ADC Clock is derived from Systems Clock
AD1CON3bits.SAMC=2; // Auto Sample Time = 0*Tad
AD1CON3bits.ADCS=5; // 12 bit ADC Conversion Clock Tad=Tcy*(ADCS+1)= (1/60M)*4 = 150nSec approx
// ADC Conversion Time for 10-bit Tc=12*Tad = 900ns (1.1MHz)
// ADC Conversion Time for 12-bit Tc=14*Tad = 2000ns (500Ksamples/sec)
AD1CON1bits.ADDMABM = 1; // DMA buffers are built in conversion order mode
AD1CON2bits.SMPI = 0; // SMPI must be 0
AD1CON4bits.ADDMAEN = 1; // Converts in ADC1BUF0
//AD1CHS0/AD1CHS123: A/D Input Select Register
AD1CHS0bits.CH0SA=ANchannel; // MUXA +ve input selection (AIN0) for CH0 AN24 RE0
AD1CHS0bits.CH0NA=0; // MUXA -ve input selection (Vref-) for CH0
//AD1CHS123bits.CH123SA=0; // MUXA +ve input selection (AIN0) for CH1
//AD1CHS123bits.CH123NA=0; // MUXA -ve input selection (Vref-) for CH1
IFS0bits.AD1IF = 0; // Clear the A/D interrupt flag bit
IEC0bits.AD1IE = 0; // Do Not Enable A/D interrupt
AD1CON1bits.ADON = 1; // Turn on the A/D converter
__delay_us(20); // Delay for 20uS to allow ADC to settle (25nS * 0x320 = 20uS)
AD1CON1bits.ASAM = 1; // Sampling begins immediately after last conversion. SAMP bit is auto-set
}
// DMA0 configuration
// Direction: Read from peripheral address 0-x300 (ADC1BUF0) and write to DMA RAM
// AMODE: Register indirect with post increment
// MODE: Continuous, Ping-Pong Mode
// IRQ: ADC Interrupt
// ADC stores results stored alternatively between DMA_BASE[0]/DMA_BASE[16] on every 16th DMA request
void initDma0(void)
{
DMA0CONbits.AMODE = 0; // Configure DMA for Register indirect with post increment
DMA0CONbits.MODE = 2; // Configure DMA for Continuous Ping-Pong mode
DMA0PAD=(int)&ADC1BUF0;
DMA0CNT=(NUMSAMP-1);
DMA0REQ=13;
#ifdef _HAS_DMA_
DMA0STAL = __builtin_dmaoffset(&BufferA);
DMA0STAH = __builtin_dmapage(&BufferA);
DMA0STBL = __builtin_dmaoffset(&BufferB);
DMA0STBH = __builtin_dmapage(&BufferB);
#else
DMA0STAL = (unsigned int)&BufferA;
DMA0STAH = (unsigned int)&BufferA;
DMA0STBL = (unsigned int)&BufferB;
DMA0STBH = (unsigned int)&BufferB;
#endif
IFS0bits.DMA0IF = 0; //Clear the DMA interrupt flag bit
IEC0bits.DMA0IE = 1; //Set the DMA interrupt enable bit
DMA0CONbits.CHEN=1;
}
/*=============================================================================
_DMA0Interrupt(): ISR name is chosen from the device linker script.
=============================================================================*/
unsigned int DmaBuffer = 0;
void __attribute__((interrupt, auto_psv)) _DMA0Interrupt(void)
{
if(DmaBuffer == 0)
{
ProcessADCSamples(BufferA);
}
else
{
ProcessADCSamples(BufferB);
}
DmaBuffer ^= 1;
static int count=0;
if(count++ > 100) {LED1=!LED1; count=0; }
// __builtin_btg((unsigned int *)&LATA, 6); // Toggle RA6
IFS0bits.DMA0IF = 0; //Clear the DMA0 Interrupt Flag
}
int ADCdata;
void ProcessADCSamples(__eds__ int * AdcBuffer)
{
/* Do something with ADC Samples */
ADCdata=AdcBuffer[0];
}