#!/usr/bin/perl
#
# Programme d'affichage LCD sur 2 lignes x 20 caracteres  
# 
# This code is distributed under the terms of the GPL
#
# (c) 2003 Fisch Bob (bob@fesch.lu)
# http://www.fesch.lu
#
my $VERSION = 'LCD - Version 0.6';
#
# Designed initially for a CFAH2004AYYBJP 20x4 display
#

use strict;
use Fcntl;
use IO::Socket::INET;
use Time::HiRes qw(usleep gettimeofday);

#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Parallel Port Config
#
#  => This is the 1. part
#     you have to set up.
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

my $BASEPORT 	= 0x378;	# -> Look at the BIOS for this value


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  LCD Config
#
#  => This is the 2. part
#     you have to set up.
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

my $ROWS 		= 4;		# -> How many rows does your LCD have?
my $COLS		= 20;		# -> How many colums does it have?

## DOES NOT WORK YET !!! 
## ONLY 8 bit mode is supported
my $MODE	= 8; 			# -> In what mode is your LCD? 4 or 8 bits?


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Interface Config
#
#  => This is the 3. part
#     you have to set up.
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

my $IFACE   = 'ppp0';		# -> What is the interface you want to monitor?

my $UPBITS 	= 160;			# -> What's the maximum upload rate in bits/second of your line?
my $DOWNBITS	= 1216;		# -> What's the maximum downlaod rate in bits/second of your line?


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Catch signals
#
#  => Don't touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

$SIG{INT} 	= \&catch_sig;
$SIG{HUP} 	= \&catch_sig;
$SIG{TERM} 	= \&catch_sig;
$SIG{QUIT} 	= \&catch_sig;


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Global Variables
#
#  => Don't touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

my $scroll 	= '';
my $ixui 	= '';
my $ixuiTS 	= -1;
my ($seconds1, $microseconds1);
my ($seconds2, $microseconds2);


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Debug Variables
#
#  => Don't touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

my $DEBUG_BUTTONS = 0;


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Cache Variables
#
#  => Don't touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

my @LINECACHE 	= ('','','','');  
my $CACHE_DOWN 	= '';
my $CACHE_DOWN_BAR	= '';
my $CACHE_UP_BAR 	= '';
my $CACHE_DL 		= -1;
my $CACHE_UL		= -1;
my $CACHE_IXUI	= '';


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Timing Variables
#
#  => Don't touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

my $TIME_DOWN     		= 0;
my $TIME_DONW_BAR 		= 0;
my $TIME_UP_BAR 		= 0;
my $TIME_IXUI			= 0;


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Menu Variables
#
#  => Don't touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

my $MENU_LINE = 0;


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Constants
#
#  => Don't touch this!
#     These are different
#     system constants.
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

my $base_port = $BASEPORT;
my $status_port = $BASEPORT + 1;
my $control_port = $BASEPORT + 2;


### E and RW must be inverted because are 
### attached to control pin 0 and 1 that 
### are logically inverted by parallel port

my $E_HIGH	= 0;
my $E_LOW	= 1;
my $RW_HIGH	= 0;
my $RW_LOW	= 2;
my $RS_HIGH	= 4;
my $RS_LOW	= 0;

my $BACK_ON	= 0x00;
my $BACK_OFF	= 0x08;

my $CLEARDISPLAY 	= 0x01;

my $RETURNHOME	= 0x02;

my $ENTRYMODE	= 0x04;
my $INCREMENT	= 0x02;
my $DECREMENT	= 0x00;
my $SHIFT_ON		= 0x01;
my $SHIFT_OFF	= 0x00;

my $DISPLAY		= 0x08;
my $DISPLAY_ON	= 0x04;
my $DISPLAY_OFF	= 0x00;
my $CURSOR_ON	= 0x02;
my $CURSOR_OFF	= 0x00;
my $BLINK_ON		= 0x01;
my $BLINK_OFF	= 0x00;

my $SHIFTMODE	= 0x10;
my $DISPLAY_SELECT	= 0x08;
my $CURSOR_SELECT	= 0x00;
my $RIGHT		= 0x01;
my $LEFT		= 0x00;

my $FUNCTIONSET	= 0x20;
my $EIGHTBITMODE	= 0x10;
my $FOURBITMODE	= 0x00;
my $TWOLINES		= 0x08;
my $ONELINE		= 0x00;
my $FONT5X11		= 0x01;
my $FONT5X8		= 0x00;

my $SETCGRAMADDRESS        	= 0x40;
my $CGRAM_ADDRESS_MASK     	= 0x3f;

my $SETDDRAMADDRESS		= 0x80;
my $DDRAM_ADDRESS_MASK     	= 0x7f;

my $READ_BF_AND_ADDRESS  	= 0x100;
my $BF_MASK     			= 0x80;
my $ADDRESS_MASK     		= 0x7f;

my $WRITE_TO_RAM         	= 0x200;
my $WRITE_TO_RAM_ADDRESS_MASK  = 0xff;

my $READ_FROM_RAM              = 0x300;
my $READ_FROM_RAM_ADDRESS_MASK = 0xff;

my $SECONDLINEOFFSET = 0x40;


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Button Constants
#
#  => Don't touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

my $LAST_BYTE = 0x00;

my $STATE_DOWN = 0;
my $STATE_UP   = 1;

my $STATE_BUSY = $STATE_UP;
my $STATE_ACK  = $STATE_UP;
my $STATE_PE   = $STATE_UP;
my $STATE_SI   = $STATE_UP;
my $STATE_ERR  = $STATE_UP;

my $BUTTON_BUSY = 0x80;
my $BUTTON_ACK  = 0x40;
my $BUTTON_PE   = 0x20;
my $BUTTON_SI   = 0x10;
my $BUTTON_ERR  = 0x08;


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Initialisation
#
#  => Here the LCD is being
#     initialised and some
#     operations, depending
#     on the script parameters
#     are executed.
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

