Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
598 rain-er 1
#!/usr/bin/perl
2
#!/usr/bin/perl -d:ptkdb
3
 
4
###############################################################################
5
#
6
# mkcomm.pl -  MK Communication Routines
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-02-21 0.0.1 rw created
41
# 2009-03-18 0.0.2 rw NC 0.14e
42
# 2009-04-01 0.1.0 rw RC1
43
# 2009-04-06 0.1.1 rw NC 0.15c
44
# 2009-05-16 0.1.2 rw External control
45
# 2009-08-15 0.1.3 rw SIG-Handler removed
46
#
47
###############################################################################
48
 
49
$Version{'mkcomm.pl'} = "0.1.3 - 2009-08-15";
50
 
51
# MK Protokoll
52
#   http://www.mikrokopter.de/ucwiki/en/SerialCommands?highlight=(command)
53
#   http://www.mikrokopter.de/ucwiki/en/SerialProtocol?highlight=(protocol)
54
#
55
# Parameter
56
#
57
 
58
# Com Port of MK Comm-Device (BT, WI.232)
59
if ( ! defined $Cfg->{'mkcomm'}->{'Port'} )
60
    {
61
    # set default
62
    $Cfg->{'mkcomm'}->{'Port'} = "COM5";
63
    }
64
 
65
$AddrFC     = "b";
66
$AddrNC     = "c";
67
$AddrMK3MAG = "d";
68
 
69
# Packages
70
use threads;                # http://search.cpan.org/~jdhedden/threads-1.72/threads.pm
71
                            # http://perldoc.perl.org/threads.html
72
use threads::shared;        # http://search.cpan.org/~jdhedden/threads-shared-1.28/shared.pm
73
use Thread::Queue;          # http://search.cpan.org/dist/Thread-Queue-2.11/lib/Thread/Queue.pm
74
use Time::HiRes qw(usleep); # http://search.cpan.org/~jhi/Time-HiRes-1.9719/HiRes.pm
75
if ( $^O =~ /Win32/i )
76
    {
77
    require Win32::SerialPort;  # http://search.cpan.org/dist/Win32-SerialPort
78
    }
79
else
80
    {
81
    require Device::SerialPort; # http://search.cpan.org/~cook/Device-SerialPort-1.04/SerialPort.pm
82
    }
83
 
84
require "libmap.pl";
85
 
86
# Hashes exported to other threads and main-program
87
share (%MkOsd);
88
share (%MkTarget);
89
share (%MkNcDebug);
90
share (%Mk);
91
 
92
# Queue for Sending to MK
93
$MkSendQueue = Thread::Queue->new();
94
 
95
sub MkCommExit()
96
    {  
97
    # close COM port
98
    &MkClose();
99
 
100
    if ( defined threads->self() )
101
        {
102
        threads->exit();
103
        }
104
    exit;
105
    }
106
 
107
 
108
sub MkInit()
109
    {
110
    if ( defined $MkPort )
111
        {
112
        return;   # already open
113
        }
114
 
115
    # open COM-Port             
116
    my $MkComPort = $Cfg->{'mkcomm'}->{'Port'};
117
    undef $MkPort;
118
    if ( $^O =~ m/Win32/ )
119
        {
120
        $MkPort = Win32::SerialPort->new ($MkComPort) || die "Error open $MkComPort\n";
121
        }
122
    else
123
        {
124
        $MkPort = Device::SerialPort->new ($MkComPort) || die "Error open $MkComPort\n";
125
        }
126
    # Set COM parameters
127
    $MkPort->baudrate(57600);
128
    $MkPort->parity("none");
129
    $MkPort->databits(8);
130
    $MkPort->stopbits(1);
131
    $MkPort->handshake('none');
132
    $MkPort->write_settings;
133
 
134
    $MkPort->read_const_time(100); # total = (avg * bytes) + const (ms)
135
    }
136
 
