Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1755 - 1
/******************************************************************************************************************
2
V0.80g-Arthur-P1 20100922
3
------------------------------------------------------------------------------------------------------------------
4
Version includes only support for external HEF4017 for FC1.x hardware, NOT for Twi2Ppm converters for ESCs.
5
 
6
20100917: Transferred changes to v0.80g-Arthur-P.
7
Arthur P. Modified to use several parameters for servo control:
8
User_Parameter4:
9
User_Parameter5:
10
User_Parameter6:
11
User_Parameter7:
12
User_Parameter8: Use external HEF4017 if bit 8 is set (>127). The remaining 7 bits are used
13
                 for the shutter cycle counter: the value is multiplied by 5 programmatically,
14
                                 resulting in steps of approx. 0.1sec. Minimum value to start using the
15
                                 interval timer is 10 (approx. 1 sec, or countervalue of 50). Note that this
16
                                 was originally done through user para 6.
17
******************************************************************************************************************/
18
 
19
#include "main.h"
20
 
21
 
22
volatile unsigned int CountMilliseconds = 0;
23
volatile static unsigned int tim_main;
24
volatile unsigned char UpdateMotor = 0;
25
volatile unsigned int cntKompass = 0;
26
volatile unsigned int beeptime = 0;
27
volatile unsigned char SendSPI = 0, ServoActive = 0;
28
 
29
unsigned int BeepMuster = 0xffff;
30
 
31
volatile int16_t        ServoNickValue = 0;
32
volatile int16_t        ServoRollValue = 0;
33
 
34
 
35
/******************************************************************************************************************
36
Arthur P: Added two variables for control of the shutter servo cycle.
37
091114 Inserted same changes into v.0.76g code.
38
091114 Inactivated the following two lines as the shutter interval funtion is not
39
used at the moment.
40
20100804 Reactivated to be able to choose slower shutter rate than normal for
41
Panasonic FX150 in continuous mode.
42
******************************************************************************************************************/
43
 
44
volatile static unsigned int CameraShutterCycleCounter = 0;
45
volatile static unsigned int CameraShutterCycle = 0;
46
volatile static unsigned int CameraShutterCycleOnCount = 20;  // Leave the shutter on for at least
47
                                                                                                                          // 20 cycles or approx. 0.2 seconds.
48
 
49
enum {
50
  STOP             = 0,
51
  CK               = 1,
52
  CK8              = 2,
53
  CK64             = 3,
54
  CK256            = 4,
55
  CK1024           = 5,
56
  T0_FALLING_EDGE  = 6,
57
  T0_RISING_EDGE   = 7
58
};
59
 
60
 
61
ISR(TIMER0_OVF_vect)    // 9,7kHz
62
{
63
   static unsigned char cnt_1ms = 1,cnt = 0, compass_active = 0;
64
   unsigned char pieper_ein = 0;
65
   if(SendSPI) SendSPI--;
66
   if(SpektrumTimer) SpektrumTimer--;
67
   if(!cnt--)
68
    {
69
     cnt = 9;
70
     CountMilliseconds++;
71
     cnt_1ms++;
72
     cnt_1ms %= 2;
73
 
74
     if(!cnt_1ms) UpdateMotor = 1;
75
         if(!(PINC & 0x10)) compass_active = 1;
76
 
77
     if(beeptime)
78
        {
79
        if(beeptime > 10) beeptime -= 10; else beeptime = 0;
80
        if(beeptime & BeepMuster)
81
         {
82
          pieper_ein = 1;
83
         }
84
         else pieper_ein = 0;
85
        }
86
     else
87
      {
88
       pieper_ein = 0;
89
       BeepMuster = 0xffff;
90
      }
91
     if(pieper_ein)
92
        {
93
          if(PlatinenVersion == 10) PORTD |= (1<<2); // Speaker an PORTD.2
94
          else                      PORTC |= (1<<7); // Speaker an PORTC.7
95
        }
96
     else
97
        {
98
         if(PlatinenVersion == 10) PORTD &= ~(1<<2);
99
         else                      PORTC &= ~(1<<7);
100
        }
101
        }
102
 if(compass_active && !NaviDataOkay && EE_Parameter.GlobalConfig & CFG_KOMPASS_AKTIV)
103
 {
104
  if(PINC & 0x10)
105
   {
106
        if(++cntKompass > 1000) compass_active = 0;
107
   }
108
  else
109
   {
110
    if((cntKompass) && (cntKompass < 362))
111
    {
112
     cntKompass += cntKompass / 41;
113
     if(cntKompass > 10) KompassValue = cntKompass - 10; else KompassValue = 0;
114
     KompassRichtung = ((540 + KompassValue - KompassStartwert) % 360) - 180;
115
    }
116
    cntKompass = 0;
117
   }
118
 }
119
}
120
 
