diff --git a/README.md b/README.md index af5460e..ebf6523 100644 --- a/README.md +++ b/README.md @@ -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]);``` diff --git a/src/SAMD21turboPWM.cpp b/src/SAMD21turboPWM.cpp index 171f07d..094fdbf 100644 --- a/src/SAMD21turboPWM.cpp +++ b/src/SAMD21turboPWM.cpp @@ -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) { @@ -184,3 +187,29 @@ float TurboPWM::frequency(unsigned int timerNumber) { } return (static_cast(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; +} \ No newline at end of file diff --git a/src/SAMD21turboPWM.h b/src/SAMD21turboPWM.h index 528b782..76c261e 100644 --- a/src/SAMD21turboPWM.h +++ b/src/SAMD21turboPWM.h @@ -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