bus frequency

Status
Not open for further replies.

paul_H

Member
Hello every body

I am trying to get a sine wave and triangle wave using LUT and I use one of the codes that posted in this forum and modified it.
I get it but there is something illogical when I change freq and amp!

my code is (par of it because it is too long):

Code:
//sine wave, I get a freq up to 150 kHz 
#include <DMAChannel.h>
#define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_CONT | PDB_SC_PDBIE | PDB_SC_DMAEN)

float Amplitude=2.00;
int Amplitude_100;
int Frequency=70000;
float num_triggers;
int devider;
int PDB_PERIOD;
DMAChannel dma(false);
//max_amplitude is 3.3v, 7bit(128)
// AMP_choice should be 1, 2 or 3

//////////////////////
void setup() {
Amplitude_100=(Amplitude)*100;
if (Frequency>70000&Frequency<150000)
{num_triggers=32*Frequency;
devider=F_BUS/(int)num_triggers;
 PDB_PERIOD=((int)devider-1);
/*//////////////////////////////////////////////*
 if (Frequency<70000)
{num_triggers=64*Frequency;
devider=F_BUS/(int)num_triggers;
 PDB_PERIOD=((int)devider-1);}
*//////////////////////////////////////
 
if (Amplitude_100==330) 
{ static volatile uint16_t sinetable[] = 
  { 2048,2448,2832,3186,3496,3751,3940,4057,
4096,4057,3940,3751,3496,3186,2832,2448,
2048,1648,1264,910,600,345,156,39,
0,39,156,345,600,910,1264,1648,};
dma.begin(true); // allocate the DMA channel first
  
  SIM_SCGC2 |= SIM_SCGC2_DAC0; // enable DAC clock
  DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // enable the DAC module, 3.3V reference
  // slowly ramp up to DC voltage, approx 1/4 second
  for (int16_t i=0; i<2048; i+=8) {
    *(int16_t *)&(DAC0_DAT0L) = i;
    delay(1);
  }
  
  // set the programmable delay block to trigger DMA requests
  SIM_SCGC6 |= SIM_SCGC6_PDB; // enable PDB clock
  PDB0_IDLY = 0; // interrupt delay register
  PDB0_MOD = PDB_PERIOD; // modulus register, sets period
  PDB0_SC = PDB_CONFIG | PDB_SC_LDOK; // load registers from buffers
  PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG; // reset and restart
  PDB0_CH0C1 = 0x0101; // channel n control register?
  
  dma.sourceBuffer(sinetable, sizeof(sinetable));
  dma.destination(*(volatile uint16_t *)&(DAC0_DAT0L));
  dma.triggerAtHardwareEvent(DMAMUX_SOURCE_PDB);
  dma.enable();}

else if (Amplitude_100==329)
{ static volatile uint16_t sinetable[] = 
  {2042,2440,2823,3176,3486,3740,3929,4045,
4084,4045,3929,3740,3486,3176,2823,2440,
2042,1644,1261,908,598,344,155,39,
0,39,155,344,598,908,1261,1644, };
dma.begin(true); // allocate the DMA channel first
  
  SIM_SCGC2 |= SIM_SCGC2_DAC0; // enable DAC clock
  DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // enable the DAC module, 3.3V reference
  // slowly ramp up to DC voltage, approx 1/4 second
  for (int16_t i=0; i<2048; i+=8) {
    *(int16_t *)&(DAC0_DAT0L) = i;
    delay(1);  }
  }

void loop() {
  // do nothing here
}

the code of triangular wave
Code:
#include <DMAChannel.h>
#define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_CONT | PDB_SC_PDBIE | PDB_SC_DMAEN)

float Amplitude=1.00;
int Amplitude_100;
int Frequency=150;
float num_triggers;
int devider;
int PDB_PERIOD;
DMAChannel dma(false);
//max_amplitude is 3.3v, 7bit(128)
// AMP_choice should be 1, 2 or 3


////////////////////////////////
void setup() {
Amplitude_100=(Amplitude)*100;
if (Frequency>0000)
{num_triggers=64*Frequency;
devider=F_BUS/(int)num_triggers;
 PDB_PERIOD=((int)devider-1);
/*//////////////////////////////////////////////*
 if (Frequency<70000)
{num_triggers=64*Frequency;
devider=F_BUS/(int)num_triggers;
 PDB_PERIOD=((int)devider-1);}
*//////////////////////////////////////
 
if (Amplitude_100==330) 
{ static volatile uint16_t sinetable[] = 
  {128,256,384,512,640,768,896,1024,
1152,1280,1408,1536,1664,1792,1920,2048,
2176,2304,2432,2560,2688,2816,2944,3072,
3200,3328,3456,3584,3712,3840,3968,4096,
3968,3840,3712,3584,3456,3328,3200,3072,
2944,2816,2688,2560,2432,2304,2176,2048,
1920,1792,1664,1536,1408,1280,1152,1024,
896,768,640,512,384,256,128,0,};
dma.begin(true); // allocate the DMA channel first
  
  SIM_SCGC2 |= SIM_SCGC2_DAC0; // enable DAC clock
  DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // enable the DAC module, 3.3V reference
  // slowly ramp up to DC voltage, approx 1/4 second
  for (int16_t i=0; i<2048; i+=8) {
    *(int16_t *)&(DAC0_DAT0L) = i;
    delay(1);
  }
  
  // set the programmable delay block to trigger DMA requests
  SIM_SCGC6 |= SIM_SCGC6_PDB; // enable PDB clock
  PDB0_IDLY = 0; // interrupt delay register
  PDB0_MOD = PDB_PERIOD; // modulus register, sets period
  PDB0_SC = PDB_CONFIG | PDB_SC_LDOK; // load registers from buffers
  PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG; // reset and restart
  PDB0_CH0C1 = 0x0101; // channel n control register?
  
  dma.sourceBuffer(sinetable, sizeof(sinetable));
  dma.destination(*(volatile uint16_t *)&(DAC0_DAT0L));
  dma.triggerAtHardwareEvent(DMAMUX_SOURCE_PDB);
  dma.enable();}

else if (Amplitude_100==329)
{ static volatile uint16_t sinetable[] = 
  {2042,2440,2823,3176,3486,3740,3929,4045,
4084,4045,3929,3740,3486,3176,2823,2440,
2042,1644,1261,908,598,344,155,39,
0,39,155,344,598,908,1261,1644, };
dma.begin(true); // allocate the DMA channel first
  
  SIM_SCGC2 |= SIM_SCGC2_DAC0; // enable DAC clock
  DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // enable the DAC module, 3.3V reference
  // slowly ramp up to DC voltage, approx 1/4 second
  for (int16_t i=0; i<2048; i+=8) {
    *(int16_t *)&(DAC0_DAT0L) = i;
    delay(1);
  }
  
  // set the programmable delay block to trigger DMA requests
  SIM_SCGC6 |= SIM_SCGC6_PDB; // enable PDB clock
  PDB0_IDLY = 0; // interrupt delay register
  PDB0_MOD = PDB_PERIOD; // modulus register, sets period
  PDB0_SC = PDB_CONFIG | PDB_SC_LDOK; // load registers from buffers
  PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG; // reset and restart
  PDB0_CH0C1 = 0x0101; // channel n control register?
  
  dma.sourceBuffer(sinetable, sizeof(sinetable));
  dma.destination(*(volatile uint16_t *)&(DAC0_DAT0L));
  dma.triggerAtHardwareEvent(DMAMUX_SOURCE_PDB);
  dma.enable();}


}



void loop() {
  // do nothing here
}

in this code I get a freq just up to 75KHz
and when I make FREQ=80000 I get 40000 triangular wave and 45000 triangular wave for freq=90000! it give me the half of the needed freq!
and some times -I cant remember the exact values- it give me twice FREQ value!
also I noted that the freq was changing with amp values changing!

can anyone find any interpretation for this?
please give me the answer ..

Thanks in advance
 
PDB_PERIOD is a 16bit unsigned integer. Thus, it must have a value between 1 and 65535 for correct PDB operation. That is prone to rounding errors and overflow/underflow and whatever, the higher the desired frequency is.

Add code for a Serial.println(PDB_PERIOD) after you calculate it. Take a calculator, divide F_BUS by the displayed value and then by 64 and you should get the effective frequency. Report here the discrepancies between desired and effective frequency. As soon as PDB_PERIOD becomes a small number, the granularity will naturally suffer. Adapting the size of the LUT might then help.
 
I'm pretty sure you're running into the limits of the DMA controller. At 45 kHz times 64 updates/cycle, you're configuring for nearly 2.9 million DMA events per second!

While the DMA has incredible speed moving data, the rate of DMA events is much less. Each event requires many clock cycles for the controller to set things up, including copying all the TCD fields from the hardware register into the actual DMA engine, and of course saving them back after the event.

You're seeing the expected failure, half the speed. When the DMA service takes longer than the rate you're triggering, you can expect it to respond to every other trigger.

To go faster, an approach using the DAC's FIFO will probably be needed, where the DMA loads more than 1 piece of data into the FIFO for each DMA event. I personally haven't ever touched the FIFO, but this awesome contribution from tni is on my to-do list to merge in to the audio lib. Maybe it can help you too?

https://forum.pjrc.com/threads/45271-Jitter-free-DAC-output-using-the-FIFO-and-DMA

For the DMA controller, F_CPU is what matters, not F_BUS (well, except for accessing the hardware registers, which you only do during setup). So overclocking F_CPU might help a bit too.

Might also be worth mentioning you're running the DAC pretty far beyond the analog bandwidth Freescale specifies. But those specs are with the worst case capacitive load, and they might even just be copied from earlier chips. With a light load and at room temperature, the DAC does have quite a lot more bandwidth than the datasheet implies by the setting time spec. Still, you might try testing with other loads, or plan on an amplifier if you need these higher speeds.
 
Status
Not open for further replies.
Back
Top