137
# Read one line from MK
138
# Check send-queue
139
sub MkIOLine()
140
    {
141
    # Init serial port
142
    &MkInit();
143
 
144
    my $RxLine = "";           
145
    while ( 1 )
146
        {      
147
        # Check Send-Queue
148
        my $Items = $MkSendQueue->pending();
149
        if ( $Items >= 3 )  # Cmd, Addr, Data
150
            {
151
            my ($Id, $Addr, $Data) = $MkSendQueue->dequeue(3);
152
            &MkSend ($Id, $Addr, $Data);       
153
            }
154
 
155
        # Zeichenweise lesen, blockierend mit Timeout
156
        my ($RxLen, $RxChar) = $MkPort->read(1);  
157
          if ( $RxLen == 1 )
158
              {
159
            if ( "$RxChar" eq "#" )       # 1st char of line
160
                {
161
                $RxLine = "#";
162
                }
163
            elsif ( "$RxChar" eq "\r" )   # last char of line
164
                {
165
                return ($RxLine);
166
                }
167
            else
168
                {
169
                $RxLine = "$RxLine" . "$RxChar";    # collect char
170
                }
171
            }
172
        }
173
    }
174
 
175
 
176
# Read and decode a command from MK
177
# process send queue in &MkIOLine()
178
sub MkIO()
179
    {  
180
    my $RxData = &MkIOLine();     # Blocking Read for complete line
181
 
182
    # Zeile decodieren
183
    if ( substr ($RxData, 0, 1) eq '#' )
184
        {                      
185
        # Zeile decodieren
186
        $Header = substr($RxData, 0, 3);
187
        $Chksum = substr($RxData, -2);
188
        $Data = substr($RxData, 3, length ($RxData) -5);
189
 
190
        # CRC prüfen
191
        if ( &CrcCheck ("$Header" . "$Data", $Chksum ) )
192
            {
193
            # Base64 decodieren
194
            $Data = &Decode64($Data);
195
 
196
            # Daten auswerten und in shared Hash schreiben
197
            if ( &ProcessRx($Header, $Data) )
198
                {
199
                return 1;    # alles OK
200
                }
201
            }
202
        }
203
 
204
    return 0;  # keine Daten empfangen
205
    }
206
 
207
 
208
# Send a command to MK
209
sub MkSend()
210
    {
211
    my ($Id, $Addr, $Data) = @_;
212
 
213
    # Init serial port
214
    &MkInit();
215
 
216
    my $Base64Data = &Encode64($Data);
217
 
218
    my $TxData = "#" . "$Addr" . "$Id" . "$Base64Data";
219
    my $Crc = &Crc($TxData);
220
    my $TxSend  = "$TxData" . "$Crc" . "\r";
221
    $MkPort->write($TxSend);
222
    }
223
 
224
 
225
# close COM-Port
226
sub MkClose()
227
    {
228
    undef $MkPort;
229
    }
230
 
231
 
232
# CRC Prüfung
233
sub CrcCheck ()
234
    {
235
    my ($Data, $Crc) = @_;
236
 
237
    my $Check = &Crc($Data);
238
    if ( $Check ne $Crc )
239
        {
240
        return 0;   # CRC passt nicht
241
        }          
242
    return (1);    # CRC OK
243
    }
244
 
245
 
246
# CRC berechnen
247
sub Crc ()
248
    {
249
    my ($Data) = @_;
250
    my $TmpCrc = 0;
251
    my $Len = length $Data;
252
 
253
    for ($i=0; $i<$Len; $i++)
254
        {
255
        $TmpCrc += ord(substr($Data, $i, 1));
256
        }
257
 
258
    $TmpCrc %= 4096;
259
    my $Crc1 = ord ("=") + $TmpCrc / 64;
260
    my $Crc2 = ord ("=") + $TmpCrc % 64;
261
    $Crc = pack("CC", $Crc1, $Crc2);
262
 
263
    return ($Crc);
264
    }
265
 
266
 
