Rev 64 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
64 | walter | 1 | //############################################################################ |
2 | // - PWM CTRL |
||
3 | // - Main |
||
4 | // - ATMEGA8 mit 8MHz |
||
5 | // - Nur für den privaten Gebrauch |
||
6 | // - Keine Garantie auf Fehlerfreiheit |
||
7 | // - Kommerzielle Nutzung nur mit meiner Zustimmung |
||
8 | // - walter Meyer @ www.freakware.de |
||
9 | // - 11.12.2007 |
||
10 | // - Make sure Fuses are programmed for internal 8 MHz RC Oscilator |
||
11 | //############################################################################*/ |
||
12 | |||
13 | #include "main.h" |
||
14 | #include "uart.h" |
||
15 | #include "twislave.h" |
||
16 | |||
17 | volatile unsigned int PPM_SIGNAL = 1520; |
||
18 | volatile unsigned char PPM_NEW = 0; |
||
19 | volatile unsigned char TMR1OvF = 0; |
||
20 | volatile unsigned int TMR1MS; |
||
21 | volatile unsigned char CH0; |
||
22 | volatile unsigned char CH1; |
||
23 | volatile unsigned char CH2; |
||
24 | volatile unsigned char CH3; |
||
25 | volatile unsigned char CH4; |
||
26 | volatile unsigned char CH5; |
||
27 | |||
28 | uint16_t EEMEM EEPMIN=0x0000; |
||
29 | uint16_t EEMEM EEPMAX=0xffff; |
||
30 | uint16_t EEMEM EEPSIG=0xffff; |
||
31 | |||
32 | |||
33 | //led kennlinie, (noch nicht implementiert, nur vorbereitet) |
||
34 | unsigned char kl[256]={ |
||
35 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
36 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
37 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
38 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
39 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
40 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
41 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
42 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
43 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
44 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
45 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
46 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
47 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
48 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
49 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, |
||
50 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 |
||
51 | }; |
||
52 | |||
53 | |||
54 | |||
55 | /*##############################################################################*/ |
||
56 | SIGNAL(SIG_OVERFLOW1) |
||
57 | { |
||
58 | TMR1OvF++; |
||
59 | } |
||
60 | |||
61 | |||
62 | SIGNAL(SIG_INPUT_CAPTURE1) |
||
63 | { |
||
64 | static unsigned int pos_ICR; |
||
65 | static unsigned int ppm; |
||
66 | |||
67 | if ((TCCR1B & (1<<ICES1)) != 0) //rising edge |
||
68 | { |
||
69 | TCCR1B &= ~(1<<ICES1); //set falling egde |
||
70 | TMR1OvF = 0; |
||
71 | pos_ICR = ICR1; |
||
72 | } |
||
73 | else //falling edge |
||
74 | { |
||
75 | TCCR1B |= (1<<ICES1); //set rising egde |
||
76 | ppm = (ICR1 - pos_ICR + (int) TMR1OvF * 65536); |
||
77 | if ((ppm > 600) && (ppm < 2400)) |
||
78 | { |
||
79 | if (ppm > 2100) ppm = 2100; |
||
80 | if (ppm < 900) ppm = 900; |
||
81 | ppm = (PPM_SIGNAL * 3 + ppm) / 4; |
||
82 | PPM_SIGNAL = ppm; |
||
83 | if (PPM_NEW < 50) PPM_NEW++; |
||
84 | } |
||
85 | |||
86 | } |
||
87 | |||
88 | } |
||
89 | |||
90 | /*##############################################################################*/ |
||
91 | SIGNAL(SIG_OVERFLOW0) |
||
92 | { |
||
93 | // this function is called every 32us, |
||
94 | // it is very important that it's execution time is as short as possible |
||
95 | // currently it's about 20us |
||
96 | |||
97 | static unsigned char counter = 254; |
||
98 | static unsigned char ms1 = 0; |
||
99 | static unsigned char ch0_tmp = 0; |
||
100 | static unsigned char ch1_tmp = 0; |
||
101 | static unsigned char ch2_tmp = 0; |
||
102 | static unsigned char ch3_tmp = 0; |
||
103 | static unsigned char ch4_tmp = 0; |
||
104 | static unsigned char ch5_tmp = 0; |
||
105 | unsigned char PORTB_BAK; |
||
106 | unsigned char PORTD_BAK; |
||
107 | |||
108 | PORTB_BAK = PORTB; |
||
109 | PORTD_BAK = PORTD; |
||
110 | |||
111 | if (counter++ == 254) |
||
112 | { |
||
113 | PORTB_BAK LEDON (CH0_B | CH1_B | CH2_B); //new cycle, output on |
||
114 | PORTD_BAK LEDON (CH3_D | CH4_D | CH5_D); // |
||
65 | walter | 115 | |
64 | walter | 116 | ch0_tmp = CH0; |
117 | ch1_tmp = CH1; |
||
118 | ch2_tmp = CH2; |
||
119 | ch3_tmp = CH3; |
||
120 | ch4_tmp = CH4; |
||
121 | ch5_tmp = CH5; |
||
65 | walter | 122 | |
64 | walter | 123 | counter = 0; |
124 | } |
||
125 | |||
126 | if (ch0_tmp == counter) PORTB_BAK LEDOFF CH0_B; //channel value reached, output off |
||
127 | if (ch1_tmp == counter) PORTB_BAK LEDOFF CH1_B; // |
||
128 | if (ch2_tmp == counter) PORTB_BAK LEDOFF CH2_B; // |
||
129 | if (ch3_tmp == counter) PORTD_BAK LEDOFF CH3_D; // |
||
130 | if (ch4_tmp == counter) PORTD_BAK LEDOFF CH4_D; // |
||
131 | if (ch5_tmp == counter) PORTD_BAK LEDOFF CH5_D; // |
||
132 | |||
133 | PORTB = PORTB_BAK; |
||
134 | PORTD = PORTD_BAK; |
||
135 | |||
136 | if (ms1++ == 32) |
||
137 | { |
||
138 | ms1=0; |
||
139 | TMR1MS++; |
||
140 | } |
||
141 | |||
142 | |||
143 | |||
144 | |||
145 | } |
||
146 | |||
147 | |||
148 | /*##############################################################################*/ |
||
149 | unsigned int SetDelay (unsigned int t) |
||
150 | { |
||
151 | unsigned char hi_byte; |
||
152 | unsigned char lo_byte; |
||
153 | |||
154 | hi_byte = (TMR1MS >> 8); |
||
155 | lo_byte = (TMR1MS & 0xff); |
||
156 | if (hi_byte != (TMR1MS >> 8)) hi_byte = (TMR1MS >> 8); |
||
157 | |||
158 | return(((hi_byte << 8) | lo_byte) + t + 1); |
||
159 | } |
||
160 | |||
161 | |||
162 | /*##############################################################################*/ |
||
163 | char CheckDelay(unsigned int t) |
||
164 | { |
||
165 | unsigned char hi_byte; |
||
166 | unsigned char lo_byte; |
||
167 | |||
168 | hi_byte = (TMR1MS >> 8); |
||
169 | lo_byte = (TMR1MS & 0xff); |
||
170 | if (hi_byte != (TMR1MS >> 8)) hi_byte = (TMR1MS >> 8); |
||
171 | |||
172 | return(((t - ((hi_byte << 8) | lo_byte)) & 0x8000) >> 9); |
||
173 | } |
||
174 | |||
175 | |||
176 | |||
177 | /*##############################################################################*/ |
||
178 | void StartPWM(void) |
||
179 | { |
||
180 | //Timer 0 Config |
||
181 | TCCR0 = (0<<CS02)|(0<<CS01)|(1<<CS00); // (@8MHz) = 1/8us Clk = 256/8 = 32us overflow |
||
182 | TIMSK setbit (1<<TOIE0); // enable Int |
||
183 | |||
184 | } |
||
185 | |||
186 | |||
187 | /*##############################################################################*/ |
||
188 | void StartPPM(void) |
||
189 | { |
||
190 | |||
191 | //Timer1 Config |
||
192 | TCCR1A = (0<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)| |
||
193 | (0<<FOC1A) |(0<<FOC1B) |(0<<WGM10) |(0<<WGM11); |
||
194 | TCCR1B = (1<<ICNC1)|(1<<ICES1)|(0<<WGM13)| |
||
195 | (0<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10); //ICP_POS_FLANKE |
||
196 | |||
197 | // interrupts |
||
198 | TIMSK |= (1<<TICIE1)|(1<<TOIE1); //ICP_INT_ENABLE and TIMER1_INT_ENABLE |
||
199 | |||
200 | } |
||
201 | |||
202 | |||
203 | /*##############################################################################*/ |
||
204 | unsigned int GetPPM(void) |
||
205 | { |
||
206 | //this routines seems to be nesseccary, as reading a 16 bit value |
||
207 | //on a 8 bit machine is not atomic, so if an interrupt apears between reading |
||
208 | //low and high byte of the 16 bit value a wrong result is possible |
||
209 | |||
210 | unsigned char temp_hi; |
||
211 | unsigned char temp_lo; |
||
212 | |||
213 | temp_hi = (PPM_SIGNAL >> 8); |
||
214 | temp_lo = (PPM_SIGNAL & 0xff); |
||
215 | if (temp_hi != (PPM_SIGNAL >> 8)) temp_hi = (PPM_SIGNAL >> 8); |
||
216 | return( (temp_hi << 8) | temp_lo); |
||
217 | |||
218 | } |
||
219 | |||
220 | |||
221 | /*##############################################################################*/ |
||
222 | // MAIN |
||
223 | /*##############################################################################*/ |
||
224 | int main (void) |
||
225 | { |
||
226 | |||
227 | #define STEP 256 |
||
228 | #define MUL 1 |
||
229 | #define REDUCE 2 |
||
230 | |||
231 | #define EEPSIGNATURE 0x55aa |
||
232 | |||
233 | #define inimin 1200 |
||
234 | #define inimax 1800 |
||
235 | |||
236 | unsigned int ppm; |
||
237 | signed int color; |
||
65 | walter | 238 | volatile unsigned int setupdly; |
239 | volatile unsigned int ppmtodly; |
||
240 | volatile unsigned int flashdly; |
||
241 | |||
242 | volatile unsigned int dly1; |
||
243 | |||
244 | unsigned char flags; |
||
245 | |||
64 | walter | 246 | unsigned char setup; |
247 | unsigned int lmax; |
||
248 | unsigned int lmin; |
||
249 | unsigned int max; |
||
250 | unsigned int min; |
||
65 | walter | 251 | unsigned char temp; |
64 | walter | 252 | signed long temp1; |
253 | signed long temp2; |
||
254 | |||
65 | walter | 255 | flags = 0; |
256 | |||
64 | walter | 257 | DDRB = (CH0_B|CH1_B|CH2_B); |
258 | PORTB = 0x00; |
||
259 | |||
260 | DDRC = (ledred); |
||
261 | PORTC = 0x00; |
||
262 | |||
263 | DDRD = (ledgreen|CH3_D|CH4_D|CH5_D); |
||
264 | PORTD = 0x00; |
||
265 | |||
65 | walter | 266 | CH0 = 0xFF; //PORTB RGBLED red |
267 | CH1 = 0xFF; //PORTB RGBLED green |
||
268 | CH2 = 0xFF; //PORTB RGBLED blue |
||
269 | CH3 = 0; |
||
64 | walter | 270 | CH4 = 0; |
271 | CH5 = 0; |
||
272 | |||
273 | lmax = 0x0000; |
||
274 | lmin = 0xffff; |
||
275 | |||
65 | walter | 276 | StartUART(); |
64 | walter | 277 | StartPPM(); |
278 | //StartI2C(); |
||
279 | StartPWM(); |
||
280 | sei(); |
||
281 | |||
282 | min = inimin; //default min |
||
283 | max = inimax; //default max |
||
284 | |||
285 | if (eeprom_read_word(&EEPSIG) != EEPSIGNATURE) //check eep if signature is there |
||
286 | { |
||
287 | eeprom_write_word(&EEPMIN, min); //no, write initial min |
||
288 | eeprom_write_word(&EEPMAX, max); //and max values |
||
289 | eeprom_write_word(&EEPSIG, EEPSIGNATURE); //along with eep signature |
||
290 | } |
||
291 | else |
||
292 | { |
||
293 | |||
294 | min = eeprom_read_word(&EEPMIN); //signature ok |
||
295 | max = eeprom_read_word(&EEPMAX); //read min and max |
||
296 | } |
||
297 | |||
298 | |||
299 | setup = 0; //reset setup toggle counter |
||
65 | walter | 300 | temp = (1<<0); |
64 | walter | 301 | setupdly = SetDelay(5000); |
65 | walter | 302 | ppmtodly = SetDelay(2000); |
303 | flashdly = SetDelay(200); |
||
64 | walter | 304 | |
305 | while (1) |
||
306 | { |
||
307 | |||
308 | if (PPM_NEW > 20) //ppm Signal ok |
||
309 | { |
||
310 | PORTC clrbit ledred; |
||
311 | ppm = GetPPM(); |
||
312 | ppmtodly = SetDelay(500); //reset timeout |
||
313 | if (lmax < ppm) lmax=ppm; //update impulse max |
||
314 | if (lmin > ppm) lmin=ppm; //and min boundarys |
||
315 | } |
||
316 | else |
||
317 | { |
||
318 | PORTC setbit ledred; //ppm signal not ok |
||
319 | ppm = min; //set ppm to minimum |
||
320 | } |
||
321 | |||
322 | |||
323 | if (CheckDelay(ppmtodly)) //timeout |
||
324 | { |
||
325 | ppmtodly = SetDelay(5000); |
||
326 | PPM_NEW = 0; //set ppm signal not ok |
||
327 | } |
||
328 | |||
329 | |||
330 | if (setup < 6) |
||
331 | { |
||
332 | if ((ppm > 1600) && ((setup&1)==0)) setup++; // |
||
333 | if ((ppm < 1400) && ((setup&1)==1)) setup++; // |
||
334 | |||
335 | if (CheckDelay(flashdly)) |
||
336 | { |
||
65 | walter | 337 | CH0 = (temp & (1<<0)) * 255; |
338 | CH1 = (temp & (1<<1)) * 255; |
||
339 | CH2 = (temp & (1<<2)) * 255; |
||
340 | CH3 = (temp & (1<<3)) * 255; |
||
341 | CH4 = (temp & (1<<4)) * 255; |
||
342 | CH5 = (temp & (1<<5)) * 255; |
||
343 | temp <<= 1; |
||
344 | if (temp == (1<<6)) temp = (1<<0); |
||
345 | |||
346 | /* |
||
347 | CH0 = CH0 ^ 0xff; //invert brightness |
||
64 | walter | 348 | CH1 = CH1 ^ 0xff; |
349 | CH2 = CH2 ^ 0xff; |
||
65 | walter | 350 | CH3 = CH3 ^ 0xff; |
351 | CH4 = CH4 ^ 0xff; |
||
352 | CH5 = CH5 ^ 0xff; |
||
353 | */ |
||
354 | |||
355 | flashdly = SetDelay(100); |
||
64 | walter | 356 | } |
357 | } |
||
358 | |||
359 | if (setup == 6) //if stick is toggled 6 times |
||
360 | { //within setup timeout |
||
361 | PORTD setbit ledgreen; //store ppm min and max |
||
362 | setupdly = SetDelay(3000); //for 2000ms |
||
363 | eeprom_write_word(&EEPMIN, lmin); //in eeprom |
||
364 | eeprom_write_word(&EEPMAX, lmax); |
||
365 | min = lmin; |
||
366 | max = lmax; |
||
367 | setup = 7; //enter PWM toggle mode |
||
368 | |||
369 | } |
||
370 | |||
371 | |||
372 | if (setup == 7) |
||
373 | { |
||
374 | if (CheckDelay(flashdly)) //each 25ms toggle PWM's |
||
375 | { |
||
65 | walter | 376 | CH0 = CH0 ^ 0xff; //invert brightness |
64 | walter | 377 | CH1 = CH1 ^ 0xff; |
378 | CH2 = CH2 ^ 0xff; |
||
65 | walter | 379 | CH3 = CH3 ^ 0xff; |
380 | CH4 = CH4 ^ 0xff; |
||
381 | CH5 = CH5 ^ 0xff; |
||
382 | |||
64 | walter | 383 | flashdly = SetDelay(25); |
384 | } |
||
385 | |||
386 | } |
||
387 | |||
65 | walter | 388 | if ((CheckDelay(setupdly)) && setup < 8) //setup timeout reached |
64 | walter | 389 | { |
390 | setup = 8; //lockdown setup |
||
391 | PORTD clrbit ledgreen; |
||
65 | walter | 392 | CH0 = 0; //start CH3 |
393 | CH1 = 85; //CH4 |
||
394 | CH2 = 170; //and CH4 with about 120° phase shift |
||
395 | |||
396 | flags = 0; |
||
397 | dly1 = SetDelay(100); |
||
64 | walter | 398 | } |
399 | |||
400 | |||
401 | if (setup == 8) |
||
402 | { |
||
403 | |||
65 | walter | 404 | |
405 | /************************************************************************************/ |
||
406 | /* control CH3, CH4 and CH5 (RGB LED) */ |
||
407 | /************************************************************************************/ |
||
408 | |||
409 | temp1 = ((long)STEP * 7 * 40000) / ((max-REDUCE) - (min+REDUCE)); |
||
64 | walter | 410 | temp2 = (((int)ppm - ((int)min+REDUCE)) * temp1); |
65 | walter | 411 | color = temp2 / 40000; |
64 | walter | 412 | |
413 | if (color < 0) color = 0; |
||
65 | walter | 414 | if (color > ((STEP*7)+1)) color = ((STEP*7)+1); |
64 | walter | 415 | |
416 | |||
417 | //printf("p %u ",ppm); |
||
418 | //printf("pm %u ",(min+REDUCE)); |
||
419 | //printf("t1 %li ",temp1); |
||
420 | //printf("t2 %li ",temp2); |
||
421 | //printf("c %i\n ",color); |
||
422 | |||
423 | |||
65 | walter | 424 | // Farbablauf: off > red > purple > blue > cyan > green > yellow > white |
64 | walter | 425 | if ((color >= (STEP * 0)) && (color < (STEP * 1))) |
426 | { |
||
65 | walter | 427 | CH3 = MUL * ((color - (STEP * 0))); //fade in red > red (red only) |
428 | CH4 = 0; |
||
429 | CH5 = 0; |
||
64 | walter | 430 | } |
431 | if ((color >= (STEP * 1)) && (color < (STEP * 2))) |
||
432 | { |
||
65 | walter | 433 | CH3 = ((STEP-1) * MUL); |
434 | CH4 = 0; |
||
435 | CH5 = MUL * ((color - (STEP * 1))); //fade in blue > purple (red + blue) |
||
64 | walter | 436 | } |
437 | if ((color >= (STEP * 2)) && (color < (STEP * 3))) |
||
438 | { |
||
65 | walter | 439 | CH3 = MUL * ((STEP - 1) - (color - (STEP * 2))); //fade out red > blue (blue only) |
440 | CH4 = 0; |
||
441 | CH5 = ((STEP-1) * MUL); |
||
64 | walter | 442 | } |
443 | if ((color >= (STEP * 3)) && (color < (STEP * 4))) |
||
444 | { |
||
65 | walter | 445 | CH3 = 0; |
446 | CH4 = MUL * ((color - (STEP * 3))); //fade in green > cyan (blue + green) |
||
447 | CH5 = ((STEP-1) * MUL); |
||
64 | walter | 448 | } |
449 | if ((color >= (STEP * 4)) && (color < (STEP * 5))) |
||
450 | { |
||
65 | walter | 451 | CH3 = 0; |
452 | CH4 = ((STEP-1) * MUL); |
||
453 | CH5 = MUL * ((STEP - 1) - (color - (STEP * 4))); //fade out blue > green (green only) |
||
64 | walter | 454 | } |
455 | if ((color >= (STEP * 5)) && (color < (STEP * 6))) |
||
456 | { |
||
65 | walter | 457 | CH3 = MUL * ((color - (STEP * 5))); //fade in red > yellow (green + red) |
458 | CH4 = ((STEP-1) * MUL); |
||
459 | CH5 = 0; |
||
64 | walter | 460 | } |
65 | walter | 461 | if ((color >= (STEP * 6)) && (color < (STEP * 7))) |
64 | walter | 462 | { |
65 | walter | 463 | CH3 = ((STEP-1) * MUL); |
464 | CH4 = ((STEP-1) * MUL); |
||
465 | CH5 = MUL * ((color - (STEP * 1))); //fade in blue > purple (red + blue) |
||
64 | walter | 466 | } |
65 | walter | 467 | |
468 | if (color >= (STEP * 7)) |
||
469 | { |
||
470 | CH3 = ((STEP-1) * MUL); |
||
471 | CH4 = ((STEP-1) * MUL); |
||
472 | CH5 = ((STEP-1) * MUL); |
||
473 | } |
||
474 | |||
475 | /************************************************************************************/ |
||
476 | /* control CH0, CH1 and CH2 */ |
||
477 | /************************************************************************************/ |
||
478 | |||
479 | if (CheckDelay(dly1)) //timeout reached ? |
||
480 | { |
||
481 | |||
482 | if ((flags & (1<<0))==0) //check if up or down |
||
483 | { |
||
484 | if (CH0++ == 254) //run CH0 up to 255 |
||
485 | { |
||
486 | flags setbit (1<<0); //255 reached next time go down |
||
487 | |||
488 | } |
||
489 | } |
||
490 | else //run down |
||
491 | { |
||
492 | if (CH0-- == 1) //run CH0 down to 0 |
||
493 | { |
||
494 | flags clrbit (1<<0); //0 reached next time go up |
||
495 | } |
||
496 | |||
497 | } |
||
498 | |||
499 | |||
500 | if ((flags & (1<<1))==0) //same for CH1 |
||
501 | { |
||
502 | if (CH1++ == 254) |
||
503 | { |
||
504 | flags setbit (1<<1); |
||
505 | } |
||
506 | } |
||
507 | else |
||
508 | { |
||
509 | if (CH1-- == 1) |
||
510 | { |
||
511 | flags clrbit (1<<1); |
||
512 | } |
||
513 | |||
514 | } |
||
515 | |||
516 | |||
517 | if ((flags & (1<<2))==0) //and same for CH2 |
||
518 | { |
||
519 | if (CH2++ == 254) |
||
520 | { |
||
521 | flags setbit (1<<2); |
||
522 | } |
||
523 | } |
||
524 | else |
||
525 | { |
||
526 | if (CH2-- == 1) |
||
527 | { |
||
528 | flags clrbit (1<<2); |
||
529 | } |
||
530 | |||
531 | } |
||
532 | |||
533 | |||
534 | dly1 = SetDelay(1); //set next timeout in 25ms |
||
535 | |||
536 | // printf("ch3:%i\n",CH0); |
||
537 | } |
||
538 | |||
64 | walter | 539 | } |
540 | |||
541 | } |
||
542 | |||
543 | } |
||
544 |