Subversion Repositories FlightCtrl

Rev

Rev 2248 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2248 - 1
/*****************************************************************************************************************************
2
* File:                 timer0.c
3
*
4
* Purpose:              setup of timer0 and timer2
5
*                               and delay functions
6
*
7
* Functions:    void Timer_Init(void);
8
*                               void TIMER2_Init(void);
9
*                               void Delay_ms(unsigned int);
10
*                               void Delay_ms_Mess(unsigned int);
11
*
12
*****************************************************************************************************************************/
13
//
14
 
15
#include "main.h"
16
 
17
volatile unsigned int CountMilliseconds = 0;
18
volatile static unsigned int tim_main;
19
volatile unsigned char UpdateMotor = 0;
20
volatile unsigned int cntKompass = 0;
21
volatile unsigned int beeptime = 0;
22
volatile unsigned char SendSPI = 0;
23
volatile unsigned char ServoActive = 0;
24
 
25
unsigned int BeepMuster = 0xFFFF;
26
 
27
volatile int16_t        ServoNickValue = 0;
28
volatile int16_t        ServoRollValue = 0;
29
 
30
 
31
//---------------------------
32
enum
33
{
34
        STOP             = 0,
35
        CK               = 1,
36
        CK8              = 2,
37
        CK64             = 3,
38
        CK256            = 4,
39
        CK1024           = 5,
40
        T0_FALLING_EDGE  = 6,
41
        T0_RISING_EDGE   = 7
42
};
43
//---------------------------
44
 
45
 
46
 
47
//********************************************************************************************************************
48
// Timer0 is running with "fast PWM" at OC0A=PORTB3 and OC0B=PORTB4 
49
// setup of Offset P_OFF1 and P_OFF2 for the air pressure sensor
50
//--------------------------------------------------------------------------------------------------------------------
51
void Timer_Init(void)
52
{
53
        tim_main = SetDelay(10);
54
 
55
        // ----------------------------------------------------------------------------------------------------------------
56
        // TCCR0B – Timer/Counter Control Register B containing: FOC0A FOC0B – – WGM02 CS02 CS01 CS0
57
        //
58
        TCCR0B = CK8;                                                                   // CK8 = 2 = clk/8 (From prescaler) one turnarround takes 0.1024ms
59
 
60
        // ----------------------------------------------------------------------------------------------------------------
61
        // TCCR0A – Timer/Counter Control Register A containing: COM0A1 COM0A0 COM0B1 COM0B0 – – WGM01 WGM00
62
        // 
63
        TCCR0A = (1<<COM0A1)|(1<<COM0B1)|3;                     // WGM02 WGM01 WGM00 = 011 = Fast PWM
64
 
65
        OCR0A =  0;                                                                             // output compare Register A for Counter 0
66
        OCR0B = 120;                                                                    // output compare Register B for Counter 0
67
 
68
        TCNT0 = (unsigned char)-TIMER_RELOAD_VALUE;     // reload       // #define TIMER_RELOAD_VALUE  250
69
 
70
        // ----------------------------------------------------------------------------------------------------------------
71
        // TIMSK0 – Timer/Counter Interrupt Mask Register containing: – – – – – OCIE0B OCIE0A TOIE0
72
        // TOIE0: Timer/Counter0 Overflow Interrupt Enable - When the TOIE0 bit is written to one, and the I-bit in the Status Register is set
73
        //
74
        TIMSK0 |= (1<<TOIE0);
75
}
76
// **************************** EOF: void Timer_Init(void) *******************************************************************
77
 
78
 
79
 
80
// *************************************************************************************************************************
81
// this funktions returns the variable "CountMilliseconds" as it will be after the waiting time hase been exipired
82
// -------------------------------------------------------------------------------------------------------------------------
83
unsigned int SetDelay(unsigned int t)
84
{
85
        return(CountMilliseconds + t + 1);
86
}
87
// *************************************************************************************************************************
88
 
89
 
90
 
91
 
