Index: trunk/FACT++/www/index.css
===================================================================
--- trunk/FACT++/www/index.css	(revision 13464)
+++ trunk/FACT++/www/index.css	(revision 13464)
@@ -0,0 +1,105 @@
+.thead {
+	background: #23a0da url(gradient.png) bottom left repeat-x;
+	color: #09415b;
+	padding: 4px 6px;
+	border-color: #1379a8;
+	border-style: solid;
+	border-width: 1px 1px 2px 1px;
+	text-shadow: 0 1px 0 #37b2eb;
+	-moz-border-radius: 5px 5px 0 0;
+	-webkit-border-top-left-radius: 5px;
+	-webkit-border-top-right-radius: 5px;
+	font-size: 13px;
+}
+
+.thead a {
+	color: #09415b;
+	text-decoration: none;
+}
+
+.tcat {
+	background: #444;
+	color: #fff;
+	padding: 4px 6px;
+	font-size: 12px;
+}
+
+.tcat a {
+	color: #fff;
+}
+
+.tcol1 {
+	border-left: 1px solid #ccc;
+	border-bottom: 1px solid #ccc;
+}
+
+.tcol2 {
+	border-right: 1px solid #ccc;
+	border-bottom: 1px solid #ccc;
+        text-align:center;
+        margin-left:5px;
+	margin-right:5px;
+}
+
+.tcell1 {
+        font-weight:bolder;
+        text-align:left;
+}
+
+.tcell2 {
+        text-align:right;
+}
+
+//.trow3 {
+//	background: #eee;
+//	border-bottom: 1px solid #ccc;
+//	padding: 4px;
+//}
+
+.trow_shaded {
+	background: #ffdde0;
+	border-bottom: 1px solid #fcc;
+}
+
+.trow_selected td {
+	background: #FFFBD9;
+}
+
+.trow_sep {
+	background: #ddd;
+	color: #555;
+	padding: 4px;
+	text-align: center;
+
+	font-size: 12px;
+	font-weight: bold;
+}
+
+.tfoot {
+	background: #737373 url(gradient.png) bottom left repeat-x;
+	color: #fff;
+	border-color: #525252;
+	border-style: solid;
+	border-width: 2px 1px 1px 1px;
+	vertical-align: middle;
+	padding: 6px;
+	-moz-border-radius: 0 0 5px 5px;
+	-webkit-border-bottom-left-radius: 5px;
+	-webkit-border-bottom-right-radius: 5px;
+	text-shadow: 0 -1px 0 #333;
+	font-size: 12px;
+}
+
+.tfoot a {
+	color: #fff;
+	text-decoration: none;
+}
+
+.container
+{
+ 	padding: 0;
+        margin: 0;
+        width: 100%;
+        border-left:  1px solid #ccc;
+        border-right: 1px solid #ccc;
+}
Index: trunk/FACT++/www/index.html
===================================================================
--- trunk/FACT++/www/index.html	(revision 13464)
+++ trunk/FACT++/www/index.html	(revision 13464)
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional"
+       "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+
+<head>
+  <title>SmartFACT++</title>
+  <script type="text/javascript" src="index.js"></script>
+  <link rel="stylesheet" type="text/css" href="index.css" />
+</head>
+
+<body id="body" onload="onload(true)" onresize="onresize(false)">
+<!--<font size="+2">-->
+<table id="table" border="0" cellspacing="0" cellpadding="6" class="tborder" width="100%">
+
+<!-------------------------------------------------->
+<!------------------    Header   ------------------->
+<!-------------------------------------------------->
+<thead>
+  <tr>
+    <td class="thead" colspan="2" width="100%">
+    <table width="100%"><tr>
+        <td class="tcell1"><font size="+2">&raquo;&nbsp;<a href="forumdisplay.php?fid=1">FACT</a>&nbsp;&laquo;</font></td>
+        <td class="tcell2"><font size="-2"><div id="time">Wed, 25 Apr 2012 10:45:23 GMT</div></font></td>
+      </tr></table>
+    </td>
+  </tr>
+</thead>
+
+<!-------------------------------------------------->
+<!------------------    Body     ------------------->
+<!-------------------------------------------------->
+<tbody>
+  
+  <!------------------- System status ---------------------->
+  <tr class="row" id="system_row">
+    <td class="tcol1" width="100%" onclick="location.href='forumdisplay.php?fid=2';">
+      <table width="100%"><tr>
+        <td class="tcell1" id="system_title">System status</td>
+        <td class="tcell2" id="system">---</td>
+      </tr></table>
+    </td>
+    <td class="tcol2">&gt;</td>
+  </tr>
+
+  <!-------------------- Drive ---------------------------->
+  <tr class="row" id="drive_row">
+    <td class="tcol1" width="100%" onclick="location.href='forumdisplay.php?fid=2';">
+      <table width="100%"><tr>
+        <td class="tcell1" id="drive_title">Drive</td>
+        <td class="tcell2" id="drive">---</td>
+      </tr></table>
+    </td>
+    <td class="tcol2">&gt;</td>
+  </tr>
+
+  <!-------------------- Temperature -------------------->
+  <tr class="row" id="temp_row">
+    <td class="tcol1" width="100%" onclick="location.href='forumdisplay.php?fid=2';">
+     <table width="100%"><tr>
+        <td class="tcell1" id="temp_title">Temp [dew]</td>
+        <td class="tcell2" id="temp">---</td>
+      </tr></table>
+    </td>
+    <td class="tcol2">&gt;</td>
+  </tr>
+
+  <!----------------------- Wind -------------------------->
+  <tr class="row" id="aux_row">
+    <td class="tcol1" width="100%" onclick="location.href='forumdisplay.php?fid=2';">
+     <table width="100%"><tr>
+        <td class="tcell1" id="aux_title">Wind</td>
+        <td class="tcell2" id="aux">---</td>
+      </tr></table>
+    </td>
+    <td class="tcol2">&gt;</td>
+  </tr>
+
+  <!-------------------- Bias ------------------------>
+  <tr class="row" id="bias_row">
+    <td class="tcol1" width="100%" onclick="location.href='forumdisplay.php?fid=2';">
+     <table width="100%"><tr>
+        <td class="tcell1" id="bias_title">Bias</td>
+        <td class="tcell2" id="bias">---</td>
+      </tr></table>
+    </td>
+    <td class="tcol2">&gt;</td>
+  </tr>
+
+  <!-------------------- Picture ------------------------>
+  <tr class="row" style="margin:0;padding:0;"> 
+     <td class="container" id="container" onclick="save()" colspan="2">
+        <canvas id="canvas" width="1" height="1"/>
+     </td>
+  </tr>
+</tbody>
+
+<!-------------------------------------------------->
+<!------------------   Footer    ------------------->
+<!-------------------------------------------------->
+<tfoot>
+  <tr>
+    <td class="tfoot" width="100%" colspan="2">
+     <table width="100%"><tr>
+        <td class="tcell1"><font size="+2"><A HREF="/logbook">logbook</A></font></td>
+        <td class="tcell2"><font size="-2"><div id="localtime">booting...</div></font></td>
+      </tr></table>
+    </td>
+  </tr>
+</tfoot>
+
+</table>
+<!--</font>-->
+
+<!-------------------- Debug ------------------------>
+<div id="debug"/>
+
+      <!--
+        <strong><a href="forumdisplay.php?fid=2" class="forum_on">Logbook</a></strong>
+        <div class="lastbytext">1,210 Posts. Last post:  17.04.2012</div>
+        -->
+
+</body>
+</html>
Index: trunk/FACT++/www/index.js
===================================================================
--- trunk/FACT++/www/index.js	(revision 13464)
+++ trunk/FACT++/www/index.js	(revision 13464)
@@ -0,0 +1,511 @@
+function onload(load)
+{
+    var W = window.innerWidth;
+    var H = window.innerHeight;
+
+    document.getElementById("canvas").width  = 1;
+    document.getElementById("canvas").height = 1;
+
+    var tw = document.getElementById('table').offsetWidth;
+    var th = document.getElementById('table').offsetHeight;
+
+    var margin = (W-tw)*2;
+
+    var cw =     tw;// - margin;
+    var ch = H - th - margin;
+
+    document.getElementById("canvas").width  = cw;
+    document.getElementById("canvas").height = ch;
+
+    // ------ debug -----
+    document.getElementById('debug').innerHTML = "";
+    document.getElementById('debug').innerHTML += "|W="+W+"/"+H;
+    document.getElementById('debug').innerHTML += "|T="+tw+"/"+th;
+    document.getElementById('debug').innerHTML += "|C="+cw+"/"+ch;
+
+    if (!load)
+        return;
+
+    refresh_text();
+    refresh_graphics();
+}
+
+function onresize() 
+{
+    onload();
+}
+
+function refresh_text()
+{
+    var xmlHttp = null;
+
+    try { xmlHttp = new XMLHttpRequest(); }
+    catch(e)
+    {
+        try { xmlHttp  = new ActiveXObject("Microsoft.XMLHTTP"); }
+        catch(e)
+        {
+            try { xmlHttp  = new ActiveXObject("Msxml2.XMLHTTP"); }
+            catch(e)
+            {
+                alert("Your browser doesn't support dynamic reload.");
+                return;
+            }
+        }
+    }
+
+    xmlHttp.open('POST', 'status.txt', true);
+
+    xmlHttp.onreadystatechange =
+        function ()
+        {
+            if (xmlHttp.readyState == 4)
+            {
+                if (xmlHttp.status==0)
+                {
+                    setTimeout("refresh_text()", 3000);
+                    return;
+                }
+                // Handle 404 (not found)
+                if (xmlHttp.status!=200)
+                {
+                    alert("HTTP request error: "+xmlHttp.statusText+" ["+xmlHttp.status+"]");
+                    setTimeout("refresh_text()", 10000);
+                    /****** invalidate ******/
+                    return;
+                }
+
+                process_status(xmlHttp.responseText);
+                setTimeout("refresh_text()", 3000);
+            }
+        };
+
+    xmlHttp.send(null);
+}
+
+function valid(str)
+{
+    if (str==undefined)
+        return false;
+
+    if (str.length==0)
+        return false;
+
+    return true;
+}
+
+function strike(id, status)
+{
+    var e = document.getElementById(id);
+    if (!e)
+        return;
+
+    if (status == false)
+        e.style.textDecoration="line-through";
+    else
+        e.style.textDecoration="";
+}
+
+function gray(id, str)
+{
+    var e = document.getElementById(id);
+    if (!e)
+        return;
+
+    if (valid(str) == true)
+    {
+        e.style.color="#000";
+        e.style.textDecoration="";
+    }
+    else
+    {
+        e.style.color="#daa";
+        e.style.textDecoration="line-through";
+    }
+
+}
+
+var date0 = null;
+
+function process_status(result)
+{
+    var temp    = 1;
+    var dew     = 2;
+    var gusts   = 3;
+    var voltmed = 4;
+    var curmed  = 5;
+    var curmax  = 6;
+    var drive   = 7;
+    var zd      = 8;
+    var az      = 9;
+
+    var tokens = result.split('\n');
+
+    var date1 = new Date();
+
+    if (tokens[0].length!=13)
+    {
+        if (date0 != null)
+        strike("time", date0.getTime()+60000>date1.getTime());
+        // FIXME: Reset display to "---" values -- no connection
+        return;
+    }
+
+    var date2 = new Date();
+    date2.setTime(tokens[0]);
+
+    strike("time", date2.getTime()+60000>date1.getTime());
+
+    date0 = date2;
+
+    gray("drive",   tokens[drive]);
+    gray("temp",    tokens[temp]);
+    gray("volt",    tokens[voltmed]);
+    gray("current", tokens[curmed]);
+
+    document.getElementById("time").innerHTML =
+        "&middot;&nbsp;"+date0.toUTCString()+"&nbsp;&middot;";//getUTCFullYear()+"/"+date0.getUTCMonth()+"/"+date0.getUTCDate()+" "+date0.getUTCHours()+":"+date0.getUTCMinutes()+":"+date0.getUTCSeconds()+"."+date0.getUTCMilliseconds();
+
+    document.getElementById("system").innerHTML =
+        "---";
+
+    if (valid(tokens[drive])) document.getElementById("drive").innerHTML =
+        tokens[drive]+" ["+tokens[zd]+" "+tokens[az]+"]";
+
+    if (valid(tokens[temp]))
+    {
+        document.getElementById("temp").innerHTML =
+            tokens[temp]+"&deg;C ["+tokens[dew]+"&deg;C]";
+        document.getElementById("aux").innerHTML =
+            tokens[gusts]+" km/h";
+
+        document.getElementById("temp_row").style.background="#fff8f0";
+        if (parseFloat(tokens[temp])-parseFloat(tokens[dew])>0.3)
+            document.getElementById("temp_row").style.background="#fffff0";
+        if (parseFloat(tokens[temp])-parseFloat(tokens[dew])>0.7)
+            document.getElementById("temp_row").style.background="#f0fff0";
+
+        document.getElementById("aux_row").style.background="#fff8f0";
+        if (parseFloat(tokens[gusts])<50)
+            document.getElementById("aux_row").style.background="#fffff0";
+        if (parseFloat(tokens[gusts])<35)
+            document.getElementById("aux_row").style.background="#f0fff0";
+    }
+    else
+    {
+        document.getElementById("temp_row").style.background="#ffffff";
+        document.getElementById("aux_row").style.background="#ffffff";
+    }
+
+
+    if (valid(tokens[voltmed]))
+    {
+        document.getElementById("bias").innerHTML =
+            tokens[curmed]+"&micro;A / "+tokens[curmax]+"&micro;A"+
+            " ["+tokens[voltmed]+"V]";
+
+        if (parseFloat(tokens[voltmed])>1)
+            document.getElementById("bias_row").style.background="#f0f0f0";
+        else
+            document.getElementById("bias_row").style.background="#fff0f0";
+    }
+    else
+    {
+        document.getElementById("bias_row").style.background="#ffffff";
+    }
+
+    document.getElementById("localtime").innerHTML = "&middot;&nbsp;"+date1.toLocaleString()+"&nbsp;&middot;";//ISOlocalDateStr();//ltoString();
+/*
+    if (tokens[1]=="Taking Data")
+        document.getElementById("row1").style.background="#d0f0d0";
+    else
+        document.getElementById("row1").style.background="#ffffff";
+
+    if (tokens[2]=="Tracking")
+        document.getElementById("row2").style.background="#d0f0d0";
+    else
+        document.getElementById("row2").style.background="#ffffff";
+
+    document.getElementById("volt").style.textColor="#808080";
+    document.getElementById("row2").style.textColor="#808080";
+    */
+}
+
+// http://billmill.org/static/canvastutorial/index.html
+// http://www.netmagazine.com/tutorials/learning-basics-html5-canvas
+// http://www.alistapart.com/articles/responsive-web-design/
+/*
+function decode_base64(s)
+{
+    var e={};
+    var i,k;
+    var v=[];
+    var r='';
+    var w=String.fromCharCode;
+
+    var n=[[65,91],[97,123],[48,58],[47,48],[43,44]];
+
+    for (z in n)
+    {
+        for(i=n[z][0]; i<n[z][1]; i++)
+        {
+            v.push(w(i));
+        }
+    }
+
+    for(i=0;i<64;i++)
+    {
+        e[v[i]]=i;
+    }
+
+    for(i=0;i<s.length;i+=72)
+    {
+        var b=0,c,x,l=0,o=s.substring(i,i+72);
+        for(x=0;x<o.length;x++)
+        {
+            c=e[o.charAt(x)];b=(b<<6)+c;l+=6;
+            while(l>=8)
+            {
+                r+=w((b>>>(l-=8))%256);
+            }
+        }
+    }
+    return r;
+}*/
+
+function refresh_graphics()
+{
+    var xmlHttp = null;
+
+    try { xmlHttp = new XMLHttpRequest(); }
+    catch(e)
+    {
+        try { xmlHttp  = new ActiveXObject("Microsoft.XMLHTTP"); }
+        catch(e)
+        {
+            try { xmlHttp  = new ActiveXObject("Msxml2.XMLHTTP"); }
+            catch(e)
+            {
+                alert("Your browser doesn't support dynamic reload.");
+                return;
+            }
+        }
+    }
+
+    xmlHttp.open('POST', 'fadcontrol-eventdata.bin', true);
+
+    xmlHttp.onload =
+        function ()
+        {
+            if (xmlHttp.readyState == 4)
+            {
+                if (xmlHttp.status!=200)
+                {
+                    alert("HTTP request error: "+xmlHttp.statusText+" ["+xmlHttp.status+"]");
+                    setTimeout("refresh_text()", 10000);
+                    //****** invalidate ******
+                    return;
+                }
+
+                process_eventdata(xmlHttp.responseText);
+                setTimeout("refresh_graphics()", 5000)
+            }
+        };
+
+    xmlHttp.send(null);
+}
+
+
+function hueToRGB(hue)
+{
+    hue /= 3;
+    hue %= 6;
+
+    if (hue<1) return parseInt(255*hue);
+    if (hue<3) return parseInt(255);
+    if (hue<4) return parseInt(255*(4-hue));
+
+/*
+    if (hue<1*5/4) return parseInt(255*hue*4/5);
+    if (hue<2*5/4) return parseInt(255);
+    if (hue<3*5/4) return parseInt(255*(3*5/4-hue)*4/5);
+*/
+/*
+    if (hue<1.5) return parseInt(255*hue/1.5);
+    if (hue<3.0) return parseInt(255);
+    if (hue<4.5) return parseInt(255*(4.5-hue)/1.5);
+*/
+    return 0.
+}
+
+function hueToHex(flt)
+{
+    var s = hueToRGB(flt).toString(16);
+    return s.length==2 ? s : "0"+s;
+}
+
+function HLStoRGB(hue)
+{
+    hue *= 14;
+
+    var sr = hueToHex(20-hue);
+    var sg = hueToHex(14-hue);
+    var sb = hueToHex(26-hue);
+
+    return sr+sg+sb;
+}
+
+
+function color(col)
+{
+    if (col==65533)
+        col = 0;
+
+    var hue = col/128;
+    return HLStoRGB(hue);
+}
+
+function toHex(str, idx)
+{
+    var ch = str[idx].toString(16);
+    return ch.length==2 ? ch : "0"+ch;
+}
+
+function drawPix(x, y, col)
+{
+    var canv = document.getElementById("canvas");
+
+    var cw = canv.width;
+    var ch = canv.height;
+
+    var w = Math.min(cw/28, ch/28);
+
+    var ctx  = canv.getContext("2d");
+
+    ctx.beginPath();
+    ctx.arc(x*w*2+cw/2, y*w*2+ch/2, w, 0, Math.PI*2, true);
+    ctx.lineWidth = 0;
+    ctx.fillStyle = "#"+color(col);
+    ctx.fill();
+    ctx.closePath();
+}
+
+function process_eventdata(result)
+{
+    if (result.length!=160)
+        return;
+
+    var canv = document.getElementById("canvas");
+
+    var cw = canv.width;
+    var ch = canv.height;
+
+    var ctx = canv.getContext("2d");
+
+    ctx.clearRect(0, 0, cw, ch);
+/*
+    ctx.beginPath();
+    ctx.strokeStyle = "#000000";
+    ctx.moveTo(0, 0);
+    ctx.lineTo(0, ch);
+    ctx.lineTo(cw, ch);
+    ctx.lineTo(cw, 0);
+    ctx.lineTo(0, 0);
+    ctx.stroke();
+    ctx.closePath();
+    */
+
+    drawPix(0, 0, result.charCodeAt(0));
+
+    var gsSin60 = Math.sqrt(3)/2;
+
+    var cnt = 1;
+    for (var ring=1; ring<=30; ring++)
+    {
+        for (var s=0; s<6; s++)
+        {
+            for (var i=1; i<=ring; i++)
+            {
+                var x=0.;
+                var y=0.;
+
+                switch (s)
+                {
+                case 0: x = ring-i*0.5;    y = i*gsSin60;         break;
+                case 1: x = ring*0.5-i;    y = ring*gsSin60;      break;
+                case 2: x = -(ring+i)*0.5; y = (ring-i)*gsSin60;  break;
+                case 3: x = 0.5*i-ring;    y = -i*gsSin60;        break;
+                case 4: x = i-ring*0.5;    y = -ring*gsSin60;     break;
+                case 5: x = (ring+i)*0.5;  y = (-ring+i)*gsSin60; break;
+                }
+
+                if (Math.sqrt(x*x+y*y)>6.7)
+                    continue;
+                if (ring==7 && i==6 && s==0)
+                    continue;
+                if (ring==7 && i==1 && s==1)
+                    continue;
+                if (ring==7 && i==6 && s==3)
+                    continue;
+                if (ring==7 && i==1 && s==4)
+                    continue;
+
+                // Rotate by 60deg
+                var px = Math.sin(Math.PI/3)*x - Math.cos(Math.PI/3)*y;
+                var py = Math.cos(Math.PI/3)*x + Math.sin(Math.PI/3)*y;
+
+                drawPix(px, py, result.charCodeAt(cnt));
+                cnt++;
+
+                if (cnt==159)
+                    break;
+            }
+            if (cnt==159)
+                break;
+        }
+        if (cnt==159)
+            break;
+    }
+
+    ctx.font         = "8pt Arial";
+    ctx.textAlign    = "right";
+    ctx.textBaseline = "top";
+
+    ctx.strokeStyle = "#"+color(0);
+    ctx.strokeText("-2.0V", cw-5, 135);
+
+    ctx.strokeStyle = "#"+color(16);
+    ctx.strokeText("-1.5V", cw-5, 120);
+
+    ctx.strokeStyle = "#"+color(32);
+    ctx.strokeText("-1.0V", cw-5, 105);
+
+    ctx.strokeStyle = "#"+color(48);
+    ctx.strokeText("-0.5V", cw-5, 90);
+
+    ctx.strokeStyle = "#"+color(64);
+    ctx.strokeText("0V", cw-5, 70);
+
+    ctx.strokeStyle = "#"+color(80);
+    ctx.strokeText("0.5V", cw-5, 50);
+
+    ctx.strokeStyle = "#"+color(86);
+    ctx.strokeText("1.0V", cw-5, 35);
+
+    ctx.strokeStyle = "#"+color(102);
+    ctx.strokeText("1.5V", cw-5, 20);
+
+    ctx.strokeStyle = "#"+color(127);
+    ctx.strokeText("2.0V", cw-5, 5);
+
+}
+
+function save()
+{
+    var canvas = document.getElementById("canvas");
+    var img    = canvas.toDataURL("image/png");
+
+    img = img.replace("image/png", "image/octet-stream");
+
+    document.location.href = img;
+}
