Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: PaulStoffregen/TimerThree
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.1
Choose a base ref
...
head repository: PaulStoffregen/TimerThree
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 17 commits
  • 8 files changed
  • 5 contributors

Commits on Feb 28, 2016

  1. Copy the full SHA
    1ef2c8c View commit details

Commits on Jul 3, 2016

  1. Add Teensy 3.4/3.5

    FrankBoesing authored Jul 3, 2016
    Copy the full SHA
    1ea5be0 View commit details

Commits on Jul 4, 2016

  1. Merge pull request #3 from FrankBoesing/patch-1

    Add Teensy 3.4/3.5
    PaulStoffregen authored Jul 4, 2016
    Copy the full SHA
    3abad53 View commit details
  2. Copy the full SHA
    00b4634 View commit details

Commits on Sep 7, 2016

  1. Copy the full SHA
    3c29710 View commit details
  2. Copy the full SHA
    131600f View commit details

Commits on Sep 8, 2016

  1. Update version to 1.1

    ivankravets authored Sep 8, 2016
    Copy the full SHA
    d9b6af8 View commit details

Commits on Sep 12, 2016

  1. Merge pull request #4 from ivankravets/patch-2

    Update version to 1.1
    PaulStoffregen authored Sep 12, 2016
    Copy the full SHA
    5d85f63 View commit details

Commits on Nov 9, 2016

  1. Copy the full SHA
    2ec999f View commit details

Commits on Jun 14, 2017

  1. Copy the full SHA
    5d04173 View commit details

Commits on Jun 17, 2017

  1. Merge pull request #6 from george-hawkins/master

    Fixed markdown issues related to Github switch to kramdown.
    PaulStoffregen authored Jun 17, 2017
    Copy the full SHA
    8b60890 View commit details

Commits on Mar 15, 2018

  1. Add issue template

    PaulStoffregen committed Mar 15, 2018
    Copy the full SHA
    dcb7067 View commit details

Commits on Jul 1, 2018

  1. Copy the full SHA
    c7bd481 View commit details

Commits on Apr 23, 2019

  1. There is no Timer 1C pin Pin 13 is on Timer 0

    The mega Pin 13 is on Timer 0 not timer 1
    Although the mega Timer 1 is 16 bit it only has two pins on the timer
    photodude authored Apr 23, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8ae965e View commit details
  2. Merge pull request #9 from photodude/patch-1

    Mega Pin 13 is on Timer 0 not Timer 1
    PaulStoffregen authored Apr 23, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    721e2da View commit details

Commits on Dec 27, 2019

  1. Support for Teensy 4.0

    PaulStoffregen committed Dec 27, 2019
    Copy the full SHA
    51b8c17 View commit details

Commits on Feb 24, 2022

  1. Copy the full SHA
    7191911 View commit details
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#TimerThree Library#
TimerThree Library
==================

Paul Stoffregen's modified TimerThree. This version provides 2 main benefits:

1: Optimized inline functions - much faster for the most common usage
2: Support for more boards

http://www.pjrc.com/teensy/td_libs_TimerOne.html
1. Optimized inline functions - much faster for the most common usage
2. Support for more boards

http://www.pjrc.com/teensy/td_libs_TimerOne.html
https://github.com/PaulStoffregen/TimerThree

Original code
@@ -30,4 +30,3 @@ authors under the GNU GPLv2 license. Multiple copies of this library, bearing
the same name but distributed under different license terms, is unfortunately
confusing. This copy, with nearly all the code redesigned as inline functions,
is provided under the "CC BY 3.0 US" license terms.

14 changes: 12 additions & 2 deletions TimerThree.cpp
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ TimerThree Timer3; // preinstatiate

unsigned short TimerThree::pwmPeriod = 0;
unsigned char TimerThree::clockSelectBits = 0;
void (*TimerThree::isrCallback)() = NULL;
void (*TimerThree::isrCallback)() = TimerThree::isrDefaultUnused;

// interrupt service routine that wraps a user defined function supplied by attachInterrupt
#if defined(__AVR__)
@@ -29,7 +29,7 @@ ISR(TIMER3_OVF_vect)
Timer3.isrCallback();
}

#elif defined(__arm__) && defined(CORE_TEENSY)
#elif defined(__arm__) && defined(TEENSYDUINO) && (defined(KINETISK) || defined(KINETISL))
void ftm2_isr(void)
{
uint32_t sc = FTM2_SC;
@@ -41,5 +41,15 @@ void ftm2_isr(void)
Timer3.isrCallback();
}

#elif defined(__arm__) && defined(TEENSYDUINO) && defined(__IMXRT1062__)
void TimerThree::isr(void)
{
FLEXPWM2_SM2STS = FLEXPWM_SMSTS_RF;
Timer3.isrCallback();
}

#endif