92
// *************************************************************************************************************************
93
// Hier wird also die Zeitdifferenz (t-CountsMilliseconds) mit der Maske 0x08000 maskiert.
94
// 0x8000 = 1000 0000 0000 0000 setzt also bis auf das höchste Bit der 16-bit Zeitdifferenz alle Bits auf 0.
95
// Bei einer Integerzahl codiert das höchst bit das Vorzeichen. Ist also t < CountMillisconds wird, 
96
// so flippt das Vorzeichen-Bit auf 1 sonst ist es 0. Diese Eigenschaft wird hier genutzt. 
97
// Das Ganze wird dann noch um 9 Bits nach rechts geshiftet, damit die Information im unteren Byte liegt, 
98
// um beim Typecast des Rückgabewertes auf 8-Bit die Ändeurng im oberen Byte nicht abgeschnitten wird.
99
//
100
// Man könnte den Code auch so aufschreiben:
101
/*
102
char CheckDelay(unsigned int t)
103
{
104
        int diff;
105
        diff = int(t-CountMilliseconds);
106
        if (diff < 0) return 255;
107
        else return 0;
108
}
109
*/
110
//
111
char CheckDelay(unsigned int t)
112
{
113
        return(((t - CountMilliseconds) & 0x8000) >> 9);                // 0x8000 = 0b 1000 0000 0000 0000
114
}
115
// *************************************************************************************************************************
116
 
117
 
118
 
119
// *************************************************************************************************************************
120
void Delay_ms(unsigned int w)
121
{
122
        unsigned int akt;
123
 
124
        akt = SetDelay(w);
125
        while (!CheckDelay(akt));
126
}
127
// *************************************************************************************************************************
128
 
129
 
130
 
131
// *************************************************************************************************************************
132
void Delay_ms_Mess(unsigned int w)
133
{
134
        unsigned int akt;
135
        akt = SetDelay(w);
136
        while (!CheckDelay(akt)) if(AdReady) {AdReady = 0; ANALOG_ON;}          // #define ANALOG_ON ADCSRA=(1<<ADEN)|(1<<ADSC)|(0<<ADATE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADIE)
137
}
138
// *************************************************************************************************************************
139
 
140
 
141
 
142
// *************************************************************************************************************************
143
// Interrupt due to overflow of Timer0
144
// --------------------------------------
145
ISR(TIMER0_OVF_vect)                                                   
146
{
147
        static unsigned char cnt_1ms=1, cnt=0;          // one turnarround of Timer0 takes 0.1024ms at 256 steps
148
        unsigned char pieper_ein = 0;
149
 
150
        if(SendSPI) SendSPI--;                                          // 
151
 
152
        if(!cnt--)
153
        {
154
                cnt=9;                                                                  // 10 steps * 0.1024ms -> 1ms
155
                cnt_1ms++;                                                             
156
                cnt_1ms %= 2;                                                   // modulo division 
157
                if(!cnt_1ms) UpdateMotor = 1;                   // all 2 ms the motor is updated
158
                CountMilliseconds++;
159
        }
160
 
161
        if(beeptime >= 1)
162
        {
163
                beeptime--;
164
                if(beeptime & BeepMuster)
165
                {
166
                        pieper_ein = 1;
167
                }
168
                else pieper_ein = 0;
169
        }
170
        else
171
        {
172
                pieper_ein = 0;
173
                BeepMuster = 0xFFFF;
174
        }
175
 
176
        if(pieper_ein)
177
        {
178
                PORTC |= (1<<7);                                                                // beeper is connected to PORTC.7
179
        }
180
        else
181
        {
182
                PORTC &= ~(1<<7);
183
        }
184
 
185
        //------------------------------------------------------------------------------------------------------------------------
186
        // Compass works per PWM at PORTC4
187
        //------------------------------------------------------------------------------------------------------------------------
188
        if(EE_Parameter.GlobalConfig & CFG_KOMPASS_AKTIV)
189
        {
190
                if(PINC & 0x10)                                                                 // PORTC4 is up
191
                {
192
                        cntKompass++;
193
                }
194
                else                                                                                    // PORTC4 is doing down now -> check lenght of PWM pulse
195
                {
196
                        if((cntKompass) && (cntKompass < 362))          // if value is positiv and less then 362
197
                        {
198
                                cntKompass += cntKompass / 41;
199
                                if(cntKompass > 10) KompassValue = cntKompass - 10; else KompassValue = 0;              // indicated value of compass
200
                        }
201
                        KompassRichtung = ((540 + KompassValue - KompassStartwert) % 360) - 180;                        // differential direction
202
                        cntKompass = 0;                                                                                                                                         // reset PWM counter
203
                }      
204
        }
205
 
206
}
207
// *************************************************************************************************************************
208
 
209
 
210
 
211
 
