Subversion Repositories Projects

Rev

Rev 64 | 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