#!/usr/bin/perl -w

############################
# dl1414ticker.pl
# output text on a DL1414 LED display
#
# (c) 2002 daduke <daduke@daduke.org>
# distribute freely
#
# requires Device::ParallelPort, Device::ParallelPort::drv::parport
# and Time::HiRes, all from CPAN
#
# takes any text from stdin and makes a nice ticker on the DL1414

use strict;
use Device::ParallelPort;	#for the parallel I/O
use Time::HiRes;	#for the timer

sub init();	#create the bitmasks
sub output($$);	#print one character on pos 0..3
sub write_string($);	#write a line as a ticker

my $port = Device::ParallelPort->new('parport:0');	#open the parport

my $padsize = 8;	#for the ticker, the text is padded with that many spaces
my $speed = 150000;	#speed for the ticker

my (@set1, @set2);
my (@write1, @write2);

init();

while (<>) {	#for each input line
	write_string($_);	#do the ticker
}

#--------------------------
sub init() {
	#the bit masks necessary to control the DL1414
	my @masks = qw(00000100 00000110 00001100 00001110 00000000 00000010 00001000 00001010 00000100 00000101 00001100 00001101 00000000 00000001 00001000 00001001);
	for my $i (0..3) {
		$set1[$i] = pack("B8", $masks[2*$i]);
		$set2[$i] = pack("B8", $masks[2*$i + 8]);
		$write1[$i] = pack("B8", $masks[2*$i + 1]);
		$write2[$i] = pack("B8", $masks[2*$i + 9]);
	}
}

sub output($$) {
	my ($char, $pos) = @_;	#write $char on $pos
	if ($pos < 4) {
		$port->set_control($set1[$pos]);	#select $pos, no write
		$port->set_data($char);	#output $char
		$port->set_control($write1[$pos]);	#write, $pos still selected
		$port->set_control($set1[$pos]);	#write off again
	} else {
		$port->set_control($set2[$pos-4]);	#select $pos, no write
		$port->set_data($char);	#output $char
		$port->set_control($write2[$pos-4]);	#write, $pos still selected
		$port->set_control($set2[$pos-4]);	#write off again
	}
}

sub write_string($) {
	my ($str) = @_;
	chomp $str;	#get rid of \n
	$str = uc " " x $padsize . $str . " " x $padsize;	#pad and uppercase
	my @string = split ('', $str);	#array with one char in each element
	my $pos = 0;	#position counter
	while ($pos < @string - 7) {	#for all characters
		for my $i (0..7) {	#loop for the 7 letters
			output($string[$pos+$i], $i);	#output 4 neighbouring chars
		}
		Time::HiRes::usleep ($speed);	#wait
		$pos++;	#next position
	}
}
