Subversion Repositories FlightCtrl

Rev

Details | 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
 
832 killagreg 23
volatile uint8_t NewRCFrames = 0;
800 killagreg 24
 
832 killagreg 25
 
687 killagreg 26
/***************************************************************/
688 killagreg 27
/*  16bit timer 1 is used to decode the PPM-Signal            */
687 killagreg 28
/***************************************************************/
712 killagreg 29
void RC_Init (void)
1 ingob 30
{
688 killagreg 31
        uint8_t sreg = SREG;
1 ingob 32
 
688 killagreg 33
        // disable all interrupts before reconfiguration
34
        cli();
685 killagreg 35
 
688 killagreg 36
        // PPM-signal is connected to the Input Capture Pin (PD6) of timer 1
37
        DDRD &= ~(1<<DDD6);
38
        PORTD |= (1<<PORTD6);
39
 
689 killagreg 40
        // Channel 5,6,7 is decoded to servo signals at pin PD5 (J3), PD4(J4), PD3(J5)
41
        // set as output
756 killagreg 42
        DDRD |= (1<<DDD5)|(1<<DDD4);
689 killagreg 43
        // low level
756 killagreg 44
        PORTD &= ~((1<<PORTD5)|(1<<PORTD4));
689 killagreg 45
 
732 killagreg 46
        // PD3 can't be used in FC 1.1 if 2nd UART is activated
766 killagreg 47
        // because TXD1 is at that port
732 killagreg 48
        if(BoardRelease == 10)
49
        {
50
                DDRD |= (1<<PORTD3);
51
                PORTD &= ~(1<<PORTD3);
52
        }
53
 
688 killagreg 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)
802 killagreg 72
        // Enable Overflow Interrupt (bit: TOIE1=0)
73
        TIMSK1 &= ~((1<<OCIE1B)|(1<<OCIE1A));
74
    TIMSK1 |= (1<<ICIE1)|(1<<TOIE1);
688 killagreg 75
 
800 killagreg 76
    RC_Quality = 0;
77
 
688 killagreg 78
    SREG = sreg;
1 ingob 79
}
80
 
81
 
802 killagreg 82
// happens every 0.209712 s.
832 killagreg 83
// check for at least one new frame per timer overflow (timeout)
802 killagreg 84
ISR(TIMER1_OVF_vect)
85
{
832 killagreg 86
        if (NewRCFrames == 0) RC_Quality /= 2;
87
        NewRCFrames = 0;
802 killagreg 88
}
89
 
90
 
688 killagreg 91
/********************************************************************/
92
/*         Every time a positive edge is detected at PD6            */
93
/********************************************************************/
761 killagreg 94
/*                               t-Frame
95
       <----------------------------------------------------------------------->
96
         ____   ______   _____   ________                ______    sync gap      ____
97
        |    | |      | |     | |        |              |      |                |
98
        |    | |      | |     | |        |              |      |                |
99
     ___|    |_|      |_|     |_|        |_.............|      |________________|
100
        <-----><-------><------><-------->              <------>                <---
101
          t0       t1      t2       t4                     tn                     t0
102
 
688 killagreg 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
1 ingob 113
{
688 killagreg 114
    int16_t signal = 0, tmp;
115
        static int16_t index;
802 killagreg 116
        static uint16_t oldICR1 = 0;
685 killagreg 117
 
688 killagreg 118
        // 16bit Input Capture Register ICR1 contains the timer value TCNT1
119
        // at the time the edge was detected
685 killagreg 120
 
688 killagreg 121
        // calculate the time delay to the previous event time which is stored in oldICR1
800 killagreg 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.
688 killagreg 124
        signal = (uint16_t) ICR1 - oldICR1;
125
        oldICR1 = ICR1;
126
 
127
    //sync gap? (3.52 ms < signal < 25.6 ms)
685 killagreg 128
        if((signal > 1100) && (signal < 8000))
688 killagreg 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.
832 killagreg 132
                if(index >= 4)
133
                {
134
                        NewPpmData = 0;  // Null means NewData for the first 4 channels
135
                        NewRCFrames++;
136
                }
688 killagreg 137
                // synchronize channel index
138
                index = 1;
139
        }
140
        else // within the PPM frame
802 killagreg 141
    {
761 killagreg 142
        if(index < 14) // PPM24 supports 12 channels
1 ingob 143
        {
688 killagreg 144
                        // check for valid signal length (0.8 ms < signal < 2.1984 ms)
711 killagreg 145
                        // signal range is from 1.0ms/3.2us = 312 to 2.0ms/3.2us = 625
688 killagreg 146
            if((signal > 250) && (signal < 687))
1 ingob 147
            {
711 killagreg 148
                                // shift signal to zero symmetric range  -154 to 159
688 killagreg 149
                signal -= 466; // offset of 1.4912 ms ??? (469 * 3.2µs = 1.5008 ms)
150
                // check for stable signal
806 killagreg 151
                if(abs(signal-PPM_in[index]) < 6)
152
                {
153
                                        if(RC_Quality < 200) RC_Quality +=10;
801 killagreg 154
                                }
688 killagreg 155
                                // calculate exponential history for signal
685 killagreg 156
                tmp = (3 * (PPM_in[index]) + signal) / 4;
604 hbuss 157
                if(tmp > signal+1) tmp--; else
685 killagreg 158
                if(tmp < signal-1) tmp++;
688 killagreg 159
                // calculate signal difference on good signal level
806 killagreg 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;
688 killagreg 162
                PPM_in[index] = tmp; // update channel value
163
            }
164
            index++; // next channel
689 killagreg 165
            // demux sum signal for channels 5 to 7 to J3, J4, J5
166
                if(index == 5) PORTD |= (1<<PORTD5); else PORTD &= ~(1<<PORTD5);
757 killagreg 167
                if(index == 6) PORTD |= (1<<PORTD4); else PORTD &= ~(1<<PORTD4);
732 killagreg 168
                if(BoardRelease == 10)
169
                {
170
                                if(index == 7) PORTD |= (1<<PORTD3); else PORTD &= ~(1<<PORTD3);
171
                }
1 ingob 172
        }
173
        }
806 killagreg 174
        if(RC_Quality) RC_Quality--;
1 ingob 175
}
176
 
177
 
178
 
179
 
180