Changing Arduino Zero PWM Frequency

Hence, I was, and am, hoping that there is a call function (or its equivalent) in the ( or a ) IDE library that allows a static (constant) or a dynamic (variable) change/alteration in the prescaler to vary the clock "divide by" (say from divide by 128 to some other appropriate multiple of 2 number).

I had a look at the source code for the Zero's tone() function. It dynamically alters the timer's prescaler to generate the specified frequency and appears to be remarkably similiar to your requirements.

The tone() function is in the Zero's "Tone.cpp" file, which (on my Windows machine at least) is located at:

C:\Users\Computer\AppData\Local\Arduino15\packages\arduino\hardware\samd\1.6.6\cores\arduino\Tone.cpp.

Hello!!!! i have a question.
I try it but i can change pwm frequency.

Can use this code in arduino mkr1000 board?
Thanks

Hi ROBERTO

Can use this code in arduino mkr1000 board?

Yes you can. However, while the port pin mapping (for example PA00, PA01, etc...) of the Zero and MKR1000 are the same, (as they share the same microcontroller), the Arduino mapping (D0, D1, etc...) for both boards is different.

The other issue is that you've got less pins to chose from, as the MKR1000 has fewer pins broken out than the Zero and some of these might also need to be configured as the default I2C or SPI port.

When selecting the timer pins you can use table 6.1 PORT Function Multiplexing from the SAMD21 datasheet for the SAMD21G. The conversion from port pin to Arduino pin can be found either in the MKR1000's "variant.cpp" file, or alternatively in the board's schematic. A PDF version of the MKR1000's schematic can be found here: https://www.arduino.cc/en/uploads/Main/MKR1000-schematic.pdf.

Anyway, here's a list of the MKR1000's pins than can be defined as TCC timer pins and their associated channel (WO[X]), unless stated otherwise the TCC timers are on peripheral F:

A0 - PA02 - None
A1 - PB02 - None
A2 - PB03 - None
A3 - PA04 - TCC0/WO[0] (same channel as TCC0/WO[4])
A4 - PA05 - TCC0/WO[1] (same channel as TCC0/WO[5])
A5 - PA06 - TCC1/WO[0]
A6 - PA07 - TCC1/WO[1]
D0 - PA22 - TCC0/WO[4] (same channel as TCC0/WO[0])
D1 - PA23 - TCC0/WO[5] (same channel as TCC0/WO[1])
D2 - PA10 - TCC1/WO[0]
D3 - PA11 - TCC1/WO[1]
D4 - PB10 - TCC0/WO[4] (same channel as TCC0/WO[0])
D5 - PB11 - TCC0/WO[5] (same channel as TCC0/WO[1])
D6 - PA20 - TCC0/WO[6] (same channel as TCC0/WO[2])
D7 - PA21 - TCC0/WO[7] (same channel as TCC0/WO[3])
D8 - PA16 - TCC0/WO[6] (same channel as TCC0/WO[2]) on peripheral F, TCC2/WO[0] on peripheral E
D9 - PA17 - TCC0/WO[7] (same channel as TCC0/WO[3]) on peripheral F, TCC2/WO[1] on peripheral E
D10 - PA19 - TCCO/WO[3] (same channel as TCC0/WO[7])
D11 - PA08 - TCC1/WO[2] (same channel as TCC1/WO[0]) on peripheral F, TCC0/WO[0] on peripheral E
D12 - PA09 - TCC1/WO[3] (same channel as TCC1/WO[1]) on peripheral F, TCC0/WO[1] on peripheral E
D13 - PB22 - None
D14 - PB23 - None

Note the timer TCC0 has only 4 channels (0-3 and 4-7 are the same), while TCC1 and TCC2 each have 2, giving you 8 channels in total.

MartinL

Thanks for this tutorial. I have to admit, it a had to read it many times to get the details.

If anybody is interested, i have got 100Hz PWM with 0.16us resolution running on 4 pins on the Adafruit Feather M0 boards.

D11/D13 runs on TCC2
D10/D12 runs on TCC0

GCLK4 running at 48MHz
Both timers are using prescaler of 4 and PER=60000

Sketch sets D10 at 1000us, D11 at 2000us, D11/13 at 1500us pulse widths.

