Subversion Repositories FlightCtrl

Rev

Rev 1544 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1538 killagreg 1
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2
// + Copyright (c) Holger Buss, Ingo Busker
3
// + Nur für den privaten Gebrauch
4
// + www.MikroKopter.com
5
// + porting the sources to other systems or using the software on other systems (except hardware from www.mikrokopter.de) is not allowed
6
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
8
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
9
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt
10
// + bzgl. der Nutzungsbedingungen aufzunehmen.
11
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
12
// + Verkauf von Luftbildaufnahmen, usw.
13
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
14
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
15
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
16
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
18
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
19
// + eindeutig als Ursprung verlinkt werden
20
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
22
// + Benutzung auf eigene Gefahr
23
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
24
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
25
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
26
// + mit unserer Zustimmung zulässig
27
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
28
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
29
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
30
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
31
// + this list of conditions and the following disclaimer.
32
// +   * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
33
// +     from this software without specific prior written permission.
34
// +   * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
35
// +     for non-commercial use (directly or indirectly)
36
// +     Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
37
// +     with our written permission
38
// +   * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
39
// +     clearly linked as origin
40
// +   * porting to systems other than hardware from www.mikrokopter.de is not allowed
41
// +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
42
// +  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
// +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
// +  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
45
// +  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
46
// +  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
47
// +  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
48
// +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN// +  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
// +  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50
// +  POSSIBILITY OF SUCH DAMAGE.
51
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
52
#include <stdlib.h>
53
#include <avr/interrupt.h>
54
 
55
#include "rc.h"
56
#include "eeprom.h"
57
#include "main.h"
58
#include "fc.h"
59
#include "uart0.h"
60
 
61
 
62
//#define ACT_S3D_SUMSIGNAL
63
 
64
volatile uint8_t RC_Channels;   // number of received channels
65
volatile int16_t PPM_in[MAX_CHANNELS]; //PPM24 supports 12 channels per frame
66
volatile int16_t PPM_diff[MAX_CHANNELS];
67
volatile uint8_t NewPpmData = 1;
68
volatile uint8_t RC_Quality = 0;
69
volatile uint8_t RC_RSSI = 0; // Received Signal Strength Indication
70
 
71
 
72
 
