Rev 780 | Rev 931 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
780 | - | 1 | // *************************************************************** |
791 | - | 2 | // ** Spektrum Diversity v1.3 - 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 | // ** ************************ ** |
791 | - | 12 | // ** LED fast flash: Waiting for first datapulse ** |
780 | - | 13 | // ** ** |
14 | // ** LED-Modes during operation ** |
||
15 | // ** ************************** ** |
||
16 | // ** LED OFF: Everything is fine ** |
||
17 | // ** LED ON: FAILURE - The first selected sat had lost sync ** |
||
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 | |
38 | volatile unsigned int TimerEvent; |
||
39 | |||
791 | - | 40 | unsigned char eedummy EEMEM; // Dummy-Variable for Address 0 in EEPROM |
41 | unsigned char eecheck EEMEM; // Check-Variable |
||
42 | unsigned char bind; // Bind-Pulse-Counter (in RAM) |
||
43 | unsigned char eebind EEMEM; // Bind-Pulse-Counter (in EEPROM) |
||
775 | - | 44 | |
778 | - | 45 | |
791 | - | 46 | |
778 | - | 47 | ISR(TIMER1_OVF_vect) // Triggered every 8,192 msec |
48 | { |
||
49 | TimerEvent++; |
||
50 | } |
||
51 | |||
52 | |||
53 | |||
775 | - | 54 | void SelectSat(unsigned char sat) |
55 | { |
||
780 | - | 56 | PORTD = (PORTD & 0b1100111) | (sat << 3); // Select the input for 74HC151 |
57 | _delay_us(10); // Wait for stable state |
||
775 | - | 58 | } |
59 | |||
778 | - | 60 | |
61 | |||
775 | - | 62 | void ResetTimer(void) |
63 | { |
||
64 | TCNT1H = 0; |
||
65 | TCNT1L = 0; |
||
66 | TimerEvent = 0; |
||
67 | } |
||
68 | |||
69 | |||
778 | - | 70 | |
791 | - | 71 | void Binding(void) // Binding sequence |
776 | - | 72 | { |
73 | unsigned char i = 0; |
||
775 | - | 74 | |
776 | - | 75 | DDRB = 0b11110000; // Sat-Pins to output |
780 | - | 76 | _delay_ms(80); // Let them time to boot up |
776 | - | 77 | |
791 | - | 78 | for (i=0;i<bind;i++) // Send negative 100µs pulses to all sat's |
776 | - | 79 | { |
80 | PORTB = 0b00000000; |
||
81 | _delay_us(100); |
||
82 | PORTB = 0b11110000; |
||
83 | _delay_us(100); |
||
84 | } |
||
85 | |||
791 | - | 86 | for (i=0;i<bind;i++) // Flash the number of used pulses to the LED |
87 | { |
||
88 | LED_ON; |
||
89 | _delay_ms(100); |
||
90 | LED_OFF; |
||
91 | _delay_ms(250); |
||
92 | } |
||
93 | |||
94 | DDRB = 0b00000000; // Sat-Pins to input again |
||
95 | |||
96 | 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... |
||
98 | eeprom_write_byte(&eebind, bind); // around the world for other combinations. Hopefully it works for them. |
||
99 | _delay_ms(500); |
||
776 | - | 100 | } |
101 | |||
102 | |||
778 | - | 103 | |
776 | - | 104 | void Testing(void) // Self Test |
775 | - | 105 | { |
778 | - | 106 | unsigned char error = 0; |
776 | - | 107 | unsigned char i = 0; |
108 | |||
778 | - | 109 | DDRB = 0b11110000; // Port B Output for satellites, Input for feedback |
776 | - | 110 | |
778 | - | 111 | PORTB = 0b01010000; // Test Pattern |
112 | SelectSat(0); |
||
780 | - | 113 | if (!(PINB & (1<<PB3))) error = 1; |
778 | - | 114 | SelectSat(1); |
780 | - | 115 | if (PINB & (1<<PB3)) error = 2; |
778 | - | 116 | SelectSat(2); |
780 | - | 117 | if (!(PINB & (1<<PB3))) error = 3; |
778 | - | 118 | SelectSat(3); |
780 | - | 119 | if (PINB & (1<<PB3)) error = 4; |
776 | - | 120 | |
778 | - | 121 | PORTB = 0b10100000; // Another (inverted) Test Pattern |
122 | SelectSat(0); |
||
780 | - | 123 | if (PINB & (1<<PB3)) error = 1; |
778 | - | 124 | SelectSat(1); |
780 | - | 125 | if (!(PINB & (1<<PB3))) error = 2; |
778 | - | 126 | SelectSat(2); |
780 | - | 127 | if (PINB & (1<<PB3)) error = 3; |
778 | - | 128 | SelectSat(3); |
780 | - | 129 | if (!(PINB & (1<<PB3))) error = 4; |
778 | - | 130 | |
131 | DDRB = 0b00000000; // Port B Input again |
||
132 | |||
791 | - | 133 | while (PIND & (1<<PD6)); // Wait for Bind-Switch |
134 | |||
776 | - | 135 | while(1) // Never return |
136 | { |
||
778 | - | 137 | if (error == 0) // When no error occured -> LED flashes at 1 Hz |
776 | - | 138 | { |
139 | LED_ON; |
||
140 | _delay_ms(100); |
||
141 | LED_OFF; |
||
778 | - | 142 | _delay_ms(900); |
776 | - | 143 | } |
778 | - | 144 | else |
145 | { |
||
780 | - | 146 | for (i=0;i<error;i++) // When error occured -> Flash-Out the Errorcode |
778 | - | 147 | { |
148 | LED_ON; |
||
149 | _delay_ms(100); |
||
150 | LED_OFF; |
||
151 | _delay_ms(400); |
||
152 | } |
||
153 | _delay_ms(1000); |
||
154 | } |
||
155 | |||
776 | - | 156 | } |
778 | - | 157 | |
776 | - | 158 | } |
159 | |||
160 | |||
775 | - | 161 | |
162 | int main(void) |
||
163 | { |
||
164 | unsigned char i = 0; |
||
776 | - | 165 | unsigned char active[4]; |
791 | - | 166 | unsigned char sat = 99; |
775 | - | 167 | |
778 | - | 168 | DDRB = 0b00000000; // Port B Input for satellites and feedback |
169 | DDRD = 0b0011001; // Port D Output for MUX and LED, Input for Switch & Test |
||
170 | PORTB = 0b11110000; // Port B Pullup's for (unused) satellites |
||
780 | - | 171 | PORTD = 0b1100001; // Port D Pullup's for Switch & Test, LED off |
775 | - | 172 | |
776 | - | 173 | for (i=0;i<4;i++) active[i] = 0; // Reset active-array |
174 | |||
791 | - | 175 | |
176 | if (eeprom_read_byte(&eecheck) != 0x42) // Invalid Data in EEPROM -> initialize |
||
177 | { |
||
178 | eeprom_write_byte(&eecheck, 0x42); |
||
179 | bind = 3; |
||
180 | eeprom_write_byte(&eebind, bind); |
||
181 | } |
||
182 | else bind = eeprom_read_byte(&eebind); // Valid Data in EEPROM -> read bind-pulse-counter |
||
183 | |||
184 | |||
778 | - | 185 | if (!(PIND & (1<<PD5))) Testing(); // Initiate Self-Test when Test-Pad is low |
776 | - | 186 | if (!(PIND & (1<<PD6))) Binding(); // Initiate Binding when Bind-Button is pressed |
187 | |||
780 | - | 188 | _delay_ms(100); |
189 | |||
776 | - | 190 | TCCR1B = ( 1 << CS10 ); // Timer1 Prescaler = 1 -> 8,192 msec |
775 | - | 191 | TIMSK = ( 1 << TOIE1 ); // Timer1 Overflow Interrupt Enable |
192 | sei(); // Global Interrupts enable |
||
193 | |||
194 | ResetTimer(); |
||
791 | - | 195 | while(sat == 99) // Wait for first signal |
775 | - | 196 | { |
197 | if (TimerEvent == 10) LED_ON; // Blink while waiting... |
||
198 | if (TimerEvent == 20) |
||
199 | { |
||
200 | LED_OFF; |
||
201 | TimerEvent = 0; |
||
202 | } |
||
203 | |||
791 | - | 204 | for (i=0;i<4;i++) // Select first active Satellite |
775 | - | 205 | { |
776 | - | 206 | if (!(PINB & (1<<(i+4)))) |
775 | - | 207 | { |
208 | active[i] = 1; |
||
791 | - | 209 | sat = i; |
210 | SelectSat(sat); |
||
211 | break; |
||
775 | - | 212 | } |
213 | } |
||
214 | } |
||
215 | |||
216 | LED_OFF; |
||
217 | |||
218 | while(1) // Main-Loop |
||
219 | { |
||
778 | - | 220 | for (i=0;i<4;i++) active[i] = 0; // Reset active-array |
221 | |||
775 | - | 222 | ResetTimer(); |
776 | - | 223 | while((PINB & 0b11110000) == 0b11110000) // Wait for first signal (SYNC to frame) |
775 | - | 224 | { |
225 | if (TimerEvent > 3) break; // (max. 3*8=24ms) |
||
226 | } |
||
227 | |||
228 | ResetTimer(); |
||
229 | while(TimerEvent < 1) // Check active satellites (for 1*8=8ms) |
||
230 | { |
||
776 | - | 231 | for (i=0;i<4;i++) |
775 | - | 232 | { |
776 | - | 233 | if (!(PINB & (1<<(i+4)))) |
775 | - | 234 | { |
235 | active[i] = 1; |
||
236 | } |
||
237 | } |
||
238 | } |
||
239 | |||
240 | if (active[sat] == 0) // Detect fail on active satellite |
||
241 | { |
||
776 | - | 242 | for (i=0;i<4;i++) // Select lowest active satellite |
775 | - | 243 | { |
244 | if (active[i] == 1) |
||
245 | { |
||
246 | sat = i; |
||
247 | SelectSat(sat); |
||
248 | break; |
||
249 | } |
||
250 | } |
||
791 | - | 251 | LED_ON; // Failure-LED ON |
775 | - | 252 | } |
776 | - | 253 | |
778 | - | 254 | if (!(PIND & (1<<PD6))) LED_OFF; // Reset Failure-LED when Bind-Button is pressed |
775 | - | 255 | } |
776 | - | 256 | |
775 | - | 257 | } |