TMR4 and DMA

Status
Not open for further replies.

DM5SG

Member
iam trying to get TMR4 to work as trigger source for dma transfer. i spend quiete some time so far but but no result as expacted.
interrupts are fired at a constant rate but arnt as predicted. changing samp_timer value or even TMR_CTRL_PCS(x) x=8..15 dosent effect the interupt rate.
i have scrached my head of but cant find the reason. even routing the timer output through XBAR to edge trigger DMA request dosent make a difference

#include <Arduino.h>
#include <DMAChannel.h>

#define buffer_len 128
#define sfreq 44100
#define samp_timer F_BUS_ACTUAL / sfreq

DMAChannel dma;

DMAMEM static volatile __attribute__((aligned(32))) int tx_buffer[buffer_len];
int volatile cnt = 0;

void myisr()
{
dma.clearInterrupt();
if (cnt++ > sfreq)
{
cnt = 0;
digitalToggle(LED_BUILTIN);
}
}

void setup()
{
// place test values
for (int x = 0; x < buffer_len; x++)
tx_buffer[x] = 10000 + x * 25;

//QuadTimer 4 channel 3
TMR4_ENBL &= ~(1 << 3); //Disable
TMR4_SCTRL3 = 0;
TMR4_LOAD3 = 0;
TMR4_CNTR3 = 0;
TMR4_COMP13 = samp_timer;
TMR4_CMPLD13 = samp_timer;
TMR4_DMA3 = TMR_DMA_CMPLD1DE;
TMR4_CSCTRL3 = TMR_CSCTRL_CL1(1);
TMR4_CTRL3 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8) | TMR_CTRL_LENGTH;
TMR4_ENBL |= (1 << 3); //Enable

dma.sourceBuffer(tx_buffer, sizeof(tx_buffer));
dma.destination(CCM_ANALOG_PLL_VIDEO_NUM);
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_QTIMER4_WRITE3_CMPLD1);
dma.interruptAtHalf();
dma.interruptAtCompletion();
dma.attachInterrupt(myisr);
dma.enable();

pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
}
 
thanks a lot .. but its actually the same same approch .. and it doesnt work for an unknown reason. i spend already plenty of time studying the datasheet.
but so far i couldnt figure out why changes in TMR4 registers like CMPLD13 value of TMR_CTRL_PCS(x) setings doenst seems to effect anything at all.
the led used in the isr always blinks at the same rate.
 
thanks a lot .. but its actually the same same approch .. and it doesnt work for an unknown reason.
No, my code works.
Maybe do a copy&paste.. or try the transmitter as a whole.

May I ask what you're tryong to archive? Must be something with frequency modulation, too...?
 
to Frank - am working on an EER (envelope elimination and restauration) transmitter project as part of a sdr project
 
i finally got it working as it thought to

Code:
#include <Arduino.h>
#include <DMAChannel.h>

#define buffer_len 128
#define sfreq 44100
#define samp_timer F_BUS_ACTUAL / sfreq

extern "C" void xbar_connect(unsigned int input, unsigned int output);

DMAChannel dma;

DMAMEM static volatile __attribute__((aligned(32))) int tx_buffer[buffer_len];
int volatile cnt = 0;

void modulator()
{
  dma.clearInterrupt();
  if (cnt++ > sfreq / buffer_len)
  {
    cnt = 0;
    digitalToggle(LED_BUILTIN);
  }
}

void setup()
{

  // place test values
  for (int x = 0; x < buffer_len; x++)
    tx_buffer[x] = 5000 + x + 25;

  TMR4_ENBL &= ~(1 << 3); //Disable
  TMR4_SCTRL3 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE;
  TMR4_CSCTRL3 = TMR_CSCTRL_CL1(1);
  TMR4_CNTR3 = 0;
  TMR4_LOAD3 = 0;
  TMR4_COMP13 = samp_timer;
  TMR4_CMPLD13 = samp_timer;
  TMR4_CTRL3 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8) | TMR_CTRL_LENGTH | TMR_CTRL_OUTMODE(3);
  TMR4_DMA3 = TMR_DMA_CMPLD1DE;
  TMR4_CNTR3 = 0;

  //route the timer output through XBAR to edge trigger DMA request
  CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON); //enable XBAR
  xbar_connect(XBARA1_IN_QTIMER4_TIMER3, XBARA1_OUT_DMA_CH_MUX_REQ30);
  XBARA1_CTRL0 = XBARA_CTRL_EDGE0(1) | XBARA_CTRL_DEN0;

  dma.sourceBuffer(tx_buffer, sizeof(tx_buffer));
  dma.destination(CCM_ANALOG_PLL_VIDEO_NUM);
  dma.triggerAtHardwareEvent(DMAMUX_SOURCE_XBAR1_0);
  dma.interruptAtHalf();
  dma.interruptAtCompletion();
  dma.attachInterrupt(modulator);
  dma.enable();

  TMR4_ENBL |= (1 << 3); //Enable

  pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
  // put your main code here, to run repeatedly:
}

