File Coverage

blib/lib/Device/WebIO/Firmata.pm
Criterion Covered Total %
statement 15 67 22.3
branch 0 12 0.0
condition n/a
subroutine 5 19 26.3
pod 0 14 0.0
total 20 112 17.8


line stmt bran cond sub pod time code
1             # Copyright (c) 2014 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 met:
6             #
7             # * Redistributions of source code must retain the above copyright notice,
8             # this list of conditions and the following disclaimer.
9             # * Redistributions in binary form must reproduce the above copyright
10             # notice, this list of conditions and the following disclaimer in the
11             # documentation and/or other materials provided with the distribution.
12             #
13             # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14             # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15             # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16             # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
17             # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18             # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19             # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20             # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21             # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22             # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23             # POSSIBILITY OF SUCH DAMAGE.
24             package Device::WebIO::Firmata;
25             $Device::WebIO::Firmata::VERSION = '0.002';
26             # ABSTRACT: Interface between Device::WebIO and Device::Firmata (Arduino)
27 1     1   512 use v5.12;
  1         2  
  1         32  
28 1     1   485 use Moo;
  1         10857  
  1         5  
29 1     1   1524 use namespace::clean;
  1         8920  
  1         5  
30 1     1   551 use Device::Firmata ();
  1         4626  
  1         23  
31 1     1   6 use Device::Firmata::Constants qw{ :all };
  1         1  
  1         1045  
32              
33             has '_firmata' => (
34             is => 'ro',
35             );
36             has 'input_pin_count' => (
37             is => 'ro',
38             # Max GPIO pins Firmata supports. Would be nice if it had a way to
39             # detect how many pins are actually on the device.
40             default => sub { 128 },
41             );
42             has 'output_pin_count' => (
43             is => 'ro',
44             default => sub { 128 },
45             );
46             has 'pwm_pin_count' => (
47             is => 'ro',
48             default => sub { 128 },
49             );
50             has 'pin_desc' => (
51             is => 'ro',
52             # TODO this is based on the Uno's pin header. Would be nice to have
53             # a configurable option for different boards.
54             default => sub {[qw{
55             SCL SDA AREF GND 13 12 11 10 9 8 7 6 5 4 3 2 1 0
56             IOREF RESET 33V 50V GND GND VIN A0 A1 A2 A3 A4 A5
57             }]},
58             );
59             has '_pin_mode' => (
60             is => 'ro',
61             );
62              
63             with 'Device::WebIO::Device::DigitalOutput';
64             with 'Device::WebIO::Device::DigitalInput';
65             with 'Device::WebIO::Device::PWM';
66             with 'Device::WebIO::Device::ADC';
67              
68              
69             sub BUILDARGS
70             {
71 0     0 0   my ($class, $args) = @_;
72 0           my $port = delete $args->{port};
73              
74 0 0         my $dev = Device::Firmata->open( $port )
75             or die "Could not connect to Firmata Server on '$port'\n";
76 0           $args->{'_firmata'} = $dev;
77              
78 0           $args->{'_pin_mode'} = [ ('IN') x 128 ];
79              
80 0           return $args;
81             }
82              
83             sub output_pin
84             {
85 0     0 0   my ($self, $pin, $set) = @_;
86 0           $self->_firmata->digital_write( $pin, $set );
87 0           return 1;
88             }
89              
90             sub input_pin
91             {
92 0     0 0   my ($self, $pin) = @_;
93 0           my $value = $self->_firmata->digital_read( $pin );
94 0           return $value;
95             }
96              
97             sub set_as_output
98             {
99 0     0 0   my ($self, $pin) = @_;
100 0           $self->_pin_mode->[$pin] = 'OUT';
101 0           $self->_firmata->pin_mode( $pin, PIN_OUTPUT );
102 0           return 1;
103             }
104              
105             sub set_as_input
106             {
107 0     0 0   my ($self, $pin) = @_;
108 0           $self->_pin_mode->[$pin] = 'IN';
109 0           $self->_firmata->pin_mode( $pin, PIN_INPUT );
110 0           return 1;
111             }
112              
113             sub is_set_input
114             {
115 0     0 0   my ($self, $pin) = @_;
116 0 0         return 1 if $self->_pin_mode->[$pin] eq 'IN';
117 0           return 0;
118             }
119              
120             sub is_set_output
121             {
122 0     0 0   my ($self, $pin) = @_;
123 0 0         return 1 if $self->_pin_mode->[$pin] eq 'OUT';
124 0           return 0;
125             }
126              
127              
128             sub pwm_bit_resolution
129             {
130 0     0 0   my ($self, $pin) = @_;
131             # Arduino Uno bit resolution
132 0           return 8;
133             }
134              
135             {
136             my %did_set_pwm;
137             sub pwm_output_int
138             {
139 0     0 0   my ($self, $pin, $value) = @_;
140 0           my $firmata = $self->_firmata;
141              
142 0 0         $firmata->pin_mode( $pin, PIN_PWM )
143             if ! exists $did_set_pwm{$pin};
144 0           $did_set_pwm{$pin} = 1;
145              
146 0           $firmata->analog_write( $pin, $value );
147 0           return 1;
148             }
149             }
150              
151             sub adc_bit_resolution
152             {
153 0     0 0   my ($self, $pin) = @_;
154             # Arduino Uno bit resolution
155 0           return 10;
156             }
157              
158             sub adc_volt_ref
159             {
160 0     0 0   my ($self, $pin) = @_;
161             # Arduino Uno, except when it's 3.3V. This is a rather large assumption.
162             # TODO fix this
163 0           return 5.0;
164             }
165              
166             sub adc_pin_count
167             {
168 0     0 0   my ($self, $pin) = @_;
169 0           return 128;
170             }
171              
172             {
173             my %did_set_adc;
174             sub adc_input_int
175             {
176 0     0 0   my ($self, $pin) = @_;
177 0           my $firmata = $self->_firmata;
178              
179 0 0         $firmata->pin_mode( $pin, PIN_ANALOG )
180             if ! exists $did_set_adc{$pin};
181 0           $did_set_adc{$pin} = 1;
182              
183 0           my $value = $firmata->analog_write( $pin );
184 0           return $value;
185             }
186             }
187              
188              
189             sub all_desc
190             {
191 0     0 0   my ($self) = @_;
192 0           my $pin_count = $self->input_pin_count;
193             return {
194 0           UART => 0,
195             SPI => 0,
196             I2C => 0,
197             ONEWIRE => 0,
198             GPIO => {
199             map {
200 0           my $function = $self->_pin_mode->[$_];
201 0 0         my $value = $function eq 'IN'
202             ? $self->input_pin( $_ )
203             : $self->{'_output_pin_value'}[$_];
204 0           $_ => {
205             function => $function,
206             value => $value,
207             };
208             } 0 .. ($pin_count - 1)
209             },
210             };
211             }
212              
213              
214              
215              
216             1;
217             __END__