Arduino Forum

Products => Arduino Due => Topic started by: paxtakor22 on Mar 01, 2019, 04:33 pm

Title: 5 MHz signal from Due
Post by: paxtakor22 on Mar 01, 2019, 04:33 pm
Hello,

I have a device that I'm trying to communicate with. I have to send 26 command bits along with a clock at 5 MHz to this device in order to get a response back. I wrote some code for the Due that will generate two signals that are close to 5 MHz (about 4.94 MHz) which i believe might be close enough. I am using PWM mode to drive these two signals. One signal is the clock the second is the data.

Here is what i want:

Image of what i want (https://imgur.com/qfXiYqn)


Here is the code i have so far:

Code: [Select]


void setup ()

{

  PMC->PMC_PCER1 |= PMC_PCER1_PID36;

  REG_PWM_DIS = PWM_DIS_CHID0|PWM_DIS_CHID2; // disable both pins

  REG_PWM_CLK = PWM_CLK_PREA(0)|PWM_CLK_DIVA(1);

  REG_PIOC_PDR |= PIO_PDR_P3; // pin 35

  REG_PIOC_ABSR |= PIO_PC3B_PWMH0; // pin 35

  REG_PWM_CMR0 = PWM_CMR_CPRE_CLKA;    

  REG_PWM_CPRD0 = 1;                 //vs 16                      

  REG_PWM_CDTY0 = 0;//100%      //vs 8

  REG_PIOC_PDR |= PIO_PDR_P7; // pin 39

  REG_PIOC_ABSR |= PIO_PC7B_PWMH2; // pin 39  

  REG_PWM_CMR2 = PWM_CMR_CPRE_CLKA;    

  REG_PWM_CPRD2 = 16;                      //vs 1      

  REG_PWM_CDTY2 = 8; // 50%             //vs 0

  //REG_PWM_SCM = 5;

  //REG_PWM_ENA = PWM_ENA_CHID0|PWM_ENA_CHID2;

}


int cnt = 26;

void loop()
{
  while(1)
  {
    while(cnt)
    {
      PWM->PWM_ENA = 5;//PWM_ENA_CHID0|PWM_ENA_CHID2;
      PWM->PWM_DIS = 5;//PWM_DIS_CHID0|PWM_DIS_CHID2;
      --cnt;
    }
    delay(1000);
    cnt = 26;
  }
}





Questions:

1. Is there a better way to do this?

2. If i swap the two PWM pins,

ie

Code: [Select]


REG_PWM_CPRD2 = 1;
REG_PWM_CDTY2 = 0;

and

REG_PWM_CPRD0 = 16;
REG_PWM_CDTY0 = 8;



my frequency drops to ~3MHz, why does that happen?

3. Are there any more optimization techniques i can use to make this faster?


Thank You.

Title: Re: 5 MHz signal from Due
Post by: ard_newbie on Mar 01, 2019, 05:25 pm
Without  altering the chip frequency (the default DUE frequency is 84 MHz), the closest square wave frequency to 5MHz you can generate is 4.94 MHz.

Question: is a 1.2 % error acceptable ?
Title: Re: 5 MHz signal from Due
Post by: paxtakor22 on Mar 01, 2019, 06:41 pm
Without  altering the chip frequency (the default DUE frequency is 84 MHz), the closest square wave frequency to 5MHz you can generate is 4.94 MHz.

Question: is a 1.2 % error acceptable ?
Yes, it is acceptable. How can i alter the frequency though? Would i have to solder on a new oscillator?
Title: Re: 5 MHz signal from Due
Post by: ard_newbie on Mar 01, 2019, 06:57 pm
There are on-chip RC oscillators (4,8,12 MHz). I didn't try out yet to switch from the Main 12 MHz oscillator to the 8 MHz on-chip RC oscillator, but this could (theoritecally) give a 80 Mhz frequency, and therefore you could output 5 MHz. Note that the 8 and 12 MHz on-chip RC oscillators are calibrated in factory (see page 546, Sam3x datasheet).

If I have some time this WE, I will try out to find a code for that.

Anyway, since 4.94MHz is acceptable, you can use a Timer Counter to output a square wave with this frequency, and trigger an interrupt at each end of a period to decide whether you set(1)or clear(0) a particuliar pin (see your drawing).

For the 5 MHz clock, do you need a nice square wave (PWM with a 50%duty cycle), or another constant duty cycle would fit too ?
Title: Re: 5 MHz signal from Due
Post by: paxtakor22 on Mar 01, 2019, 07:12 pm
There are on-chip RC oscillators (4,8,12 MHz). I didn't try out yet to switch from the Main 12 MHz oscillator to the 8 MHz on-chip RC oscillator, but this could (theoritecally) give a 80 Mhz frequency, and therefore you could output 5 MHz. Note that the 8 and 12 MHz on-chip RC oscillators are calibrated in factory (see page 546, Sam3x datasheet).

If I have some time this WE, I will try out to find a code for that.

Anyway, since 4.94MHz is acceptable, you can use a Timer Counter to output a square wave with this frequency, and trigger an interrupt at each end of a period to decide whether you set(1)or clear(0) a particuliar pin (see your drawing).

For the 5 MHz clock, do you need a nice square wave (PWM with a 50%duty cycle), or another constant duty cycle would fit too ?
I'm hoping it is acceptable because i havent tried it out yet. Yes the clock signal has to be a 50% duty cycle square wave. I didnt know the Due had on-chip oscillators. Ill try to find more information about that.

Could you point me to any examples that use an interrupt in a similar manner?

Thank you!
Title: Re: 5 MHz signal from Due
Post by: ard_newbie on Mar 02, 2019, 10:13 am

An example sketch to output a quasi square wave at 4.94 MHz and set or clear a pin every 4.94 MHz (not tested though):

Code: [Select]

/******************************************************************************/
/*                         PWMH0 ~ 5MHz                                        */
/******************************************************************************/

void setup() {

  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                   // PWM power ON

  PWM->PWM_CLK = PWM_CLK_PREB(0) | PWM_CLK_DIVB(1);    // select Frequency for clock B: Mck = 84 MHz

  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKB;      // The period is left aligned, clock source as CLKB on channel 0
  PWM->PWM_CH_NUM[0].PWM_CPRD = 17;                    // Set the PWM frequency 84 MHz/PWM_CPRD = 4941176 Hz

  PWM->PWM_CMP[0].PWM_CMPM = PWM_CMPM_CEN;
  PWM->PWM_CMP[0].PWM_CMPV = PWM_CMPV_CV(8);

  PWM->PWM_IER1 = PWM_IER1_CHID0;                      // Interrupt on PWM Channel 0 counter match (CPRD)
  PWM->PWM_IER2 = PWM_IER2_CMPM0;                      // Interrupt on CMPV match (CV)
  NVIC_EnableIRQ(PWM_IRQn);                            // Enable interrupt

  PWM->PWM_ENA = PWM_ENA_CHID0;                        // Enable PWM channel 0
}

void loop() {

}

// The Handler is triggered at 2*4.94 MHz
void PWM_Handler() {

  // End of the 4.94 Mhz period
  if (PWM->PWM_ISR1 & PWM_ISR1_CHID0)
  {
   
    // toggle the clock pin e.g.: PIOB->PIO_ODSR ^= PIO_ODSR_P27;
    // Set or clear the data pin with PIO_SODR/PIO_CODR

  }

  // End of the middle of the 4.94 MHz period
  if (PWM->PWM_ISR2 & PWM_ISR2_CMPM0)
  {
   
    // toggle the clock pin e.g.: PIOB->PIO_ODSR ^= PIO_ODSR_P27;
  }
}







Title: Re: 5 MHz signal from Due
Post by: weird_dave on Mar 04, 2019, 09:39 am
Given that the data is clocked, does it really need to be 5MHz anyway, isn't that just the max for the device? What is the device?
Title: Re: 5 MHz signal from Due
Post by: paxtakor22 on Mar 05, 2019, 06:20 pm
An example sketch to output a quasi square wave at 4.94 MHz and set or clear a pin every 4.94 MHz (not tested though):

Code: [Select]

/******************************************************************************/
/*                         PWMH0 ~ 5MHz                                        */
/******************************************************************************/

void setup() {

  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                   // PWM power ON

  PWM->PWM_CLK = PWM_CLK_PREB(0) | PWM_CLK_DIVB(1);    // select Frequency for clock B: Mck = 84 MHz

  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKB;      // The period is left aligned, clock source as CLKB on channel 0
  PWM->PWM_CH_NUM[0].PWM_CPRD = 17;                    // Set the PWM frequency 84 MHz/PWM_CPRD = 4941176 Hz

  PWM->PWM_CMP[0].PWM_CMPM = PWM_CMPM_CEN;
  PWM->PWM_CMP[0].PWM_CMPV = PWM_CMPV_CV(8);

  PWM->PWM_IER1 = PWM_IER1_CHID0;                      // Interrupt on PWM Channel 0 counter match (CPRD)
  PWM->PWM_IER2 = PWM_IER2_CMPM0;                      // Interrupt on CMPV match (CV)
  NVIC_EnableIRQ(PWM_IRQn);                            // Enable interrupt

  PWM->PWM_ENA = PWM_ENA_CHID0;                        // Enable PWM channel 0
}

void loop() {

}

// The Handler is triggered at 2*4.94 MHz
void PWM_Handler() {

  // End of the 4.94 Mhz period
  if (PWM->PWM_ISR1 & PWM_ISR1_CHID0)
  {
    
    // toggle the clock pin e.g.: PIOB->PIO_ODSR ^= PIO_ODSR_P27;
    // Set or clear the data pin with PIO_SODR/PIO_CODR

  }

  // End of the middle of the 4.94 MHz period
  if (PWM->PWM_ISR2 & PWM_ISR2_CMPM0)
  {
    
    // toggle the clock pin e.g.: PIOB->PIO_ODSR ^= PIO_ODSR_P27;
  }
}





Why did you use clock B instead of A? Seems like the interrupts are slowing the signal down. I cant change the frequency even if i change the  PWM_CPRD = 20  and PWM_CMPV_CV(21) values.

I got a 1.333 MHz PWM signal, that is not at 50% duty cycle, off pin 13 with the following code:


Code: [Select]


/******************************************************************************/
/*                         PWMH0 ~ 5MHz                                        */
/******************************************************************************/

void setup() {
  
  pinMode(13, OUTPUT);

  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                   // PWM power ON

  PWM->PWM_CLK = PWM_CLK_PREB(0) | PWM_CLK_DIVB(1);    // select Frequency for clock B: Mck = 84 MHz

  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKB;      // The period is left aligned, clock source as CLKB on channel 0
  PWM->PWM_CH_NUM[0].PWM_CPRD = 17;                    // Set the PWM frequency 84 MHz/PWM_CPRD = 4941176 Hz

  PWM->PWM_CMP[0].PWM_CMPM = PWM_CMPM_CEN;
  PWM->PWM_CMP[0].PWM_CMPV = PWM_CMPV_CV(8);

  PWM->PWM_IER1 = PWM_IER1_CHID0;                      // Interrupt on PWM Channel 0 counter match (CPRD)
  PWM->PWM_IER2 = PWM_IER2_CMPM0;                      // Interrupt on CMPV match (CV)
  NVIC_EnableIRQ(PWM_IRQn);                            // Enable interrupt

  PWM->PWM_ENA = PWM_ENA_CHID0;                        // Enable PWM channel 0
}

void loop() {
  
  while(1)
  {
    PWM_Handler();
  }

}

// The Handler is triggered at 2*4.94 MHz
void PWM_Handler() {

  // End of the 4.94 Mhz period
  if (PWM->PWM_ISR1 & PWM_ISR1_CHID0)
  {
    
    // toggle the clock pin e.g.:
    PIOB->PIO_ODSR ^= PIO_ODSR_P27;
    // Set or clear the data pin with PIO_SODR/PIO_CODR

  }

  // End of the middle of the 4.94 MHz period
  if (PWM->PWM_ISR2 & PWM_ISR2_CMPM0)
  {
    
    // toggle the clock pin e.g.:
    PIOB->PIO_ODSR ^= PIO_ODSR_P27;
  }
}








Given that the data is clocked, does it really need to be 5MHz anyway, isn't that just the max for the device? What is the device?
I guess i could run it slower than 5MHz, i will confirm. The device is something our company makes, it is not commercially available to a regular consumer.
Title: Re: 5 MHz signal from Due
Post by: ard_newbie on Mar 05, 2019, 06:41 pm
What frequency/duty cycle do you get for pin 35 (or pin 13):

Code: [Select]

/******************************************************************************/
/*                         PWMH0 5 MHz                                        */
/******************************************************************************/

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                   // PWM power ON

  PIOC->PIO_PDR |= PIO_PDR_P3;                         // Set PWM pin to a peripheral
  PIOC->PIO_ABSR |= PIO_PC3B_PWMH0;                    // Set PWM pin peripheral type B for PWMH0 (Arduino pin 35)

  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(1);    // select Frequency for clock A: Mck = 84 MHz

  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;      // The period is left aligned, clock source as CLKA on channel 0
  PWM->PWM_CH_NUM[0].PWM_CPRD = 17;                    // Set the PWM frequency 84 MHz/PWM_CPRD = 4941176 Hz
  PWM->PWM_CH_NUM[0].PWM_CDTY = 8;                     // Set the PWM duty cycle = (CPRD/CDTY) * 100 %

  PWM->PWM_IER1 = PWM_IER1_CHID0;                      // Interrupt on PWM Channel 0 counter
  NVIC_EnableIRQ(PWM_IRQn);                            // Enable interrupt

  PWM->PWM_ENA = PWM_ENA_CHID0;                        // Enable PWM channel 0
}

