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