9d205fc2703410e731abe05f92d8ef3d4186d3db
[avr_bc100.git] / BaseTinyFirmware / GCC / PWM.c
1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
2 /*! \file *********************************************************************\r
3  *\r
4  * \brief\r
5  *      Functions for use of PWM\r
6  *\r
7  *      Contains functions for initializing and controlling PWM output.\r
8  *\r
9  * \par Application note:\r
10  *      AVR458: Charging Li-Ion Batteries with BC100\n\r
11  *      AVR463: Charging NiMH Batteries with BC100\r
12  *\r
13  * \par Documentation\r
14  *      For comprehensive code documentation, supported compilers, compiler \r
15  *      settings and supported devices see readme.html\r
16  *\r
17  * \author\r
18  *      Atmel Corporation: http://www.atmel.com \n\r
19  *      Support email: avr@atmel.com\r
20  *\r
21  * \r
22  * $Name$\r
23  * $Revision: 2299 $\r
24  * $RCSfile$\r
25  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $\r
26  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
27  ******************************************************************************/\r
28 \r
29 #include <avr/io.h>\r
30 \r
31 #include "enums.h"\r
32 \r
33 #include "main.h"\r
34 #include "PWM.h"\r
35 #include "time.h"\r
36 \r
37 \r
38 //******************************************************************************\r
39 // Functions\r
40 //******************************************************************************\r
41 /*! \brief Stops PWM output\r
42  *\r
43  */\r
44 void PWM_Stop(void)\r
45 {\r
46         OCR1B = 0;  // Reset compare level.\r
47         PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode.\r
48         TCCR1A = 0; // Set normal port operation, disable PWM modes.\r
49         TCCR1B = 0; // Stop timer/counter1.\r
50         TCCR1C = 0; // Set normal port operation.\r
51         TCCR1D = 0; // No fault protection, normal waveform.\r
52         OCR1C = 0;  // Reset compare.\r
53         OCR1D = 0;  // Reset compare.\r
54         DT1 = 0;    // No dead time values.\r
55 }\r
56 \r
57 \r
58 /*! \brief Initializes and starts PWM output\r
59  *\r
60  * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n\r
61  * Its comparator is connected to PB3 and will output high until timer1 reaches\r
62  * the value of OCR1B. It is then dropped to 0.\n\r
63  * The comparator outputs high again when the counter overflows, which will\r
64  * happen at a rate of 250 kHz.\r
65  */\r
66 void PWM_Start(void)\r
67 {\r
68         // Clear OC1B on compare match, enable PWM on comparator OCR1B.\r
69         TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);\r
70         \r
71         // Non-inverted PWM, T/C stopped.\r
72         TCCR1B = 0;\r
73         \r
74         // Copy shadow bits, disconnect OC1D.\r
75         TCCR1C = (TCCR1A & 0xF0);\r
76         \r
77         // No fault protection, use phase & frequency correct PWM.\r
78         TCCR1D = (0<<WGM11)|(1<WGM10);\r
79         \r
80         // Does not matter -- PWM6 mode not used.\r
81         TCCR1E = 0;\r
82         \r
83         // Does not matter -- OC1A is disabled.\r
84         OCR1A = 0;\r
85         \r
86         // Set reset compare level. (Offset is used, or JumperCheck() will fail.)\r
87         OCR1B = PWM_OFFSET;\r
88         \r
89         // TOP value for PWM, f(PWM) = 64MHz / 255 = 251kHz.\r
90         OCR1C = 0xFF;\r
91         \r
92         // Does not matter -- OC1D is disabled.\r
93         OCR1D = 0;\r
94         \r
95         // No dead time values.\r
96         DT1 = 0;\r
97         \r
98         // Set PWM port pin to output.\r
99         DDRB |= (1<<PB3);\r
100         \r
101         // Enable PLL, use full speed mode.\r
102         PLLCSR = (0<<LSM) | (1<<PLLE);\r
103         \r
104         // Use general timer and wait 1 ms for PLL lock to settle.\r
105         Time_Set(TIMER_GEN,0,0,1);\r
106         do{ \r
107         }while(Time_Left(TIMER_GEN));\r
108         \r
109         // Now wait for PLL to lock.\r
110         do{ \r
111         }while((PLLCSR & (1<<PLOCK)) == 0);\r
112 \r
113         // Use PLL as clock source.\r
114         PLLCSR |= (1<<PCKE);\r
115         \r
116         // CLK PCK = 64MHz / 1 = 64MHz.\r
117         TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);\r
118 }\r
119 \r
120 \r
121 /*! \brief Increments the PWM duty cycle, if not already at max\r
122  *\r
123  * \retval TRUE Success, duty cycle could be incremented.\r
124  * \retval FALSE Failure, duty cycle already at maximum.\r
125  */\r
126 unsigned char PWM_IncrementDutyCycle(void){\r
127 \r
128         if (OCR1B < PWM_MAX) {\r
129                 OCR1B += 1;\r
130                 return(TRUE);\r
131         } else {\r
132                 return(FALSE);\r
133         }\r
134 }\r
135 \r
136 \r
137 /*! \brief Decrements the PWM duty cycle, if not already at zero.\r
138  *\r
139  * \retval TRUE Success, duty cycle could be decremented.\r
140  * \retval FALSE Failure, duty cycle already at zero.\r
141  */\r
142 unsigned char PWM_DecrementDutyCycle(void){\r
143         \r
144         if (OCR1B > 0)  {\r
145                 OCR1B -= 1;\r
146                 return(TRUE);\r
147         } else {\r
148                 return(FALSE);\r
149         }\r
150 }\r