73
/***************************************************************/
74
/*  16bit timer 1 is used to decode the PPM-Signal            */
75
/***************************************************************/
76
void RC_Init (void)
77
{
78
        uint8_t sreg = SREG;
79
 
80
        // disable all interrupts before reconfiguration
81
        cli();
82
 
1545 LPDunwell 83
        #ifndef USE_RC_JENNIC // LPD: FC_JN_Receiver support added
84
                // PPM-signal is connected to the Input Capture Pin (PD6) of timer 1
85
                DDRD &= ~(1<<DDD6);
86
                PORTD |= (1<<PORTD6);
87
        #endif
1538 killagreg 88
 
89
        // Channel 5,6,7 is decoded to servo signals at pin PD5 (J3), PD4(J4), PD3(J5)
90
        // set as output
91
        DDRD |= (1<<DDD5)|(1<<DDD4);
92
        // low level
93
        PORTD &= ~((1<<PORTD5)|(1<<PORTD4));
94
 
95
        // PD3 can't be used if 2nd UART is activated
96
        // because TXD1 is at that port
97
        if(CPUType != ATMEGA644P)
98
        {
99
                DDRD |= (1<<PORTD3);
100
                PORTD &= ~(1<<PORTD3);
101
        }
102
 
103
        // Timer/Counter1 Control Register A, B, C
104
 
105
        // Normal Mode (bits: WGM13=0, WGM12=0, WGM11=0, WGM10=0)
106
        // Compare output pin A & B is disabled (bits: COM1A1=0, COM1A0=0, COM1B1=0, COM1B0=0)
107
        TCCR1A &= ~((1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|(1<<WGM11)|(1<<WGM10));
108
#ifndef ACT_S3D_SUMSIGNAL
109
        // Set clock source to SYSCLK/64 (bit: CS12=0, CS11=1, CS10=1)
110
        // Enable input capture noise cancler (bit: ICNC1=1)
111
        // Trigger on positive edge of the input capture pin (bit: ICES1=1),
112
        // Therefore the counter incremets at a clock of 20 MHz/64 = 312.5 kHz or 3.2µs
113
        // The longest period is 0xFFFF / 312.5 kHz = 0.209712 s.
114
        TCCR1B &= ~((1<<WGM13)|(1<<WGM12)|(1<<CS12));
115
        TCCR1B |= (1<<CS11)|(1<<CS10)|(1<<ICES1)|(1<<ICNC1);
116
#else
117
        // Set clock source to SYSCLK/8 (bit: CS12=0, CS11=1, CS10=0)
118
        // Enable input capture noise cancler (bit: ICNC1=1)
119
        // Trigger on positive edge of the input capture pin (bit: ICES1=1),
120
        // Therefore the counter incremets at a clock of 20 MHz/8 = 2.5 MHz or 0.4µs
121
    // The longest period is 0xFFFF / 2.5 MHz = 0.026214 s.
122
        TCCR1B &= ~((1<<WGM13)|(1<<WGM12)|(1<<CS12)|(1<<CS10));
123
        TCCR1B |= (1<<CS11)|(1<<ICES1)|(1<<ICNC1);
124
#endif
125
        TCCR1C &= ~((1<<FOC1A)|(1<<FOC1B));
126
 
127
        // Timer/Counter1 Interrupt Mask Register
128
 
129
        // Enable Input Capture Interrupt (bit: ICIE1=1)
130
        // Disable Output Compare A & B Match Interrupts and Overflow Interrupt (bit: OCIE1B=0, OICIE1A=0, TOIE1=0)
131
        TIMSK1 &= ~((1<<OCIE1B)|(1<<OCIE1A)|(1<<TOIE1));
132
 
133
    PPM_INPUT_ON; //enabled by default
134
 
135
    SREG = sreg;
136
}
137
 
138
 
139
/********************************************************************/
140
/*         Every time a positive edge is detected at PD6            */
141
/********************************************************************/
142
/*                               t-Frame
143
       <----------------------------------------------------------------------->
144
         ____   ______   _____   ________                ___   ________________   ____
145
        |    | |      | |     | |        |              |   | |                | |
146
        |    | |      | |     | |        |              |   | |    sync gap    | |
147
     ___|    |_|      |_|     |_|        |_............_|   |_|                |_|
148
        <-----><-------><------><-------->              <----->                   <---
149
          t0       t1      t2       t4                     tn                       t0
150
 
151
The PPM-Frame length is 22.5 ms.
152
Channel high pulse width range is 0.7 ms to 1.7 ms completed by an 0.3 ms low pulse.
153
The mininimum time delay of two events coding a channel is ( 0.7 + 0.3) ms = 1 ms.
154
The maximum time delay of two events coding a chanel is ( 1.7 + 0.3) ms = 2 ms.
155
The minimum duration of all channels at minimum value is  8 * 1 ms = 8 ms.
156
The maximum duration of all channels at maximum value is  8 * 2 ms = 16 ms.
157
The remaining time of (22.5 - 8 ms) ms = 14.5 ms  to (22.5 - 16 ms) ms = 6.5 ms is
158
the syncronization gap.
159
*/
160
 
1545 LPDunwell 161
#ifndef USE_RC_JENNIC // LPD: FC_JN_Receiver support added   
1538 killagreg 162
#ifndef ACT_S3D_SUMSIGNAL
163
 
164
ISR(TIMER1_CAPT_vect) // typical rate of 1 ms to 2 ms
165
{
166
    int16_t signal = 0, tmp;
167
    uint8_t i;
168
        static uint8_t index = 1;
169
        static uint16_t oldICR1 = 0;
170
 
171
 
172
        // 16bit Input Capture Register ICR1 contains the timer value TCNT1
173
        // at the time the edge was detected
174
 
175
        // calculate the time delay to the previous event time which is stored in oldICR1
176
        // calculatiing the difference of the two uint16_t and converting the result to an int16_t
177
        // implicit handles a timer overflow 65535 -> 0 the right way.
178
        signal = (uint16_t) ICR1 - oldICR1;
179
        oldICR1 = ICR1;
180
 
181
        if(ParamSet.Config2 & CFG2_SENSITIVE_RC)
182
        {
183
                static int16_t old_ppm_in[MAX_CHANNELS];
184
                static int16_t ppm_in[MAX_CHANNELS];
185
                static int16_t ppm_diff[MAX_CHANNELS];
186
                static uint8_t okay_cnt = 0;
187
 
188
                //sync gap? (3.52 ms < signal < 25.6 ms)
189
                if((signal > 1100) && (signal < 8000))
190
                {
191
                        // if a sync gap happens and there where at least 4 channels decoded
192
                        // and the number of channes decoded since the last sync gap matches the expectation
193
                        // then the NewPpmData flag is reset indicating valid data in the PPM_in[] array.
194
                        index--; // no next channel because the sync gap was detected
195
                        if(index >= 4 && index == RC_Channels)
196
                        {
197
                                if(okay_cnt > 10) // at least 10 frames in line ok
198
                                {
199
 
200
                                        for(i=0; i < MAX_CHANNELS; i++)
201
                                        {
202
                                                if(okay_cnt > 30) // at least 30 frames ok
203
                                                {
204
                                                        old_ppm_in[i] = PPM_in[i]; // backup data
205
                                                }
206
                                                PPM_in[i] = ppm_in[i];
207
                                                PPM_diff[i] = ppm_diff[i];
208
                                        }
209
                                        NewPpmData = 0;  // Null means NewData for at least the first 4 channels
210
                                }
211
                                if(okay_cnt < 255) okay_cnt++;
212
                        } // eof if(index >= 4 && index == RC_Channels)
213
                        else
214
                        {
215
                                if(okay_cnt > 100) okay_cnt = 10;
216
                                else okay_cnt = 0;
217
                                RED_ON;
218
                        }
219
                        // store max channels transmitted
220
                        if(!(MKFlags & MKFLAG_MOTOR_RUN)) RC_Channels = index;
221
                        // reset channel index
222
                        index = 1;
223
                }
224
                else // assuming within the PPM frame
225
                {
226
                        if(index < MAX_CHANNELS)
227
                        {
228
                                // check for valid signal length (0.8 ms < signal < 2.1984 ms)
229
                                // signal range is from 1.0ms/3.2us = 312 to 2.0ms/3.2us = 625
230
                                if((signal > 250) && (signal < 687))
231
                                {
232
                                        // shift signal to zero symmetric range  -154 to 159
233
                                        signal -= 466; // offset of 1.4912 ms ??? (469 * 3.2µs = 1.5008 ms)
234
                                        // check for stable signal
235
                                        if(abs(signal - ppm_in[index]) < 6)
236
                                        {
237
                                                if(okay_cnt > 25) RC_Quality +=10;
238
                                                else if(okay_cnt > 10) RC_Quality += 2;
239
                                                if(RC_Quality > 200) RC_Quality = 200;
240
                                        }
241
                                        // calculate exponential history for signal
242
                                        tmp = (3 * (ppm_in[index]) + signal) / 4;
243
                                        if(tmp > signal+1) tmp--; else
244
                                        if(tmp < signal-1) tmp++;
245
                                        // calculate signal difference on good signal level
246
                                        if(RC_Quality >= 190)  ppm_diff[index] = ((tmp - ppm_in[index]) / 3) * 3; // cut off lower 3 bit for nois reduction
247
                                        else ppm_diff[index] = 0;
248
                                        ppm_in[index] = tmp; // update channel value
249
                                }
250
                                else // invalid signal lenght
251
                                {
252
                                        RED_ON;
253
                                }
254
                                // demux sum signal for channels 5 to 7 to J3, J4, J5
255
                                if(index == 5) J3HIGH; else J3LOW;
256
                                if(index == 6) J4HIGH; else J4LOW;
257
                                if(CPUType != ATMEGA644P) // not used as TXD1
258
                                {
259
                                        if(index == 7) J5HIGH; else J5LOW;
260
                                }
261
                                index++; // next channel
262
                        }
263
                        else // (index >= MAX_CHANNELS)
264
                        {
265
                                RED_ON;
266
                                if(index == MAX_CHANNELS)
267
                                {
268
                                        for(i = 0; i < MAX_CHANNELS; i++)
269
                                        {
270
                                                PPM_in[i] = old_ppm_in[i]; // restore old valid values
271
                                                PPM_diff[i] = 0;
272
                                        }
273
                                        index++;
274
                                }
275
                        } // eof (index >= MAX_CHANNELS)
276
                } // eof within the PPM frame
277
        } // eof sensitive rc
278
        else // old more tolerant version
279
        {
280
                //sync gap? (3.52 ms < signal < 25.6 ms)
281
                if((signal > 1100) && (signal < 8000))
282
                {
283
                        // if a sync gap happens and there where at least 4 channels decoded before
284
                        // then the NewPpmData flag is reset indicating valid data in the PPM_in[] array.
285
                        index--; // no next channel because the sync gap was detected
286
                        RC_Channels = index;
287
                        if(index >= 4)
288
                        {
289
                                NewPpmData = 0;  // Null means NewData for the first 4 channels
290
                        }
291
                        // synchronize channel index
292
                        index = 1;
293
                }
294
                else // within the PPM frame
295
                {
296
                        if(index < MAX_CHANNELS)
297
                        {
298
                                // check for valid signal length (0.8 ms < signal < 2.1984 ms)
299
                                // signal range is from 1.0ms/3.2us = 312 to 2.0ms/3.2us = 625
300
                                if((signal > 250) && (signal < 687))
301
                                {
302
                                        // shift signal to zero symmetric range  -154 to 159
303
                                        signal -= 466; // offset of 1.4912 ms ??? (469 * 3.2µs = 1.5008 ms)
304
                                        // check for stable signal
305
                                        if(abs(signal - PPM_in[index]) < 6)
306
                                        {
307
                                                if(RC_Quality < 200) RC_Quality +=10;
308
                                                else RC_Quality = 200;
309
                                        }
310
                                        // calculate exponential history for signal
311
                                        tmp = (3 * (PPM_in[index]) + signal) / 4;
312
                                        if(tmp > signal+1) tmp--; else
313
                                        if(tmp < signal-1) tmp++;
314
                                        // calculate signal difference on good signal level
315
                                        if(RC_Quality >= 195)  PPM_diff[index] = ((tmp - PPM_in[index]) / 3) * 3; // cut off lower 3 bit for nois reduction
316
                                        else PPM_diff[index] = 0;
317
                                        PPM_in[index] = tmp; // update channel value
318
                                }
319
                                index++; // next channel
320
                                // demux sum signal for channels 5 to 7 to J3, J4, J5
321
                                if(index == 5) J3HIGH; else J3LOW;
322
                                if(index == 6) J4HIGH; else J4LOW;
323
                                if(CPUType != ATMEGA644P) // not used as TXD1
324
                                {
325
                                        if(index == 7) J5HIGH; else J5LOW;
326
                                }
327
                        } // eof (index < MAX_CHANNELS)
328
                } // eof within the PPM frame
329
        } // eof old more tolerant version
330
}
331
 
332
#else // ACT_S3D_SUMSIGNAL
333
 
334
ISR(TIMER1_CAPT_vect) // typical rate of 1 ms to 2 ms
335
{
336
        int16_t signal = 0, tmp;
337
        uint8_t i;
338
        static uint8_t index = 1;
339
        static uint16_t oldICR1 = 0;
340
 
341
 
342
        // 16bit Input Capture Register ICR1 contains the timer value TCNT1
343
        // at the time the edge was detected
344
 
345
        // calculate the time delay to the previous event time which is stored in oldICR1
346
        // calculatiing the difference of the two uint16_t and converting the result to an int16_t
347
        // implicit handles a timer overflow 65535 -> 0 the right way.
348
        signal = (uint16_t) ICR1 - oldICR1;
349
        signal /= 2;
350
        oldICR1 = ICR1;
351
        //sync gap? (3.52 ms < signal < 25.6 ms)
352
        if((signal > 1100*2) && (signal < 8000*2))
353
        {
354
                // if a sync gap happens and there where at least 4 channels decoded before
355
                // then the NewPpmData flag is reset indicating valid data in the PPM_in[] array.
356
                index--; // no next channel because the sync gap was detected
357
                RC_Channels = index;
358
                if(index >= 4)
359
                {
360
                        NewPpmData = 0;  // Null means NewData for the first 4 channels
361
                }
362
                // synchronize channel index
363
                index = 1;
364
        }
365
        else // within the PPM frame
366
        {
367
                if(index < MAX_CHANNELS)
368
                {
369
                        // check for valid signal length (0.8 ms < signal < 2.1984 ms)
370
                        // signal range is from 1.0ms/3.2us = 312 to 2.0ms/3.2us = 625
371
                        if((signal > 250) && (signal < 687*2))
372
                        {
373
                                // shift signal to zero symmetric range  -154 to 159
374
                                signal -= 962; // offset of 1.4912 ms ??? (469 * 3.2µs = 1.5008 ms)
375
                                // check for stable signal
376
                                if(abs(signal - PPM_in[index]) < 6)
377
                                {
378
                                        if(RC_Quality < 200) RC_Quality +=10;
379
                                        else RC_Quality = 200;
380
                                }
381
                                // calculate exponential history for signal
382
                                tmp = (3 * (PPM_in[index]) + signal) / 4;
383
                                if(tmp > signal+1) tmp--; else
384
                                if(tmp < signal-1) tmp++;
385
                                // calculate signal difference on good signal level
386
                                if(RC_Quality >= 195)  PPM_diff[index] = ((tmp - PPM_in[index]) / 3) * 3; // cut off lower 3 bit for nois reduction
387
                                else PPM_diff[index] = 0;
388
                                PPM_in[index] = tmp; // update channel value
389
                        }
390
                        index++; // next channel
391
                } // eof (index < MAX_CHANNELS)
392
        } // eof within the PPM frame
393
}
394
#endif
1545 LPDunwell 395
#endif
1538 killagreg 396
 
397
 
398