ADC to DAC revisited

The simple program shown previously got me started on the Arduino, but no real processing is done on the input. To do any useful processing the system will need to be better organised. The time critical processes are reading the ADC and writing the DAC, these can be done under interrupts with the rest of the processing done in the loop function. Some form of co-operative scheduing would seem to be appropriate.

As a first step, here is the same program reorganised with buffers for input from the ADC and for ouput to the DAC. Values are added and removed from these buffers under interrupt while transfer from one buffer to the other is done inside the loop function.


/**********************************************************************
* Sketch:      audioTest.ino
* Description: Audio filtering test - read ADC, process, write to DAC
*              This first test just transfers values from input to
*              output
*
* Author:      Chris Newton
*
* (C) Copyright 2015, Chris Newton.
*
**********************************************************************/

// Define the circular buffers used in these tests
#include "circularBuffer.h"

#include "DAC_routines.h"
#include "ADC_routines.h"
#include "timer_routines.h"

volatile int16_t DACMissCount; // number of times there is no data for the DAC 

void setup()
{
  Serial.begin (115200) ;
  double frequencySet = timer_setup(48000);        // setup timer
  Serial.print("Frequency set is: ");
  Serial.println(frequencySet);
  adc_setup () ;        // setup ADC
  dac_setup () ;        // setup up DAC auto-triggered at 48kHz
}

void dac_write (int val)
{
  DACC->DACC_CDR = val & 0xFFF ;
}
 
#ifdef __cplusplus
extern "C" 
{
#endif

void ADC_Handler (void)  // Read the ADC and write to the DAC,
{                        //  all done her for now
  int16_t val;
  if (ADC->ADC_ISR & ADC_ISR_EOC7)   
  {  // ensure there was an End-of-Conversion and we read the ISR reg
    val=*(ADC->ADC_CDR+7);  // get conversion result
    inputBuffer[ibFront]=(val-2048); // put in the input buffer
    ibFront=(ibFront+1)&BUFMASK;     // move pointer
    ibCount++;
  }
  if (obCount != 0)  // Check to see if there is anything in the
  {                  // output buffer 
	  val = outputBuffer[obBack] + 2048;
	  obBack = (obBack + 1)&BUFMASK;
	  obCount--;
	  dac_write(val);    // send the value to the DAC output FIFO
  }
  else
	  DACMissCount++;
}

#ifdef __cplusplus
}
#endif

void loop() 
{
  Serial.print("Starting the processing loop ...\n");
  DACMissCount = 0;
  enableADCTrigger();
  TC0ClockEnable(0);
  while(1)
  {
    int16_t val;
    int32_t imr;
    if (ibCount!=0)  // Check to see if there is input waiting
    {                // If so copy one value to the output buffer
	  imr = ADC->ADC_IMR;
	  ADC->ADC_IDR = 0x1F00FFFF;   // disable all interrupts
      val=outputBuffer[obFront]=inputBuffer[ibBack];
      ibBack=(ibBack+1)&BUFMASK;
      ibCount--;
      obFront=(obFront+1)&BUFMASK;
      obCount++;
	  ADC->ADC_IER = imr;   // re-enable interrupts
    }
	if (DACMissCount > 0)
	{
		Serial.println(DACMissCount);
		imr = ADC->ADC_IMR;
		ADC->ADC_IDR = 0x1F00FFFF;   // disable all interrupts
		DACMissCount = 0;
		ADC->ADC_IER = imr;   // re-enable interrupts
	}
  }
}

The setup routines have been moved to a separate file, they are the same as before and so are not repeated here. circularBuffer.h just defines the variables used for the circular buffers. There should be a circular buffer class, but for these first tests I wanted to avoid any overhead. I added routines to enable and disable the ADC trigger allowing the ADC to be started and stopped as required. These are in the ADC_routines file.


void enableADCTrigger(void)
{
	ADC->ADC_MR |= (ADC_MR_TRGEN);	// Set the trigger enable bit
}

void disableADCTrigger(void)
{
	ADC->ADC_MR &= (~ADC_MR_TRGEN);	// Clear the trigger enable bit
}

Update: M0XPD has built an SDR receiver using the Arduino Due (see his blog) so there is hope.

Advertisements
This entry was posted in Arduino, SDR. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s