267
# Empfangene Daten decodieren, modifiziertes Base64
268
sub Decode64()
269
    {
270
    my ($DataIn) = @_;
271
 
272
    my $ptrIn  = 0;
273
    my $DataOut  = "";
274
    my $len = length ($DataIn);
275
 
276
    while ( $len > 0 )
277
        {
278
        $a = ord (substr ($DataIn, $ptrIn ++, 1)) - ord ("=");
279
        $b = ord (substr ($DataIn, $ptrIn ++, 1)) - ord ("=");
280
        $c = ord (substr ($DataIn, $ptrIn ++, 1)) - ord ("=");
281
        $d = ord (substr ($DataIn, $ptrIn ++, 1)) - ord ("=");
282
 
283
        $x = ($a << 2) | ($b >> 4);
284
        $y = (($b & 0x0f) << 4) | ($c >> 2);
285
        $z = (($c & 0x03) << 6) | $d;
286
 
287
        foreach $i ( $x, $y, $z )
288
            {
289
            if ( $len--)
290
                {
291
                my $Tmp = pack ('C1', $i);
292
                $DataOut = "$DataOut" . "$Tmp";
293
                }
294
            else
295
                {
296
                last;
297
                }
298
            }
299
        }
300
 
301
    return ($DataOut);
302
    }
303
 
304
 
305
# zu sendende Daten codieren, modifiziertes Base64
306
sub Encode64()
307
    {
308
    my ($Data) = @_;
309
 
310
    my $Length = length $Data;
311
    my $TxBuf = "";
312
    my $ptr = 0;
313
 
314
    while( $Length > 0 )
315
        {
316
        my $a = 0;
317
        my $b = 0;
318
        my $c = 0;
319
        if ($Length) {$a = ord(substr ($Data, $ptr++, $Length--));}
320
        if ($Length) {$b = ord(substr ($Data, $ptr++, $Length--));}
321
        if ($Length) {$c = ord(substr ($Data, $ptr++, $Length--));}
322
 
323
        my $ac = ord("=") +    ($a >> 2);
324
        my $bc = ord("=") + ( (($a & 0x03) << 4) | (($b & 0xf0) >> 4) );
325
        my $cc = ord("=") + ( (($b & 0x0f) << 2) | (($c & 0xc0) >> 6) );
326
        my $dc = ord("=") +    ($c & 0x3f);
327
        $TxBuf = "$TxBuf" . pack ("C4", $ac, $bc, $cc, $dc);
328
        }
329
    return ($TxBuf);
330
    }
331
 
332
 
