WilliamASumner / Tlc5948

An library for controlling the Tlc5948 chip
4 stars 0 forks source link

PWM for GSClk not working on SAMD (Arduino Nano IOT) #2

Open 97Cweb opened 1 year ago

97Cweb commented 1 year ago

Hello William I just reached out to you on Arduino forums as well. I don't know how to fork but here is the code for making a GSClk on pin 9 for nanos.

` // this function may be a source of trouble if // GSCLK default frequency is too low (3KHz is around the minimum) inline void Tlc5948::startBuiltinGsclk() { // Number to count to with PWM (TOP value). Frequency can be calculated by // freq = GCLK4_freq / (TCC0_prescaler * (1 + TOP_value)) // With TOP of 47, we get a 1 MHz square wave in this example

//freq = 48 / (1 (1+top)) //freq out should be 8 //8 = 48 / (1 (1+top)) //8 * (1 + top) = 48 //1 + top = 6 //top = 5 uint32_t period = 6 - 1;

// Because we are using TCC0, limit period to 24 bits period = ( period < 0x00ffffff ) ? period : 0x00ffffff;

// Enable and configure generic clock generator 4 GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC | // Improve duty cycle GCLK_GENCTRL_GENEN | // Enable generic clock gen GCLK_GENCTRL_SRC_DFLL48M | // Select 48MHz as source GCLK_GENCTRL_ID(4); // Select GCLK4 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization

// Set clock divider of 1 to generic clock generator 4 GCLK->GENDIV.reg = GCLK_GENDIV_DIV(1) | // Divide 48 MHz by 1 GCLK_GENDIV_ID(4); // Apply to GCLK4 4 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization

// Enable GCLK4 and connect it to TCC0 and TCC1 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable generic clock GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4 GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0/1 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization

// Divide counter by 1 giving 48 MHz (20.83 ns) on each TCC0 tick TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER(TCC_CTRLA_PRESCALER_DIV1_Val);

// Use "Normal PWM" (single-slope PWM): count up to PER, match on CC[n] TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Select NPWM as waveform while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization

// Set the period (the number to count to (TOP) before resetting timer) TCC0->PER.reg = period; while (TCC0->SYNCBUSY.bit.PER);

// Set PWM signal to output 50% duty cycle // n for CC[n] is determined by n = x % 4 where x is from WO[x] TCC0->CC[2].reg = period / 2; while (TCC0->SYNCBUSY.bit.CC2);

// Configure PA20 (D9 on Arduino Nano) to be output PORT->Group[PORTA].DIRSET.reg = PORT_PA20; // Set pin as output PORT->Group[PORTA].OUTCLR.reg = PORT_PA20; // Set pin to low

// Enable the port multiplexer for PA18 PORT->Group[PORTA].PINCFG[20].reg |= PORT_PINCFG_PMUXEN;

// Connect TCC0 timer to PA18. Function F is TCC0/WO[2] for PA18. // Odd pin num (2n + 1): use PMUXO // Even pin num (2n): use PMUXE PORT->Group[PORTA].PMUX[10].reg = PORT_PMUX_PMUXE_F;

// Enable output (start PWM) TCC0->CTRLA.reg |= (TCC_CTRLA_ENABLE); while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization } `

97Cweb commented 1 year ago

If you want to read more, it is based heavily off of https://shawnhymel.com/1710/arduino-zero-samd21-raw-pwm-using-cmsis/