void loop() {
}

void PWM_Handler() {
  
  PWM->PWM_ISR1;      // Clear status register
  PIOB->PIO_ODSR ^= PIO_ODSR_P27;
 
}
Title: Re: 5 MHz signal from Due
Post by: paxtakor22 on Mar 05, 2019, 07:14 pm
I'm getting 4.94 MHz with 50% duty cycle on pin 35.
Getting 1.29 MHz on pin 13. Duty cycle is not at 50%

Thank You!!

The data signal (pin 13) lags behind the clock, is there a way to sync them or fire them off more closely to each other?

Also i believe i can use a lower frequency to do this after talking to another engineer. Would a lower frequency give me signals that are closer together? I know PWM signals can be synchronized. Was my idea to use two PWM signals (one at 50% duty cycle for clock and second at 100% duty cycle for data) by enabling and disabling the two PWM pins no good? I was able to get them pretty close to synchronized.
Title: Re: 5 MHz signal from Due
Post by: ard_newbie on Mar 05, 2019, 08:40 pm
I don't understand the issue...maybe something weird with PB27, the builtin LED (Page 1413, Sam3x datasheet states that the maximum output frequency for PIOs is between 35 and 65 MHz).

Try to replace PB27 (pin 13) by PA15(pin 24).

And yes you can synchro several PWM channels with PWM channel 0(search in the DUE sub forum for example sketches for manual or automatic PWM synchro channels). Or more simply, enable 2 PWM channels at the same time : PWM->PWM_ENA = PWM_ENA_CHID0 | PWM_ENA_CHID1;
Title: Re: 5 MHz signal from Due
Post by: paxtakor22 on Mar 05, 2019, 09:25 pm
Its even worse with pin24. The duty cycle doesnt stay constant.

