source: orbit/arduino/libraries/PWM/utility/ATimerDefs.cpp @ 1f70352

RawEEGRaw_EEG_PlotServoTab_Interfacepyramid
Last change on this file since 1f70352 was 1f70352, checked in by AzureViolin <zhanghaotz@…>, 9 years ago

arduino fly Orbit

  • Property mode set to 100644
File size: 9.7 KB
Line 
1/*
2Copyright (c) 2012 Sam Knight
3Permission is hereby granted, free of charge, to any person obtaining a copy
4of this software and associated documentation files (the "Software"), to deal
5in the Software without restriction, including without limitation the rights to
6use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7of the Software, and to permit persons to whom the Software is furnished to do
8so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19*/
20
21#if defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
22
23#include "wiring_private.h"
24#include "../PWM.h"
25
26#define UINT16_MAX 65535
27#define UINT8_MAX 255
28
29//--------------------------------------------------------------------------------
30//                                                      Helper Functions
31//--------------------------------------------------------------------------------
32
33static float toBaseTwo(double baseTenNum)
34{
35        return log(baseTenNum + 1)/log(2);
36}
37
38//--------------------------------------------------------------------------------
39//                                                      16 Bit Timer Functions
40//--------------------------------------------------------------------------------
41
42uint32_t GetFrequency_16(const int16_t timerOffset)
43{
44        return (int32_t)(F_CPU/(2 * (int32_t)GetTop_16(timerOffset) * GetPrescaler_16(timerOffset)));
45}
46
47bool SetFrequency_16(const int16_t timerOffset, uint32_t f)
48{
49        if(f > 2000000 || f < 1)
50        return false;
51       
52        //find the smallest usable multiplier
53        uint16_t multiplier = (int16_t)(F_CPU / (2 * f * UINT16_MAX));
54       
55        uint8_t iterate = 0;
56        while(multiplier > pscLst[iterate++]);
57       
58        multiplier = pscLst[iterate];           //multiplier holds the clock select value, and iterate holds the corresponding CS flag
59       
60        //getting the timer top using the new multiplier
61        uint16_t timerTop = (uint16_t)(F_CPU/(2* f * multiplier));
62       
63        SetTop_16(timerOffset, timerTop);
64        SetPrescaler_16(timerOffset, (prescaler)iterate);
65       
66        return true;
67}
68
69uint16_t GetPrescaler_16(const int16_t timerOffset)
70{
71        return pscLst[(TCCRB_16(timerOffset) & 7)];
72}
73
74void SetPrescaler_16(const int16_t timerOffset, prescaler psc)
75{
76        TCCRB_16(timerOffset) = (TCCRB_16(timerOffset) & ~7) | (psc & 7);
77}
78
79void SetTop_16(const int16_t timerOffset, uint16_t top)
80{
81        ICR_16(timerOffset) = top;
82}
83
84uint16_t GetTop_16(const int16_t timerOffset)
85{
86        return ICR_16(timerOffset);
87}
88
89void Initialize_16(const int16_t timerOffset)
90{
91        //setting the waveform generation mode
92        uint8_t wgm = 8;
93       
94        TCCRA_16(timerOffset) = (TCCRA_16(timerOffset) & B11111100) | (wgm & 3);
95        TCCRB_16(timerOffset) = (TCCRB_16(timerOffset) & B11100111) | ((wgm & 12) << 1);
96       
97        SetFrequency_16(timerOffset, 500);
98}
99
100float GetResolution_16(const int16_t timerOffset)
101{
102        return toBaseTwo(ICR_16(timerOffset));
103}
104
105//--------------------------------------------------------------------------------
106//                                                      8 Bit Timer Functions
107//--------------------------------------------------------------------------------
108
109uint32_t GetFrequency_8(const int16_t timerOffset)
110{
111        return (uint32_t)(F_CPU/((uint32_t)2 * GetTop_8(timerOffset) * GetPrescaler_8(timerOffset)));
112}
113
114bool SetFrequency_8(const int16_t timerOffset, uint32_t f)
115{
116        if(f > 2000000 || f < 31)
117                return false;
118       
119        //find the smallest usable multiplier
120        uint16_t multiplier = (F_CPU / (2 * (uint32_t)f * UINT8_MAX));
121       
122        uint8_t iterate = 0;
123        uint16_t timerTop;
124       
125        do
126        {
127                if(TIMER2_OFFSET != timerOffset)
128                {
129                        while(multiplier > pscLst[++iterate]);
130                        multiplier = pscLst[iterate];
131                }
132                else
133                {
134                        while(multiplier > pscLst_alt[++iterate]);
135                        multiplier = pscLst_alt[iterate];
136                }
137                //getting the timer top using the new multiplier
138                timerTop = (F_CPU/(2* f * (uint32_t)multiplier));
139        } while (timerTop > UINT8_MAX);
140       
141        SetTop_8(timerOffset, timerTop);
142       
143        if(timerOffset != TIMER2_OFFSET)
144        SetPrescaler_8(timerOffset, (prescaler)iterate);
145        else
146        SetPrescalerAlt_8(timerOffset, (prescaler_alt)iterate);
147       
148        return true;
149}
150
151uint16_t GetPrescaler_8(const int16_t timerOffset)
152{
153        if(timerOffset != TIMER2_OFFSET)
154                return pscLst[(TCCRB_8(timerOffset) & 7)];
155        else
156                return pscLst_alt[(TCCRB_8(timerOffset) & 7)];
157}
158
159void SetPrescalerAlt_8(const int16_t timerOffset, prescaler_alt psc)
160{
161        TCCRB_8(timerOffset) = (TCCRB_8(timerOffset) & ~7) | (psc & 7);
162}
163
164void SetPrescaler_8(const int16_t timerOffset, prescaler psc)
165{
166        TCCRB_8(timerOffset) = (TCCRB_8(timerOffset) & ~7) | (psc & 7);
167}
168
169void SetTop_8(const int16_t timerOffset, uint8_t top)
170{
171        OCRA_8(timerOffset) = top;
172}
173
174uint8_t GetTop_8(const int16_t timerOffset)
175{
176        return OCRA_8(timerOffset);
177}
178
179void Initialize_8(const int16_t timerOffset)
180{
181        //setting the waveform generation mode
182        uint8_t wgm = 5;
183       
184        TCCRA_8(timerOffset) = (TCCRA_8(timerOffset) & B11111100) | (wgm & 3);
185        TCCRB_8(timerOffset) = (TCCRB_8(timerOffset) & B11110111) | ((wgm & 12) << 1);
186       
187        //disable timer0's interrupt when initialization is called, otherwise handler will eat
188        //up processor cycles when PWM on timer0 is set to high frequencies. This will effectively disable
189        //Arduino's time keeping functions, which the user should be aware of before initializing timer0
190        if(timerOffset == 0)
191        {
192                TIMSK0 &= B11111110;
193        }
194       
195        SetFrequency_8(timerOffset, 500);
196}
197
198float GetResolution_8(const int16_t timerOffset)
199{
200        return toBaseTwo(OCRA_8(timerOffset));
201}
202
203//--------------------------------------------------------------------------------
204//                                                      Timer Independent Functions
205//--------------------------------------------------------------------------------
206
207void pwmWrite(uint8_t pin, uint8_t val)
208{
209        pinMode(pin, OUTPUT);
210       
211        uint32_t tmp = val;
212       
213        if (val == 0)
214                digitalWrite(pin, LOW);
215        else if (val == 255)
216                digitalWrite(pin, HIGH);
217        else
218        {
219                TimerData td = timer_to_pwm_data[digitalPinToTimer(pin)];
220                if(td.ChannelRegLoc) //null checking
221                {
222                        if(td.Is16Bit)
223                        {
224                                sbi(_SFR_MEM8(td.PinConnectRegLoc), td.PinConnectBits);
225                                _SFR_MEM16(td.ChannelRegLoc) = (tmp * _SFR_MEM16(td.TimerTopRegLoc)) / 255;
226                        }
227                        else
228                        {
229                                sbi(_SFR_MEM8(td.PinConnectRegLoc), td.PinConnectBits);
230                                _SFR_MEM8(td.ChannelRegLoc) = (tmp * _SFR_MEM8(td.TimerTopRegLoc)) / 255;
231                        }
232                }               
233        }
234}
235
236//takes a 16 bit value instead of an 8 bit value for maximum resolution
237void pwmWriteHR(uint8_t pin, uint16_t val)
238{
239        pinMode(pin, OUTPUT);
240       
241        uint32_t tmp = val;     
242       
243        if (val == 0)
244        digitalWrite(pin, LOW);
245        else if (val == 65535)
246        digitalWrite(pin, HIGH);
247        else
248        {
249                TimerData td = timer_to_pwm_data[digitalPinToTimer(pin)];
250                if(td.ChannelRegLoc) //null checking
251                {
252                        if(td.Is16Bit)
253                        {
254                                sbi(_SFR_MEM8(td.PinConnectRegLoc), td.PinConnectBits);
255                                _SFR_MEM16(td.ChannelRegLoc) = (tmp * _SFR_MEM16(td.TimerTopRegLoc)) / 65535;
256                        }
257                        else
258                        {
259                                sbi(_SFR_MEM8(td.PinConnectRegLoc), td.PinConnectBits);
260                                _SFR_MEM8(td.ChannelRegLoc) = (tmp * _SFR_MEM8(td.TimerTopRegLoc)) / 65535;
261                        }
262                }
263        }
264}
265
266//Initializes all timer objects, setting them to modes compatible with frequency manipulation. All timers are set to 488 - 500 Hz at the end of initialization.
267void InitTimers()
268{
269        Timer0_Initialize();
270        InitTimersSafe();
271}
272
273//initializes all timer objects except for timer 0, which is necessary for the Arduino's time keeping functions
274void InitTimersSafe()
275{
276        Timer1_Initialize();
277        Timer2_Initialize();
278        Timer3_Initialize();
279        Timer4_Initialize();
280        Timer5_Initialize();
281}
282
283bool SetPinFrequency(int8_t pin, uint32_t frequency)
284{
285        uint8_t timer = digitalPinToTimer(pin);
286       
287        if(timer == TIMER0B)
288        return Timer0_SetFrequency(frequency);
289        else if(timer == TIMER1A || timer == TIMER1B)
290        return Timer1_SetFrequency(frequency);
291        else if(timer == TIMER2B)
292        return Timer2_SetFrequency(frequency);
293        else if(timer == TIMER3A || timer == TIMER3B || timer == TIMER3C)
294        return Timer3_SetFrequency(frequency);
295        else if(timer == TIMER4A || timer == TIMER4B || timer == TIMER4C)
296        return Timer4_SetFrequency(frequency);
297        else if(timer == TIMER5A || timer == TIMER5B || timer == TIMER5C)
298        return Timer5_SetFrequency(frequency);
299        else
300        return false;
301}
302
303bool SetPinFrequencySafe(int8_t pin, uint32_t frequency)
304{
305        uint8_t timer = digitalPinToTimer(pin);
306       
307        if(timer == TIMER1A || timer == TIMER1B)
308        return Timer1_SetFrequency(frequency);
309        else if(timer == TIMER2B)
310        return Timer2_SetFrequency(frequency);
311        else if(timer == TIMER3A || timer == TIMER3B || timer == TIMER3C)
312        return Timer3_SetFrequency(frequency);
313        else if(timer == TIMER4A || timer == TIMER4B || timer == TIMER4C)
314        return Timer4_SetFrequency(frequency);
315        else if(timer == TIMER5A || timer == TIMER5B || timer == TIMER5C)
316        return Timer5_SetFrequency(frequency);
317        else
318        return false;
319}
320
321float GetPinResolution(uint8_t pin)
322{
323        TimerData td = timer_to_pwm_data[digitalPinToTimer(pin)];
324        double baseTenRes = 0;
325       
326        if(td.ChannelRegLoc)
327        {
328                //getting a base 10 resolution
329                td.Is16Bit? (baseTenRes = _SFR_MEM16(td.TimerTopRegLoc)) : (baseTenRes = _SFR_MEM8(td.TimerTopRegLoc));
330                 
331                //change the base and return   
332                return toBaseTwo(baseTenRes);
333        }
334        else
335        {
336                return 0;
337        }
338}
339#endif
Note: See TracBrowser for help on using the repository browser.