if(
   ($ARGV[0] eq '-loop') || 
   ($ARGV[0] eq '-init')
   )
{
 &lcd_init; 			# <- init the LCD

 &generate_bars; 		# <- setup bars (user characters 0-4)
 &generate_heart;		# <- setup hearts (user characters 5-6)
}

if(
   ($ARGV[0] eq '-') || 
   ($ARGV[0] eq '-text') || 
   ($ARGV[0] eq '-line') || 
   ($ARGV[0] eq '-xy')
  )
{
 &clear_display;		# <- clear the display
}

if(
   ($ARGV[0] eq '-init')
   )
{
 &set_data_at(0,0,0);	# <- Put some bars on the screen
 &set_data_at(1,0,1);	# <- to show the initialisation 
 &set_data_at(2,0,2);	# <- has been done.
 &set_data_at(3,0,3);
 &set_data_at(4,0,4);
}

#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Loop
#
#  => This is the 4. part
#     you may set up.
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

 ##### possible function calls
 #
 # get_system_load			SYSTEM_LOAD
 # get_cpu_idle			CPU_IDLE
 # get_name				NAME
 # get_uptime				UPTIME
 # get_swap				SWAP
 # get_downupload 			DOWNUPLOAD
 # get_ipconnected 			IPCONNECTED
 # get_connected_machines		MACHINES
 # get_time				TIME
 # get_bar_down			BAR_DOWN
 # get_bar_up				BAR_UP
 # get_bar_down_val			BAR_DOWN_VAL
 # get_bar_up_val			BAR_UP_VAL
 # get_mount_1			MOUNT_1
 # get_mount_2			MOUNT_2
 # get_mount_3			MOUNT_3
 # get_ixui				IXUI
 # 
 ##### ATTENTION
 #
 #  Do not use get_bar_X and get_bar_X_val
 #  at the same time!
 #
 #####

my @FUNCTIONS = (
                 'SYSTEM_LOAD',		# 0
		     'CPU_IDLE',		# 1
		     'NAME',			# 2
		     'UPTIME',		# 3
		     'SWAP',			# 4
		     'DOWNUPLOAD',		# 5
		     'IPCONNECTED',		# 6
		     'MACHINES',		# 7
		     'TIME',			# 8
		     'BAR_DOWN',		# 9
		     'BAR_UP',		# 10
		     'BAR_DOWN_VAL',	# 11	
		     'BAR_UP_VAL',		# 12
		     'MOUNT_1',		# 13
		     'MOUNT_2',		# 14
		     'MOUNT_3',		# 15
		     'IXUI'			# 16
                );

my @LINE_FUNC = (8,0,12,11);
if(fileExists('lcd.conf'))
{
 &load_LINES;
}
my @MENU = (\&get_line,\&get_function,\&get_none,\&get_version);

sub get
{
 my $who = shift;
 my $res = \&get_none;
 if($who eq 'SYSTEM_LOAD') 	{$res = \&get_system_load;} 
 if($who eq 'CPU_IDLE') 		{$res = \&get_cpu_idle;} 
 if($who eq 'NAME') 		{$res = \&get_name;} 
 if($who eq 'UPTIME') 		{$res = \&get_uptime;} 
 if($who eq 'SWAP') 		{$res = \&get_swap;} 
 if($who eq 'DOWNUPLOAD') 		{$res = \&get_downupload;} 
 if($who eq 'IPCONNECTED') 	{$res = \&get_ipconnected;} 
 if($who eq 'MACHINES') 		{$res = \&get_connected_machines;} 
 if($who eq 'TIME') 		{$res = \&get_time;} 
 if($who eq 'BAR_DOWN') 		{$res = \&get_bar_down;} 
 if($who eq 'BAR_UP') 		{$res = \&get_bar_up;} 
 if($who eq 'BAR_DOWN_VAL') 	{$res = \&get_bar_down_val;} 
 if($who eq 'BAR_UP_VAL') 		{$res = \&get_bar_up_val;} 
 if($who eq 'MOUNT_1') 		{$res = \&get_mount_1;} 
 if($who eq 'MOUNT_2') 		{$res = \&get_mount_2;} 
 if($who eq 'MOUNT_3') 		{$res = \&get_mount_3;} 
 if($who eq 'IXUI')	 		{$res = \&get_ixui;} 
 return $res;
}

