Subversion Repositories Projects

Rev

Rev 791 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
780 - 1
// ***************************************************************
931 - 2
// ** Spektrum Diversity v2.0 - use up to 4 satellite receivers **
780 - 3
// ***************************************************************
4
// ** Target: An Atmel ATtiny2313 (RC-Oscillator @ 8 MHz)       **
5
// **         controls a 74HC151 Multiplexer                    **
6
// ***************************************************************
7
// ** It monitors the data from 4 satellite receivers and       **
8
// ** connects a valid one to the output via the multiplexer    **
9
// ***************************************************************
791 - 10
// ** LED-Modes during startup                                  **
780 - 11
// ** ************************                                  **
931 - 12
// ** LED fast flash: Waiting for first signal                  **
780 - 13
// **                                                           **
14
// ** LED-Modes during operation                                **
15
// ** **************************                                **
931 - 16
// ** LED flash 1x - 4x: Shows which channel is active every 2s **
17
// ** LED ON after flash: FAILURE - A used signal was lost      **
780 - 18
// **                                                           **
791 - 19
// ** LED-Modes after Self-Test and pressed button              **
20
// ** ********************************************              **
780 - 21
// ** LED flashes at 1 Hz: Everything is fine                   **
22
// ** LED flashes some times: Times flashed -> damaged Channel# **
791 - 23
// ** LED off: check voltage(regulator), button or firmware     **
780 - 24
// ***************************************************************
25
// ** (c) 2010-0xFFFF Stefan Pendsa                             **
26
// ** License: don't know - use it and have fun                 **
27
// ***************************************************************
775 - 28
 
29
#include <avr/io.h>
791 - 30
#include <avr/eeprom.h>
775 - 31
#include <avr/interrupt.h>
32
#include <util/delay.h>
33
 
791 - 34
 
780 - 35
#define LED_OFF	PORTD |= 1 << PD0
36
#define LED_ON	PORTD &= ~(1 << PD0)
775 - 37
 
931 - 38
volatile unsigned char Timer0Event = 0;
39
volatile unsigned int Timer1Event;
40
volatile unsigned char BlinkCode = 0;
41
volatile unsigned char failure = 0;
775 - 42
 
791 - 43
unsigned char eedummy EEMEM;								// Dummy-Variable for Address 0 in EEPROM
44
unsigned char eecheck EEMEM;								// Check-Variable
45
unsigned char bind;											// Bind-Pulse-Counter (in RAM)
46
unsigned char eebind EEMEM;									// Bind-Pulse-Counter (in EEPROM)
775 - 47
 
778 - 48
 
791 - 49
 
931 - 50
ISR(TIMER0_OVF_vect)										// Triggered every 32,768 msec
51
{
52
	if (Timer0Event > 64)									// Max. 64*32 msec = 2,097152 sec
53
	{
54
		Timer0Event = 0;
55
		LED_OFF;
56
	}
57
 
58
	if(Timer0Event == 0 && BlinkCode > 0) LED_ON;
59
	else if(Timer0Event == 4 && BlinkCode > 0) LED_OFF;
60
	else if(Timer0Event == 8 && BlinkCode > 1) LED_ON;
61
	else if(Timer0Event == 12 && BlinkCode > 1) LED_OFF;
62
	else if(Timer0Event == 16 && BlinkCode > 2) LED_ON;
63
	else if(Timer0Event == 20 && BlinkCode > 2) LED_OFF;
64
	else if(Timer0Event == 24 && BlinkCode > 3) LED_ON;
65
	else if(Timer0Event == 28 && BlinkCode > 3) LED_OFF;
66
	else if(Timer0Event == 35 && failure == 1) LED_ON;
67
	else if(Timer0Event == 55 && failure == 1) LED_OFF;
68
 
69
	Timer0Event++;
70
}
71
 
72
 
778 - 73
ISR(TIMER1_OVF_vect)										// Triggered every 8,192 msec
74
{
931 - 75
	Timer1Event++;
778 - 76
}
77
 
78
 
775 - 79
void SelectSat(unsigned char sat)
80
{
780 - 81
	PORTD = (PORTD & 0b1100111) | (sat << 3);				// Select the input for 74HC151
82
	_delay_us(10);											// Wait for stable state
775 - 83
}
84
 
778 - 85
 
86
 
931 - 87
void ResetTimer1(void)
775 - 88
{
89
	TCNT1H = 0;
90
	TCNT1L = 0;
931 - 91
	Timer1Event = 0;
775 - 92
}
93
 
94
 
778 - 95
 
