diff --git a/Changes b/Changes index 5d2d168..1a0973d 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,19 @@ Revision history for Device-Firmata +0.69 2020.06.01 - Jens B. + - fix analog channel mapping in method pin_mode, analog_read and observe_analog of Device::Firmata::Platform + - added method close() to Device::Firmata::IO::SerialIO + - added and updated POD + +0.68 2020.06.01 - Jens B. + - dist preparation + +0.67 2020.05.31 - Jens B. + - dist preparation + +0.66 2020.05.31 - Jens B. + - dist preparation + 0.65 2018.06.09 - Jens B. fix push on reference in method attach of Device::Firmata::IO::NetIO added and updated POD diff --git a/MANIFEST b/MANIFEST index 6e449dd..4bcd561 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,82 +1,79 @@ Changes CONTRIBUTING -dist.ini environment -ignore.txt -LICENSE -Makefile.PL -MANIFEST -README -t/00-load.t -t/boilerplate.t -t/manifest.t -t/pod.t -t/pod-coverage.t -lib/Device/Firmata/Platform/Arduino.pm +examples/example-blink.pl +examples/example-callbacks.pl +examples/example-i2c.pl +examples/example-matrix-draw.pl +examples/example-matrix-time.pl +examples/example-matrix-time2.pl +examples/example-matrix.pl +examples/example-onewire-alarms.pl +examples/example-onewire.pl +examples/example-pwm.pl +examples/example-tcpserver.pl +examples/example_DHT11.pl +examples/example_encoder.pl +examples/example_stepper.pl +examples/test.pl +lib/Device/Firmata.pm lib/Device/Firmata/Base.pm lib/Device/Firmata/Constants.pm -lib/Device/Firmata/Language.pm -lib/Device/Firmata/Platform.pm lib/Device/Firmata/Error.pm -lib/Device/Firmata/Protocol.pm lib/Device/Firmata/IO/NetIO.pm lib/Device/Firmata/IO/SerialIO.pm -lib/Device/Firmata.pm -presentation/index.html -presentation/scripts/jquery.js -presentation/scripts/global.js -presentation/scripts/jquery.presentation.js -presentation/scripts/dd_roundies.js -presentation/scripts/jquery.presentation-full.js -presentation/images/HT1632-spec-8.png -presentation/images/HappySkies.png -presentation/images/HT1632-spec-4.png -presentation/images/HT1632-spec-5.png +lib/Device/Firmata/Language.pm +lib/Device/Firmata/Platform.pm +lib/Device/Firmata/Platform/Arduino.pm +lib/Device/Firmata/Protocol.pm +LICENSE +Makefile.PL +MANIFEST This list of files +MANIFEST.SKIP presentation/images/ArduinoDuemilanove.png -presentation/images/HT1632-spec-19.png -presentation/images/sureelectronics-32x8matrix-back2.png -presentation/images/HT1632-spec-16.png -presentation/images/HT1632-spec-6.png -presentation/images/HT1632-spec-2.png -presentation/images/structure/bg-body.png -presentation/images/bear-work.png -presentation/images/DE-DP105_Ver1.0_EN_0.pdf -presentation/images/HT1632-spec-7.png -presentation/images/HT1632-spec-18.png -presentation/images/HT1632-spec-3.png -presentation/images/sureelectronics-32x8matrix-back.png -presentation/images/HT1632-spec-14.png -presentation/images/HT1632-spec-15.png presentation/images/ArduinoIDE.png +presentation/images/bear-work.png presentation/images/Cloud_Background_by_RedemptionDesign_at_deviantart.jpg -presentation/images/sureelectronics-32x8matrix.png +presentation/images/DE-DP105_Ver1.0_EN_0.pdf +presentation/images/firmatagui.png +presentation/images/HappySkies.png presentation/images/HT1632-spec-0.png -presentation/images/HT1632-spec-9.png +presentation/images/HT1632-spec-1.png +presentation/images/HT1632-spec-10.png presentation/images/HT1632-spec-11.png +presentation/images/HT1632-spec-12.png presentation/images/HT1632-spec-13.png -presentation/images/HT1632-spec-10.png -presentation/images/HT1632-spec-1.png +presentation/images/HT1632-spec-14.png +presentation/images/HT1632-spec-15.png +presentation/images/HT1632-spec-16.png presentation/images/HT1632-spec-17.png -presentation/images/firmatagui.png +presentation/images/HT1632-spec-18.png +presentation/images/HT1632-spec-19.png +presentation/images/HT1632-spec-2.png +presentation/images/HT1632-spec-3.png +presentation/images/HT1632-spec-4.png +presentation/images/HT1632-spec-5.png +presentation/images/HT1632-spec-6.png +presentation/images/HT1632-spec-7.png +presentation/images/HT1632-spec-8.png +presentation/images/HT1632-spec-9.png +presentation/images/structure/bg-body.png +presentation/images/sureelectronics-32x8matrix-back.png +presentation/images/sureelectronics-32x8matrix-back2.png +presentation/images/sureelectronics-32x8matrix.png presentation/images/write-signal-logic.png -presentation/images/HT1632-spec-12.png +presentation/index.html presentation/README +presentation/scripts/dd_roundies.js +presentation/scripts/global.js +presentation/scripts/jquery.js +presentation/scripts/jquery.presentation-full.js +presentation/scripts/jquery.presentation.js presentation/stylesheets/.DS_Store presentation/stylesheets/screen.css -examples/example-matrix.pl -examples/example-matrix-time2.pl -examples/example-tcpserver.pl -examples/example-callbacks.pl -examples/example-pwm.pl -examples/example_LCD_I2C.pl -examples/example-onewire-alarms.pl -examples/example-i2c.pl -examples/example-blink.pl -examples/example-matrix-draw.pl -examples/example_stepper.pl -examples/test.pl -examples/LiquidCrystal_I2C.pm -examples/example_encoder.pl -examples/example-onewire.pl -examples/example-matrix-time.pl -examples/example_DHT11.pl +README +t/00-load.t +t/boilerplate.t +t/manifest.t +t/pod-coverage.t +t/pod.t diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index ddcd5c8..3e192d1 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -1,2 +1,9 @@ ^.*~$ -MANIFEST.SKIP +.*\.bak$ +.*\.tar\.gz$ +^.git +^examples/LiquidCrystal_I2C.pm$ +^examples/example_LCD_I2C.pl$ +^Makefile$ +^Makefile\.old$ +^MYMETA.* diff --git a/Makefile.PL b/Makefile.PL index 63df8a4..c6228b7 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -13,11 +13,9 @@ WriteMakefile( VERSION_FROM => 'lib/Device/Firmata.pm', ABSTRACT_FROM => 'lib/Device/Firmata.pm', ($ExtUtils::MakeMaker::VERSION >= 6.3001? ('LICENSE'=> 'perl_5') : ()), + ($ExtUtils::MakeMaker::VERSION >= 6.18? ('SIGN'=> '0') : ()), PL_FILES => {}, MIN_PERL_VERSION => 5.006, - CONFIGURE_REQUIRES => { - 'ExtUtils::MakeMaker' => 0, - }, BUILD_REQUIRES => { 'Test::More' => 0, }, diff --git a/README b/README index b68505b..0a5e618 100644 --- a/README +++ b/README @@ -1,6 +1,11 @@ Device-Firmata -Device::Firmata - Perl interface to the Firmata protocol for talking to the arduino microcontroler platform. See http://firmata.org/wiki/Main_Page for more details. +Device::Firmata - A Perl implementation of the Firmata protocol. + +This module allows a computer running Perl to connect to Firmata devices (Arduinos and compatible, including ESP8266), either via serial I/O (RS-232, USB, etc.) or TCP/IP (LAN, WiFi). + +Protocol details can be found at https://github.com/firmata/protocol. + INSTALLATION diff --git a/dist.ini b/dist.ini deleted file mode 100644 index 6cf1036..0000000 --- a/dist.ini +++ /dev/null @@ -1,24 +0,0 @@ -name = Device-Firmata -author = Aki Mimoto , Norbert Truchsess , Jens B. -license = Perl_5 -copyright_holder = Aki Mimoto, Norbert Truchsess, Jens B. -copyright_year = 2010 - -version = 0.65 - -[GatherDir] -[MetaYAML] -[PruneCruft] -[MetaJSON] -[License] -[PodWeaver] -[ManifestSkip] - -[PodCoverageTests] -[PodSyntaxTests] -[TestRelease] -[EOLTests] - -[UploadToCPAN] -[ConfirmRelease] -[AutoPrereqs] \ No newline at end of file diff --git a/ignore.txt b/ignore.txt deleted file mode 100644 index c47b486..0000000 --- a/ignore.txt +++ /dev/null @@ -1,18 +0,0 @@ -Makefile -Makefile.old -Build -Build.bat -META.* -MYMETA.* -.build/ -_build/ -cover_db/ -blib/ -inc/ -.lwpcookies -.last_cover_stats -nytprof.out -pod2htm*.tmp -pm_to_blib -Device-Firmata-* -Device-Firmata-*.tar.gz diff --git a/lib/Device/Firmata.pm b/lib/Device/Firmata.pm index 9eb6e95..ec6e4bd 100644 --- a/lib/Device/Firmata.pm +++ b/lib/Device/Firmata.pm @@ -11,17 +11,19 @@ use Device::Firmata::Base =head1 NAME -Device::Firmata - A Perl implementation of the Firmata protocol. +Device::Firmata - module for controlling Firmata devices -This module allows a computer running Perl to connect to Firmata devices (Arduinos and compatible, including ESP8266), either via serial IO (RS-232, USB, etc.) or TCP/IP (LAN, WiFi). Protocol details can be found at L. +=head1 DESCRIPTION + +This module allows a computer running Perl to connect to Firmata devices (Arduinos and compatible, including ESP8266), either via serial I/O (RS-232, USB, etc.) or TCP/IP (LAN, WiFi). Protocol details can be found at L. =head1 VERSION -Version 0.65 +Version 0.69 =cut -our $VERSION = '0.65'; +our $VERSION = '0.69'; our $DEBUG = 0; @@ -76,7 +78,7 @@ sub open { return $platform; } -=head2 listen ( host, port ) +=head2 listen ( host, port, [opts] ) Start a TCP server bound to given local address and port for the Arduino to connect to. Returns a L object. An implementation example can be found in file F. @@ -96,11 +98,11 @@ sub listen { =head1 EXAMPLES -In the folder F you will find more than 15 implementation examples for various Firmata IO operations including digital I/O, PWM, stepper and encoder as well as bus I/O for I2C and 1-Wire. +In the folder F you will find more than 15 implementation examples for various Firmata I/O operations including digital I/O, PWM, stepper and encoder as well as bus I/O for I2C and 1-Wire. =head1 SEE ALSO -L +L =head1 LICENSE @@ -113,7 +115,7 @@ Copyright (C) 2016 Jens B. This is free software; you can redistribute it and/or modify it under the same terms as Perl itself. -See http://dev.perl.org/licenses/ for more information. +See L for more information. =cut diff --git a/lib/Device/Firmata/Base.pm b/lib/Device/Firmata/Base.pm index 15ca54c..9f95233 100644 --- a/lib/Device/Firmata/Base.pm +++ b/lib/Device/Firmata/Base.pm @@ -1,5 +1,15 @@ package Device::Firmata::Base; +=head1 NAME + +Device::Firmata::Base - abstract baseclass for Device::Firmata modules + +=head1 DESCRIPTION + +Provides various convenience methods for module internal use. + +=cut + use strict 'vars', 'subs'; use warnings; use vars qw/ @@ -14,12 +24,6 @@ use vars qw/ $FIRMATA_LOCALE_MESSAGES /; -=head1 NAME - -Device::Firmata::Base -- Abstract baseclass for Device::Firmata modules - -=cut - $FIRMATA_DEBUGGING = 1; $FIRMATA_ATTRIBS = {}; $FIRMATA_LOCALE = 'en'; diff --git a/lib/Device/Firmata/Constants.pm b/lib/Device/Firmata/Constants.pm index 15d382e..1d043f8 100644 --- a/lib/Device/Firmata/Constants.pm +++ b/lib/Device/Firmata/Constants.pm @@ -2,7 +2,51 @@ package Device::Firmata::Constants; =head1 NAME -Device::Firmata::Constants - constants used in the Device::Firmata system +Device::Firmata::Constants - constants used in the Device::Firmata modules + +=head1 DESCRIPTION + +Provides several constants to be used with L. + +Pin modes: + +=over + +=item * PIN_INPUT + +=item * PIN_OUTPUT + +=item * PIN_ANALOG + +=item * PIN_PWM + +=item * PIN_SERVO + +=item * PIN_SHIFT + +=item * PIN_I2C + +=item * PIN_ONEWIRE + +=item * PIN_STEPPER + +=item * PIN_ENCODER + +=item * PIN_SERIAL + +=item * PIN_PULLUP + +=back + +Digital pin states: + +=over + +=item * PIN_LOW + +=item * PIN_HIGH + +=back =cut diff --git a/lib/Device/Firmata/Error.pm b/lib/Device/Firmata/Error.pm index cef07a8..32faf63 100644 --- a/lib/Device/Firmata/Error.pm +++ b/lib/Device/Firmata/Error.pm @@ -1,9 +1,14 @@ package Device::Firmata::Error; -# ================================================================== =head1 NAME -Device::Firmata::Error - Error handlers +Device::Firmata::Error - error reporting + +=head1 DESCRIPTION + +Intendend for module internal error reporting. + +Implementation Status: experimental, unused =cut @@ -25,6 +30,7 @@ use Device::Firmata::Base; $FIRMATA_ERROR_DEFAULT = -1; +=head1 METHODS =head2 error @@ -79,7 +85,6 @@ sub error { return $text; } - =head2 errors_flush =cut diff --git a/lib/Device/Firmata/IO/NetIO.pm b/lib/Device/Firmata/IO/NetIO.pm index f87c2c9..f8ff01b 100644 --- a/lib/Device/Firmata/IO/NetIO.pm +++ b/lib/Device/Firmata/IO/NetIO.pm @@ -1,8 +1,8 @@ package Device::Firmata::IO::NetIO; -=head1 Device::Firmata::IO::NetIO +=head1 NAME -Implements the low level TCP/IP server socket IO. +Device::Firmata::IO::NetIO - TCP/IP server interface to Firmata device =cut @@ -17,11 +17,11 @@ use Device::Firmata::Base FIRMATA_ATTRIBS => { }; -=head2 METHODS +=head1 METHODS -=head3 listen ( host, port ) +=head2 listen ( host, port, [opts] ) -Start a TCP server bound to given local address and port for the Firmata device to connect to. Returns a C object. Typically called by method C of L. An implementation example can be found in file F. +Start a TCP server bound to given local address and port for the Firmata device to connect to. Returns a L object. Typically called internally by L. An implementation example can be found in file F. =cut @@ -50,9 +50,9 @@ sub listen { return $self; } -=head3 accept ( timeout ) +=head2 accept ( timeout ) -Wait until timeout seconds for an Firmata device to connect. Returns a L object on success or C. An implementation example can be found in file F. +Wait until timeout seconds for an Firmata device to connect. Will call L on connect. Returns a L object on success or C on error. An implementation example can be found in file F. =cut @@ -79,7 +79,7 @@ sub accept { return undef; } -=head3 close ( ) +=head2 close ( ) Closes the TCP server socket and disconnects all Firmata devices. An implementation example can be found in file F. @@ -103,9 +103,9 @@ sub close { } } -=head3 attach ( connectedSocket ) +=head2 attach ( connectedSocket, [opts] ) -Assign a connected L as IO port and return a L object. Typically used internally by the C method. +Assign a connected L socket as I/O port, call L and return a L object. Typically used internally by the L method. =cut @@ -142,9 +142,9 @@ sub attach { return $platform; } -=head3 poll ( timeout ) +=head2 poll ( timeout ) -Wait for timeout seconds for data from Firmata devices. If data is received the method C of L will be called for processing. An implementation example can be found in file F. +Wait for timeout seconds for data from Firmata devices. If data is received L will be called for processing. An implementation example can be found in file F. =cut @@ -173,9 +173,9 @@ sub poll { package Device::Firmata::IO::NetIO::Client; -=head1 Device::Firmata::IO::NetIO::Client +=head1 NAME -Implements the low level TCP/IP client socket IO. +Device::Firmata::IO::NetIO::Client - I/O operations on TCP/IP client session =cut @@ -189,11 +189,11 @@ use Device::Firmata::Base FIRMATA_ATTRIBS => { }; -=head2 METHODS +=head1 METHODS -=head3 attach ( connectedSocket ) +=head2 attach ( connectedSocket, [opts] ) -Assign a connected L as IO port and return a C object. Typically used internally by the C method of L. +Assign a connected L as I/O port and return a L object. Typically used internally by L. =cut @@ -207,9 +207,9 @@ sub attach { return $self; } -=head3 data_write ( buffer ) +=head2 data_write ( buffer ) -Send a bunch of data to the Firmata device. Typically used internally by L. +Send a bunch of data to the Firmata device. Returns number of transmitted bytes. Typically used internally by L. =cut @@ -221,7 +221,7 @@ sub data_write { } -=head3 data_read ( bytes ) +=head2 data_read ( numBytes ) Fetch up to given number of bytes from the client socket. This function is non-blocking. Returns the received data. Typically used internally by L. @@ -240,9 +240,9 @@ sub data_read { return $buf; } -=head3 close +=head2 close ( ) -Close the TCP client socket to the Firmata device. The listening socket will not be affected. Typically used internally by L and C. +Close the TCP client socket to the Firmata device. The listening socket will not be affected. Typically used internally by L and L. =cut @@ -253,7 +253,7 @@ sub close { =head1 SEE ALSO -L +L =cut diff --git a/lib/Device/Firmata/IO/SerialIO.pm b/lib/Device/Firmata/IO/SerialIO.pm index 664f83e..702781e 100644 --- a/lib/Device/Firmata/IO/SerialIO.pm +++ b/lib/Device/Firmata/IO/SerialIO.pm @@ -2,7 +2,7 @@ package Device::Firmata::IO::SerialIO; =head1 NAME -Device::Firmata::IO::SerialIO - implement the low level serial IO. +Device::Firmata::IO::SerialIO - serial port interface to Firmata device =cut @@ -21,10 +21,11 @@ $SERIAL_CLASS = $^O eq 'MSWin32' ? 'Win32::SerialPort' : 'Device::SerialPort'; eval "require $SERIAL_CLASS"; +=head1 METHODS =head2 open ( serialPort , [opts] ) -Establish a serial connection with a Firmata device. The first parameter is the name of the serial device connected with the Firmata device, e.g. '/dev/ttyUSB0' or 'COM9'. The second parameter is an optional hash of parameters for the serial port. The parameter C is supported and defaults to C<57600>. Returns a C object. Typically called internally by the C method of L. +Establish a serial connection with a Firmata device. The first parameter is the name of the serial device connected with the Firmata device, e.g. '/dev/ttyUSB0' or 'COM9'. The second parameter is an optional hash of parameters for the serial port. The parameter C is supported and defaults to C<57600>. Returns a L object. Typically called internally by L. =cut @@ -33,16 +34,16 @@ sub open { my ( $pkg, $serial_port, $opts ) = @_; my $self = ref $pkg ? $pkg : $pkg->new($opts); my $serial_obj = $SERIAL_CLASS->new( $serial_port, 1, 0 ) or return; - $self->attach($serial_obj,$opts); + $self->attach($serial_obj, $opts); $self->{handle}->baudrate($self->{baudrate}); $self->{handle}->databits(8); $self->{handle}->stopbits(1); return $self; } -=head2 attach ( serialPort ) +=head2 attach ( serialPort , [opts] ) -Assign a L (or L) as IO port and return a L object. Typically used internally by the C method. +Assign a L (or L) as IO port and return a L object. Typically used internally by L method. =cut @@ -53,7 +54,7 @@ sub attach { return $self; } -=head2 data_write +=head2 data_write ( buffer ) Send a bunch of data to the Firmata device. Typically used internally by L. @@ -66,8 +67,7 @@ sub data_write { return $self->{handle}->write( $buf ); } - -=head2 data_read +=head2 data_read ( numBytes ) Fetch up to given number of bytes from the serial port. This function is non-blocking. Returns the received data. Typically used internally by L. @@ -81,9 +81,24 @@ sub data_read { return $string; } +=head2 close ( ) + +Close serial connection to Firmata device. + +=cut + +sub close { +# -------------------------------------------------- + my ( $self ) = @_; + if ($self->{handle}) { + $self->{handle}->close(); + delete $self->{handle}; + } +} + =head1 SEE ALSO -L +L =cut diff --git a/lib/Device/Firmata/Language.pm b/lib/Device/Firmata/Language.pm index 989caeb..0185103 100644 --- a/lib/Device/Firmata/Language.pm +++ b/lib/Device/Firmata/Language.pm @@ -1,9 +1,15 @@ package Device::Firmata::Language; -# ================================================================== =head1 NAME -Device::Firmata::Language - Localization +Device::Firmata::Language - localization + +=head1 DESCRIPTION + +Intendend for I8N of L. +Requires a file named .txt containing translations at runtime. + +Implementation Status: experimental, unused =cut @@ -25,6 +31,7 @@ $FIRMATA_LOCALE_MESSAGES = { $FIRMATA_LOCALE = 'en'; $FIRMATA_LOCALE_PATH = '.'; +=head1 METHODS =head2 numbers diff --git a/lib/Device/Firmata/Platform.pm b/lib/Device/Firmata/Platform.pm index 8c3afda..b14cf65 100644 --- a/lib/Device/Firmata/Platform.pm +++ b/lib/Device/Firmata/Platform.pm @@ -2,7 +2,36 @@ package Device::Firmata::Platform; =head1 NAME -Device::Firmata::Platform - Platform specifics +Device::Firmata::Platform - Firmata API + +=head1 DESCRIPTION + +Provides the application programming interface for Device::Firmata +implementing all major features of the Firmata 2.5 specification: + +=over + +=item * Analog Firmata + +=item * Digital Firmata + +=item * I2C Firmata + +=item * 1-Wire Firmata + +=item * Serial Firmata + +=item * Servo Firmata + +=item * Stepper Firmata + +=item * Firmata Scheduler + +=back + +This API documentation is currently incomplete and only covers a small +subset of the implementation. Anyone willing to help improve the +documentation is welcome. =cut @@ -60,18 +89,38 @@ use Device::Firmata::Base stringresponse => {}, }; -=head2 open +=head1 METHODS + +=head2 attach ( ioPort ) -Connect to the IO port and do some basic operations -to find out how to connect to the device +Creates new Firmata Platform instance and attaches the provided I/O port. + +=over + +=item * param pkg: Perl package name or an instance of Device::Firmata::Platform + +=item * param ioPort: either an instance of L or L or + of any other class that provides compatible implementations for the methods data_read and data_write + +=item * return new Device::Firmata::Platform instance + +=back + +After attaching the I/O port to the Firmata Platform the following sequence of operations is recommended: + +=over + +=item * 1. Call L to request the capabilities of the Firmata device. + +=item * 2. Call L to configure the pins of the Firmata device. + +=item * Periodically call L to processess messages from the Firmata device. + +=back =cut sub attach { - # -------------------------------------------------- - # Attach to an open IO port and do some basic operations - # to find out how to connect to the device - # my ( $pkg, $port, $opts ) = @_; my $self = ref $pkg ? $pkg : $pkg->new($opts); $self->{io} = $port or return; @@ -79,6 +128,13 @@ sub attach { return $self; } +=head2 detach ( ) + +Detach IO port from Firmata Platform. +Typically used only internally by L. + +=cut + sub detach { my $self = shift; delete $self->{io} if ($self->{io}); @@ -102,12 +158,24 @@ sub detach { $self->{metadata} = {}; } +=head2 close ( ) + +Close IO port and detach from Firmata Platform. + +=cut + sub close { my $self = shift; $self->{io}->close(); $self->detach(); } +=head2 system_reset ( ) + +Try to reset Firmata device. Will only work if Firmata device is connected. + +=cut + sub system_reset { my $self = shift; $self->{io}->data_write($self->{protocol}->message_prepare( SYSTEM_RESET => 0 )); @@ -129,11 +197,11 @@ sub system_reset { $self->{metadata} = {}; } -=head2 messages_handle +=head2 messages_handle ( messages ) -Receive identified message packets and convert them -into their appropriate structures and parse -them as required +Receive identified message packets and convert them into their appropriate +structures and parse them as required. +Typically used only internally by L. =cut @@ -223,11 +291,11 @@ sub messages_handle { } } -=head2 sysex_handle +=head2 sysex_handle ( sysexMessage) -Receive identified sysex packets and convert them -into their appropriate structures and parse -them as required +Receive identified sysex packets and convert them into their appropriate +structures and parse them as required. +Typically used only internally by L. =cut @@ -289,11 +357,11 @@ sub sysex_handle { push @onewirepins, $pin; } if ($capabilities->{$pin}->{PIN_STEPPER+0}) { - push @stepperpins, $pin; + push @stepperpins, $pin; $self->{metadata}{stepper_resolutions}{$pin} = $capabilities->{$pin}->{PIN_STEPPER+0}->{resolution}; } if ($capabilities->{$pin}->{PIN_ENCODER+0}) { - push @encoderpins, $pin; + push @encoderpins, $pin; $self->{metadata}{encoder_resolutions}{$pin} = $capabilities->{$pin}->{PIN_ENCODER+0}->{resolution}; } if ($capabilities->{$pin}->{PIN_SERIAL+0}) { @@ -401,7 +469,7 @@ sub sysex_handle { } } -=head2 probe +=head2 probe ( ) On device boot time we wait 3 seconds for firmware name that the target device is using. @@ -410,6 +478,12 @@ response another 2 seconds and fire requests for version. If the response received, then we store protocol version and analog mapping and capability. +=over + +=item * return on success, C on error + +=back + =cut sub probe { @@ -445,10 +519,17 @@ sub probe { return; } -=head2 pin_mode +=head2 pin_mode ( pin, mode ) + +Set mode of Firmata device pin. + +=over + +=item * parm pin: Firmata device pin -Similar to the pinMode function on the -arduino +=item * param mode: use a member of constant $BASE from L + +=back =cut @@ -469,8 +550,10 @@ sub pin_mode { }; $mode == PIN_ANALOG and do { + my $channel = $self->device_pin_to_analog_channel($pin); + die "pin '".$pin."' is not reported as 'ANALOG' channel by Firmata device" unless defined($channel) && $channel >= 0 && $channel <= 0xF; $self->{io}->data_write($self->{protocol}->message_prepare( SET_PIN_MODE => 0, $pin, $mode )); - $self->{io}->data_write($self->{protocol}->message_prepare( REPORT_ANALOG => $pin, 1 )); + $self->{io}->data_write($self->{protocol}->message_prepare( REPORT_ANALOG => $channel, 1 )); last; }; @@ -480,14 +563,19 @@ sub pin_mode { return 1; } -=head2 digital_write +=head2 digital_write ( pin, state ) + +=over + +=item * parm pin: Firmata device pin -Analogous to the digitalWrite function on the -arduino +=item * param state: new state (0 or 1) for digial pin to set on Firmata device -Deprecation Warning: -Writing to pin with mode "INPUT" is only supported for backward compatibility -to switch pullup on and off. Use sub pin_mode with $mode=PIN_PULLUP instead. +=back + +Deprecation warning: +Writing to pin with mode "PIN_INPUT" is only supported for backward compatibility +to switch pullup on and off. Use sub L with $mode=PIN_PULLUP instead. =cut @@ -513,10 +601,15 @@ sub digital_write { return 1; } -=head2 digital_read +=head2 digital_read ( pin ) + +=over + +=item * parm pin: Firmata device pin -Analogous to the digitalRead function on the -arduino +=item * return last state (0 or 1) of digital pin received from Firmata device + +=back =cut @@ -532,30 +625,43 @@ sub digital_read { return ( $port_state & $pin_mask ? 1 : 0 ); } -=head2 analog_read +=head2 analog_read ( pin ) + +=over + +=item * parm pin: Firmata device pin -Fetches the analog value of a pin +=item * return last value of analog pin received from Firmata device + +=back =cut sub analog_read { # -------------------------------------------------- - # my ( $self, $pin ) = @_; die "pin '".$pin."' is not configured for mode 'ANALOG'" unless $self->is_configured_mode($pin,PIN_ANALOG); - return $self->{analog_pins}[$pin]; + my $channel = $self->device_pin_to_analog_channel($pin); + die "pin '".$pin."' is not reported as 'ANALOG' channel by Firmata device" unless defined($channel) && $channel >= 0 && $channel <= 0xF; + return $self->{analog_pins}[$channel]; } -=head2 analog_write +=head2 analog_write ( pin, value ) + +=over + +=item * parm pin: Firmata device pin + +=item * param state: new value for PWM pin to set on Firmata device + +=back =cut sub analog_write { # -------------------------------------------------- - # Sets the PWM value on an arduino - # my ( $self, $pin, $value ) = @_; die "pin '".$pin."' is not configured for mode 'PWM'" unless $self->is_configured_mode($pin,PIN_PWM); @@ -565,9 +671,9 @@ sub analog_write { return $self->{io}->data_write($self->{protocol}->message_prepare( ANALOG_MESSAGE => $pin, $byte_0, $byte_1 )); } -=head2 pwm_write +=head2 pwm_write ( pin, value ) -pmw_write is an alias for analog_write +pmw_write ( pin, value ) is an alias for L =cut @@ -609,7 +715,7 @@ sub sampling_interval { return $self->{io}->data_write($sampling_interval_packet); } -sub sysex_send { +sub sysex_send { my ( $self, @sysex_data ) = @_; my $sysex_packet = $self->{protocol}->packet_sysex(@sysex_data); return $self->{io}->data_write($sysex_packet); @@ -646,7 +752,7 @@ sub i2c_config { sub servo_write { # -------------------------------------------------- - # Sets the SERVO value on an arduino + # Sets the SERVO value on an Arduino # my ( $self, $pin, $value ) = @_; die "pin '".$pin."' is not configured for mode 'SERVO'" unless $self->is_configured_mode($pin,PIN_SERVO); @@ -893,11 +999,11 @@ sub serial_config { return $self->{io}->data_write($self->{protocol}->packet_serial_config( $port, $baud, $rxPin, $txPin )); } -=head2 poll +=head2 poll ( ) Call this function every once in a while to check up on the status of the comm port, receive -and process data from the arduino +and process data from the Firmata device =cut @@ -911,6 +1017,23 @@ sub poll { return $messages; } +=head2 observe_digital ( pin, observer, context ) + +Register callback sub that will be called by L +if a new value for a digital pin was received from the Firmata device. + +=over + +=item * parm pin: Firmata device pin + +=item * parm observer: callback sub reference with the parameters pin, oldState, newState, context + +=item * parm context: context value passed as last parameter to callback sub + +=back + +=cut + sub observe_digital { my ( $self, $pin, $observer, $context ) = @_; die "unsupported mode 'INPUT' for pin '".$pin."'" unless ($self->is_supported_mode($pin,PIN_INPUT)); @@ -923,14 +1046,33 @@ sub observe_digital { return 1; } +=head2 observe_analog ( pin, observer, context ) + +Register callback sub that will be called by L +if the value of the analog pin received from the Firmata device has changed. + +=over + +=item * parm pin: Firmata device pin + +=item * parm observer: callback sub reference with the parameters pin, oldValue, newValue, context + +=item * parm context: context value passed as last parameter to callback sub + +=back + +=cut + sub observe_analog { my ( $self, $pin, $observer, $context ) = @_; - die "unsupported mode 'ANALOG' for pin '".$pin."'" unless ($self->is_supported_mode($pin,PIN_ANALOG)); + die "pin '".$pin."' is not configured for mode 'ANALOG'" unless $self->is_configured_mode($pin,PIN_ANALOG); $self->{analog_observer}[$pin] = { method => $observer, context => $context, }; - $self->{io}->data_write($self->{protocol}->message_prepare( REPORT_ANALOG => $pin, 1 )); + my $channel = $self->device_pin_to_analog_channel($pin); + die "pin '".$pin."' is not reported as 'ANALOG' channel by Firmata device" unless defined($channel) && $channel >= 0 && $channel <= 0xF; + $self->{io}->data_write($self->{protocol}->message_prepare( REPORT_ANALOG => $channel, 1 )); return 1; } @@ -1017,10 +1159,62 @@ sub is_supported_mode { return 1; } +=head2 device_pin_to_analog_channel ( pin ) + +=over + +=item * parm pin: Firmata device pin + +=item * return analog channel number if analog mapping is available (e.g. by calling L), + C if given pin is not mapped as an analog channel or + given pin if analog mapping is not available + +=back + +=cut + +sub device_pin_to_analog_channel { + my ($self,$pin) = @_; + + if (defined $self->{metadata}{analog_mappings}) { + my $analog_mappings = $self->{metadata}{analog_mappings}; + foreach my $channel (keys %$analog_mappings) { + if ($analog_mappings->{$channel} == $pin) { + return $channel; + } + } + return undef; + } + + return $pin; +} + +=head2 is_configured_mode ( pin, mode ) + +Verify if pin was configured with L for requested mode. + +=over + +=item * parm pin: Firmata device pin + +=item * param mode: use a member of constant $BASE from L + +=item * return 1 on success or C on error + +=back + +=cut + sub is_configured_mode { my ($self,$pin,$mode) = @_; return undef if (!defined $self->{pin_modes}->{$pin} or $self->{pin_modes}->{$pin} != $mode); return 1; } +=head1 SEE ALSO + +L + +=cut + 1; diff --git a/lib/Device/Firmata/Platform/Arduino.pm b/lib/Device/Firmata/Platform/Arduino.pm index 67230d0..6168acd 100644 --- a/lib/Device/Firmata/Platform/Arduino.pm +++ b/lib/Device/Firmata/Platform/Arduino.pm @@ -2,12 +2,15 @@ package Device::Firmata::Platform::Arduino; =head1 NAME -Device::Firmata::Platform::Arduino - subclass for the Arduino itself +Device::Firmata::Platform::Arduino - subclass for Arduino Firmata devices =head1 DESCRIPTION -No customization required at this time so this is just a specification of the -Device::Firmata::Platform class. +Subclass of L to provide a specific +implementation for Arduino Firmata devices. + +Note: Currently there is no specific implemention, consider using the +base class directly. =cut diff --git a/lib/Device/Firmata/Protocol.pm b/lib/Device/Firmata/Protocol.pm index 21803ea..f927b31 100644 --- a/lib/Device/Firmata/Protocol.pm +++ b/lib/Device/Firmata/Protocol.pm @@ -2,7 +2,7 @@ package Device::Firmata::Protocol; =head1 NAME -Device::Firmata::Protocol - details of the actual firmata protocol +Device::Firmata::Protocol - Firmata protocol implementation =cut @@ -119,6 +119,8 @@ our $MODENAMES = { =head1 DESCRIPTION +Implementation of the Firmata 2.5 protocol specification. + Because we're dealing with a permutation of the MIDI protocol, certain commands are one byte, others 2 or even 3. We do this part to figure out @@ -162,7 +164,7 @@ D 1 E 2 F 0 or variable -=cut +=head1 METHODS =head2 message_data_receive