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 )