Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ingob 1
/*#######################################################################################
886 killagreg 2
Decodieren eines RC Summen Signals
1 ingob 3
#######################################################################################*/
4
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5
// + Copyright (c) 04.2007 Holger Buss
6
// + only for non-profit use
7
// + www.MikroKopter.com
8
// + see the File "License.txt" for further Informations
9
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10
 
886 killagreg 11
#include <stdlib.h>
12
#include <avr/io.h>
13
#include <avr/interrupt.h>
14
 
1 ingob 15
#include "rc.h"
16
#include "main.h"
17
 
886 killagreg 18
volatile int16_t PPM_in[15]; //PPM24 supports 12 channels per frame
19
volatile int16_t PPM_diff[15];
20
volatile uint8_t NewPpmData = 1;
21
volatile int16_t RC_Quality = 0;
1 ingob 22
 
886 killagreg 23
volatile uint8_t NewRCFrames = 0;
24
 
25
 
26
/***************************************************************/
27
/*  16bit timer 1 is used to decode the PPM-Signal            */
28
/***************************************************************/
29
void RC_Init (void)
1 ingob 30
{
886 killagreg 31
        uint8_t sreg = SREG;
1 ingob 32
 
886 killagreg 33
        // disable all interrupts before reconfiguration
34
        cli();
35
 
36
        // PPM-signal is connected to the Input Capture Pin (PD6) of timer 1
37
        DDRD &= ~(1<<DDD6);
38
        PORTD |= (1<<PORTD6);
39
 
40
        // Channel 5,6,7 is decoded to servo signals at pin PD5 (J3), PD4(J4), PD3(J5)
41
        // set as output
42
        DDRD |= (1<<DDD5)|(1<<DDD4);
43
        // low level
44
        PORTD &= ~((1<<PORTD5)|(1<<PORTD4));
45
 
46
        // PD3 can't be used in FC 1.1 if 2nd UART is activated
47
        // because TXD1 is at that port
48
        if(BoardRelease == 10)
49
        {
50
                DDRD |= (1<<PORTD3);
51
                PORTD &= ~(1<<PORTD3);
52
        }
53
 
54
        // Timer/Counter1 Control Register A, B, C
55
 
56
        // Normal Mode (bits: WGM13=0, WGM12=0, WGM11=0, WGM10=0)
57
        // Compare output pin A & B is disabled (bits: COM1A1=0, COM1A0=0, COM1B1=0, COM1B0=0)
58
        // Set clock source to SYSCLK/64 (bit: CS12=0, CS11=1, CS10=1)
59
        // Enable input capture noise cancler (bit: ICNC1=1)
60
        // Trigger on positive edge of the input capture pin (bit: ICES1=1),
61
        // Therefore the counter incremets at a clock of 20 MHz/64 = 312.5 kHz or 3.2µs
62
    // The longest period is 0xFFFF / 312.5 kHz = 0.209712 s.
63
        TCCR1A &= ~((1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|(1<<WGM11)|(1<<WGM10));
64
        TCCR1B &= ~((1<<WGM13)|(1<<WGM12)|(1<<CS12));
65
        TCCR1B |= (1<<CS11)|(1<<CS10)|(1<<ICES1)|(1<<ICNC1);
66
        TCCR1C &= ~((1<<FOC1A)|(1<<FOC1B));
67
 
68
        // Timer/Counter1 Interrupt Mask Register
69
 
70
        // Enable Input Capture Interrupt (bit: ICIE1=1)
71
        // Disable Output Compare A & B Match Interrupts (bit: OCIE1B=0, OICIE1A=0)
72
        // Enable Overflow Interrupt (bit: TOIE1=0)
73
        TIMSK1 &= ~((1<<OCIE1B)|(1<<OCIE1A));
74
    TIMSK1 |= (1<<ICIE1)|(1<<TOIE1);
75
 
76
    RC_Quality = 0;
77
 
78
    SREG = sreg;
1 ingob 79
}
80
 
81
 
886 killagreg 82
// happens every 0.209712 s.
83
// check for at least one new frame per timer overflow (timeout)
84
ISR(TIMER1_OVF_vect)
1 ingob 85
{
886 killagreg 86
        if (NewRCFrames == 0) RC_Quality -= RC_Quality/8;
87
        NewRCFrames = 0;
88
}
89
 
90
 
91
/********************************************************************/
92
/*         Every time a positive edge is detected at PD6            */
93
/********************************************************************/
94
/*                               t-Frame
95
       <----------------------------------------------------------------------->
96
         ____   ______   _____   ________                ______    sync gap      ____
97
        |    | |      | |     | |        |              |      |                |
98
        |    | |      | |     | |        |              |      |                |
99
     ___|    |_|      |_|     |_|        |_.............|      |________________|
100
        <-----><-------><------><-------->              <------>                <---
101
          t0       t1      t2       t4                     tn                     t0
102
 
103
The PPM-Frame length is 22.5 ms.
104
Channel high pulse width range is 0.7 ms to 1.7 ms completed by an 0.3 ms low pulse.
105
The mininimum time delay of two events coding a channel is ( 0.7 + 0.3) ms = 1 ms.
106
The maximum time delay of two events coding a chanel is ( 1.7 + 0.3) ms = 2 ms.
107
The minimum duration of all channels at minimum value is  8 * 1 ms = 8 ms.
108
The maximum duration of all channels at maximum value is  8 * 2 ms = 16 ms.
109
The remaining time of (22.5 - 8 ms) ms = 14.5 ms  to (22.5 - 16 ms) ms = 6.5 ms is
110
the syncronization gap.
111
*/
112
ISR(TIMER1_CAPT_vect) // typical rate of 1 ms to 2 ms
113
{
114
    int16_t signal = 0, tmp;
115
        static int16_t index;
116
        static uint16_t oldICR1 = 0;
117
 
118
        // 16bit Input Capture Register ICR1 contains the timer value TCNT1
119
        // at the time the edge was detected
120
 
121
        // calculate the time delay to the previous event time which is stored in oldICR1
122
        // calculatiing the difference of the two uint16_t and converting the result to an int16_t
123
        // implicit handles a timer overflow 65535 -> 0 the right way.
124
        signal = (uint16_t) ICR1 - oldICR1;
125
        oldICR1 = ICR1;
126
 
127
    //sync gap? (3.52 ms < signal < 25.6 ms)
128
        if((signal > 1100) && (signal < 8000))
129
        {
130
                // if a sync gap happens and there where at least 4 channels decoded before
131
                // then the NewPpmData flag is reset indicating valid data in the PPM_in[] array.
132
                if(index >= 4)
133
                {
134
                        NewPpmData = 0;  // Null means NewData for the first 4 channels
135
                        NewRCFrames++;
136
                }
137
                // synchronize channel index
138
                index = 1;
139
        }
140
        else // within the PPM frame
141
    {
142
        if(index < 14) // PPM24 supports 12 channels
1 ingob 143
        {
886 killagreg 144
                        // check for valid signal length (0.8 ms < signal < 2.1984 ms)
145
                        // signal range is from 1.0ms/3.2us = 312 to 2.0ms/3.2us = 625
146
            if((signal > 250) && (signal < 687))
1 ingob 147
            {
886 killagreg 148
                                // shift signal to zero symmetric range  -154 to 159
149
                signal -= 466; // offset of 1.4912 ms ??? (469 * 3.2µs = 1.5008 ms)
150
                // check for stable signal
151
                if(abs(signal-PPM_in[index]) < 6)
152
                {
153
                                        if(RC_Quality < 200) RC_Quality +=10;
154
                                }
155
                                // calculate exponential history for signal
156
                tmp = (3 * (PPM_in[index]) + signal) / 4;
604 hbuss 157
                if(tmp > signal+1) tmp--; else
886 killagreg 158
                if(tmp < signal-1) tmp++;
159
                // calculate signal difference on good signal level
160
                if(RC_Quality >= 195)  PPM_diff[index] = ((tmp - PPM_in[index]) / 3) * 3; // cut off lower 3 bit for nois reduction
604 hbuss 161
                else PPM_diff[index] = 0;
886 killagreg 162
                PPM_in[index] = tmp; // update channel value
163
            }
164
            index++; // next channel
165
            // demux sum signal for channels 5 to 7 to J3, J4, J5
166
                if(index == 5) PORTD |= (1<<PORTD5); else PORTD &= ~(1<<PORTD5);
167
                if(index == 6) PORTD |= (1<<PORTD4); else PORTD &= ~(1<<PORTD4);
168
                if(BoardRelease == 10)
169
                {
170
                                if(index == 7) PORTD |= (1<<PORTD3); else PORTD &= ~(1<<PORTD3);
171
                }
1 ingob 172
        }
173
        }
886 killagreg 174
        if(RC_Quality) RC_Quality--;
1 ingob 175
}
176
 
177
 
178
 
179
 
180