mirror of
https://github.com/cnlohr/lolra.git
synced 2026-06-15 07:19:25 +00:00
225 lines
7.1 KiB
HTML
225 lines
7.1 KiB
HTML
<!DOCTYPE html>
|
|
<HTML>
|
|
<HEAD>
|
|
<LINK rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
|
|
<META charset="UTF-8">
|
|
<STYLE>
|
|
body {
|
|
background-color: Canvas;
|
|
color: CanvasText;
|
|
}
|
|
:root {
|
|
color-scheme: dark;
|
|
}
|
|
</STYLE>
|
|
|
|
<SCRIPT src=webhidcontrol.js></SCRIPT>
|
|
|
|
<SCRIPT>
|
|
|
|
|
|
function DrawSpan( colspan, freq, target, docolor, extrastr = "" )
|
|
{
|
|
var fdist = Math.abs( freq - target );
|
|
fdist = Math.pow( fdist, 0.5 ) * 500;
|
|
// if( fdist > 255 ) fdist = 255;
|
|
let ret = "<TD COLSPAN=" + colspan + ' ';
|
|
if( docolor ) ret += 'STYLE="color:black;background-color:rgb(' + fdist + ',' + (511-fdist) + ',0)";';
|
|
ret += '>' + extrastr + freq.toFixed(6) + "</TD>";
|
|
return ret;
|
|
}
|
|
|
|
function Goertz( n, mhz, fr, brf )
|
|
{
|
|
let omega = fr * 3.1415926535*2.0;
|
|
var textarea = document.getElementById("goertzeloutput");
|
|
textarea.value =
|
|
"int g_pwm_period = ("+n+"-1);\n" +
|
|
"int g_goertzel_buffer = ("+brf+");\n" +
|
|
"int32_t g_goertzel_omega_per_sample = " + ( omega*2*(1<<29)).toFixed(0) + "; // " + ( omega / (3.1415926535*2.0)).toFixed(6) + " of whole per step / " + mhz.toFixed(6) + "MHz\n" +
|
|
"int32_t g_goertzel_coefficient = " + (2 * Math.cos( omega ) * (1<<30)).toFixed(0) + ";\n" +
|
|
"int32_t g_goertzel_coefficient_s = "+ (2 * Math.sin( omega ) * (1<<30)).toFixed(0) + ";\n";
|
|
|
|
// Highlight its content
|
|
textarea.select();
|
|
|
|
// Copy the highlighted text
|
|
document.execCommand("copy");
|
|
}
|
|
|
|
function computeTable()
|
|
{
|
|
let xtal = Number(document.getElementById("crystalmhz").value );
|
|
let target = Number(document.getElementById("targetmhz").value );
|
|
let quadrature = document.getElementById("QUADRATURE").checked;
|
|
let quanta = Math.round(Number(document.getElementById("quanta").value));
|
|
let quantasearch = Math.round(Number(document.getElementById("quantasearch").value));
|
|
|
|
|
|
const max_harmonics = 28|0;
|
|
const min_harmonics = (quadrature?1:0)|0;
|
|
|
|
let contents = "";
|
|
|
|
if( quadrature )
|
|
{
|
|
contents += "<TABLE>" +
|
|
"<TR><TD>Quadrature:</TD></TR>" +
|
|
"<TR><TD>I = + + - -</TD></TR>" +
|
|
"<TR><TD>Q = + - - +</TD></TR>" +
|
|
"<TR><TD>Differntial:</TD></TR>" +
|
|
"<TR><TD>V = + - + -</TD></TR>" +
|
|
"<TR><TD>You choose the mode you operate in, either Quadrature or differential</TD></TR>" +
|
|
"</TABLE>" +
|
|
"<p> Table shows: </P>" +
|
|
"<TABLE BORDER=1>" +
|
|
"<TR><TD>Sample Frequency Harmonic</TD></TR>" +
|
|
"<TR><TD>Lower Quadrature Frequency</TD></TR>" +
|
|
"<TR><TD>Upper Quadrature Frequency</TD></TR>" +
|
|
"<TR><TD>Differential Frequency</TD></TR>" +
|
|
"</TABLE>";
|
|
}
|
|
else
|
|
{
|
|
contents +=
|
|
"<TABLE BORDER=1>" +
|
|
"<TR><TD>Goertzel</TD></TR>" +
|
|
"<TR><TD>Goertzel (Inverse)</TD></TR>" +
|
|
"</TABLE><TEXTAREA ROWS=6 COLS=120 ID=goertzeloutput></TEXTAREA>" +
|
|
"<P>Click on a ordinal offset to create the C code needed for that tuning parameter. Clicking will copy-to-clipboard.</P>" +
|
|
"<P>N Divisor #30 (row 3) is usually pretty good. And, try to select things near 0.25 / 0.75, and avoid 0.0, 0.5, and 1.0.</P>" +
|
|
"<P>Goertzel's mode is for the ch32v203</P>";
|
|
}
|
|
|
|
contents += "<TABLE BORDER=1>";
|
|
contents += '<TR><TH>d\\h</div></TH>';
|
|
for( let h = 0|min_harmonics; h <= max_harmonics; h++ )
|
|
{
|
|
contents += "<TH COLSPAN=2>" + h + "</TH>";
|
|
}
|
|
|
|
for( let n = 0|28; n <= 66; n++ )
|
|
{
|
|
let freq = ( xtal / n );
|
|
let goertzelpoint = 0;
|
|
let goertzelpointinv = 0;
|
|
let tgoertzelp = 0;
|
|
let tgoertzelpi = 0;
|
|
let quantaA = 0;
|
|
let quantaINV = 0;
|
|
for( let h = 0|min_harmonics; h <= max_harmonics; h++ )
|
|
{
|
|
let base = freq * h;
|
|
let next = freq * (h+1);
|
|
|
|
// Round quanta down to next order-of-4-even
|
|
for( let tquanta = (quanta&0xffffc) - (quantasearch&0xffffc); tquanta < (quanta&0xffffc) + (quantasearch&0xffffc); tquanta+=4 )
|
|
{
|
|
if( target <= next && target >= base )
|
|
{
|
|
var t;
|
|
let tgoertzelpoint = ( target - base ) / ( next - base );
|
|
tgoertzelpoint = Math.round(tquanta * tgoertzelpoint)/tquanta;
|
|
if( Math.abs( freq*(h+tgoertzelpoint) - target ) < Math.abs( freq*(h+goertzelpoint) - target ) )
|
|
{
|
|
goertzelpoint = tgoertzelpoint;
|
|
tgoertzelp = h;
|
|
quantaA = tquanta;
|
|
}
|
|
|
|
let tgoertzelpointinv = (1.0 - ( target - base ) / ( next - base ));
|
|
tgoertzelpointinv = Math.round(tquanta * tgoertzelpointinv)/tquanta;
|
|
|
|
if( Math.abs( freq*(h-tgoertzelpointinv+1) - target ) < Math.abs( freq*(h-goertzelpointinv+1) - target ) )
|
|
{
|
|
goertzelpointinv = tgoertzelpointinv;
|
|
tgoertzelpi = h;
|
|
quantaINV = tquanta;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
contents += "</TR>";
|
|
|
|
for( let mode = 0; mode < 4; mode++ )
|
|
{
|
|
contents += "<TR>";
|
|
if( mode == 0 )
|
|
contents += "<TD ROWSPAN=" + 4 + ">" + n + "</TD>";
|
|
for( let h = 0|min_harmonics; h <= max_harmonics; h++ )
|
|
{
|
|
if( quadrature )
|
|
{
|
|
if( mode == 0 )
|
|
contents += DrawSpan( 2, freq * h, target, false );
|
|
else if( mode == 1 )
|
|
contents += DrawSpan( 2, freq * (h-.25), target, true );
|
|
else if( mode == 2 )
|
|
contents += DrawSpan( 2, freq * (h+.25), target, true );
|
|
else if( mode == 3 )
|
|
contents += DrawSpan( 2, freq * (h+0.5), target, true );
|
|
}
|
|
else
|
|
{
|
|
if( mode == 0 )
|
|
{
|
|
contents += "<TD COLSPAN=2>"
|
|
if( tgoertzelp == h ) contents += "<SPAN ONCLICK='Goertz(" + n + ", " + freq * (h+goertzelpoint) + ", " + (goertzelpoint) + ", " + quantaA + ")'>↑" + (goertzelpoint).toFixed(6) + "</SPAN>";
|
|
contents += "</TD>";
|
|
}
|
|
else if( mode == 1 )
|
|
{
|
|
contents += DrawSpan( 2, freq * (h+goertzelpoint), target, true );
|
|
}
|
|
else if( mode == 2 )
|
|
{
|
|
contents += "<TD COLSPAN=2>"
|
|
if( tgoertzelpi == h-1 ) contents += "<SPAN ONCLICK='Goertz(" + n + ", " + freq * (h-goertzelpointinv) + ", " + goertzelpointinv + ", " + quantaINV + ")'>↓" + goertzelpointinv.toFixed(6) + "</SPAN>";
|
|
contents += "</TD>";
|
|
}
|
|
else if( mode == 3 )
|
|
{
|
|
contents += DrawSpan( 2, freq * (h-goertzelpointinv), target, true );
|
|
}
|
|
}
|
|
}
|
|
contents += "</TD>";
|
|
}
|
|
}
|
|
contents += "</TABLE>";
|
|
document.getElementById( "TABLE" ).innerHTML = contents;
|
|
}
|
|
|
|
function onLoad()
|
|
{
|
|
onLoadWebHidControl();
|
|
}
|
|
</SCRIPT>
|
|
</HEAD>
|
|
<BODY onLoad="onLoad()">
|
|
|
|
<p>Tool for computing tuning to specific frequencies by use of direct ADC reading at specific timer-controlled rate to "tune" to specific frequencies either by quadrature or differential.</p>
|
|
<TABLE>
|
|
<TR>
|
|
<TD VALIGN=TOP>
|
|
<TABLE>
|
|
<TR><TD>Crystal MHz</TD><TD><INPUT ID=crystalmhz VALUE=144></TD></TR>
|
|
<TR><TD>Target MHz</TD><TD><INPUT ID=targetmhz VALUE=27.019360></TD></TR>
|
|
<TR><TD>Quanta</TD><TD><INPUT ID=quanta VALUE=1024> (Goertzel's Algorithm Only)</TD></TR>
|
|
<TR><TD>Quanta Search Range</TD><TD><INPUT ID=quantasearch VALUE=64> (Goertzel's Algorithm Only)</TD></TR>
|
|
<TR><TD>Table Type</TD><TD><INPUT TYPE=RADIO ID=QUADRATURE NAME=computetype checked>Quadrature</INPUT><INPUT TYPE=RADIO ID=GOERTZELS NAME=computetype>Goertzels</INPUT></TD></TR>
|
|
<TR><TD COLSPAN=2><INPUT TYPE=SUBMIT VALUE="Compute" ONCLICK="computeTable()"></TD></TR>
|
|
</TABLE>
|
|
</TD>
|
|
<TD VALIGN=TOP>
|
|
Live Control:
|
|
<TABLE><TR><TD><INPUT TYPE=SUBMIT onClick="reqConnect()" VALUE="Open Device" ID=connectButton></TD><TD><DIV ID=STATUS></DIV></TD></TR></TABLE>
|
|
<DIV ID="StatusPerf"></DIV>
|
|
</TR>
|
|
</TABLE>
|
|
|
|
<DIV ID=TABLE></DIV>
|
|
|
|
</BODY>
|
|
</HTML>
|