=head1 NAME

RPi::WiringPi::FAQ - FAQ and Tutorial for RPi::WiringPi

=head1 DESCRIPTION

This document will hopefully provide enough information in a sane way to get
you well on your way with manipulating your Raspberry Pi with the
L<RPi::WiringPi> and related distributions.

In this document we use constants that are provided with the C<:all> tag in
L<RPi::WiringPi::Constant> module.

=head1 GLOSSARY OF TERMS

    HIGH         -  connected to 3.3v (positive)
    LOW          -  connected to 0v (ground)
    floating     -  state where a pin is not stable at HIGH or LOW
    PWM          -  Pulse Width Modulation (potentiometer-like)
    INPUT        -  pin is listening only
    OUTPUT       -  pin is active in turning things on/off
    PWM_OUT      -  pin is OUTPUT, but PWM capable
    GPIO_CLOCK   -  pin is used for timing
    PUD          -  internal pull up/down resistor
    PUD_UP       -  PUD resistor pulled to HIGH
    PUD_DOWN     -  PUD resistor pulled to LOW
    EDGE_FALLING -  a state when a pin goes from HIGH to LOW
    EDGE_RISING  -  a state when a pin goes from LOW to HIGH
    EDGE_BOTH    -  both of the above states

=head1 HOWTO

=head2 Setup: Configure your system

If you want to avoid using your system installed Perl installation to use this
software (or you want to use interrupts), you should do some pre-configuration
of your system. Note that the system installed Perl does not use threads, which
is required for interrupts to function.

As your normal, every day user, install L<perlbrew|http://perlbrew.pl>, Then
install an instance of Perl, and switch to it:

    perlbrew install perl-5.24.0
    perlbrew switch perl-5.24.0

To use C<sudo> to run your scripts within the appropriate Perl
installation, you need to modify the C</etc/sudoers> file. Prepend the string
value for the C<secure_path> directive to include the path to the new
C<perlbrew> managed perl, followed by a colon. For example:
C</home/pi/perl5/perlbrew/perls/perl-5.24.0/bin:>. Leave the existing part of
the string in place.

Now, you can do everything with the normal user account, using their personal
installation of Perl, and you just need C<sudo> to run your scripts, leaving
your default system installation intact.

=head2 Pi: Create a Raspberry Pi object

The first thing you need to do is call an appropriate setup method. We do
that automatically. See L<new()|RPi::WiringPi/"new-args"> to see how to use
non-default setup routines. By default, we use the GPIO pin numbering scheme.
Run the included C<pinmap> program to get a printout of a chart containing the
various pin numbers for the different mapping schemes.

    my $pi = RPi::WiringPi->new;

=head2 Pin: Creating and using a GPIO pin object

The L<RPi::WiringPi::Pin> class provides you with objects that directly map to
the Raspberry Pi's onboard GPIO pins. You generate a pin object through the
main C<$pi> object we created above.

    my $pin = $pi->pin(27);

    # set the mode to output, presumably to power an external device

    $pin->mode(OUTPUT);

    # by default, pins are set to LOW (ie. 0 voltage). Turn it on...

    $pin->write(HIGH);

    # get the current status of a pin (HIGH or LOW)

    my $state = $pin->read;

    # get a pin's pin number

    my $num = $pin->num;

=head2 Pin: Setting a pin's internal pull up/down resistor

All GPIO pins on the Raspberry Pi have built-in pull up/down resistors to
prevent pins being in a "floating" state when not connected to either ground or
power. This is very important in many situations, particularly when using
interrupts.

    # HIGH when not in use

    $pin->pull(PUD_UP);

    # LOW when not in use

    $pin->pull(PUD_DOWN);

=head2 Pin: Using Pulse Width Modulation (PWM)

