Skip to content

Commit 2b9a7f6

Browse files
committed
imported TimerOne library
1 parent 3940d99 commit 2b9a7f6

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed

libraries/TimerOne/TimerOne.cpp

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
3+
* Original code by Jesse Tane for http://labs.ideo.com August 2008
4+
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
5+
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
6+
* Modified June 2011 by Lex Talionis to add a function to read the timer
7+
*
8+
* This is free software. You can redistribute it and/or modify it under
9+
* the terms of Creative Commons Attribution 3.0 United States License.
10+
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
11+
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
12+
*
13+
* See Google Code project http://code.google.com/p/arduino-timerone/ for latest
14+
*/
15+
#ifndef TIMERONE_cpp
16+
#define TIMERONE_cpp
17+
18+
#include "TimerOne.h"
19+
20+
TimerOne Timer1; // preinstatiate
21+
22+
ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt
23+
{
24+
Timer1.isrCallback();
25+
}
26+
27+
void TimerOne::initialize(long microseconds)
28+
{
29+
TCCR1A = 0; // clear control register A
30+
TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer
31+
setPeriod(microseconds);
32+
}
33+
34+
void TimerOne::setPeriod(long microseconds)
35+
{
36+
long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
37+
if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal
38+
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8
39+
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64
40+
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256
41+
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024
42+
else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum
43+
ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode
44+
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
45+
TCCR1B |= clockSelectBits; // reset clock select register
46+
}
47+
48+
void TimerOne::setPwmDuty(char pin, int duty)
49+
{
50+
unsigned long dutyCycle = pwmPeriod;
51+
dutyCycle *= duty;
52+
dutyCycle >>= 10;
53+
if(pin == 1 || pin == 9) OCR1A = dutyCycle;
54+
else if(pin == 2 || pin == 10) OCR1B = dutyCycle;
55+
}
56+
57+
void TimerOne::pwm(char pin, int duty, long microseconds) // expects duty cycle to be 10 bit (1024)
58+
{
59+
if(microseconds > 0) setPeriod(microseconds);
60+
if(pin == 1 || pin == 9) {
61+
DDRB |= _BV(PORTB1); // sets data direction register for pwm output pin
62+
TCCR1A |= _BV(COM1A1); // activates the output pin
63+
}
64+
else if(pin == 2 || pin == 10) {
65+
DDRB |= _BV(PORTB2);
66+
TCCR1A |= _BV(COM1B1);
67+
}
68+
setPwmDuty(pin, duty);
69+
start();
70+
}
71+
72+
void TimerOne::disablePwm(char pin)
73+
{
74+
if(pin == 1 || pin == 9) TCCR1A &= ~_BV(COM1A1); // clear the bit that enables pwm on PB1
75+
else if(pin == 2 || pin == 10) TCCR1A &= ~_BV(COM1B1); // clear the bit that enables pwm on PB2
76+
}
77+
78+
void TimerOne::attachInterrupt(void (*isr)(), long microseconds)
79+
{
80+
if(microseconds > 0) setPeriod(microseconds);
81+
isrCallback = isr; // register the user's callback with the real ISR
82+
TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit
83+
sei(); // ensures that interrupts are globally enabled
84+
start();
85+
}
86+
87+
void TimerOne::detachInterrupt()
88+
{
89+
TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit
90+
}
91+
92+
void TimerOne::start()
93+
{
94+
TCCR1B |= clockSelectBits;
95+
}
96+
97+
void TimerOne::stop()
98+
{
99+
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits
100+
}
101+
102+
void TimerOne::restart()
103+
{
104+
TCNT1 = 0;
105+
}
106+
107+
unsigned long TimerOne::read() //returns the value of the timer in microseconds
108+
{ //rember! phase and freq correct mode counts up to then down again
109+
unsigned int tmp=TCNT1;
110+
char scale=0;
111+
switch (clockSelectBits)
112+
{
113+
case 1:// no prescalse
114+
scale=0;
115+
break;
116+
case 2:// x8 prescale
117+
scale=3;
118+
break;
119+
case 3:// x64
120+
scale=6;
121+
break;
122+
case 4:// x256
123+
scale=8;
124+
break;
125+
case 5:// x1024
126+
scale=10;
127+
break;
128+
}
129+
while (TCNT1==tmp) //if the timer has not ticked yet
130+
{
131+
//do nothing -- max delay here is ~1023 cycles
132+
}
133+
tmp = ( (TCNT1>tmp) ? (tmp) : (ICR1-TCNT1)+ICR1 );//if we are counting down add the top value to how far we have counted down
134+
return ((tmp*1000L)/(F_CPU /1000L))<<scale;
135+
}
136+
137+
#endif

libraries/TimerOne/TimerOne.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
3+
* Original code by Jesse Tane for http://labs.ideo.com August 2008
4+
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
5+
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
6+
* Modified June 2011 by Lex Talionis to add a function to read the timer
7+
*
8+
* This is free software. You can redistribute it and/or modify it under
9+
* the terms of Creative Commons Attribution 3.0 United States License.
10+
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
11+
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
12+
*
13+
* See Google Code project http://code.google.com/p/arduino-timerone/ for latest
14+
*/
15+
#ifndef TIMERONE_h
16+
#define TIMERONE_h
17+
18+
#include <avr/io.h>
19+
#include <avr/interrupt.h>
20+
21+
#define RESOLUTION 65536 // Timer1 is 16 bit
22+
23+
class TimerOne
24+
{
25+
public:
26+
27+
// properties
28+
unsigned int pwmPeriod;
29+
unsigned char clockSelectBits;
30+
31+
// methods
32+
void initialize(long microseconds=1000000);
33+
void start();
34+
void stop();
35+
void restart();
36+
unsigned long read();
37+
void pwm(char pin, int duty, long microseconds=-1);
38+
void disablePwm(char pin);
39+
void attachInterrupt(void (*isr)(), long microseconds=-1);
40+
void detachInterrupt();
41+
void setPeriod(long microseconds);
42+
void setPwmDuty(char pin, int duty);
43+
void (*isrCallback)();
44+
};
45+
46+
extern TimerOne Timer1;
47+
#endif
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Timer1 library example
3+
* June 2008 | jesse dot tane at gmail dot com
4+
*/
5+
6+
#include "TimerOne.h"
7+
8+
void setup()
9+
{
10+
pinMode(10, OUTPUT);
11+
Timer1.initialize(500000); // initialize timer1, and set a 1/2 second period
12+
Timer1.pwm(9, 512); // setup pwm on pin 9, 50% duty cycle
13+
Timer1.attachInterrupt(callback); // attaches callback() as a timer overflow interrupt
14+
}
15+
16+
void callback()
17+
{
18+
digitalWrite(10, digitalRead(10) ^ 1);
19+
}
20+
21+
void loop()
22+
{
23+
// your program here...
24+
}
25+

0 commit comments

Comments
 (0)