333
# Empfangenen Datensatz verarbeiten
334
sub ProcessRx()
335
    {
336
    my ($Header, $Data) = @_;
337
 
338
    my $Adr = substr ($Header, 1, 1);    # b=FC, c=NC, d=MK3MAG
339
    my $Id  = substr ($Header, 2, 1);
340
 
341
    if ( $Id eq "O" )
342
        {
343
        #
344
        # OSD-Daten nach %MkOsd einlesen
345
        #
346
 
347
        # Struktur Datensatz:
348
        #     u8  Version                                     // version of the data structure
349
        #     GPS_Pos_t CurrentPosition;
350
        #     GPS_Pos_t TargetPosition;
351
        #     GPS_PosDev_t TargetPositionDeviation;
352
        #     GPS_Pos_t HomePosition;
353
        #     GPS_PosDev_t HomePositionDeviation;
354
        #     u8  WaypointIndex;                              // index of current waypoints running from 0 to WaypointNumber-1
355
        #     u8  WaypointNumber;                             // number of stored waypoints
356
        #     u8  SatsInUse;                                  // no of satellites used for position solution
357
        #     s16 Altimeter;                                  // hight according to air pressure
358
        #     s16 Variometer;                                 // climb(+) and sink(-) rate
359
        #     u16 FlyingTime;                                 // in seconds
360
        #     u8  UBat;                                       // Battery Voltage in 0.1 Volts
361
        #     u16 GroundSpeed;                                // speed over ground in cm/s (2D)
362
        #     s16 Heading;                                    // current flight direction in deg as angle to north
363
        #     s16 CompassHeading;                             // current compass value
364
        #     s8  AngleNick;                                  // current Nick angle in 1°
365
        #     s8  AngleRoll;                                  // current Rick angle in 1°
366
        #     u8  RC_Quality;                                 // RC_Quality
367
        #     u8  MKFlags;                                    // Flags from FC
368
        #     u8  NCFlags;                                    // Flags from NC
369
        #     u8  Errorcode;                                  // 0 --> okay
370
        #     u8  OperatingRadius                             // current operation radius around the Home Position in m
371
        #     s16 TopSpeed;                                   // velocity in vertical direction in cm/s
372
        #     u8  TargetHoldTime;                             // time in s to stay at the given target, counts down to 0 if target has been reached
373
        #     u8  Reserve[4];                                 // for future use
374
 
375
        # GPS_Pos_t:
376
        #     s32 Longitude;   // in 1E-7 deg
377
        #     s32 Latitude;    // in 1E-7 deg
378
        #     s32 Altitude;    // in mm
379
        #     u8  Status;      // validity of data
380
 
381
        # GPS_PosDev_t:
382
        #     s16 Distance;                                   // distance to target in dm
383
        #     s16 Bearing;                                    // course to target in deg      
384
 
385
        # Status:
386
        #     INVALID         = 0
387
        #     NEWDATA         = 1
388
        #     PROCESSED       = 2
389
 
390
        # MKFlags  0x01: MOTOR_RUN, 0x02 FLY, 0x04: CALIBRATE, 0x08: START, 0x10: EMERGENCY_LANDING
391
        # NCFlags  0x01: FLAG_FREE, 0x02: FLAG_PH, 0x04: FLAG_CH, 0x08: FLAG_RANGE_LIMIT
392
        #          0x10: FLAG_NOSERIALLINK, 0x20: FLAG_TARGET_REACHED, FLAG_MANUAL_CONTROL: 0x40
393
        #          0x80: FLAG_8
394
 
395
        lock (%MkOsd);  # until end of Block
396
 
397
        (
398
        $MkOsd{'Version'},
399
        $MkOsd{'CurPos_Lon'},
400
        $MkOsd{'CurPos_Lat'},
401
        $MkOsd{'CurPos_Alt'},
402
        $MkOsd{'CurPos_Stat'},
403
        $MkOsd{'TargetPos_Lon'},
404
        $MkOsd{'TargetPos_Lat'},
405
        $MkOsd{'TargetPos_Alt'},
406
        $MkOsd{'TargetPos_Stat'},
407
        $MkOsd{'TargetPosDev_Dist'},
408
        $MkOsd{'TargetPosDev_Bearing'},
409
        $MkOsd{'HomePos_Lon'},
410
        $MkOsd{'HomePos_Lat'},
411
        $MkOsd{'HomePos_Alt'},
412
        $MkOsd{'HomePos_Stat'},
413
        $MkOsd{'HomePosDev_Dist'},
414
        $MkOsd{'HomePosDev_Bearing'},
415
        $MkOsd{'WaypointIndex'},
416
        $MkOsd{'WaypointNumber'},
417
        $MkOsd{'SatsInUse'},
418
        $MkOsd{'Altimeter'},
419
        $MkOsd{'Variometer'},
420
        $MkOsd{'FlyingTime'},
421
        $MkOsd{'UBat'},
422
        $MkOsd{'GroundSpeed'},
423
        $MkOsd{'Heading'},
424
        $MkOsd{'CompassHeading'},
425
        $MkOsd{'AngleNick'},
426
        $MkOsd{'AngleRoll'},
427
        $MkOsd{'RC_Quality'},
428
        $MkOsd{'MKFlags'},
429
        $MkOsd{'NCFlags'},
430
        $MkOsd{'Errorcode'},
431
        $MkOsd{'OperatingRadius'},
432
        $MkOsd{'TopSpeed'},
433
        $MkOsd{'TargetHoldTime'},
434
        ) = unpack ('ClllClllCsslllCssCCCssSCSssccCCCCCsC', $Data);
435
 
436
        $MkOsd{'CurPos_Lon'}     = sprintf("%.7f", $MkOsd{'CurPos_Lon'} / 10000000);
437
        $MkOsd{'CurPos_Lat'}     = sprintf("%.7f", $MkOsd{'CurPos_Lat'} / 10000000);
438
        $MkOsd{'CurPos_Alt'}     = sprintf("%.3f", $MkOsd{'CurPos_Alt'} / 1000);
439
        $MkOsd{'TargetPos_Lon'}  = sprintf("%.7f", $MkOsd{'TargetPos_Lon'} / 10000000);
440
        $MkOsd{'TargetPos_Lat'}  = sprintf("%.7f", $MkOsd{'TargetPos_Lat'} / 10000000);
441
        $MkOsd{'TargetPos_Alt'}  = sprintf("%.3f", $MkOsd{'TargetPos_Alt'} / 1000);
442
        $MkOsd{'HomePos_Lon'}    = sprintf("%.7f", $MkOsd{'HomePos_Lon'} / 10000000);
443
        $MkOsd{'HomePos_Lat'}    = sprintf("%.7f", $MkOsd{'HomePos_Lat'} / 10000000);
444
        $MkOsd{'HomePos_Alt'}    = sprintf("%.3f", $MkOsd{'HomePos_Alt'} / 1000);
445
        $MkOsd{'UBat'}           = sprintf("%.1f", $MkOsd{'UBat'} / 10);
446
 
447
        # Timestamp, wann der Datensatz geschtieben wurde
448
        $MkOsd{'_Timestamp'} = time;
449
        }
450
 
451
    elsif ( $Id eq "s" )
452
        {
453
        #
454
        # NC Target position in %MkTarget
455
        #
456
        # Datenstruktur:
457
        #    GPS_Pos_t Position;     // the gps position of the waypoint, see ubx.h for details
458
        #    s16 Heading;            // orientation, future implementation
459
        #    u8  ToleranceRadius;    // in meters, if the MK is within that range around the target, then the next target is 
460
        #    u8  HoldTime;           // in seconds, if the MK was once in the tolerance area around a WP,
461
        #                            // this time defines the delay before the next WP is triggered
462
        #    u8  Event_Flag;         // future emplementation
463
        #    u8  reserve[12];        // reserved
464
 
465
        lock (%MkTarget);  # until end of block
466
 
467
        (
468
        $MkTarget{'Pos_Lon'},
469
        $MkTarget{'Pos_Lat'},
470
        $MkTarget{'Pos_Alt'},
471
        $MkTarget{'Pos_Stat'},
472
        $MkTarget{'Heading'},
473
        $MkTarget{'ToleranceRadius'},
474
        $MkTarget{'HoldTime'},
475
        $MkTarget{'EventFlag'},
476
        ) = unpack ('lllCsCCC', $Data);
477
 
478
        $MkTarget{'Pos_Lon'} = sprintf("%.7f", $MkTarget{'Pos_Lon'} / 10000000);
479
        $MkTarget{'Pos_Lat'} = sprintf("%.7f", $MkTarget{'Pos_Lat'} / 10000000);
480
        $MkTarget{'Pos_Alt'} = sprintf("%.3f", $MkTarget{'Pos_Alt'} / 1000);
481
 
482
        # Timestamp, wann der Datensatz geschtieben wurdw
483
        $MkTarget{'_Timestamp'} = time;
484
        }
485
 
486
    elsif ( $Id eq "W" )
487
        {
488
        #
489
        # Request new waypoint
490
        #
491
        # Datenstruktur:
492
        #    u8 Number of waypoint
493
 
494
        ($WpNumber) = unpack ('C', $Data);
495
 
496
        # keine Ahnung wofuer das gut sein soll
497
 
498
        # print "Request new Waypoint Number: $WpNumber\n";
499
 
500
        }
501
 
502
    elsif ( $Id eq "V" )
503
        {
504
        #
505
        # Version
506
        #
507
        # Datenstruktur:
508
        #    u8 SWMajor
509
        #    u8 SWMinor
510
        #    u8 ProtoMajor
511
        #    u8 ProtoMinor
512
        #    u8 SWPatch
513
        #    u8 Reserved[5]
514
 
515
        (
516
        $Mk{'SWMajor'},
517
        $Mk{'SWMinor'},
518
        $Mk{'ProtoMajor'},
519
        $Mk{'ProtoMinor'},
520
        $Mk{'SWPatch'},
521
        ) = unpack ('C5', $Data);
522
 
523
        $Mk{'_Timestamp'} = time;
524
        }
525
 
526
    elsif ( $Id eq "E" )
527
        {
528
        #
529
        # Error Text
530
        #
531
        # Datenstruktur:
532
        #    s8 ErrorMsg[25]
533
 
534
        $Mk{'ErrorMsg'} = unpack ('Z25', $Data);
535
        }
536
 
537
    elsif ( $Id eq "D" )
538
        {
539
        #
540
        # NC Debug %MkNcDebug
541
        #
542
        # Datenstruktur:
543
        #    u8 Digital[2];
544
        #    u16 Analog[32];
545
 
546
        lock (%MkNcDebug);    # until end of block
547
 
548
        (
549
        $MkNcDebug{'Digital_00'},
550
        $MkNcDebug{'Digital_01'},
551
        $MkNcDebug{'Analog_00'},
552
        $MkNcDebug{'Analog_01'},
553
        $MkNcDebug{'Analog_02'},
554
        $MkNcDebug{'Analog_03'},
555
        $MkNcDebug{'Analog_04'},
556
        $MkNcDebug{'Analog_05'},
557
        $MkNcDebug{'Analog_06'},
558
        $MkNcDebug{'Analog_07'},
559
        $MkNcDebug{'Analog_08'},
560
        $MkNcDebug{'Analog_09'},
561
        $MkNcDebug{'Analog_10'},
562
        $MkNcDebug{'Analog_11'},
563
        $MkNcDebug{'Analog_12'},
564
        $MkNcDebug{'Analog_13'},
565
        $MkNcDebug{'Analog_14'},
566
        $MkNcDebug{'Analog_15'},
567
        $MkNcDebug{'Analog_16'},
568
        $MkNcDebug{'Analog_17'},
569
        $MkNcDebug{'Analog_18'},
570
        $MkNcDebug{'Analog_19'},
571
        $MkNcDebug{'Analog_20'},
572
        $MkNcDebug{'Analog_21'},               
573
        $MkNcDebug{'Analog_22'},
574
        $MkNcDebug{'Analog_23'},
575
        $MkNcDebug{'Analog_24'},
576
        $MkNcDebug{'Analog_25'},
577
        $MkNcDebug{'Analog_26'},
578
        $MkNcDebug{'Analog_27'},
579
        $MkNcDebug{'Analog_28'},
580
        $MkNcDebug{'Analog_29'},
581
        $MkNcDebug{'Analog_30'},
582
        $MkNcDebug{'Analog_31'},
583
        ) = unpack ('C2s32', $Data);
584
 
585
        # Timestamp, wann der Datensatz geschrieben wurde
586
        $MkNcDebug{'_Timestamp'} = time;
587
        }
588
 
589
    elsif ( $Id eq "B" )
590
        {
591
        #
592
        # External Control
593
        #
594
        # Datenstruktur:
595
        #    u8 ConfirmFrame;
596
 
597
        my ($ConfirmFrame) = unpack ('C5', $Data);
598
 
599
        }
600
    else
601
        {
602
        print "Unknown Command: $Header $Data\n";
603
        }
604
    }  