Runs fine in 1.6.11 IDE

FEATHER-PWM_TCC2-D13D11-TCC0-D10D12.ino (4.97 KB)

Hi MartinL.
Would you help to set this up?
I need 50khz on D9 pin, in my board this pin is mapped to PA07. What value I need to modify to alter duty cycle after making the configuration?
Thanks in advance.

Hi rjastap,

The following code sets-up 50kHz, at 50% duty cycle on D9:

// Output 50kHz PWM on timer TCC1 (9-bit resolution)
void setup()
{
  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) |          // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz
                    GCLK_GENDIV_ID(4);            // Select Generic Clock (GCLK) 4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |           // Set the duty cycle to 50/50 HIGH/LOW
                     GCLK_GENCTRL_GENEN |         // Enable GCLK4
                     GCLK_GENCTRL_SRC_DFLL48M |   // Set the 48MHz clock source
                     GCLK_GENCTRL_ID(4);          // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // Enable the port multiplexer for the PWM channel on pin D9  
  PORT->Group[g_APinDescription[9].ulPort].PINCFG[g_APinDescription[9].ulPin].bit.PMUXEN = 1;
  
  // Connect the TCC1 timer to the port outputs - port pins are paired odd PMUO and even PMUXE
  // F & E peripherals specify the timers: TCC0, TCC1 and TCC2
  PORT->Group[g_APinDescription[9].ulPort].PMUX[g_APinDescription[9].ulPin >> 1].reg |= PORT_PMUX_PMUXO_E; 

  // Feed GCLK4 to TCC0 and TCC1
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to TCC0 and TCC1
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                     GCLK_CLKCTRL_ID_TCC0_TCC1;   // Feed GCLK4 to TCC0 and TCC1
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // Normal (single slope) PWM operation: timers countinuously count up to PER register value and then is reset to 0
  REG_TCC1_WAVE |= TCC_WAVE_WAVEGEN_NPWM;        // Setup single slope PWM on TCC1
  while (TCC1->SYNCBUSY.bit.WAVE);                // Wait for synchronization

  // Each timer counts up to a maximum or TOP value set by the PER register,
  // this determines the frequency of the PWM operation: 959 = 50kHz
  REG_TCC1_PER = 959;      // Set the frequency of the PWM on TCC1 to 50kHz
  while(TCC1->SYNCBUSY.bit.PER);

  // The CCBx register value corresponds to the pulsewidth in microseconds (us) 
  REG_TCC1_CC1 = 480;      // Set the duty cycle of the PWM on TCC0 to 50%
  while(TCC1->SYNCBUSY.bit.CC1);
 
  // Enable TCC1 timer
  REG_TCC1_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 |    // Divide GCLK4 by 1
                    TCC_CTRLA_ENABLE;             // Enable the TCC0 output
  while (TCC1->SYNCBUSY.bit.ENABLE);              // Wait for synchronization
}

void loop() { }

Digital pin 9, or PA07 uses timer TCC1 on perhiperal E. The timer is clocked a 48MHz, as the generic clock divisor and the timer prescaler are set to 1. I've also set-up the timer work in normal PWM mode, rather than dual slope, as at 50kHz this will increase your resolution by 1-bit.

The formula for working out the frequency (in normal PWM mode) is:

timer frequency = generic clock frequency / (N * (PER + 1))

where:
N = timer prescaler (in this case 1)
PER = value in the period (PER) register

We can therefore rearrange this formula to find the PER value for a given timer frequency:

PER = 48MHz / 50kHz - 1 = 959

This will give you a 50kHz PWM output.

Loading the counter compare 1 register (REG_TCC1_CC1) with a value half that of the PER gives a 50% duty cycle.

To change the duty cycle during operation however, it's better to load the buffered counter compare register, in this case REG_TCC1_CCB1. Note the 'B'. For example, to set the duty cycle to 25%:

REG_TCC1_CCB1 = 240;                      // Load the CCB1 register with a new value
while(TCC1->SYNCBUSY.bit.CCB1);                  // Wait for synchronization

The buffered register loads the new value into the unbuffered CC1 register at the beginning of each timer cycle. Loading the CC1 register directly (not using the buffered register) may cause glitches on you output PWM waveform when changing the duty cycle.

