Subversion Repositories FlightCtrl

Rev

Rev 802 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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