if($ARGV[0] eq '-loop')
{

 my $STATE = $STATE_SI;
 while(1)
 {

  if($STATE_SI==$STATE_UP)
  {
   &set_wait();
   for(my $i=0;$i<$ROWS;$i++)
   {
    &set_line($i,&{get(@FUNCTIONS[@LINE_FUNC[$i]])}());
   } 
   &make_wait(100);
  }
  else
  {
   &set_wait();
   for(my $i=0;$i<$ROWS;$i++)
   {
    &set_line($i,&{@MENU[$i]}());
   } 

   #&set_line(0,&get_line());
   #&set_line(1,&get_function());
   &make_wait(100);
  }
 }

 if($STATE != $STATE_SI)
 {
  $STATE=$STATE_SI;
  &clear_display;
 }
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Direct Text Output
#
#  => do not touch
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

if(($ARGV[0] eq '-') || ($ARGV[0] eq '-text') || ($ARGV[0] eq '-line') || ($ARGV[0] eq '-xy'))
{
 my $count = @ARGV;
 my $sentence = '';

 my $row = 0;
 my $start = 1;
 my $col = 0;
 if($ARGV[0] eq '-line')
 {
  $row = $ARGV[1];
  $start = 2;
 }

 if($ARGV[0] eq '-xy')
 {
  $row = $ARGV[1];
  $col = $ARGV[2];
  $start = 3;
 }

 for(my $i = $start; $i<$count; $i++)
 {
  if($i == $start)
  {
   $sentence.=$ARGV[$i];
  }
  else
  {
   $sentence.=" ".$ARGV[$i];
  }
 }
 while(length($sentence)>$COLS-$col)
 {
  &write_string_at($col,$row,trim(substr($sentence,0,$COLS-$col)));
  $row++;
  $sentence=substr($sentence,$COLS-$col,length($sentence)-$COLS+$col);
 }
 &write_string_at($col,$row,trim($sentence));
}

#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Backlight Commands
#
#  => do not touch
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

if($ARGV[0] eq '-back')
{
 if($ARGV[1] eq 'on') 
 {
  &set_back_on();
 }
 else
 {
  &set_back_off();
 }
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Help Screen
#
#  => do not touch
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

if($ARGV[0] eq '')
{
 print "$VERSION\n";
 print "by fesch\@ixus.net\n";
 print "-----------------\n";
 print "usage: lcd [-option] [on|off] [row] [col] [text]\n";
 print "\n";
 print "[-option] may be:   -, -text   => simply outputs the [text] on the LCD\n";
 print "                    -back on   => switches the backlight ON\n";
 print "                    -back off  => switches the backlight OFF\n";
 print "                    -line      => outputs [text] at row [row]\n";
 print "                    -xy        => outputs [text] at row [row], colum [col]\n";
 print "                    -init      => only initializes the LCD\n";
 print "                    -loop      => starts the loop\n";
 print "\n";
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  High Resolution Timer
#  Procedure
#
#  -> Do not touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub set_wait()
{
 ($seconds1, $microseconds1) = gettimeofday;
 &checkButtons;
}

sub make_wait()
{
 &checkButtons;
 my $milli = shift;
 ($seconds2, $microseconds2) = gettimeofday;
 my $i = $milli*1000-($seconds2*1000000+$microseconds2)+($seconds1*1000000+$microseconds1);
 if($i<0) {$i=0;}
 usleep($i);
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Buttons Caption
#
#  -> Do not touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub checkButtons
{

 my $byte = &read_byte($status_port);

 #print "> ".unpack('B8',chr($byte))."\t".unpack('B8',chr($LAST_BYTE))."\n";
 #print "> ".(($byte ^ $LAST_BYTE))."\t".(($byte & $BUTTON_ACK  ))."\n";

 
 if( (( $byte ^ $LAST_BYTE ) == $BUTTON_BUSY ) && (( $byte & $BUTTON_BUSY ) == $BUTTON_BUSY) ) {$STATE_BUSY=$STATE_DOWN; &doBUSYdown;}
 if( (( $byte ^ $LAST_BYTE ) == $BUTTON_ACK  ) && (( $byte & $BUTTON_ACK  ) == 0x00        ) ) {$STATE_ACK =$STATE_DOWN; &doACKdown; }
 if( (( $byte ^ $LAST_BYTE ) == $BUTTON_PE   ) && (( $byte & $BUTTON_PE   ) == 0x00        ) ) {$STATE_PE  =$STATE_DOWN; &doPEdown;  }
 if( (( $byte ^ $LAST_BYTE ) == $BUTTON_SI   ) && (( $byte & $BUTTON_SI   ) == 0x00        ) ) {$STATE_SI  =$STATE_DOWN; &doSIdown;  }
 if( (( $byte ^ $LAST_BYTE ) == $BUTTON_ERR  ) && (( $byte & $BUTTON_ERR  ) == 0x00        ) ) {$STATE_ERR =$STATE_DOWN; &doERRdown; }

 if( (( $byte ^ $LAST_BYTE ) == $BUTTON_BUSY ) && (( $byte & $BUTTON_BUSY ) == 0x00        ) ) {$STATE_BUSY=$STATE_UP; &doBUSYup;}
 if( (( $byte ^ $LAST_BYTE ) == $BUTTON_ACK  ) && (( $byte & $BUTTON_ACK  ) == $BUTTON_ACK ) ) {$STATE_ACK =$STATE_UP; &doACKup; }
 if( (( $byte ^ $LAST_BYTE ) == $BUTTON_PE   ) && (( $byte & $BUTTON_PE   ) == $BUTTON_PE  ) ) {$STATE_PE  =$STATE_UP; &doPEup;  }
 if( (( $byte ^ $LAST_BYTE ) == $BUTTON_SI   ) && (( $byte & $BUTTON_SI   ) == $BUTTON_SI  ) ) {$STATE_SI  =$STATE_UP; &doSIup;  }
 if( (( $byte ^ $LAST_BYTE ) == $BUTTON_ERR  ) && (( $byte & $BUTTON_ERR  ) == $BUTTON_ERR ) ) {$STATE_ERR =$STATE_UP; &doERRup; }

 $LAST_BYTE=$byte;
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Buttons Events
#
#  -> This one you may modify.
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub doSIdown
{
 if($DEBUG_BUTTONS == 1) {print "SIdown\n";}
}

sub doSIup
{
 if($DEBUG_BUTTONS == 1) {print "SIup\n";}
 &save_LINES;
}

sub doPEdown
{
 if($DEBUG_BUTTONS == 1) {print "PEdown\n";}
 if($STATE_SI==$STATE_DOWN)
 {
  $MENU_LINE++;
  $MENU_LINE=($MENU_LINE % $ROWS);
 }
}

sub doPEup
{
 if($DEBUG_BUTTONS == 1) {print "PEup\n";}
}

sub doBUSYdown
{
 if($DEBUG_BUTTONS == 1) {print "BUSYdown\n";}
 if($STATE_SI==$STATE_DOWN)
 {
  my $funcs = @FUNCTIONS;
  @LINE_FUNC[$MENU_LINE]++;
  @LINE_FUNC[$MENU_LINE]=(@LINE_FUNC[$MENU_LINE] % $funcs)
 }
}

sub doBUSYup
{
 if($DEBUG_BUTTONS == 1) {print "BUSYup\n";}
}

sub doACKdown
{
 if($DEBUG_BUTTONS == 1) {print "ACKdown\n";}
 #`killall lcd | ./lcd -loop &`
 exec('./lcd -loop');
}

sub doACKup
{
 if($DEBUG_BUTTONS == 1) {print "ACKup\n";}
}

sub doERRdown
{
 if($DEBUG_BUTTONS == 1) {print "ERRdown\n";}
 &clear_display;
 &write_string_at(0,0,'Shutting down the');
 &write_string_at(0,1,'system right now ...');
 usleep(1000);
 `killall lcd | halt`;
}

sub doERRup
{
 if($DEBUG_BUTTONS == 1) {print "ERRup\n";}
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Script Termination  Method
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub catch_sig
{
 &save_LINES;
 &clear_display;
 &write_string_at(0,0,'LCD shutdown ...    ');
 print "LCD Shutdown ...\n";
 exit 0;
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Line caching & writing
#
#  -> do not touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub set_line
{
 my $line  = shift;
 my $title = shift;
 my $LINE = $LINECACHE[$line];

 if($LINE  ne '')
 {
  for(my $i=0;$i<$COLS;$i++)
  {
   if(substr($LINE,$i,1) ne substr($title,$i,1))
   {
    &write_string_at($i,$line,substr($title,$i,1));
   }
  }
 }
 else 
 { 
  &write_string_at(0,$line,$title);
 }

 $LINECACHE[$line]=$title;
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Menu Data
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub get_line
{
 my $title = "Line: $MENU_LINE";
 while(length($title )<$COLS) {$title .=' ';}
 return substr($title,0,$COLS);
}

sub get_function
{
 my $title = 'Func: '.@FUNCTIONS[@LINE_FUNC[$MENU_LINE]];
 while(length($title )<$COLS) {$title .=' ';}
 return substr($title,0,$COLS);
}

#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Catch Data
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub get_none
{
 my $none='';
 for(my $i=0;$i<$COLS;$i++) {$none.=' ';}
 return $none;
}

sub get_connected_machines
{
 # affiche le nombre de machines accdantes 
 # internet via IpCOP (ou autre?). 
 # ATTENTION: Si une machine s'teind, son adresse
 # MAC reste encore un certain temps dans le cache,
 # donc la valeur n'est pas toujours tout  fait 
 # jour. Ce n'est qu'une indication!

 my $name = `arp -a|wc -l`;
 chop($name);
 my $title = 'Online';
 while(length($title)!=$COLS-10) {$title.=' ';}
 $title = sprintf("$title%10s",$name);
 return substr($title,0,$COLS);
}

sub get_name
{
 # by oxy750
 # modified 15/07/2004 by Fesch

 my $name = `/bin/uname -n`;
 chop($name);
 return substr($name,0,$COLS);
}

sub get_uptime 
{ 
 # by oxy750 
 # modified by gysmovoile ... 
 # l'uptime ne fonctionnait pas !!! 
 # modified 15/07/2004 by Fesch

 my ($title,$uptime,$time,$days,$other,$hours,$users,$ld); 
 $uptime = `/usr/bin/uptime`;
 
 #($days,$hours,$other)=split(/,/,$uptime); 
 #($other,$time,$other,$days,$other)=split(/ +/,$days); 
 #if ($hours eq "") 
 #{ 
 # $hours = $days; 
 # $days = 0; 
 #} 
 #my ($h,$m)=split(/:/,$hours); 
 #$title=sprintf("Uptime   %3dd %02dh%02dm",$days,$h,$m); 

 my @some = explode('up',$uptime);
 @some = explode(',',$some[1]);
 $uptime=trim($some[0]); 

 my $title='Uptime';
 while(length($title)<$COLS-length($uptime)) {$title.=' ';}

 return substr($title.$uptime,0,$COLS);
} 

sub get_cpu_idle
{
 my($swp,$title,$total,$used,$free);
 $swp=`top -n 1 | head -n 3 | tail -n 1`;
 chop($swp);
 my @some=explode(' ',$swp);
 my $title="CPU idle";

 while( length($title) != ($COLS-8)) 
 {
  $title.=' ';
 } 
 $title=sprintf("$title%8s",$some[14]);
 return $title;
}

sub get_system_load
{
 my($swp,$title,$total,$used,$free);
 $swp=`/usr/bin/uptime`;
 chop($swp);
 my @some=split(/average/,$swp);
 #print $some[1]." -- ".substr($some[1],2,16)."\n";
 @some=split(/ /,substr($some[1],2,16));
 #substr($some[13].$some[14].$some[15],0,14)
 my $title=sprintf("%-6s%14s","Load",substr($some[0].$some[1].$some[2],0,14));
 return $title;
}

sub get_swap
{
 # by oxy750
 # modified 15/007/2004 by Fesch

 my($swp,$title,$total,$used,$free);
 $swp=`/usr/bin/free | tail -n 1`;
 chop($swp);
 my($title,$total,$used,$free)=split(/ +/,$swp);
 my $sizefree=sprintf("%.f MB",$free/1024);
 my $pourcentuse=sprintf("%3d%%",int($used*100/$total));
 $title="Swap";
 while(length($title) != $COLS-11) {$title.=' ';}
 $title=sprintf("$title%4s %6s",$pourcentuse,$sizefree);

 return substr($title,0,$COLS);
}

sub get_bar_up
{
 my $itIs = time();

 if($TIME_UP_BAR!=-1 && (($itIs-$TIME_UP_BAR)>=2))
 {
  my ($title);
  my ($DspeedByte,$DspeedBits,$DspeedKBits);
  my ($UspeedByte,$UspeedBits,$UspeedKBits);

  # get RX
  my $data = `ifconfig $IFACE | head -n 7 | tail -n 1`;
  $data = substr($data,19);
  my @pieces = split(/ /,$data);
  my $us = substr($pieces[5],6);

  # calculate upload speed
  $UspeedByte = ($us-$CACHE_UL)/($itIs-$TIME_UP_BAR);
  $UspeedBits = int($UspeedByte * 8); 
  $UspeedKBits = ($UspeedBits / 1024);
  my $UP=$UspeedKBits;
  my $UPs = "UP ";
  $UP=($UP/$UPBITS)*(($COLS-3)*5);
  $UP=sprintf("%i",$UP);
  my $ganzUP = sprintf("%i",$UP/5);
  for(my $i=0;$i<$ganzUP;$i++) {$UPs.=chr(4);}
  $UPs.=chr($UP % 5);
  while(length($UPs)<$COLS) {$UPs.=' ';}
  $UPs=substr($UPs,0,$COLS);
  
  $CACHE_UP_BAR=$UPs;
  $TIME_UP_BAR=$itIs;
  $CACHE_UL=$us;
  return $UPs;
 }
 else
 {
  return $CACHE_UP_BAR;
 }
}

sub get_bar_up_val
{
 my $itIs = time();

 if($TIME_UP_BAR!=-1 && (($itIs-$TIME_UP_BAR)>=2))
 {
  my ($title);
  my ($UspeedByte,$UspeedBits,$UspeedKBits,$UspeedBits2,$UspeedKBits2);

  # get RX
  my $data = `ifconfig $IFACE | head -n 7 | tail -n 1`;
  $data = substr($data,19);
  my @pieces = split(/ /,$data);
  my $us = substr($pieces[5],6);

  # calculate upload speed
  $UspeedByte = ($us-$CACHE_UL)/($itIs-$TIME_UP_BAR);
  $UspeedBits = int($UspeedByte * 8); 
  $UspeedBits2 = int($UspeedByte * 1); # on laisse en octet
  $UspeedKBits = ($UspeedBits / 1024);
  $UspeedKBits2 = ($UspeedBits2 / 1024);
  my $UP=$UspeedKBits;
  my $UPs = "UP ";
  $UP=($UP/$UPBITS)*(($COLS-3-7)*5);
  $UP=sprintf("%i",$UP);
  my $ganzUP = sprintf("%i",$UP/5);
  for(my $i=0;$i<$ganzUP;$i++) {$UPs.=chr(4);}
  $UPs.=chr($UP % 5);
  while(length($UPs)<$COLS-7) {$UPs.=' ';}
  $UPs=substr($UPs,0,$COLS-7);
  if($UspeedKBits2<10) {$UP=sprintf("%.1f",$UspeedKBits2);}
  else {$UP=sprintf("%i",$UspeedKBits2);}
  my $titleUP=sprintf("%4s KB",$UP);
  $UPs=substr($UPs.$titleUP,0,$COLS);
  $CACHE_UP_BAR=$UPs;
  $TIME_UP_BAR=$itIs;
  $CACHE_UL=$us;
  return $UPs;
 }
 else
 {
  return $CACHE_UP_BAR;
 }
}

sub get_bar_down
{
 my $itIs = time();

 if($TIME_DONW_BAR!=-1 && (($itIs-$TIME_DONW_BAR)>=2))
 {
  my ($title);
  my ($DspeedByte,$DspeedBits,$DspeedKBits);

  # get RX
  my $data = `ifconfig $IFACE | head -n 7 | tail -n 1`;
  $data = substr($data,19);
  my @pieces = split(/ /,$data);
  my $ds = $pieces[0]; 

  # calculate download speed
  $DspeedByte = ($ds-$CACHE_DL)/($itIs-$TIME_DONW_BAR);
  $DspeedBits = int($DspeedByte * 8); 
  $DspeedKBits = ($DspeedBits / 1024);


  my $DL=$DspeedKBits;
  my $DLs = "DL ";
  $DL=($DL/$DOWNBITS)*(($COLS-3)*5);
  $DL=sprintf("%i",$DL);
  my $ganzDL = sprintf("%i",$DL/5);
  for(my $i=0;$i<$ganzDL;$i++) {$DLs.=chr(4);}
  $DLs.=chr($DL % 5);
  while(length($DLs)<$COLS) {$DLs.=' ';}
  $DLs=substr($DLs,0,$COLS);
  $CACHE_DL=$ds;
  $CACHE_DOWN_BAR=$DLs;
  $TIME_DONW_BAR=$itIs;
  return $DLs;
 }
 else
 {
  return $CACHE_DOWN_BAR;
 }
}

sub get_bar_down_val
{
 my $itIs = time();

 if($TIME_DONW_BAR!=-1 && (($itIs-$TIME_DONW_BAR)>=2))
 {
  my ($title);
  my ($DspeedByte,$DspeedBits,$DspeedKBits,$DspeedBits2,$DspeedKBits2);

  # get RX
  my $data = `ifconfig $IFACE | head -n 7 | tail -n 1`;
  $data = substr($data,19);
  my @pieces = split(/ /,$data);
  my $ds = $pieces[0]; 

  # calculate download speed
  $DspeedByte = ($ds-$CACHE_DL)/($itIs-$TIME_DONW_BAR);
  $DspeedBits = int($DspeedByte * 8); 
  $DspeedBits2 = int($DspeedByte * 1); # on laisse en octet
  $DspeedKBits = ($DspeedBits / 1024);
  $DspeedKBits2 = ($DspeedBits2 / 1024);

  my $DL=$DspeedKBits;
  my $DLs = "DL ";
  $DL=($DL/$DOWNBITS)*(($COLS-3-7)*5);
  $DL=sprintf("%i",$DL);
  my $ganzDL = sprintf("%i",$DL/5);
  for(my $i=0;$i<$ganzDL;$i++) {$DLs.=chr(4);}
  $DLs.=chr($DL % 5);
  while(length($DLs)<$COLS-7) {$DLs.=' ';}
  $DLs=substr($DLs,0,$COLS-7);

  if($DspeedKBits2<10) {$DL=sprintf("%.1f",$DspeedKBits2);}
  else {$DL=sprintf("%i",$DspeedKBits2);}
  my $titleDL=sprintf("%4s KB",$DL);
  $DLs=substr($DLs.$titleDL,0,$COLS);
  $CACHE_DL=$ds;
  $CACHE_DOWN_BAR=$DLs;
  $TIME_DONW_BAR=$itIs;
  return $DLs;
 }
 else
 {
  return $CACHE_DOWN_BAR;
 }
}

sub get_downupload 
{
 # by oxy750
 # Calcul de la vitesse de UP et DL bas
 # sur speedDeamon de Fesch
 # modified 15/07/2004 by Fesch

 my $itIs = time();

 if(($itIs-$TIME_DOWN)>=2)
 {
  my ($title);
  my ($DspeedByte,$DspeedBits,$DspeedKBits);
  my ($UspeedByte,$UspeedBits,$UspeedKBits);  

  # get RX
  my $data = `ifconfig $IFACE | head -n 7 | tail -n 1`;
  $data = substr($data,19);
  my @pieces = split(/ /,$data);
  my $ds = $pieces[0];
  my $us = substr($pieces[5],6); 

  # calculate download speed
  $DspeedByte = ($ds-$CACHE_DL)/($itIs-$TIME_DOWN);
  $DspeedBits = int($DspeedByte * 1); # on laisse en octet
  $DspeedKBits = ($DspeedBits / 1024);  

  # calculate upload speed
  $UspeedByte = ($us-$CACHE_UL)/($itIs-$TIME_DOWN);
  $UspeedBits = int($UspeedByte * 1); # on laisse en octet
  $UspeedKBits = ($UspeedBits / 1024);

  $CACHE_DL=$ds;
  $CACHE_UL=$us;
  $TIME_DOWN=$itIs;

  my $UP=0;
  my $DL=0;

  if($UspeedKBits<10) {$UP=sprintf("%.1f",$UspeedKBits);}
  else {$UP=sprintf("%i",$UspeedKBits);}

  if($DspeedKBits<10) {$DL=sprintf("%.1f",$DspeedKBits);}
  else {$DL=sprintf("%i",$DspeedKBits);}

  $title=sprintf("UP:%4s DL:%4s KB/s",$UP,$DL);

  $CACHE_DOWN=$title;
  return $title;
 }
 else
 {
  return $CACHE_DOWN;
 }
}

sub get_ipconnected 
{
 # by oxy750
 
 my $data = `ifconfig $IFACE | grep -i "inet addr"`;
 my($other,$inet,$addr,$ptp,$mask)=split(/ +/,$data);
 my($other,$ip)=split(/:/,$addr);
 my $title=sprintf("IP %".($COLS-3)."s",$ip);
 return "$title";
}

sub get_time 
{
 # by oxy750

 my ($sec,$min,$heure,$mjour,$mois,$annee,$sjour,$ajour,$isdst)=localtime(time);
 $mois++;
 $annee += 1900;
 my $title=sprintf("%02d/%02d/%4d  %02d:%02d:%02d",$mjour,$mois,$annee,$heure,$min,$sec);

 return $title;
}

sub get_mount_1
{
 return &get_disk(1);
}

sub get_mount_2
{
 return &get_disk(2);
}

sub get_mount_3
{
 return &get_disk(3);
}

sub get_disk
{
 # by oxy750
 # modified 15/007/2004 by Fesch

 my ($fs,$size,$used,$avail,$pourcentuse,$mount);
 my $numdisk = shift;
 $numdisk++;
 my $disk=`/bin/df -h | head -n $numdisk | tail -n 1`;
 chop($disk);
 ($fs,$size,$used,$avail,$pourcentuse,$mount)=split(/ +/,$disk);
 my @some = explode('M',$avail);
 my $co = @some;
 if($co = 1)
 {
  my @some = explode('G',$some[0]);
  $avail=$some[0].' GB';
 }
 else
 {
  $avail=$some[0].' MB';
 }
 while(length($mount) != $COLS-11) {$mount.=' ';}
 my $title=sprintf("$mount%4s %6s",$pourcentuse,$avail);

 return substr($title,0,$COLS);
}

sub get_version
{
 my $title=$VERSION;
 while(length($title) != $COLS) {$title.=' ';}
 return substr($title,0,$COLS);
}

#################3

sub get_ixui
{
 # get time
 my $itIs = time();

 if(($itIs-$TIME_IXUI)>30)
 {
  $TIME_IXUI=$itIs;

  my $peer = 'www.ixus.net';
  my $peerport = 80;
  my $sock;
  unless($sock = new IO::Socket::INET (PeerAddr => $peer, PeerPort => $peerport, Proto => 'tcp', Timeout => 5))
  {
   print 'could not connect to www.ixus.net';
   return 0;
  }
  my $GET_CMD;
  $GET_CMD  = "GET http://www.ixus.net/ixui.html HTTP/1.1\r\n";
  $GET_CMD .= "Host: www.ixus.net\r\n";
  $GET_CMD .= "Cache-Control: no-cache\r\n";
  $GET_CMD .= "Connection: close\r\n\r\n";
  print $sock "$GET_CMD";
  my $ret = '';
  while (<$sock>) 
  {
   $ret .= $_; 
  }
  close($sock);
  my @lines = explode("\n",$ret);
  @lines = explode('<br>',$lines[10]);
  # 1 => time
  # 3 => title
  # 4 => forum
  # 5 => user
  my $title = $lines[1].': '.$lines[3].' ('.$lines[5].') ';
  $title = &strReplace('','e',$title);
  $title = &strReplace('','e',$title);
  $title = &strReplace('','e',$title);
  $title = &strReplace('','e',$title);
  $title = &strReplace('','a',$title);
  $title = &strReplace('','a',$title);
  $title = &strReplace('','a',$title);
  $title = &strReplace('','a',$title);
  $title = &strReplace('','i',$title);
  $title = &strReplace('','i',$title);
  $title = &strReplace('','i',$title);
  $title = &strReplace('','i',$title);
  $title = &strReplace('','u',$title);
  $title = &strReplace('','u',$title);
  $title = &strReplace('','u',$title);
  $title = &strReplace('','u',$title);
  $title = &strReplace('','o',$title);
  $title = &strReplace('','o',$title);
  $title = &strReplace('','o',$title);
  $title = &strReplace('','o',$title);
  $title = &strReplace('','c',$title);
  $title = &strReplace('&gt;','>',$title);
  $title = &strReplace('&lt;','<',$title);
  $title = &strReplace('&quot;','"',$title);
  if($ixui ne $title)
  {
   $CACHE_IXUI=$title;
   return substr($CACHE_IXUI,0,$COLS);
  }
 }
 else
 {
   my $title = substr($CACHE_IXUI,0,20);
   $CACHE_IXUI=substr($CACHE_IXUI,1,length($CACHE_IXUI)).substr($CACHE_IXUI,0,1);
   return $title;
 }
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  LCD User Character
#  Generation Methods
#
#  => Don't touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub generate_heart
{
 my $c = 5;

 &set_instruction($SETDDRAMADDRESS + $c);

 &set_instruction($SETCGRAMADDRESS + $c*8 + 0);
 &mem(0x08 | 0x02);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 1);
 &mem(0x10 | 0x04 | 0x01);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 2);
 &mem(0x10 | 0x04 | 0x01);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 3);
 &mem(0x10 | 0x01);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 4);
 &mem(0x10 | 0x01);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 5);
 &mem(0x08 | 0x02);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 6);
 &mem(0x08 | 0x02);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 7);
 &mem(0x04);

 $c = 6;

 &set_instruction($SETDDRAMADDRESS + $c);

 &set_instruction($SETCGRAMADDRESS + $c*8 + 0);
 &mem(0x08 | 0x02);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 1);
 &mem(0x10 | 0x08 | 0x04 | 0x02 | 0x01);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 2);
 &mem(0x10 | 0x08 | 0x04 | 0x02 | 0x01);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 3);
 &mem(0x10 | 0x08 | 0x04 | 0x02 | 0x01);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 4);
 &mem(0x10 | 0x08 | 0x04 | 0x02 | 0x01);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 5);
 &mem(0x08 | 0x04 | 0x02);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 6);
 &mem(0x08 | 0x04 | 0x02);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 7);
 &mem(0x04);
}