The value of the CCB1 register can range from 0 = 0% duty cycle (0V), through to the value in the PER register, in this case 959 = 100% duty cycle (3.3V).

This configuration will give out an output resolution of 9-bits.

Hi MartinL.

Thank you so much for taking your time to write that beautiful explanation.

I was in a hurry , so I kept trying to configure it and I got to understand the whole concepts exactly as you explained.

Finally I made an aproximation to 20kHz that sastisfy my requirements.

This is the code I've got.

void pwmconfig()
{
  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) |          // Divide the 48MHz clock source by divisor 1: 48MHz
                    GCLK_GENDIV_ID(4);            // Select Generic Clock (GCLK) 4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |           // Set the duty cycle to 50/50 HIGH/LOW
                     GCLK_GENCTRL_GENEN |         // Enable GCLK4
                     GCLK_GENCTRL_SRC_DFLL48M |   // Set the 48MHz clock source
                     GCLK_GENCTRL_ID(4);          // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

//Enable port multiplexer
 PORT->Group[g_APinDescription[9].ulPort].PINCFG[g_APinDescription[9].ulPin].bit.PMUXEN = 1;  // D9(PA07)
  
  // Connect the TCC1 timer to the port outputs - port pins are paired odd PMUO and even PMUXE
  // F & E specify the timers: TCC0, TCC1 and TCC2
 PORT->Group[g_APinDescription[8].ulPort].PMUX[g_APinDescription[8].ulPin>>1].reg = PORT_PMUX_PMUXO_E | PORT_PMUX_PMUXE_E; // D8
  
  // Feed GCLK4 to TCC0 and TCC1         ??? Is there any way to feed GCLK4? only to TCC1?
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to TCC0 and TCC1
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                     GCLK_CLKCTRL_ID_TCC0_TCC1;   // Feed GCLK4 to TCC0 and TCC1
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // Single slope PWM operation

   REG_TCC1_WAVE |= TCC_WAVE_WAVEGEN_NPWM;

   while (TCC1->SYNCBUSY.bit.WAVE);               // Wait for synchronization

  // Each timer counts up to a maximum or TOP value set by the PER register,
  // this determines the frequency of the PWM operation:
  // 
  REG_TCC1_PER = 2400;      // Set the frequency of the PWM on TCC1 to 
  while(TCC1->SYNCBUSY.bit.PER);

  // The CCBx register value corresponds to the pulsewidth in microseconds (us)
  REG_TCC1_CCB1 = 1200;       // TCC0 CCB0 - 50% duty cycle on D2
  while(TCC1->SYNCBUSY.bit.CCB1);


  // Divide the 48MHz signal by 1 giving 48MHz 
  REG_TCC1_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 |    // Divide GCLK4 by 1
                    TCC_CTRLA_ENABLE;             // Enable the TCC1 output
  while (TCC1->SYNCBUSY.bit.ENABLE);              // Wait for synchronization
}

And I made a function to replace analogWrite(i,9);

void set_pwm(int i){
  REG_TCC1_CCB1 = i;       // TCC0 CCB0 - 50% duty cycle on D2
  while(TCC1->SYNCBUSY.bit.CCB1);

}

Hi MartinL,

I am interested in your code since I need to generate a number (N) of pulses at a given frequency (20 to 45 KHz more or less), on a given PIN of my M0PRO board.

I tried to compile your example (dual slope PWM over PIN 7) to start with.

I unfortunately got the following error message.

Could you help ?

Many thanks,

Daniel

Arduino : 1.7.9 (Windows XP), Carte : "Arduino M0 Pro (Programming Port)"

Gene_frequence_1.ino: In function 'void setup()':

Gene_frequence_1.ino:24:22: error: 'GCLK_CLKCTRL_ID_TCC0_TCC1' was not declared in this scope

Erreur lors de la compilation.

Hi Daniel,

The reason why the code doesn't compile is because you're using Arduino.org's IDE and M0 Pro board, rather than Arduino.cc's IDE and Arduino/Genuino Zero.

Arduino split into two companies, Arduino.org and Arduino.cc (and are currently seeking an amicable resolution), but the Zero and M0 Pro never fully escaped the consequences. The main differences between the boards being that the digital pins D2 and D4 are reversed and that the M0 Pro doesn't have the additional ATN pin. In addition, the two boards use a different bootloader.

