#!/usr/local/bin/perl
use strict;
##################################
#Machine depend Setting
my $nofCore=2; # Number of
my $statHz=133; #you can see your stathz in `sysctl kern.clockrate` 
my $clockBase=1660; #Your CPU clock  
                    #(See dev.cpu.0.freq_levels (choice max one))
my $dspFreq=48000; #your audio player sample speed
#####################################
#######################
#servo setting
my $servoSpan=18;  #normaly 18 ms
my $servoMin=0.5;  #normaly 0.5 ms
my $servoMax=1.5;  #normaly 1.5 ms


use Time::HiRes qw ( time );
my $span=0.8; #status update rate (in sec.)
my $timeBase=$statHz*$nofCore;
my $uspan=1000*1000*$span;
my $on=pack("H2", "FF");
my $off=pack("H2", "00");
my $smoothStep=2;



sub idleTime{
    return (split(/\s/,`sysctl kern.cp_time`))[5];
}
sub clock{
    return (split(/\s/,`sysctl dev.cpu.0.freq`))[1];
}
`mixer -f /dev/mixer1 pcm 100`;
open(PLAY,"|rawplay -f u8 -c 2 -s $dspFreq -B ".$span*$dspFreq*0.5." -d /dev/dsp1.0") or die("cannt play");
select PLAY;
$|=1;
select STDOUT;
while(0){
  rawPlay(0,0);
  rawPlay(1,1);
}

rawPlay(0,0);

if(0){ #debug
    for(my $i=0;$i<48*$smoothStep;$i++){
	rawPlay($i/48/$smoothStep,1- $i/48/$smoothStep);
    }
}


my $oldIdle=idleTime();
my $oldTime=time();


rawPlay(1,1);
while(1){
    my $idle=idleTime();
    my $nowTime=time();
    my $realSpan=$nowTime-$oldTime;
    my $load=($realSpan*$timeBase - ($idle-$oldIdle) )/($realSpan*$timeBase)*100;
    my $freq=100*clock()/$clockBase;
    #print "$load $freq \n";
    rawPlay($load/100,$freq/100);
    $oldIdle=$idle;
    $oldTime=$nowTime;
}



sub rawPlay{
    my($rateL,$rateR)=@_;
    my($countL,$countR);
    $countR= ( ($servoMax-$servoMin)*$rateR+$servoMin  )*$dspFreq/1000;
    $countL= ( ($servoMax-$servoMin)*$rateL+$servoMin  )*$dspFreq/1000;
    my($i,$j,$im,$jm,$s);


    $jm=$span*1000/$servoSpan/$smoothStep;
    $im=$dspFreq*$servoSpan/1000;
    my $out="";
    my $oout="";
    for($s=0;$s<$smoothStep;$s++){
	my $sL= $countL+$s/$smoothStep;
	my $sR= $countR+$s/$smoothStep;
	
	for($i=0;$i<$im;$i++){ #0กม0.5
	    $out .= ($i< $sL )?$on:$off;
	    $out .= ($i< $sR )?$on:$off;
	}
    }
    for($j=0;$j<$jm;$j++){
	$oout.=$out;
    }
    print PLAY $oout;
}
