Line No. | Rev | Author | Line |
---|---|---|---|
1 | 6 | kaklik | /*! \file pulse.c \brief Pulse/frequency generation function library. */ |
2 | //***************************************************************************** |
||
3 | // |
||
4 | // File Name : 'pulse.c' |
||
5 | // Title : Pulse/frequency generation function library |
||
6 | // Author : Pascal Stang - Copyright (C) 2000-2002 |
||
7 | // Created : 2002-08-19 |
||
8 | // Revised : 2003-05-29 |
||
9 | // Version : 0.7 |
||
10 | // Target MCU : Atmel AVR Series |
||
11 | // Editor Tabs : 4 |
||
12 | // |
||
13 | // This code is distributed under the GNU Public License |
||
14 | // which can be found at http://www.gnu.org/licenses/gpl.txt |
||
15 | // |
||
16 | //***************************************************************************** |
||
17 | |||
18 | #include <avr/io.h> |
||
19 | #include <avr/interrupt.h> |
||
20 | #include <avr/pgmspace.h> |
||
21 | |||
22 | #include "global.h" |
||
23 | #include "timer.h" |
||
24 | #include "pulse.h" |
||
25 | |||
26 | // Global variables |
||
27 | // pulse generation registers |
||
28 | volatile static unsigned char PulseT1AMode; |
||
29 | volatile static unsigned short PulseT1ACount; |
||
30 | volatile static unsigned short PulseT1APeriodTics; |
||
31 | volatile static unsigned char PulseT1BMode; |
||
32 | volatile static unsigned short PulseT1BCount; |
||
33 | volatile static unsigned short PulseT1BPeriodTics; |
||
34 | |||
35 | // pulse mode bit definitions |
||
36 | // PULSE_MODE_COUNTED |
||
37 | // if true, the requested number of pulses are output, then output is turned off |
||
38 | // if false, pulses are output continuously |
||
39 | #define PULSE_MODE_CONTINUOUS 0x00 |
||
40 | #define PULSE_MODE_COUNTED 0x01 |
||
41 | |||
42 | // functions |
||
43 | |||
44 | void pulseInit(void) |
||
45 | { |
||
46 | // initialize timer1 for pulse operation |
||
47 | pulseT1Init(); |
||
48 | } |
||
49 | |||
50 | void pulseT1Init(void) |
||
51 | { |
||
52 | // try to make sure that timer1 is in "normal" mode |
||
53 | // most importantly, turn off PWM mode |
||
54 | timer1PWMOff(); |
||
55 | |||
56 | // set some reasonable initial values |
||
57 | // in case the user forgets to |
||
58 | PulseT1AMode = 0; |
||
59 | PulseT1BMode = 0; |
||
60 | PulseT1ACount = 0; |
||
61 | PulseT1BCount = 0; |
||
62 | PulseT1APeriodTics = 0x8000; |
||
63 | PulseT1BPeriodTics = 0x8000; |
||
64 | |||
65 | // attach the pulse service routines to |
||
66 | // the timer 1 output compare A and B interrupts |
||
67 | timerAttach(TIMER1OUTCOMPAREA_INT,pulseT1AService); |
||
68 | timerAttach(TIMER1OUTCOMPAREB_INT,pulseT1BService); |
||
69 | } |
||
70 | |||
71 | void pulseT1Off(void) |
||
72 | { |
||
73 | // turns pulse outputs off immediately |
||
74 | |||
75 | // set pulse counters to zero (finished) |
||
76 | PulseT1ACount = 0; |
||
77 | PulseT1BCount = 0; |
||
78 | // disconnect OutputCompare action from OC1A pin |
||
79 | cbi(TCCR1A,COM1A1); |
||
80 | cbi(TCCR1A,COM1A0); |
||
81 | // disconnect OutputCompare action from OC1B pin |
||
82 | cbi(TCCR1A,COM1B1); |
||
83 | cbi(TCCR1A,COM1B0); |
||
84 | // detach the pulse service routines |
||
85 | timerDetach(TIMER1OUTCOMPAREA_INT); |
||
86 | timerDetach(TIMER1OUTCOMPAREB_INT); |
||
87 | } |
||
88 | |||
89 | void pulseT1ASetFreq(u16 freqHz) |
||
90 | { |
||
91 | // set the frequency of the pulse output |
||
92 | // we need to find the requested period/2 (in timer tics) |
||
93 | // from the frequency (in hertz) |
||
94 | |||
95 | // calculate how many tics in period/2 |
||
96 | // this is the (timer tic rate)/(2*requested freq) |
||
97 | PulseT1APeriodTics = ((u32)F_CPU/((u32)timer1GetPrescaler()*2*freqHz)); |
||
98 | } |
||
99 | |||
100 | void pulseT1BSetFreq(u16 freqHz) |
||
101 | { |
||
102 | // set the frequency of the pulse output |
||
103 | // we need to find the requested period/2 (in timer tics) |
||
104 | // from the frequency (in hertz) |
||
105 | |||
106 | // calculate how many tics in period/2 |
||
107 | // this is the (timer tic rate)/(2*requested freq) |
||
108 | PulseT1BPeriodTics = ((u32)F_CPU/((u32)timer1GetPrescaler()*2*freqHz)); |
||
109 | } |
||
110 | |||
111 | void pulseT1ARun(u16 nPulses) |
||
112 | { |
||
113 | // set the number of pulses we want and the mode |
||
114 | if(nPulses) |
||
115 | { |
||
116 | // if the nPulses is non-zero, use "counted" mode |
||
117 | PulseT1AMode |= PULSE_MODE_COUNTED; |
||
118 | PulseT1ACount = nPulses<<1; |
||
119 | } |
||
120 | else |
||
121 | { |
||
122 | // if nPulses is zero, run forever |
||
123 | PulseT1AMode &= ~PULSE_MODE_COUNTED; |
||
124 | PulseT1ACount = 1<<1; |
||
125 | } |
||
126 | // set OutputCompare action to toggle OC1A pin |
||
127 | cbi(TCCR1A,COM1A1); |
||
128 | sbi(TCCR1A,COM1A0); |
||
129 | |||
130 | // now the "enabling" stuff |
||
131 | |||
132 | // set the output compare one pulse cycle ahead of current timer position |
||
133 | // to make sure we don't have to wait until the timer overflows and comes |
||
134 | // back to the current value |
||
135 | // set future output compare time to TCNT1 + PulseT1APeriodTics |
||
136 | //outw(OCR1A, inw(TCNT1) + PulseT1APeriodTics); |
||
137 | OCR1A += PulseT1APeriodTics; |
||
138 | |||
139 | // enable OutputCompare interrupt |
||
140 | sbi(TIMSK, OCIE1A); |
||
141 | } |
||
142 | |||
143 | void pulseT1BRun(u16 nPulses) |
||
144 | { |
||
145 | // set the number of pulses we want and the mode |
||
146 | if(nPulses) |
||
147 | { |
||
148 | // if the nPulses is non-zero, use "counted" mode |
||
149 | PulseT1BMode |= PULSE_MODE_COUNTED; |
||
150 | PulseT1BCount = nPulses<<1; |
||
151 | } |
||
152 | else |
||
153 | { |
||
154 | // if nPulses is zero, run forever |
||
155 | PulseT1BMode &= ~PULSE_MODE_COUNTED; |
||
156 | PulseT1BCount = 1<<1; |
||
157 | } |
||
158 | // set OutputCompare action to toggle OC1B pin |
||
159 | // (note: with all the A's and B's flying around, TCCR1A is not a bug) |
||
160 | cbi(TCCR1A,COM1B1); |
||
161 | sbi(TCCR1A,COM1B0); |
||
162 | |||
163 | // now the "enabling" stuff |
||
164 | |||
165 | // set the output compare one pulse cycle ahead of current timer position |
||
166 | // to make sure we don't have to wait until the timer overflows and comes |
||
167 | // back to the current value |
||
168 | // set future output compare time to TCNT1 + PulseT1APeriodTics |
||
169 | //outw(OCR1B, inw(TCNT1) + PulseT1BPeriodTics); |
||
170 | OCR1B += PulseT1BPeriodTics; |
||
171 | |||
172 | // enable OutputCompare interrupt |
||
173 | sbi(TIMSK, OCIE1B); |
||
174 | } |
||
175 | |||
176 | void pulseT1AStop(void) |
||
177 | { |
||
178 | // stop output regardless of remaining pulses or mode |
||
179 | // go to "counted" mode |
||
180 | PulseT1AMode |= PULSE_MODE_COUNTED; |
||
181 | // set pulses to zero |
||
182 | PulseT1ACount = 0; |
||
183 | } |
||
184 | |||
185 | void pulseT1BStop(void) |
||
186 | { |
||
187 | // stop output regardless of remaining pulses or mode |
||
188 | // go to "counted" mode |
||
189 | PulseT1BMode |= PULSE_MODE_COUNTED; |
||
190 | // set pulses to zero |
||
191 | PulseT1BCount = 0; |
||
192 | } |
||
193 | |||
194 | u16 pulseT1ARemaining(void) |
||
195 | { |
||
196 | // return the number of pulses remaining for channel A |
||
197 | // add 1 to make sure we round up, >>1 equivalent to /2 |
||
198 | return (PulseT1ACount+1)>>1; |
||
199 | } |
||
200 | |||
201 | u16 pulseT1BRemaining(void) |
||
202 | { |
||
203 | // return the number of pulses remaining for channel A |
||
204 | // add 1 to make sure we round up, >>1 equivalent to /2 |
||
205 | return (PulseT1BCount+1)>>1; |
||
206 | } |
||
207 | |||
208 | void pulseT1AService(void) |
||
209 | { |
||
210 | // check if TimerPulseACount is non-zero |
||
211 | // (i.e. pulses are still requested) |
||
212 | if(PulseT1ACount) |
||
213 | { |
||
214 | //u16 OCValue; |
||
215 | // read in current value of output compare register OCR1A |
||
216 | //OCValue = inp(OCR1AL); // read low byte of OCR1A |
||
217 | //OCValue += inp(OCR1AH)<<8; // read high byte of OCR1A |
||
218 | // increment OCR1A value by PulseT1APeriodTics |
||
219 | //OCValue += PulseT1APeriodTics; |
||
220 | // set future output compare time to this new value |
||
221 | //outp((OCValue>>8), OCR1AH); // write high byte |
||
222 | //outp((OCValue & 0x00FF),OCR1AL); // write low byte |
||
223 | |||
224 | // the following line should be identical in operation |
||
225 | // to the lines above, but for the moment, I'm not convinced |
||
226 | // this method is bug-free. At least it's simpler! |
||
227 | //outw(OCR1A, inw(OCR1A) + PulseT1APeriodTics); |
||
228 | // change again |
||
229 | OCR1A += PulseT1APeriodTics; |
||
230 | |||
231 | // decrement the number of pulses executed |
||
232 | if(PulseT1AMode & PULSE_MODE_COUNTED) |
||
233 | PulseT1ACount--; |
||
234 | } |
||
235 | else |
||
236 | { |
||
237 | // pulse count has reached zero |
||
238 | // disable the output compare's action on OC1A pin |
||
239 | cbi(TCCR1A,COM1A1); |
||
240 | cbi(TCCR1A,COM1A0); |
||
241 | // and disable the output compare's interrupt to stop pulsing |
||
242 | cbi(TIMSK, OCIE1A); |
||
243 | } |
||
244 | } |
||
245 | |||
246 | void pulseT1BService(void) |
||
247 | { |
||
248 | // check if TimerPulseACount is non-zero |
||
249 | // (i.e. pulses are still requested) |
||
250 | if(PulseT1BCount) |
||
251 | { |
||
252 | //u16 OCValue; |
||
253 | // read in current value of output compare register OCR1B |
||
254 | //OCValue = inp(OCR1BL); // read low byte of OCR1B |
||
255 | //OCValue += inp(OCR1BH)<<8; // read high byte of OCR1B |
||
256 | // increment OCR1B value by PulseT1BPeriodTics |
||
257 | //OCValue += PulseT1BPeriodTics; |
||
258 | // set future output compare time to this new value |
||
259 | //outp((OCValue>>8), OCR1BH); // write high byte |
||
260 | //outp((OCValue & 0x00FF),OCR1BL); // write low byte |
||
261 | |||
262 | // the following line should be identical in operation |
||
263 | // to the lines above, but for the moment, I'm not convinced |
||
264 | // this method is bug-free. At least it's simpler! |
||
265 | //outw(OCR1B, inw(OCR1B) + PulseT1BPeriodTics); |
||
266 | // change again |
||
267 | OCR1B += PulseT1BPeriodTics; |
||
268 | |||
269 | |||
270 | // decrement the number of pulses executed |
||
271 | if(PulseT1BMode & PULSE_MODE_COUNTED) |
||
272 | PulseT1BCount--; |
||
273 | } |
||
274 | else |
||
275 | { |
||
276 | // pulse count has reached zero |
||
277 | // disable the output compare's action on OC1B pin |
||
278 | cbi(TCCR1A,COM1B1); |
||
279 | cbi(TCCR1A,COM1B0); |
||
280 | // and disable the output compare's interrupt to stop pulsing |
||
281 | cbi(TIMSK, OCIE1B); |
||
282 | } |
||
283 | } |
Powered by WebSVN v2.8.3