#########################################################################################
# Package HiPi::Interface::PCF8574
# Description : Control NXP PCF8574 8-channel port extender
# Copyright : Copyright (c) 2013-2017 Mark Dootson
# License : This is free software; you can redistribute it and/or modify it under
# the same terms as the Perl 5 programming language system itself.
#########################################################################################
package HiPi::Interface::PCF8574;
#########################################################################################
use strict;
use warnings;
use parent qw( HiPi::Interface );
use HiPi qw( :i2c :rpi );
use Carp;
use Time::HiRes qw( usleep );
__PACKAGE__->create_ro_accessors( qw(
backend
) );
our $VERSION ='0.68';
sub new {
my ($class, %userparams) = @_;
my $pi = HiPi::RaspberryPi->new();
my %params = (
devicename => ( $pi->board_type == RPI_BOARD_TYPE_1 ) ? '/dev/i2c-0' : '/dev/i2c-1',
address => 0x3f,
device => undef,
backend => 'i2c',
);
# get user params
foreach my $key( keys (%userparams) ) {
$params{$key} = $userparams{$key};
}
unless( defined($params{device}) ) {
if ( $params{backend} eq 'bcm2835' ) {
require HiPi::BCM2835::I2C;
$params{device} = HiPi::BCM2835::I2C->new(
address => $params{address},
peripheral => ( $params{devicename} eq '/dev/i2c-0' ) ? HiPi::BCM2835::I2C::BB_I2C_PERI_0() : HiPi::BCM2835::I2C::BB_I2C_PERI_1(),
);
} else {
require HiPi::Device::I2C;
$params{device} = HiPi::Device::I2C->new(
devicename => $params{devicename},
address => $params{address},
busmode => $params{backend},
);
}
}
my $self = $class->SUPER::new(%params);
return $self;
}
sub read_byte {
my ( $self ) = @_;
my @bytes = $self->device->bus_read(undef, 1);
return $bytes[0];
}
sub write_byte {
my( $self, $byte) = @_;
$self->device->bus_write($byte & 0xFF);
}
sub read_bits {
my ( $self ) = @_;
my $byte = $self->read_byte;
my @bits;
for ( my $i = 0; $i < 8; $i++ ) {
push @bits, ( $byte >> $i ) & 1;
}
return @bits;
}
sub write_bits {
my( $self, @bits) = @_;
my $bitcount = @bits;
unless( $bitcount == 8 ) {
warn qq(Only $bitcount bits provided in write_bits. Needs 8);
return;
}
my $byte = 0;
for ( my $i = 0; $i < 8; $i++ ) {
$byte += ($bits[$i] & 1 ) << $i;
}
$self->write_byte( $byte );
}
sub set_bit {
my( $self, $bit, $value) = @_;
if($bit < 0 || $bit > 7) {
warn qq(Bit argument must be between 0 and 7 in set_bit. You passed $bit);
return;
}
if($value < 0 || $value > 1) {
warn qq(Value argument muist be 1 or 0 in set_bit. You passed $value);
return;
}
my @bits = $self->read_bits;
$bits[$bit] = $value;
$self->write_bits(@bits);
}
sub get_bit {
my( $self, $bit ) = @_;
if($bit < 0 || $bit > 7) {
warn qq(Bit argument must be between 0 and 7 in get_bit. You passed $bit);
return;
}
my @bits = $self->read_bits;
return $bits[$bit];
}
sub set_port { set_bit( @_ ); }
sub get_port { get_bit( @_ ); }
1;
__END__