me8100_test_perl/ME8100.pm
changeset 32 e0b741bb5ce0
parent 31 33280ad0f4b2
equal deleted inserted replaced
31:33280ad0f4b2 32:e0b741bb5ce0
    10 
    10 
    11 my %Objects = ();
    11 my %Objects = ();
    12 my $gotSignal = 0;
    12 my $gotSignal = 0;
    13 my $opt_async = 0;
    13 my $opt_async = 0;
    14 
    14 
    15 sub iohandler($);
    15 sub _iohandler($);
    16 sub import { $opt_async = grep { /^:async/ } @_; }
    16 sub import { $opt_async = grep { /^:async/ } @_; }
    17 
    17 
    18 # Install the signal handler only if we have passed the ':async' tag
    18 # Install the signal handler only if we have passed the ':async' tag
    19 # to the module...
    19 # to the module...
    20 INIT { $SIG{IO} = \&iohandler if $opt_async; }
    20 INIT { $SIG{IO} = \&_iohandler if $opt_async; }
    21 
    21 
    22 # Create a new object. Open all the named devices (read only)
    22 # Create a new object. Open all the named devices (read only)
    23 # and read the current values (as the driver guarantees the
    23 # and read the current values (as the driver guarantees the
    24 # very first read to succeed).
    24 # very first read to succeed).
    25 # The order depends on the order the device names are passed 
    25 # The order depends on the order the device names are passed 
    57     $self->{fds} = [@fds];	    # list of fds
    57     $self->{fds} = [@fds];	    # list of fds
    58     $self->{select} = new IO::Select(@fds);
    58     $self->{select} = new IO::Select(@fds);
    59 
    59 
    60     $self->{bits} = $idx * 16;
    60     $self->{bits} = $idx * 16;
    61     $self->{inputBits} = $inputBits;
    61     $self->{inputBits} = $inputBits;
    62     $self->{oldBits} = "";		
    62     $self->{oldBits} = undef;		
    63     $self->{changedBits} = "";
    63     $self->{changedBits} = "";
    64 
    64 
    65     $self->{changed} = [split //, "0" x $self->{bits} ];
    65     $self->{changed} = [split //, "0" x $self->{bits} ];
    66     return $self;
    66     return $self;
    67 }
    67 }
    71     # race condition might occur: while we're waiting for the select()
    71     # race condition might occur: while we're waiting for the select()
    72     # to complete, the SIGIO might be catched.  Both, SIGIO as well as
    72     # to complete, the SIGIO might be catched.  Both, SIGIO as well as
    73     # the suddenly succeeding select() indicate a possible successful
    73     # the suddenly succeeding select() indicate a possible successful
    74     # read... But only one of them will be successful!
    74     # read... But only one of them will be successful!
    75 
    75 
    76     my ($self, $timeout) = @_;
    76     my ($self, %args) = @_;
    77 
    77 
    78     {
    78     {
    79 	local $SIG{IO} = sub { $gotSignal = $_[0] } if $opt_async;
    79 	local $SIG{IO} = sub { $gotSignal = $_[0] } if $opt_async;
    80 	my @ready = $self->{select}->can_read($timeout);
    80 	my @ready = $self->{select}->can_read($args{timeout});
    81 
    81 
    82 	if (!@ready) {
    82 	if (!@ready) {
    83 	    warn "select() returned nothing: $!\n";
    83 	    warn "select() returned nothing: $!\n";
    84 	    return undef;
    84 	    return undef;
    85 	}
    85 	}
    86 
    86 
    87 	$self->_read(@ready);
    87 	$self->_read(@ready);
    88     }
    88     }
    89 
    89 
    90     $gotSignal and iohandler($gotSignal);
    90     $gotSignal and _iohandler($gotSignal);
    91     $self->{changedBits} = "";
       
    92     $self->{changed} = [ split //, "0" x $self->{bits} ];
       
    93     return split //, unpack("b*", $self->{inputBits});
    91     return split //, unpack("b*", $self->{inputBits});
    94 }
    92 }
    95 
    93 
    96 sub status {
    94 sub status {
    97     my $self = shift;
    95     my $self = shift;
    98     return split //, unpack("b*", $self->{inputBits});
    96     return split //, unpack("b*", $self->{inputBits});
    99 }
    97 }
   100 
    98 
   101 # Read *really* from the board and store the result at the proper
    99 # Read *really* from the board and store the result at the proper
   102 # element of our @inputs array.
   100 # element of our @inputs array.
   103 sub _read {
   101 sub _read($@) {
   104     my ($self, @fds) = @_;
   102     my ($self, @fds) = @_;
   105     my $val;	# bit0-7 bit8-15
   103     my $val;	# bit0-7 bit8-15
   106 
   104 
   107     foreach my $fd (@fds) {
   105     foreach my $fd (@fds) {
   108 	my $idx = $self->{idx}->{$fd};
   106 	my $idx = $self->{idx}->{$fd};
   111     }
   109     }
   112 
   110 
   113     # Now get the difference between the old bits and the current values...
   111     # Now get the difference between the old bits and the current values...
   114     # and then add these values to the array containing the change counters
   112     # and then add these values to the array containing the change counters
   115     
   113     
       
   114     $self->{oldBits} = $self->{inputBits} if not defined $self->{oldBits};
   116     my $changedBits = $self->{inputBits} ^ $self->{oldBits};
   115     my $changedBits = $self->{inputBits} ^ $self->{oldBits};
   117 
   116 
   118     my @changed = split //, unpack("b*", $changedBits);
   117     my @changed = split //, unpack("b*", $changedBits);
   119     #print STDERR "o: ", unpack("b*", $self->{oldBits}), "\n";
   118     #print STDERR "o: ", unpack("b*", $self->{oldBits}), "\n";
   120     #print STDERR "n: ", unpack("b*", $self->{inputBits}), "\n";
   119     #print STDERR "n: ", unpack("b*", $self->{inputBits}), "\n";
   126 
   125 
   127     $self->{changedBits} |= $changedBits;
   126     $self->{changedBits} |= $changedBits;
   128     $self->{oldBits} = $self->{inputBits};
   127     $self->{oldBits} = $self->{inputBits};
   129 }
   128 }
   130 
   129 
   131 sub iohandler($) { 
   130 sub _iohandler($) { 
   132     # If an interrupt occurs, we've to search for the file descriptor(s)
   131     # If an interrupt occurs, we've to search for the file descriptor(s)
   133     # that caused the interrupt.  This is done by a lookup in the module global
   132     # that caused the interrupt.  This is done by a lookup in the module global
   134     # %Objects hash.  ("fd" -> { fd => XXX, object => XXXX })
   133     # %Objects hash.  ("fd" -> { fd => XXX, object => XXXX })
   135 
   134 
   136     my $signal = shift;
   135     my $signal = shift;
   137 
   136 
   138     # I do some magic(?) here, since the key isn't usable a a refence
   137     # I do some magic(?) here, since the key isn't usable a a refence
   139     # anymore, we stored the reference itself behind the key, as well
   138     # anymore, we stored the reference itself behind the key, as well
   140     # as the object reference...
   139     # as the object reference...
   141     
   140     
   142 
       
   143     # Now a race condition might occur.  It's possible that an other
       
   144     # select() runs too (called in the read() method).
       
   145     my $select = new IO::Select(map { $Objects{$_}->{fd} } keys %Objects);
   141     my $select = new IO::Select(map { $Objects{$_}->{fd} } keys %Objects);
   146     my @ready = $select->can_read(0);
   142     my @ready = $select->can_read(0);
   147 
   143 
   148     foreach (@ready) {
   144     foreach (@ready) {
   149 	my $object = $Objects{$_}->{object};
   145 	my $object = $Objects{$_}->{object};
   154 };
   150 };
   155 
   151 
   156 
   152 
   157 sub changed {
   153 sub changed {
   158     my $self = shift;
   154     my $self = shift;
       
   155     my @changed = @{$self->{changed}};
   159     my $r = 0;
   156     my $r = 0;
   160 
   157 
   161     wantarray and return @{$self->{changed}};
   158     $self->{changedBits} = "";
   162     foreach (@{$self->{changed}}) {
   159     $self->{changed} = [ split //, "0" x $self->{bits} ];
       
   160 
       
   161     wantarray and return @changed;
       
   162 
       
   163     foreach (@changed) {
   163 	$r += $_;
   164 	$r += $_;
   164     }
   165     }
   165     return $r;
   166     return $r;
   166 }
   167 }
   167 
   168 
   168 sub DESTROY
   169 #sub DESTROY
   169 {
   170 #{
   170     my $self = shift;
   171 #    my $self = shift;
   171     delete @Objects{ @{$self->{fds}} };
   172 #    delete @Objects{ @{$self->{fds} }};
   172 }
   173 #}
   173 
   174 
   174 
   175 
   175 #-- Documenation follows 
   176 #-- Documenation follows 
   176 
   177 
   177 =head1 NAME
   178 =head1 NAME
   197 
   198 
   198 =item new(I<device>,...)
   199 =item new(I<device>,...)
   199 
   200 
   200 Creates a new ME8100 object connected to all the listed devices.
   201 Creates a new ME8100 object connected to all the listed devices.
   201 
   202 
   202 =item read([I<timeout>])
   203 =item read(I<[timeout =E<gt> timeout]>)
   203 
   204 
   204 Read the input from the devices.  This call is guaranteed to succeede
   205 Read the input from the devices.  This call is guaranteed to succeede
   205 on the first run, but every following call will block until the status
   206 on the first run, but every following call will block until the status
   206 of the input changed.  (This behaviour is due to the driver.)
   207 of the input changed.  (This behaviour is due to the driver.)
   207 
   208 
   208 A timeout may be passed.
   209 A timeout may be passed.
   209 
   210 
   210 Every read() resets the register for obtaining the changed bits.
       
   211 
       
   212 On success an array of the input bits is returned, otherwise undef.
   211 On success an array of the input bits is returned, otherwise undef.
   213 
   212 
   214 =item status()
   213 =item status()
   215 
   214 
   216 Returns an array with the current status of all input bits.
   215 Returns an array with the current status of all input bits.
   217 Never blocks.
   216 Never blocks.  No side effects.
   218 
   217 
   219 =item changed()
   218 =item changed()
   220 
   219 
   221 Returns an array containing the number of detected changes per input
   220 In array context returns an array containing the counts of changes
   222 bit.
   221 for every single bit.  In scalar context returns the total number of
   223 
   222 changes.
   224 =item iohandler(I<signal>)
   223 
       
   224 Every call resets the counter.
       
   225 
       
   226 =item _iohandler(I<signal>)
   225 
   227 
   226 For internal use only.
   228 For internal use only.
   227 
   229 
   228 =item _read()
   230 =item _read()
   229 
   231