Unfotunately, it also appears that Arduino.org software doesn't use some of the Atmel register definitions for the SAMD21 microcontroller found on both boards and that's what's causing the error.

Personally, I think the easiest solution is to download the Arduino.cc IDE and take the following steps below to burn the Arduino.cc bootloader on to your M0 Pro. However, this will have the effect that that the digital pins: D2 and D4 will be reversed. So, calling D2 in your sketch will effect the D4 pin and vice-versa. Following this you should be able to compile and upload the above sketch without any errors. It also has the added benefit that you'll be using the same software as most of the other Zero/M0 Pro users on this forum.

To burn the Arduino.cc bootloader on to your Arduino M0 Pro:

  1. Download the Arduino.cc IDE (currently version 1.6.12)
  2. In the menu go to Tools->Board: ...->Boards Manager
  3. Install the "Arduino SAMD Boards (32-bit ARM Cortex M0+)" package (currently version 1.6.9)
  4. Close the Boards Manager
  5. Select Tools->Board: ..., then select "Arduino/Genuino Zero (Programming Port)
  6. Plug your USB into your M0 Pro's programming port and the other end into your PC
  7. Select Tools->Port and select your M0 Pro's COM port
  8. Select Tools->Programmer..., and select "Atmel EDBG"
  9. Select Tools->Burn Bootloader

Hi MartinL

I have been trying to read up on how to implement PWM on an M0. I have learnt heaps up to this point from this thread. I have included some of the code posted to create my own code to drive 7 PWM pins of an Adafruit Feather M0: PA15, PA20, PA07, PA18, PA16, PA19 and PA17 if I am to believe the following figure:
Adafruit M0 proto

However I get the following errors when verifying my code (see attachment). Could you point me out what I am doing wrong, and more importantly, point out how to fix this error?

Arduino: 1.6.8 (Mac OS X), Board: "Adafruit Feather M0 (Native USB Port)"

error: 'REG_TCC0_CC5' was not declared in this scope
REG_TCC0_CC5 = 600; // TCC0 CC5 - on D05
error: 'REG_TCC0_CC6' was not declared in this scope
REG_TCC0_CC6 = 600; // TCC0 CC6 - on D06
error: 'volatile struct TCC_SYNCBUSY_Type::' has no member named 'CC6'
while (TCC0->SYNCBUSY.bit.CC6); // Wait for synchronization

exit status 1
Error compiling for board Adafruit Feather M0 (Native USB Port).

FeatherM0-20kHz.ino (7.53 KB)

Hi Maverick123,

The reason why you're getting the errors, is because timer TCC0 only has 4 channels for the waveform outputs: WO[0] to WO[3]. These 4 channels are then repeated for waveform outputs: WO[4] to WO[7]. So counter compare registers CC5 and CC6 registers don't exist, they instead correspond to CC1 and CC2.

This means that digtal pin D05 uses REG_TCC0_CC1 and D06 the register REG_TCC0_CC2.

Note that each CCx register requires write synchronization, for example:

while (TCC0->SYNCBUSY.bit.CC1);
Also in your loop() section, it's possible to use the buffered CCBx registers, as these allow the waveform's duty cycle to be changed at the beginning of each waveform period and therefore prevents glitches from appearing on your output. Note that these buffered registers also have to be write synchronized.

Hi MartinL,

thank you for your quick response. Changing CC5 and CC6 to CC1 and CC2 works like a charm.

I do still have some questions about your second remark:
do you mean that in the setup I should use

while (TCCx->SYNCBUSY.bit.CCy)

for every pin?

Should I, in the loop() section, use

REG_TCCx_CCBy in stead of REG_TCCx_CCy

since this will write to the same buffer as was initialized during setup?
and should I then also use

while(TCCx->SYNCBUSY.bit.CCy)

after each change in PWM duty cycle?

P.S. now that I take a better look at the code, I see that both D6 (PA20) and D10 (PA18) now use TCC0_CC2. Isn't this a problem? Could I use PA04: TCC0 CC0 and PA10: TCC1 CC0 instead of PA20 to create 8 independent PWM signals?