121
 
122
// -----------------------------------------------------------------------
123
unsigned int SetDelay (unsigned int t)
124
{
125
//  TIMSK0 &= ~_BV(TOIE0);
126
  return(CountMilliseconds + t + 1);
127
//  TIMSK0 |= _BV(TOIE0);
128
}
129
 
130
// -----------------------------------------------------------------------
131
char CheckDelay(unsigned int t)
132
{
133
//  TIMSK0 &= ~_BV(TOIE0);
134
  return(((t - CountMilliseconds) & 0x8000) >> 9);
135
//  TIMSK0 |= _BV(TOIE0);
136
}
137
 
138
// -----------------------------------------------------------------------
139
void Delay_ms(unsigned int w)
140
{
141
 unsigned int akt;
142
 akt = SetDelay(w);
143
 while (!CheckDelay(akt));
144
}
145
 
146
void Delay_ms_Mess(unsigned int w)
147
{
148
 unsigned int akt;
149
 akt = SetDelay(w);
150
 while (!CheckDelay(akt)) if(AdReady) {AdReady = 0; ANALOG_ON;}
151
}
152
 
153
/*****************************************************/
154
/*              Initialize Timer 2                   */
155
/*****************************************************/
156
// The timer 2 is used to generate the PWM at PD7 (J7)
157
// to control a camera servo for nick compensation.
158
void TIMER2_Init(void)
159
{
160
        uint8_t sreg = SREG;
161
 
162
/******************************************************************************************************************
163
Arthur P: Added initialization of the CameraShutterCycle value here as this routine is only
164
called once. This retains all code changes in timer0.c. If (parameter 8 & 127) > 0 then the user
165
has set a value for the cycle. CameraShuytterCycle == 5x (Para8 & 127) to get approx 0.1sec increments.
166
090807: Arthur P.: Removed the shutter cycle parts as they may be impacting timing loops.
167
20100804 Arthur P.: Reactivate shutter cycle counters. Modified to use the lower 7 bits of
168
user parameter 8 (bit 8 is used for enabling the external HEF4017).
169
CameraShutterCycle = Parameter_UserParam6;
170
******************************************************************************************************************/
171
        CameraShutterCycle = 5 *  (Parameter_UserParam8 & 127);
172
 
173
 
174
 
175
        // disable all interrupts before reconfiguration
176
        cli();
177
 
178
        PORTD &= ~(1<<PORTD7);  // set PD7 to low
179
 
180
        DDRC  |= (1<<DDC6);     // set PC6 as output (Reset for HEF4017)
181
    HEF4017R_ON;
182
        // Timer/Counter 2 Control Register A
183
 
184
        // Timer Mode is FastPWM with timer reload at OCR2A (Bits: WGM22 = 1, WGM21 = 1, WGM20 = 1)
185
    // PD7: Normal port operation, OC2A disconnected, (Bits: COM2A1 = 0, COM2A0 = 0)
186
    // PD6: Normal port operation, OC2B disconnected, (Bits: COM2B1 = 0, COM2B0 = 0)
187
        TCCR2A &= ~((1<<COM2A1)|(1<<COM2A0)|(1<<COM2B1)|(1<<COM2B0));
188
    TCCR2A |= (1<<WGM21)|(1<<WGM20);
189
 
190
    // Timer/Counter 2 Control Register B
191
 
192
        // Set clock divider for timer 2 to SYSKLOCK/32 = 20MHz / 32 = 625 kHz
193
        // The timer increments from 0x00 to 0xFF with an update rate of 625 kHz or 1.6 us
194
        // hence the timer overflow interrupt frequency is 625 kHz / 256 = 2.44 kHz or 0.4096 ms
195
 
196
    // divider 32 (Bits: CS022 = 0, CS21 = 1, CS20 = 1)
197
        TCCR2B &= ~((1<<FOC2A)|(1<<FOC2B)|(1<<CS22));
198
    TCCR2B |= (1<<CS21)|(1<<CS20)|(1<<WGM22);
199
 
200
        // Initialize the Timer/Counter 2 Register
201
    TCNT2 = 0;
202
 
203
        // Initialize the Output Compare Register A used for PWM generation on port PD7.
204
        OCR2A = 255;
205
        TCCR2A |= (1<<COM2A1); // set or clear at compare match depends on value of COM2A0
206
 
207
        // Timer/Counter 2 Interrupt Mask Register
208
        // Enable timer output compare match A Interrupt only
209
        TIMSK2 &= ~((1<<OCIE2B)|(1<<TOIE2));
210
        TIMSK2 |= (1<<OCIE2A);
211
 
212
    SREG = sreg;
213
}
214
 
