Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ingob 1
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2
// + Copyright (c) 04.2007 Holger Buss
1180 killagreg 3
// + Nur für den privaten Gebrauch
1 ingob 4
// + www.MikroKopter.com
5
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1180 killagreg 6
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
7
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
8
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt
9
// + bzgl. der Nutzungsbedingungen aufzunehmen.
10
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
11
// + Verkauf von Luftbildaufnahmen, usw.
12
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
14
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
15
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
17
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
18
// + eindeutig als Ursprung verlinkt werden
19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
21
// + Benutzung auf eigene Gefahr
22
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
23
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
25
// + mit unserer Zustimmung zulässig
26
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
28
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
29
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
30
// + this list of conditions and the following disclaimer.
31
// +   * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
32
// +     from this software without specific prior written permission.
33
// +   * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
34
// +     for non-commercial use (directly or indirectly)
35
// +     Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
36
// +     with our written permission
37
// +   * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
38
// +     clearly linked as origin
39
// +   * porting to systems other than hardware from www.mikrokopter.de is not allowed
40
// +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
41
// +  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
// +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43
// +  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
44
// +  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
45
// +  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
46
// +  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47
// +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN// +  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48
// +  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49
// +  POSSIBILITY OF SUCH DAMAGE.
50
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
886 killagreg 51
#include <stdlib.h>
52
#include <avr/io.h>
53
#include <avr/interrupt.h>
54
 
1 ingob 55
#include "rc.h"
56
#include "main.h"
57
 
886 killagreg 58
volatile int16_t PPM_in[15]; //PPM24 supports 12 channels per frame
59
volatile int16_t PPM_diff[15];
60
volatile uint8_t NewPpmData = 1;
61
volatile int16_t RC_Quality = 0;
1 ingob 62
 
886 killagreg 63
volatile uint8_t NewRCFrames = 0;
64
 
65
 
