Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
670 rain-er 1
#!/usr/bin/perl
2
#!/usr/bin/perl -d:ptkdb
3
 
4
###############################################################################
5
#
6
# libmktime.pl -  MK Mission Cockpit - Timer for GUI Frontend
7
#
8
# Copyright (C) 2009  Rainer Walther  (rainerwalther-mail@web.de)
9
#
10
# Creative Commons Lizenz mit den Zusaetzen (by, nc, sa)
11
#
12
# Es ist Ihnen gestattet: 
13
#     * das Werk vervielfältigen, verbreiten und öffentlich zugänglich machen
14
#     * Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen
15
# 
16
# Zu den folgenden Bedingungen:
17
#     * Namensnennung.
18
#       Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen.
19
#     * Keine kommerzielle Nutzung.
20
#       Dieses Werk darf nicht für kommerzielle Zwecke verwendet werden.
21
#     * Weitergabe unter gleichen Bedingungen.
22
#       Wenn Sie den lizenzierten Inhalt bearbeiten oder in anderer Weise umgestalten,
23
#       verändern oder als Grundlage für einen anderen Inhalt verwenden,
24
#       dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von Lizenzbedingungen
25
#       weitergeben, die mit denen dieses Lizenzvertrages identisch oder vergleichbar sind.
26
# 
27
# Im Falle einer Verbreitung müssen Sie anderen die Lizenzbedingungen, unter welche dieses
28
# Werk fällt, mitteilen. Am Einfachsten ist es, einen Link auf diese Seite einzubinden.
29
# 
30
# Jede der vorgenannten Bedingungen kann aufgehoben werden, sofern Sie die Einwilligung
31
# des Rechteinhabers dazu erhalten.
32
# 
33
# Diese Lizenz lässt die Urheberpersönlichkeitsrechte unberührt.
34
# 
35
# Weitere Details zur Lizenzbestimmung gibt es hier:
36
#   Kurzform: http://creativecommons.org/licenses/by-nc-sa/3.0/de/
37
#   Komplett: http://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode
38
#
39
###############################################################################
40
# 2009-08-09 0.2.5 rw Timer moved from mkcockpit.pl
41
#                     Optional Player home-pos in map configuration
42
# 2009-08-23 0.2.6 rw Tracking-Antenna Icon
43
#                     POI heading control
44
# 2009-10-11 0.2.7 rw Tracker control changed
45
#
46
###############################################################################
47
 
48
$Version{'libmktimer.pl'}  = "0.2.7 - 2009-10-11";
49
 
50
use Math::Trig;
51
 
52
#
53
# Timer: 5s
54
#
55
$main->repeat (5000, sub
56
    {
57
    if ( ! $MkSendWp )
58
        {
59
        # Abfragefrequenz OSD und Debug regelmäßig neu einstellen, falls Übertragungsfehler
60
        $MkSendQueue->enqueue( "o", "$AddrNC", pack ("C", 10) );   # Frequenz OSD Datensatz, * 10ms
61
        $MkSendQueue->enqueue( "d", "$AddrNC", pack ("C", 10) );   # Frequenz MK Debug Datensatz, * 10ms
62
        $MkSendQueue->enqueue( "v", "$AddrNC", "");   # Version
63
        $MkSendQueue->enqueue( "e", "$AddrNC", "");   # Error Text Request
64
        }
65
 
66
    lock (%MkOsd);              # until end of block
67
 
68
    # Draw Operation Radius Border
69
    $map_canvas->delete('Map-Border-OperatingRadius');
70
    if ( &HomePosIsValid() )
71
        {
72
        my $Radius = $MkOsd{'OperatingRadius'};
73
        my $H_Lat = $MkOsd{'HomePos_Lat'};
74
        my $H_Lon = $MkOsd{'HomePos_Lon'};
75
        my $Angel = &MapAngel();
76
 
77
        my ($T_Lat, $T_Lon) = &MapGpsAt ($H_Lat, $H_Lon, $Radius, $Angel -90);
78
        my ($R_Lat, $R_Lon) = &MapGpsAt ($H_Lat, $H_Lon, $Radius, $Angel);
79
        my ($B_Lat, $B_Lon) = &MapGpsAt ($H_Lat, $H_Lon, $Radius, $Angel + 90);
80
        my ($L_Lat, $L_Lon) = &MapGpsAt ($H_Lat, $H_Lon, $Radius, $Angel + 180);
81
 
82
        my ($T_x, $T_y) = &MapGps2XY ($T_Lat, $T_Lon);
83
        my ($R_x, $R_y) = &MapGps2XY ($R_Lat, $R_Lon);
84
        my ($B_x, $B_y) = &MapGps2XY ($B_Lat, $B_Lon);
85
        my ($L_x, $L_y) = &MapGps2XY ($L_Lat, $L_Lon);
86
 
87
        $map_canvas->createArc ( $L_x, $B_y, $R_x, $T_y,
88
                                 '-tags' => 'Map-Border-OperatingRadius',
89
                                 '-extent' => '359',
90
                                 '-start' => '0',
91
                                 '-style' => 'chord',
92
                                 '-outline' => $Cfg->{'mkcockpit'}->{'ColorAirfield'},
93
                                 '-width' => '1',
94
                               );
95
        $map_canvas->raise('Map-Border-OperatingRadius', 'Map');  # Border above Map
96
        }
97
 
98
    });
