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

Generated on Fri Nov 28 00:06:24 2008 for elphel by  doxygen 1.5.1