Subversion Repositories Projects

Rev

Go to most recent revision | Details | 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);		//
115
		ch0_tmp = CH0;
116
		ch1_tmp = CH1;
117
		ch2_tmp = CH2;
118
		ch3_tmp = CH3;
119
		ch4_tmp = CH4;
120
		ch5_tmp = CH5;
121
		counter = 0;
122
	}
123
 
124
	if (ch0_tmp == counter)	PORTB_BAK LEDOFF CH0_B;		//channel value reached, output off
125
	if (ch1_tmp == counter)	PORTB_BAK LEDOFF CH1_B;		//
126
	if (ch2_tmp == counter)	PORTB_BAK LEDOFF CH2_B;		//
127
	if (ch3_tmp == counter)	PORTD_BAK LEDOFF CH3_D;		//
128
	if (ch4_tmp == counter)	PORTD_BAK LEDOFF CH4_D;		//
129
	if (ch5_tmp == counter)	PORTD_BAK LEDOFF CH5_D;		//
130
 
131
	PORTB = PORTB_BAK;
132
	PORTD = PORTD_BAK;
133
 
134
	if (ms1++ == 32)
135
	{
136
		ms1=0;
137
		TMR1MS++;
138
	}
139
 
140
 
141
 
142
 
143
}
144
 
145
 
146
/*##############################################################################*/
147
unsigned int SetDelay (unsigned int t)
148
{
149
	unsigned char hi_byte;
150
	unsigned char lo_byte;
151
 
152
	hi_byte = (TMR1MS >> 8);
153
	lo_byte = (TMR1MS & 0xff);
154
	if (hi_byte != (TMR1MS >> 8)) hi_byte = (TMR1MS >> 8);
155
 
156
	return(((hi_byte << 8) | lo_byte)  + t + 1);
157
}
158
 
159
 
160
/*##############################################################################*/
161
char CheckDelay(unsigned int t)
162
{
163
	unsigned char hi_byte;
164
	unsigned char lo_byte;
165
 
166
	hi_byte = (TMR1MS >> 8);
167
	lo_byte = (TMR1MS & 0xff);
168
	if (hi_byte != (TMR1MS >> 8)) hi_byte = (TMR1MS >> 8);
169
 
170
	return(((t - ((hi_byte << 8) | lo_byte)) & 0x8000) >> 9);
171
}
172
 
173
 
174
 
175
/*##############################################################################*/
176
void StartPWM(void)
177
{
178
	//Timer 0 Config
179
	TCCR0 = (0<<CS02)|(0<<CS01)|(1<<CS00);		// (@8MHz) =  1/8us Clk = 256/8 = 32us overflow
180
	TIMSK setbit (1<<TOIE0);						// enable Int
181
 
182
}
183
 
184
 
185
/*##############################################################################*/
186
void StartPPM(void)
187
{
188
 
189
	//Timer1 Config
190
	TCCR1A = 	(0<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)|
191
				(0<<FOC1A) |(0<<FOC1B) |(0<<WGM10) |(0<<WGM11);
192
    TCCR1B = 	(1<<ICNC1)|(1<<ICES1)|(0<<WGM13)|
193
				(0<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10); 				//ICP_POS_FLANKE
194
 
195
	// interrupts
196
	TIMSK |= 	(1<<TICIE1)|(1<<TOIE1);									//ICP_INT_ENABLE and TIMER1_INT_ENABLE
197
 
198
}
199
 
200
 
201
/*##############################################################################*/
202
unsigned int GetPPM(void)
203
{
204
	//this routines seems to be nesseccary, as reading a 16 bit value
205
	//on a 8 bit machine is not atomic, so if an interrupt apears between reading
206
	//low and high byte of the 16 bit value a wrong result is possible
207
 
208
	unsigned char temp_hi;
209
	unsigned char temp_lo;
210
 
211
	temp_hi = (PPM_SIGNAL >> 8);
212
	temp_lo = (PPM_SIGNAL & 0xff);
213
	if (temp_hi != (PPM_SIGNAL >> 8)) temp_hi = (PPM_SIGNAL >> 8);
214
	return( (temp_hi << 8) | temp_lo);
215
 
216
}
217
 
