Arduino Forum

Products => MKR Boards => MKRGSM1400 => Topic started by: neilster on Jun 12, 2019, 03:52 am

Title: MKR oscillator output
Post by: neilster on Jun 12, 2019, 03:52 am
Hi,

I want to create a very fast (fastest I can get) external oscillator with a MKR 1400 GSM.

With an Uno, this works, and generates a 8Mhz clock at pin 9...
Code: [Select]

  DDRB |= (1 << 1);         // Pin 9 is output
  TCCR1A = (1 << COM1A0) | (1 << WGM11) | (1 << WGM10);   // Toggle OC1A compare match
  TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);       // Clock select with no prescaler
  OCR1A = 0;                      // Match on 0 for fastest output (8Mhz).


How would I go about doing something similar with the MKR 1400 GSM?  I'm looking at section 31 (page 704+) in the datasheet (http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf), but this is the first time I'm using a SAMD21 and am considerably confused.  I'm also not sure how to get the output to a pin and which pin.
Anyone have example code that will do this?

Thanks.

Title: Re: MKR oscillator output
Post by: MartinL on Jun 12, 2019, 09:51 am
Hi neilster,

The following code will output an 8MHz, 50% duty-cycle PWM signal on digital pin D7:

Code: [Select]
// Output 8MHz, 50% duty-cycle PWM on timer TCC0
void setup()
{
  GCLK->GENDIV.reg = 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

  GCLK->GENCTRL.reg = 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
  GCLK->CLKCTRL.reg = 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

  // Enable the port multiplexer for the TCC0 PWM channel 3 (digital pin D7), SAMD21 pin PA21
  PORT->Group[g_APinDescription[7].ulPort].PINCFG[g_APinDescription[7].ulPin].bit.PMUXEN = 1;
 
  // Connect the TCC0 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[7].ulPort].PMUX[g_APinDescription[7].ulPin >> 1].reg |= /*PORT_PMUX_PMUXO_F |*/ PORT_PMUX_PMUXO_F;

  // Normal (single slope) PWM operation: timer countinuouslys count up to PER register value and then is reset to 0
  TCC0->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;        // Setup single slope PWM on TCC0
  while (TCC0->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:
  TCC0->PER.reg = 5;                              // Set the frequency of the PWM on TCC0 to 8MHz
  while(TCC0->SYNCBUSY.bit.PER);                  // Wait for synchronization

  // The CCx register value corresponds to the pulsewidth in microseconds (us)
  TCC0->CC[3].reg = 3;                            // TCC0 CC3 - 50% duty cycle on D7
  while(TCC0->SYNCBUSY.bit.CC3);                  // Wait for synchronization
 

   // Divide the 48MHz signal by 1 giving 48MHz (20.8ns) timer tick and enable timer TCC0
  TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1;    // Divide GCLK4 by 1
  TCC0->CTRLA.bit.ENABLE = 1;                     // Enable the TCC0 output
  while (TCC0->SYNCBUSY.bit.ENABLE);              // Wait for synchronization
}

void loop() {}
Title: Re: MKR oscillator output
Post by: neilster on Jun 12, 2019, 02:21 pm
MartinL,

Tried this and it works beautifully!  The comments mostly explain it well, except for the part about connecting the timer to the port output, which I'll go read up on in the datasheet.

Much appreciated!

Thanks.
Title: Re: MKR oscillator output
Post by: MartinL on Jun 12, 2019, 03:19 pm
Quote
The comments mostly explain it well, except for the part about connecting the timer to the port output, ...
Here's a explanation of how the activate the SAMD21's peripheral outputs, such as the TCC timer: https://forum.arduino.cc/index.php?topic=346731.210 (https://forum.arduino.cc/index.php?topic=346731.210).