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