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