99
 
100
 
101
 
102
#       
103
# Timer: 0.1s - Map Overlay aktualisieren
104
#
105
$frame_map_top->repeat (100, sub
106
    {
107
 
108
    # Clear old messages from this timer
109
    &MkMessageInit ("Timer-MapOverlay");
110
 
111
    lock (%MkOsd);              # until end of block
112
 
113
    # Aktuell gültige Karte
114
    %Map = %{$Maps{'Current'}};
115
 
116
    if ( &MkOsdIsValid() )
117
        {
118
        # Gueltige OSD Daten
119
 
120
        # Operation Mode
121
        $OperationMode = "";
122
        if ( &MkIsWptMode() )         { $OperationMode = "WPT"; }
123
        if ( $PlayerMode eq "Play" )  { $OperationMode = "Play"; }
124
        if ( $PlayerMode eq "Pause" ) { $OperationMode = "Paus"; }
125
        if ( $PlayerMode eq "Home" )  { $OperationMode = "Home"; }
126
        if ( &MkIsPhMode() )          { $OperationMode = "PH"; }
127
        if ( &MkIsFreeMode() )        { $OperationMode = "Free"; }
128
 
129
        my $SatsInUse = $MkOsd{'SatsInUse'};
130
        if ( &CurPosIsValid()  and  &HomePosIsValid() )
131
            {
132
            # ausreichender GPS Empfang
133
 
134
            # get x,y map coords of current position
135
            my ($C_x, $C_y, $C_Angel) = &MapGps2XY($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}, $MkOsd{'CompassHeading'});
136
            $MkPos_x = $C_x;
137
            $MkPos_y = $C_y;
138
 
139
            # rotate MK arrow
140
            my $dy = sin (deg2rad $C_Angel) * ($MapMkLen/2);
141
            my $dx = cos (deg2rad $C_Angel) * ($MapMkLen/2);
142
            my $x0 = $C_x - $dx;
143
            my $y0 = $C_y - $dy;
144
            my $x1 = $C_x + $dx;
145
            my $y1 = $C_y + $dy;
146
            $map_canvas->coords ('MK-Arrow', $x0, $y0, $x1, $y1);
147
 
148
            # Update speed vector
149
            my $MapAngel = &MapAngel();   # North to Map-Horizont
150
            my $GpsSpeedNorth = $MkNcDebug{'Analog_21'};
151
            my $GpsSpeedEast  = $MkNcDebug{'Analog_22'};
152
            my $PhiGpsSpeed = rad2deg atan2 ( $GpsSpeedEast, $GpsSpeedNorth );
153
            $PhiMapSpeed = $PhiGpsSpeed - $MapAngel;
154
 
155
            # 555 cm/s ~ 20 km/h -> Zeigerlänge = $MkSpeedLen bei 20 km/h
156
            my $dy = sin (deg2rad $PhiMapSpeed) * $MapMkSpeedLen * $MkOsd{'GroundSpeed'} / 555;
157
            my $dx = cos (deg2rad $PhiMapSpeed) * $MapMkSpeedLen * $MkOsd{'GroundSpeed'} / 555;
158
            my $x0 = $C_x;
159
            my $y0 = $C_y;
160
            my $x1 = $C_x + $dx;
161
            my $y1 = $C_y + $dy;
162
            $map_canvas->coords ('MK-Speed', $x0, $y0, $x1, $y1);
163
 
164
            # Update Line between Home and MK
165
            my ($H_x, $H_y) = &MapGps2XY($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'});
166
            $map_canvas->coords ('MK-Home-Line', $H_x, $H_y, $C_x, $C_y);
167
 
168
            # Update Distance between Home and MK
169
            my ($Dist, $Bearing) = &MapGpsTo($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'},
170
                                                    $MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'} );
171
            my $x = ($C_x - $H_x) / 2 + $H_x + 8;
172
            my $y = ($C_y - $H_y) / 2 + $H_y + 8;
173
            $map_canvas->coords ('MK-Home-Dist', $x, $y);
174
            $map_canvas->itemconfigure ('MK-Home-Dist',
175
                                        '-text' => sprintf ("%4d m", int ($Dist + 0.5) ),
176
                                       );
177
 
178
            # Update OSD - Sat dependent values
179
            $map_canvas->itemconfigure ('MK-OSD-Spd-Value', '-text' => sprintf ("%3d km/h", $MkOsd{'GroundSpeed'} * 0.036) );
180
 
181
            # Alt = average Luftdruck und Sat
182
            my $Alt = int ( ($MkOsd{'Altimeter'} / $Cfg->{'mkcockpit'}->{'AltFactor'} +
183
                             $MkOsd{'CurPos_Alt'} - $MkOsd{'HomePos_Alt'} ) / 2 + 0.5 );
184
            $System{'Alt'} = $Alt;
185
            $map_canvas->itemconfigure ('MK-OSD-Alt-Value', '-text' => sprintf ("%3d m", $Alt) );
186
 
187
            if ( &TargetIsValid() )
188
                {
189
                # Valid Target
190
 
191
                # Update Line between Target and MK
192
                my ($T_x, $T_y) = &MapGps2XY($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'});
193
                $map_canvas->coords ('MK-Target-Line', $C_x, $C_y, $T_x, $T_y);
194
 
195
                # Update Distance between Target and MK
196
                my ($Dist, $Bearing) = &MapGpsTo($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'},
197
                                                         $MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'} );
198
                if ( $Dist >= 25 )  
199
                    {
200
                    my $x = ($C_x - $T_x) / 2 + $T_x - 8;
201
                    my $y = ($C_y - $T_y) / 2 + $T_y + 8;
202
                    $map_canvas->coords ('MK-Target-Dist', $x, $y);
203
                    $map_canvas->itemconfigure ('MK-Target-Dist',
204
                                                '-text' => sprintf ("%4d m", int ($Dist + 0.5) ),
205
                                               );
206
                    }
207
                else
208
                    {
209
                    # Don't show distance < 25m
210
                    $map_canvas->coords ('MK-Target-Dist', 0, -100);
211
                    }
212
 
213
                # show target icon
214
                my $IconHeight = 48;
215
                my $IconWidth = 48;
216
                $map_canvas->coords('Target', $T_x - $IconWidth/2, $T_y - $IconHeight );
217
 
218
                $System{'CrossingBorder'} = 0;
219
                if ( &MkIsFlying()  and  &IsCrossingBorder($MkPos_x, $MkPos_y, $T_x, $T_y) )
220
                    {
221
                    # only, if MK is flying
222
                    $System{'CrossingBorder'} = 1;
223
                    &MkMessage ($Translate{'MsgCrossingBorder'}, "Timer-MapOverlay");
224
                    }
225
                }
226
            else
227
                {
228
                # No valid Target, move target line out of sight/canvas
229
                $map_canvas->coords ('MK-Target-Line', 0, -100, 0, -100);
230
                $map_canvas->coords ('MK-Target-Dist', 0, -100);
231
 
232
                # hide target icon
233
                $map_canvas->coords('Target', 0, -100, );
234
                }
235
 
236
            # Update Line between MK and POI
237
            if ( $PoiMode )
238
                {
239
                my ($P_x, $P_y) = &MapGps2XY($Poi_Lat, $Poi_Lon);
240
                $map_canvas->coords ('MK-POI-Line', $P_x, $P_y, $C_x, $C_y);
241
                }
242
            else
243
                {
244
                $map_canvas->coords ('MK-POI-Line', 0, -200, 0, -200);
245
                }
246
            }
247
        else
248
            {
249
            # kein ausreichender Sat-Empfang
250
            $map_canvas->itemconfigure ('MK-OSD-Spd-Value', '-text' => sprintf ("%3d km/h", 0 ) );
251
            }
252
 
253
        # Update OSD - non Sat dependent values
254
        $map_canvas->itemconfigure ('MK-OSD-Odo-Value', '-text' => sprintf ("%3.3f km", $OdoMeter / 1000) );
255
        $map_canvas->itemconfigure ('MK-OSD-Tim-Value', '-text' => sprintf ("%02d:%02d", $MkFlyingTime / 60, $MkFlyingTime % 60) );
256
        $map_canvas->itemconfigure ('MK-OSD-Sat-Value', '-text' => $MkOsd{'SatsInUse'} );
257
 
258
        # battery - OSD and warning
259
        my $UBat = sprintf ("%3.1f", $MkOsd{'UBat'});
260
        $System{'UBat'} = $UBat;
261
        $map_canvas->itemconfigure ('MK-OSD-Bat-Value', '-text' => "$UBat V" );
262
 
263
        $System{'BatWarning'} = 0;
264
        $map_canvas->itemconfigure ('MK-OSD-Bat-Value', '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'});
265
        if ( $MkOsd{'UBat'}  <  $Cfg->{'mkcockpit'}->{'UBatWarning'} )
266
            {
267
            if ( time %2 )
268
                {
269
                $map_canvas->itemconfigure ('MK-OSD-Bat-Value', '-fill' => 'red');
270
                }
271
 
272
            &MkMessage ($Translate{'MsgBatWarning'}, "Timer-MapOverlay");
273
            $System{'BatWarning'} = 1;
274
            }
275
 
276
 
277
        # Display Operation Mode
278
        my $DisplayMode = $OperationMode;
279
        if ( &MkIsWptMode()  and  $OperationMode eq "Play" )
280
            {
281
            my %ModeMatrix =
282
               (
283
               "KML-STD" => "Play KML",
284
               "KML-RND" => "Play KML",
285
               "KML-MAP" => "Play KML",
286
               "WPT-STD" => "Play WPT",
287
               "WPT-RND" => "Rand WPT",
288
               "WPT-MAP" => "Rand MAP",
289
               );
290
            my $Key = "${PlayerWptKmlMode}-${PlayerRandomMode}";
291
            $DisplayMode = $ModeMatrix{$Key};
292
            }
293
 
294
        $System{'RangeWarning'} = 0;
295
        if ( &MkRangeLimit() )
296
            {
297
            $DisplayMode  = "$DisplayMode" . " !!";   # Range Warning
298
            $System{'RangeWarning'} = 1;
299
            }
300
        $map_canvas->itemconfigure ('MK-OSD-Mode-Value', '-text' => $DisplayMode );
301
 
302
 
303
        # Waypoints abhaengig vom Modus NC/Player
304
        my $WpValue = "-- / --";
305
        if ( $MkOsd{'WaypointNumber'} > 0)
306
            {
307
            $WpValue = sprintf ("%d / %d", $MkOsd{'WaypointIndex'}, $MkOsd{'WaypointNumber'});
308
            }
309
        if ($PlayerMode ne "Stop" and $PlayerWptKmlMode eq "WPT")
310
            {
311
            $WpValue = sprintf ("%d / %d", $WpPlayerIndex +1, scalar @Waypoints);
312
            }
313
        if ($PlayerMode ne "Stop" and $PlayerWptKmlMode eq "KML" )
314
            {
315
            my $KmlTimeBase = $Cfg->{'waypoint'}->{'KmlTimeBase'} || 1.0;
316
            my $CurrTime = int ($KmlPlayerIndex * $KmlTimeBase + 0.5);
317
            my $TotTime = int (scalar @KmlTargets * $KmlTimeBase + 0.5);
318
            $WpValue = sprintf ("%02d:%02d / %02d:%02d", $CurrTime / 60, $CurrTime % 60, $TotTime / 60, $TotTime % 60);
319
            }
320
        $map_canvas->itemconfigure ('MK-OSD-Wp-Value',  '-text' => "$WpValue");
321
 
322
        # Recording Mode
323
        my $RecordText = "";
324
        if ( $PlayerRecordMode =~ /REC/i )
325
            {
326
            my $KmlTimeBase = $Cfg->{'waypoint'}->{'KmlTimeBase'} || 1.0;
327
            my $TotTime = int (scalar @KmlTargets * $KmlTimeBase + 0.5);
328
            $RecordText = sprintf ("Recording %02d:%02d", $TotTime / 60, $TotTime % 60);
329
            }
330
        $map_canvas->itemconfigure ('MK-OSD-Rec-Value', '-text' => $RecordText );
331
 
332
 
333
        # Farbe MK-Zeiger abhängig vom GPS Empfang
334
        my $MkCol= $Cfg->{'mkcockpit'}->{'ColorMkSatNo'};
335
        if ( $SatsInUse >= 1 ) { $MkCol = $Cfg->{'mkcockpit'}->{'ColorMkSatLow'} ; }
336
        if ( $SatsInUse >= 6 ) { $MkCol = $Cfg->{'mkcockpit'}->{'ColorMkSatGood'}; }
337
        $map_canvas->itemconfigure ('MK-Arrow', '-fill' => $MkCol);
338
 
339
 
340
        # Show/Hide SatFix Icon
341
        if ($SatsInUse >= 6 )
342
            {
343
            $map_canvas->coords('Satellite', $MapSizeX-300, 10, );
344
            }
345
        else
346
            {
347
            # move icon out of sight
348
            $map_canvas->coords('Satellite', 0, -100, );
349
            }
350
 
351
 
352
        # Variometer Pointer
353
        my $dy = -$MkOsd{'Variometer'} * 10;
354
        $map_canvas->coords('Map-Variometer-Pointer', 5, $MapSizeY/2+$dy, 20, $MapSizeY/2+10+$dy, 20, $MapSizeY/2-10+$dy);
355
 
356
        #
357
        # System checks
358
        #
359
 
360
        if ( ! &MkIsMotorOn() )      { &MkMessage ($Translate{'MsgMotorOff'}, "Timer-MapOverlay"); }
361
        if ( ! &MkIsFlying() )       { &MkMessage ($Translate{'MsgNotFlying'}, "Timer-MapOverlay"); }
362
        if ( &MkIsCalibrating() )    { &MkMessage ($Translate{'MsgCalibrate'}, "Timer-MapOverlay"); }
363
        if ( &MkIsMotorStarting() )  { &MkMessage ($Translate{'MsgStart'}, "Timer-MapOverlay") }
364
        if ( &MkEmergencyLanding() ) { &MkMessage ($Translate{'MsgEmergencyLanding'}, "Timer-MapOverlay"); }
365
        if ( &MkRangeLimit() )       { &MkMessage ($Translate{'MsgRangeLimit'}, "Timer-MapOverlay"); }
366
 
367
        # RC range check
368
        my $RcQuality = $MkOsd{'RC_Quality'};
369
        $System{'RCQuality'} = "";
370
 
371
        if ( $RcQuality < 100 )
372
            {
373
            $System{'RCQuality'} = "NO";
374
            &MkMessage ($Translate{'MsgRcError'}, "Timer-MapOverlay");
375
            }
376
        elsif ( $RcQuality < 150 )
377
            {
378
            $System{'RCQuality'} = "WEAK";
379
            &MkMessage ($Translate{'MsgRcWarning'}, "Timer-MapOverlay");
380
            }
381
 
382
        # Sat reception quality
383
        if ( $SatsInUse == 0 )
384
            {
385
            &MkMessage ($Translate{'MsgNoSatReception'}, "Timer-MapOverlay");
386
            }
387
        elsif ( $SatsInUse > 0  and $SatsInUse < 6 )
388
            {
389
            &MkMessage ($Translate{'MsgWeakSatReception'}, "Timer-MapOverlay");
390
            }
391
 
392
        # MK Border check
393
        $System{'OutsideBorder'} = "0";
394
        if ( &MkIsFlying() and ! &IsInsideBorder($MkPos_x, $MkPos_y) )
395
            {
396
            # only, if MK is flying
397
            $System{'OutsideBorder'} = "1";
398
            &MkMessage ($Translate{'MsgOutsideBorder'}, "Timer-MapOverlay");
399
            }
400
 
401
        # Show Balloon, when aproaching Target
402
        &TargetMessageShow();
403
 
404
        }
405
    else
406
        {
407
        # keine aktuellen OSD Daten vom MK verfügbar
408
        &MkMessage ($Translate{'MsgNoData'}, "Timer-MapOverlay");
409
        }
410
 
411
 
412
    # Wp-Number input from keyboard
413
    $KbTimer++;
414
    if ( $CbPlayerKey ne "" )
415
        {
416
        # Key pressed
417
        $KbNum = "$KbNum" . "$CbPlayerKey";
418
 
419
        $CbPlayerKey = "";
420
        $KbTimer = 0;
421
        }
422
    if ( $KbTimer > 7  and $KbNum ne "" )
423
        {
424
        # number complete, set target
425
        my $WpIndex = sprintf ("%d", $KbNum);
426
        &WpTargetSet ($WpIndex - 1);
427
 
428
        # prepare for next number
429
        $KbNum = "";
430
        }
431
 
432
 
433
    # Show System Messages
434
    &MkMessageShow();
435
 
436
    });
437
 
438
#       
439
# Timer: 0.1s - Tracking Anzeige aktualisieren
440
#
441
if ( $Cfg->{'track'}->{'Active'} =~ /y/i )
442
    {
443
    $TrackMkCalibrateEdge = 0;  # calibrate edge detection
444
 
445
    $frame_map_top->repeat (100, sub
446
        {
447
        # Clear old messages from this timer
448
        &MkMessageInit ("Timer-Tracking");    
449
 
450
        lock (%MkOsd);              # until end of block
451
        lock (%MkTrack);            # until end of block
452
 
453
        # Aktuell gültige Karte
454
        %Map = %{$Maps{'Current'}};
455
 
456
        # Zeiger neu zeichnen
457
        my $ServoPan = @ServoPos[$MkTrack{'ServoPan'}];
458
        if ( $ServoPan ne ""  )
459
            {
460
            my $x0 = $TrackSizeX/2;    
461
            my $y0 = $TrackSizeY - 0 - $TrackOffY;
462
            my $x1 = $TrackSizeX/2 - ($TrackPtrLen-22) * cos( deg2rad $ServoPan);
463
            my $y1 = $TrackSizeY   - ($TrackPtrLen-22) * sin (deg2rad $ServoPan) - $TrackOffY;
464
            $track_canvas->coords ('Track-Ptr', $x0, $y0, $x1, $y1);
465
            }
466
 
467
        # Farbe Zeiger abhängig vom GPS Empfang
468
        my $SatsInUse = $MkOsd{'SatsInUse'};
469
        my $TrackPtrCol= 'red';
470
        if ( $SatsInUse >= 1 ) { $TrackPtrCol = 'orange'; }
471
        if ( $SatsInUse >= 6 ) { $TrackPtrCol = 'green'; }
472
        $track_canvas->itemconfigure ('Track-Ptr', '-fill' => $TrackPtrCol);
473
 
474
        # tracker coldstart condition at MK calibration, rising edge of signal
475
        if ( &MkIsCalibrating() )
476
            {
477
            if ( $TrackMkCalibrateEdge == 0 )
478
                {
479
                $TrackMkCalibrateEdge = 1;
480
 
481
                # send coldstart command to tracker
482
                $TrackQueue->enqueue("COLDSTART");
483
                }
484
            }
485
        else
486
            {
487
            $TrackMkCalibrateEdge = 0;
488
            }
489
        });
490
    }
491
 
492
 
493
#       
494
# Timer: 0.5s - Waypoint Player
495
#
496
$frame_map_top->repeat (500, sub
497
    {
498
    # Clear old messages from this timer
499
    &MkMessageInit ("Timer-Player");        
500
 
501
    lock (%MkOsd);              # until end of block
502
 
503
    if ( &MkIsWptMode() )
504
        {
505
        # NC is in WPT Mode 
506
 
507
        my $PoiHeading = $Cfg->{'waypoint'}->{'DefaultHeading'};
508
        if ( &CurPosIsValid()  and  $PoiMode )
509
            {
510
            $PoiHeading = &MapGpsTo ( $MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'},
511
                                      $Poi_Lat,  $Poi_Lon );
512
            }
513
 
514
        if ( $PlayerMode eq "Pause" )
515
            {
516
            if ( $PlayerPause_Lat ne ""  and  $PlayerPause_Lon ne "" )
517
                {
518
                # Gespeicherte Pausen-Pos senden
519
                &MkFlyTo ( '-lat'  => $PlayerPause_Lat,
520
                           '-lon'  => $PlayerPause_Lon,
521
                           '-holdtime' => "60",
522
                           '-heading' => $PoiHeading,
523
                           '-mode' => "Target",
524
                         );
525
                }
526
            }
527
 
528
        if ( $PlayerMode eq "Home" and &HomePosIsValid() )
529
            {
530
            # Gespeicherte oder eingestellte Home-Pos senden
531
 
532
            my $Home_Lat = $Map{'Home_Lat'} || $MkOsd{'HomePos_Lat'};
533
            my $Home_Lon = $Map{'Home_Lon'} || $MkOsd{'HomePos_Lon'};
534
 
535
            &MkFlyTo ( '-lat'  => $Home_Lat,
536
                       '-lon'  => $Home_Lon,
537
                       '-holdtime' => "60",
538
                       '-heading' => $PoiHeading,
539
                       '-mode' => "Target",
540
                     );
541
            }
542
 
543
 
544
        if ( $PlayerWptKmlMode ne 'WPT' )
545
            {
546
            # not in Wp mode
547
            return;
548
            }
549
 
550
 
551
        if ( $PlayerMode eq "Play"  )
552
            {
553
 
554
            if ( $PlayerRandomMode =~ /RND/i  or $PlayerRandomMode =~ /STD/i )
555
                {
556
                my $WpCnt = scalar @Waypoints;
557
                if ( $WpCnt > 0  and  $WpPlayerIndex < $WpCnt )
558
                    {
559
                    # Target WP-Pos senden
560
                    my $Wp = $Waypoints[$WpPlayerIndex];
561
                    my $Wp_Lon = $Wp->{'Pos_Lon'};
562
                    my $Wp_Lat = $Wp->{'Pos_Lat'};
563
                    if ( $Wp_Lat ne ""  and  $Wp_Lon ne "" )
564
                        {
565
                        &MkFlyTo ( '-lat'  => $Wp_Lat,
566
                                   '-lon'  => $Wp_Lon,
567
                                   '-holdtime' => "60",
568
                                   '-heading' => $PoiHeading,
569
                                   '-mode' => "Target",
570
                                 );
571
                        }
572
                    }
573
                }
574
 
575
            if ( $PlayerRandomMode =~ /MAP/i )
576
                {
577
                # Target Map-Pos senden
578
                &MkFlyTo ( '-x'  => $RandomTarget_x ,
579
                           '-y'  => $RandomTarget_y ,
580
                           '-holdtime' => "60",
581
                           '-heading' => $PoiHeading,
582
                           '-mode' => "Target",
583
                         );
584
                }
585
 
586
            # Ziel erreicht?
587
            if ( &WpCheckTargetReached() )
588
                {
589
                &WpTargetNext();
590
                }
591
            }
592
        }
593
 
594
    # WP Player Holdtime count down
595
    if ( $WpPlayerHoldtime > 0  )
596
        {
597
        $WpPlayerHoldtime --;
598
        }
599
    });
600
 
601
 
602
#       
603
# Timer: variabel - KML Player
604
#
605
my $KmlTimeBase = $Cfg->{'waypoint'}->{'KmlTimeBase'} || 1.0;
606
$KmlTimeBase *= 1000;
607
 
608
$frame_map_top->repeat ($KmlTimeBase, sub
609
    {
610
 
611
    # Clear old messages from this timer
612
    &MkMessageInit ("Timer-KMLPlayer");    
613
 
614
    lock (%MkOsd);              # until end of block
615
 
616
    if ( &CurPosIsValid() and $PlayerRecordMode =~ /REC/i )
617
        {
618
        # record current position
619
        push @KmlTargets, {
620
                          'Lat' => $MkOsd{'CurPos_Lat'},
621
                          'Lon' => $MkOsd{'CurPos_Lon'},
622
                          'Alt' => $MkOsd{'CurPos_Alt'},
623
                          };
624
        }
625
 
626
 
627
    if ( &MkIsWptMode() and  $PlayerMode eq "Play"  and  $PlayerWptKmlMode eq 'KML')
628
        {
629
        # Play KML
630
 
631
        # Pause, Home is handled in WPT-Timer
632
 
633
        my $KmlCnt = scalar @KmlTargets;
634
        if ( $KmlCnt > 0  and  $KmlPlayerIndex < $KmlCnt )
635
            {
636
            my $Lat = $KmlTargets[$KmlPlayerIndex]->{'Lat'};
637
            my $Lon = $KmlTargets[$KmlPlayerIndex]->{'Lon'};
638
            my $Alt = $KmlTargets[$KmlPlayerIndex]->{'Alt'};
639
 
640
            &MkFlyTo ( '-lat'             => $Lat,
641
                       '-lon'             => $Lon,
642
                       '-alt'             => $Alt,
643
                       '-holdtime'        => "60",
644
                       '-mode'            => "Target",
645
                     );
646
 
647
            # proceed to next Target
648
            $KmlPlayerIndex ++;
649
            if ( $KmlPlayerIndex >= $KmlCnt )
650
                {
651
                $KmlPlayerIndex = 0;
652
                }
653
            }
654
        }
655
 
656
    });
657
 
658
 
659
#       
660
# Timer: 1s
661
#
662
$frame_map_top->repeat (1000, sub
663
    {
664
    # Clear old messages from this timer
665
    &MkMessageInit ("Timer-Misc-1s");    
666
 
667
    lock (%MkOsd);              # until end of block
668
 
669
    # Aktuell gültige Karte
670
    %Map = %{$Maps{'Current'}};
671
 
672
    if ( &MkOsdIsValid() )
673
        {
674
 
675
        # Heartbeat MK Datenübertragung
676
        if ( time %2 )
677
            {
678
            $map_canvas->itemconfigure('Heartbeat', '-image' => 'HeartbeatLarge', );
679
            }
680
        else
681
            {
682
            $map_canvas->itemconfigure('Heartbeat', '-image' => 'HeartbeatSmall', );
683
            }
684
 
685
        # Flugzeit aktualisieren
686
        # Flugzeit selber mitzählen, da $MkOsd{'FlyingTime'} immer 0 (0.14b)
687
        if ( &MkIsFlying() )
688
            {
689
            $MkFlyingTime += 1;
690
            }
691
 
692
        # Update ODO-Meter
693
        if ( &CurPosIsValid() )
694
            {
695
            my $C_Lat = $MkOsd{'CurPos_Lat'};
696
            my $C_Lon = $MkOsd{'CurPos_Lon'};
697
 
698
            if ( $OdoFirst ne "" )
699
                {
700
                my ($Dist, $Bearing) = &MapGpsTo($C_Lat, $C_Lon, $OdoPos_Lat, $OdoPos_Lon );
701
                $OdoMeter += $Dist;
702
                }
703
            $OdoPos_Lat = $C_Lat;
704
            $OdoPos_Lon = $C_Lon;
705
            $OdoFirst = "1";
706
            }
707
 
708
        # # Bat capacity
709
        # my $Capacity = 100.0;
710
        # my $CapacityText = "";
711
        # if ( &MkIsFlying() )
712
        #     {
713
        #     if ( $UBatAverage eq "" )
714
        #         {
715
        #         $UBatAverage = $MkOsd{'UBat'};
716
        #         }
717
        #     $UBatAverage = (9.0 * $UBatAverage + $MkOsd{'UBat'}) / 10.0;
718
        #     $Capacity = &BatCapacity($UBatAverage);
719
        #     $CapacityText = sprintf ("(%d %)", int ($Capacity + 0.5) );
720
        #     }
721
        # $map_canvas->itemconfigure ('MK-OSD-Bat-Level', '-text' => $CapacityText );
722
 
723
 
724
        # # Estimate remaining flight time
725
        # my $TextTimeLeft = "";
726
        # if ( &MkIsFlying()  and  $Capacity <= 90 )
727
        #     {
728
        #     my $MaxTime = 100.0 / (100.0 - $Capacity) * $MkFlyingTime;
729
        #     my $TimeLeft = $MaxTime - $MkFlyingTime;
730
        #     $TextTimeLeft = sprintf ("(%d min)", int ($TimeLeft / 60.0 + 0.8) );
731
        #     }
732
        # $map_canvas->itemconfigure ('MK-OSD-Tim-Left', '-text' => $TextTimeLeft );
733
 
734
 
735
        # Footprint
736
        if ( $Cfg->{'mkcockpit'}->{'FootprintLength'} > 0 )
737
            {
738
            if ( &CurPosIsValid() )
739
                {
740
                # neuen Footprint hinten anhaengen
741
                my ($x, $y) = &MapGps2XY($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'});
742
                push @Footprint, $x, $y;
743
                }
744
 
745
            while ( $#Footprint / 2  >  $Cfg->{'mkcockpit'}->{'FootprintLength'} )
746
                {
747
                # alte Footprints entfernen
748
                splice @Footprint, 0, 2;
749
                }
750
 
751
            &FootprintRedraw();
752
            }
753
 
754
        # show tracking antenna icon
755
        if ( $MkTrack{'HomePos_Lat'} ne ""  and  $MkTrack{'HomePos_Lon'} ne ""  )
756
            {
757
            # show antenna icon
758
            my ($x, $y) = &MapGps2XY($MkTrack{'HomePos_Lat'}, $MkTrack{'HomePos_Lon'});
759
 
760
            my $IconHeight = 48;
761
            my $IconWidth = 48;
762
            $map_canvas->coords('Track-Antenna', $x - $IconWidth/2, $y - $IconHeight );
763
            }
764
        else
765
            {
766
            # move icon out of sight
767
            $map_canvas->coords('Track-Antenna', 0, -50 );
768
            }
769
 
770
 
771
        # fun :-)
772
        if ( int rand (100) == 43 )
773
            {
774
            &TtsSpeak ('LOW', $Translate{'TtsFun'});
775
            }
776
        }
777
 
778
    });
779
 
780
 
781
#       
782
# Timer: 1s - TTS Sprachausgabe
783
#
784
$frame_map_top->repeat (1000, sub
785
    {
786
    # Aktuell gültige Karte
787
    %Map = %{$Maps{'Current'}};
788
 
789
    lock (%MkOsd);              # until end of block
790
 
791
    my $StatusInterval = $Cfg->{'tts'}->{'StatusInterval'}  || "30";  
792
    $SpeechTimer ++;
793
    my @TtsMsg;
794
 
795
    if ( &MkOsdIsValid() )
796
        {
797
        # Gueltige OSD Daten
798
 
799
        if ( $SpeechTimer % $StatusInterval == 0 )
800
            {
801
            #
802
            # give system status, low prio messages
803
            #
804
 
805
            # clear old low prio messages
806
            &TtsClear('LOW');
807
 
808
            # Flight time
809
            my $Min = int ( ($MkFlyingTime +1) / 60);
810
            my $Sec = int ( ($MkFlyingTime +1) % 60);
811
            my $Text = sprintf ("$Translate{'TtsFlightTimeMinSec'}", $Min, $Sec);
812
            if ( $Min == 0 )
813
                {
814
                $Text = sprintf ("$Translate{'TtsFlightTimeSec'}", $Sec);
815
                }
816
            &TtsSpeak ('LOW', "$Text");
817
 
818
            # Battery
819
            my ($Volt, $Tenth) = split '\.', $System{'UBat'};
820
            &TtsSpeak ('LOW', sprintf ("$Translate{'TtsBattery'}", $Volt, $Tenth));
821
 
822
            # Altitude
823
            if ( $System{'Alt'} < 0 )
824
                {
825
                &TtsSpeak ('LOW', sprintf ("$Translate{'TtsAltitudeNegative'}", abs($System{'Alt'}) ) );
826
                }
827
            else
828
                {
829
                &TtsSpeak ('LOW', sprintf ("$Translate{'TtsAltitude'}", $System{'Alt'} ) );
830
                }
831
 
832
            # Satellites
833
            &TtsSpeak ('LOW', sprintf ("$Translate{'TtsSatellite'}",  $MkOsd{'SatsInUse'}) );
834
            }
835
 
836
       # high prio messages
837
       if ( $SpeechTimer % 5 == 0 )
838
            {
839
            if ( $System{'BatWarning'} )          { push @TtsMsg, $Translate{'TtsBatteryWarning'}; }
840
            if ( $System{'RCQuality'} eq "WEAK" ) { push @TtsMsg, $Translate{'TtsRcWeak'}; }
841
            if ( $System{'RCQuality'} eq "NO" )   { push @TtsMsg, $Translate{'TtsRcNo'}; }
842
            if ( $System{'CrossingBorder'} )      { push @TtsMsg, $Translate{'TtsCrossingBorder'}; }
843
            if ( $System{'OutsideBorder'} )       { push @TtsMsg, $Translate{'TtsOutsideAirfield'}; }
844
            if ( $System{'RangeWarning'} )        { push @TtsMsg, $Translate{'TtsRange'}; }
845
            }
846
        }
847
    else
848
        {
849
        # no data link
850
        if ( $SpeechTimer % 5 == 0 )
851
            {
852
            push @TtsMsg, $Translate{'TtsNoDataLink'};
853
            }
854
        }
855
 
856
    # speak high prio messages 
857
    if ( scalar @TtsMsg > 0 )
858
        {
859
        # Clear pending messsages
860
        &TtsClear('HIGH');
861
 
862
        # Speak collected messages
863
        foreach $Msg (@TtsMsg)
864
            {
865
            &TtsSpeak ('HIGH', $Msg);
866
            }
867
        }
868
    });
869
 
870
 
871
__END__