Hi Maverick123,

On the SAMD21 each of the peripherals, such as SERCOM modules or the TCC/TC timers are internally connected to the processor through a single digital interface, on the what is know as the APB bus, (Advanced Peripheral Bus). This bus is clocked using a synchronous clock.

The peripherals themselves are also clocked by a core clock supplied by the generic clock controller. In order to read and write to some of the peripheral registers, these clocks need to be synchronized.

After writing to a peripheral register that requires write synchronization, it's necessary to check that clocks have synchronized. This can be achieved in the case of the TCC timer, either by polling the register's SYNCBUSY bit or generating an associated interrupt. If you do not check that synchronization has occured, then in the case of the TCC timer it risks another write to the same register being discarded. In other peripherals such as the TC timer it risks stalling the bus interface if you try to immediately read or write to the peripheral again.

The TCCx timers' CCx and CCB registers require write synchonization. So after each write I poll the register's SYNCBUSY bit with the line:

while (TCCx->SYNCBUSY.bit.CCy);

P.S. now that I take a better look at the code, I see that both D6 (PA20) and D10 (PA18) now use TCC0_CC2. Isn't this a problem?

Yes, then it's necessary to reassign either D6 (PA20) or D10 (PA18) to another pin.

Could I use PA04: TCC0 CC0 and PA10: TCC1 CC0 instead of PA20 to create 8 independent PWM signals?

Yes, using either PA04 or PA10 as an output for TCC0/WO[0] would work.

In the loop() section to use the buffered registers, just add a 'B' to the CC in the register name and poll the corresponding CCBx SYNCBUSY bit. So just as you mentioned it's:

REG_TCCx_CCBy = 600;
while (TCCx->SYNCBUSY.bit.CCBy);

Hi MartinL,

thanks again for the quick response and the elaborate answer. If it is possible I would like to use 8 pins for PWM.

If I want to use:

  • PA04 TCC0 CC0
  • PA10 TCC1 CC0

Would the following code work?

PORT->Group[PORTA].PMUX[04 >> 1].reg = PORT_PMUX_PMUXE_E; //E PA04 (TCC0/ WO[0])
PORT->Group[PORTA].PMUX[10 >> 1].reg = PORT_PMUX_PMUXE_E; //E PA10 (TCC1/ WO[0])

Since PA04 and PA10 are not of the kind D6 (PA20), what would be the equivalent description using:

PORT->Group[g_APinDescription[z].ulPort].PMUX[g_APinDescription[z].ulPin >> 1].reg = PORT_PMUX_PMUXE_E;

or should z in these cases be:

  • PA04: z=17
  • PA10: z=1

Hi Maverick123,

Would the following code work?

Yes.

Since PA04 and PA10 are not of the kind D6 (PA20), what would be the equivalent description using:

As PA04 is the A3 pin and PA10 is D1, it's also possible to use:

PORT->Group[g_APinDescription[A3].ulPort].PMUX[g_APinDescription[A3].ulPin >> 1].reg |= PORT_PMUX_PMUXE_E;
PORT->Group[g_APinDescription[1].ulPort].PMUX[g_APinDescription[1].ulPin >> 1].reg |= PORT_PMUX_PMUXE_E;

Hi MartinL,

Thank you for your response. It has been really helpful. I do have a question about setting up the Feather M0 as an SPI slave, but I will post that question in a more appropriate thread.

Hi MartinL
I followed your recommendations upthere and your code is working perfectly on my m0pro board. I can generate a frequency of 40 khz with dedicated duty cycle. Nice.
Now I need to start / stop the timers so that I get a burst of let say 30 ms. The idea being to create a fsk2 modulation, generating frequency burts for example :
F1 (39 Khz) for 0 / 33ms
F2 (41 khz) for 1 /33 ms
So could you help me to manage start / stop on relevant timers ?
DR49

Hi DR49,

To stop the (TCC0) timer:

REG_TCC0_CTRLBSET = TCC_CTRLBSET_CMD_STOP;
while(TCC0->SYNCBUSY.bit.CTRLB);

To restart the timer again:

REG_TCC0_CTRLBSET = TCC_CTRLBSET_CMD_RETRIGGER;
while(TCC0->SYNCBUSY.bit.CTRLB);

