Welcome to Tribbeck.com

Matrix Orbital LK202-24-USB

I'd been given a Matrix Orbital a while ago, and a friend of mine (Rich Goodwin) had come up with some basic software to control it. It's downloadable from here. He didn't want to use LCDproc to control it - he wanted more manual control.

I did a bit of work on the software and sent it back to him - however, between us we never really did anything with it.

Since I didn't have a particular need for it, it languished on the top of my freezer for a while, until Friday 14th March 2009, I set up a new firewall/web server/email server, and I thought this would be ideal as a simple display panel.

I found the old code, and emailed Rich to let him know what I was doing. By coincidence, he'd just set up a new machine too, and wanted the code anyway.

Since it could be useful, I've decided to publish it. It's based on Rich's code (even has the comments in), with the following changes:

  • Performs the initialisation for you
  • Reads keys properly
  • Doesn't use too much CPU
#!/usr/bin/perl

# We use this to set the baud rate for the LCD unit
use POSIX qw(:termios_h);

# We use this to reduce CPU loading while having responsive keys
use Time::HiRes;
 
# open a file handle so we can write to the LCD screen
open LCD, "+< /dev/ttyUSB0" or die("Couldn't open connection to USB device");

# Get the file descriptor for the LCD connection
local $lcdfd = fileno(LCD);

# Set up the termios control
my $termios = POSIX::Termios->new;

# Set baud rate and so forth (taken from LCDd)
$termios->getattr($lcdfd);
$termios->setiflag($termios->getiflag & ~ (&POSIX::IGNBRK |
					   &POSIX::BRKINT |
					   &POSIX::PARMRK |
					   &POSIX::ISTRIP |
					   &POSIX::INLCR |
					   &POSIX::IGNCR |
					   &POSIX::ICRNL |
					   &POSIX::IXON));
$termios->setoflag($termios->getoflag & ~ (&POSIX::OPOST));
$termios->setlflag($termios->getlflag & ~ (&POSIX::ECHO |
					   &POSIX::ECHONL |
					   &POSIX::ICANON |
					   &POSIX::ISIG |
					   &POSIX::IEXTEN));
$termios->setcflag($termios->getcflag & ~ (&POSIX::CSIZE |
					   &POSIX::PARENB));
$termios->setcflag($termios->getcflag | (&POSIX::CS8 |
					 &POSIX::CREAD |
					 &POSIX::CLOCAL));
$termios->setcc(&POSIX::VMIN, 1);
$termios->setcc(&POSIX::VTIME, 3);
$termios->setospeed(&POSIX::B19200);
$termios->setispeed(&POSIX::B0);

# And actually set the values
$termios->setattr($lcdfd, &POSIX::TCSANOW);

# Make buffers flush immediately (only for printing keys)
$|=1;

# clear the screen - we'll do this 3 times, so use a subroutine
clear_screen();

# use the LCD file handle as the default print handle
# - instead of each print statement starting LCD,
# this is quicker.
select LCD;
    
# Pick out the relevant bits - uptime, users and current load average
if (`uptime` =~ m~up\s+(.*?),\s+(\d+)\s+users?,\s+load average: ([0-9\.]+),~i) {
    my $uptime = $1;
    my $users  = $2;
    my $load   = $3;
    
    # clear the print our info, 
    # wait for 5 seconds before moving on,
    # clear screen before printing more info.
    print "Uptime:\n";
    print "$uptime\n";
    wait_keys(5);
    clear_screen();
    print "Users:\n";
    print "$users\n";
    wait_keys(5);
    clear_screen();
    print "Current Load:\n";
    print "$load\n";
    wait_keys(5);

}

# Display the list of users (using 'who')
my $user = 1;
while(`who`=~m:([^ ]+).*?([^ ]+)[^\n]+\n:g) {
    clear_screen();
    print "User $user:\n";
    print "$1 on $2\n";
    wait_keys(5);
    $user++;
}

clear_screen();
print "Demonstration over!\n";
print "Please call again.\n";

# Now we're done printing to LCD,
# let's go back to STandarD OUTput
select STDOUT;

# We're finished writing to the LCD, so let's be neat
# and close the file handle we opened at the start
close LCD;

sub clear_screen {
    print LCD chr(254) . chr(88);
}

sub wait_keys {
    my $wait = shift;

    # We use this for finding out if we've been alarmed
    local $finished = 0;
    
    # Set the alarm to clear the flag
    $SIG{ALRM} = sub { $finished = 1; };

    # And set the time for the alarm to occur
    alarm($wait);

    # Repeat the following until the end...
    while($finished == 0) {
	# This bit is taken from the Perl FAQ
	# Works on Mandrake 10, Perl FAQ says it works on BSD
	local $rin;
        vec($rin, $lcdfd, 1) = 1;

	# Check to see if there's anything present
        if(select($rin, undef, undef, 0) > 0) {
	    # Read whatever's in there
	    my $l = "";
	    read LCD, $l, 1;
	    print STDOUT $l;
	} else {
	    Time::HiRes::usleep(10000);
	}
    }
}

OpenBSD

OpenBSD 4.4 can use this device natively (in fact, I think it was in 3.7 that it could be). Just change the /dev/ttyUSB0 to /dev/cuaU0 - although if you run it as a user, you need to make sure you have read/write access to the port.

Updated: 2011-06-08 20:40:59 | Comments: 0 | Show comments | Add comment
© Copyright 1997-2017
Tribbeck.com / Jason Tribbeck
All trademarks are the property of their respective owners.