Hi does anyone know if this code is capable of being used for ultrasound data collection? If so, how would i go about increasing the sampling rate? I would like for it to be close to 2 samples per microsecond. I am also getting some noise in the data, but that may be because of the low sampling rate. Please let me know thanks
// adcdma
// analog A1
// could use DAC to provide input voltage A0
// http://www.atmel.com/Images/Atmel-42258-ASF-Manual-SAM-D21_AP-Note_AT07627.pdf pg 73
#define ADCPIN A1
#define HWORDS 1024
uint16_t adcbuf[HWORDS];
#include <SPI.h>
#include <SD.h>
const int chipSelect = SDCARD_SS_PIN;
typedef struct {
uint16_t btctrl;
uint16_t btcnt;
uint32_t srcaddr;
uint32_t dstaddr;
uint32_t descaddr;
} dmacdescriptor ;
volatile dmacdescriptor wrb[12] attribute ((aligned (16)));
dmacdescriptor descriptor_section[12] attribute ((aligned (16)));
dmacdescriptor descriptor attribute ((aligned (16)));
static uint32_t chnl = 0; // DMA channel
volatile uint32_t dmadone;
void DMAC_Handler() {
// interrupts DMAC_CHINTENCLR_TERR DMAC_CHINTENCLR_TCMPL DMAC_CHINTENCLR_SUSP
uint8_t active_channel;
// disable irqs ?
__disable_irq();
active_channel = DMAC->INTPEND.reg & DMAC_INTPEND_ID_Msk; // get channel number
DMAC->CHID.reg = DMAC_CHID_ID(active_channel);
dmadone = DMAC->CHINTFLAG.reg;
DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL; // clear
DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_SUSP;
__enable_irq();
}
void dma_init() {
// probably on by default
PM->AHBMASK.reg |= PM_AHBMASK_DMAC ;
PM->APBBMASK.reg |= PM_APBBMASK_DMAC ;
NVIC_EnableIRQ( DMAC_IRQn ) ;
DMAC->BASEADDR.reg = (uint32_t)descriptor_section;
DMAC->WRBADDR.reg = (uint32_t)wrb;
DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xf);
}
void adc_dma(void *rxdata, size_t hwords) {
uint32_t temp_CHCTRLB_reg;
DMAC->CHID.reg = DMAC_CHID_ID(chnl);
DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE;
DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST;
DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << chnl));
temp_CHCTRLB_reg = DMAC_CHCTRLB_LVL(0) |
DMAC_CHCTRLB_TRIGSRC(ADC_DMAC_ID_RESRDY) | DMAC_CHCTRLB_TRIGACT_BEAT;
DMAC->CHCTRLB.reg = temp_CHCTRLB_reg;
DMAC->CHINTENSET.reg = DMAC_CHINTENSET_MASK ; // enable all 3 interrupts
dmadone = 0;
descriptor.descaddr = 0;
descriptor.srcaddr = (uint32_t) &ADC->RESULT.reg;
descriptor.btcnt = hwords;
descriptor.dstaddr = (uint32_t)rxdata + hwords*2; // end address
descriptor.btctrl = DMAC_BTCTRL_BEATSIZE_HWORD | DMAC_BTCTRL_DSTINC | DMAC_BTCTRL_VALID;
memcpy(&descriptor_section[chnl],&descriptor, sizeof(dmacdescriptor));
// start channel
DMAC->CHID.reg = DMAC_CHID_ID(chnl);
DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
}
static inline void ADCsync() attribute((always_inline, unused));
static void ADCsync() {
while (ADC->STATUS.bit.SYNCBUSY == 1); //Just wait till the ADC is free
}
void adc_init(){
analogRead(ADCPIN); // do some pin init pinPeripheral()
ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC
ADCsync();
//ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC0_Val; // 2.2297 V Supply VDDANA
//ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain select as 1X
ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val; // default
ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val;
ADCsync(); // ref 31.6.16
ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ADCPIN].ulADCChannelNumber;
ADCsync();
ADC->AVGCTRL.reg = 0x00 ; //no averaging
ADC->SAMPCTRL.reg = 0x00; ; //sample length in 1/2 CLK_ADC cycles
ADCsync();
ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV16 | ADC_CTRLB_FREERUN | ADC_CTRLB_RESSEL_10BIT;
ADCsync();
ADC->CTRLA.bit.ENABLE = 0x01;
ADCsync();
}
void setup(){
Serial.begin(9600);
analogWriteResolution(10);
analogWrite(A1,64); // test with DAC
adc_init();
dma_init();
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
while (1);
}
Serial.println("card initialized.");
}
}
void loop() {
uint32_t t;
t = micros();
adc_dma(adcbuf,HWORDS);
while(!dmadone); // await DMA done isr
t = micros() - t;
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.txt", FILE_WRITE);
// if the file is available, write to it:
if (dataFile) {
dataFile.print(t);
dataFile.print(" us ");
dataFile.println(adcbuf[0]);
dataFile.close();
// print to the serial port too:
Serial.print(t);
Serial.print(" us ");
Serial.println(adcbuf[0]);
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}
}