Device-FTDI
view release on metacpan or search on metacpan
lib/Device/FTDI/I2C.pm view on Meta::CPAN
my $self = shift;
print STDERR "FTDI MPSSE I2C REPEAT-START\n" if DEBUG;
# Release the lines without appearing as STOP
$self->write_gpio( DBUS, HIGH, I2C_SDA_OUT ) for 1 .. 10;
$self->write_gpio( DBUS, HIGH, I2C_SCL ) for 1 .. 10;
$self->i2c_start;
}
sub i2c_stop
{
my $self = shift;
print STDERR "FTDI MPSSE I2C STOP\n" if DEBUG;
my $f;
$self->write_gpio( DBUS, LOW, I2C_SDA_OUT );
# S&H delay
$self->write_gpio( DBUS, HIGH, I2C_SCL ) for 1 .. 10;
$f = $self->write_gpio( DBUS, HIGH, I2C_SDA_OUT ) for 1 .. 10;
return $f;
}
sub i2c_send
{
my $self = shift;
my ( $data, $more_f ) = @_;
printf STDERR "FTDI MPSSE I2C SEND %v02X\n", $data if DEBUG;
my $check = $self->{i2c_check_mode};
repeat {
my ( $byte ) = @_;
$self->write_bits( 8, $byte );
# Release SDA
$self->write_gpio( DBUS, HIGH, I2C_SDA_OUT );
my $f = $self->read_bits( 1 );
if( $check ) {
$f = $f->transform( done => sub {
my ( $ack ) = @_;
$ack eq "\x00" or
die "Received NACK to data byte\n";
});
}
if( $check >= CHECK_EACH_BYTE ) {
return $f;
}
else {
push @$more_f, $f;
return Future->done;
}
} foreach => [ split m//, $data ],
while => sub { !shift->failure };
}
use constant { WRITE => 0, READ => 1 };
sub i2c_sendaddr
{
my $self = shift;
my ( $addr, $rd, $more_f ) = @_;
printf STDERR "FTDI MPSSE I2C ADDR %02X %s\n", $addr, $rd ? "R" : "W" if DEBUG;
my $check = $self->{i2c_check_mode};
$self->write_bits( 8, pack "C", $rd | $addr << 1 );
# Release SDA
$self->write_gpio( DBUS, HIGH, I2C_SDA_OUT );
my $f = $self->read_bits( 1 );
if( $check ) {
$f = $f->transform( done => sub {
my ( $ack ) = @_;
$ack eq "\x00" or
die sprintf "Received NACK to addressing command to 0x%02X\n", $addr;
});
}
if( $check >= CHECK_AFTER_ADDR ) {
return $f;
}
else {
push @$more_f, $f;
return Future->done;
}
}
sub i2c_recv
{
my $self = shift;
my ( $len ) = @_;
my $data_in = "";
my $f;
foreach my $ack ( ( 1 ) x ( $len - 1 ), 0 ) {
$f = $self->read_bytes( 1 )
->on_done( sub { $data_in .= $_[0] } );
$f->on_done( sub { printf STDERR "FTDI MPSSE I2C READ %v02X\n", $_[0] } ) if DEBUG;
$f->on_fail( sub { printf STDERR "FTDI MPSSE I2C READ FAILED\n" } ) if DEBUG;
$self->write_bits( 1, chr( $ack ? LOW : HIGH ) );
# Release SDA
$self->write_gpio( DBUS, HIGH, I2C_SDA_OUT );
}
return $f->transform( done => sub { $data_in } );
}
=head2 write
( run in 1.173 second using v1.01-cache-2.11-cpan-71847e10f99 )