I think i will go back to my original code in the first post. It works as desired except that i cannot get the 50% duty cycle pwm signal coming off of pin 35 to go down to 0 volts "quickly" (it takes about 400us) after the 26th "1"

Any idea how i can do this?
Title: Re: 5 MHz signal from Due
Post by: MartinL on Mar 05, 2019, 11:03 pm
How about setting the clock and data as synchronous PWM channels and use the PDC (Peripheral DMA Controller) to transfer the 26 command bits from memory to the PWM Controller?

If say the clock is on channel 0 and the data on channel 1, the duty-cycle information for both channels can be interleaved in a single data array:

Code: [Select]
{ CLK, DATA, CLK, DATA, CLK, DATA ... }
This method would save having to call the interrupt service routine at 5MHz. (The ISR would only be called once the PDC reached the end of the array).
Title: Re: 5 MHz signal from Due
Post by: paxtakor22 on Mar 05, 2019, 11:55 pm
How about setting the clock and data as synchronous PWM channels and use the PDC (Peripheral DMA Controller) to transfer the 26 command bits from memory to the PWM Controller?

If say the clock is on channel 0 and the data on channel 1, the duty-cycle information for both channels can be interleaved in a single data array:

Code: [Select]
{ CLK, DATA, CLK, DATA, CLK, DATA ... }
This method would save having to call the interrupt service routine at 5MHz. (The ISR would only be called once the PDC reached the end of the array).
I dont quite follow. Could you give me an example or some more info?