Pulse Width Modulation kind of acts like a potentiometer (or a variable
switch... like a light dimmer). They are used to send pulses of electricity
to a device across time. It is required for things like stepper motors, or
dimming an LED. Note that only physical pin C<12> on the Raspberry Pi has
hardware-based PWM (GPIO #18).

    # set the pin to PWM_OUT mode. Must be physical pin 12

    $pin->mode(PWM_OUT);

    # values are 0-1023 which represent 0% to 100% power

    $pin->pwm(512); # pin output is ~50%

    # make pin go from off to bright gradually...
    # requires Time::HiRes qw(usleep);

    my $pin = $pi->pin(18);
    $pin->mode(PWM_OUT);

    for (0..1023){
        $pin->pwm($_);
        usleep 50000;
    }

=head2 Pin: Using interrupts

Built in is the ability to have Perl code you define executed when a pin's edge
changes (a pin goes from LOW to HIGH or vice-versa). This code acts as an
interrupt handler. The Interrupt Service Request that listens for the change
runs in a separate C thread than your application.

Interrupts are useful in many cases, but think of a button; you want an action
to happen when someone presses a physical button on your prototype, but you
obviously want to be doing other things while waiting for that button press.

    # set an interrupt handler for when the pin goes from
    # LOW to HIGH. The second parameter is the string name
    # of the Perl subroutine at the bottom of this example

    $pin->interrupt_set(EDGE_RISING, 'handler');

    # HIGH to LOW

    $pin->interrupt_set(EDGE_FALLING, 'handler');

    # HIGH and LOW (handler will be called on both changes)

    $pin->interrupt_set(EDGE_BOTH, 'handler');

    sub handler {
        print "in handler\n";
        # do other stuff, perhaps turning on/off other pins
    }

=head2 Interrupt: Overview

Although we've already used interrupts from within a pin object, you can use
them separately as well.

=head2 Interrupt: Configuring

    my $interrupt = $pi->interrupt;

    # set an EDGE_RISING interrupt on pin 27

    # callback is the string name of your handler
    # subroutine that'll be called when an interrupt
    # has occurred

    $interrupt->set(27, EDGE_RISING, 'callback');

    sub callback {
        ...
    }

=head2 Serial Peripheral Interface (SPI)

Allows you to write to and read from devices attached to the SPI bus, using the
external L<RPi::SPI> distribution. Please refer to that documentation for full
usage instructions.

    # generate a new SPI object

    my $channel = 0; # /dev/spidev0.0

    my $spi = $pi->spi($channel);

    my $buf = [0x01, 0x02];
    my $len = 2;

    # write the two bytes in the buffer to channel /dev/spidev0.0

    $spi->rw($buf, $len);

=head2 Analog to Digital Converter

This functionality is brought in from L<RPi::ADC::ADS>. Please refer to that
documentation for full usage instructions.

    # fetch a new ADC object

    my $adc = $pi->adc;

    # fetch the voltage level on pin A0 on the ADC

    my $v = $adc->volts(0);

    # fetch the percentage of input on pin A0

    my $p = $adc->percent(0);

=head2 Shift Register: Utilization

This software has the capability to add up to four 74HC595 shift registers.
This allows you to add up to eight extra output pins per register.

We'll get right into the code:

    # the new register pins will start at GPIO 100.
    # this can be any number outside of existing GPIO

    my $base = 100;
    
    # the number of pins on the register(s) you plan on
    # using. Maximum eight per register

    my $num_pins = 8;

    # the GPIO pin number that the register's DS pin (14)
    # is connected to

    my $data = 5;

    # the GPIO pin number that the register's SHCP pin (11)
    # is connected to. This is the register's clock

    my $clk = 6;

    # the GPIO pin number that the register's STCP pin (12)
    # is connected to. This is the register's latch pin

    my $latch = 13;

    # initialize the register

    $pi->shift_register($base, $num_pins, $data, $clk, $latch);

    # now you have full access to the register's eight outputs
    # through standard methods

    for (100..107){
        my $pin = $pi->pin($_);
        $pin->write(HIGH);
    }

=head2 Board: Get the GPIO layout

    my $revision = $pi->gpio_layout;

=head2 LCD: Initialize

Typical 16-pin, 2-4 row and 16-20 column LCD screens work here. You can use
4-bit or 8-bit mode (4-bit requires 6 GPIO pins, 8-bit requires 10). If you
need a higher rate of data transmission to the LCD, use 8-bit mode. Typically,
4-bit has always worked perfectly for me.

Before an LCD can be used, it must be initialized. This may look like a lot,
but you only need to do it once. Essentially, you're configuring all pins up
front.

NOTE: When in 4-bit mode, although you're setting C<d0> through C<d3> pins
up and leaving C<d4> through C<d7> as C<0>, the wiring must connect to LCD pins
C<d4> through C<d7>. Look at LCD pin 4-7 as LCD pin 0-3 when in 4-bit mode.

    my $lcd = $pi->lcd;

    my %lcd_args = (
        rows  => 2,     # number of display rows, 2 or 4
        cols  => 16,    # number of display columns 16 or 20
        bits  => 4,     # data width in bits, 4 or 8
        rs    => 1,     # GPIO pin for the LCD RS pin
        strb  => 2,     # GPIO pin for the LCD strobe (E) pin
        d0    => 3,     #
        ...             # d0-d3 GPIO pinout numbers
        d3    => 6,     #
        d4    => 7,     # set d4-d7 to all 0 (zero) if in 4-bit mode
        ...             # otherwise, set them to their respective
        d7    => 11     # GPIO pins
    );

    $lcd->init(%lcd_args);

=head2 LCD: Display operations

Now that we've initialized the LCD, we're ready to use it.

    # turn the display on/off. It's on by default

    $lcd->display(ON);  # or OFF

    # put the cursor at col 0, row 0

    $lcd->home;

    # clear the display and move cursor to home

    $lcd->clear;

=head2 LCD: Cursor operations

    # move the cursor to a position

    $lcd->position(0, 0);   # col 0 (first slot), row 0 (top row)
    $lcd->position(0, 1);   # col 0 (first slot), row 1 (bottom row on 2 row LCD)
    $lcd->positon(5, 1);    # col 5 (6th slot), row 1

    # turn on/off cursor (on by default)

    $lcd->cursor(OFF);  # or ON

    # make the cursor blink (off by default)

    $lcd->cursor_blink(ON); # or OFF

=head2 LCD: Output operations

By default, output starts at col 0 and row 0 of the display. Use C<position()>
to move it around before outputting.

    # print out a string

    $lcd->print("My name is stevieb");

=head2 LCD: Putting it all together

Here's a trivial script that outputs information to specific LCD positions
(we'll start right after an LCD C<init()>).

    my $perl_ver = '5.24.0';
    my $name = 'stevieb';

    $lcd->home;

    $lcd->print("${name}'s RPi, on");
    $lcd->position(0, 1);
    $lcd->print("Perl $perl_ver...");

=head2 BMP180 barometric sensor

A full use-case example of using the barometric/temperature sensor:

    my $pin_base = 200; # any number higher than the highest GPIO

    my $bmp = $pi->bmp($pin_base);

    my $f = $bmp->temp;
    my $c = $bmp->temp('c');
    my $p = $bmp->pressure; # kPa

=head2 Util: Overview

The included L<RPi::WiringPi::Util> module contains a few helper-type methods
for internal and external use. Most of these you won't need, but others are
very helpful when writing your own scripts that go beyond trivial.

You can transform pin numbers from one scheme to another, get full pin number
maps/translation hashes, manually export and unexport GPIO pins etc.

It's worth having a look at...

=head1 AUTHOR

Steve Bertrand, E<lt>steveb@cpan.orgE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2016 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.
