aboutsummaryrefslogtreecommitdiffstats
path: root/notes/timers.txt
blob: 3f5b9f415107bb11e7933442eb4822d947d16b16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

Each timer (1-4) has 4 capture/compare channels (1-4). These are directly used
by PWM but have a ton of other possible functionality. The STM32 implementation
is particularly complicated with, eg, the ability to chain together timers

Timer1 is an "advanced timer" with many more features. I think if we use just
the "Capture and compare interrupt", and enable MOE during initialization
everything will be ok. There are seperate Break, Update, and Trigger interrupts
as well that we will ignore for now.

Timer2,Ch 3+4 are D0 and D1, which conflict with Serial2. USART should work
fine as long as pins aren't in output mode? and timers should work fine if
Serial2 isn't in use?

Caveats
------------------------------------------------------------------------------
There are probably subtle bugs with the way register settings get read in; eg,
it is often required to have the counter fully overflow before new settings
come into effect?
Getting really good timing is still an art, not a science here... usually you 
need to fiddle with an oscilloscope and the exact overflow/compare numbers to
get just the right time values.
Any other interrupts (SysTick, USB, Serial, etc) can blow away all the nice 
timing stuff.

Misc Notes
------------------------------------------------------------------------------
Implementation with case/switch in the interrupt handlers doesn't work; a lot
of the time multiple interrupt flags are active at the same time (or become
active?)

TODO
------------------------------------------------------------------------------
- document carefully (eg, determine clock-wise and overflow-wise behavior for
  each function)
- track down and handle all pin conflicts
- implement the update interrupt as a "5th channel"
- "pulse in" stuff, both c and c++
- function to read out CCR registers
- allow comparison output to the pin (a la PWM)
- additional modes and configuration (up, down, up/down, etc)

Possible Wirish implementation
------------------------------------------------------------------------------
Inspired by Timer1 Library for arduino
http://arduino.cc/pipermail/developers_arduino.cc/2010-June/002845.html

        class HardwareTimer {

        public:

            void pause();
            void resume();
            void setPrescaleFactor(uint8 factor);
            void setOverflow(uint16 val); // truncates to overflow
            void setCount(uint16 val);    // truncates to overflow
            uint16 getCount();
            uint16 setPeriod(uint32 microseconds); // tries to set prescaler and overflow wisely; returns overflow
            void setMode(uint8 mode);
            void setCompare1(uint16 val); // truncates to overflow
            void setCompare2(uint16 val); // truncates to overflow
            void setCompare3(uint16 val); // truncates to overflow
            void setCompare4(uint16 val); // truncates to overflow
            void attachCompare1Interrupt(void (*f)(void));
            void attachCompare2Interrupt(void (*f)(void));
            void attachCompare3Interrupt(void (*f)(void));
            void attachCompare4Interrupt(void (*f)(void));
            void detachCompare1Interrupt();
            void detachCompare2Interrupt();
            void detachCompare3Interrupt();
            void detachCompare4Interrupt();
        };

        HardwareTimer Timer1 = HardwareTimer(1);
        HardwareTimer Timer2 = HardwareTimer(2);
        HardwareTimer Timer3 = HardwareTimer(3);
        HardwareTimer Timer4 = HardwareTimer(4);

Here's one of the more standard libaries out there:
http://www.arduino.cc/playground/Code/Timer1

        void initialize(long microseconds=1000000);
        void start();
        void stop();
        void restart();
        void setPeriod(long microseconds);
        void pwm(char pin, int duty, long microseconds=-1);
        void setPwmDuty(char pin, int duty);
        void disablePwm(char pin);
        void attachInterrupt(void (*isr)(), long microseconds=-1);
        void detachInterrupt();