At this point the signal need not be 5MHz. I just need two synchronized square waves that i could use for clock and data like i the "what i want" picture: What I want (https://imgur.com/qfXiYqn). I guess direct port manipulation would suffice.
Title: Re: 5 MHz signal from Due
Post by: ard_newbie on Mar 06, 2019, 07:10 am
If a PWM PDC DMA is used, the "clock pin" frequency will be 84 MHz/8/2 = 5250000 Hz. If a 5% error is still acceptable, that's OK.

Edit: I took some more time to explore a solution since a 5 MHz interrupt frequency is an issue.

1/ It's possible to output a 4.94 quasi square wave on a "clock pin", say PWM channel 1 PWMH1

2/ As MartinL suggested, use PWM channel 0 PWMH0 to output 26 signals on a "data pin" at a 4.94 MHz frequency by using this channel as a synchro channel but only with itself (only one interruption after 26 ouput signals), and enable PWM channel 0 and channel 1 at the same time to be synchro.

3/ Once the 26 signals have been sent by PWM channel 1, disable this channel inside the interrupt handler, but keep PWM channel 0 enabled.


I guess after that you will have to decipher a receiving message from the device and attachinterrupt() won't be fast enough to decipher 5 MHz  input signals....
Title: Re: 5 MHz signal from Due
Post by: weird_dave on Mar 06, 2019, 10:39 am
Any chance you could extend the command to accept 32 clocks? You could then use the SPI controller.

I suspect the clock doesn't need to be 50/50, usually the data is sampled on one of the edges (the falling edge in your example would be what I would expect the device to use), as long as the on or off time isn't shorter than 100ns, any method you choose should work.

What methods have you actually used to communicate with the device, and what were the results? Note that if the device samples on the rising edge, the picture of the waveform you think you want, isn't.
Title: Re: 5 MHz signal from Due
Post by: paxtakor22 on Mar 07, 2019, 12:23 am
If a PWM PDC DMA is used, the "clock pin" frequency will be 84 MHz/8/2 = 5250000 Hz. If a 5% error is still acceptable, that's OK.

Edit: I took some more time to explore a solution since a 5 MHz interrupt frequency is an issue.

1/ It's possible to output a 4.94 quasi square wave on a "clock pin", say PWM channel 1 PWMH1

2/ As MartinL suggested, use PWM channel 0 PWMH0 to output 26 signals on a "data pin" at a 4.94 MHz frequency by using this channel as a synchro channel but only with itself (only one interruption after 26 ouput signals), and enable PWM channel 0 and channel 1 at the same time to be synchro.

3/ Once the 26 signals have been sent by PWM channel 1, disable this channel inside the interrupt handler, but keep PWM channel 0 enabled.


I guess after that you will have to decipher a receiving message from the device and attachinterrupt() won't be fast enough to decipher 5 MHz  input signals....
Sorry, im not following.

Do you mean something like this?


Code: [Select]


void setup()
{
  //pinMode(LED_BUILTIN, OUTPUT);
  pinMode(24, OUTPUT);

  REG_PMC_PCER1 |= PMC_PCER1_PID36;                   // PWM power ON

  REG_PIOC_PDR |= PIO_PDR_P3;                         // Set PWM pin to a peripheral
  REG_PIOC_ABSR |= PIO_PC3B_PWMH0;                    // Set PWM pin peripheral type B for PWMH0 (Arduino pin 35)

  REG_PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(1);    // select Frequency for clock A: Mck = 84 MHz

  REG_PWM_CMR0 = PWM_CMR_CPRE_CLKA;      // The period is left aligned, clock source as CLKA on channel 0
  REG_PWM_CPRD0 = 17;                    // Set the PWM frequency 84 MHz/PWM_CPRD = 4941176 Hz
  REG_PWM_CDTY0 = 8;                     // Set the PWM duty cycle = (CPRD/CDTY) * 100 %


  REG_PIOA_PDR |= PIO_PDR_P19; // pin 42

  REG_PIOA_ABSR |= PIO_PA19B_PWMH1; // pin 42  

  REG_PWM_CMR1 = PWM_CMR_CPRE_CLKB;    

  REG_PWM_CPRD1 = 1;                            

  REG_PWM_CDTY1 = 0; // 100%    



  REG_PWM_IER1 = PWM_IER1_CHID0;                      // Interrupt on PWM Channel 0 counter
  NVIC_EnableIRQ(PWM_IRQn);                           // Enable interrupt

  REG_PWM_SCM |= PWM_SCM_SYNC0; // sync ch 0

  REG_PWM_ENA = PWM_ENA_CHID0|PWM_ENA_CHID01;                   // Enable PWM channel 0 and 1
}


void loop()
{
}

void PWM_Handler()
{
  
  REG_PWM_ISR1;      // Clear status register
  //REG_PIOB_ODSR ^= PIO_ODSR_P27;
  //REG_PIOA_ODSR ^= PIO_ODSR_P15;
  
  REG_PWM_DIS = PWM_ENA_CHID0;
 
}




Any chance you could extend the command to accept 32 clocks? You could then use the SPI controller.

I suspect the clock doesn't need to be 50/50, usually the data is sampled on one of the edges (the falling edge in your example would be what I would expect the device to use), as long as the on or off time isn't shorter than 100ns, any method you choose should work.

What methods have you actually used to communicate with the device, and what were the results? Note that if the device samples on the rising edge, the picture of the waveform you think you want, isn't.
The documentation on this signal says that the "Polarity" is positive. I'm not sure what that means.

We have an ancient tester that can test these devices using some obsolete National Instruments card. I probed the data and clock lines on this tester and saw a 5MHz clock signal in sync with the data on a rising edge so i think it samples on the falling edge.

I cannot extend to 32.
Title: Re: 5 MHz signal from Due
Post by: ard_newbie on Mar 07, 2019, 06:32 am
A sketch for the Clock pin and the Data pin (I took as an example for the Data pin output 101010.....). Note that the 26 samples of the Data pin are output only once in this example, whereas the clock pin runs at 50% duty cycle forever:

Code: [Select]

/*******************************************************************************************/
/*  Synchro channel PWMH0 ONLY with PDC DMA trigger on Compare for the Data pin            */
/*                PWM channel 1 50% duty cycle for the clock pin                           */
/*******************************************************************************************/

// Pin 35 (PC3)is the data pin
// Pin 37 (PC5)is the clock pin

#define BufferSize  (26)                // Sample number (a power of 2 is better)
#define PERIOD_VALUE (17)               // For  4.94 MHz
#define NbCh      (1)                   // Only channel 0 ---> Number of channels = 1

#define DUTY_BUFFER_LENGTH      (BufferSize * NbCh) // Half words

uint16_t Duty_Buffer[DUTY_BUFFER_LENGTH];
uint16_t Duty_Buffer_Null[DUTY_BUFFER_LENGTH];
uint16_t Buffer_Duty[BufferSize];

void setup () {

  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                            // PWM controller power ON
  PWM->PWM_CLK = PWM_CLK_PREA(0b0000) | PWM_CLK_DIVA(1);        // Set the PWM clock rate for 84 MHz/1

  /*****************  Data pin programming       *********************/
  // PWMH0 on PC3, peripheral type B
  PIOC->PIO_PDR |= PIO_PDR_P3;                                 // Set PWM pin to a peripheral
  PIOC->PIO_ABSR |= PIO_PC3B_PWMH0;                            // Set PWM pin peripheral type B for PWMH1 (Arduino pin 35)

  // Set synchro channels list : Channel 0
  PWM->PWM_DIS = PWM_DIS_CHID0;

  PWM->PWM_SCM  = PWM_SCM_SYNC0 |      // Add SYNCx accordingly, at least SYNC0
                  PWM_SCM_UPDM_MODE2;  //Automatic write of duty-cycle update registers by the PDC DMA

  // Set the PWM Reference channel 0 i.e. : Clock/Frequency/Alignment
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;               // The period is left aligned, clock source as CLKA on channel 0
  PWM->PWM_CH_NUM[0].PWM_CPRD = PERIOD_VALUE;                   // Set the PWM frequency (84MHz/1)/PERIOD_VALUE Hz


  // Fill duty cycle buffer for channels 0, x, y ...
  // Buffer_Duty is a buffer of Half Words(H_W) composed of N lines which structure model for each duty cycle update is :
  // [ H_W: First synchro channel 0 duty cycle **Mandatory** ]/[ H_W: Second synchro channel duty cycle ] ... and so on

  for (int i = 0; i < BufferSize / 2; i++)     // Data pin output example: Buffer = 10101010 ....
  {
    Buffer_Duty[2 * i] = 4095;
    Buffer_Duty[2 * i + 1] = 0;
  }
  for (int i = 0; i < DUTY_BUFFER_LENGTH ; i++)
  {
    Duty_Buffer_Null[i] = 0;
  }
  for (int i = 0; i < DUTY_BUFFER_LENGTH ; i++) // Data pin output example: Buffer = 10101010 ....
  {
    Duty_Buffer[i] = Buffer_Duty[i];
  }
  

  PWM->PWM_TPR  = (uint32_t)Duty_Buffer;        // FIRST DMA buffer
  PWM->PWM_TCR  = DUTY_BUFFER_LENGTH;           // Number of Half words
  PWM->PWM_TNPR = (uint32_t)Duty_Buffer_Null;        // Next DMA buffer
  PWM->PWM_TNCR = DUTY_BUFFER_LENGTH;
  PWM->PWM_PTCR = PWM_PTCR_TXTEN;               // Enable PDC Transmit channel request

  // Set Interrupt events
  PWM->PWM_IER2 = PWM_IER2_WRDY;                //Write Ready for Synchronous Channels Update Interrupt Enable
  NVIC_EnableIRQ(PWM_IRQn);
  /*************************************************************************/

  /*******************       Clock pin programming        ***********/
  PIOC->PIO_PDR |= PIO_PDR_P5;                         // Set PWM pin to a peripheral
  PIOC->PIO_ABSR |= PIO_PC5B_PWMH1;                    // Set PWM pin peripheral type B for PWMH1 (Arduino pin 37)

  PWM->PWM_DIS = PWM_DIS_CHID1;

  PWM->PWM_CH_NUM[1].PWM_CMR = PWM_CMR_CPRE_CLKA;      // The period is left aligned, clock source as CLKA on channel 1
  PWM->PWM_CH_NUM[1].PWM_CPRD = PERIOD_VALUE;          // Set the PWM frequency 84 MHz/PWM_CPRD = 4.94 MHz
  PWM->PWM_CH_NUM[1].PWM_CDTY = (uint8_t)(PERIOD_VALUE/2);        // Set the PWM duty cycle = (CPRD/CDTY) * 100 %
  /***********************************************************/

  PWM->PWM_ENA = PWM_ENA_CHID0 |                       // Enable PWM channel 0 and channel 1 at the same time
                 PWM_ENA_CHID1;
}

void loop() {
}

void PWM_Handler() {  // move PDC DMA pointers to next buffer

  PWM->PWM_ISR2;      // Clear status register

  PWM->PWM_TNPR = (uint32_t)Duty_Buffer_Null;
  PWM->PWM_TNCR = DUTY_BUFFER_LENGTH;

}