File Coverage

blib/lib/Device/Spektrum/Packet.pm
Criterion Covered Total %
statement 41 41 100.0
branch n/a
condition n/a
subroutine 13 13 100.0
pod 1 1 100.0
total 55 55 100.0


line stmt bran cond sub pod time code
1             # Copyright (c) 2015, Timm Murray
2             # All rights reserved.
3             #
4             # Redistribution and use in source and binary forms, with or without
5             # modification, are permitted provided that the following conditions are
6             # met:
7             #
8             # * Redistributions of source code must retain the above copyright
9             # notice, this list of conditions and the following disclaimer.
10             # * Redistributions in binary form must reproduce the above copyright
11             # notice, this list of conditions and the following disclaimer in
12             # the documentation and/or other materials provided with the
13             # distribution.
14             #
15             # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16             # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17             # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18             # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19             # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20             # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21             # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22             # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23             # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24             # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25             # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26             #
27             package Device::Spektrum::Packet;
28             $Device::Spektrum::Packet::VERSION = '0.498225878299312';
29 2     2   22254 use v5.14;
  2         8  
30 2     2   9 use warnings;
  2         5  
  2         52  
31 2     2   863 use Moose;
  2         481787  
  2         14  
32 2     2   14267 use namespace::autoclean;
  2         8516  
  2         15  
33 2     2   140 use base 'Exporter';
  2         4  
  2         147  
34              
35 2     2   11 use constant HEADER => 0x039b;
  2         4  
  2         136  
36             use constant {
37 2         210 THROTTLE_ID => 0x00,
38             AILERON_ID => 0x01,
39             ELEVATOR_ID => 0x02,
40             RUDDER_ID => 0x03,
41             GEAR_ID => 0x04,
42             AUX1_ID => 0x05,
43             AUX2_ID => 0x06,
44 2     2   12 };
  2         10  
45 2     2   10 use constant SPEKTRUM_LOW => 170;
  2         4  
  2         101  
46 2     2   11 use constant SPEKTRUM_HIGH => 853;
  2         2  
  2         124  
47 2         695 use constant SPEKTRUM_MIDDLE => int( ((SPEKTRUM_HIGH - SPEKTRUM_LOW) / 2)
48 2     2   26 + SPEKTRUM_LOW );
  2         4  
49              
50             my @EXPORT_SYM = qw( SPEKTRUM_LOW SPEKTRUM_MIDDLE SPEKTRUM_HIGH );
51             our @EXPORT_OK = @EXPORT_SYM;
52             our @EXPORT = @EXPORT_SYM;
53              
54              
55             has $_ => (
56             is => 'ro',
57             isa => 'Int',
58             required => 1,
59             ) for qw{
60             throttle aileron elevator rudder gear aux1 aux2
61             };
62              
63             has 'field_order' => (
64             is => 'ro',
65             isa => 'ArrayRef[Str]',
66             default => sub {[qw{
67             throttle
68             aileron
69             elevator
70             rudder
71             gear
72             aux1
73             aux2
74             }]},
75             );
76             has 'field_id' => (
77             is => 'ro',
78             isa => 'HashRef[Str]',
79             default => sub {{
80             throttle => 'THROTTLE_ID',
81             aileron => 'AILERON_ID',
82             elevator => 'ELEVATOR_ID',
83             rudder => 'RUDDER_ID',
84             gear => 'GEAR_ID',
85             aux1 => 'AUX1_ID',
86             aux2 => 'AUX2_ID',
87             }},
88             );
89              
90              
91             sub encode_packet
92             {
93 2     2 1 462 my ($self) = @_;
94             my $packet = pack( 'n*',
95             HEADER,
96             map {
97 14         514 my $field_id = $self->field_id->{$_};
98 14         596 $self->_encode( $self->$field_id, $self->$_ );
99 2         5 } @{ $self->field_order },
  2         87  
100             );
101 2         10 return $packet;
102             }
103              
104              
105             sub _encode
106             {
107 14     14   27 my ($self, $id, $val) = @_;
108 14         22 my $encoded_val = 0xFFFF & (($id << 10) | $val);
109 14         41 return $encoded_val;
110             }
111              
112              
113 2     2   11 no Moose;
  2         7  
  2         11  
114             __PACKAGE__->meta->make_immutable;
115             1;
116             __END__
117              
118              
119             =head1 NAME
120              
121             Device::Spektrum::Packet - Represent a packet of Spektrum data
122              
123             =head1 SYNOPSIS
124              
125             use Device::Spektrum::Packet;
126             my $packet = Device::Spektrum::Packet->new({
127             throttle => 170,
128             aileron => 200,
129             elevator => 250,
130             rudder => 800,
131             gear => SPEKTRUM_LOW,
132             aux1 => SPEKTRUM_MIDDLE,
133             aux2 => SPEKTRUM_HIGH,
134              
135             # Optional; may correct problems with buggy implementations
136             field_order => [qw(
137             throttle
138             aileron
139             elevator
140             rudder
141             gear
142             aux1
143             aux2
144             )],
145             });
146            
147             my $encoded_packet = $packet->encode_packet;
148              
149             =head1 DESCRIPTION
150              
151             Represents a single packet of Spektrum data.
152              
153             =head1 ATTRIBUTES
154              
155             =over 4
156              
157             =item * throttle
158              
159             =item * aileron
160              
161             =item * elevator
162              
163             =item * rudder
164              
165             =item * gear
166              
167             =item * aux1
168              
169             =item * aux2
170              
171             =back
172              
173             Each attribute takes an integer. These are typically in between 170 (exported as
174             C<SPEKTRUM_LOW>) and 853 (C<SPEKTRUM_HIGH>). The protocol is technically capable of
175             values between 0 and 1023, but servos and flight controllers may not be well-behaved outside
176             the typical range.
177              
178             There is also a C<field_order> parameter, which shouldn't be necessary, because the
179             protocol uses a few identifier bits for each channel. However, some implementations out
180             there hardcode the channel order to what common Spektrum recievers put out, so you may need
181             to work around them with this parameter.
182              
183             =head1 METHODS
184              
185             =head2 encode_packet
186              
187             Return a byte string containing the encoded packet.
188              
189             =head1 LICENSE
190              
191             Copyright (c) 2015, Timm Murray
192             All rights reserved.
193              
194             Redistribution and use in source and binary forms, with or without modification, are
195             permitted provided that the following conditions are met:
196              
197             * Redistributions of source code must retain the above copyright notice, this list of
198             conditions and the following disclaimer.
199             * Redistributions in binary form must reproduce the above copyright notice, this list of
200             conditions and the following disclaimer in the documentation and/or other materials
201             provided with the distribution.
202              
203             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
204             OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
205             MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
206             COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
207             EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
208             SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
209             HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
210             TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
211             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
212              
213             =cut