File Coverage

blib/lib/Rinchi/CIGIPP/StartOfFrame.pm
Criterion Covered Total %
statement 69 105 65.7
branch 12 34 35.2
condition 5 21 23.8
subroutine 19 21 90.4
pod 17 17 100.0
total 122 198 61.6


line stmt bran cond sub pod time code
1             #
2             # Rinchi Common Image Generator Interface for Perl
3             # Class Identifier: f78b1860-200e-11de-bdc6-001c25551abc
4             # Author: Brian M. Ames
5             #
6              
7             package Rinchi::CIGIPP::StartOfFrame;
8              
9 1     1   30 use 5.006;
  1         3  
  1         92  
10 1     1   8 use strict;
  1         3  
  1         38  
11 1     1   6 use warnings;
  1         2  
  1         41  
12 1     1   6 use Carp;
  1         2  
  1         1875  
13              
14             require Exporter;
15              
16             our @ISA = qw(Exporter);
17              
18             # Items to export into callers namespace by default. Note: do not export
19             # names by default without a very good reason. Use EXPORT_OK instead.
20             # Do not simply export all your public functions/methods/constants.
21              
22             # This allows declaration use Rinchi::CIGI::AtmosphereControl ':all';
23             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
24             # will save memory.
25             our %EXPORT_TAGS = ( 'all' => [ qw(
26            
27             ) ] );
28              
29             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
30              
31             our @EXPORT = qw(
32            
33             );
34              
35             our $VERSION = '0.01';
36              
37             # Preloaded methods go here.
38              
39             =head1 NAME
40              
41             Rinchi::CIGIPP::StartOfFrame - Perl extension for the Common Image Generator
42             Interface - Start Of Frame data packet.
43             data packet.
44             =head1 SYNOPSIS
45              
46             use Rinchi::CIGIPP::StartOfFrame;
47             my $start_of_frame = Rinchi::CIGIPP::StartOfFrame->new();
48              
49             $packet_type = $start_of_frame->packet_type();
50             $packet_size = $start_of_frame->packet_size();
51             $major_version = $start_of_frame->major_version();
52             $database_number = $start_of_frame->database_number(65);
53             $ig_status = $start_of_frame->ig_status(190);
54             $minor_version = $start_of_frame->minor_version();
55             $earth_reference_model = $start_of_frame->earth_reference_model(Rinchi::CIGIPP->HostDefined);
56             $timestamp_valid = $start_of_frame->timestamp_valid(Rinchi::CIGIPP->Invalid);
57             $ig_mode = $start_of_frame->ig_mode(Rinchi::CIGIPP->Reset);
58             $magic_number = $start_of_frame->magic_number();
59             $ig_frame_number = $start_of_frame->ig_frame_number(44786);
60             $timestamp = $start_of_frame->timestamp(37374);
61             $last_host_frame_number = $start_of_frame->last_host_frame_number(55338);
62              
63             =head1 DESCRIPTION
64              
65             The Start of Frame packet is used to signal the beginning of a new frame. Every
66             IG-to-Host message must contain exactly one Start of Frame packet. This packet
67             must be the first packet in the message.
68              
69             =head2 EXPORT
70              
71             None by default.
72              
73             #==============================================================================
74              
75             =item new $start_of_frame = Rinchi::CIGIPP::StartOfFrame->new()
76              
77             Constructor for Rinchi::StartOfFrame.
78              
79             =cut
80              
81             sub new {
82 1     1 1 141 my $class = shift;
83 1   33     7 $class = ref($class) || $class;
84              
85 1         27 my $self = {
86             '_Buffer' => '',
87             '_ClassIdent' => 'f78b1860-200e-11de-bdc6-001c25551abc',
88             '_Pack' => 'CCCcCCSIIII',
89             '_Swap1' => 'CCCcCCvVVVV',
90             '_Swap2' => 'CCCcCCnNNNN',
91             'packetType' => 101,
92             'packetSize' => 24,
93             'majorVersion' => 3,
94             'databaseNumber' => 0,
95             '_igStatus' => 0,
96             '_bitfields1' => 48, # Includes bitfields minorVersion, earthReferenceModel, timestampValid, and igMode.
97             'minorVersion' => 3,
98             'earthReferenceModel' => 0,
99             'timestampValid' => 0,
100             'igMode' => 0,
101             'magicNumber' => 32768,
102             'igFrameNumber' => 0,
103             'timestamp' => 0,
104             'lastHostFrameNumber' => 0,
105             '_unused65' => 0,
106             };
107              
108 1 50       6 if (@_) {
109 0 0       0 if (ref($_[0]) eq 'ARRAY') {
    0          
110 0         0 $self->{'_Buffer'} = $_[0][0];
111             } elsif (ref($_[0]) eq 'HASH') {
112 0         0 foreach my $attr (keys %{$_[0]}) {
  0         0  
113 0 0       0 $self->{"_$attr"} = $_[0]->{$attr} unless ($attr =~ /^_/);
114             }
115             }
116             }
117              
118 1         3 bless($self,$class);
119 1         11 return $self;
120             }
121              
122             #==============================================================================
123              
124             =item sub packet_type()
125              
126             $value = $start_of_frame->packet_type();
127              
128             Data Packet Identifier.
129              
130             This attribute identifies this data packet as the Start of Frame packet. The
131             value of this attribute must be 101.
132              
133             =cut
134              
135             sub packet_type() {
136 1     1 1 8 my ($self) = @_;
137 1         9 return $self->{'packetType'};
138             }
139              
140             #==============================================================================
141              
142             =item sub packet_size()
143              
144             $value = $start_of_frame->packet_size();
145              
146             Data Packet Size.
147              
148             This attribute indicates the number of bytes in this data packet. The value of
149             this attribute must be 24.
150              
151             =cut
152              
153             sub packet_size() {
154 1     1 1 6 my ($self) = @_;
155 1         4 return $self->{'packetSize'};
156             }
157              
158             #==============================================================================
159              
160             =item sub major_version()
161              
162             $value = $start_of_frame->major_version();
163              
164             Major Version.
165              
166             This attribute indicates the major version of the CIGI interface that is
167             currently being used by the IG. The Host can use this number to determine
168             concurrency. The value of this attribute must be 3.
169              
170             =cut
171              
172             sub major_version() {
173 1     1 1 6 my ($self) = @_;
174 1         4 return $self->{'majorVersion'};
175             }
176              
177             #==============================================================================
178              
179             =item sub database_number([$newValue])
180              
181             $value = $start_of_frame->database_number($newValue);
182              
183             Database Number.
184              
185             This attribute is used to indicate to the Host which database is currently in
186             use and if that database is being loaded into primary memory.
187              
188             The Host will set the Database Number attribute of the IG Control packet to
189             direct the IG to begin loading the corresponding database. The IG will indicate
190             that the database is being loaded by negating the value and placing it in the
191             Database Number attribute of the Start of Frame packet. The Host will then
192             acknowledge this change by setting the Database Number attribute of the IG
193             Control packet to zero (0).
194              
195             When the database load is complete and after the Host has acknowledged the
196             database change, the IG will set this attribute to the positive database
197             number. The IG can now be considered mission-ready.
198              
199             If the Host requests a database that does not exist or cannot be loaded, the IG
200             will set this attribute to -128.
201              
202             Zero (0) is used to indicate that the IG controls the database loading.
203              
204             =cut
205              
206             sub database_number() {
207 1     1 1 6 my ($self,$nv) = @_;
208 1 50       4 if (defined($nv)) {
209 1         3 $self->{'databaseNumber'} = $nv;
210             }
211 1         4 return $self->{'databaseNumber'};
212             }
213              
214             #==============================================================================
215              
216             =item sub ig_status([$newValue])
217              
218             $value = $start_of_frame->ig_status($newValue);
219              
220             IG Status Code.
221              
222             This attribute indicates the error status of the IG.
223              
224             Error codes are IG-specific. Refer to the appropriate IG documentation for a
225             list of error codes.
226              
227             If more than one error is detected, the IG will report the one with the highest
228             priority.
229             If additional error reporting must be performed, the IG should be placed in
230             Debug mode via the IG Control packet's IG Mode attribute or the IG's user interface.
231              
232             =cut
233              
234             sub ig_status() {
235 1     1 1 5 my ($self,$nv) = @_;
236 1 50       11 if (defined($nv)) {
237 1         3 $self->{'_igStatus'} = $nv;
238             }
239 1         3 return $self->{'_igStatus'};
240             }
241              
242             #==============================================================================
243              
244             =item sub minor_version()
245              
246             $value = $start_of_frame->minor_version();
247              
248             Minor Version.
249              
250             This attribute indicates the minor version of the CIGI interface that is
251             currently being used by the IG. The Host can use this number to determine concurrency.
252              
253             =cut
254              
255             sub minor_version() {
256 1     1 1 6 my ($self) = @_;
257 1         5 return (($self->{'_bitfields1'} & 0xF0) >> 4);
258             }
259              
260             #==============================================================================
261              
262             =item sub earth_reference_model([$newValue])
263              
264             $value = $start_of_frame->earth_reference_model($newValue);
265              
266             Earth Reference Model.
267              
268             This attribute indicates whether the IG is using a custom (Host-defined) Earth
269             Reference Model (ERM) or the default WGS 84 reference ellipsoid for coordinate
270             conversion calculations. Host-defined ERMs are defined with the Earth Reference
271             Model Definition packet (see Section 4.1.19).
272              
273             If the Host defines an ERM that the IG cannot support, this value is set to WGS
274             84 (0). In such cases, the Host must redefine the ERM or use the WGS 84
275             reference ellipsoid.
276              
277             WGS84 0
278             HostDefined 1
279              
280             =cut
281              
282             sub earth_reference_model() {
283 1     1 1 3 my ($self,$nv) = @_;
284 1 50       4 if (defined($nv)) {
285 1 50 33     10 if (($nv==0) or ($nv==1)) {
286 1         2 $self->{'earthReferenceModel'} = $nv;
287 1         3 $self->{'_bitfields1'} |= ($nv << 3) &0x08;
288             } else {
289 0         0 carp "earth_reference_model must be 0 (WGS84), or 1 (HostDefined).";
290             }
291             }
292 1         5 return (($self->{'_bitfields1'} & 0x08) >> 3);
293             }
294              
295             #==============================================================================
296              
297             =item sub timestamp_valid([$newValue])
298              
299             $value = $start_of_frame->timestamp_valid($newValue);
300              
301             Timestamp Valid.
302              
303             This attribute indicates whether the Timestamp attribute contains a valid value.
304              
305             Invalid 0
306             Valid 1
307              
308             =cut
309              
310             sub timestamp_valid() {
311 1     1 1 3 my ($self,$nv) = @_;
312 1 50       6 if (defined($nv)) {
313 1 50 33     6 if (($nv==0) or ($nv==1)) {
314 1         3 $self->{'timestampValid'} = $nv;
315 1         3 $self->{'_bitfields1'} |= ($nv << 2) &0x04;
316             } else {
317 0         0 carp "timestamp_valid must be 0 (Invalid), or 1 (Valid).";
318             }
319             }
320 1         3 return (($self->{'_bitfields1'} & 0x04) >> 2);
321             }
322              
323             #==============================================================================
324              
325             =item sub ig_mode([$newValue])
326              
327             $value = $start_of_frame->ig_mode($newValue);
328              
329             IG Mode.
330              
331             This attribute indicates the current IG mode. It may be one of the following
332             values:
333             Reset/Standby – This is the IG's initial state upon start-up. When set to this
334             mode, the IG will initialize/reinitialize the simulation. All entities that
335             were instantiated during a previous mission will be destroyed. All
336             environmental properties, views, components, and sensors will revert to their
337             default settings. Any Host-defined rates, trajectories, and collision detection
338             segments and volumes will be removed. The IG will only send the Start of Frame
339             data packet to the Host and will ignore Host inputs except for the IG Mode
340             attribute of the IG Control data packet. The IG will remain in this mode until
341             directed otherwise by the Host or the IG's user interface.
342              
343             Operate – This is the normal real-time operating mode for the IG. All packets
344             issued by the Host will be processed by the IG. The IG should not perform
345             diagnostics in this mode.
346              
347             Debug – This mode is similar to the Operate mode but provides data and/or error
348             logging and other debugging features to aid integration or troubleshooting of
349             the Host and IG interface. Because of the overhead of these debugging features,
350             the IG may not always operate in a hard real-time fashion.
351              
352             Offline Maintenance – In this mode, the IG ignores all data from the Host and
353             sends only Start of Frame packets. This mode can be activated only from the IG.
354             Because the IG Control packets from the Host are ignored by the IG, the IG must
355             be placed into Reset/Standby mode before the Host can initiate further mode changes.
356              
357             Reset 0
358             Standby 1
359             Operate 1
360             Debug 2
361             OfflineMaintenance 3
362              
363             =cut
364              
365             sub ig_mode() {
366 1     1 1 3 my ($self,$nv) = @_;
367 1 50       6 if (defined($nv)) {
368 1 50 33     8 if (($nv==0) or ($nv==1) or ($nv==1) or ($nv==2) or ($nv==3)) {
      33        
      0        
      0        
369 1         2 $self->{'igMode'} = $nv;
370 1         3 $self->{'_bitfields1'} |= $nv &0x03;
371             } else {
372 0         0 carp "ig_mode must be 0 (Reset), 1 (Standby), 1 (Operate), 2 (Debug), or 3 (OfflineMaintenance).";
373             }
374             }
375 1         12 return ($self->{'_bitfields1'} & 0x03);
376             }
377              
378             #==============================================================================
379              
380             =item sub magic_number()
381              
382             $value = $start_of_frame->magic_number();
383              
384             Byte Swap Magic Number.
385              
386             This attribute is used by the Host to determine whether it needs to byte-swap
387             incoming data. Refer to the CIGI ICD, Section 2.1.4 for details on this mechanism.
388              
389             =cut
390              
391             sub magic_number() {
392 1     1 1 6 my ($self) = @_;
393 1         3 return $self->{'magicNumber'};
394             }
395              
396             #==============================================================================
397              
398             =item sub ig_frame_number([$newValue])
399              
400             $value = $start_of_frame->ig_frame_number($newValue);
401              
402             IG Frame Number.
403              
404             This attribute uniquely identifies an IG data frame. The IG should increment
405             this value by one (1) for each successive message.
406              
407             =cut
408              
409             sub ig_frame_number() {
410 1     1 1 6 my ($self,$nv) = @_;
411 1 50       5 if (defined($nv)) {
412 1         3 $self->{'igFrameNumber'} = $nv;
413             }
414 1         3 return $self->{'igFrameNumber'};
415             }
416              
417             #==============================================================================
418              
419             =item sub timestamp([$newValue])
420              
421             $value = $start_of_frame->timestamp($newValue);
422              
423             Timestamp.
424              
425             This attribute indicates the number of 10μs “ticks” since some initial
426             reference time. This will enable the IG to correct for latencies as described
427             in the CIGI ICD, Section 2.1.1.1.
428              
429             The 10μs unit allows the simulation to run for approximately 12 hours before a
430             timestamp rollover occurs. The Host software should contain logic to detect and
431             correct for rollover.
432              
433             The use of this attribute is required for asynchronous operation.
434              
435             The use of this attribute is optional for synchronous operation. If this
436             attribute does not contain a valid timestamp, the Timestamp Valid attribute
437             should be set to zero (0).
438              
439             =cut
440              
441             sub timestamp() {
442 1     1 1 6 my ($self,$nv) = @_;
443 1 50       3 if (defined($nv)) {
444 1         2 $self->{'timestamp'} = $nv;
445             }
446 1         4 return $self->{'timestamp'};
447             }
448              
449             #==============================================================================
450              
451             =item sub last_host_frame_number([$newValue])
452              
453             $value = $start_of_frame->last_host_frame_number($newValue);
454              
455             Last Host Frame Number.
456              
457             This attribute contains the value of the Host Frame Number attribute in the
458             last IG Control packet received from the Host. This attribute serves as an
459             acknowledgement that the IG received the last message.
460              
461             =cut
462              
463             sub last_host_frame_number() {
464 1     1 1 6 my ($self,$nv) = @_;
465 1 50       10 if (defined($nv)) {
466 1         3 $self->{'lastHostFrameNumber'} = $nv;
467             }
468 1         4 return $self->{'lastHostFrameNumber'};
469             }
470              
471             #==========================================================================
472              
473             =item sub pack()
474              
475             $value = $start_of_frame->pack();
476              
477             Returns the packed data packet.
478              
479             =cut
480              
481             sub pack($) {
482 1     1 1 5 my $self = shift ;
483            
484 1         9 $self->{'_Buffer'} = CORE::pack($self->{'_Pack'},
485             $self->{'packetType'},
486             $self->{'packetSize'},
487             $self->{'majorVersion'},
488             $self->{'databaseNumber'},
489             $self->{'_igStatus'},
490             $self->{'_bitfields1'}, # Includes bitfields minorVersion, earthReferenceModel, timestampValid, and igMode.
491             $self->{'magicNumber'},
492             $self->{'igFrameNumber'},
493             $self->{'timestamp'},
494             $self->{'lastHostFrameNumber'},
495             $self->{'_unused65'},
496             );
497              
498 1         5 return $self->{'_Buffer'};
499             }
500              
501             #==========================================================================
502              
503             =item sub unpack()
504              
505             $value = $start_of_frame->unpack();
506              
507             Unpacks the packed data packet.
508              
509             =cut
510              
511             sub unpack($) {
512 0     0 1   my $self = shift @_;
513              
514 0 0         if (@_) {
515 0           $self->{'_Buffer'} = shift @_;
516             }
517 0           my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k) = CORE::unpack($self->{'_Pack'},$self->{'_Buffer'});
518 0           $self->{'packetType'} = $a;
519 0           $self->{'packetSize'} = $b;
520 0           $self->{'majorVersion'} = $c;
521 0           $self->{'databaseNumber'} = $d;
522 0           $self->{'_igStatus'} = $e;
523 0           $self->{'_bitfields1'} = $f; # Includes bitfields minorVersion, earthReferenceModel, timestampValid, and igMode.
524 0           $self->{'magicNumber'} = $g;
525 0           $self->{'igFrameNumber'} = $h;
526 0           $self->{'timestamp'} = $i;
527 0           $self->{'lastHostFrameNumber'} = $j;
528 0           $self->{'_unused65'} = $k;
529              
530 0           $self->{'minorVersion'} = $self->minor_version();
531 0           $self->{'earthReferenceModel'} = $self->earth_reference_model();
532 0           $self->{'timestampValid'} = $self->timestamp_valid();
533 0           $self->{'igMode'} = $self->ig_mode();
534              
535 0           return $self->{'_Buffer'};
536             }
537              
538             #==========================================================================
539              
540             =item sub byte_swap()
541              
542             $obj_name->byte_swap();
543              
544             Byte swaps the packed data packet.
545              
546             =cut
547              
548             sub byte_swap($) {
549 0     0 1   my $self = shift @_;
550            
551 0 0         if (@_) {
552 0           $self->{'_Buffer'} = shift @_;
553             } else {
554 0           $self->unpack();
555             }
556 0           my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k) = CORE::unpack($self->{'_Swap1'},$self->{'_Buffer'});
557              
558 0           $self->{'_Buffer'} = CORE::pack($self->{'_Swap2'},$a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k);
559 0           $self->unpack();
560              
561 0           return $self->{'_Buffer'};
562             }
563              
564             1;
565             __END__