# sda10.pm # (C)2001 Paris Sinclair # Control library for data acquisition module 232SDA10 # from B&B Electronics http://www.bb-elec.com package sda10; use strict; use warnings; use POSIX; use Fcntl; use IO::Select; use IO::Handle; #public data our $TIMEOUT_AD = .03; our $TIMEOUT_D = .26; our $TIMEOUT_SO = 1; our $BUFFER_SIZE = 1024; # private data my $_select = new IO::Select; $_select->add( \*STDOUT ); #put in something that will never be ready to read :) sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; bless $self, $class; $self->{dev} = shift || '/dev/ttyS1'; $self->{baud} = B9600; sysopen( $self->{fh}, $self->{dev}, O_RDWR | O_NOCTTY ) or die "failed opening serial device ".$self->{dev}.": $!"; $self->{termios_old} = POSIX::Termios->new(); $self->{termios_old}->getattr( $self->{fh} ); $self->{termios} = POSIX::Termios->new(); $self->{termios}->setispeed( $self->{baud} ); $self->{termios}->setcflag( CS8 | CLOCAL | CREAD ); $self->{termios}->setiflag( IGNPAR ); $self->{termios}->setattr( $self->{fh} ); $self->{flags} = chr(0); $self->{fh}->blocking( 0 ); return $self; } sub get_ad_flags { no warnings; my $self = shift or return undef; my $n_channels = (shift @_) - 1; $n_channels = 0 unless defined $n_channels and $n_channels <= 13; return undef unless $self->send_read_ad( $n_channels ) == 5; ($_select->can_read( $TIMEOUT_AD * ($n_channels + 1) )); my $flags = $self->read_sda; my @channels = (); for ( my $i = 0; $i < length $flags; $i += 2 ) { my $msb = ord( substr $flags, $i, 1 ); my $lsb = ord( substr $flags, $i+1, 1); unshift @channels, "$msb$lsb"; } if ( (+length $flags) * .5 < $n_channels ) { $channels[((length $flags)*.5)..$n_channels] = 0; } return @channels; } sub send_read_ad { my $self = shift; defined( my $n_channels = +shift ) or return undef; my $bytes = syswrite( $self->{fh}, '!0RA'.chr($n_channels) ); return $bytes; } sub get_d_flags { my $self = shift or return undef; unless ( $self->send_read_d( $self->{fh} ) == 4 ) { return undef; } return $self->read_sda; } sub send_read_d { my $self = shift or return undef; my $bytes = syswrite( $self->{fh}, '!0RD' ); ($_select->can_read( $TIMEOUT_D )); return $bytes; } sub read_sda { my $self = shift or return undef; my $data = ""; defined( my $bytes = $self->{fh}->sysread( $data, $BUFFER_SIZE ) ) or warn "error reading from ".$self->{dev}.": $!"; $self->{flags} = $data; return $data; } sub toggle_out1 { my $self = shift; my $flag = vec( $self->{flags}, 0, 1 ); vec( $self->{flags}, 0, 1 ) = !($flag); my $bytes = syswrite( $self->{fh}, '!0SO'.$self->{flags} ); ($_select->can_read( $TIMEOUT_SO )); } sub toggle_out2 { my $self = shift; my $flag = vec( $self->{flags}, 1, 1 ); vec( $self->{flags}, 1, 1 ) = !($flag); my $bytes = syswrite( $self->{fh}, '!0SO'.$self->{flags} ); ($_select->can_read( $TIMEOUT_SO )); } sub toggle_out3 { my $self = shift; my $flag = vec( $self->{flags}, 2, 1 ); vec( $self->{flags}, 2, 1 ) = !($flag); my $bytes = syswrite( $self->{fh}, '!0SO'.$self->{flags} ); ($_select->can_read( $TIMEOUT_SO * 2)); } 1;