# # This Win32 program displays patterns of up to 8 LEDs # driven from a PC's parallel port and the speed of # the pattern is inversely based on CPU load. # # LEDs are hooked to the data pins (2-9) with 470 # ohm resistors and then to a ground pin (18-25). # Note that data pins are numbered 0-7 and that my # examples below are hooked up to a 7 segment # (figure 8) display. # # If you'd like a steady speed pattern or a program # to display characters take a look here: # # http://www.anderbergfamily.net/ant/ledcontrol/ # # Version 1.0 - 12/23/2007 # by Anthony Anderberg ant@anderbergfamily.net # # # Scott Penrose's parallel port direct-control module, # needed for direct port access. This requires inpout32.dll # use Device::ParallelPort; my $pp = Device::ParallelPort->new('win32:0'); if (!defined($pp)) { print "\nParallel port setup error: \n $! \n"; exit; } # # Set to a non-zero to leave a window # open and print useful info. # $debug = 0; # # This is used to get the current CPU load. # use Win32::OLE qw(in with); $WMI = Win32::OLE->new('WbemScripting.SWbemLocator') || die "Cannot access WMI on machine: ", Win32::OLE->LastError; $Services = $WMI->ConnectServer('localhost') || die "Cannot access WMI on machine: ", Win32::OLE->LastError; # # This lets us give sleep() non-integer values. # use Time::HiRes qw(sleep); # # This is the order the LEDs are turned on in, # it will depend on what order the LEDs are # hooked to the parallel port data pins. # @displayorder=(5,3,6,4,2,0,6,7); # Clockwise Figure 8 # @displayorder=(7,6,0,2,4,6,3,5); # Counter Clockwise Figure 8 # @displayorder=(5,3,0,2,4,7); # Clockwise Circle # @displayorder=(5,7,4,2,0,3); # Counter Clockwise Circle # @displayorder=(5,6,2,6); # Back and forth # # We need to know how many steps our # chosen pattern has. # $displaycount = @displayorder; # # Most of the time the data ports are all # 'on' to begin with, we'll turn them off. # for ($step=0;$step<=8;$step++) { $pp->set_bit($step, 0); } # # Here's our main loops, it does what you'd expect. # while (1) # Who ever said infinite loops are bad? { # # This block of code finds the current CPU load # $proc_count = 0; $proc_total = 0; $processor_set = $Services->InstancesOf("Win32_Processor"); foreach $proc (in($processor_set)) { if ($debug) { print "$proc->{'DeviceID'} $proc->{'LoadPercentage'}\n"; } $proc_count++; $proc_total = $proc_total + $proc->{'LoadPercentage'}; } $proc_avg = $proc_total / $proc_count; # # The amount of time between pattern updates # varies based on the proc load we just found. # if ($proc_avg == 0) { $sleeptime = 0.05; } elsif ($proc_avg < 6) { $sleeptime = 0.1; } elsif ($proc_avg < 11) { $sleeptime = 0.2; } elsif ($proc_avg < 26) { $sleeptime = 0.3; } elsif ($proc_avg < 50) { $sleeptime = 0.4; } else { $sleeptime = 0.5; } if ($debug) { print "Avg Proc Load: $proc_avg - Sleeptime: $sleeptime\n"; } # # Well go through the pattern 200 times then check # the CPU load, note that this means that during # high CPU loads out program checks the CPU load # less often. It also means that a smaller pattern # will result in checking the CPU speed more often. # for ($loopcount=0;$loopcount<200;$loopcount++) { # # This loop displays the pattern with the # speed based on the current processor load. # for ($step=0;$step<$displaycount;$step++) { # # This code chooses which LEDs to turn on and off. # $led=$displayorder[$step]; if ($step == 0) { $lastled=$displayorder[$displaycount-1]; } else { $lastled=$displayorder[$step-1]; } # # This code actually changes the LEDs. # $pp->set_bit($lastled, 0); $pp->set_bit($led, 1); if ($debug) { print "Step:$step - LED:$led - LastLED:$lastled\n"; } sleep($sleeptime); } } }