to Frank - it migth be a good idea to set XBARA_CTRL_EDGE0 to 1 wich means fire on rising edge. you used 3 and fire dma request on rsing and falling edge of TMR4_CH3 out.
 
You don't want 44100Hz... there is no divisor for it.
Try 44117,64706Hz (there is no audible difference)

to Frank - it migth be a good idea to set XBARA_CTRL_EDGE0 to 1 wich means fire on rising edge. you used 3 and fire dma request on rsing and falling edge of TMR4_CH3 out.

As said above: It works. As it is :) I'm aware that it fires twice.
 
Last edited:
thanks Frank - my little program was all about test of functionalty not absolut numbers :cool:
by the way .. TMR4_CSCTRL3 can be set to "0" since there isnt a real output to any pin
i also saw you use .. static const unsigned ndiv = 0xffffff as PLL denominator value
according "MCUXpresso Config Tool" from NXP .. denominator value shouldnt exeed 960000
 
i also saw you use .. static const unsigned ndiv = 0xffffff as PLL denominator value
according "MCUXpresso Config Tool" from NXP .. denominator value shouldnt exeed 960000

Thanks!
The reference manual says not any word about this. (only that it can be 29 (or was it 30?) Bits wide) - I'll test if it makes any difference. As said.. the program works .. so i wonder if there is a difference :)
But thank you for the hint.
 
the datasheet is very vague in many respects. its a pure datasheet with almost none reference to practicle use.
the MCUXpresso Config Tool gives at least some ideas about coherences, limits and restrictions
Gruß aus der nähe von dresden
 
as follow the limits:

PLL5 - DIV = 27..54, NUM max 960000, DENOM max 960000, PLL5_POST_DIV = 1,2,4, VIDEO_DIV = 1,2,4
SAIx_PRED = 1..8
SAIx_PODF = 1..64
vco = must be in range 650MHz - 1.3GHz
xtal = must be 24MHz

vco = (DIV + NUM/DENON) * xtal
Fout = vco / (PLL5_POST_DIV * VIDEO_DIV * SAIx_PRED * SAIx_PODF)
 
as follow the limits:

PLL5 - DIV = 27..54, NUM max 960000, DENOM max 960000, PLL5_POST_DIV = 1,2,4, VIDEO_DIV = 1,2,4
SAIx_PRED = 1..8
SAIx_PODF = 1..64
vco = must be in range 650MHz - 1.3GHz
xtal = must be 24MHz

vco = (DIV + NUM/DENON) * xtal
Fout = vco / (PLL5_POST_DIV * VIDEO_DIV * SAIx_PRED * SAIx_PODF)

Yes, thats the same what the Reference manual says - everything but the max 960000.
I'll update that value. Thanx :)
 
@DM5SG: EER transmission/polar transmitter is exactly the idea that came to my mind when FrankB wrote that excellent FM transmitter code! Would be nice to hear more on your developments! Maybe it would be worth coupling Teensy Convolution SDR Rx with an EER Tx approach on the Teensy 4.0/4.1 ? You probably already know about the µSDX polar transmitter approach: https://github.com/threeme3/QCX-SSB
73 aus Dresden von Frank DD4WH :)
 
I've patched the denom value,
and added a search for the divs - now, more frequencies are working (if not all - tests needed)

Edit: really amazing that the PLLs work with up to 1.3GHz - tell this an AVR user..
 
Last edited:
Status
Not open for further replies.
Back
Top