931 - 96
void Binding(void)											// Binding sequence (for Spektrum sats only)
776 - 97
{
98
	unsigned char i = 0;
775 - 99
 
776 - 100
	DDRB = 0b11110000;										// Sat-Pins to output
780 - 101
	_delay_ms(80);											// Let them time to boot up
776 - 102
 
791 - 103
	for (i=0;i<bind;i++)									// Send negative 100µs pulses to all sat's
776 - 104
	{
105
		PORTB = 0b00000000;
106
		_delay_us(100);
107
		PORTB = 0b11110000;
108
		_delay_us(100);
109
	}
110
 
791 - 111
	for (i=0;i<bind;i++)									// Flash the number of used pulses to the LED
112
	{
113
		LED_ON;
114
		_delay_ms(100);
115
		LED_OFF;
116
		_delay_ms(250);
117
	}
118
 
119
	DDRB = 0b00000000;										// Sat-Pins to input again
120
 
121
	bind++;													// Save increased bind-pulse-counter for next binding.
122
	if (bind > 6) bind = 3;									// 3 pulses are for DX7+AR6200, 4-6 pulses have been seen...
123
	eeprom_write_byte(&eebind, bind);						// around the world for other combinations. Hopefully it works for them.
124
	_delay_ms(500);
776 - 125
}
126
 
127
 
778 - 128
 
776 - 129
void Testing(void)											// Self Test
775 - 130
{
778 - 131
	unsigned char error = 0;
776 - 132
	unsigned char i = 0;
133
 
778 - 134
	DDRB = 0b11110000;										// Port B Output for satellites, Input for feedback
776 - 135
 
778 - 136
	PORTB = 0b01010000;										// Test Pattern
137
	SelectSat(0);
780 - 138
	if (!(PINB & (1<<PB3))) error = 1;
778 - 139
	SelectSat(1);
780 - 140
	if (PINB & (1<<PB3)) error = 2;
778 - 141
	SelectSat(2);
780 - 142
	if (!(PINB & (1<<PB3))) error = 3;
778 - 143
	SelectSat(3);
780 - 144
	if (PINB & (1<<PB3)) error = 4;
776 - 145
 
778 - 146
	PORTB = 0b10100000;										// Another (inverted) Test Pattern
147
	SelectSat(0);
780 - 148
	if (PINB & (1<<PB3)) error = 1;
778 - 149
	SelectSat(1);
780 - 150
	if (!(PINB & (1<<PB3))) error = 2;
778 - 151
	SelectSat(2);
780 - 152
	if (PINB & (1<<PB3)) error = 3;
778 - 153
	SelectSat(3);
780 - 154
	if (!(PINB & (1<<PB3))) error = 4;
778 - 155
 
156
	DDRB = 0b00000000;										// Port B Input again
157
 
791 - 158
	while (PIND & (1<<PD6));								// Wait for Bind-Switch
159
 
776 - 160
	while(1)												// Never return
161
	{
778 - 162
		if (error == 0)										// When no error occured -> LED flashes at 1 Hz
776 - 163
		{
164
			LED_ON;
165
			_delay_ms(100);
166
			LED_OFF;
778 - 167
			_delay_ms(900);
776 - 168
		}
778 - 169
		else
170
		{
780 - 171
			for (i=0;i<error;i++)							// When error occured -> Flash-Out the Errorcode
778 - 172
			{
173
				LED_ON;
174
				_delay_ms(100);
175
				LED_OFF;
176
				_delay_ms(400);
177
			}
178
			_delay_ms(1000);
179
		}
180
 
776 - 181
	}
778 - 182
 
776 - 183
}
184
 
185
 
775 - 186
 
