<?php /** * @file index.php * @brief index page * @copyright Copyright (C) 2017 Elphel Inc. * @author Oleg Dzhimiev <oleg@elphel.com> * * @par <b>License</b>: * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ ?> <!doctype html> <html lang="en"> <head> <title>Elphel 393</title> <meta charset="utf-8"/> <script> // for LibreJS: /** * @file index.php * @copyright Copyright (C) 2017 Elphel Inc. * @author - * * @licstart The following is the entire license notice for the * JavaScript code in this page. * * The JavaScript code in this page is free software: you can * redistribute it and/or modify it under the terms of the GNU * General Public License (GNU GPL) as published by the Free Software * Foundation, either version 3 of the License, or (at your option) * any later version. The code is distributed WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. * * As additional permission under GNU GPL version 3 section 7, you * may distribute non-source (e.g., minimized or compacted) forms of * that code without the copy of the GNU GPL normally required by * section 4, provided you include this license notice and a URL * through which recipients can access the Corresponding Source. * * @licend The above is the entire license notice * for the JavaScript code in this page. */ </script> <script type='text/javascript' src='js/jquery-3.1.1.js'></script> <!--<script type='text/javascript' src='../js/bootstrap/js/bootstrap.js'></script>--> <script src="js/elphel.js"></script> <script src="js/jcanvas.js"></script> <script src="js/UTIF.js"></script> <script src="js/exif.js"></script> <script src="js/jquery-jp4.js"></script> <link rel="stylesheet" href="js/bootstrap/css/bootstrap.css"> <style> .port_window{ padding: 5px; background: rgba(240,240,240,0.5); border-radius: 2px; } .img_window{ border: 1px solid rgba(210,210,210,1); } .port_preview{ width:300px; min-height:224px; overflow: auto; } table td { padding-right:10px; } .btn.active:focus, .btn:focus{ outline:none; } .btn-toggle{ padding: 1px 0px; } #aexp_limit, #exposure, #fps{ width: 50px; text-align:right; margin-top: 1px; } #ll_status{ color: rgba(0,150,0,1); opacity: 0; } .qlink{ cursor: pointer; } .qlink:hover { text-decoration: underline; } </style> </head> <body> <div style='padding:10px'> <?php include "include/elphel_functions_include.php"; $port0 = 2323; $table_contents = ""; $port_links = ""; $sample_port = -1; $sensors = get_sensors(); $sensor_type = "none"; foreach($sensors as $i => $sensor){ if ($sensor!="none"){ $sensor_type = $sensor; $sample_port = $i; $sandp = "http://{$_SERVER["SERVER_ADDR"]}:".($port0+$i); $href1 = "$sandp/bimg"; $href2 = "$sandp/mimg"; $table_contents .= "<td valign='top'>"; $table_contents .= "<div class='port_window img_window'>"; //$table_contents .= "<div><a href=\"$href1\"><img class='img_window' src='$href1' style='width:300px'/></a></div>"; $table_contents .= "<div><a href=\"$href1\"><div index='$i' class='port_preview'></div></a></div>"; $table_contents .= "<div style='text-align:center;'>"; $table_contents .= "port $i: "; $table_contents .= "<a title='single image' href='$href1'>bimg</a>, "; $table_contents .= "<a href=\"img.html?port=$i\" title='single image, auto refreshed on load, LOW RES, displays jpeg, tiff and jp4 formats'>img</a>, "; $table_contents .= "<a title='multi-part image stream (M-JPEG). Played in browser as is.' href='$href2'>mimg</a>, "; $table_contents .= "<a href=\"mjpeg.html?port=$i\" title='MJPEG stream played in html canvas' class='canvas_mjpeg'>canvas</a>"; $table_contents .= "</div>"; $table_contents .= "</div>"; $table_contents .= "</td>"; $port_links .= "<li><a href=\"#\" onclick=\"window.open('camvc.html?sensor_port=$i&reload=0', 'port $i','menubar=0, width=800, height=600, toolbar=0, location=0, personalbar=0, status=0, scrollbars=1')\">port $i</a></li>\n"; } } // check awb of master channel $master_port = elphel_get_P_value($sample_port,ELPHEL_TRIG_MASTER); $awb_on = elphel_get_P_value($master_port,ELPHEL_WB_EN); $aexp_on = elphel_get_P_value($master_port,ELPHEL_AUTOEXP_ON); $aexp_max = elphel_get_P_value($master_port,ELPHEL_AUTOEXP_EXP_MAX); $aexp_max = round($aexp_max/100)/10; $trig_period = elphel_get_P_value($master_port,ELPHEL_TRIG_PERIOD); if ($trig_period!=1){ // single $trig_period_step_s = 0.00000001; $trig_period_s = $trig_period*$trig_period_step_s; $fps = round(1/$trig_period_s*10)/10; }else{ $fps = 10; } $expos = elphel_get_P_value($master_port,ELPHEL_EXPOS); $expos = round($expos/100)/10; $sensor_width = elphel_get_P_value($master_port,ELPHEL_SENSOR_WIDTH); $sensor_height = elphel_get_P_value($master_port,ELPHEL_SENSOR_HEIGHT); echo "<table><tr>$table_contents</tr></table>\n"; echo "<br/>"; echo "Camera Control Interface<ul>$port_links</ul>\n"; ?> <table> <tr> <td> <span title='Frames Per Second. Set internal trigger per second. WARNING: Trigger can be programmed to be faster than real fps. In that case some triggers are ignored.'>FPS:</span> </td> <td><input id='fps' type='text' value='<?php echo $fps;?>' pname='TRIG_PERIOD' /></td> </tr> <tr> <td> <span title='Initial read from master port, applied to all ports'>Manual Exposure:</span> </td> <td><input id='exposure' type='text' value='<?php echo $expos;?>' pname='EXPOS'/> ms</td> </tr> </table> <br/> <table> <tr id="toggle_awb_div" title='Auto White Balance'> <td> Auto WB: </td> <td> <div id="toggle_awb" class="btn-group btn-toggle"> <button class="btn btn-xs <?php echo ($awb_on)?"btn-success active":"btn-default";?>">ON</button> <button class="btn btn-xs <?php echo (!$awb_on)?"btn-danger active":"btn-default";?>">OFF</button> </div> </td> </tr> <tr id="toggle_aexp_div" title='Auto Exposure'> <td> Auto Exposure: </td> <td> <div id="toggle_aexp" class="btn-group btn-toggle"> <button class="btn btn-xs <?php echo ($aexp_on)?"btn-success active":"btn-default";?>">ON</button> <button class="btn btn-xs <?php echo (!$aexp_on)?"btn-danger active":"btn-default";?>">OFF</button> </div> </td> <td> <span title="Auto Exposure Limit in ms">Limit: </td> <td><input id='aexp_limit' type='text' value='<?php echo $aexp_max;?>' pname='AUTOEXP_EXP_MAX'/> ms</td> </tr> </table> <br /> <a href="autocampars.php" title="autocampars.php">Parameter Editor</a><br /> <br /> <a href="camogmgui.php" title="Store video/images to the camera's storage">Recorder</a><br /> <a href="snapshot/" title="Take a snapshot and download from the camera">Snapshot</a><br /> <a href="raw.php" title="Take a snapshot and download raw pixel data from the camera">Snapshot (raw image data)</a><br /> <span title="5Mpx (MT9P006) and 14Mpx (MT9F002) sensors are supported">Quick setup (5 & 14Mpx sensors):</span> <ul> <li><span id="quick_fullres" class='text-primary qlink'>fullres 10fps</span> <span id='ll_status'>settings applied</span></li> <li><span id="quick_1080p" class='text-primary qlink'>1920x1080 30fps</span> <span id='ll_status'>settings applied</span></li> <li><span id="quick_720p" class='text-primary qlink'>1280x720 60fps</span> <span id='ll_status'>settings applied</span></li> </ul> <a href="photofinish/" title="Scanline mode demo. 5Mpx sensor (MT9P006) only">Photo finish demo</a><br /> <br /> <a href="hwmon.html" title="hwmon.html">Temperature monitor</a><br /> <a href="update_software.html" title="Update NAND flash">Update firmware</a><br /> <br /> <a title="docs" href="http://wiki.elphel.com/index.php?title=Tmp_manual">User manual</a><br /> <a href="jp4-viewer/?width=1200&quality=1" title="Preview jp4 images (drag and drop from PC)">JP4 Viewer</a><br /> <a href="/diagnostics/index.html" title="Inspect camera system info">System info</a><br /> <a href="/test_sensors.php" title="Switch to test pattern and check md5sums">Test sensors</a><br /> <a href="/debugfs.html" title="Linux Kernel Dynamic Debug helper interface (debug device drivers)">DebugFS</a><br /> </div> <script> var sensor_type = "<?php echo $sensor_type;?>"; var sensor_width = <?php echo $sensor_width;?>; var sensor_height = <?php echo $sensor_height;?>; var jp4_previews_enable = true; var jp4_previews = []; $(function(){ check_time(); init_awb_toggle(); init_aexp_toggle(); init_jp4_previews(); init_inputs(); init_quick_res_fps(); update_canvas_mjpeg(); }); async function check_time(){ $.ajax({ url: "utils.php?cmd=time&ts="+Date.now(), success: (res)=>{ console.log(res); } }); } function init_jp4_previews(){ $('.port_preview').each(function(){ index = parseInt($(this).attr("index")); if (jp4_previews_enable) { //jp4_previews[index] = $(this).jp4({ip:location.host,port:2323+index,width:300,fast:true,lowres:4}); jp4_previews[index] = $(this).jp4({src:"http://"+location.host+":"+(2323+index)+"/img",width:300,fast:true,lowres:4}); }else{ $(this).html("<img width='300' src='http://"+location.host+":"+(2323+index)+"/img' />"); } }); } function init_awb_toggle(){ $('#toggle_awb').click(function() { if ($(this).find('.btn.active').html()=="ON"){ $(this).find('.btn.active').toggleClass('btn-success'); }else{ $(this).find('.btn.active').toggleClass('btn-danger'); } // toggle active $(this).find('.btn').toggleClass('active'); if ($(this).find('.btn.active').html()=="ON"){ wb_en = 1; $(this).find('.btn.active').toggleClass('btn-success'); }else{ wb_en = 0; $(this).find('.btn.active').toggleClass('btn-danger'); } $(this).find('.btn').toggleClass('btn-default'); url = "parsedit.php?immediate&sensor_port=<?php echo $master_port;?>&WB_EN="+wb_en+"&*WB_EN=0xf"; $.ajax({ url: url, success: function(){ console.log("awb "+(wb_en?"on":"off")); } }); }); } function init_aexp_toggle(){ $('#toggle_aexp').click(function() { if ($(this).find('.btn.active').html()=="ON"){ $(this).find('.btn.active').toggleClass('btn-success'); }else{ $(this).find('.btn.active').toggleClass('btn-danger'); } // toggle active $(this).find('.btn').toggleClass('active'); if ($(this).find('.btn.active').html()=="ON"){ aexp_en = 1; $(this).find('.btn.active').toggleClass('btn-success'); }else{ aexp_en = 0; $(this).find('.btn.active').toggleClass('btn-danger'); } $(this).find('.btn').toggleClass('btn-default'); url = "parsedit.php?immediate&sensor_port=<?php echo $master_port;?>&AUTOEXP_ON="+aexp_en+"&*AUTOEXP_ON=0xf"; $.ajax({ url: url, success: function(){ console.log("aexp "+(aexp_en?"on":"off")); } }); }); } async function init_inputs(){ $("input").change(function(){ let pname = $(this).attr('pname'); let pvalue = $(this).val(); switch(pname){ case "AUTOEXP_EXP_MAX": pvalue = parseInt(pvalue*1000); set_params({[pname]:pvalue},()=>{ console.log("ok"); }); break; case "EXPOS": pvalue = parseInt(pvalue*1000); // autoexp off if ($('#toggle_aexp').find('.btn.active').html()==="ON"){ $('#toggle_aexp').click(); } set_params({[pname]:pvalue},()=>{ console.log("ok"); }); break; case "TRIG_PERIOD": pvalue = parseInt(1/pvalue*10e7); set_params({[pname]:pvalue},()=>{ console.log("ok"); update_canvas_mjpeg(); }); break; default: } }); } async function init_quick_res_fps(){ // quick_fullres // quick_1080p // quick_720p $("#quick_fullres").click(async function(){ await set_params({ "TRIG_PERIOD" : 10000000 },-2); await set_params({ "AUTOEXP_EXP_MAX": 100000, "WOI_WIDTH" : 10000, "WOI_HEIGHT" : 10000, "WOI_TOP" : 0, "WOI_LEFT" : 0, "SENSOR_RUN" : 0, "COMPRESSOR_RUN" : 3 },3); await set_params({ "TRIG_PERIOD" : 10000000, "SENSOR_RUN" : 2, "COMPRESSOR_RUN" : 2 },7); $(this).parent().find("#ll_status").css({opacity:1}).animate({opacity:0},2000); update_canvas_mjpeg(); }); $("#quick_1080p").click(async function(){ let w = 1920; let h = 1088; await set_params({ "TRIG_PERIOD" : 10000000 },-2); await set_params({ "AUTOEXP_EXP_MAX": 30000, "WOI_WIDTH" : w, "WOI_HEIGHT" : h, "WOI_TOP" : (sensor_height-h)/2, "WOI_LEFT" : (sensor_width-w)/2, "SENSOR_RUN" : 0, "COMPRESSOR_RUN" : 3 },3); await set_params({ "TRIG_PERIOD" : 3333333, "SENSOR_RUN" : 2, "COMPRESSOR_RUN" : 2 },7); $(this).parent().find("#ll_status").css({opacity:1}).animate({opacity:0},2000); update_canvas_mjpeg(); }); $("#quick_720p").click(async function(){ let w = 1280; let h = 720; await set_params({ "TRIG_PERIOD" : 10000000 },-2); await set_params({ "AUTOEXP_EXP_MAX": 16000, "WOI_WIDTH" : w, "WOI_HEIGHT" : h, "WOI_TOP" : (sensor_height-h)/2, "WOI_LEFT" : (sensor_width-w)/2, "SENSOR_RUN" : 0, "COMPRESSOR_RUN" : 3 },3); await set_params({ "TRIG_PERIOD" : 1666667, "SENSOR_RUN" : 2, "COMPRESSOR_RUN" : 2 },7); $(this).parent().find("#ll_status").css({opacity:1}).animate({opacity:0},2000); update_canvas_mjpeg(); }); } async function update_canvas_mjpeg(){ let refresh = parseInt(1/$("#fps").val()*1000); $(".canvas_mjpeg").each(function(){ let href = $(this).attr("href"); href = href.split("?"); let p = new URLSearchParams(href[1]); let port = p.get("port"); $(this).attr("href",href[0]+"?port="+port+"&refresh="+refresh); }); } async function set_params(pars,ahead=3){ let req = []; for(p in pars){ req.push(p+"="+pars[p]+"*"+ahead+"&*"+p+"=0xf"); } let res = await $.ajax({ url: "parsedit.php?immediate&sensor_port=<?php echo $master_port;?>&"+req.join("&") }); return res; } const sleep = ms => { return new Promise(resolve => setTimeout(resolve, ms)); } </script> <body> </html>