I wrote this little program to display random messages and caller ID information on my BetaBrite LED Sign. (These used to be available at Sam's club for about $200.) A word about the hardware setup: This is coded for an old PC of mine running Windows 98. The sign is connected to COM2 and my caller-id-capable modem is connected to COM1.

The program reads message strings to display from the file "messages." Each message is assumed to occupy one line. If the string begins with "sub {" it is treated as a subroutine that returns a string to be displayed -- good for random or other run-time content.

The program has a primitive gui that I built with the Gui Loft. The only option available is to display or suppress the random messages (via a checkbox). If the random messages are enabled, one is picked at random (duh!) and displayed with a random mode, e.g., flashing, "snowing", etc. A different message is selected every few seconds.

Caller ID info is displayed even when the random messages are suppressed. Polling the modem for incoming calls occurs in the my_sleep routine (while we're waiting to select the next message.)

Comments and suggestions are welcome.

laughingboy

#! perl -w use strict; use Win32::SerialPort; use Win32::GUI; use Win32; use Win32::GUI::Loft::Design; use constant ROTATE => 1; # "a" use constant HOLD => 2; # "b" use constant FLASH => 3; # "c" use constant ROLLUP => 4; # "e" use constant ROLLDOWN => 5; # "f" use constant ROLLLEFT => 6; # "g" use constant ROLLRIGHT => 7; # "h" use constant WIPEUP => 8; # "i" use constant WIPEDOWN => 9; # "j" use constant WIPELEFT => 10; # "k" use constant WIPERIGHT => 11; # "l" use constant SCROLL => 12; # "m" use constant AUTOMODE => 13; # "o" use constant ROLLIN => 14; # "p" use constant ROLLOUT => 15; # "q" use constant WIPEIN => 16; # "r" use constant WIPEOUT => 17; # "s" use constant COMPROTATE => 18; # "t" use constant TWINKLE => 19; # "n0" use constant SPARKLE => 20; # "n1" use constant SNOW => 21; # "n2" use constant INTERLOCK => 22; # "n3" use constant SWITCH => 23; # "n4" use constant SLIDE => 24; # "n5" use constant SPRAY => 25; # "n6" use constant STARBURST => 26; # "n7" use constant NUM_MODES => 26; my $bShowRandom = 0; my $ob; my $ob2; my @msgs; my %modestring = ( ROTATE , "a", HOLD , "b", FLASH , "c", ROLLUP , "e", ROLLDOWN , "f", ROLLLEFT , "g", ROLLRIGHT , "h", WIPEUP , "i", WIPEDOWN , "j", WIPELEFT , "k", WIPERIGHT , "l", SCROLL , "m", AUTOMODE , "o", ROLLIN , "p", ROLLOUT , "q", WIPEIN , "r", WIPEOUT , "s", COMPROTATE , "t", TWINKLE , "n0", SPARKLE , "n1", SNOW , "n2", INTERLOCK , "n3", SWITCH , "n4", SLIDE , "n5", SPRAY , "n6", STARBURST , "n7" ); sub ::winMain_Activate { # send twenty nulls so sign can detect baud rate my $nulls = pack("a20"); $ob->write($nulls); ClearDisplay(); my $counter = 1; my ($mode, $msgnum, $oldmsgnum, $msg); while (1) { Win32::GUI::DoEvents(); if ($bShowRandom) { $mode = int(rand NUM_MODES) + 1; $oldmsgnum = $msgnum; $msgnum = int(rand @msgs) until $msgnum != $oldmsgnum; $msg = $msgs[$msgnum]->(); SendMessage($msg, $mode); } my_sleep(6); } undef $ob; undef $ob2; return(1); } sub ::winMain_Terminate { return(-1); } sub ::chbShowRandom_Click { #The Name property of the loaded window is "winMain" defined(my $win = $Win32::GUI::Loft::window{winMain}) or return(1); $bShowRandom = $win->chbShowRandom->Checked(); ClearDisplay() if $bShowRandom == 0; return(1); } sub my_sleep { my ($delay) = @_; my ($date, $time, $name, $nmbr); $ob2->read_interval(100); $ob2->read_const_time($delay * 1000); my ($count, $result) = $ob2->read(1000); # print "waited $delay seconds, count = $count, result = *$result*\n +" if $count != 0; ($date, $time, $name, $nmbr) = ($result =~ /DATE = (.*)\nTIME = (. +*)\nNAME = (.*)\nNMBR = (.*)\n/); if ($name || $nmbr) { # print "name initialized to *$name*\n"; # print "length of name is ", length($name), "\n"; # print "nmbr initialized to *$nmbr*\n"; # print "length of nmbr is ", length($name), "\n"; $name = "Unknown Caller" if ($name =~ /^\s*O\s*$/); $nmbr = "Unknown Number" if ($nmbr =~ /^\s*O\s*$/); $nmbr =~ s/(\d\d\d)(\d\d\d)(\d\d\d\d)/($1)-$2-$3/; $nmbr =~ s/(\d\d\d)(\d\d\d\d)/$1-$2/; # print "name is $name\n"; # print "nmbr is $nmbr\n"; # print "date is $date\n"; # print "time is $time\n"; for (my $i = 1; $i <= 3; $i++) { # print "sending name...$name...\n"; SendMessage($name, HOLD); sleep(3); # print "sending number...$nmbr...\n"; SendMessage($nmbr, HOLD); sleep(3); } ClearDisplay(); } } sub SendMessage { my ($string, $mode) = @_; my $len = length($string); my $modestr = $modestring{$mode}; my $modelen = length($modestr); my $msg = pack("ca3ca2caa${modelen}a${len}c", 1, "Z00", 2, "AA", 27, + " ", $modestr, $string, 4); $ob->write($msg); } sub ClearDisplay { SendMessage(" ", HOLD); } print "reading messages...\n"; open(MSGS, "messages") || die("can't open messages: $!"); while (my $msg = <MSGS>) { chomp $msg; push @msgs, ($msg =~ /^sub \{/) ? eval $msg : sub { $msg; }; } print "Initializing sign port...\n"; $ob = Win32::SerialPort->new ('COM2') || die; $ob->user_msg(1); # misc. warnings $ob->error_msg(1); # hardware and data errors $ob->baudrate(9600); $ob->parity("even"); $ob->parity_enable(1); # for any parity except "none" $ob->databits(7); $ob->stopbits(1); $ob->handshake('none'); $ob->write_settings; my ($count, $result); print "Initializing modem port...\n"; $ob2 = Win32::SerialPort->new ('COM1') || die; $ob2->user_msg(1); # misc. warnings $ob2->error_msg(1); # hardware and data errors $ob2->baudrate(9600) || die "fail setting baud"; $ob2->parity('none') || die "fail setting parity"; $ob2->databits(8) || die "fail setting databits"; $ob2->stopbits(1) || die "fail setting stopbits"; $ob2->handshake('none') || die "fail setting handshake"; $ob2->write_settings || die "no settings"; print "Setting up caller ID...\n"; $ob2->write("at#cid=1\r"); $ob2->read_interval(100); $ob2->read_const_time(1000); ($count, $result) = $ob2->read(20); # print "count = $count, result = $result\n"; print "Finished setting up caller ID...\n"; my $fileWindow = "SignGUI.gld"; my $objDesign = Win32::GUI::Loft::Design->newLoad($fileWindow) or die("Could not open window file ($fileWindow)"); my $win = $objDesign->buildWindow() or die("Could not build window ($f +ileWindow)"); $win->{-dialogui} = 1; $win->Show(); Win32::GUI::Dialog();

Edited: ~Thu Jul 11 20:13:14 2002 (GMT), by footpad:
Added <readmore> tag


In reply to Caller ID Display / LED Sign Driver by laughingboy

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.