Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 16 of 16

Thread: TMR4 and DMA

  1. #1
    Junior Member DM5SG's Avatar
    Join Date
    Feb 2021
    Posts
    7

    TMR4 and DMA

    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_W RITE3_CMPLD1);
    dma.interruptAtHalf();
    dma.interruptAtCompletion();
    dma.attachInterrupt(myisr);
    dma.enable();

    pinMode(LED_BUILTIN, OUTPUT);
    }

    void loop()
    {
    }

  2. #2
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,280
    Take a look here: https://github.com/FrankBoesing/Teen...ut_fm.cpp#L159

    Similar to yours... uses the timer @ audio sampling rate and uses the triggered dma to write to the video pll.

    It's an FM Transmitter, Stereo and RDS. I think you're trying something similar?
    Last edited by Frank B; 02-23-2021 at 04:16 PM.

  3. #3
    Junior Member DM5SG's Avatar
    Join Date
    Feb 2021
    Posts
    7
    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.

  4. #4
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,280
    Quote Originally Posted by DM5SG View Post
    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...?

  5. #5
    Junior Member DM5SG's Avatar
    Join Date
    Feb 2021
    Posts
    7
    to Frank - am working on an EER (envelope elimination and restauration) transmitter project as part of a sdr project

  6. #6
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,280
    Sounds interesting!

  7. #7
    Junior Member DM5SG's Avatar
    Join Date
    Feb 2021
    Posts
    7
    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.

  8. #8
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,280
    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 by Frank B; 02-24-2021 at 11:49 AM.

  9. #9
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,280
    I'd check your desired frequency with a scope or frequency counter.

  10. #10
    Junior Member DM5SG's Avatar
    Join Date
    Feb 2021
    Posts
    7
    thanks Frank - my little program was all about test of functionalty not absolut numbers
    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

  11. #11
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,280
    Quote Originally Posted by DM5SG View Post
    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.

  12. #12
    Junior Member DM5SG's Avatar
    Join Date
    Feb 2021
    Posts
    7
    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 nhe von dresden

  13. #13
    Junior Member DM5SG's Avatar
    Join Date
    Feb 2021
    Posts
    7
    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)

  14. #14
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,280
    Quote Originally Posted by DM5SG View Post
    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

  15. #15
    Senior Member DD4WH's Avatar
    Join Date
    Oct 2015
    Location
    Central Europe
    Posts
    654
    @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 :-)

  16. #16
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,280
    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 by Frank B; 02-25-2021 at 07:43 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •