Major changes to enable much more wifi information

This commit is contained in:
cnlohr 2015-08-06 23:55:53 -04:00
parent 8e67b46173
commit 577a0e2d36
19 changed files with 1337 additions and 726 deletions

View file

@ -1,9 +1,12 @@
all : execute_reflash page.dat push
IP?=192.168.4.1
mfsmaker : mfsmaker.c
gcc -o $@ $^
page.dat : mfsmaker page
# cat to_compress/*.js | gzip -9 > page/compressed.js.gz
./mfsmaker page page.dat
pushtodev : pushtodev.c
@ -13,7 +16,7 @@ execute_reflash : execute_reflash.c md5.c
gcc -o $@ $^
push : pushtodev page.dat
./pushtodev 192.168.4.1 1048576 page.dat
./pushtodev $(IP) 1048576 page.dat
clean :
rm -rf mfsmaker page.dat pushtodev execute_reflash

View file

@ -127,7 +127,8 @@ uint32_t Push( uint32_t offset, const char * file )
fprintf( stderr, "Error: Timeout in communications.\n" );
exit( -6 );
}
devo += sendsize;
if( reads != 0 )
devo += sendsize;
}
return devo;

View file

@ -1,103 +0,0 @@
<html>
<head>
<title>ColorChord Control Panel</title>
<script language="javascript" type="text/javascript" src=jquery-2.1.4.min.js.gz></script>
<script language="javascript" type="text/javascript" src=colorchord.js></script>
<meta charset="UTF-8">
<style>
table { width: 100%; }
td { vertical-align: top; }
.collapsible { display:none; }
.inbutton { background-color:blue; }
</style>
</head>
<body>
<h2>ColorChord: Embedded</h2>
<hr>
<table>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'SystemStatus' );" value="System Status" id=SystemStatusClicker></td><td>
<div id=SystemStatus class="collapsible">
<table width=100% border=1><tr><td>
<div id=output>
</td></tr></table></div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'Introduction' );" value="Introduction"></td><td>
<div id=Introduction class="collapsible">
<table border=1><tr><td>
System Info...<br>line2<br>line3
</div></td></tr></table></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'WifiSettings' ); KickWifiTicker();" value="Wifi Settings"></td><td>
<div id=WifiSettings class="collapsible">
<table width=100% border=1><tr><td>
Current Configuration:<form name="wifisection" action="javascript:ChangeWifiConfig();">
<table border=1 width=1%>
<tr><td width=1>Type:</td><td><input type="radio" name="wifitype" value=1>Station (Connect to infrastructure)<br><input type="radio" name="wifitype" value=2>AP (Broadcast a new AP)</td></tr>
<tr><td>SSID:</td><td><input type="text" id="wificurname"></td></tr>
<tr><td>PASS:</td><td><input type="text" id="wificurpassword"></td></tr>
<tr><td>Enc:</td><td><input type="radio" name="wificurenctype" value="open">Open<br><input type="radio" name="wificurenctype" value="wpa-wpa2">WPA2-PSK (Ignored in Station mode)</td></tr>
<tr><td>Chan:</td><td><input type="text" id="wificurchannel"> (Ignored in Station mode)</td></tr></tr>
<tr><td></td><td><input type=submit value="Change Settings"></td></tr>
</form></table>
Scanned Stations:
<div id=WifiStations></div>
<input type=submit onclick="QueueOperation('ws', null);" value="Scan For Stations (Will disconnect!)">
</td></tr></table></div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'CustomCommand' );" value="Custom Command"></td><td>
<div id=CustomCommand class="collapsible">
<table width=100% border=1><tr><td>
Command: <input type=text id=custom_command>
<input type=submit value="Submit" onclick="IssueCustomCommand()"><br>
<textarea id=custom_command_response readonly rows=15 cols=80></textarea>
</td></tr></table></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'GPIOs' ); GPIODataTicker();" value="GPIOs"></td><td>
<div id=GPIOs class="collapsible">
<table width=100% border=1><tr>
<td align=center>0<input type=button id=ButtonGPIO0 value=0 onclick="TwiddleGPIO(0);"><input type=button id=BGPIOIn0 value=In onclick="GPIOInput(0);" class="inbutton"></td>
<td align=center>1<input type=button id=ButtonGPIO1 value=0 onclick="TwiddleGPIO(1);"><input type=button id=BGPIOIn1 value=In onclick="GPIOInput(1);" class="inbutton"></td>
<td align=center>2<input type=button id=ButtonGPIO2 value=0 onclick="TwiddleGPIO(2);"><input type=button id=BGPIOIn2 value=In onclick="GPIOInput(2);" class="inbutton"></td>
<td align=center>3<input type=button id=ButtonGPIO3 value=0 onclick="TwiddleGPIO(3);"><input type=button id=BGPIOIn3 value=In onclick="GPIOInput(3);" class="inbutton"></td>
<td align=center>4<input type=button id=ButtonGPIO4 value=0 onclick="TwiddleGPIO(4);"><input type=button id=BGPIOIn4 value=In onclick="GPIOInput(4);" class="inbutton"></td>
<td align=center>5<input type=button id=ButtonGPIO5 value=0 onclick="TwiddleGPIO(5);"><input type=button id=BGPIOIn5 value=In onclick="GPIOInput(5);" class="inbutton"></td>
<td>...</td>
<td align=center>12<input type=button id=ButtonGPIO12 value=0 onclick="TwiddleGPIO(12);"><input type=button id=BGPIOIn12 value=In onclick="GPIOInput(12);" class="inbutton"></td>
<td align=center>13<input type=button id=ButtonGPIO13 value=0 onclick="TwiddleGPIO(13);"><input type=button id=BGPIOIn13 value=In onclick="GPIOInput(13);" class="inbutton"></td>
<td align=center>14<input type=button id=ButtonGPIO14 value=0 onclick="TwiddleGPIO(14);"><input type=button id=BGPIOIn14 value=In onclick="GPIOInput(14);" class="inbutton"></td>
<td align=center>15<input type=button id=ButtonGPIO15 value=0 onclick="TwiddleGPIO(15);"><input type=button id=BGPIOIn15 value=In onclick="GPIOInput(15);" class="inbutton"></td>
</tr></table></div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'OScope' ); KickOscilloscope();" value="Oscilloscope"></td><td>
<div id=OScope class="collapsible">
<table width=100% border=1><tr><td width=10%>
<CANVAS id=OScopeCanvas width=512></CANVAS>
</td><td><input type=button onclick="ToggleOScopePause();" id=OScopePauseButton value="|| / >"></td></tr></table></div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'DFT' ); KickDFT();" value="DFT"></td><td>
<div id=DFT class="collapsible">
<table width=100% border=1><tr><td width=100%>
<CANVAS id=DFTCanvas width=512></CANVAS>
</td></tr></table></div></td></tr>
</table>
</body>
</html>

View file

@ -1,477 +0,0 @@
var wsUri = "ws://" + location.host + "/d/ws/issue";
var output;
var websocket;
var commsup = 0;
//Push objects that have:
// .request
// .callback = function( ref (this object), data );
var workqueue = [];
var workarray = {};
var lastitem;
function QueueOperation( command, callback )
{
if( workarray[command] == 1 )
{
return;
}
workarray[command] = 1;
var vp = new Object();
vp.callback = callback;
vp.request = command;
workqueue.push( vp );
}
function init()
{
$( ".collapsible" ).each(function( index ) {
if( localStorage["sh" + this.id] > 0.5 )
{
$( this ).show().toggleClass( 'opened' );
// console.log( "OPEN: " + this.id );
}
});
$("#custom_command_response").val( "" );
output = document.getElementById("output");
Ticker();
KickWifiTicker();
GPIODataTickerStart();
KickOscilloscope();
KickDFT();
}
function StartWebSocket()
{
output.innerHTML = "Connecting...";
if( websocket ) websocket.close();
workqueue = [];
lastitem = null;
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt)
{
doSend('e' );
}
function onClose(evt)
{
$('#SystemStatusClicker').css("color", "red" );
commsup = 0;
}
var msg = 0;
var tickmessage = 0;
var lasthz = 0;
function Ticker()
{
lasthz = (msg - tickmessage);
tickmessage = msg;
if( lasthz == 0 )
{
$('#SystemStatusClicker').css("color", "red" );
commsup = 0;
StartWebSocket();
}
setTimeout( Ticker, 1000 );
}
function onMessage(evt)
{
msg++;
output.innerHTML = "<p>Messages: " + msg + "</p><p>Hz:" + lasthz + "</p>";
if( commsup != 1 )
{
commsup = 1;
$('#SystemStatusClicker').css("color", "green" );
}
if( lastitem && lastitem.callback )
{
lastitem.callback( lastitem, evt.data );
lastitem = null;
}
if( workqueue.length )
{
var elem = workqueue.shift();
delete workarray[elem.request];
if( elem.request )
{
doSend( elem.request );
lastitem = elem;
return;
}
}
doSend('e');
}
function onError(evt)
{
$('#SystemStatusClicker').css("color", "red" );
commsup = 0;
}
function doSend(message)
{
websocket.send(message);
}
function IsTabOpen( objname )
{
var obj = $( "#" + objname );
var opened = obj.is( '.opened' );
return opened != 0;
}
function ShowHideEvent( objname )
{
var obj = $( "#" + objname );
obj.slideToggle( 'fast' ).toggleClass( 'opened' );
var opened = obj.is( '.opened' );
localStorage["sh" + objname] = opened?1:0;
return opened!=0;
}
function IssueCustomCommand()
{
QueueOperation( $("#custom_command").val(), function( req,data) { $("#custom_command_response").val( data ); } );
}
window.addEventListener("load", init, false);
///////// Various functions that are not core appear down here.
is_oscilloscope_running = false;
pause_oscilloscope = false;
function KickOscilloscope()
{
$( "#OScopePauseButton" ).css( "background-color", (is_oscilloscope_running&&pause_oscilloscope)?"green":"red" );
if( !is_oscilloscope_running && !pause_oscilloscope)
OScopeDataTicker();
}
function ToggleOScopePause()
{
pause_oscilloscope = !pause_oscilloscope;
KickOscilloscope();
}
function GotOScope(req,data)
{
var canvas = document.getElementById('OScopeCanvas');
var ctx = canvas.getContext('2d');
var h = canvas.height;
var w = canvas.width;
if( ctx.canvas.width != canvas.clientWidth ) ctx.canvas.width = canvas.clientWidth;
if( ctx.canvas.height != canvas.clientHeight ) ctx.canvas.height = canvas.clientHeight;
$( "#OScopePauseButton" ).css( "background-color", "green" );
var secs = data.split( ":" );
var samps = Number( secs[1] );
var data = secs[2];
var lastsamp = parseInt( data.substr(0,2),16 );
ctx.clearRect( 0, 0, canvas.width, canvas.height );
ctx.beginPath();
for( var i = 0; i < samps; i++ )
{
var x2 = (i+1) * canvas.clientWidth / samps;
var samp = parseInt( data.substr(i*2+2,2),16 );
var y2 = ( 1.-samp / 255 ) * canvas.clientHeight;
if( i == 0 )
{
var x1 = i * canvas.clientWidth / samps;
var y1 = ( 1.-lastsamp / 255 ) * canvas.clientHeight;
ctx.moveTo( x1, y1 );
}
ctx.lineTo( x2, y2 );
lastsamp = samp;
}
ctx.stroke();
var samp = parseInt( data.substr(i*2,2),16 );
OScopeDataTicker();
}
function OScopeDataTicker()
{
if( IsTabOpen('OScope') && !pause_oscilloscope )
{
is_oscilloscope_running = true;
QueueOperation( "CM", GotOScope );
}
else
{
is_oscilloscope_running = 0;
}
$( "#OScopePauseButton" ).css( "background-color", (is_oscilloscope_running&&!pause_oscilloscope)?"green":"red" );
}
is_dft_running = false;
function KickDFT()
{
if( !is_dft_running )
DFTDataTicker();
}
function GotDFT(req,data)
{
var canvas = document.getElementById('DFTCanvas');
var ctx = canvas.getContext('2d');
var h = canvas.height;
var w = canvas.width;
if( ctx.canvas.width != canvas.clientWidth ) ctx.canvas.width = canvas.clientWidth;
if( ctx.canvas.height != canvas.clientHeight ) ctx.canvas.height = canvas.clientHeight;
var secs = data.split( ":" );
var samps = Number( secs[1] );
var data = secs[2];
var lastsamp = parseInt( data.substr(0,4),16 );
ctx.clearRect( 0, 0, canvas.width, canvas.height );
ctx.beginPath();
for( var i = 0; i < samps; i++ )
{
var x2 = (i+1) * canvas.clientWidth / samps;
var samp = parseInt( data.substr(i*4+4,4),16 );
var y2 = ( 1.-samp / 2047 ) * canvas.clientHeight;
if( i == 0 )
{
var x1 = i * canvas.clientWidth / samps;
var y1 = ( 1.-lastsamp / 2047 ) * canvas.clientHeight;
ctx.moveTo( x1, y1 );
}
ctx.lineTo( x2, y2 );
lastsamp = samp;
}
ctx.stroke();
var samp = parseInt( data.substr(i*2,2),16 );
DFTDataTicker();
}
function DFTDataTicker()
{
if( IsTabOpen('DFT') )
{
is_dft_running = true;
QueueOperation( "CB", GotDFT );
}
else
{
is_dft_running = 0;
}
}
did_wifi_get_config = false;
is_data_ticker_running = false;
function KickWifiTicker()
{
if( !is_data_ticker_running )
WifiDataTicker();
}
function WifiDataTicker()
{
if( IsTabOpen('WifiSettings') )
{
is_data_ticker_running = true;
if( !did_wifi_get_config )
{
QueueOperation( "WI", function(req,data)
{
var params = data.split( "\t" );
document.wifisection.wifitype.value = Number( params[0].substr(2) );
document.wifisection.wificurname.value = params[1];
document.wifisection.wificurpassword.value = params[2];
document.wifisection.wificurenctype.value = params[3];
document.wifisection.wificurchannel.value = Number( params[4] );
did_wifi_get_config = true;
} );
}
QueueOperation( "WR", function(req,data) {
var lines = data.split( "\n" );
var innerhtml;
if( lines.length < 3 )
{
innerhtml = "No APs found. Did you scan?";
}
else
{
innerhtml = "<TABLE border=1><TR><TH>SSID</TH><TH>MAC</TH><TH>RS</TH><TH>Ch</TH><TH>Enc</TH></TR>"
for( i = 1; i < lines.length-1; i++ )
{
var dats = lines[i].split( "\t" );
innerhtml += "<TR><TD>" + dats[0] + "</TD><TD>" + dats[1] + "</TD><TD>" + dats[2] + "</TD><TD>" + dats[3] + "</TD><TD>" + dats[4] + "</TD></TR>";
}
}
innerhtml += "</TABLE>";
document.getElementById("WifiStations").innerHTML = innerhtml;
} );
setTimeout( WifiDataTicker, 500 );
}
else
{
is_data_ticker_running = 0;
}
}
function ChangeWifiConfig()
{
var st = "W";
st += document.wifisection.wifitype.value;
st += ":" + document.wifisection.wificurname.value;
st += ":" + document.wifisection.wificurpassword.value;
QueueOperation( st );
did_wifi_get_config = false;
}
function TwiddleGPIO( gp )
{
var st = "GF";
st += gp;
QueueOperation( st );
}
function GPIOInput( gp )
{
var st = "GI";
st += gp;
QueueOperation( st );
}
function GPIOUpdate(req,data) {
var secs = data.split( ":" );
var op = 0;
var n = Number(secs[2]);
var m = Number(secs[1]);
for( op = 0; op < 16; op++ )
{
var b = $( "#ButtonGPIO" + op );
if( b )
{
if( 1<<op & n )
{
b.css("background-color","red" );
b.css("color","black" );
b.prop( "value", "1" );
}
else
{
b.css("background-color","black" );
b.css("color","white" );
b.prop( "value", "0" );
}
}
b = $( "#BGPIOIn" + op );
if( b )
{
if( 1<<op & m )
{
b.css("background-color","blue" );
b.css("color","white" );
b.attr( "value", "out" );
}
else
{
b.css("background-color","green" );
b.css("color","white" );
b.attr( "value", "in" );
}
}
}
if( IsTabOpen('GPIOs') )
QueueOperation( "GS", GPIOUpdate );
}
function GPIODataTicker()
{
if( !IsTabOpen('GPIOs') ) return;
QueueOperation( "GS", GPIOUpdate );
setTimeout( GPIODataTicker, 500 );
}
function GPIODataTickerStart()
{
if( IsTabOpen('GPIOs') )
GPIODataTicker();
}

View file

@ -1,8 +1,132 @@
<HTML>
<BODY>
Hello! This is a test page.<BR>
<html>
<head>
<title>ColorChord Control Panel</title>
<script language="javascript" type="text/javascript" src=jquery-2.1.4.min.js.gz></script>
<script language="javascript" type="text/javascript" src=main.js></script>
<meta charset="UTF-8">
<style>
table { width: 100%; }
td { vertical-align: top; }
.collapsible { display:none; }
.inbutton { background-color:blue; }
</style>
</head>
<body>
<h2>ColorChord: Embedded</h2>
<hr>
<table>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'SystemStatus' );" value="System Status" id=SystemStatusClicker></td><td>
<div id=SystemStatus class="collapsible">
<table width=100% border=1><tr><td>
<div id=output>
</td></tr></table></div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'Introduction' );" value="Introduction"></td><td>
<div id=Introduction class="collapsible">
<table border=1><tr><td>
<p>Welcome to the ColorChord: Embedded ESP8266 Web-based GUI.</p>
<p>This GUI uses WebSockets, and has only been tested under the newest (as of August, 2015) Chrome and Firefox browsers.</p>
<p>For more information about ColorChord, visit it on github, here: <a href=https://github.com/cnlohr/colorchord>https://github.com/cnlohr/colorchord</a></p>
</div></td></tr></table></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'WifiSettings' ); KickWifiTicker();" value="Wifi Settings"></td><td>
<div id=WifiSettings class="collapsible">
<table width=100% border=1><tr><td>
Current Configuration: (May deviate from default configuration, reset here if in doubt)<form name="wifisection" action="javascript:ChangeWifiConfig();">
<table border=1 width=1%>
<tr><td width=1>Type:</td><td><input type="radio" name="wifitype" value=1>Station (Connect to infrastructure)<br><input type="radio" name="wifitype" value=2 onclick="document.wifisection.wificurname.value = 'ESP'">AP (Broadcast a new AP)</td></tr>
<tr><td>SSID:</td><td><input type="text" id="wificurname"></td></tr>
<tr><td>PASS:</td><td><input type="text" id="wificurpassword"></td></tr>
<tr><td>MAC:</td><td><input type="text" id="wifimac"> (Ignored in softAP mode)</td></tr>
<tr><td>Chan:</td><td><input type="text" id="wificurchannel"> (Ignored in Station mode)</td></tr></tr>
<tr><td></td><td><input type=submit value="Change Settings"> (Automatically saves to flash)</td></tr>
</table></form>
Scanned Stations:
<div id=WifiStations></div>
<input type=submit onclick="QueueOperation('WS', null);" value="Scan For Stations (Will disconnect!)">
</td></tr></table></div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'CustomCommand' );" value="Custom Command"></td><td>
<div id=CustomCommand class="collapsible">
<table width=100% border=1><tr><td>
Command: <input type=text id=custom_command>
<input type=submit value="Submit" onclick="IssueCustomCommand()"><br>
<textarea id=custom_command_response readonly rows=15 cols=80></textarea>
</td></tr></table></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'GPIOs' ); GPIODataTicker();" value="GPIOs"></td><td>
<div id=GPIOs class="collapsible">
<table width=100% border=1><tr>
<td align=center>0<input type=button id=ButtonGPIO0 value=0 onclick="TwiddleGPIO(0);"><input type=button id=BGPIOIn0 value=In onclick="GPIOInput(0);" class="inbutton"></td>
<td align=center>1<input type=button id=ButtonGPIO1 value=0 onclick="TwiddleGPIO(1);"><input type=button id=BGPIOIn1 value=In onclick="GPIOInput(1);" class="inbutton"></td>
<td align=center>2<input type=button id=ButtonGPIO2 value=0 onclick="TwiddleGPIO(2);"><input type=button id=BGPIOIn2 value=In onclick="GPIOInput(2);" class="inbutton"></td>
<td align=center>3<input type=button id=ButtonGPIO3 value=0 onclick="TwiddleGPIO(3);"><input type=button id=BGPIOIn3 value=In onclick="GPIOInput(3);" class="inbutton"></td>
<td align=center>4<input type=button id=ButtonGPIO4 value=0 onclick="TwiddleGPIO(4);"><input type=button id=BGPIOIn4 value=In onclick="GPIOInput(4);" class="inbutton"></td>
<td align=center>5<input type=button id=ButtonGPIO5 value=0 onclick="TwiddleGPIO(5);"><input type=button id=BGPIOIn5 value=In onclick="GPIOInput(5);" class="inbutton"></td>
<td>...</td>
<td align=center>12<input type=button id=ButtonGPIO12 value=0 onclick="TwiddleGPIO(12);"><input type=button id=BGPIOIn12 value=In onclick="GPIOInput(12);" class="inbutton"></td>
<td align=center>13<input type=button id=ButtonGPIO13 value=0 onclick="TwiddleGPIO(13);"><input type=button id=BGPIOIn13 value=In onclick="GPIOInput(13);" class="inbutton"></td>
<td align=center>14<input type=button id=ButtonGPIO14 value=0 onclick="TwiddleGPIO(14);"><input type=button id=BGPIOIn14 value=In onclick="GPIOInput(14);" class="inbutton"></td>
<td align=center>15<input type=button id=ButtonGPIO15 value=0 onclick="TwiddleGPIO(15);"><input type=button id=BGPIOIn15 value=In onclick="GPIOInput(15);" class="inbutton"></td>
</tr></table></div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'OScope' ); KickOscilloscope();" value="Oscilloscope"></td><td>
<div id=OScope class="collapsible">
<table width=100% border=1><tr><td width=10%>
<CANVAS id=OScopeCanvas width=512></CANVAS>
</td><td><input type=button onclick="ToggleOScopePause();" id=OScopePauseButton value="|| / >"></td></tr></table></div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'DFT' ); KickDFT();" value="DFT"></td><td>
<div id=DFT class="collapsible">
<table width=100% border=1><tr><td width=10%>
<CANVAS id=DFTCanvas width=512></CANVAS>
</td><td><select id=WhichCanvas><option value=0>DFT</option><option value=1>Fuzzed</option><option value=2>Folded</option></select>
<br><input type=button onclick="ToggleDFTPause();" id=DFTPauseButton value="|| / >"></td></tr></table></div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'LEDs' ); KickLEDs();" value="LEDs"></td><td>
<div id=LEDs class="collapsible">
<table width=100% border=1><tr><td id=LEDCanvasHolder><CANVAS id=LEDCanvas width=512 height=100></CANVAS></td>
<td><input type=button onclick="ToggleLEDPause();" id=LEDPauseButton value="|| / >"></td></tr></table>
</div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'Notes' ); KickNotes();" value="Notes"></td><td>
<div id=Notes class="collapsible">
<table width=1 border=1><tr><td><CANVAS id=NotesCanvas width=512 height=100></CANVAS></td>
<td width=100%><input type=button onclick="ToggleNotesPause();" id=NotesPauseButton value="|| / >"></td></tr></table>
</div></td></tr>
<tr><td width=1>
<input type=submit onclick="ShowHideEvent( 'Parameters' );" value="Parameters"></td><td>
<div id=Parameters class="collapsible">
<div id=InnerParameters></div>
<input type=button value="Save" onclick='QueueOperation( "CSS" )'> <input type=button value="Revert" onclick='QueueOperation( "CSR" )'> <input type=button value="Restore" onclick='QueueOperation( "CSD" )'>
</div>
</td></tr>
</table>
</body>
</html>
<IMG SRC=dsc.jpg>
</BODY>
</HTML>

View file

@ -0,0 +1,884 @@
var wsUri = "ws://" + location.host + "/d/ws/issue";
var output;
var websocket;
var commsup = 0;
globalParams = {};
//Push objects that have:
// .request
// .callback = function( ref (this object), data );
var workqueue = [];
var wifilines = [];
var workarray = {};
var lastitem;
function QueueOperation( command, callback )
{
if( workarray[command] == 1 )
{
return;
}
workarray[command] = 1;
var vp = new Object();
vp.callback = callback;
vp.request = command;
workqueue.push( vp );
}
function init()
{
$( ".collapsible" ).each(function( index ) {
if( localStorage["sh" + this.id] > 0.5 )
{
$( this ).show().toggleClass( 'opened' );
// console.log( "OPEN: " + this.id );
}
});
$("#custom_command_response").val( "" );
output = document.getElementById("output");
Ticker();
KickWifiTicker();
GPIODataTickerStart();
KickOscilloscope();
KickDFT();
KickNotes();
KickLEDs();
}
function StartWebSocket()
{
output.innerHTML = "Connecting...";
if( websocket ) websocket.close();
workarray = {};
workqueue = [];
lastitem = null;
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt)
{
doSend('e' );
}
function onClose(evt)
{
$('#SystemStatusClicker').css("color", "red" );
commsup = 0;
}
var msg = 0;
var tickmessage = 0;
var lasthz = 0;
function Ticker()
{
setTimeout( Ticker, 1000 );
lasthz = (msg - tickmessage);
tickmessage = msg;
if( lasthz == 0 )
{
$('#SystemStatusClicker').css("color", "red" );
$('#SystemStatusClicker').prop( "value", "System Offline" );
commsup = 0;
StartWebSocket();
}
else
{
$('#SystemStatusClicker').prop( "value", "System " + lasthz + "Hz" );
}
QueueOperation( "CVR", ReceiveParameters );
}
function onMessage(evt)
{
msg++;
if( commsup != 1 )
{
commsup = 1;
$('#SystemStatusClicker').css("color", "green" );
}
if( lastitem )
{
if( lastitem.callback )
{
lastitem.callback( lastitem, evt.data );
lastitem = null;
}
}
else
{
output.innerHTML = "<p>Messages: " + msg + "</p><p>RSSI: " + evt.data.substr(2) + "</p>";
}
if( workqueue.length )
{
var elem = workqueue.shift();
delete workarray[elem.request];
if( elem.request )
{
doSend( elem.request );
lastitem = elem;
return;
}
}
doSend('wx'); //Request RSSI.
}
function onError(evt)
{
$('#SystemStatusClicker').css("color", "red" );
commsup = 0;
}
function doSend(message)
{
websocket.send(message);
}
function IsTabOpen( objname )
{
var obj = $( "#" + objname );
var opened = obj.is( '.opened' );
return opened != 0;
}
function ShowHideEvent( objname )
{
var obj = $( "#" + objname );
obj.slideToggle( 'fast' ).toggleClass( 'opened' );
var opened = obj.is( '.opened' );
localStorage["sh" + objname] = opened?1:0;
return opened!=0;
}
function IssueCustomCommand()
{
QueueOperation( $("#custom_command").val(), function( req,data) { $("#custom_command_response").val( data ); } );
}
window.addEventListener("load", init, false);
///////// Various functions that are not core appear down here.
function ChangeParam( p )
{
var num = Number( p.value );
var elem = p.id.substr( 5 );
QueueOperation( "CVW:" + elem + ":" + num );
}
var hasCreateParams = false;
function ReceiveParameters(req,data) {
var elems = data.split( ":" );
for( var v = 0; v < elems.length; v++ )
{
var pair = elems[v].split( "=" );
if( pair.length == 2 )
{
globalParams[pair[0]] = Number( pair[1] );
}
}
if( !hasCreateParams )
{
hasCreateParams = true;
var htv = "<table border=1><tr><th>Value</th><th width=100%>Parameter</th></tr>";
for( var v in globalParams )
{
var vp = globalParams[v];
htv += "<tr><td><INPUT TYPE=TEXT ID=param" + v + " VALUE=" + vp + " onchange=ChangeParam(this)></td><td>" + v + "</td></tr>";
}
$("#InnerParameters").html( htv + "</table>" );
for( var v in globalParams )
{
if( v.substr(0,1) == 'r' )
{
$("#param" + v).prop( "disabled", true );
}
}
}
for( var v in globalParams )
{
var vp = globalParams[v];
var p = $("#param"+v);
if( !p.is(":focus" ) )
p.val(vp);
}
}
is_oscilloscope_running = false;
pause_oscilloscope = false;
function KickOscilloscope()
{
$( "#OScopePauseButton" ).css( "background-color", (is_oscilloscope_running&&pause_oscilloscope)?"green":"red" );
if( !is_oscilloscope_running && !pause_oscilloscope)
OScopeDataTicker();
}
function ToggleOScopePause()
{
pause_oscilloscope = !pause_oscilloscope;
KickOscilloscope();
}
function GotOScope(req,data)
{
var canvas = document.getElementById('OScopeCanvas');
var ctx = canvas.getContext('2d');
var h = canvas.height;
var w = canvas.width;
if( ctx.canvas.width != canvas.clientWidth ) ctx.canvas.width = canvas.clientWidth;
if( ctx.canvas.height != canvas.clientHeight ) ctx.canvas.height = canvas.clientHeight;
$( "#OScopePauseButton" ).css( "background-color", "green" );
var secs = data.split( ":" );
var samps = Number( secs[1] );
var data = secs[2];
var lastsamp = parseInt( data.substr(0,2),16 );
ctx.clearRect( 0, 0, canvas.width, canvas.height );
ctx.beginPath();
for( var i = 0; i < samps; i++ )
{
var x2 = (i+1) * canvas.clientWidth / samps;
var samp = parseInt( data.substr(i*2+2,2),16 );
var y2 = ( 1.-samp / 255 ) * canvas.clientHeight;
if( i == 0 )
{
var x1 = i * canvas.clientWidth / samps;
var y1 = ( 1.-lastsamp / 255 ) * canvas.clientHeight;
ctx.moveTo( x1, y1 );
}
ctx.lineTo( x2, y2 );
lastsamp = samp;
}
ctx.stroke();
var samp = parseInt( data.substr(i*2,2),16 );
OScopeDataTicker();
}
function OScopeDataTicker()
{
if( IsTabOpen('OScope') && !pause_oscilloscope )
{
is_oscilloscope_running = true;
QueueOperation( "CM", GotOScope );
}
else
{
is_oscilloscope_running = 0;
}
$( "#OScopePauseButton" ).css( "background-color", (is_oscilloscope_running&&!pause_oscilloscope)?"green":"red" );
}
is_dft_running = false;
pause_dft = false;
function KickDFT()
{
$( "#DFTPauseButton" ).css( "background-color", (is_dft_running&&!pause_dft)?"green":"red" );
if( !is_dft_running && !pause_dft )
DFTDataTicker();
}
function ToggleDFTPause()
{
pause_dft = !pause_dft;
KickDFT();
}
function GotDFT(req,data)
{
var canvas = document.getElementById('DFTCanvas');
var ctx = canvas.getContext('2d');
var h = canvas.height;
var w = canvas.width;
if( ctx.canvas.width != canvas.clientWidth ) ctx.canvas.width = canvas.clientWidth;
if( ctx.canvas.height != canvas.clientHeight ) ctx.canvas.height = canvas.clientHeight;
var secs = data.split( ":" );
$( "#DFTPauseButton" ).css( "background-color", "green" );
var samps = Number( secs[1] );
var data = secs[2];
var lastsamp = parseInt( data.substr(0,4),16 );
ctx.clearRect( 0, 0, canvas.width, canvas.height );
ctx.beginPath();
for( var i = 0; i < samps; i++ )
{
var x2 = i * canvas.clientWidth / samps;
var samp = parseInt( data.substr(i*4,4),16 );
var y2 = ( 1.-samp / 2047 ) * canvas.clientHeight;
ctx.fillStyle = CCColor( i % globalParams["rFIXBPERO"] );
ctx.fillRect( x2, y2, canvas.clientWidth / samps, canvas.clientHeight-y2 );
ctx.strokeStyle = "#000000";
ctx.strokeRect( x2, y2, canvas.clientWidth / samps, canvas.clientHeight-y2 );
}
ctx.stroke();
var samp = parseInt( data.substr(i*2,2),16 );
DFTDataTicker();
}
function DFTDataTicker()
{
if( IsTabOpen('DFT') && !pause_dft )
{
is_dft_running = true;
QueueOperation( "CB" + $("#WhichCanvas").val(), GotDFT );
}
else
{
is_dft_running = 0;
}
$( "#DFTPauseButton" ).css( "background-color", (is_dft_running&&!pause_dft)?"green":"red" );
}
is_leds_running = false;
pause_led = false;
function KickLEDs()
{
$( "#LEDPauseButton" ).css( "background-color", (is_leds_running&&!pause_led)?"green":"red" );
if( !is_leds_running && !pause_led )
LEDDataTicker();
}
function ToggleLEDPause()
{
pause_led = !pause_led;
KickLEDs();
}
function GotLED(req,data)
{
var ls = document.getElementById('LEDCanvasHolder');
var canvas = document.getElementById('LEDCanvas');
var ctx = canvas.getContext('2d');
var h = ls.height;
var w = ls.width;
if( canvas.width != ls.clientWidth-10 ) canvas.width = ls.clientWidth-10;
if( ctx.canvas.width != canvas.clientWidth ) ctx.canvas.width = canvas.clientWidth;
var secs = data.split( ":" );
$( "#LEDPauseButton" ).css( "background-color", "green" );
var samps = Number( secs[1] );
var data = secs[2];
var lastsamp = parseInt( data.substr(0,4),16 );
ctx.clearRect( 0, 0, canvas.width, canvas.height );
for( var i = 0; i < samps; i++ )
{
var x2 = i * canvas.clientWidth / samps;
var samp = data.substr(i*6,6);
var y2 = ( 1.-samp / 2047 ) * canvas.clientHeight;
ctx.fillStyle = "#" + samp.substr( 2, 2 ) + samp.substr( 0, 2 ) + samp.substr( 4, 2 );
ctx.lineWidth = 0;
ctx.fillRect( x2, 0, canvas.clientWidth / samps+1, canvas.clientHeight );
}
var samp = parseInt( data.substr(i*2,2),16 );
LEDDataTicker();
}
function LEDDataTicker()
{
if( IsTabOpen('LEDs') && !pause_led )
{
is_leds_running = true;
QueueOperation( "CL", GotLED );
}
else
{
is_leds_running = 0;
}
$( "#LEDPauseButton" ).css( "background-color", (is_leds_running&&!pause_led)?"green":"red" );
}
is_notes_running = false;
pause_notes = false;
function KickNotes()
{
$( "#NotesPauseButton" ).css( "background-color", (is_notes_running&&!pause_notes)?"green":"red" );
if( !is_notes_running && !pause_notes )
NotesTicker();
}
function ToggleNotesPause()
{
pause_notes = !pause_notes;
KickNotes();
}
function GotNotes(req,data)
{
var canvas = document.getElementById('NotesCanvas');
var ctx = canvas.getContext('2d');
var secs = data.split( ":" );
var elems = Number(secs[1] );
ctx.canvas.width = 400;
ctx.canvas.height = elems*25;
$( "#NotesPauseButton" ).css( "background-color", "green" );
var data = secs[2];
ctx.fillStyle = "#000000";
ctx.font = "18px serif"
ctx.fillRect( 0, 0, canvas.width, canvas.height );
for( var i = 0; i < elems; i++ )
{
var peak = parseInt( data.substr(i*12+0,2),16 );
var amped = parseInt( data.substr(i*12+2,4),16 );
var amped2 = parseInt( data.substr(i*12+6,4),16 );
var jump = parseInt( data.substr(i*12+10,2),16 );
if( peak == 255 )
{
ctx.fillStyle = "#ffffff";
ctx.fillText( jump, 10, i*25 + 20 );
continue;
}
ctx.fillStyle = CCColorDetail( peak );
ctx.lineWidth = 0;
ctx.fillRect( 0, i*25, 100,25);
ctx.fillRect( 101, i*25, amped/200,25);
ctx.fillRect( 229, i*25, amped2/200,25);
ctx.fillStyle = "#000000";
ctx.fillText( peak, 10, i*25 + 20 );
ctx.fillStyle = "#ffffff";
ctx.fillText( amped, 121, i*25 + 20 );
ctx.fillText( amped2, 240, i*25 + 20 );
}
var samp = parseInt( data.substr(i*2,2),16 );
NotesTicker();
}
function NotesTicker()
{
if( IsTabOpen('Notes')&& !pause_notes )
{
is_notes_running = true;
QueueOperation( "CN", GotNotes );
}
else
{
is_notes_running = 0;
}
$( "#NotesPauseButton" ).css( "background-color", (is_notes_running&&!pause_notes)?"green":"red" );
}
did_wifi_get_config = false;
is_data_ticker_running = false;
function KickWifiTicker()
{
if( !is_data_ticker_running )
WifiDataTicker();
}
function BSSIDClick( i )
{
var tlines = wifilines[i];
document.wifisection.wifitype.value = 1;
document.wifisection.wificurname.value = tlines[0].substr(1);
document.wifisection.wificurpassword.value = "";
document.wifisection.wifimac.value = tlines[1];
document.wifisection.wificurchannel.value = 0;
return false;
}
function WifiDataTicker()
{
if( IsTabOpen('WifiSettings') )
{
is_data_ticker_running = true;
if( !did_wifi_get_config )
{
QueueOperation( "WI", function(req,data)
{
var params = data.split( "\t" );
document.wifisection.wifitype.value = Number( params[0].substr(2) );
document.wifisection.wificurname.value = params[1];
document.wifisection.wificurpassword.value = params[2];
document.wifisection.wifimac.value = params[3];
document.wifisection.wificurchannel.value = Number( params[4] );
did_wifi_get_config = true;
} );
}
QueueOperation( "WR", function(req,data) {
var lines = data.split( "\n" );
var innerhtml;
if( lines.length < 3 )
{
innerhtml = "No APs found. Did you scan?";
}
else
{
innerhtml = "<TABLE border=1><TR><TH>SSID</TH><TH>MAC</TH><TH>RS</TH><TH>Ch</TH><TH>Enc</TH></TR>"
wifilines = [];
for( i = 1; i < lines.length-1; i++ )
{
tlines = lines[i].split( "\t" );
wifilines.push(tlines);
var bssidval = "<a href='javascript:void(0);' onclick='return BSSIDClick(" + (i -1 )+ ")'>" + tlines[1];
innerhtml += "<TR><TD>" + tlines[0].substr(1) + "</TD><TD>" + bssidval + "</TD><TD>" + tlines[2] + "</TD><TD>" + tlines[3] + "</TD><TD>" + tlines[4] + "</TD></TR>";
}
}
innerhtml += "</TABLE>";
document.getElementById("WifiStations").innerHTML = innerhtml;
} );
setTimeout( WifiDataTicker, 500 );
}
else
{
is_data_ticker_running = 0;
}
}
function ChangeWifiConfig()
{
var st = "W";
st += document.wifisection.wifitype.value;
st += "\t" + document.wifisection.wificurname.value;
st += "\t" + document.wifisection.wificurpassword.value;
st += "\t" + document.wifisection.wifimac.value;
st += "\t" + document.wifisection.wificurchannel.value;
QueueOperation( st );
did_wifi_get_config = false;
}
function TwiddleGPIO( gp )
{
var st = "GF";
st += gp;
QueueOperation( st );
}
function GPIOInput( gp )
{
var st = "GI";
st += gp;
QueueOperation( st );
}
function GPIOUpdate(req,data) {
var secs = data.split( ":" );
var op = 0;
var n = Number(secs[2]);
var m = Number(secs[1]);
for( op = 0; op < 16; op++ )
{
var b = $( "#ButtonGPIO" + op );
if( b )
{
if( 1<<op & n )
{
b.css("background-color","red" );
b.css("color","black" );
b.prop( "value", "1" );
}
else
{
b.css("background-color","black" );
b.css("color","white" );
b.prop( "value", "0" );
}
}
b = $( "#BGPIOIn" + op );
if( b )
{
if( 1<<op & m )
{
b.css("background-color","blue" );
b.css("color","white" );
b.attr( "value", "out" );
}
else
{
b.css("background-color","green" );
b.css("color","white" );
b.attr( "value", "in" );
}
}
}
if( IsTabOpen('GPIOs') )
QueueOperation( "GS", GPIOUpdate );
}
function GPIODataTicker()
{
if( !IsTabOpen('GPIOs') ) return;
QueueOperation( "GS", GPIOUpdate );
setTimeout( GPIODataTicker, 500 );
}
function GPIODataTickerStart()
{
if( IsTabOpen('GPIOs') )
GPIODataTicker();
}
function CCColor( note )
{
return ECCtoHEX( (note * globalParams["rNOTERANGE"] / globalParams["rFIXBPERO"] + globalParams["gROOT_NOTE_OFFSET"] + globalParams["rNOTERANGE"] )%globalParams["rNOTERANGE"], 255, 255 );
}
function CCColorDetail( note )
{
return ECCtoHEX( (note + globalParams["gROOT_NOTE_OFFSET"] + globalParams["rNOTERANGE"] )%globalParams["rNOTERANGE"], 255, 255 );
}
function ECCtoHEX( note, sat, val )
{
var hue = 0;
var third = 65535/3;
var scalednote = note;
var renote = note * 65536 / globalParams["rNOTERANGE"];
//Note is expected to be a vale from 0..(NOTERANGE-1)
//renote goes from 0 to the next one under 65536.
if( renote < third )
{
//Yellow to Red.
hue = (third - renote) >> 1;
}
else if( renote < (third<<1) )
{
//Red to Blue
hue = (third-renote);
}
else
{
//hue = ((((65535-renote)>>8) * (uint32_t)(third>>8)) >> 1) + (third<<1);
hue = (((65536-renote)<<16) / (third<<1)) + (third>>1); // ((((65535-renote)>>8) * (uint32_t)(third>>8)) >> 1) + (third<<1);
}
hue >>= 8;
return EHSVtoHEX( hue, sat, val );
}
function EHSVtoHEX( hue, sat, val ) //0..255 for all
{
var SIXTH1 = 43;
var SIXTH2 = 85;
var SIXTH3 = 128;
var SIXTH4 = 171;
var SIXTH5 = 213;
var or = 0, og = 0, ob = 0;
hue -= SIXTH1; //Off by 60 degrees.
hue = (hue+256)%256;
//TODO: There are colors that overlap here, consider
//tweaking this to make the best use of the colorspace.
if( hue < SIXTH1 ) //Ok: Yellow->Red.
{
or = 255;
og = 255 - (hue * 255) / (SIXTH1);
}
else if( hue < SIXTH2 ) //Ok: Red->Purple
{
or = 255;
ob = hue*255 / SIXTH1 - 255;
}
else if( hue < SIXTH3 ) //Ok: Purple->Blue
{
ob = 255;
or = ((SIXTH3-hue) * 255) / (SIXTH1);
}
else if( hue < SIXTH4 ) //Ok: Blue->Cyan
{
ob = 255;
og = (hue - SIXTH3)*255 / SIXTH1;
}
else if( hue < SIXTH5 ) //Ok: Cyan->Green.
{
og = 255;
ob = ((SIXTH5-hue)*255) / SIXTH1;
}
else //Green->Yellow
{
og = 255;
or = (hue - SIXTH5) * 255 / SIXTH1;
}
var rv = val;
if( rv > 128 ) rv++;
var rs = sat;
if( rs > 128 ) rs++;
//or, og, ob range from 0...255 now.
//Need to apply saturation and value.
or = (or * val)>>8;
og = (og * val)>>8;
ob = (ob * val)>>8;
//OR..OB == 0..65025
or = or * rs + 255 * (256-rs);
og = og * rs + 255 * (256-rs);
ob = ob * rs + 255 * (256-rs);
//printf( "__%d %d %d =-> %d\n", or, og, ob, rs );
or >>= 8;
og >>= 8;
ob >>= 8;
if( or > 255 ) or = 255;
if( og > 255 ) og = 255;
if( ob > 255 ) ob = 255;
return "#" + tohex8(og) + tohex8(or) + tohex8(ob);
}
function tohex8( c )
{
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}

View file

@ -1 +0,0 @@
test

View file

@ -1,10 +0,0 @@
<HTML>
<HEAD>
<title>WebSocket Test</title>
<script language="javascript" type="text/javascript" src=wstest.js></script>
</HEAD>
<BODY>
<h2>WebSocket Test</h2>
<div id="output"></div>
</BODY>
</HTML>

View file

@ -1,86 +0,0 @@
var wsUri = "ws://" + location.host + "/d/ws/echo";
var output;
function init()
{
output = document.getElementById("output");
console.log( wsUri );
testWebSocket();
}
function testWebSocket()
{
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function repeatsend()
{
doSend('Hello!' );
setTimeout( repeatsend, 1000 );
}
function onOpen(evt)
{
writeToScreen("CONNECTED");
doSend('Hello.' );
//repeatsend();
// doSend('{"args": ["entity", 1000], "kwargs": {}, "op": "ClientUpdater__requestUpdates", "seq": 1, "context": ["ClientUpdater", 0]}');
}
function onClose(evt)
{
writeToScreen("DISCONNECTED");
}
var msg = 0;
var tickmessage = 0;
var lasthz = 0;
function Ticker()
{
lasthz = msg - tickmessage;
tickmessage = msg;
setTimeout( Ticker, 1000 );
}
function onMessage(evt)
{
// eval( evt.data );
output.innerHTML = msg++ + " " + lasthz;
doSend('x' );
// obj = JSON.parse(evt.data);
// console.log( obj );
// writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
// websocket.close();
}
function onError(evt)
{
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message)
{
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message)
{
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
Ticker();

View file

@ -84,7 +84,7 @@ int main(int argc, char**argv)
servaddr.sin_port=htons(7878);
int devo = 0;
int lastsector = -1;
int lastsector_block = -1;
int resend_times = 0;
int r;
while( !feof( f ) )
@ -96,9 +96,10 @@ int main(int argc, char**argv)
int reads = fread( buffer, 1, 1024, f );
int sendplace = offset + devo;
int sendsize = reads;
int sector = sendplace / sector_SIZE;
if( sector != lastsector )
#ifdef SECTOR
int sector = sendplace / sector_SIZE;
if( sector != lastsector_block )
{
char se[64];
int sel = sprintf( se, "FE%d\r\n", sector );
@ -120,9 +121,36 @@ int main(int argc, char**argv)
exit( -6 );
}
lastsector = sector;
lastsector_block = sector;
}
#else //block
int block = sendplace / 65536;
if( block != lastsector_block )
{
char se[64];
int sel = sprintf( se, "FB%d\r\n", block );
thissuccess = 0;
for( tries = 0; tries < 10; tries++ )
{
char match[75];
printf( "Erase: %d\n", block );
sendto( sockfd, se, sel, MSG_NOSIGNAL, (struct sockaddr *)&servaddr,sizeof(servaddr));
sprintf( match, "FB%d", block );
if( PushMatch(match) == 0 ) { thissuccess = 1; break; }
printf( "Retry.\n" );
}
if( !thissuccess )
{
fprintf( stderr, "Error: Timeout in communications.\n" );
exit( -6 );
}
lastsector_block = block;
}
#endif
resend_times = 0;
resend:
r = sprintf( bufferout, "FW%d:%d:", sendplace, sendsize );