Subversion Repositories FlightCtrl

Rev

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