218
 
219
/*##############################################################################*/
220
// MAIN
221
/*##############################################################################*/
222
int main (void)
223
{
224
 
225
	#define	STEP		256
226
	#define	MUL			1
227
	#define REDUCE		2
228
 
229
	#define EEPSIGNATURE	0x55aa
230
 
231
	#define inimin		1200
232
	#define inimax		1800
233
 
234
	unsigned int	ppm;
235
	signed int		color;
236
	unsigned int	setupdly;
237
	unsigned int	ppmtodly;
238
	unsigned int	flashdly;
239
	unsigned char	setup;
240
	unsigned int	lmax;
241
	unsigned int	lmin;
242
	unsigned int	max;
243
	unsigned int	min;
244
	signed long		temp1;
245
	signed long		temp2;
246
 
247
    DDRB  = (CH0_B|CH1_B|CH2_B);
248
    PORTB = 0x00;
249
 
250
    DDRC  = (ledred);
251
    PORTC = 0x00;
252
 
253
    DDRD  = (ledgreen|CH3_D|CH4_D|CH5_D);
254
    PORTD = 0x00;
255
 
256
	CH0 = 0;
257
	CH1 = 0;
258
	CH2 = 0;
259
	CH3 = 0;
260
	CH4 = 0;
261
	CH5 = 0;
262
 
263
	lmax = 0x0000;
264
	lmin = 0xffff;
265
 
266
//	StartUART();
267
	StartPPM();
268
	//StartI2C();
269
	StartPWM();
270
	sei();
271
 
272
	min = inimin;												//default min
273
	max = inimax;												//default max
274
 
275
	if (eeprom_read_word(&EEPSIG) != EEPSIGNATURE)				//check eep if signature is there
276
	{
277
		eeprom_write_word(&EEPMIN, min);						//no, write initial min
278
		eeprom_write_word(&EEPMAX, max);						//and max values
279
		eeprom_write_word(&EEPSIG, EEPSIGNATURE);				//along with eep signature
280
	}
281
	else
282
	{
283
 
284
		min = eeprom_read_word(&EEPMIN);			 			//signature ok
285
		max = eeprom_read_word(&EEPMAX);						//read min and max
286
	}
287
 
288
 
289
	setup = 0;													//reset setup toggle counter
290
	setupdly = SetDelay(5000);
291
	ppmtodly = SetDelay(5000);
292
	flashdly = SetDelay(1000);
293
 
294
    while (1)
295
	{
296
 
297
		if (PPM_NEW > 20)										//ppm Signal ok
298
		{
299
			PORTC clrbit ledred;
300
			ppm = GetPPM();
301
			ppmtodly = SetDelay(500);							//reset timeout
302
			if (lmax < ppm) lmax=ppm;							//update impulse max
303
			if (lmin > ppm) lmin=ppm;							//and min boundarys
304
		}
305
		else
306
		{
307
			PORTC setbit ledred;								//ppm signal not ok
308
			ppm = min;											//set ppm to minimum
309
		}
310
 
311
 
312
		if (CheckDelay(ppmtodly))								//timeout
313
		{
314
			ppmtodly = SetDelay(5000);
315
			PPM_NEW = 0;										//set ppm signal not ok
316
		}
317
 
318
 
319
		if (setup < 6)
320
		{
321
			if ((ppm > 1600) && ((setup&1)==0)) setup++;		//
322
			if ((ppm < 1400) && ((setup&1)==1)) setup++;		//
323
 
324
			if (CheckDelay(flashdly))
325
			{
326
				CH0 = CH0 ^ 0xff;
327
				CH1 = CH1 ^ 0xff;
328
				CH2 = CH2 ^ 0xff;
329
				flashdly = SetDelay(250);
330
			}
331
		}
332
 
333
		if (setup == 6) 										//if stick is toggled 6 times
334
		{														//within setup timeout
335
			PORTD setbit ledgreen;								//store ppm min and max
336
			setupdly = SetDelay(3000);							//for 2000ms
337
			eeprom_write_word(&EEPMIN, lmin);					//in eeprom
338
			eeprom_write_word(&EEPMAX, lmax);
339
			min = lmin;
340
			max = lmax;
341
			setup = 7;											//enter PWM toggle mode
342
 
343
		}
344
 
345
 
346
		if (setup == 7)
347
		{
348
			if (CheckDelay(flashdly)) 							//each 25ms toggle PWM's
349
			{
350
				CH0 = CH0 ^ 0xff;
351
				CH1 = CH1 ^ 0xff;
352
				CH2 = CH2 ^ 0xff;
353
				flashdly = SetDelay(25);
354
			}
355
 
356
		}
357
 
358
		if (CheckDelay(setupdly)) 								//setup timeout reached
359
		{
360
			setup = 8;											//lockdown setup
361
			PORTD clrbit ledgreen;
362
		}
363
 
364
 
365
		if (setup == 8)
366
		{
367
 
368
 
369
 
370
			temp1 = ((long)STEP * 6 * 20000) / ((max-REDUCE) - (min+REDUCE));
371
			temp2 = (((int)ppm - ((int)min+REDUCE)) * temp1);
372
			color = temp2 / 20000;
373
 
374
			if (color < 0) color = 0;
375
			if (color > ((STEP*6)+1)) color = ((STEP*6)+1);
376
 
377
 
378
			//printf("p %u  ",ppm);
379
			//printf("pm %u  ",(min+REDUCE));
380
			//printf("t1 %li  ",temp1);
381
			//printf("t2 %li  ",temp2);
382
			//printf("c %i\n  ",color);
383
 
384
 
385
			// Farbablauf: rot > Violett > blau > tuerkis > gruen > gelb >
386
			if ((color >= (STEP * 0)) && (color < (STEP * 1)))
387
			{
388
				CH0 = MUL * ((color - (STEP * 0)));				//fade in red > red (red only)
389
				CH1 = 0;
390
				CH2 = 0;
391
			}
392
			if ((color >= (STEP * 1)) && (color < (STEP * 2)))
393
			{
394
				CH0 = ((STEP-1) * MUL);
395
				CH1 = 0;
396
				CH2 = MUL * ((color - (STEP * 1)));				//fade in blue > purple (red + blue)
397
			}
398
			if ((color >= (STEP * 2)) && (color < (STEP * 3)))
399
			{
400
				CH0 = MUL * ((STEP - 1) - (color - (STEP * 2)));	//fade out red > blue (blue only)
401
				CH1 = 0;
402
				CH2 = ((STEP-1) * MUL);
403
			}
404
			if ((color >= (STEP * 3)) && (color < (STEP * 4)))
405
			{
406
				CH0 = 0;
407
				CH1 = MUL * ((color - (STEP * 3)));				//fade in green > cyan (blue + green)
408
				CH2 = ((STEP-1) * MUL);
409
			}
410
			if ((color >= (STEP * 4)) && (color < (STEP * 5)))
411
			{
412
				CH0 = 0;
413
				CH1 = ((STEP-1) * MUL);
414
				CH2 = MUL * ((STEP - 1) - (color - (STEP * 4)));	//fade out blue > green (green only)
415
			}
416
			if ((color >= (STEP * 5)) && (color < (STEP * 6)))
417
			{
418
				CH0 = MUL * ((color - (STEP * 5)));				//fade in red > yellow (green + red)
419
				CH1 = ((STEP-1) * MUL);
420
				CH2 = 0;
421
			}
422
			if (color >= (STEP * 6))
423
			{
424
				CH0 = ((STEP-1) * MUL);							//fade in red > yellow (green + red)
425
				CH1 = ((STEP-1) * MUL);
426
				CH2 = 0;
427
			}
428
		}
429
 
430
 
431
	}
432
 
433
}
434