1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
#########################################################################################
# Package HiPi::Interface::PCA9544
# Description : Control NXP PCA9544A & Philips PCA9544 4 channel I2C MUX
# Copyright : Copyright (c) 2018 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::PCA9544;
#########################################################################################
use strict;
use warnings;
use parent qw( HiPi::Interface );
use HiPi qw( :i2c :rpi );
use Carp;
__PACKAGE__->create_ro_accessors( qw(
devicename
backend
) );
our $VERSION ='0.81';
use constant {
CHANNEL_BIT => 0x4,
CHANNEL_0 => 0x4,
CHANNEL_1 => 0x5,
CHANNEL_2 => 0x6,
CHANNEL_3 => 0x7,
CHANNEL_NONE => 0x0,
CHANNEL_MASK => 0x7,
INTERRUPT_0 => 0x10,
INTERRUPT_1 => 0x20,
INTERRUPT_2 => 0x40,
INTERRUPT_3 => 0x80,
};
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 => 0x70,
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 => 'i2c', # needs read without write
);
}
}
my $self = $class->SUPER::new(%params);
return $self;
}
sub set_channel {
my($self, $channel) = @_;
if(!defined($channel)) {
$self->write_control_register( CHANNEL_NONE );
} elsif( $channel =~ /^0|1|2|3$/ ) {
$self->write_control_register( $channel + CHANNEL_BIT );
} else {
warn 'invalid channel requested';
}
}
sub get_status {
my $self = shift;
my $register = $self->read_control_register();
my $channel = undef;
my $regbits = $register & CHANNEL_MASK;
if( $regbits & CHANNEL_BIT ) {
$channel = $regbits - CHANNEL_BIT;
}
return $channel unless( wantarray );
my @interrupts = (
( $register & INTERRUPT_0 ) ? 1 : 0,
( $register & INTERRUPT_1 ) ? 1 : 0,
( $register & INTERRUPT_2 ) ? 1 : 0,
( $register & INTERRUPT_3 ) ? 1 : 0,
);
return ( $channel , @interrupts );
}
sub read_control_register {
my( $self ) = @_;
my @bytes = $self->device->bus_read( undef, 1 );
return $bytes[0];
}
sub write_control_register {
my( $self , $regbyte) = @_;
$self->device->bus_write( $regbyte );
}
1;
__END__
|