Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

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