Skip to content

Commit

Permalink
Merge pull request #24 from jnsbyr/develop
Browse files Browse the repository at this point in the history
serial pin support and protocol version support
  • Loading branch information
ntruchsess committed Jan 10, 2016
2 parents 35f9e7f + bb48a78 commit 4423041
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 9 deletions.
6 changes: 6 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
Revision history for Device-Firmata

0.61 2016.01.09 - Jens Beyer
added serial pin support (Platform, Protocol, Constants)
added protocol version query (Platform)
fixed messages_handle: REPORT_VERSION returns protocol version (Platform)
added method get_max_compatible_protocol_version (Protocol)

0.60 2014.06.28 - Norbert Truchsess
Fixed formating of Firmata.pm as Windows line-endings break automatic install from CPAN

Expand Down
1 change: 1 addition & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ LICENSE AND COPYRIGHT

Copyright (C) 2011 amimato
Copyright (C) 2012 ntruchsess
Copyright (C) 2016 jnsbyr

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
Expand Down
10 changes: 8 additions & 2 deletions lib/Device/Firmata/Constants.pm
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use constant (
PIN_ONEWIRE => 7,
PIN_STEPPER => 8,
PIN_ENCODER => 9,
PIN_SERIAL => 10,
PIN_LOW => 0,
PIN_HIGH => 1,
}
Expand Down Expand Up @@ -260,6 +261,8 @@ use constant (

# extended command set using sysex (0-127/0x00-0x7F)
RESERVED_COMMAND => 0x00, # 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI, etc).
SERIAL_DATA => 0x60, # serial port config/write/read/close/flush/listen request and read reply
ENCODER_DATA => 0x61, # receive rotary-encoders current positions
ANALOG_MAPPING_QUERY => 0x69, # ask for mapping of analog to pin numbers
ANALOG_MAPPING_RESPONSE => 0x6A, # reply with mapping info
CAPABILITY_QUERY => 0x6B, # ask for supported modes and resolution of all pins
Expand Down Expand Up @@ -291,6 +294,8 @@ use constant (
I2C => 0x06, # pin included in I2C setup
ONEWIRE => 0x07, # pin configured for 1-Wire commuication
STEPPER => 0x08, # pin configured for stepper motor
SERIAL => 0x0A, # pin configured for serial port

# Deprecated entries
deprecated => [
qw( FIRMATA_STRING SYSEX_I2C_REQUEST SYSEX_I2C_REPLY SYSEX_SAMPLING_INTERVAL )
Expand All @@ -315,6 +320,7 @@ use constant (

# extended command set using sysex (0-127/0x00-0x7F)
RESERVED_COMMAND => 0x00, # 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI, etc).
SERIAL_DATA => 0x60, # serial port config/write/read/close/flush/listen request and read reply
ENCODER_DATA => 0x61, # receive rotary-encoders current positions
ANALOG_MAPPING_QUERY => 0x69, # ask for mapping of analog to pin numbers
ANALOG_MAPPING_RESPONSE => 0x6A, # reply with mapping info
Expand Down Expand Up @@ -348,14 +354,14 @@ use constant (
ONEWIRE => 0x07, # pin configured for 1-Wire commuication
STEPPER => 0x08, # pin configured for stepper motor
ENCODER => 0x09, # pin configured for rotary-encoders

SERIAL => 0x0A, # pin configured for serial port

# Deprecated entries
deprecated => [
qw( FIRMATA_STRING SYSEX_I2C_REQUEST SYSEX_I2C_REPLY SYSEX_SAMPLING_INTERVAL )
],

}, # /Constants for Version 2.6
}, # /Constants for Version 2.6
}
);

Expand Down
71 changes: 65 additions & 6 deletions lib/Device/Firmata/Platform.pm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use Device::Firmata::Base
servo_resolutions => {},
stepper_resolutions => {},
encoder_resolutions => {},
serial_resolutions => {},
ports => [],
input_ports => [],
pins => {},
Expand All @@ -44,6 +45,7 @@ use Device::Firmata::Base
onewire_observer => [],
stepper_observer => [],
encoder_observer => [],
serial_observer => [],
scheduler_observer => undef,
string_observer => undef,

Expand Down Expand Up @@ -93,6 +95,7 @@ sub detach {
$self->{onewire_observer} = [];
$self->{stepper_observer} = [];
$self->{encoder_observer} = [];
$self->{serial_observer} = [];
$self->{scheduler_observer} = undef;
$self->{tasks} = [];
$self->{metadata} = {};
Expand All @@ -119,6 +122,7 @@ sub system_reset {
$self->{onewire_observer} = [];
$self->{stepper_observer} = [];
$self->{encoder_observer} = [];
$self->{serial_observer} = [];
$self->{scheduler_observer} = undef;
$self->{tasks} = [];
$self->{metadata} = {};
Expand Down Expand Up @@ -186,7 +190,7 @@ sub messages_handle {

# Handle metadata information
$command eq 'REPORT_VERSION' and do {
$self->{metadata}{firmware_version} = sprintf "V_%i_%02i",
$self->{metadata}{protocol_version} = sprintf "V_%i_%02i",
@$data;
last;
};
Expand Down Expand Up @@ -251,6 +255,7 @@ sub sysex_handle {
my @onewirepins;
my @stepperpins;
my @encoderpins;
my @serialpins;

foreach my $pin (keys %$capabilities) {
if (defined $capabilities->{$pin}) {
Expand Down Expand Up @@ -289,6 +294,10 @@ sub sysex_handle {
push @encoderpins, $pin;
$self->{metadata}{encoder_resolutions}{$pin} = $capabilities->{$pin}->{PIN_ENCODER+0}->{resolution};
}
if ($capabilities->{$pin}->{PIN_SERIAL+0}) {
push @serialpins, $pin;
$self->{metadata}{serial_resolutions}{$pin} = $capabilities->{$pin}->{PIN_SERIAL+0}->{resolution};
}
}
}
$self->{metadata}{input_pins} = \@inputpins;
Expand All @@ -301,6 +310,7 @@ sub sysex_handle {
$self->{metadata}{onewire_pins} = \@onewirepins;
$self->{metadata}{stepper_pins} = \@stepperpins;
$self->{metadata}{encoder_pins} = \@encoderpins;
$self->{metadata}{serial_pins} = \@serialpins;
last;
};

Expand Down Expand Up @@ -373,6 +383,15 @@ sub sysex_handle {
};
last;
};

$sysex_message->{command_str} eq 'SERIAL_DATA' and do {
my $serialPort = $data->{port};
my $observer = $self->{serial_observer}[$serialPort];
if (defined $observer) {
$observer->{method}( $data, $observer->{context} );
}
last;
};
}
}

Expand All @@ -392,14 +411,16 @@ sub probe {
my ($self) = @_;
$self->{metadata}{firmware} = '';
$self->{metadata}{firmware_version} = '';
$self->{metadata}{protocol_version} = '';

# Wait for 5 seconds only
my $end_tics = time + 5;
$self->firmware_version_query();
$self->protocol_version_query();
while ( $end_tics >= time ) {
select( undef, undef, undef, 0.2 ); # wait for response
if ( $self->poll && $self->{metadata}{firmware} && $self->{metadata}{firmware_version} ) {
$self->{protocol}->{protocol_version} = $self->{metadata}{firmware_version};
select( undef, undef, undef, 0.2 ); # wait for responses
if ( $self->poll && $self->{metadata}{firmware} && $self->{metadata}{firmware_version} && $self->{metadata}{protocol_version} ) {
$self->{protocol}->{protocol_version} = $self->{protocol}->get_max_supported_protocol_version($self->{metadata}{protocol_version});
if ( $self->{metadata}{capabilities} ) {
if ( $self->{metadata}{analog_mappings} ) {
return 1;
Expand All @@ -409,8 +430,10 @@ sub probe {
} else {
$self->capability_query();
}
} else {
$self->firmware_version_query() unless $end_tics - 2 >= time; # version query on last 2 sec only
} elsif ($end_tics - 2 < time) {
# version query on last 2 sec only
$self->firmware_version_query();
$self->protocol_version_query();
}
}
return;
Expand Down Expand Up @@ -540,6 +563,12 @@ pmw_write is an alias for analog_write

*pwm_write = *analog_write;

sub protocol_version_query {
my $self = shift;
my $protocol_version_query_packet = $self->{protocol}->packet_query_version;
return $self->{io}->data_write($protocol_version_query_packet);
}

sub firmware_version_query {
my $self = shift;
my $firmware_version_query_packet = $self->{protocol}->packet_query_firmware;
Expand Down Expand Up @@ -831,6 +860,26 @@ sub encoder_detach {
return $self->{io}->data_write($self->{protocol}->packet_encoder_detach( $encoderNum ));
}

sub serial_write {
my ( $self, $port, @data ) = @_;
return $self->{io}->data_write($self->{protocol}->packet_serial_write( $port, @data ));
}

sub serial_read {
my ( $self, $port, $numbytes ) = @_;
return $self->{io}->data_write($self->{protocol}->packet_serial_read( $port, 0x00, $numbytes ));
}

sub serial_stopreading {
my ( $self, $port) = @_;
return $self->{io}->data_write($self->{protocol}->packet_serial_read( $port, 0x01, 0 ));
}

sub serial_config {
my ( $self, $port, $baud ) = @_;
return $self->{io}->data_write($self->{protocol}->packet_serial_config( $port, $baud ));
}

=head2 poll
Call this function every once in a while to
Expand Down Expand Up @@ -921,6 +970,16 @@ sub observe_encoder {
return 1;
}

sub observe_serial {
my ( $self, $port, $observer, $context ) = @_;
return undef if (defined $self->{metadata}->{serialpins} && @$self->{metadata}->{serialpins} == 0 );
$self->{serial_observer}[$port] = {
method => $observer,
context => $context,
};
return 1;
}

sub observe_scheduler {
my ( $self, $observer, $context ) = @_;
$self->{scheduler_observer} = {
Expand Down

0 comments on commit 4423041

Please sign in to comment.