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
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ const int fanPin = 4;

void setup(void)
{
Timer1.initialize(40); // 40 us = 25 kHz
//Timer1.initialize(40); // 40 us = 25 kHz
Timer1.setFrequency(25000); // 25 kHz
Serial.begin(9600);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
#include <TimerOne.h>

// This example uses the timer interrupt to blink an LED
// and also demonstrates how to share a variable between
// the interrupt and the main program.


const int led = LED_BUILTIN; // the pin with a LED

void setup(void)
{
pinMode(led, OUTPUT);
Timer1.initialize(150000);
Timer1.attachInterrupt(blinkLED); // blinkLED to run every 0.15 seconds
Serial.begin(9600);
}


// The interrupt will blink the LED, and keep
// track of how many times it has blinked.
Expand All @@ -33,6 +20,19 @@ void blinkLED(void)
}



void setup(void)
{
pinMode(led, OUTPUT);
//Timer1.initialize(150000);
//Timer1.attachInterrupt(blinkLED); // blinkLED to run every 0.15 seconds
//Timer1.initialize(150000).attachInterrupt(blinkLED); //alternative way to enable the timer in one line
Timer1.setFrequency(6.66).attachInterrupt(blinkLED); //alternative way to enable the timer by frequency
Serial.begin(9600);
}



// The main program will print the blink count
// to the Arduino Serial Monitor
void loop(void)
Expand All @@ -44,11 +44,12 @@ void loop(void)
// not change while we are reading. To minimize the time
// with interrupts off, just quickly make a copy, and then
// use the copy while allowing the interrupt to keep working.
noInterrupts();
blinkCopy = blinkCount;
interrupts();
//noInterrupts();
//blinkCopy = blinkCount;
//interrupts();

Serial.print("blinkCount = ");
Serial.println(blinkCopy);
delay(100);

}
File renamed without changes.
110 changes: 61 additions & 49 deletions TimerOne.h → src/TimerOne.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ class TimerOne
//****************************
// Configuration
//****************************
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
TimerOne& initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer
TCCR1A = 0; // clear control register A
setPeriod(microseconds);
return *this;
}
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
const unsigned long cycles = (F_CPU / 2000000) * microseconds;
Expand Down Expand Up @@ -76,6 +77,10 @@ class TimerOne
ICR1 = pwmPeriod;
TCCR1B = _BV(WGM13) | clockSelectBits;
}
TimerOne& setFrequency(float f = 1) {
unsigned long period = 1000000 / f;
return initialize(period);
}

//****************************
// Run Control
Expand Down Expand Up @@ -138,13 +143,14 @@ class TimerOne
//****************************
// Interrupt Function
//****************************
void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
TimerOne& attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
isrCallback = isr;
TIMSK1 = _BV(TOIE1);
return *this;
}
void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
TimerOne& attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
if(microseconds > 0) setPeriod(microseconds);
attachInterrupt(isr);
return attachInterrupt(isr);
}
void detachInterrupt() __attribute__((always_inline)) {
TIMSK1 = 0;
Expand Down Expand Up @@ -174,11 +180,12 @@ class TimerOne
//****************************
// Configuration
//****************************
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
setPeriod(microseconds);
TimerOne& initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
setPeriod(microseconds);
return *this;
}
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
const unsigned long cycles = (F_TIMER / 2000000) * microseconds;
const unsigned long cycles = (F_TIMER / 2000000) * microseconds;
// A much faster if-else
// This is like a binary serch tree and no more than 3 conditions are evaluated.
// I haven't checked if this becomes significantly longer ASM than the simple ladder.
Expand Down Expand Up @@ -226,47 +233,51 @@ class TimerOne
}
}
*/
if (cycles < TIMER1_RESOLUTION) {
clockSelectBits = 0;
pwmPeriod = cycles;
} else
if (cycles < TIMER1_RESOLUTION * 2) {
clockSelectBits = 1;
pwmPeriod = cycles >> 1;
} else
if (cycles < TIMER1_RESOLUTION * 4) {
clockSelectBits = 2;
pwmPeriod = cycles >> 2;
} else
if (cycles < TIMER1_RESOLUTION * 8) {
clockSelectBits = 3;
pwmPeriod = cycles >> 3;
} else
if (cycles < TIMER1_RESOLUTION * 16) {
clockSelectBits = 4;
pwmPeriod = cycles >> 4;
} else
if (cycles < TIMER1_RESOLUTION * 32) {
clockSelectBits = 5;
pwmPeriod = cycles >> 5;
} else
if (cycles < TIMER1_RESOLUTION * 64) {
clockSelectBits = 6;
pwmPeriod = cycles >> 6;
} else
if (cycles < TIMER1_RESOLUTION * 128) {
clockSelectBits = 7;
pwmPeriod = cycles >> 7;
} else {
clockSelectBits = 7;
pwmPeriod = TIMER1_RESOLUTION - 1;
}

uint32_t sc = FTM1_SC;
FTM1_SC = 0;
FTM1_MOD = pwmPeriod;
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE);
if (cycles < TIMER1_RESOLUTION) {
clockSelectBits = 0;
pwmPeriod = cycles;
} else
if (cycles < TIMER1_RESOLUTION * 2) {
clockSelectBits = 1;
pwmPeriod = cycles >> 1;
} else
if (cycles < TIMER1_RESOLUTION * 4) {
clockSelectBits = 2;
pwmPeriod = cycles >> 2;
} else
if (cycles < TIMER1_RESOLUTION * 8) {
clockSelectBits = 3;
pwmPeriod = cycles >> 3;
} else
if (cycles < TIMER1_RESOLUTION * 16) {
clockSelectBits = 4;
pwmPeriod = cycles >> 4;
} else
if (cycles < TIMER1_RESOLUTION * 32) {
clockSelectBits = 5;
pwmPeriod = cycles >> 5;
} else
if (cycles < TIMER1_RESOLUTION * 64) {
clockSelectBits = 6;
pwmPeriod = cycles >> 6;
} else
if (cycles < TIMER1_RESOLUTION * 128) {
clockSelectBits = 7;
pwmPeriod = cycles >> 7;
} else {
clockSelectBits = 7;
pwmPeriod = TIMER1_RESOLUTION - 1;
}

uint32_t sc = FTM1_SC;
FTM1_SC = 0;
FTM1_MOD = pwmPeriod;
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE);
}
TimerOne& setFrequency(float f = 1) {
unsigned long period = 1000000 / f;
return initialize(period);
}

//****************************
// Run Control
Expand Down Expand Up @@ -322,14 +333,15 @@ class TimerOne
//****************************
// Interrupt Function
//****************************
void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
TimerOne& attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
isrCallback = isr;
FTM1_SC |= FTM_SC_TOIE;
NVIC_ENABLE_IRQ(IRQ_FTM1);
return *this;
}
void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
if(microseconds > 0) setPeriod(microseconds);
attachInterrupt(isr);
return attachInterrupt(isr);
}
void detachInterrupt() __attribute__((always_inline)) {
FTM1_SC &= ~FTM_SC_TOIE;
Expand Down
File renamed without changes.