66
/***************************************************************/
67
/*  16bit timer 1 is used to decode the PPM-Signal            */
68
/***************************************************************/
69
void RC_Init (void)
1 ingob 70
{
886 killagreg 71
        uint8_t sreg = SREG;
1 ingob 72
 
886 killagreg 73
        // disable all interrupts before reconfiguration
74
        cli();
75
 
76
        // PPM-signal is connected to the Input Capture Pin (PD6) of timer 1
77
        DDRD &= ~(1<<DDD6);
78
        PORTD |= (1<<PORTD6);
79
 
80
        // Channel 5,6,7 is decoded to servo signals at pin PD5 (J3), PD4(J4), PD3(J5)
81
        // set as output
82
        DDRD |= (1<<DDD5)|(1<<DDD4);
83
        // low level
84
        PORTD &= ~((1<<PORTD5)|(1<<PORTD4));
85
 
1180 killagreg 86
        // PD3 can't be used if 2nd UART is activated
886 killagreg 87
        // because TXD1 is at that port
1180 killagreg 88
        if(CPUType != ATMEGA644P)
886 killagreg 89
        {
90
                DDRD |= (1<<PORTD3);
91
                PORTD &= ~(1<<PORTD3);
92
        }
93
 
94
        // Timer/Counter1 Control Register A, B, C
95
 
96
        // Normal Mode (bits: WGM13=0, WGM12=0, WGM11=0, WGM10=0)
97
        // Compare output pin A & B is disabled (bits: COM1A1=0, COM1A0=0, COM1B1=0, COM1B0=0)
98
        // Set clock source to SYSCLK/64 (bit: CS12=0, CS11=1, CS10=1)
99
        // Enable input capture noise cancler (bit: ICNC1=1)
100
        // Trigger on positive edge of the input capture pin (bit: ICES1=1),
101
        // Therefore the counter incremets at a clock of 20 MHz/64 = 312.5 kHz or 3.2µs
102
    // The longest period is 0xFFFF / 312.5 kHz = 0.209712 s.
103
        TCCR1A &= ~((1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|(1<<WGM11)|(1<<WGM10));
104
        TCCR1B &= ~((1<<WGM13)|(1<<WGM12)|(1<<CS12));
105
        TCCR1B |= (1<<CS11)|(1<<CS10)|(1<<ICES1)|(1<<ICNC1);
106
        TCCR1C &= ~((1<<FOC1A)|(1<<FOC1B));
107
 
108
        // Timer/Counter1 Interrupt Mask Register
109
 
110
        // Enable Input Capture Interrupt (bit: ICIE1=1)
111
        // Disable Output Compare A & B Match Interrupts (bit: OCIE1B=0, OICIE1A=0)
112
        // Enable Overflow Interrupt (bit: TOIE1=0)
113
        TIMSK1 &= ~((1<<OCIE1B)|(1<<OCIE1A));
114
    TIMSK1 |= (1<<ICIE1)|(1<<TOIE1);
115
 
116
    RC_Quality = 0;
117
 
118
    SREG = sreg;
1 ingob 119
}
120
 
121
 
886 killagreg 122
// happens every 0.209712 s.
123
// check for at least one new frame per timer overflow (timeout)
124
ISR(TIMER1_OVF_vect)
1 ingob 125
{
886 killagreg 126
        if (NewRCFrames == 0) RC_Quality -= RC_Quality/8;
127
        NewRCFrames = 0;
128
}
129
 
130
 
131
/********************************************************************/
132
/*         Every time a positive edge is detected at PD6            */
133
/********************************************************************/
134
/*                               t-Frame
135
       <----------------------------------------------------------------------->
136
         ____   ______   _____   ________                ______    sync gap      ____
137
        |    | |      | |     | |        |              |      |                |
138
        |    | |      | |     | |        |              |      |                |
139
     ___|    |_|      |_|     |_|        |_.............|      |________________|
140
        <-----><-------><------><-------->              <------>                <---
141
          t0       t1      t2       t4                     tn                     t0
142
 
143
The PPM-Frame length is 22.5 ms.
144
Channel high pulse width range is 0.7 ms to 1.7 ms completed by an 0.3 ms low pulse.
145
The mininimum time delay of two events coding a channel is ( 0.7 + 0.3) ms = 1 ms.
146
The maximum time delay of two events coding a chanel is ( 1.7 + 0.3) ms = 2 ms.
147
The minimum duration of all channels at minimum value is  8 * 1 ms = 8 ms.
148
The maximum duration of all channels at maximum value is  8 * 2 ms = 16 ms.
149
The remaining time of (22.5 - 8 ms) ms = 14.5 ms  to (22.5 - 16 ms) ms = 6.5 ms is
150
the syncronization gap.
151
*/
152
ISR(TIMER1_CAPT_vect) // typical rate of 1 ms to 2 ms
153
{
154
    int16_t signal = 0, tmp;
155
        static int16_t index;
156
        static uint16_t oldICR1 = 0;
157
 
158
        // 16bit Input Capture Register ICR1 contains the timer value TCNT1
159
        // at the time the edge was detected
160
 
161
        // calculate the time delay to the previous event time which is stored in oldICR1
162
        // calculatiing the difference of the two uint16_t and converting the result to an int16_t
163
        // implicit handles a timer overflow 65535 -> 0 the right way.
164
        signal = (uint16_t) ICR1 - oldICR1;
165
        oldICR1 = ICR1;
166
 
167
    //sync gap? (3.52 ms < signal < 25.6 ms)
168
        if((signal > 1100) && (signal < 8000))
169
        {
170
                // if a sync gap happens and there where at least 4 channels decoded before
171
                // then the NewPpmData flag is reset indicating valid data in the PPM_in[] array.
172
                if(index >= 4)
173
                {
174
                        NewPpmData = 0;  // Null means NewData for the first 4 channels
175
                        NewRCFrames++;
176
                }
177
                // synchronize channel index
178
                index = 1;
179
        }
180
        else // within the PPM frame
181
    {
182
        if(index < 14) // PPM24 supports 12 channels
1 ingob 183
        {
886 killagreg 184
                        // check for valid signal length (0.8 ms < signal < 2.1984 ms)
185
                        // signal range is from 1.0ms/3.2us = 312 to 2.0ms/3.2us = 625
186
            if((signal > 250) && (signal < 687))
1 ingob 187
            {
886 killagreg 188
                                // shift signal to zero symmetric range  -154 to 159
189
                signal -= 466; // offset of 1.4912 ms ??? (469 * 3.2µs = 1.5008 ms)
190
                // check for stable signal
191
                if(abs(signal-PPM_in[index]) < 6)
192
                {
193
                                        if(RC_Quality < 200) RC_Quality +=10;
1180 killagreg 194
                                        else RC_Quality = 200;
886 killagreg 195
                                }
196
                                // calculate exponential history for signal
197
                tmp = (3 * (PPM_in[index]) + signal) / 4;
604 hbuss 198
                if(tmp > signal+1) tmp--; else
886 killagreg 199
                if(tmp < signal-1) tmp++;
200
                // calculate signal difference on good signal level
201
                if(RC_Quality >= 195)  PPM_diff[index] = ((tmp - PPM_in[index]) / 3) * 3; // cut off lower 3 bit for nois reduction
604 hbuss 202
                else PPM_diff[index] = 0;
886 killagreg 203
                PPM_in[index] = tmp; // update channel value
204
            }
205
            index++; // next channel
206
            // demux sum signal for channels 5 to 7 to J3, J4, J5
1180 killagreg 207
                if(index == 5) J3HIGH; else J3LOW;
208
                if(index == 6) J4HIGH; else J3LOW;
209
                if(CPUType != ATMEGA644P) // not used as TXD1
886 killagreg 210
                {
1180 killagreg 211
                                if(index == 7) J5HIGH; else J5LOW;
886 killagreg 212
                }
1 ingob 213
        }
214
        }
886 killagreg 215
        if(RC_Quality) RC_Quality--;
1 ingob 216
}
217
 
218
 
219
 
220
 
221