Who can make a Fast 8/10-bit PWM DAC for the Arduino Zero?

It would be nice to have a library for the Arduino zero, equal to this library:

building further on the theme of the topic (and borrowing greatly from it) I tried to implement a 50/50 duty cycle PWM clock output which is triggered on the rising edge of an incoming signal on pin 4 of an Arduino M0 Pro and which is stopped on the falling edge.
Doing this with a software interupt and invoking STOP and RETRIGGER commands works fine but is very slow (as was expected from previous arduino uno experience).
So I tried to set this up with the EVSYS events, using one event to RETRIGGER and hook it up to the rising edge on pin4 (extint14) via the EIC and another event invoking STOP on the falling edge. However it seems this STOP command stops the timer forever so that it can't be RETRIGGERED later. The retriggering using both event works fine.

Anyone with experience that can help me out here as I am running out of ideas...
(minimum code reproducing my issue attached)

//test program to create a 50/50 clock pulse
//with a period 2xPIXTIME+1
//that starts/stops on the rising/falling edge on the IRQ pin
//aim is to get the response to IRQ as fast as possible
//for now it seems approx 250ns on scope (why so long? still 12 clockcycles?)
//and the pulse train only works for one cycle on IRQ
//for Arduino M0 pro

//what I have so far is hacked together from several bits and pieces and probably contains superficial instructions
#define IRQ 4//line sync interupt on pin 2 CAREFUL for Arduino M0 Pro pin 4 and 2 are swapped!!!!!
#define PIX 9//clock output generated
#define PIXTIME 3200 //defines the period of 1 clock pulse

void setup() {
  // put your setup code here, to run once:
  pinMode(PIX, OUTPUT);
  pinMode(IRQ,INPUT);
  pinMode(2,INPUT); //to be sure with the 2/4 confusion
  noInterrupts(); // disable all interrupts while setting up

  //use event channels to start and stop the timer connected to EXTINT
  REG_PM_APBCMASK |= PM_APBCMASK_EVSYS;     // Switch on the event system peripheral
  EVSYS->CTRL.reg = EVSYS_CTRL_SWRST;       // reset
  
  REG_PM_APBAMASK |= PM_APBAMASK_EIC;        // PM_APBAMASK for the EIC
  
  //connect IRQ pin to EIC via port mux
  PORT->Group[g_APinDescription[IRQ].ulPort].PINCFG[g_APinDescription[IRQ].ulPin].bit.PMUXEN = 1;
  PORT->Group[g_APinDescription[IRQ].ulPort].PMUX[g_APinDescription[IRQ].ulPin >> 1].reg |= PORT_PMUX_PMUXE_A;
  // connect PIX pin to TCC1 output via port mux
  PORT->Group[g_APinDescription[PIX].ulPort].PINCFG[g_APinDescription[PIX].ulPin].bit.PMUXEN = 1;
  PORT->Group[g_APinDescription[PIX].ulPort].PMUX[g_APinDescription[PIX].ulPin >> 1].reg = PORT_PMUX_PMUXO_E;
  
  attachInterrupt(IRQ, NULL, HIGH);          //I suppose this avoids setting it up all manually even though we don't want a software ISR

  // set up GCLK4
  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) |          // Take full 48Mhz speed
                    GCLK_GENDIV_ID(1);            // 
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |           // Set the duty cycle to 50/50 HIGH/LOW
                     GCLK_GENCTRL_GENEN |         // Enable GCLK4
                     GCLK_GENCTRL_SRC_DFLL48M |   // Set the 48MHz clock source
                     GCLK_GENCTRL_ID(4) ;        // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization
  
  // Feed GCLK4 to TCC0 and TCC1
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to TCC0 and TCC1
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                     GCLK_CLKCTRL_ID_TCC0_TCC1;  // Feed GCLK4 to TCC0 and TCC1
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  //and to evsys ch0 (this is essential to make it work!)
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to EVSYS
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                     GCLK_CLKCTRL_ID_EVSYS_0;
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization
 
  //and for evsys ch1
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to EVSYS
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                     GCLK_CLKCTRL_ID_EVSYS_1;
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization
  
  //and for EIC (needed?)
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to EVSYS
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                     GCLK_CLKCTRL_ID( GCLK_CLKCTRL_ID_EIC);
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // normal PWM operation
  REG_TCC1_WAVE |= TCC_WAVE_POL(0x0) |         // Don't Reverse the output polarity on all TCC1 outputs
                    TCC_WAVE_WAVEGEN_NPWM;    // Setup normal PWM on TCC1
  while (TCC1->SYNCBUSY.bit.WAVE);               // Wait for synchronization

  // Each timer counts up to a maximum or TOP value set by the PER register,
  // this determines the period of the pulse
  REG_TCC1_PER = PIXTIME*2+1;      // Set the frequency of the PWM on TCC1 to 2xpixtime
  while(TCC1->SYNCBUSY.bit.PER);

  // The CCBx register value corresponds to the pulsewidth
  REG_TCC1_CC1 = PIXTIME;       // 50% duty cycle
  while(TCC1->SYNCBUSY.bit.CC1);

  //Event ch0 on rising edge  
  REG_EVSYS_USER = EVSYS_USER_CHANNEL(1) |                               // Attach TCC1_EV0 (receiver) to channel 0 (n + 1)
                   EVSYS_USER_USER(EVSYS_ID_USER_TCC1_EV_1) ;               
  REG_EVSYS_CHANNEL = EVSYS_CHANNEL_EDGSEL_RISING_EDGE |                 // Rising edge detection
                      EVSYS_CHANNEL_PATH_SYNCHRONOUS |                   // Set event path as synchronous
                      EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_14) |  // Set event generator (sender) as external interrupt 14 (which connects to pin 2 = pa14
                      EVSYS_CHANNEL_CHANNEL(0);                          // Attach the generator (sender) to channel 0
  //Event ch1 on falling edge
  REG_EVSYS_USER = EVSYS_USER_CHANNEL(2) |                                // Attach TCC1_EV0 (receiver) to channel 0 (n + 1)
                   EVSYS_USER_USER(EVSYS_ID_USER_TCC1_EV_0) ;               
  REG_EVSYS_CHANNEL = EVSYS_CHANNEL_EDGSEL_FALLING_EDGE |                // Falling edge detection
                      EVSYS_CHANNEL_PATH_SYNCHRONOUS |                   // Set event path as synchronous
                      EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_14) |  // Set event generator (sender) as external interrupt 14 (which connects to pin 2 = pa14
                      EVSYS_CHANNEL_CHANNEL(1);                          // Attach the generator (sender) to channel 0