sub generate_bars
{
 for(my $c=0;$c <5;$c++)
 {
  &set_instruction($SETDDRAMADDRESS + $c);
 
  my $sim = 0;
  if($c==0) {$sim=0x10;}
  if($c==1) {$sim=0x18;}
  if($c==2) {$sim=0x1C;}
  if($c==3) {$sim=0x1E;}
  if($c==4) {$sim=0x1F;}
 
  for(my $l=0;$l<8;$l++)
  {
   &set_instruction($SETCGRAMADDRESS + $c*8 + $l);
   &mem($sim);
  }
 }
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  LCD Control Procedure
#
#  => Don't touch this!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub lcd_init
{
 &set_instruction($FUNCTIONSET | $EIGHTBITMODE);
 &set_instruction($FUNCTIONSET | $EIGHTBITMODE);
 &set_instruction($FUNCTIONSET | $EIGHTBITMODE);
 if($MODE == 4)
 {
  &set_instruction($FUNCTIONSET | $FOURBITMODE );
  &set_instruction( 
		 	$FUNCTIONSET | 
	 		$FOURBITMODE |  
 			$TWOLINES |  
			$FONT5X8
			);
 }
 else
 {
  &set_instruction( 
		 	$FUNCTIONSET | 
	 		$EIGHTBITMODE |  
 			$TWOLINES |  
			$FONT5X8
			);
 }
 ##### display off
 &set_instruction($DISPLAY | $DISPLAY_OFF);
 ##### display clear
 &set_instruction($CLEARDISPLAY);
 ##### entry mode
 &set_instruction(	$ENTRYMODE |
			$INCREMENT |
			$SHIFT_OFF
		);
 ##### end of initialization
 &set_instruction($RETURNHOME);
 ##### turn on display
 &set_instruction(	$DISPLAY | 
			$DISPLAY_ON |
			$CURSOR_OFF |
			$BLINK_OFF
		);
}

sub set_data_at
{
 my $offset = shift;
 my $line = shift;
 my $c = shift;

 my $lineIs = $line;

 if($line == 1) {$lineIs=1*$SECONDLINEOFFSET;}
 if($line == 2) {$lineIs=$COLS;}
 if($line == 3) {$lineIs=1*$SECONDLINEOFFSET + $COLS;}
 
 &set_instruction($SETDDRAMADDRESS + $offset + $lineIs);
 &set_data($c);
}

sub set_data
{
 my $data = shift;
 write_byte($data,$base_port);
 write_byte($RS_HIGH | $RW_LOW | $E_HIGH,$control_port);
 write_byte($RS_HIGH | $RW_LOW | $E_LOW,$control_port);
}

sub mem
{
 my $data = shift;
 write_byte($data,$base_port);
 write_byte($RS_HIGH | $RW_LOW | $E_HIGH,$control_port);
 write_byte($RS_HIGH | $RW_LOW | $E_LOW,$control_port);
}

sub set_instruction
{
 my $data = shift;
 write_byte($data,$base_port);
 write_byte($RS_LOW | $RW_LOW | $E_HIGH,$control_port);
 usleep(0.0000002000);
 write_byte($RS_LOW | $RW_LOW | $E_LOW,$control_port);
}

sub read_byte
{
 my $port = shift;
 my $show = 0;

 sysopen (PORT,"/dev/port",O_RDWR) || die "Datei: $!";
 binmode (PORT);
 sysseek (PORT,$port,0)|| die "seek_err\n";
 my $test = sysread(PORT,$show,1)  || print "write_err while reading from port\n";
 close (PORT);
 $show=ord($show);
 return $show;
}

sub write_byte
{
 my $data = shift;
 my $show = chr($data);
 my $port = shift;

 if($MODE==4 && $port==$base_port)
 {
  my $first = $data;
  $first = ($first >> 4);
  my $second = $data;
  $second = (($second << 4) >> 4) % 256;

  sysopen (PORT,"/dev/port",O_RDWR) || die "Datei: $!";
  binmode (PORT);
  $show = chr($first);
  sysseek (PORT,$port,0)|| die "seek_err\n";
  syswrite(PORT,$show)  || print "write_err while writing $data \n";

  $show = chr($second);
  sysseek (PORT,$port,0)|| die "seek_err\n";
  syswrite(PORT,$show)  || print "write_err while writing $data \n";
  close (PORT);
 }
 else
 {
  sysopen (PORT,"/dev/port",O_RDWR) || die "Datei: $!";
  binmode (PORT);
  sysseek (PORT,$port,0)|| die "seek_err\n";
  syswrite(PORT,$show)  || print "write_err while writing $data \n";
  close (PORT);
 }
}

sub write_string
{
 my $str = shift;
 for(my $i=0;$i<length($str);$i++)
 {
  set_data(ord(substr($str,$i,1)));
 } 
}

sub write_string_at
{
 my $off = shift;
 my $line = shift;
 my $str = shift;

 #print "$str\n";

 for(my $i=0;$i<length($str);$i++)
 {
  set_data_at($off+$i,$line,ord(substr($str,$i,1)));
  &checkButtons;
 } 
}

sub clear_display
{
 @LINECACHE = ('','','','');
 &set_instruction($CLEARDISPLAY);
}


sub set_back_on
{
 &write_byte($BACK_ON, $control_port);
}

sub set_back_off
{
 &write_byte($BACK_OFF, $control_port);
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Save Procedure
#
#  -> Do not touch!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub load_LINES
{
 open (LINES, "lcd.conf") || die "couldn't open the file!";
 my $i = 0;
 while (my $record = <LINES>)
 {
  if(trim($record) ne '')
  {
   @LINE_FUNC[$i] = trim($record);
   $i=$i+1;
  }
 }
 close(LINES);
}

sub save_LINES
{
 open (LINES, ">lcd.conf") or die "no such file";
 foreach (@LINE_FUNC)
 {
  if(trim($_) ne '')
  {
   print LINES "$_\n";
  }
 }
 close(LINES);
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  General functions
#
#  -> Do not touch!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub fileExists
{
 return (-f shift);
}

sub trim
{
  my $temp = shift;
  $temp =~ s/^\s*//;
  $temp =~ s/\s*$//;
  return $temp;
}

sub explode
{
 my $splitter = shift;
 my $who = shift;
 my $tmp;
 my @result;
 my $i = 0;
 my $count = 0;

 while($i<length($who))
 {
  if(substr($who,$i,length($splitter)) eq $splitter)
  {
   $result[$count]=$tmp;
   $tmp='';
   $count++;
   $i+=length($splitter);
  }
  else
  {
   $tmp=$tmp.substr($who,$i,1);
   $i++;
  }
 }
 $result[$count]=$tmp;
 return @result;
}

sub strReplace
{
 my $what = shift;
 my $with = shift;
 my $who = shift;
 $who =~ s/$what/$with/g;
 return $who;
}

sub file
{
 open (FILE, shift) || die "couldn't open the file!";
 my @LINES;
 my $i = 0;
 while (my $record = <FILE>)
 {
  @LINES[$i] = trim($record);
  $i=$i+1;
 }
 close(FILE);
 return @LINES;
}


#/\/\/\/\/\/\/\/\/\/\/\/\/\
# 
#  Not used !!!
#
#\/\/\/\/\/\/\/\/\/\/\/\/\/

sub write_char_X{
 my $show = shift;
 my $port = shift;

 ##### to modify !

 open (PORT,">/dev/port");
 binmode (PORT);
 seek (PORT,$port,0)|| die "seek_err\n";
 print PORT "$show" ||die "write_err while writing $show\n";
 close (PORT);
}

sub set_instruction_4bit
{
 my $data = shift;
 my $first = $data;
 $first = ($first >> 4) << 4;
 my $second = $data;
 $second = $data << 4;
 &set_instruction($first);
 &set_instruction($second);
}

sub lcd_init_4bit
{
 &set_instruction( $FUNCTIONSET | $EIGHTBITMODE );
 &set_instruction( $FUNCTIONSET | $EIGHTBITMODE );
 &set_instruction( $FUNCTIONSET | $EIGHTBITMODE );
 &set_instruction( $FUNCTIONSET | $FOURBITMODE );
 &set_instruction( $FUNCTIONSET | $FOURBITMODE );
 &set_instruction( $FUNCTIONSET | $FOURBITMODE | $TWOLINES | $FONT5X8 );
 ##### display off
 &set_instruction( $DISPLAY | $DISPLAY_OFF );
 ##### display clear
 &set_instruction( $DISPLAY | $CLEARDISPLAY );
 ##### entry mode
 &set_instruction( $ENTRYMODE | $INCREMENT | $SHIFT_OFF );
 ##### end of initialization
 &set_instruction( $RETURNHOME );
 ##### turn on display
 &set_instruction( $DISPLAY | $DISPLAY_ON | $CURSOR_OFF | $BLINK_OFF );
}

sub generate_bars2
{
 for(my $c=0;$c <5;$c++)
 {
  &set_instruction($SETDDRAMADDRESS + $c);
 
  my $sim = 0;
  if($c==0) {$sim=0x10;}
  if($c==1) {$sim=0x18;}
  if($c==2) {$sim=0x1C;}
  if($c==3) {$sim=0x1E;}
  if($c==4) {$sim=0x1F;}
 
  &set_instruction($SETCGRAMADDRESS + $c*8 + 0);
  &mem(0x1F);
  &set_instruction($SETCGRAMADDRESS + $c*8 + 7);
  &mem(0x1F);
  for(my $l=1;$l<7;$l++)
  {
   &set_instruction($SETCGRAMADDRESS + $c*8 + $l);
   &mem($sim);
  }
 }

 my $c=7;
 my $sim=0x00;
 &set_instruction($SETCGRAMADDRESS + $c*8 + 0);
 &mem(0x1F);
 &set_instruction($SETCGRAMADDRESS + $c*8 + 7);
 &mem(0x1F);
 for(my $l=1;$l<7;$l++)
 {
  &set_instruction($SETCGRAMADDRESS + $c*8 + $l);
  &mem($sim);
 }
}

__END__ 

