package RPi::WiringPi::Util; use strict; use warnings; use parent 'WiringPi::API'; use RPi::WiringPi::Constant qw(:all); our $VERSION = '2.3616'; sub gpio_layout { return $_[0]->gpio_layout; } sub pin_to_gpio { my ($self, $pin, $scheme) = @_; $scheme = defined $scheme ? $scheme : $self->pin_scheme; if ($scheme == RPI_MODE_WPI){ return $self->wpi_to_gpio($pin); } elsif ($scheme == RPI_MODE_PHYS){ return $self->phys_to_gpio($pin); } elsif ($scheme == RPI_MODE_GPIO){ return $pin; } if ($scheme == RPI_MODE_UNINIT){ die "setup not run; pin mapping scheme not initialized\n"; } } sub pin_map { my ($self, $scheme) = @_; $scheme = $self->pin_scheme if ! defined $scheme; return {} if $scheme eq RPI_MODE_UNINIT; if (defined $self->{pin_map_cache}{$scheme}){ return $self->{pin_map_cache}{$scheme}; } my %map; for (0..63){ my $pin; if ($scheme == RPI_MODE_WPI) { $pin = $self->phys_to_wpi($_); } elsif ($scheme == RPI_MODE_GPIO){ $pin = $self->phys_to_gpio($_); } elsif ($scheme == RPI_MODE_PHYS){ $pin = $_; } $map{$_} = $pin; } $self->{pin_map_cache}{$scheme} = \%map; return \%map; } sub pin_scheme { my ($self, $scheme) = @_; if (defined $scheme){ $ENV{RPI_PIN_MODE} = $scheme; } return defined $ENV{RPI_PIN_MODE} ? $ENV{RPI_PIN_MODE} : RPI_MODE_UNINIT; } sub pwm_range { my ($self, $range) = @_; if (defined $range){ $self->{pwm_range} = $range; $self->pwm_set_range($range); } return defined $self->{pwm_range} ? $self->{pwm_range} : 1023; } sub export_pin { my ($self, $pin) = @_; system "sudo", "gpio", "export", $self->pin_to_gpio($pin), "in"; } sub unexport_pin { my ($self, $pin) = @_; system "sudo", "gpio", "unexport", $self->pin_to_gpio($pin); } sub registered_pins { return $ENV{RPI_PINS}; } sub register_pin { my ($self, $pin) = @_; my $gpio_num = $self->pin_to_gpio($pin->num); if (defined $ENV{RPI_PINS}){ my @pi_env_pins = split /,/, $ENV{RPI_PINS}; if (grep {$gpio_num == $_} @pi_env_pins){ die "\npin $pin is already in use... can't re-register it\n"; } } $ENV{RPI_PINS} = ! defined $ENV{RPI_PINS} ? $gpio_num : "$ENV{RPI_PINS},$gpio_num"; } sub unregister_pin { my ($self, $pin) = @_; my @pin_nums = split /,/, $self->registered_pins; my @updated_list; for my $pin_num (@pin_nums){ if ($pin->num == $pin_num){ $pin->mode(INPUT); } else { push @updated_list, $pin_num; } } $ENV{RPI_PINS} = join ",", @updated_list; } sub cleanup{ my $pins = $ENV{RPI_PINS}; return if ! $ENV{RPI_PINS}; for (split /,/, $pins){ `gpio -g mode $_ in`; `gpio -g mode $_ tri`; } delete $ENV{RPI_PINS}; } sub _vim{1;}; 1; __END__ =head1 NAME RPi::WiringPi::Util - Utility methods for RPi::WiringPi Raspberry Pi interface =head1 DESCRIPTION This module contains various utilities for L<RPi::WiringPi> that don't necessarily fit anywhere else. It is a base class, and is not designed to be used independently. =head1 METHODS =head2 gpio_layout() Returns the GPIO layout which indicates the board revision number. =head2 pin_scheme() Returns the current pin mapping in use. Returns C<0> for C<wiringPi> scheme, C<1> for GPIO, C<2> for System GPIO, C<3> for physical board and C<-1> if a scheme has not yet been configured (ie. one of the C<setup*()> methods has not yet been called). If using L<RPi::WiringPi::Constant>, these map out to: 0 => RPI_MODE_WPI 1 => RPI_MODE_GPIO 2 => RPI_MODE_GPIO_SYS # unused in RPi::WiringPi 3 => RPI_MODE_PHYS -1 => RPI_MODE_UNINIT =head2 pin_map($scheme) Returns a hash reference in the following format: $map => { phys_pin_num => pin_num, ... }; If no scheme is in place or one isn't sent in, return will be an empty hash reference. Parameters: $scheme Optional: By default, we'll check if you've already run a setup routine, and if so, we'll use the scheme currently in use. If one is not in use and no C<$scheme> has been sent in, we'll return an empty hash reference, otherwise if a scheme is sent in, the return will be: For C<'wiringPi'> scheme: $map = { phys_pin_num => wiringPi_pin_num, .... }; For C<'GPIO'> scheme: $map = { phys_pin_num => gpio_pin_num, ... }; =head2 pin_to_gpio($pin, $scheme) Dynamically converts the specified pin from the specified scheme (C<RPI_MODE_WPI> (wiringPi), or C<RPI_MODE_PHYS> (physical board numbering scheme) to the GPIO number format. If C<$scheme> is not sent in, we'll attempt to fetch the scheme currently in use and use that. Example: my $num = pin_to_gpio(6, RPI_MODE_WPI); That will understand the pin number C<6> to be the wiringPi representation, and will return the GPIO representation. =head2 wpi_to_gpio($pin_num) Converts a pin number from C<wiringPi> notation to GPIO notation. Parameters: $pin_num Mandatory: The C<wiringPi> representation of a pin number. =head2 phys_to_gpio($pin_num) Converts a pin number as physically documented on the Raspberry Pi board itself to GPIO notation, and returns it. Parameters: $pin_num Mandatory: The pin number printed on the physical Pi board. =head2 pwm_range($range) Changes the range of Pulse Width Modulation (PWM). The default is C<0> through C<1023>. Parameters: $range Mandatory: An integer specifying the high-end of the range. The range always starts at C<0>. Eg: if C<$range> is C<359>, if you incremented PWM by C<1> every second, you'd rotate a step motor one complete rotation in exactly one minute. =head2 export_pin($pin_num) Exports a pin. Only needed if using the C<setup_sys()> initialization method. Pin number must be the C<GPIO> pin number representation. =head2 unexport_pin($pin_num) Unexports a pin. Only needed if using the C<setup_sys()> initialization method. Pin number must be the C<GPIO> pin number representation. =head2 registered_pins() Returns a list of comma-separated pin numbers in GPIO scheme that have been used in your program run. =head2 register_pin($pin_obj) Registers a pin within the system for error checking, and proper resetting of the pins in use when required. Parameters: $pin_obj Mandatory: An object instance of L<RPi::WiringPi::Pin> class. =head2 unregister_pin($pin_obj) Removes an already registered pin from the registry. This method shouldn't be used in the normal course of operation, but is available for convenience anyhow. Parameters: $pin_obj Mandatory: An object instance of L<RPi::WiringPi::Pin> class. =head2 cleanup() Resets all registered pins back to default settings (off). It's important that this method be called in each application. =head1 ENVIRONMENT VARIABLES There are certain environment variables available to aid in testing on non-Raspberry Pi boards. =head2 NO_BOARD Set to true, will bypass the C<wiringPi> board checks. False will re-enable them. =head2 PI_BOARD Useful only for unit testing. Tells us that we're on Pi hardware. =head1 AUTHOR Steve Bertrand, E<lt>steveb@cpan.orgE<gt> =head1 COPYRIGHT AND LICENSE Copyright (C) 2017 by Steve Bertrand This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.18.2 or, at your option, any later version of Perl 5 you may have available.