//stop works ONCE only, but then doesnt retrigger again, 
//is this a documented feature? datasheet is not very expanded on this feature
//doing a software stop and retrigger works fine
//both EV channels work, retrigger works well, but STOP avoids the timer to be retriggered: WHY?
  REG_TCC1_EVCTRL |= TCC_EVCTRL_TCEI0 |               // Enable the TCC1 event input EV0
                    TCC_EVCTRL_TCEI1 |                // Enable the TCC1 event input EV1
                    TCC_EVCTRL_EVACT0_RETRIGGER |     //retrigger on EV0
                    TCC_EVCTRL_EVACT1_STOP   ;         //stop on EV1 (this is where it fails, putting OFF or RETRIGGER here does what is expected)
                    //TCC_EVCTRL_TCINV0 |             // Invert the event input                 
  while (TCC1->SYNCBUSY.bit.ENABLE);                  // Wait for synchronization 
  
//enable interupt...totally unsure what to do here (what is needed and what is superficial or wrong)
  REG_EIC_EVCTRL |= EIC_EVCTRL_EXTINTEO14;      // Enable event output on external interrupt 14=pin2 pa14
  //REG_EIC_CTRL=0x2; //enable EIC  
  //NVIC_SetPriority(EIC_IRQn, 0);              // Set the Nested Vector Interrupt Controller (NVIC) priority for TC3 to 0 (highest)
  //NVIC_EnableIRQ(EIC_IRQn);
  
  //enable the outputs
  REG_TCC1_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 | TCC_CTRLA_ENABLE;             // Enable the TCC1 output
  while (TCC1->SYNCBUSY.bit.ENABLE);              // Wait for synchronization 
  
}

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