187
int main(void)
188
{
189
	unsigned char i = 0;
776 - 190
	unsigned char active[4];
931 - 191
	unsigned char active_lo[4];
192
	unsigned char active_hi[4];
791 - 193
	unsigned char sat = 99;
775 - 194
 
931 - 195
 
778 - 196
	DDRB = 0b00000000;										// Port B Input for satellites and feedback
197
	DDRD = 0b0011001;										// Port D Output for MUX and LED, Input for Switch & Test
198
	PORTB = 0b11110000;										// Port B Pullup's for (unused) satellites
780 - 199
	PORTD = 0b1100001;										// Port D Pullup's for Switch & Test, LED off
775 - 200
 
791 - 201
    if (eeprom_read_byte(&eecheck) != 0x42)					// Invalid Data in EEPROM -> initialize
202
	{
203
		eeprom_write_byte(&eecheck, 0x42);
204
		bind = 3;
205
		eeprom_write_byte(&eebind, bind);
206
	}
207
	else bind = eeprom_read_byte(&eebind);					// Valid Data in EEPROM -> read bind-pulse-counter
208
 
209
 
778 - 210
	if (!(PIND & (1<<PD5))) Testing();						// Initiate Self-Test when Test-Pad is low
776 - 211
	if (!(PIND & (1<<PD6))) Binding();						// Initiate Binding when Bind-Button is pressed
212
 
931 - 213
 
214
	for (i=0;i<4;i++)										// Reset active-arrays
215
	{
216
		active[i] = 0;
217
		active_lo[i] = 0;
218
		active_hi[i] = 0;
219
	}
220
 
780 - 221
	_delay_ms(100);
222
 
931 - 223
	TCCR0B = ( 1 << CS00 ) | ( 1 << CS02 );					// Timer0 Prescaler = 1024 -> 32,768 msec
776 - 224
	TCCR1B = ( 1 << CS10 );									// Timer1 Prescaler = 1 -> 8,192 msec
931 - 225
	TIMSK = ( 1 << TOIE0 ) | ( 1 << TOIE1 );				// Timer0+1 Overflow Interrupt Enable
775 - 226
	sei();													// Global Interrupts enable
227
 
931 - 228
	ResetTimer1();
791 - 229
	while(sat == 99)										// Wait for first signal
775 - 230
	{
931 - 231
		if (Timer1Event == 10) LED_ON;						// Blink while waiting
232
		if (Timer1Event == 20)
775 - 233
		{
234
			LED_OFF;
931 - 235
			Timer1Event = 0;
775 - 236
		}
237
 
931 - 238
		while(Timer1Event < 3)								// Check active satellites (for 3*8=24ms)
775 - 239
		{
931 - 240
			for (i=0;i<4;i++)
775 - 241
			{
931 - 242
				if (PINB & (1<<(i+4))) active_hi[i] = 1;
243
				else active_lo[i] = 1;
244
			}
245
		}
246
 
247
		for (i=0;i<4;i++)									// When an input had low AND high signals, mark it as active
248
		{
249
			if (active_lo[i] == 1 && active_hi[i] == 1) active[i] = 1;
250
		}
251
 
252
 
253
		for (i=0;i<4;i++)									// Select first active satellite
254
		{
255
			if (active[i] == 1)
256
			{
257
				SelectSat(i);
791 - 258
				sat = i;
931 - 259
				BlinkCode = i+1;
791 - 260
				break;
775 - 261
			}
262
		}
931 - 263
 
775 - 264
	}
265
 
266
 
931 - 267
 
268
 
775 - 269
	while(1)												// Main-Loop
270
	{
931 - 271
		for (i=0;i<4;i++)									// Reset active-arrays
775 - 272
		{
931 - 273
			active[i] = 0;
274
			active_lo[i] = 0;
275
			active_hi[i] = 0;
775 - 276
		}
931 - 277
 
278
		ResetTimer1();
279
		while(Timer1Event < 3)								// Check active satellites (for 3*8=24ms)
775 - 280
		{
776 - 281
			for (i=0;i<4;i++)
775 - 282
			{
931 - 283
				if (PINB & (1<<(i+4))) active_hi[i] = 1;
284
				else active_lo[i] = 1;
775 - 285
			}
286
		}
287
 
931 - 288
 
289
		for (i=0;i<4;i++)									// When an input had low AND high signals, mark it as active
775 - 290
		{
931 - 291
			if (active_lo[i] == 1 && active_hi[i] == 1) active[i] = 1;
292
		}
293
 
294
 
295
		if (active[0] == 0 && active[1] == 0 && active[2] == 0 && active[3] == 0 && sat != 99)
296
		{
297
			failure = 1;									// Set Failure-LED when the signal is lost completely
298
			BlinkCode = 0;
299
			sat = 99;
300
		}
301
 
302
 
303
		for (i=0;i<4;i++)									// Select active satellite (priorized)
304
		{
305
			if (active[i] == 1)
775 - 306
			{
931 - 307
				SelectSat(i);
308
				if (sat != i) failure = 1;					// Set Failure-LED when the active satellite changes
309
				sat = i;
310
				BlinkCode = i+1;
311
				break;
775 - 312
			}
313
		}
776 - 314
 
931 - 315
 
316
 
317
		if (!(PIND & (1<<PD6))) failure = 0;				// Reset Failure-LED when Bind-Button is pressed
775 - 318
	}
776 - 319
 
775 - 320
}