215
//----------------------------
216
void Timer_Init(void)
217
{
218
    tim_main = SetDelay(10);
219
    TCCR0B = CK8;
220
    TCCR0A = (1<<COM0A1)|(1<<COM0B1)|3;//fast PWM
221
    OCR0A =  0;
222
    OCR0B = 180;
223
    TCNT0 = (unsigned char)-TIMER_RELOAD_VALUE;  // reload
224
    //OCR1  = 0x00;
225
    TIMSK0 |= _BV(TOIE0);
226
}
227
 
228
 
229
/*****************************************************/
230
/*              Control Servo Position               */
231
/*****************************************************/
232
 
233
ISR(TIMER2_COMPA_vect)
234
{
235
        // frame len 22.5 ms = 14063 * 1.6 us
236
        // stop pulse: 0.3 ms = 188 * 1.6 us
237
        // min servo pulse: 0.6 ms =  375 * 1.6 us
238
        // max servo pulse: 2.4 ms = 1500 * 1.6 us
239
        // resolution: 1500 - 375 = 1125 steps
240
 
241
        #define IRS_RUNTIME 127
242
        #define PPM_STOPPULSE 188
243
//      #define PPM_FRAMELEN (14063
244
    #define PPM_FRAMELEN (1757 * EE_Parameter.ServoNickRefresh)
245
        #define MINSERVOPULSE 375
246
        #define MAXSERVOPULSE 1500
247
        #define SERVORANGE (MAXSERVOPULSE - MINSERVOPULSE)
248
 
249
        static uint8_t  PulseOutput = 0;
250
        static uint16_t RemainingPulse = 0;
251
        static uint16_t ServoFrameTime = 0;
252
        static uint8_t  ServoIndex = 0;
253
 
254
        #define MULTIPLYER 4
255
        static int16_t ServoNickOffset = (255 / 2) * MULTIPLYER; // initial value near center positon
256
        static int16_t ServoRollOffset = (255 / 2) * MULTIPLYER; // initial value near center positon
257
 
258
/******************************************************************************************************************
259
Arthur P: Modified the code to scheck the value of parameter 8. If 128 or higher then a HEF4017 is
260
expected and will be used. Else J7 and J9 are seen as separate normal outputs.
261
if((PlatinenVersion < 20)
262
091114. Inserted same changes into v.0.76g code.
263
20100802 Inserted same changes into v.0.80d code.
264
******************************************************************************************************************/    
265
 
266
//      if(PlatinenVersion < 20)
267
 
268
        if((PlatinenVersion < 20) && (Parameter_UserParam8 < 128 ))
269
        {
270
                //---------------------------
271
                // Nick servo state machine
272
                //---------------------------
273
                if(!PulseOutput) // pulse output complete
274
                {
275
                        if(TCCR2A & (1<<COM2A0)) // we had a low pulse
276
                        {
277
                                TCCR2A &= ~(1<<COM2A0);// make a high pulse
278
                                RemainingPulse  = MINSERVOPULSE + SERVORANGE/2; // center position ~ 1.5ms
279
 
280
                                ServoNickOffset = (ServoNickOffset * 3 + (int16_t)Parameter_ServoNickControl * MULTIPLYER) / 4; // lowpass offset
281
                                ServoNickValue = ServoNickOffset; // offset (Range from 0 to 255 * 3 = 765)
282
                                if(EE_Parameter.ServoCompInvert & 0x01)
283
                                {       // inverting movement of servo
284
                                        ServoNickValue += (int16_t)( ( (int32_t)EE_Parameter.ServoNickComp * MULTIPLYER * (IntegralNick / 128L ) ) / (256L) );
285
                                }
286
                                else
287
                                {       // non inverting movement of servo
288
                                        ServoNickValue -= (int16_t)( ( (int32_t)EE_Parameter.ServoNickComp * MULTIPLYER * (IntegralNick / 128L ) ) / (256L) );
289
                                }
290
                                // limit servo value to its parameter range definition
291
                                if(ServoNickValue < ((int16_t)EE_Parameter.ServoNickMin * MULTIPLYER) )
292
                                {
293
                                        ServoNickValue = (int16_t)EE_Parameter.ServoNickMin * MULTIPLYER;
294
                                }
295
                                else
296
                                if(ServoNickValue > ((int16_t)EE_Parameter.ServoNickMax * MULTIPLYER) )
297
                                {
298
                                        ServoNickValue = (int16_t)EE_Parameter.ServoNickMax * MULTIPLYER;
299
                                }
300
 
301
                                RemainingPulse += ServoNickValue - (256 / 2) * MULTIPLYER; // shift ServoNickValue to center position
302
 
303
                                ServoNickValue /= MULTIPLYER;
304
 
305
                                // range servo pulse width
306
                                if(RemainingPulse > MAXSERVOPULSE )                     RemainingPulse = MAXSERVOPULSE; // upper servo pulse limit
307
                                else if(RemainingPulse < MINSERVOPULSE )        RemainingPulse = MINSERVOPULSE; // lower servo pulse limit
308
                                // accumulate time for correct update rate
309
                                ServoFrameTime = RemainingPulse;
310
                        }
311
                        else // we had a high pulse
312
                        {
313
                                TCCR2A |= (1<<COM2A0); // make a low pulse
314
                                RemainingPulse = PPM_FRAMELEN - ServoFrameTime;
315
                        }
316
                        // set pulse output active
317
                        PulseOutput = 1;
318
                }
319
        } // EOF Nick servo state machine
320
        else
321
        {
322
                //-----------------------------------------------------
323
                // PPM state machine, onboard demultiplexed by HEF4017
324
                //-----------------------------------------------------
325
                if(!PulseOutput) // pulse output complete
326
                {
327
                        if(TCCR2A & (1<<COM2A0)) // we had a low pulse
328
                        {
329
                                TCCR2A &= ~(1<<COM2A0);// make a high pulse
330
 
331
                                if(ServoIndex == 0) // if we are at the sync gap
332
                                {
333
                                        RemainingPulse = PPM_FRAMELEN - ServoFrameTime; // generate sync gap by filling time to full frame time
334
                                        ServoFrameTime = 0; // reset servo frame time
335
                                        HEF4017R_ON; // enable HEF4017 reset
336
                                }
337
                                else // servo channels
338
                                {
339
                                        RemainingPulse  = MINSERVOPULSE + SERVORANGE/2; // center position ~ 1.5ms
340
                                        switch(ServoIndex) // map servo channels
341
                                        {
342
                                                case 1: // Nick Compensation Servo
343
                                                        ServoNickOffset = (ServoNickOffset * 3 + (int16_t)Parameter_ServoNickControl * MULTIPLYER) / 4; // lowpass offset
344
                                                        ServoNickValue = ServoNickOffset; // offset (Range from 0 to 255 * 3 = 765)
345
                                                        if(EE_Parameter.ServoCompInvert & 0x01)
346
                                                        {       // inverting movement of servo
347
                                                                ServoNickValue += (int16_t)( ( (int32_t)EE_Parameter.ServoNickComp * MULTIPLYER * (IntegralNick / 128L ) ) / (256L) );
348
                                                        }
349
                                                        else
350
                                                        {       // non inverting movement of servo
351
                                                                ServoNickValue -= (int16_t)( ( (int32_t)EE_Parameter.ServoNickComp * MULTIPLYER * (IntegralNick / 128L ) ) / (256L) );
352
                                                        }
353
                                                        // limit servo value to its parameter range definition
354
                                                        if(ServoNickValue < ((int16_t)EE_Parameter.ServoNickMin * MULTIPLYER) )
355
                                                        {
356
                                                                ServoNickValue = (int16_t)EE_Parameter.ServoNickMin * MULTIPLYER;
357
                                                        }
358
                                                        else
359
                                                        if(ServoNickValue > ((int16_t)EE_Parameter.ServoNickMax * MULTIPLYER) )
360
                                                        {
361
                                                                ServoNickValue = (int16_t)EE_Parameter.ServoNickMax * MULTIPLYER;
362
                                                        }
363
                                                        RemainingPulse += ServoNickValue - (256 / 2) * MULTIPLYER; // shift ServoNickValue to center position
364
                                                        ServoNickValue /= MULTIPLYER;
365
                                                        break;
366
                                         case 2: // Roll Compensation Servo
367
                                                        ServoRollOffset = (ServoRollOffset * 3 + (int16_t) Parameter_ServoRollControl  * MULTIPLYER) / 4; // lowpass offset
368
                                                        ServoRollValue = ServoRollOffset; // offset (Range from 0 to 255 * 3 = 765)
369
                                                        if(EE_Parameter.ServoCompInvert & 0x02)
370
                                                        {       // inverting movement of servo
371
                                                                ServoRollValue += (int16_t)( ( (int32_t) EE_Parameter.ServoRollComp * MULTIPLYER * (IntegralRoll / 128L ) ) / (256L) );
372
                                                        }
373
                                                        else
374
                                                        {       // non inverting movement of servo
375
                                                                ServoRollValue -= (int16_t)( ( (int32_t) EE_Parameter.ServoRollComp * MULTIPLYER * (IntegralRoll / 128L ) ) / (256L) );
376
                                                        }
377
                                                    // limit servo value to its parameter range definition
378
                                                        if(ServoRollValue < ((int16_t)EE_Parameter.ServoRollMin * MULTIPLYER) )
379
                                                        {
380
                                                                ServoRollValue = (int16_t)EE_Parameter.ServoRollMin * MULTIPLYER;
381
                                                        }
382
                                                        else
383
                                                        if(ServoRollValue > ((int16_t)EE_Parameter.ServoRollMax * MULTIPLYER) )
384
                                                        {
385
                                                                ServoRollValue = (int16_t)EE_Parameter.ServoRollMax * MULTIPLYER;
386
                                                        }
387
                                                        RemainingPulse += ServoRollValue - (256 / 2) * MULTIPLYER; // shift ServoNickValue to center position
388
                                                        ServoRollValue /= MULTIPLYER;
389
                                                        //DebugOut.Analog[20] = ServoRollValue;
390
                                                        break;
391
/******************************************************************************************************************
392
Arthur P: Shutter Servo including interval control over parameter 5 and 6.
393
091114 Inserted same modification into v.0.76g code, removing previously REM-ed out modified parts.
394
20100802 Inserted same modification into v.0.76g code, removing previously REM-ed out modified parts.
395
Modified to use lower 7 bits of user parameter 7.
396
******************************************************************************************************************/
397
                                         case 3:
398
//                                                      RemainingPulse += ((int16_t)Parameter_Servo3 * MULTIPLYER) - (256 / 2) * MULTIPLYER;
399
//                                                      break;
400
 
401
 
402
                                                        if(PPM_in[EE_Parameter.Kanalbelegung[K_POTI3]] < -32)
403
                                                        {
404
                                                        // Set servo to null position, turning camera off.
405
                                                                RemainingPulse  = MINSERVOPULSE;
406
                                                        }
407
                                                        else
408
                                                        {
409
                                                                // 090807: Arthur P.: Removed the shutter cycle parts as they may be impacting timing loops.
410
                                                                // 20100804 Reactived shutter interval timer capability.
411
                                                                if(PPM_in[EE_Parameter.Kanalbelegung[K_POTI3]] > 32)
412
                                                                // Top position on a 3 position switch which runs from -127 to +127
413
                                                                {
414
 
415
                                                                        RemainingPulse  = MINSERVOPULSE + SERVORANGE;
416
                                                                }
417
                                                                else
418
                                                                {
419
                                                                        // Cycle shutter servo between 50% on and off depending upon CameraShutterCycleCounter
420
                                                                        // If CameraShutterCylce < 50 then default to continuous shoot.
421
                                                                        if(CameraShutterCycle < 50 )    // == 5x the minimum value of userpara8 lower 7 bits
422
                                                                        {
423
                                                                                RemainingPulse  = MINSERVOPULSE + SERVORANGE/2;
424
                                                                        }
425
                                                                        else
426
                                                                        {      
427
                                                                                if(CameraShutterCycleCounter == CameraShutterCycle)
428
                                                                                {
429
                                                                                        // Shutter on
430
                                                                                        CameraShutterCycleCounter = 0;
431
                                                                                        RemainingPulse  = MINSERVOPULSE + SERVORANGE/2;
432
                                                                                }
433
                                                                                else
434
                                                                                {
435
                                                                                        // Leave on for at least 20 cycles or 0.2 seconds to allow 
436
                                                                                        // the camera to properly trigger, turn off if past 0.2 sec.
437
                                                                                        // For now this is actually set via para5 to allow for a long enough
438
                                                                                        // shutter pulse for different cameras. Once it is clear what value
439
                                                                                        // works, this can be changed to a hardcoded value.
440
                                                                                        CameraShutterCycleCounter++;
441
                                                                                        if(CameraShutterCycleCounter == CameraShutterCycleOnCount)
442
                                                                                        {
443
                                                                                                // Shutter off
444
                                                                                                RemainingPulse = MINSERVOPULSE;
445
                                                                                        }
446
                                                                                }
447
                                                                        }
448
                                                                }      
449
                                                        }
450
                                                        break;
451
 
452
                                         case 4:
453
                                                        RemainingPulse += ((int16_t)Parameter_Servo4 * MULTIPLYER) - (256 / 2) * MULTIPLYER;
454
                                                        break;
455
                                         case 5:
456
                                                        RemainingPulse += ((int16_t)Parameter_Servo5 * MULTIPLYER) - (256 / 2) * MULTIPLYER;
457
                                                        break;
458
                                                default: // other servo channels
459
                                                        RemainingPulse += 2 * PPM_in[ServoIndex]; // add channel value, factor of 2 because timer 1 increments 3.2µs
460
                                                        break;
461
                                        }
462
                                        // range servo pulse width
463
                                        if(RemainingPulse > MAXSERVOPULSE )                     RemainingPulse = MAXSERVOPULSE; // upper servo pulse limit
464
                                        else if(RemainingPulse < MINSERVOPULSE )        RemainingPulse = MINSERVOPULSE; // lower servo pulse limit
465
                                        // substract stop pulse width
466
                                        RemainingPulse -= PPM_STOPPULSE;
467
                                        // accumulate time for correct sync gap
468
                                        ServoFrameTime += RemainingPulse;
469
                                }
470
                        }
471
                        else // we had a high pulse
472
                        {
473
                                TCCR2A |= (1<<COM2A0); // make a low pulse
474
                                // set pulsewidth to stop pulse width
475
                                RemainingPulse = PPM_STOPPULSE;
476
                                // accumulate time for correct sync gap
477
                                ServoFrameTime += RemainingPulse;
478
                                if((ServoActive && SenderOkay > 180) || ServoActive == 2) HEF4017R_OFF; // disable HEF4017 reset
479
                                else HEF4017R_ON;
480
                                ServoIndex++; // change to next servo channel
481
                                if(ServoIndex > EE_Parameter.ServoNickRefresh) ServoIndex = 0; // reset to the sync gap
482
                        }
483
                        // set pulse output active
484
                        PulseOutput = 1;
485
                }
486
        } // EOF PPM state machine
487
 
488
        // General pulse output generator
489
        if(RemainingPulse > (255 + IRS_RUNTIME))
490
        {
491
                OCR2A = 255;
492
                RemainingPulse -= 255;
493
        }
494
        else
495
        {
496
                if(RemainingPulse > 255) // this is the 2nd last part
497
                {
498
                        if((RemainingPulse - 255) < IRS_RUNTIME)
499
                        {
500
                                OCR2A = 255 - IRS_RUNTIME;
501
                                RemainingPulse -= 255 - IRS_RUNTIME;
502
 
503
                        }
504
                        else // last part > ISR_RUNTIME
505
                        {
506
                                OCR2A = 255;
507
                                RemainingPulse -= 255;
508
                        }
509
                }
510
                else // this is the last part
511
                {
512
                        OCR2A = RemainingPulse;
513
                        RemainingPulse = 0;
514
                        PulseOutput = 0; // trigger to stop pulse
515
                }
516
        } // EOF general pulse output generator
517
}