packages/web/353/php_top/mshutter.php

Go to the documentation of this file.
00001 <?php
00002 /*!***************************************************************************
00003 *! FILE NAME  : mshutter.php
00004 *! DESCRIPTION: controls mechanical shutters (sequencer)
00005 *! Copyright (C) 2007 Elphel, Inc
00006 *! -----------------------------------------------------------------------------**
00007 *!
00008 *!  This program is free software: you can redistribute it and/or modify
00009 *!  it under the terms of the GNU General Public License as published by
00010 *!  the Free Software Foundation, either version 3 of the License, or
00011 *!  (at your option) any later version.
00012 *!
00013 *!  This program is distributed in the hope that it will be useful,
00014 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 *!  GNU General Public License for more details.
00017 *!
00018 *!  You should have received a copy of the GNU General Public License
00019 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020 *! -----------------------------------------------------------------------------**
00021 *!  $Log: mshutter.php,v $
00022 *!  Revision 1.1  2007/12/06 19:02:51  elphel
00023 *!  collected most of the camera PHP script into one  /packages/web/353/php_top directory
00024 *!
00025 *!  Revision 1.2  2007/10/12 05:33:53  elphel
00026 *!  Fixed wrong fillout of the "Even exposures" form
00027 *!
00028 *!  Revision 1.1.1.1  2007/10/10 05:43:21  elphel
00029 *!  This is a fresh tree based on elphel353-2.10
00030 *!
00031 */
00032 
00033 //slow version of functions - they will reopen i2c for each word
00034 function send347($register_address,$d0=0,$d1=-1,$d2=-1,$d3=-1,$d4=-1,$d5=-1,$d6=-1,$d7=-1) {
00035    $i2c  = fopen('/dev/xi2c16', 'w');
00036    fseek ($i2c, 0x2000+2*$register_address) ; //Micron sensor slave 0xba
00037    fwrite($i2c, chr (floor($d0/256)).chr ($d0-256*floor($d0/256)));
00038    if ($d1>=0) {
00039     fwrite($i2c, chr (floor($d1/256)).chr ($d1-256*floor($d1/256)));
00040     if ($d2>=0) {
00041      fwrite($i2c, chr (floor($d2/256)).chr ($d2-256*floor($d2/256)));
00042      if ($d3>=0) {
00043       fwrite($i2c, chr (floor($d3/256)).chr ($d3-256*floor($d3/256)));
00044       if ($d4>=0) {
00045        fwrite($i2c, chr (floor($d4/256)).chr ($d4-256*floor($d4/256)));
00046        if ($d5>=0) {
00047         fwrite($i2c, chr (floor($d5/256)).chr ($d5-256*floor($d5/256)));
00048         if ($d6>=0) {
00049          fwrite($i2c, chr (floor($d6/256)).chr ($d6-256*floor($d6/256)));
00050          if ($d7>=0) {
00051           fwrite($i2c, chr (floor($d7/256)).chr ($d7-256*floor($d7/256)));
00052          }
00053         }
00054        }
00055       }
00056      }
00057     }
00058    }
00059    fclose($i2c);
00060 }
00061 
00062 function receive347($register_address) { // very slow?
00063    $i2c  = fopen('/dev/xi2c16', 'r');
00064    fseek ($i2c, 0x2000+2*$register_address) ; //Micron sensor slave 0xba
00065    $data = fread($i2c, 2);
00066    fclose($i2c);
00067    $v=unpack('n1',$data);
00068 //   var_dump($v);
00069    return $v[1];
00070 }
00071 
00072 
00073 function i2cread16 ($start,$length=256) {
00074    $i2c  = fopen('/dev/xi2c16', 'r');
00075    fseek ($i2c, 2*$start) ; // 16-bit registers
00076    $data = fread($i2c, 2*$length);
00077    fclose($i2c);
00078    $regs=unpack('n*',$data);
00079 //   print_r($regs);
00080    echo "<table>\n";
00081    for ($i=0; $i<$length; $i+=16){
00082      printf("<tr><td>%x</td>",$i);
00083      for ($j=1; $j<17; $j++){
00084        printf("<td>%x</td>",$regs[$i+$j]);
00085      }
00086      echo "</tr>\n";
00087    }
00088    echo "</table>\n";
00089 }
00090 
00091 function nicefloaty($f) {
00092   $s=sprintf("%f",$f);
00093   if (strpos($s, ".") !== false) $s=rtrim ( $s, "0" );
00094   return rtrim ( $s, "." );
00095 }
00096 function write_coil_form($coil1,$coil2,$coil3,$coil4,$alternate,$coil1e,$coil2e,$coil3e,$coil4e) {
00097    $tick=$GLOBALS['tick'];
00098    $tick_us=$tick*1000;
00099    if ($alternate) {
00100     $head1="<tr><td colspan=\"2\"><b>Odd exposures</b></td></tr>\n";
00101     $table_even="<tr><td colspan=\"2\"><b>Even exposures</b></td></tr>\n".
00102                 "<tr><td>coil1:</td><td> <input name=\"coil1_e\" type=\"text\" size=\"80\" value=\"$coil1e\"/> </td></tr>\n".
00103                 "<tr><td>coil2:</td><td> <input name=\"coil2_e\" type=\"text\" size=\"80\" value=\"$coil2e\"/> </td></tr>\n".
00104                 "<tr><td>coil3:</td><td> <input name=\"coil3_e\" type=\"text\" size=\"80\" value=\"$coil3e\"/> </td></tr>\n".
00105                 "<tr><td>coil4:</td><td> <input name=\"coil4_e\" type=\"text\" size=\"80\" value=\"$coil4e\"/> </td></tr>\n";
00106    } else {
00107     $head1="";
00108     $table_even="";
00109    }
00110    echo "<form action=\"$self\" method=\"post\">";
00111     echo <<<HTMLFORM
00112    <p>You may specify individual sequences for each coil, sequence consists of command_letter and duration pairs (no spaces are required but allowed). Here is an example:</p>
00113    <pre>
00114    f1 b1.5 p5 r 2.1 b1.5
00115    </pre>
00116    <p>Forward 1 ms, brake for 1.5ms, pause for 5 ms, reverse for 2.1ms and finally brake for 1.5ms.</p>
00117    <ul>
00118     <li><b>p</b> - initial state of the coil, both ends shorted to ground (should not leave this state for more than 15ms)</li>
00119     <li><b>d</b> - forward </li>
00120     <li><b>r</b> - reverse </li>
00121     <li><b>b</b> - brake - coil is allowed to develop voltage equal to the power supply - limited by the H-bridge diodes </li>
00122    </ul>
00123    <p>Delay after the command letter is specified in ms, minimal delay/dealy step is $tick ms ($tick_us us). If delay is ommitted it will default to $tick.</p>
00124    <input type="hidden" name="is_post" value="it_is">
00125     <table>
00126      $head1
00127      <tr><td>coil1:</td><td> <input name="coil1" type="text" size="80" value="$coil1"/> </td></tr>
00128      <tr><td>coil2:</td><td> <input name="coil2" type="text" size="80" value="$coil2"/> </td></tr>
00129      <tr><td>coil3:</td><td> <input name="coil3" type="text" size="80" value="$coil3"/> </td></tr>
00130      <tr><td>coil4:</td><td> <input name="coil4" type="text" size="80" value="$coil4"/> </td></tr>
00131      $table_even
00132      <tr><td colspan="2"> <input type="submit" /> </td></tr>
00133     </table> 
00134    </form>
00135 HTMLFORM;
00136 
00137 }
00138 function parse_seq($sec_str,$chn){
00139   $times=array();
00140   $states=array();
00141   $channels=array();
00142   $tick=$GLOBALS['tick']; 
00143   $s=strtolower ($sec_str);
00144   $s=str_replace (" ","",$s);
00145   $s=str_replace ("d"," d ",$s);
00146   $s=str_replace ("f"," d ",$s);
00147   $s=str_replace ("r"," r ",$s);
00148   $s=str_replace ("p"," p ",$s);
00149   $s=str_replace ("n"," p ",$s);
00150   $s=str_replace ("b"," b ",$s);
00151   $s=str_replace ("  "," ",$s);
00152   $s=trim($s);
00153   if ($s=="") return array ("times"=>$times,"channels"=>$channels,"states"=>$states); // empty sequence - don't add " p"
00154   $s.= " p";
00155   $a=explode(" ", $s);
00156   foreach ($a as $value) {
00157     if      ($value =="p") $p[]= array(0,1);
00158     else if ($value =="d") $p[]= array(1,1);
00159     else if ($value =="r") $p[]= array(2,1);
00160     else if ($value =="b") $p[]= array(3,1);
00161     else  {
00162        sscanf($value,"%f",$f);
00163        $f=round($f/$tick); if ($f<1) $f=1;
00164        $p[count($p)-1][1]=$f;
00165     }
00166   }
00167 
00168   unset ($a);
00169   $time=0;
00170   foreach ($p as $value) {
00171    $times[]=$time;
00172    $states[]=$value[0];
00173    $channels[]=$chn;
00174    $time+=$value[1];
00175   }
00176   return array ("times"=>$times,"channels"=>$channels,"states"=>$states);
00177 }
00178 function seq_table ($seq) {
00179     echo "<table border=\"1\">\n <tr><td>Time (ms)</td><td>1</td><td>2</td><td>3</td><td>4</td></tr>\n";
00180     foreach ($seq as $time => $state) 
00181 //      printf ("<tr><td>%f</td><td>%d</td><td>%d</td><td>%d</td><td>%d</td></tr>\n",
00182       printf ("<tr><td>%s</td><td>%02b</td><td>%02b</td><td>%02b</td><td>%02b</td></tr>\n",
00183              nicefloaty($time*$GLOBALS['tick']),
00184              ($state >> 0) & 3,
00185              ($state >> 2) & 3,
00186              ($state >> 4) & 3,
00187              ($state >> 6) & 3);
00188     echo "</table>";
00189 }
00190 function seq_send ($seq,$adr) {
00191 //  $adr=$GLOBALS['mshutter_seq'];
00192   $seqtime=0;
00193   $pstate=0;
00194   foreach ($seq as $time => $state) {
00195     $duration=$time-$seqtime;
00196     if ($duration>0) {
00197      $msw=0x9000 | (($pstate & 0xff) << 4) | ((($duration-1) >> 16) & 0xf);
00198      $lsw=(($duration-1) & 0xffff);
00199      send347 ($adr,$lsw, $msw);
00200      $adr+=2;
00201     }
00202     $seqtime=$time;
00203     $pstate=$state;
00204   }
00205   send347 ($adr,0, 0); // end sequence
00206 }
00207 
00208 //receive347($register_address)
00209 function seq_receive($adr,$length) { // seq array
00210 //  $adr=$GLOBALS['mshutter_seq'];
00211 //  $length=0x100;
00212   $i2c  = fopen('/dev/xi2c16', 'r');
00213   fseek ($i2c,  0x2000+2*$adr) ; // 16-bit registers
00214 
00215   $data = fread($i2c, 2*$length);
00216   fclose($i2c);
00217   $regs=unpack('n*',$data);
00218 //  print_r ($regs);
00219   $seqtime=0;
00220   $state=0;
00221   $seq=array();
00222   $i=1;
00223   for (;;) {
00224     $lsw=$regs[$i++];
00225     $msw=$regs[$i++];
00226     if (!($msw & 0x8000)) break;
00227 //    printf ("lsw=%x, msw=%x, seqtime=%x\n",$lsw,$msw,$seqtime);
00228     if (($msw & 0xf000)==0x9000) $seq[$seqtime]= ($msw >> 4) & 0xff; // state
00229     $seqtime += ( $lsw | (($msw & 0xf)<<16))+1; // nop commands can add duration, each command adds 1 tick also
00230   }
00231 //  printf ("---- lsw=%x, msw=%x, seqtime=%x\n",$lsw,$msw,$seqtime);
00232   $seq[$seqtime]= 0; // state
00233   return $seq;
00234 }
00235 
00236 function seq_extract_channel($seq, $chn) { // extract individual channel (1..4) from the sequencer
00237    $seqtime=0;
00238    $seqstate=0;
00239    $s="";
00240    $cmds="pfrb";
00241    $tick=$GLOBALS['tick'];
00242    foreach ($seq as $time => $state) {
00243       if ((($state >> (2*($chn-1))) & 3) != $seqstate) {
00244         if ($time > $seqtime) {
00245 //           $s .= " " . ($cmds[$seqstate]) . nicefloaty(($time-$seqtime)*$GLOBALS['tick']);
00246            $dt=($time-$seqtime); //integer ticks
00247            $dtus=round(1000*$dt*$tick);
00248 //   printf ("dtus=%f, round(dtus/(1000*tick))=%d, dt=%d<br/>\n",$dtus,round($dtus/(1000*$tick)),$dt);
00249            if (round($dtus/(1000*$tick))==$dt) $dt=0.001*$dtus;
00250            else $dt *= $tick;
00251            $s .= " " . ($cmds[$seqstate]) . nicefloaty($dt);
00252         }
00253         $seqstate= (($state >> (2*($chn-1))) & 3);
00254         $seqtime=$time;
00255       }
00256    }
00257    return trim($s);
00258 }
00259 
00260 // main starts here:
00261 
00262 $GLOBALS['mshutter_alternate']=1;
00263 $GLOBALS['mshutter_seq']=0x200;
00264 $GLOBALS['mshutter_seq_even']=0x280;
00265 $GLOBALS['tick']=0.000008*4*(receive347(0x70)+1);
00266 echo <<<HEADER
00267 <html>
00268   <head>
00269     <title></title>
00270     <meta content="">
00271     <style></style>
00272   </head>
00273   <body>
00274 HEADER;
00275 echo "<p><i>sequencer tick=" . $GLOBALS['tick'] . "ms</i></p>";
00276 // make that first time only reads FPGA
00277 if ($_POST['is_post'] == 'it_is') {
00278   $icoil1 =$_POST['coil1'];
00279   $icoil2 =$_POST['coil2'];
00280   $icoil3 =$_POST['coil3'];
00281   $icoil4 =$_POST['coil4'];
00282   $coil1 = parse_seq($icoil1,1);
00283   $coil2 = parse_seq($icoil2,2);
00284   $coil3 = parse_seq($icoil3,3);
00285   $coil4 = parse_seq($icoil4,4);
00286 
00287   $coils=array ("times"=>   array_merge($coil1["times"],    $coil2["times"],    $coil3["times"],    $coil4["times"]),
00288                 "channels"=>array_merge($coil1["channels"], $coil2["channels"], $coil3["channels"], $coil4["channels"]),
00289                 "states"=>  array_merge($coil1["states"],   $coil2["states"],   $coil3["states"],   $coil4["states"]));
00290   array_multisort($coils["times"],$coils["channels"],$coils["states"]);
00291 //  print_r($coils);
00292   $seq=array();
00293   $state=0;
00294   for ($i=0;$i<count($coils["times"]);) {
00295     $ti=$coils["times"][$i];
00296     $state &= ~(3  << (2 * ($coils["channels"][$i]-1)));
00297     $state |=  $coils["states"][$i] << (2 * ($coils["channels"][$i]-1)); 
00298     for ($j=$i+1; $tj=$coils["times"][$j], $ti==$tj;$j++) {
00299       $state &= ~(3  << (2 * ($coils["channels"][$j]-1)));
00300       $state |=  $coils["states"][$j] << (2 * ($coils["channels"][$j]-1));
00301     }  
00302     $seq[$ti]= $state;
00303     $i=$j;
00304   }
00305   seq_table ($seq);
00306 
00307   if ($GLOBALS['mshutter_alternate']) {
00308     $icoil1_e =$_POST['coil1_e'];
00309     $icoil2_e =$_POST['coil2_e'];
00310     $icoil3_e =$_POST['coil3_e'];
00311     $icoil4_e =$_POST['coil4_e'];
00312     $coil1_e = parse_seq($icoil1_e,1);
00313     $coil2_e = parse_seq($icoil2_e,2);
00314     $coil3_e = parse_seq($icoil3_e,3);
00315     $coil4_e = parse_seq($icoil4_e,4);
00316     $coils_e=array ("times"=>   array_merge($coil1_e["times"],    $coil2_e["times"],    $coil3_e["times"],    $coil4_e["times"]),
00317                     "channels"=>array_merge($coil1_e["channels"], $coil2_e["channels"], $coil3_e["channels"], $coil4_e["channels"]),
00318                     "states"=>  array_merge($coil1_e["states"],   $coil2_e["states"],   $coil3_e["states"],   $coil4_e["states"]));
00319     array_multisort($coils_e["times"],$coils_e["channels"],$coils_e["states"]);
00320 //  print_r($coilse);
00321     $seq_e=array();
00322     $state_e=0;
00323     for ($i=0;$i<count($coils_e["times"]);) {
00324       $ti=$coils_e["times"][$i];
00325       $state_e &= ~(3  << (2 * ($coils_e["channels"][$i]-1)));
00326       $state_e |=  $coils_e["states"][$i] << (2 * ($coils_e["channels"][$i]-1)); 
00327       for ($j=$i+1; $tj=$coils_e["times"][$j], $ti==$tj;$j++) {
00328         $state_e &= ~(3  << (2 * ($coils_e["channels"][$j]-1)));
00329         $state_e |=  $coils_e["states"][$j] << (2 * ($coils_e["channels"][$j]-1));
00330       }
00331       $seq_e[$ti]= $state_e;
00332       $i=$j;
00333     }
00334     seq_table ($seq_e);
00335   }
00336  
00337     if ($GLOBALS['mshutter_alternate']) {
00338       seq_send ($seq,$GLOBALS['mshutter_seq']);
00339       $seq=seq_receive($GLOBALS['mshutter_seq'],0x80);
00340       seq_send ($seq_e,$GLOBALS['mshutter_seq_even']);
00341       $seq_e=seq_receive($GLOBALS['mshutter_seq_even'],0x80);
00342 
00343       write_coil_form(seq_extract_channel($seq, 1),
00344                       seq_extract_channel($seq, 2),
00345                       seq_extract_channel($seq, 3),
00346                       seq_extract_channel($seq, 4),
00347                       1,
00348                       seq_extract_channel($seq_e, 1),
00349                       seq_extract_channel($seq_e, 2),
00350                       seq_extract_channel($seq_e, 3),
00351                       seq_extract_channel($seq_e, 4));
00352     } else {
00353       seq_send ($seq,$GLOBALS['mshutter_seq']);
00354       $seq=seq_receive($GLOBALS['mshutter_seq'],0x100);
00355       write_coil_form(seq_extract_channel($seq, 1),
00356                       seq_extract_channel($seq, 2),
00357                       seq_extract_channel($seq, 3),
00358                       seq_extract_channel($seq, 4),0,"","","","");
00359     }
00360   } else {
00361     if ($GLOBALS['mshutter_alternate']) {
00362       $seq=seq_receive($GLOBALS['mshutter_seq'],0x80);
00363       $seq_e=seq_receive($GLOBALS['mshutter_seq_even'],0x80);
00364 //    echo "<pre>\n"; 
00365 //    print_r($seq);
00366 //    print_r($seq_e);
00367 //    echo "</pre>\n"; 
00368 
00369       write_coil_form(seq_extract_channel($seq, 1),
00370                       seq_extract_channel($seq, 2),
00371                       seq_extract_channel($seq, 3),
00372                       seq_extract_channel($seq, 4),
00373                       1,
00374                       seq_extract_channel($seq_e, 1),
00375                       seq_extract_channel($seq_e, 2),
00376                       seq_extract_channel($seq_e, 3),
00377                       seq_extract_channel($seq_e, 4));
00378     } else {
00379       $seq=seq_receive($GLOBALS['mshutter_seq'],0x100);
00380       write_coil_form(seq_extract_channel($seq, 1),
00381                       seq_extract_channel($seq, 2),
00382                       seq_extract_channel($seq, 3),
00383                       seq_extract_channel($seq, 4),0,"","","","");
00384     }
00385   }
00386 echo <<<FOOTER
00387   </body>
00388 </html>
00389 FOOTER;
00390 ?>

Generated on Thu Aug 7 16:19:01 2008 for elphel by  doxygen 1.5.1