void TimerThree::isrDefaultUnused()
{
}
181 changes: 179 additions & 2 deletions TimerThree.h
Original file line number Diff line number Diff line change
@@ -150,6 +150,7 @@ class TimerThree
TIMSK3 = 0;
}
static void (*isrCallback)();
static void isrDefaultUnused();

private:
// properties
@@ -158,14 +159,22 @@ class TimerThree



#elif defined(__arm__) && defined(CORE_TEENSY)
#elif defined(__arm__) && defined(TEENSYDUINO) && (defined(KINETISK) || defined(KINETISL))

#if defined(KINETISK)
#define F_TIMER F_BUS
#elif defined(KINETISL)
#define F_TIMER (F_PLL/2)
#endif

// Use only 15 bit resolution. From K66 reference manual, 45.5.7 page 1200:
// The CPWM pulse width (duty cycle) is determined by 2 x (CnV - CNTIN) and the
// period is determined by 2 x (MOD - CNTIN). See the following figure. MOD must be
// kept in the range of 0x0001 to 0x7FFF because values outside this range can produce
// ambiguous results.
#undef TIMER3_RESOLUTION
#define TIMER3_RESOLUTION 32768

public:
//****************************
// Configuration
@@ -175,6 +184,48 @@ class TimerThree
}
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
const unsigned long cycles = (F_TIMER / 2000000) * microseconds;

/*
// This code does not work properly in all cases :(
// https://github.com/PaulStoffregen/TimerOne/issues/17
if (cycles < TIMER3_RESOLUTION * 16) {
if (cycles < TIMER3_RESOLUTION * 4) {
if (cycles < TIMER3_RESOLUTION) {
clockSelectBits = 0;
pwmPeriod = cycles;
}else{
clockSelectBits = 1;
pwmPeriod = cycles >> 1;
}
}else{
if (cycles < TIMER3_RESOLUTION * 8) {
clockSelectBits = 3;
pwmPeriod = cycles >> 3;
}else{
clockSelectBits = 4;
pwmPeriod = cycles >> 4;
}
}
}else{
if (cycles > TIMER3_RESOLUTION * 64) {
if (cycles > TIMER3_RESOLUTION * 128) {
clockSelectBits = 7;
pwmPeriod = TIMER3_RESOLUTION - 1;
}else{
clockSelectBits = 7;
pwmPeriod = cycles >> 7;
}
}else{
if (cycles > TIMER3_RESOLUTION * 32) {
clockSelectBits = 6;
pwmPeriod = cycles >> 6;
}else{
clockSelectBits = 5;
pwmPeriod = cycles >> 5;
}
}
}
*/
if (cycles < TIMER3_RESOLUTION) {
clockSelectBits = 0;
pwmPeriod = cycles;
@@ -210,6 +261,7 @@ class TimerThree
clockSelectBits = 7;
pwmPeriod = TIMER3_RESOLUTION - 1;
}

uint32_t sc = FTM2_SC;
FTM2_SC = 0;
FTM2_MOD = pwmPeriod;
@@ -231,7 +283,7 @@ class TimerThree
start();
}
void resume() __attribute__((always_inline)) {
FTM2_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
FTM2_SC = (FTM2_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
}

//****************************
@@ -284,6 +336,7 @@ class TimerThree
NVIC_DISABLE_IRQ(IRQ_FTM2);
}
static void (*isrCallback)();
static void isrDefaultUnused();

private:
// properties
@@ -292,6 +345,130 @@ class TimerThree

#undef F_TIMER

#elif defined(__arm__) && defined(TEENSYDUINO) && defined(__IMXRT1062__)

public:
//****************************
// Configuration
//****************************
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
setPeriod(microseconds);
}
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
uint32_t period = (float)F_BUS_ACTUAL * (float)microseconds * 0.0000005f;
uint32_t prescale = 0;
while (period > 32767) {
period = period >> 1;
if (++prescale > 7) {
prescale = 7; // when F_BUS is 150 MHz, longest
period = 32767; // period is 55922 us (~17.9 Hz)
break;
}
}
//Serial.printf("setPeriod, period=%u, prescale=%u\n", period, prescale);
FLEXPWM2_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(4); // logic high = fault
FLEXPWM2_FSTS0 = 0x0008; // clear fault status
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_CLDOK(4);
FLEXPWM2_SM2CTRL2 = FLEXPWM_SMCTRL2_INDEP;
FLEXPWM2_SM2CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale);
FLEXPWM2_SM2INIT = -period;
FLEXPWM2_SM2VAL0 = 0;
FLEXPWM2_SM2VAL1 = period;
FLEXPWM2_SM2VAL2 = 0;
FLEXPWM2_SM2VAL3 = 0;
FLEXPWM2_SM2VAL4 = 0;
FLEXPWM2_SM2VAL5 = 0;
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_LDOK(4) | FLEXPWM_MCTRL_RUN(4);
pwmPeriod = period;
}
//****************************
// Run Control
//****************************
void start() __attribute__((always_inline)) {
stop();
// TODO: how to force counter back to zero?
resume();
}
void stop() __attribute__((always_inline)) {
FLEXPWM2_MCTRL &= ~FLEXPWM_MCTRL_RUN(4);
}
void restart() __attribute__((always_inline)) {
start();
}
void resume() __attribute__((always_inline)) {
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_RUN(4);
}

