Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
825 - 1
#!/usr/bin/perl
2
#!/usr/bin/perl -d:ptkdb
3
 
4
###############################################################################
5
#
6
# libmap.pl -  Conversion GPS and Map-X/Y Coordinates
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
#
41
# 2009-10-10 0.0.1 rw created
42
# 2009-12-05 0.0.2 rw check, if no WP is defined
43
# 2010-01-27 0.0.3 rw UsedCapacity, Current
44
#                     switch of logging while sim is active
45
# 2010-09-15 0.0.4 rw Check invalid $MkSim{'Target_Heading'} >= 360
46
#
47
###############################################################################
48
 
49
$Version{'libmksim.pl'} = "0.0.4 - 2010-09-15";
50
 
51
my $Simulator = "OFF";
52
 
53
sub MkSim()
54
    {
55
    # switch off logging
56
    $LogQueue->enqueue( "OFF" );
57
 
58
    my $popup = $main->Toplevel();
59
    $popup->title("MikroKopter Simulator");
60
 
61
    # Catch delete window event and exit sim
62
    $popup->protocol( 'WM_DELETE_WINDOW' => sub
63
        {
64
        &CbSimStop();
65
        $popup->destroy();
66
        });
67
 
68
 
69
    my $menu_bar = $popup->Menu;
70
    $popup->optionAdd("*tearOff", "false");
71
    $popup->configure ('-menu' => $menu_bar);
72
 
73
    my $menu_action = $menu_bar->cascade('-label' => "Action");
74
    $menu_action->command('-label' => "3D Fix",
75
                          '-command' => [\&CbSim3DFix ],
76
                        );
77
    $menu_action->command('-label' => "Make MK Fly",
78
                          '-command' => [\&CbSimMkFly ],
79
                        );
80
    $menu_action->separator;                                   
81
    $menu_action->command('-label' => "Start Simulator",
82
                          '-command' => [\&CbSimStart ],
83
                         );
84
    $menu_action->command('-label' => "Stop Simulator",
85
                          '-command' => [\&CbSimStop ],
86
                        );
87
 
88
    my $frame = $popup->Frame() -> pack('-side' => 'top',
89
                                        '-expand' => 'y',
90
                                        '-anchor' => 's',
91
                                        '-padx' => 5,
92
                                        '-pady' => 5,
93
                                        );
94
 
95
    my $button = $popup->Frame() -> pack('-side' => 'bottom',
96
                                          '-expand' => 'y',
97
                                          '-anchor' => 's',
98
                                          '-padx' => 5,
99
                                          '-pady' => 5,
100
                                          );
101
 
102
     # Exit Button
103
     $button->Button('-text'    => 'Exit',
104
                     '-width' => 10,
105
                     '-command' => sub
106
                {
107
                &CbSimStop();
108
                $popup->destroy();
109
                }) -> pack( '-anchor' => 's',
110
                            '-padx' => 5,
111
                            '-pady' => 5,
112
                          );
113
 
114
 
115
    # Tabs erstellen
116
    my $book = $frame->NoteBook()->pack( -fill=>'both', -expand=>1 );
117
 
118
    #
119
    # Tab: GPS
120
    #
121
    my $GpsTab = $book->add( "GPS", -label=>"GPS" );
122
 
123
    # canvas grid position
124
    my $GpsRow = 0;
125
    my $GpsCol = 0;
126
    my $GpsRowMap = $GpsRow + 1;
127
    my $GpsColMap = $GpsCol;
128
    my $GpsRowAlt = $GpsRow + 2;
129
    my $GpsColAlt = $GpsCol;
130
    my $GpsRowStat = $GpsRow + 4;
131
    my $GpsColStat = $GpsCol;
132
    my $GpsRowSats = $GpsRow + 5;
133
    my $GpsColSats = $GpsCol;
134
 
135
    # Create and scale Photo
136
    my $ImgWidth = "$Cfg->{'map'}->{'SimImageSize'}" || 300;
137
    my $Factor = $MapSizeX / $ImgWidth;
138
 
139
    my $Img1 = $popup->Photo( 'SimFoto',
140
                              '-file' => "$Cfg->{'map'}->{'MapDir'}/$Map{'File'}",
141
                            );
142
    my $Img2 = $popup->Photo ('SimFoto-Resized');
143
    $Img2->copy ( $Img1,
144
                  '-shrink',
145
                  '-subsample' => $Factor, $Factor,
146
                 );
147
 
148
    my $ImgWidth  = $Img2->width;
149
    my $ImgHeight = $Img2->height;
150
    my $ImgScaleX = $MapSizeX / $ImgWidth;
151
    my $ImgScaleY = $MapSizeY / $ImgHeight;
152
 
153
    # display scaled Photo on canvas
154
    my $canvas = $GpsTab->Canvas( '-width'  => $ImgWidth,
155
                                  '-height' => $ImgHeight,
156
                                ) -> grid (-row    => $GpsRowMap,
157
                                           -column => $GpsColMap,
158
                                           -columnspan => 4,
159
                                          );
160
    $canvas->createImage( 0, 0,
161
                          '-tags'   => 'SimMap',
162
                          '-anchor' => 'nw',
163
                          '-image'  => $Img2,
164
                         );
165
 
166
    # Circle-Icon for MK, Target, Home
167
    my $Dia = 14;
168
    my $ImgSplit = $ImgWidth / 4;
169
    my $MkX     = $ImgSplit - $Dia/2;
170
    my $MkY     = $ImgHeight / 2 + $Dia/2;
171
    my $TargetX = $ImgSplit * 2  - $Dia/2;
172
    my $TargetY = $ImgHeight / 2 + $Dia/2;
173
    my $HomeX   = $ImgSplit * 3  - $Dia/2;
174
    my $HomeY   = $ImgHeight / 2 + $Dia/2;
175
 
176
 
177
    ($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'})       = &MapXY2Gps ($MkX * $ImgScaleX, $MkY * $ImgScaleY);
178
    ($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'}) = &MapXY2Gps ($TargetX * $ImgScaleX, $TargetY * $ImgScaleY);
179
    ($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'})     = &MapXY2Gps ($HomeX * $ImgScaleX, $HomeY * $ImgScaleY);
180
 
181
    $canvas->createOval ( $HomeX, $HomeY, $HomeX + $Dia, $HomeY + $Dia,
182
                         '-tags'    => "SimHome",
183
                         '-fill'    => $Cfg->{'mkcockpit'}->{'ColorHomeLine'},
184
                         '-outline' => "white",
185
                       );
186
    $canvas->createOval ( $TargetX, $TargetY, $TargetX + $Dia, $TargetY + $Dia,
187
                         '-tags'    => "SimTarget",
188
                         '-fill'    => $Cfg->{'mkcockpit'}->{'ColorTargetLine'},
189
                         '-outline' => "white",
190
                       );
191
    $canvas->createOval ( $MkX, $MkY, $MkX + $Dia, $MkY + $Dia,
192
                         '-tags'    => "SimMk",
193
                         '-fill'    => $Cfg->{'mkcockpit'}->{'ColorMkSatGood'},
194
                         '-outline' => "white",
195
                       );
196
 
197
    # GPS Alt MK
198
    $GpsTab->Label(-text => , $Translate{'CurPos_Alt'},
199
                  )->grid ('-row'    => $GpsRowAlt,
200
                           '-column' => $GpsColAlt,
201
                           '-sticky' => 'w',
202
                         );
203
 
204
    $MkOsd{'CurPos_Alt'} = 0;
205
    $scCurPos_Alt = $GpsTab->Scale(
206
                    '-orient'       => 'vertical',
207
                    '-from'         => 400,
208
                    '-to'           => 0,
209
                    '-tickinterval' => 50,
210
                    '-resolution'   => 1,
211
                    '-label'        => "",
212
                    '-font'         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
213
                    '-length'       => 150,
214
                    '-width'        => 15,
215
                    '-variable'     => \$MkOsd{'CurPos_Alt'},
216
                   )->grid ('-row'    => $GpsRowAlt+1,
217
                            '-column' => $GpsColAlt,
218
                           );
219
 
220
    $MkOsd{'CurPos_Stat'} = 0;
221
    $cbCurPos_Stat = $GpsTab->Checkbutton(
222
                      -text => $Translate{'CurPos_Stat'},
223
                      -offvalue  => 0x00,
224
                      -onvalue   => 0x01,
225
                      -variable  => \$MkOsd{'CurPos_Stat'},
226
                     )->grid (-row    => $GpsRowStat,
227
                              -column => $GpsColStat,
228
                              -columnspan => 2,
229
                              -sticky => 'w',
230
                             );
231
 
232
    # Altimeter
233
    $GpsTab->Label(-text => , $Translate{'Altimeter'},
234
                  )->grid ('-row'    => $GpsRowAlt,
235
                           '-column' => $GpsColAlt +1,
236
                         );
237
 
238
    $MkOsd{'Altimeter'} = 0;
239
    $scAltimeter = $GpsTab->Scale(
240
                  -orient       => 'vertical',
241
                  -from         => 8000,
242
                  -to           => 0,
243
                  -tickinterval => 2000,
244
                  -resolution   => 1,
245
                  -label        => "",
246
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
247
                  -length       => 150,
248
                  -width        => 15,
249
                  -variable     => \$MkOsd{'Altimeter'},
250
                  )->grid (-row    => $GpsRowAlt +1,
251
                           -column => $GpsColAlt +1,
252
                          );
253
 
254
    # GPS Alt Target
255
    $GpsTab->Label(-text => , $Translate{'TargetPos_Alt'},
256
                  )->grid ('-row'    => $GpsRowAlt,
257
                           '-column' => $GpsColAlt +2,
258
                         );
259
 
260
    $MkOsd{'TargetPos_Alt'} = 0;
261
    $scTargetPos_Alt = $GpsTab->Scale(
262
                    '-orient'       => 'vertical',
263
                    '-from'         => 400,
264
                    '-to'           => 0,
265
                    '-tickinterval' => 50,
266
                    '-resolution'   => 1,
267
                    '-label'        => "",
268
                    '-font'         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
269
                    '-length'       => 150,
270
                    '-width'        => 15,
271
                    '-variable'     => \$MkOsd{'TargetPos_Alt'},
272
                   )->grid ('-row'    => $GpsRowAlt +1,
273
                            '-column' => $GpsColAlt +2,
274
                           );
275
 
276
    $MkOsd{'TargetPos_Stat'} = 0;
277
    $cbTargetPos_Stat = $GpsTab->Checkbutton(-text => $Translate{'TargetPos_Stat'},
278
                      -offvalue  => 0x00,
279
                      -onvalue   => 0x01,
280
                      -variable  => \$MkOsd{'TargetPos_Stat'},
281
                     )->grid (-row    => $GpsRowStat,
282
                              -column => $GpsColStat +2,
283
                             );
284
 
285
    # GPS Alt Home
286
    $GpsTab->Label(-text => , $Translate{'HomePos_Alt'},
287
                  )->grid ('-row'    => $GpsRowAlt,
288
                           '-column' => $GpsColAlt +3,
289
                         );
290
 
291
    $MkOsd{'HomePos_Alt'} = 0;
292
    $scHomePos_Alt = $GpsTab->Scale(
293
                    '-orient'       => 'vertical',
294
                    '-from'         => 400,
295
                    '-to'           => 0,
296
                    '-tickinterval' => 50,
297
                    '-resolution'   => 1,
298
                    '-label'        => "",
299
                    '-font'         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
300
                    '-length'       => 150,
301
                    '-width'        => 15,
302
                    '-variable'     => \$MkOsd{'HomePos_Alt'},
303
                   )->grid ('-row'    => $GpsRowAlt +1,
304
                            '-column' => $GpsColAlt +3,
305
                           );
306
 
307
    $MkOsd{'HomePos_Stat'} = 0;
308
    $cbHomePos_Stat = $GpsTab->Checkbutton(
309
                      -text => "Home Status",   # $Translate{'HomePos_Stat'},
310
                      -offvalue  => 0x00,
311
                      -onvalue   => 0x01,
312
                      -variable  => \$MkOsd{'HomePos_Stat'},
313
                     )->grid (-row    => $GpsRowStat,
314
                              -column => $GpsColStat +3,
315
                             );
316
 
317
    # Sats in Use
318
    $MkOsd{'SatsInUse'} = 0;
319
    $scSatsInUse = $GpsTab->Scale(
320
                   '-orient'       => 'horizontal',
321
                   '-from'         => 0,
322
                   '-to'           => 12,
323
                   '-resolution'   => 1,
324
                   '-tickinterval' => 1,
325
                   '-label'        => $Translate{'SatsInUse'},
326
                   '-font'         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
327
                   '-length'       => 300,
328
                   '-width'        => 15,
329
                   '-variable'     => \$MkOsd{'SatsInUse'},
330
                   )->grid (-row    => $GpsRowSats,
331
                            -column => $GpsColSats,
332
                            -columnspan => 4,
333
                           );
334
 
335
     # Balloon
336
     my $simballoon = $popup->Balloon();
337
     $simballoon->attach($canvas,
338
                         '-balloonposition' => 'mouse',
339
                         '-state' => 'balloon',
340
                         '-msg' => { 'SimMk'     => 'MikroKopter',
341
                                     'SimTarget' => 'Target',
342
                                     'SimHome'   => 'Home',
343
                                   },
344
                        );
345
 
346
    # Mouse button 1 for MK
347
    my $MkOldx = 0;
348
    my $MkOldy = 0;
349
 
350
    # Pick MK
351
    $canvas->bind('SimMk' => '<Button-1>' => sub
352
        {
353
        # prepare to move
354
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
355
        $MkOldx = $x;
356
        $MkOldy = $y;
357
        });
358
 
359
    # Move Mk
360
    $canvas->bind('SimMk' => '<Button1-Motion>' => sub
361
        {
362
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
363
        my $id      = $canvas->find('withtag', 'current');
364
 
365
        my $Dia2 = $Dia/2;
366
        if ( $x < $Dia2 ) { $x = $Dia2 };
367
        if ( $y < $Dia2 ) { $y = $Dia2 };
368
        if ( $x > $ImgWidth - $Dia2 ) { $x = $ImgWidth - $Dia2 };
369
        if ( $y > $ImgHeight - $Dia2) { $y = $ImgHeight - $Dia2 };
370
 
371
        $canvas->move($id => $x - $MkOldx, $y - $MkOldy);
372
        $MkOldx = $x;
373
        $MkOldy = $y;
374
 
375
        ($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}) = &MapXY2Gps ($x * $ImgScaleX, $y * $ImgScaleY);
376
        });
377
 
378
    # Mouse button 1 for Target
379
    my $TargetOldx = 0;
380
    my $TargetOldy = 0;
381
 
382
    # Pick Target
383
    $canvas->bind('SimTarget' => '<Button-1>' => sub
384
        {
385
        # prepare to move
386
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
387
        $TargetOldx = $x;
388
        $TargetOldy = $y;
389
        });
390
 
391
    # Move Target
392
    $canvas->bind('SimTarget' => '<Button1-Motion>' => sub
393
        {
394
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
395
        my $id      = $canvas->find('withtag', 'current');
396
 
397
        my $Dia2 = $Dia/2;
398
        if ( $x < $Dia2 ) { $x = $Dia2 };
399
        if ( $y < $Dia2 ) { $y = $Dia2 };
400
        if ( $x > $ImgWidth - $Dia2 ) { $x = $ImgWidth - $Dia2 };
401
        if ( $y > $ImgHeight - $Dia2) { $y = $ImgHeight - $Dia2 };
402
 
403
        $canvas->move($id => $x - $TargetOldx, $y - $TargetOldy);
404
        $TargetOldx = $x;
405
        $TargetOldy = $y;
406
 
407
        ($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'}) = &MapXY2Gps ($x * $ImgScaleX, $y * $ImgScaleY);
408
        });
409
 
410
    # Mouse button 1 for Home
411
    my $HomeOldx = 0;
412
    my $HomeOldy = 0;
413
 
414
    # Pick Home
415
    $canvas->bind('SimHome' => '<Button-1>' => sub
416
        {
417
        # prepare to move
418
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
419
        $HomeOldx = $x;
420
        $HomeOldy = $y;
421
        });
422
 
423
    # Move Home
424
    $canvas->bind('SimHome' => '<Button1-Motion>' => sub
425
        {
426
        my ($x, $y) = ($Tk::event->x, $Tk::event->y);
427
        my $id      = $canvas->find('withtag', 'current');
428
 
429
        my $Dia2 = $Dia/2;
430
        if ( $x < $Dia2 ) { $x = $Dia2 };
431
        if ( $y < $Dia2 ) { $y = $Dia2 };
432
        if ( $x > $ImgWidth - $Dia2 ) { $x = $ImgWidth - $Dia2 };
433
        if ( $y > $ImgHeight - $Dia2) { $y = $ImgHeight - $Dia2 };
434
 
435
        $canvas->move($id => $x - $HomeOldx, $y - $HomeOldy);
436
        $HomeOldx = $x;
437
        $HomeOldy = $y;
438
 
439
        ($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'}) = &MapXY2Gps ($x * $ImgScaleX, $y * $ImgScaleY);
440
        });
441
 
442
 
443
    #
444
    # Tab: Navigation
445
    #
446
    my $NavTab = $book->add( "Navigation", -label=>"Navigation", );
447
 
448
    my $Row = 0;
449
    my $Col = 0;
450
 
451
    # Waypoint Index
452
    $MkOsd{'WaypointIndex'} = 0;
453
    $scWaypointIndex = $NavTab->Scale(
454
                   -orient       => 'horizontal',
455
                   -from         => 0,
456
                   -to           => 20,
457
                   -tickinterval => 5,
458
                   -resolution   => 1,
459
                   -label        => $Translate{'WaypointIndex'},
460
                   -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
461
                   -length       => 300,
462
                   -width        => 15,
463
                   -variable     => \$MkOsd{'WaypointIndex'},
464
                   )->grid (-row    => $Row + 1,
465
                            -column => $Col,
466
                           );
467
 
468
    # Waypoint Number
469
    $MkOsd{'WaypointNumber'} = 0;
470
    $scWaypointNumber = $NavTab->Scale(
471
                   -orient       => 'horizontal',
472
                   -from         => 0,
473
                   -to           => 20,
474
                   -tickinterval => 5,
475
                   -resolution   => 1,
476
                   -label        => $Translate{'WaypointNumber'},
477
                   -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
478
                   -length       => 300,
479
                   -width        => 15,
480
                   -variable     => \$MkOsd{'WaypointNumber'},
481
                   )->grid (-row    => $Row + 2,
482
                            -column => $Col,
483
                           );
484
 
485
    # Operating Radius
486
    $MkOsd{'OperatingRadius'} = 250;
487
    $scOperatingRadius = $NavTab->Scale(
488
                   -orient       => 'horizontal',
489
                   -from         => 0,
490
                   -to           => 250,
491
                   -tickinterval => 50,
492
                   -resolution   => 1,
493
                   -label        => "$Translate{'OperatingRadius'} (m)",
494
                   -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
495
                   -length       => 300,
496
                   -width        => 15,
497
                   -variable     => \$MkOsd{'OperatingRadius'},
498
                   )->grid (-row    => $Row + 3,
499
                            -column => $Col,
500
                           );
501
 
502
    # TargetPosDev_Dist
503
    $MkOsd{'TargetPosDev_Dist'} = 250;
504
    $scTargetPosDev_Dist = $NavTab->Scale(
505
                   -orient       => 'horizontal',
506
                   -from         => 0,
507
                   -to           => 500,
508
                   -tickinterval => 100,
509
                   -resolution   => 1,
510
                   -label        => "$Translate{'TargetPosDev_Dist'} (dm)",
511
                   -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
512
                   -length       => 300,
513
                   -width        => 15,
514
                   -variable     => \$MkOsd{'TargetPosDev_Dist'},
515
                   )->grid (-row    => $Row + 4,
516
                            -column => $Col,
517
                           );
518
 
519
 
520
    #
521
    # Tab: MK
522
    #
523
    my $MkTab = $book->add( "MikroKopter1", -label=>"MikroKopter 1", );
524
 
525
    my $Row = 0;
526
    my $Col = 0;
527
 
528
    # Battery
529
    $MkOsd{'UBat'} = 12.6;
530
    $scUBat = $MkTab->Scale(
531
                   -orient       => 'horizontal',
532
                   -from         => 6.0,
533
                   -to           => 18.0,
534
                   -tickinterval => 2,
535
                   -resolution   => 0.1,
536
                   -label        => "$Translate{'UBat'} (V)",
537
                   -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
538
                   -length       => 200,
539
                   -width        => 15,
540
                   -variable     => \$MkOsd{'UBat'},
541
                   )->grid (-row    => $Row,
542
                            -column => $Col,
543
                           );
544
 
545
    # RC Quality
546
    $MkOsd{'RC_Quality'} = 190;
547
    $scRC_Quality = $MkTab->Scale(
548
                  -orient       => 'horizontal',
549
                  -from         => 0,
550
                  -to           => 200,
551
                  -tickinterval => 50,
552
                  -resolution   => 1,
553
                  -label        => $Translate{'RC_Quality'},
554
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
555
                  -length       => 200,
556
                  -width        => 15,
557
                  -variable     => \$MkOsd{'RC_Quality'},
558
                  )->grid (-row    => $Row +1,
559
                           -column => $Col,
560
                          );
561
    # CompassHeading
562
    $MkOsd{'CompassHeading'} = 0;
563
    $scCompassHeading = $MkTab->Scale(
564
                  -orient       => 'horizontal',
565
                  -from         => 0,
566
                  -to           => 360,
567
                  -tickinterval => 45,
568
                  -resolution   => 1,
569
                  -label        => $Translate{'CompassHeading'},
570
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
571
                  -length       => 200,
572
                  -width        => 15,
573
                  -variable     => \$MkOsd{'CompassHeading'},
574
                  )->grid (-row    => $Row +2,
575
                           -rowspan => 4,
576
                           -column => $Col,
577
                          );
578
 
579
    # GPS Groundspeed
580
    $MkOsd{'GroundSpeed'} = 0;
581
    $scGroundSpeed = $MkTab->Scale(
582
                  -orient       => 'horizontal',
583
                  -from         => 0,
584
                  -to           => 1000,
585
                  -tickinterval => 200,
586
                  -resolution   => 1,
587
                  -label        => "$Translate{'GroundSpeed'} (dm/s)",
588
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
589
                  -length       => 200,
590
                  -width        => 15,
591
                  -variable     => \$MkOsd{'GroundSpeed'},
592
                  )->grid (-row    => $Row + 6,
593
                           -rowspan => 4,
594
                           -column => $Col,
595
                          );
596
 
597
    # GPS Speed North
598
    $MkNcDebug{'Analog_21'} = 0;
599
    $scAnalog_21 = $MkTab->Scale(
600
                  -orient       => 'horizontal',
601
                  -from         => -1000,
602
                  -to           => 1000,
603
                  -tickinterval => 400,
604
                  -resolution   => 1,
605
                  -label        => "$Translate{'Analog_21'} (dm/s)",
606
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
607
                  -length       => 200,
608
                  -width        => 15,
609
                  -variable     => \$MkNcDebug{'Analog_21'},
610
                  )->grid (-row    => $Row + 10,
611
                           -rowspan => 4,
612
                           -column => $Col,
613
                          );
614
 
615
    # GPS Speed East
616
    $MkNcDebug{'Analog_22'} = 0;
617
    $scAnalog_22 = $MkTab->Scale(
618
                  -orient       => 'horizontal',
619
                  -from         => -1000,
620
                  -to           => 1000,
621
                  -tickinterval => 400,
622
                  -resolution   => 1,
623
                  -label        => "$Translate{'Analog_22'} (dm/s)",
624
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
625
                  -length       => 200,
626
                  -width        => 15,
627
                  -variable     => \$MkNcDebug{'Analog_22'},
628
                  )->grid (-row    => $Row + 14,
629
                           -rowspan => 4,
630
                           -column => $Col,
631
                          );
632
 
633
    # Variometer
634
    $MkOsd{'Variometer'} = 0;
635
    $scVariometer = $MkTab->Scale(
636
                  -orient       => 'vertical',
637
                  -from         => 30,
638
                  -to           => -30,
639
                  -tickinterval => 10,
640
                  -resolution   => 1,
641
                  -label        => $Translate{'Variometer'},
642
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
643
                  -length       => 100,
644
                  -width        => 15,
645
                  -variable     => \$MkOsd{'Variometer'},
646
                  )->grid (-row    => $Row,
647
                           -rowspan => 2,
648
                           -column => $Col + 1,
649
                          );
650
 
651
    my $DataLink = 1;
652
    $cbDataLink = $MkTab->Checkbutton(
653
                        -text => $Translate{'DataLink'},
654
                        -offvalue => 0x00,
655
                        -onvalue  => 0x01,
656
                        -variable  => \$DataLink,
657
                       )->grid (-row    => $Row + 2,
658
                                -column => $Col +1,
659
                                -sticky=>'w',
660
                                -ipadx => 10,
661
                               );
662
 
663
    $MkTab->Label(-text => "",                    # space
664
                 )->grid (-row    => $Row +3,
665
                          -column => $Col +1,
666
                          -sticky=>'w',
667
                          -ipadx => 10,
668
                         );
669
 
670
    $MkTab->Label(-text => "$Translate{'MKFlags'}: --------",
671
                 )->grid (-row    => $Row +4,
672
                          -column => $Col +1,
673
                          -sticky=>'w',
674
                          -ipadx => 10,
675
                         );
676
    my $MkMotorRun = 0;
677
    $cbMkMotorRun = $MkTab->Checkbutton(
678
                        -text => $Translate{'MkMotorRun'},
679
                        -offvalue => 0x00,
680
                        -onvalue  => 0x01,
681
                        -variable  => \$MkMotorRun,
682
                       )->grid (-row    => $Row + 5,
683
                                -column => $Col +1,
684
                                -sticky=>'w',
685
                                -ipadx => 10,
686
                               );
687
    my $MkFly = 0;
688
    $cbMkFly = $MkTab->Checkbutton(
689
                      -text => $Translate{'MkFly'},
690
                      -variable  => \$MkFly,
691
                      -offvalue => 0x00,
692
                      -onvalue  => 0x02,
693
                     )->grid (-row    => $Row + 6,
694
                              -column => $Col +1,
695
                                -sticky=>'w',
696
                                -ipadx => 10,
697
                             );
698
    my $MkCalibrate = 0;
699
    $cbMkCalibrate = $MkTab->Checkbutton(
700
                      -text => $Translate{'MkCalibrate'},
701
                      -variable  => \$MkCalibrate,
702
                      -offvalue => 0x00,
703
                      -onvalue  => 0x04,
704
                     )->grid (-row    => $Row + 7,
705
                              -column => $Col +1,
706
                               -sticky=>'w',
707
                               -ipadx => 10,
708
                             );
709
    my $MkStart = 0;
710
    $cbMkStart = $MkTab->Checkbutton(
711
                      -text => $Translate{'MkStart'},
712
                      -variable  => \$MkStart,
713
                      -offvalue => 0x00,
714
                      -onvalue  => 0x08,
715
                     )->grid (-row    => $Row + 8,
716
                              -column => $Col + 1,
717
                              -sticky=>'w',
718
                              -ipadx => 10,
719
                             );
720
    my $MkEmergency = 0;
721
    $cbMkEmergency = $MkTab->Checkbutton(
722
                      -text => $Translate{'MkEmergency'},
723
                      -variable  => \$MkEmergency,
724
                      -offvalue => 0x00,
725
                      -onvalue  => 0x10,
726
                     )->grid (-row    => $Row + 9,
727
                              -column => $Col + 1,
728
                              -sticky=>'w',
729
                              -ipadx => 10,
730
                             );
731
 
732
    $MkTab->Label(-text => "$Translate{'NCFlags'}: --------",
733
                 )->grid (-row    => $Row + 10,
734
                          -column => $Col + 1,
735
                           -sticky=>'w',
736
                           -ipadx => 10,
737
                         );
738
    my $NcFlagFree = 0;
739
    $cbNcFlagFree = $MkTab->Checkbutton(
740
                      -text => $Translate{'NcFlagFree'},
741
                      -offvalue => 0x00,
742
                      -onvalue  => 0x01,
743
                      -variable  => \$NcFlagFree,
744
                     )->grid (-row    => $Row + 11,
745
                              -column => $Col + 1,
746
                              -sticky=>'w',
747
                              -ipadx => 10,
748
                             );
749
    my $NcFlagPH = 0;
750
    $cbNcFlagPH = $MkTab->Checkbutton(
751
                      -text => $Translate{'NcFlagPH'},
752
                      -offvalue => 0x00,
753
                      -onvalue  => 0x02,
754
                      -variable  => \$NcFlagPH,
755
                     )->grid (-row    => $Row + 12,
756
                              -column => $Col + 1,
757
                              -sticky=>'w',
758
                              -ipadx => 10,
759
                             );
760
    my $NcFlagCH = 0;
761
    $cbNcFlagCH = $MkTab->Checkbutton(
762
                      -text => $Translate{'NcFlagCH'},
763
                      -offvalue => 0x00,
764
                      -onvalue  => 0x04,
765
                      -variable  => \$NcFlagCH,
766
                     )->grid (-row    => $Row + 13,
767
                              -column => $Col + 1,
768
                              -sticky=>'w',
769
                              -ipadx => 10,
770
                             );
771
    my $NcFlagRangeLimit = 0;
772
    $cbNcFlagRangeLimit = $MkTab->Checkbutton(
773
                      -text => $Translate{'NcFlagRangeLimit'},
774
                      -offvalue => 0x00,
775
                      -onvalue  => 0x08,
776
                      -variable  => \$NcFlagRangeLimit,
777
                     )->grid (-row    => $Row + 14,
778
                              -column => $Col + 1,
779
                              -sticky=>'w',
780
                              -ipadx => 10,
781
                             );
782
    my $NcFlagNoSerialLink = 0;
783
    $cbNcFlagNoSerialLink = $MkTab->Checkbutton(
784
                      -text => $Translate{'NcFlagNoSerialLink'},
785
                      -offvalue => 0x00,
786
                      -onvalue  => 0x10,
787
                      -variable  => \$NcFlagNoSerialLink,
788
                     )->grid (-row    => $Row + 15,
789
                              -column => $Col + 1,
790
                              -sticky=>'w',
791
                              -ipadx => 10,
792
                             );
793
    my $NcFlagTargetReached = 0;
794
    $cbNcFlagTargetReached = $MkTab->Checkbutton(
795
                      -text => $Translate{'NcFlagTargetReached'},
796
                      -offvalue => 0x00,
797
                      -onvalue  => 0x20,
798
                      -variable  => \$NcFlagTargetReached,
799
                     )->grid (-row    => $Row + 16,
800
                              -column => $Col + 1,
801
                              -sticky=>'w',
802
                              -ipadx => 10,
803
                             );
804
 
805
    my $NcFlagManualControl = 0;
806
    $cbNcFlagManualControl = $MkTab->Checkbutton(
807
                      -text => $Translate{'NcFlagManualControl'},
808
                      -offvalue => 0x00,
809
                      -onvalue  => 0x40,
810
                      -variable  => \$NcFlagManualControl
811
                     )->grid (-row    => $Row + 17,
812
                              -column => $Col + 1,
813
                              -sticky=>'w',
814
                              -ipadx => 10,
815
                             );
816
 
817
    #
818
    # Tab: MK 2
819
    #
820
    my $Mk2Tab = $book->add( "MikroKopter2", -label=>"MikroKopter 2", );
821
 
822
    my $Row = 0;
823
    my $Col = 0;
824
 
825
    # Current
826
    $MkOsd{'Current'} = 0;
827
    $scCurrent = $Mk2Tab->Scale(
828
                  -orient       => 'horizontal',
829
                  -from         => 0,
830
                  -to           => 50,
831
                  -tickinterval => 10,
832
                  -resolution   => 1,
833
                  -label        => "$Translate{'Current'} (A)",
834
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
835
                  -length       => 300,
836
                  -width        => 15,
837
                  -variable     => \$MkOsd{'Current'},
838
                  )->grid (-row    => $Row,
839
                           -column => $Col,
840
                          );
841
 
842
    # Used Capacity
843
    $MkOsd{'UsedCapacity'} = 0;
844
    $scUsedCapacity = $Mk2Tab->Scale(
845
                  -orient       => 'horizontal',
846
                  -from         => 0,
847
                  -to           => 5000,
848
                  -tickinterval => 1000,
849
                  -resolution   => 50,
850
                  -label        => "$Translate{'UsedCapacity'} (mAh)",
851
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
852
                  -length       => 300,
853
                  -width        => 15,
854
                  -variable     => \$MkOsd{'UsedCapacity'},
855
                  )->grid (-row    => $Row + 1,
856
                           -column => $Col,
857
                          );
858
 
859
    #
860
    # Tab: Simulator
861
    #
862
    my $MkTab = $book->add( "Simulator", -label=>"Simulator", );
863
 
864
    my $Row = 0;
865
    my $Col = 0;
866
 
867
    # Speed
868
    my $SimSpeed = 20;  # km/h
869
    $scSimSpeed = $MkTab->Scale(
870
                  -orient       => 'horizontal',
871
                  -from         => 0,
872
                  -to           => 50,
873
                  -tickinterval => 5,
874
                  -resolution   => 1,
875
                  -label        => "Speed (km/h)",
876
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
877
                  -length       => 300,
878
                  -width        => 15,
879
                  -variable     => \$SimSpeed,
880
                  )->grid (-row    => $Row,
881
                           -column => $Col,
882
                          );
883
 
884
    # Acceleration
885
    my $SimAcc = 10;  # m/s**2
886
    $scSimAcc = $MkTab->Scale(
887
                  -orient       => 'horizontal',
888
                  -from         => 0,
889
                  -to           => 30,
890
                  -tickinterval => 5,
891
                  -resolution   => 0.5,
892
                  -label        => "Acceleration (m/s**2)",
893
                  -font         => '-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1',
894
                  -length       => 300,
895
                  -width        => 15,
896
                  -variable     => \$SimAcc,
897
                  )->grid (-row    => $Row +1,
898
                           -column => $Col,
899
                          );
900
 
901
 
902
    my $Speed  = 0;  # Current Mk Speed
903
    my $SpeedN = 0;  # Speed North
904
    my $SpeedE = 0;  # Speed East
905
 
906
 
907
    #
908
    # Timer
909
    #
910
    my $SimTimebase = 100;    # Simulator Timebase in ms
911
    $popup->repeat ($SimTimebase, sub
912
        {
913
        lock (%MkOsd);              # until end of block
914
 
915
        $MkOsd{'MKFlags'} = $MkMotorRun | $MkFly | $MkCalibrate | $MkStart | $MkEmergency;
916
        $MkOsd{'NCFlags'} = $NcFlagFree | $NcFlagPH | $NcFlagCH | $NcFlagRangeLimit |
917
                            $NcFlagNoSerialLink | $NcFlagTargetReached | $NcFlagManualControl;
918
 
919
        # Calibration sequence
920
        if ( $CalibCount > 0 )
921
            {
922
            $CalibCount ++;
923
            }
924
        if ( $CalibCount > 2 * 1000 / $SimTimebase )  # 2s
925
            {
926
            $cbMkCalibrate-> deselect();
927
            $cbMkStart->deselect();
928
 
929
            $cbMkMotorRun->select();
930
            $cbMkFly->select();
931
 
932
            $CalibCount = 0;
933
            }
934
 
935
        #
936
        # Simulator
937
        #
938
        if ( $Simulator =~ /ON/i and
939
             $MkSim{'Target_Lat'} ne ""  and $MkSim{'Target_Lon'} ne "" )
940
            {
941
            # Set Target-Pos
942
            $MkOsd{'TargetPos_Lat'} = $MkSim{'Target_Lat'};
943
            $MkOsd{'TargetPos_Lon'} = $MkSim{'Target_Lon'};
944
            $MkOsd{'TargetPos_Alt'} = $MkSim{'Target_Alt'};
945
            $MkOsd{'TargetPos_Stat'} = 1;
946
 
947
            my ($HomeDist, $HomeBearing) = &MapGpsTo($MkOsd{'HomePos_Lat'},   $MkOsd{'HomePos_Lon'},
948
                                                     $MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'} );
949
            if ( $HomeDist > $MkOsd{'OperatingRadius'} )
950
                {
951
                # Target entsprechend Operation Radius neu berechnen
952
                $HomeDist = $MkOsd{'OperatingRadius'};
953
                ($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'}) = &MapGpsAt($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'},
954
                                                                               $HomeDist, $HomeBearing);
955
                $cbNcFlagRangeLimit->select;
956
                }
957
            else
958
                {
959
                $cbNcFlagRangeLimit->deselect;
960
                }
961
 
962
            #
963
            # Mk physics
964
            # Move MK to Target with constant acceleration
965
            #
966
            my ($Dist, $Bearing) = &MapGpsTo($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'},
967
                                             $MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'} );
968
 
969
            $MkOsd{'TargetPosDev_Dist'} = $Dist * 10;  # in dm
970
            $MkOsd{'TargetPosDev_Bearing'} = $Bearing;
971
 
972
            my $AccN = $SimAcc * cos (deg2rad $Bearing);     # Acceleration North
973
            my $AccE = $SimAcc * sin (deg2rad $Bearing);     # Acceleration East
974
            my $t = $SimTimebase / 1000;
975
 
976
            $SpeedN = $SpeedN + $AccN * $t;  # Speed North
977
            $SpeedE = $SpeedE + $AccE * $t;  # Speed East
978
            $Speed  = sqrt ($SpeedN * $SpeedN + $SpeedE * $SpeedE);
979
 
980
            if ( $Speed >= $SimSpeed/3.6 )
981
                {
982
                # Limit maximum Speed
983
                my $SpeedBearing = rad2deg (atan2 ($SpeedE, $SpeedN));
984
 
985
                $SpeedN = $SimSpeed/3.6 * cos (deg2rad $SpeedBearing);
986
                $SpeedE = $SimSpeed/3.6 * sin (deg2rad $SpeedBearing);
987
                $Speed = $SimSpeed/3.6;
988
                }
989
 
990
            my $BreakDist = 5;
991
            if ( $Dist <= $BreakDist )
992
                {
993
                $Speed = $SimSpeed/3.6 - $SimSpeed/3.6 * (1 - $Dist/$BreakDist);
994
                my $SpeedBearing = rad2deg (atan2 ($SpeedE, $SpeedN));
995
                $SpeedN = $Speed * cos (deg2rad $SpeedBearing);
996
                $SpeedE = $Speed * sin (deg2rad $SpeedBearing);
997
                $AccN = 0;
998
                $AccE = 0;
999
                }
1000
 
1001
            # Distance to go in this loop
1002
            my $GoDistN = $SpeedN * $t + 0.5 * $AccN * $t * $t;
1003
            my $GoDistE = $SpeedE * $t + 0.5 * $AccE * $t * $t;
1004
            my $GoDist = sqrt ( $GoDistN * $GoDistN + $GoDistE * $GoDistE);
1005
            my $GoBearing = rad2deg (atan2 ($GoDistE, $GoDistN));
1006
 
1007
            if ($GoDist > 0 )
1008
                {
1009
                ($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'}) = &MapGpsAt($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'},
1010
                                                                         $GoDist, $GoBearing);            
1011
                }
1012
 
1013
            if ( $Dist < $MkSim{'Target_ToleranceRadius'} )
1014
                {
1015
                $cbNcFlagTargetReached -> select();
1016
                }
1017
            else
1018
                {
1019
                $cbNcFlagTargetReached -> deselect();
1020
                }
1021
 
1022
            # GPS Groundspeed, North, East
1023
            $MkOsd{'GroundSpeed'}  = $Speed * 100;  # dm/s
1024
            $MkNcDebug{'Analog_21'} = $SpeedN * 100;
1025
            $MkNcDebug{'Analog_22'} = $SpeedE * 100;
1026
 
1027
            # Heading
1028
            if ( $MkSim{'Target_Heading'} != 0  and  $MkSim{'Target_Heading'} < 360 )
1029
                {
1030
                $scCompassHeading -> set($MkSim{'Target_Heading'});
1031
                }
1032
 
1033
            }
1034
 
1035
        # update display
1036
        $scAnalog_21 -> set($MkNcDebug{'Analog_21'});
1037
        $scAnalog_22 -> set($MkNcDebug{'Analog_22'});
1038
        $scTargetPos_Alt -> set($MkOsd{'TargetPos_Alt'});
1039
        $scTargetPosDev_Dist -> set ($MkOsd{'TargetPosDev_Dist'});
1040
        $scGroundSpeed -> set($MkOsd{'GroundSpeed'});
1041
        $scWaypointNumber -> set ($MkOsd{'WaypointNumber'});
1042
        $scWaypointIndex -> set ($MkOsd{'WaypointIndex'});
1043
 
1044
        # move MK symbol on canvas
1045
        my ($x, $y) = &MapGps2XY ($MkOsd{'CurPos_Lat'}, $MkOsd{'CurPos_Lon'});
1046
        $x = $x / $ImgScaleX;
1047
        $y = $y / $ImgScaleY;
1048
        $canvas->coords ('SimMk', $x, $y, $x + $Dia, $y + $Dia);
1049
 
1050
        # move Home symbol on canvas
1051
        my ($x, $y) = &MapGps2XY ($MkOsd{'HomePos_Lat'}, $MkOsd{'HomePos_Lon'});
1052
        $x = $x / $ImgScaleX;
1053
        $y = $y / $ImgScaleY;
1054
        $canvas->coords ('SimHome', $x, $y, $x + $Dia, $y + $Dia);
1055
 
1056
        # move Target symbol on canvas
1057
        my ($x, $y) = &MapGps2XY ($MkOsd{'TargetPos_Lat'}, $MkOsd{'TargetPos_Lon'});
1058
        $x = $x / $ImgScaleX;
1059
        $y = $y / $ImgScaleY;
1060
        $canvas->coords ('SimTarget', $x, $y, $x + $Dia, $y + $Dia);
1061
 
1062
        if ( $DataLink)
1063
            {
1064
            # Timestamp, wann der Datensatz geschrieben wurde
1065
            $MkOsd{'_Timestamp'} = time;
1066
            }
1067
 
1068
        });
1069
    }
1070
 
1071
# Make MK Fly
1072
sub CbSimMkFly
1073
    {
1074
    $scWaypointIndex->set(5);
1075
    $scWaypointNumber->set(10);
1076
    $cbNcFlagCH->select();
1077
 
1078
    # start calibration sequence
1079
    $cbMkCalibrate-> select();
1080
    $cbMkStart->select();
1081
    $CalibCount = 1;
1082
    }
1083
 
1084
 
1085
# 3D Fix
1086
sub CbSim3DFix
1087
    {
1088
    my $Alt = 50;
1089
    $scCurPos_Alt->set($Alt);
1090
    $scAltimeter->set($Alt * $Cfg->{'map'}->{'AltFactor'});
1091
 
1092
    $scSatsInUse->set(10);
1093
    $cbCurPos_Stat->select();
1094
    $cbTargetPos_Stat->select();
1095
    $cbHomePos_Stat->select();
1096
 
1097
    # Set Home-Pos to Cur-Pos
1098
    $MkOsd{'HomePos_Lat'} = $MkOsd{'CurPos_Lat'};
1099
    $MkOsd{'HomePos_Lon'} = $MkOsd{'CurPos_Lon'};
1100
 
1101
    $scGroundSpeed->set(400);
1102
    $scAnalog_21->set(10);
1103
    $scAnalog_22->set(10);
1104
    }
1105
 
1106
# Switch Simulator ON
1107
sub CbSimStart
1108
    {
1109
    $Simulator = "ON";
1110
 
1111
    # Only one Target from Player
1112
    $MkOsd{'WaypointNumber'} = 1;
1113
    $MkOsd{'WaypointIndex'} = 0;
1114
    }
1115
 
1116
 
1117
# Switch Simulator OFF
1118
sub CbSimStop
1119
    {
1120
    $Simulator = "OFF";
1121
 
1122
    # switch on logging
1123
    $MkOsd{'_Timestamp'} = 0;
1124
    $LogQueue->enqueue( "LOG" );
1125
    }
1126
 
1127
 
1128
1;
1129
 
1130
__END__