212
// *************************************************************************************************************************
213
// Purpose:     Initialize Timer 2
214
//
215
// Timer 2 is used to generate the PWM at PD7 (J7) to control a camera servo for nick compensation.
216
//
217
//---------------------------------------------------------------------------------------------------------------------------------------
218
void TIMER2_Init(void)
219
{
220
        unsigned char sreg = SREG;      // copy SREG – Status Register
221
 
222
        cli();                                          // disable all interrupts before reconfiguration
223
 
224
        PORTD &= ~(1<<PORTD7);  // set PD7 = OC2A to low = Servo PPM 
225
 
226
        //------------------------------------------------------------------------------------------
227
        // DDRC – Port C Data Direction Register containing: DDC7 DDC6 DDC5 DDC4 DDC3 DDC2 DDC1 DDC0
228
        DDRC  |= (1<<DDC6);             // set PC6 as output (Reset for HEF4017)
229
        HEF4017R_ON;                            // #define HEF4017R_ON     PORTC |=  (1<<PORTC6)
230
 
231
        //------------------------------------------------------------------------------------------
232
        // TCCR2A = Timer/Counter 2 Control Register A containing: COM2A1 COM2A0 COM2B1 COM2B0 – – WGM21 WGM20
233
        // COM2A1:0: Compare Match Output A Mode. These bits control the Output Compare pin (OC2A) behavior
234
        // COM2B1:0: Compare Match Output B Mode. These bits control the Output Compare pin (OC2B) behavior
235
        TCCR2A &= ~((1<<COM2A1)|(1<<COM2A0)|(1<<COM2B1)|(1<<COM2B0));   // Normal port operation
236
        //
237
        // The counter counts from BOTTOM to TOP then restarts from BOTTOM.
238
        // TOP is defined as OCR2A asxxx, MGM22:0 = 111.
239
        TCCR2A |= (1<<WGM21)|(1<<WGM20);
240
 
241
        //------------------------------------------------------------------------------------------
242
        // TCCR2B = Timer/Counter 2 Control Register B containing: FOC2A FOC2B – – WGM22 CS22 CS21 CS20
243
        // FOC2A: Force Output Compare A. The FOC2A bit is only active when the WGM bits specify a non-PWM mode
244
        // FOC2B: Force Output Compare B. The FOC2B bit is only active when the WGM bits specify a non-PWM mode.
245
        // CS22:0: Clock Select. The three Clock Select bits select the clock source to be used by the Timer/Counter
246
        // Clock Select = 011 = SYSKLOCK/32 at 20MHz / 32 = 625 kHz
247
        // The timer increments from 0x00 to OCR2A with an update rate of 625 kHz or 0.0016 ms
248
        // 
249
        TCCR2B &= ~((1<<FOC2A)|(1<<FOC2B)|(1<<CS22));
250
        TCCR2B |= (1<<CS21)|(1<<CS20)|(1<<WGM22);
251
 
252
        //------------------------------------------------------------------------------------------
253
        // Reset the Timer/Counter 2
254
        TCNT2 = 0;
255
 
256
        OCR2A = 255;                                                    // Initialize the Output Compare Register A used for PWM generation on port PD7.
257
        TCCR2A |= (1<<COM2A1);                          // Clear OC2A on Compare Match when up-counting. Set OC2A on Compare Match when down-counting
258
 
259
        //------------------------------------------------------------------------------------------
260
        // TIMSK2 – Timer/Counter2 Interrupt Mask Register containing: – – – – – OCIE2B OCIE2A TOIE2
261
        // OCIE2B: Timer/Counter2 Output Compare Match B Interrupt Enable
262
        // TOIE2: Timer/Counter2 Overflow Interrupt Enable
263
        //
264
        TIMSK2 &= ~((1<<OCIE2B)|(1<<TOIE2));    // Output Compare Match B Interrupt is dissabled as Overflow Interrupt
265
        TIMSK2 |= (1<<OCIE2A);                                  // Timer/Counter2 Output Compare Match A Interrupt is enabled
266
 
267
        SREG = sreg;                                                    // recopy SREG – Status Register
268
}
269
// *************************************************************************************************************************
270
 
271
 
272
 