605
 
606
 
607
# send Target or Waypoint to MK
608
sub MkFlyTo()
609
    {
610
    my %Param = @_;
611
 
612
    my $x               = $Param{'-x'};
613
    my $y               = $Param{'-y'};
614
    my $Lat             = $Param{'-lat'};
615
    my $Lon             = $Param{'-lon'};
616
    my $Alt             = $Param{'-alt'};
617
    my $Heading         = $Param{'-heading'};
618
    my $ToleranceRadius = $Param{'-toleranceradius'};
619
    my $Holdtime        = $Param{'-holdtime'};
620
    my $EventFlag       = $Param{'-eventflag'};
621
    my $Mode            = $Param{'-mode'};
622
 
623
    if ( $x ne ""  and  $y ne ""  and  $Lat eq ""  and  $Lon eq "" )
624
        {
625
        ($Lat, $Lon) = &MapXY2Gps($x, $y);
626
        }
627
 
628
    if ( $Alt eq "" )             { $Alt = $MkOsd{'CurPos_Alt'}; }
629
    if ( $Heading eq "" )         { $Heading         = $Cfg->{'waypoint'}->{'DefaultHeading'}; }
630
    if ( $ToleranceRadius eq "" ) { $ToleranceRadius = $Cfg->{'waypoint'}->{'DefaultToleranceRadius'}; }
631
    if ( $Holdtime eq "" )        { $Holdtime        = $Cfg->{'waypoint'}->{'DefaultHoldtime'}; }
632
    if ( $EventFlag eq "" )       { $EventFlag       = $Cfg->{'waypoint'}->{'DefaultEventFlag'}; }
633
 
634
    my $Status = 1;     # valid
635
    if ( $Mode =~ /delete/i )
636
        {
637
        $Status = 0;    # invalid -> delete NC WP-List
638
        }
639
 
640
    my $Lat_i = sprintf "%d", $Lat * 10000000;
641
    my $Lon_i = sprintf "%d", $Lon * 10000000;
642
    my $Alt_i = sprintf "%d", $Alt * 1000;
643
 
644
    # Datenstruktur:
645
    #    GPS_Pos_t Position;     // the gps position of the waypoint, see ubx.h for details
646
    #    s16 Heading;            // orientation, future implementation
647
    #    u8  ToleranceRadius;    // in meters, if the MK is within that range around the target, then the next target is 
648
    #    u8  HoldTime;           // in seconds, if the MK was once in the tolerance area around a WP,
649
    #                            // this time defines the delay before the next WP is triggered
650
    #    u8  Event_Flag;         // future emplementation
651
    #    u8  reserve[12];        // reserved
652
 
653
    my $Wp = pack ('lllCsC15',
654
                   $Lon_i,
655
                   $Lat_i,
656
                   $Alt_i,
657
                   $Status,
658
                   $Heading,
659
                   $ToleranceRadius,
660
                   $Holdtime,
661
                   $EventFlag,
662
                   0,0,0,0,0,0,0,0,0,0,0,0,
663
                  );
664
 
665
    if ( $Mode =~ /waypoint/i )
666
        {
667
        $MkSendQueue->enqueue( "w", "$AddrNC", $Wp );
668
        # &MkSend( "w", "$AddrNC", $Wp );
669
        }
670
    elsif ( $Mode =~ /target/i )
671
        {
672
        $MkSendQueue->enqueue( "s", "$AddrNC", $Wp );
673
        # &MkSend( "w", "$AddrNC", $Wp );
674
        }
675
    else
676
        {
677
        # ignore
678
        }
679
 
680
    return 0;
681
    }
