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 | } |