//****************************
// PWM outputs
//****************************
void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) {
if (duty > 1023) duty = 1023;
int dutyCycle = (pwmPeriod * duty) >> 10;
//Serial.printf("setPwmDuty, period=%u\n", dutyCycle);
if (pin == TIMER3_A_PIN) {
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_CLDOK(4);
FLEXPWM2_SM2VAL5 = dutyCycle;
FLEXPWM2_SM2VAL4 = -dutyCycle;
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_LDOK(4);
} else if (pin == TIMER3_B_PIN) {
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_CLDOK(4);
FLEXPWM2_SM2VAL3 = dutyCycle;
FLEXPWM2_SM2VAL2 = -dutyCycle;
FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_LDOK(4);
}
}
void pwm(char pin, unsigned int duty) __attribute__((always_inline)) {
setPwmDuty(pin, duty);
if (pin == TIMER3_A_PIN) {
FLEXPWM2_OUTEN |= FLEXPWM_OUTEN_PWMB_EN(4);
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_11 = 2; // pin 9 FLEXPWM2_PWM2_B
} else if (pin == TIMER3_B_PIN) {
FLEXPWM2_OUTEN |= FLEXPWM_OUTEN_PWMA_EN(4);
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_10 = 2; // pin 6 FLEXPWM2_PWM2_A
}
}
void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) {
if (microseconds > 0) setPeriod(microseconds);
pwm(pin, duty);
}
void disablePwm(char pin) __attribute__((always_inline)) {
if (pin == TIMER3_A_PIN) {
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_11 = 5; // pin 9 FLEXPWM2_PWM2_B
FLEXPWM2_OUTEN &= ~FLEXPWM_OUTEN_PWMB_EN(4);
} else if (pin == TIMER3_B_PIN) {
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_10 = 5; // pin 6 FLEXPWM2_PWM2_A
FLEXPWM2_OUTEN &= ~FLEXPWM_OUTEN_PWMA_EN(4);
}
}
//****************************
// Interrupt Function
//****************************
void attachInterrupt(void (*f)()) __attribute__((always_inline)) {
isrCallback = f;
attachInterruptVector(IRQ_FLEXPWM2_2, &isr);
FLEXPWM2_SM2STS = FLEXPWM_SMSTS_RF;
FLEXPWM2_SM2INTEN = FLEXPWM_SMINTEN_RIE;
NVIC_ENABLE_IRQ(IRQ_FLEXPWM2_2);
}
void attachInterrupt(void (*f)(), unsigned long microseconds) __attribute__((always_inline)) {
if(microseconds > 0) setPeriod(microseconds);
attachInterrupt(f);
}
void detachInterrupt() __attribute__((always_inline)) {
NVIC_DISABLE_IRQ(IRQ_FLEXPWM2_2);
FLEXPWM2_SM2INTEN = 0;
}
static void isr(void);
static void (*isrCallback)();
static void isrDefaultUnused();

private:
// properties
static unsigned short pwmPeriod;
static unsigned char clockSelectBits;


#endif
};

23 changes: 20 additions & 3 deletions config/known_16bit_timers.h
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@
#define TIMER1_B_PIN 4
#define TIMER1_ICP_PIN 4

// Teensy 3.1
// Teensy 3.1 / Teensy 3.2
//
#elif defined(__MK20DX256__)
#define TIMER1_A_PIN 3
@@ -48,7 +48,17 @@
#define TIMER3_A_PIN 32
#define TIMER3_B_PIN 25
#define TIMER3_ICP_PIN 32


// Teensy 3.5 / Teensy 3.6
//
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define TIMER1_A_PIN 3
#define TIMER1_B_PIN 4
#define TIMER1_ICP_PIN 4
#define TIMER3_A_PIN 29
#define TIMER3_B_PIN 30
#define TIMER3_ICP_PIN 29

// Teensy-LC
//
#elif defined(__MKL26Z64__)
@@ -59,12 +69,19 @@
#define TIMER3_B_PIN 4
#define TIMER3_ICP_PIN 4

// Teensy 4.0
//
#elif defined(__IMXRT1062__)
#define TIMER1_A_PIN 7
#define TIMER1_B_PIN 8
#define TIMER3_A_PIN 9
#define TIMER3_B_PIN 6

// Arduino Mega
//
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER1_A_PIN 11
#define TIMER1_B_PIN 12
#define TIMER1_C_PIN 13
#define TIMER3_A_PIN 5
#define TIMER3_B_PIN 2
#define TIMER3_C_PIN 3
Loading