?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 6

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 }
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3