682
 
683
 
684
# send External control to MK
685
sub ExternalControl()
686
    {
687
    my %Param = @_;
688
 
689
    my $RemoteButtons = $Param{'-remotebuttons'};
690
    my $Nick = $Param{'-nick'};
691
    my $Roll = $Param{'-roll'};
692
    my $Yaw = $Param{'-yaw'};
693
    my $Gas = $Param{'-gas'};
694
    my $Hight = $Param{'-hight'};
695
    my $Free = $Param{'-free'};
696
    my $Frame = $Param{'-frame'};
697
    my $Config = $Param{'-config'};
698
 
699
    # Datenstruktur:
700
    #    u8      Digital[2];
701
    #    u8      RemoteButtons;
702
    #    s8      Nick;
703
    #    s8      Roll;
704
    #    s8      Yaw;
705
    #    u8      Gas;
706
    #    s8      Height;
707
    #    u8      free;
708
    #    u8      Frame;
709
    #    u8      Config;
710
 
711
    my $Ec = pack ('CCCcccCcCCC',
712
                   0, 0,
713
                   $RemoteButtons,
714
                   $Nick,
715
                   $Roll,
716
                   $Yaw,
717
                   $Gas,
718
                   $Hight,
719
                   $Free,
720
                   $Frame,
721
                   $Config
722
                  );
723
 
724
    $MkSendQueue->enqueue( "b", "$AddrNC", $Ec );
725
    # &MkSend( "b", "$AddrNC", $Ec );
726
 
727
    return 0;
728
    }
729
 
730
 
731
# when called as thread
732
sub MkCommLoop()
733
    {
734
    while (1)
735
       {
736
       &MkIO();
737
       }
738
    }
739
 
740
 
741
#
742
# Hauptprgramm
743
#       
744
 
745
if ( $0 =~ /mkcomm.pl$/i )
746
    {
747
    # Program wurde direkt aufgerufen
748
    &MkCommLoop();
749
 
750
    # should never exit
751
    }
752
 
753
1;
754
 
755
__END__
756