273
// *************************************************************************************************************************
274
// Timer2 controlls the  Position of Control Servos at
275
// OC2A=PORTD7
276
//---------------------------------------------------------------------------------------------------------------------------------------------
277
ISR(TIMER2_COMPA_vect)
278
{
279
        // frame len 22.5 ms = 14063 * 1.6 us
280
        // stop pulse: 0.3 ms = 188 * 1.6 us
281
        // min servo pulse: 0.6 ms =  375 * 1.6 us
282
        // max servo pulse: 2.4 ms = 1500 * 1.6 us
283
        // resolution: 1500 - 375 = 1125 steps
284
 
285
        #define IRS_RUNTIME 127
286
        #define PPM_STOPPULSE 188
287
    #define PPM_FRAMELEN (1757 * EE_Parameter.ServoNickRefresh)
288
        #define MINSERVOPULSE 375
289
        #define MAXSERVOPULSE 1500
290
        #define SERVORANGE (MAXSERVOPULSE - MINSERVOPULSE)
291
 
292
        static uint8_t  PulseOutput = 0;
293
        static uint16_t RemainingPulse = 0;
294
        static uint16_t ServoFrameTime = 0;
295
        //static uint8_t  ServoIndex = 0;
296
 
297
        #define MULTIPLYER 4
298
        static int16_t ServoNickOffset = (255 / 2) * MULTIPLYER;        // initial value near center positon
299
        //static int16_t ServoRollOffset = (255 / 2) * MULTIPLYER;      // initial value near center positon
300
 
301
        //------------------------------------------------------------------------------------------------------------------------
302
        // Nick servo state machine
303
        //------------------------------------------------------------------------------------------------------------------------
304
        if(!PulseOutput) // pulse output complete
305
        {
306
                if(TCCR2A & (1<<COM2A0))                                                                        // we had a low pulse
307
                {
308
                        TCCR2A &= ~(1<<COM2A0);                                                         // make a high pulse
309
                        RemainingPulse  = MINSERVOPULSE + SERVORANGE/2;                 // center position ~ 1.5ms
310
 
311
                        ServoNickOffset = (ServoNickOffset * 3 + (int16_t)Parameter_ServoNickControl * MULTIPLYER) / 4; // lowpass offset
312
                        ServoNickValue = ServoNickOffset;                                               // offset (Range from 0 to 255 * 3 = 765)
313
 
314
                        if(EE_Parameter.ServoCompInvert & 0x01)
315
                        {       // inverting movement of servo
316
                                ServoNickValue += (int16_t)( ( (int32_t)EE_Parameter.ServoNickComp * MULTIPLYER * (IntegralNick / 128L ) ) / (256L) );
317
                        }
318
                        else
319
                        {       // non inverting movement of servo
320
                                ServoNickValue -= (int16_t)( ( (int32_t)EE_Parameter.ServoNickComp * MULTIPLYER * (IntegralNick / 128L ) ) / (256L) );
321
                        }
322
 
323
                        // limit servo value to its parameter range definition
324
                        if(ServoNickValue < ((int16_t)EE_Parameter.ServoNickMin * MULTIPLYER) )
325
                        {
326
                                ServoNickValue = (int16_t)EE_Parameter.ServoNickMin * MULTIPLYER;
327
                        }
328
                        else if(ServoNickValue > ((int16_t)EE_Parameter.ServoNickMax * MULTIPLYER) )
329
                        {
330
                                ServoNickValue = (int16_t)EE_Parameter.ServoNickMax * MULTIPLYER;
331
                        }
332
 
333
                        RemainingPulse += ServoNickValue - (256 / 2) * MULTIPLYER; // shift ServoNickValue to center position
334
 
335
                        ServoNickValue /= MULTIPLYER;
336
 
337
                        // range servo pulse width
338
                        if(RemainingPulse > MAXSERVOPULSE )                     RemainingPulse = MAXSERVOPULSE; // upper servo pulse limit
339
                        else if(RemainingPulse < MINSERVOPULSE )        RemainingPulse = MINSERVOPULSE; // lower servo pulse limit
340
 
341
                        ServoFrameTime = RemainingPulse;                                        // accumulate time for correct update rate
342
                }
343
                else                                                                                                    // we had a high pulse
344
                {
345
                        TCCR2A |= (1<<COM2A0);                                                  // make a low pulse
346
                        RemainingPulse = PPM_FRAMELEN - ServoFrameTime;
347
                }
348
                PulseOutput = 1;                                                                                // set pulse output active
349
        }
350
 
351
        if(RemainingPulse > (255 + IRS_RUNTIME))                                        // General pulse output generator
352
        {
353
                OCR2A = 255;
354
                RemainingPulse -= 255;
355
        }
356
        else
357
        {
358
                if(RemainingPulse > 255)                                                                // this is the 2nd last part
359
                {
360
                        if((RemainingPulse - 255) < IRS_RUNTIME)
361
                        {
362
                                OCR2A = 255 - IRS_RUNTIME;
363
                                RemainingPulse -= 255 - IRS_RUNTIME;
364
                        }
365
                        else                                                                                            // last part > ISR_RUNTIME
366
                        {
367
                                OCR2A = 255;
368
                                RemainingPulse -= 255;
369
                        }
370
                }
371
                else                                                                                                    // this is the last part
372
                {
373
                        OCR2A = RemainingPulse;
374
                        RemainingPulse = 0;
375
                        PulseOutput = 0;                                                                        // trigger to stop pulse
376
                }
377
 
378
        } // EOF: general pulse output generator        
379
}
380
// *** EOF: ISR(TIMER2_COMPA_vect) ***************************************************************************************