Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ MaxSteps is 0xFFFFFF for (24-bits) timers 0 and 1, and 0xFFFF for (16 bits) time

```pwm.analogWrite([pin number], [0-1000]);```

**Start PWM on a pin with a 16 bit duty cycle:**

```pwm.analogWrite([pin number], [0-65535]);```

Note that the duty cycle will be limited to the number of steps specified with the `timer` function. It is also limited to 16 bits.

**Enable/disable a timer:**

```pwm.enable([0, 1, 2], [true, false]);```
Expand Down
59 changes: 44 additions & 15 deletions src/SAMD21turboPWM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,30 +121,33 @@ int TurboPWM::timer(unsigned int timerNumber, unsigned int TCCDiv, unsigned long

int TurboPWM::analogWrite(int pin, unsigned int dutyCycle) {
// Check if an acceptable pin is used
unsigned int i;
for (i = 0; i < pinTableSize; i++) {
if (pinTable[i].arduinoPin == pin) {
break;
}
}
if (i >= pinTableSize || pin < 0) {
if (checkPin(pin) == 0) {
return 0;
}

// Enable a SAMD21 pin as multiplexed and connect it to a pin using the port multiplexer
PORT->Group[pinTable[pin].port].PINCFG[pinTable[pin].samd21Pin].bit.PMUXEN = 1;
PORT->Group[pinTable[pin].port].PMUX[pinTable[pin].samd21Pin >> 1].reg |= pinTable[pin].pMux;

// Clamp dutycycle to the maximum duty cycle set in the header file; duty cycle will be (dutyCycle / _maxDutyCycle) * 100%
if (dutyCycle > _maxDutyCycle) {
dutyCycle = _maxDutyCycle;
}

// Set duty cycle
*(RwReg*)pinTable[pin].REG_TCCx_CCBy = (timerTable[pinTable[pin].timer].steps * dutyCycle) / _maxDutyCycle;
while (timerTable[pinTable[pin].timer].TCCx->SYNCBUSY.vec.CCB);
dutyCycle = (timerTable[pinTable[pin].timer].steps * dutyCycle) / _maxDutyCycle;

return writeOutput(pin, dutyCycle);
}


int TurboPWM::analogWrite16Bit(int pin, uint16_t dutyCycle) {
// Check if an acceptable pin is used
if (checkPin(pin) == 0) {
return 0;
}

// Clamp dutycycle to the maximum number of steps for the given timer:
if (dutyCycle > timerTable[pinTable[pin].timer].steps) {
dutyCycle = timerTable[pinTable[pin].timer].steps;
}

return 1;
return writeOutput(pin, dutyCycle);
}

int TurboPWM::enable(unsigned int timerNumber, bool enabled) {
Expand Down Expand Up @@ -184,3 +187,29 @@ float TurboPWM::frequency(unsigned int timerNumber) {
}
return (static_cast<float>(VARIANT_MCK) * PLL96M) / (fastDivider * _GCLKDiv * timerTable[timerNumber].TCCDiv * timerTable[timerNumber].steps);
}

bool TurboPWM::checkPin(int pin){
// Check if an acceptable pin is used
unsigned int i;
for (i = 0; i < pinTableSize; i++) {
if (pinTable[i].arduinoPin == pin) {
return 1;
}
}
if (i >= pinTableSize || pin < 0) {
return 0;
}
return 0;
}

int TurboPWM::writeOutput(int pin, uint16_t dutyCycle){
// Enable a SAMD21 pin as multiplexed and connect it to a pin using the port multiplexer
PORT->Group[pinTable[pin].port].PINCFG[pinTable[pin].samd21Pin].bit.PMUXEN = 1;
PORT->Group[pinTable[pin].port].PMUX[pinTable[pin].samd21Pin >> 1].reg |= pinTable[pin].pMux;

// Set duty cycle
*(RwReg*)pinTable[pin].REG_TCCx_CCBy = dutyCycle;
while (timerTable[pinTable[pin].timer].TCCx->SYNCBUSY.vec.CCB);

return 1;
}
3 changes: 3 additions & 0 deletions src/SAMD21turboPWM.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ class TurboPWM {
void setClockDivider(unsigned int GCLKDiv, bool turbo);
int timer(unsigned int timernumber, unsigned int TCCDiv, unsigned long long int steps, bool fastPWM);
int analogWrite(int pin, unsigned int dutyCycle);
int analogWrite16Bit(int pin, uint16_t dutyCycle);
int enable(unsigned int timerNumber, bool enabled);
float frequency(unsigned int timerNumber);
private:
unsigned int _GCLKDiv = 1; // Main clock divider: 1 to 255 for both TCC0 and TCC1
bool _turbo = false; // False for 48MHz clock, true for 96MHz clock
const unsigned int _maxDutyCycle = 1000; // The maximum duty cycle number; duty cycle will be (dutyCycle / _maxDutyCycle) * 100%
bool checkPin(int pin);
int writeOutput(int pin, uint16_t dutyCycle);
};

//Table for looking up and storing values for TCCx
Expand Down