source: orbit/arduino/libraries/PWM/utility/BTimerDefs.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.2 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_ATmega48__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
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()
43{
44        return (int32_t)(F_CPU/(2 * (int32_t)GetTop_16() * GetPrescaler_16()));
45}
46
47bool SetFrequency_16(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(timerTop);
64        SetPrescaler_16((prescaler)iterate);
65       
66        return true;
67}
68
69uint16_t GetPrescaler_16()
70{
71        return pscLst[(TCCR1B & 7)];
72}
73
74void SetPrescaler_16(prescaler psc)
75{
76        TCCR1B = (TCCR1B & ~7) | (psc & 7);
77}
78
79void SetTop_16(uint16_t top)
80{
81        ICR1 = top;
82}
83
84uint16_t GetTop_16()
85{
86        return ICR1;
87}
88
89void Initialize_16()
90{
91        //setting the waveform generation mode
92        uint8_t wgm = 8;
93       
94        TCCR1A = (TCCR1A & B11111100) | (wgm & 3);
95        TCCR1B = (TCCR1B & B11100111) | ((wgm & 12) << 1);
96       
97        SetFrequency_16(500);
98}
99
100float GetResolution_16()
101{
102        return toBaseTwo(ICR1);
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               
138                //getting the timer top using the new multiplier
139                timerTop = (F_CPU/(2* f * (uint32_t)multiplier));
140               
141        } while (timerTop > UINT8_MAX);
142       
143        SetTop_8(timerOffset, timerTop);
144       
145        if(timerOffset != TIMER2_OFFSET)
146        SetPrescaler_8(timerOffset, (prescaler)iterate);
147        else
148        SetPrescalerAlt_8(timerOffset, (prescaler_alt)iterate);
149       
150        return true;
151}
152
153uint16_t GetPrescaler_8(const int16_t timerOffset)
154{
155        if(timerOffset != TIMER2_OFFSET)
156                return pscLst[(TCCRB_8(timerOffset) & 7)];
157        else
158                return pscLst_alt[(TCCRB_8(timerOffset) & 7)];
159}
160
161void SetPrescaler_8(const int16_t timerOffset, prescaler psc)
162{
163        TCCRB_8(timerOffset) = (TCCRB_8(timerOffset) & ~7) | (psc & 7);
164}
165
166void SetPrescalerAlt_8(const int16_t timerOffset, prescaler_alt psc)
167{
168        TCCRB_8(timerOffset) = (TCCRB_8(timerOffset) & ~7) | (psc & 7);
169}
170
171void SetTop_8(const int16_t timerOffset, uint8_t top)
172{
173        OCRA_8(timerOffset) = top;
174}
175
176uint8_t GetTop_8(const int16_t timerOffset)
177{
178        return OCRA_8(timerOffset);
179}
180
181void Initialize_8(const int16_t timerOffset)
182{
183        //setting the waveform generation mode
184        uint8_t wgm = 5;
185       
186        TCCRA_8(timerOffset) = (TCCRA_8(timerOffset) & B11111100) | (wgm & 3);
187        TCCRB_8(timerOffset) = (TCCRB_8(timerOffset) & B11110111) | ((wgm & 12) << 1);
188       
189        //disable timer0's interrupt when initialization is called, otherwise handler will eat
190        //up processor cycles when PWM on timer0 is set to high frequencies. This will effectively disable
191        //Arduino's time keeping functions, which the user should be aware of before initializing timer0
192        if(timerOffset == 0)
193        {
194                TIMSK0 &= B11111110;
195        }
196       
197        SetFrequency_8(timerOffset, 500);
198}
199
200float GetResolution_8(const int16_t timerOffset)
201{
202        return toBaseTwo(OCRA_8(timerOffset));
203}
204
205
206//--------------------------------------------------------------------------------
207//                                                      Timer Independent Functions
208//--------------------------------------------------------------------------------
209
210void pwmWrite(uint8_t pin, uint8_t val)
211{
212        pinMode(pin, OUTPUT);
213       
214        //casting "val" to be larger so that the final value (which is the partially
215        //the result of multiplying two potentially high value int16s) will not truncate
216        uint32_t tmp = val;
217       
218        if (val == 0)
219                digitalWrite(pin, LOW);
220        else if (val == 255)
221                digitalWrite(pin, HIGH);
222        else
223        {
224                uint16_t regLoc16 = 0;
225                uint16_t regLoc8 = 0;
226               
227                uint16_t top;
228               
229                switch(digitalPinToTimer(pin))
230                {
231                        case TIMER0B:
232                        sbi(TCCR0A, COM0B1);
233                        regLoc8 = OCR0B_MEM;
234                        top = Timer0_GetTop();
235                        break;
236                        case TIMER1A:
237                        sbi(TCCR1A, COM1A1);
238                        regLoc16 = OCR1A_MEM;
239                        top = Timer1_GetTop();
240                        break;
241                        case TIMER1B:
242                        sbi(TCCR1A, COM1B1);
243                        regLoc16 = OCR1B_MEM;
244                        top = Timer1_GetTop();
245                        break;
246                        case TIMER2B:
247                        sbi(TCCR2A, COM2B1);
248                        regLoc8 = OCR2B_MEM;
249                        top = Timer2_GetTop();
250                        break;
251                        case NOT_ON_TIMER:
252                        default:
253                        if (val < 128)
254                        digitalWrite(pin, LOW);
255                        else
256                        digitalWrite(pin, HIGH);
257                        return;
258                }
259               
260                if(regLoc16)
261                        _SFR_MEM16(regLoc16) = (tmp*top)/255;
262                else
263                        _SFR_MEM8(regLoc8) = (tmp*top)/255;
264               
265        }               
266}
267
268//takes a 16 bit value instead of an 8 bit value for maximum resolution
269void pwmWriteHR(uint8_t pin, uint16_t val)
270{
271        pinMode(pin, OUTPUT);
272       
273        uint32_t tmp = val;
274       
275        if (val == 0)
276        digitalWrite(pin, LOW);
277        else if (val == 65535)
278        digitalWrite(pin, HIGH);
279        else
280        {
281                uint16_t regLoc16 = 0;
282                uint16_t regLoc8 = 0;
283               
284                uint16_t top;
285                switch(digitalPinToTimer(pin))
286                {
287                        case TIMER0B:
288                        sbi(TCCR0A, COM0B1);
289                        regLoc8 = OCR0B_MEM;
290                        top = Timer0_GetTop();
291                        break;
292                        case TIMER1A:
293                        sbi(TCCR1A, COM1A1);
294                        regLoc16 = OCR1A_MEM;
295                        top = Timer1_GetTop();
296                        break;
297                        case TIMER1B:
298                        sbi(TCCR1A, COM1B1);
299                        regLoc16 = OCR1B_MEM;
300                        top = Timer1_GetTop();
301                        break;
302                        case TIMER2B:
303                        sbi(TCCR2A, COM2B1);
304                        regLoc8 = OCR2B_MEM;
305                        top = Timer2_GetTop();
306                        break;
307                        case NOT_ON_TIMER:
308                        default:
309                        if (val < 128)
310                        digitalWrite(pin, LOW);
311                        else
312                        digitalWrite(pin, HIGH);
313                        return;
314                }                       
315               
316                if(regLoc16)
317                        _SFR_MEM16(regLoc16) = (tmp*top)/65535;
318                else
319                        _SFR_MEM8(regLoc8) = (tmp*top)/65535;
320        }
321}
322
323void InitTimers()
324{
325        Timer0_Initialize();
326        Timer1_Initialize();
327        Timer2_Initialize();
328}
329
330void InitTimersSafe()
331{
332        Timer1_Initialize();
333        Timer2_Initialize();
334}
335
336extern bool SetPinFrequency( int8_t pin, uint32_t frequency )
337{
338        uint8_t timer = digitalPinToTimer(pin);
339       
340        if(timer == TIMER0B)
341                return Timer0_SetFrequency(frequency);
342        else if(timer == TIMER1A || timer == TIMER1B)
343                return Timer1_SetFrequency(frequency);
344        else if(timer == TIMER2B)
345                return Timer2_SetFrequency(frequency);
346        else
347                return false;
348}
349
350bool SetPinFrequencySafe(int8_t pin, uint32_t frequency)
351{
352        uint8_t timer = digitalPinToTimer(pin);
353       
354        if(timer == TIMER1A || timer == TIMER1B)
355                return Timer1_SetFrequency(frequency);
356        else if(timer == TIMER2B)
357                return Timer2_SetFrequency(frequency);
358        else
359                return false;
360}
361
362float GetPinResolution(uint8_t pin)
363{
364        uint8_t timer = digitalPinToTimer(pin);
365        uint16_t top;
366       
367        switch(timer)
368        {
369                case TIMER0B:
370                        top = Timer0_GetTop();
371                        break;
372                case TIMER1A:
373                        top = Timer1_GetTop();
374                        break;
375                case TIMER1B:
376                        top = Timer1_GetTop();
377                        break;
378                case TIMER2B:
379                        top = Timer2_GetTop();
380                default:
381                        return 0;
382        }
383       
384        return toBaseTwo(top);
385}
386
387#endif
Note: See TracBrowser for help on using the repository browser.