Lots of general updates. closing in on a solution

This commit is contained in:
cnlohr
2024-07-09 02:17:18 -07:00
parent e0d41ca056
commit edede9d517
5 changed files with 184 additions and 63 deletions
+66 -32
View File
@@ -74,7 +74,7 @@ SOFTWARE.
#include "./usb_config.h" #include "./usb_config.h"
#include "../ch32v003fun/examples_v20x/otg_device/otgusb.h" #include "../ch32v003fun/examples_v20x/otg_device/otgusb.h"
// Bigger buffer decreases chance of fall-through, but increases the size of each operation.
#define ADC_BUFFSIZE 512 #define ADC_BUFFSIZE 512
volatile uint16_t adc_buffer[ADC_BUFFSIZE]; volatile uint16_t adc_buffer[ADC_BUFFSIZE];
@@ -141,8 +141,8 @@ const int32_t g_goertzel_coefficient_s = 2129111628;
int intensity_average = 1; int intensity_average = 1;
#define LOG_GOERTZEL_LIST 512 #define LOG_GOERTZEL_LIST 512
int16_t qibaselogs[LOG_GOERTZEL_LIST*2]; int32_t qibaselogs[LOG_GOERTZEL_LIST];
int qibaselogs_head; volatile int qibaselogs_head;
void SetupADC() void SetupADC()
{ {
@@ -270,9 +270,14 @@ uint32_t g_goertzel_outs;
int32_t g_goertzel, g_goertzelp, g_goertzelp2; int32_t g_goertzel, g_goertzelp, g_goertzelp2;
int32_t g_goertzelp_store, g_goertzelp2_store; int32_t g_goertzelp_store, g_goertzelp2_store;
int32_t g_laststart = 0;
int32_t g_lastper;
int32_t g_lastlen;
void DMA1_Channel1_IRQHandler( void ) __attribute__((interrupt)); void DMA1_Channel1_IRQHandler( void ) __attribute__((interrupt));
void DMA1_Channel1_IRQHandler( void ) void DMA1_Channel1_IRQHandler( void )
{ {
int32_t start = SysTick->CNT;
#ifdef PROFILING_PIN #ifdef PROFILING_PIN
funDigitalWrite( PROFILING_PIN, 1 ); funDigitalWrite( PROFILING_PIN, 1 );
#endif #endif
@@ -360,26 +365,20 @@ void DMA1_Channel1_IRQHandler( void )
if( adc_tail == adc_buffer_top ) adc_tail = adc_buffer; if( adc_tail == adc_buffer_top ) adc_tail = adc_buffer;
if( goertzel_samples == g_goertzel_buffer ) if( goertzel_samples == g_goertzel_buffer )
{ {
#ifdef PROFILING_PIN
funDigitalWrite( PROFILING_PIN, 0 );
#endif
g_goertzelp_store = goertzel - (g_goertzel_omega_per_sample>>(29-16)); g_goertzelp_store = goertzel - (g_goertzel_omega_per_sample>>(29-16));
g_goertzelp2_store = goertzelp; g_goertzelp2_store = goertzelp;
// gertzellogs[gertzellogs_head++] = g_goertzelp_store;
// gertzellogs[gertzellogs_head++] = g_goertzelp2_store;
// gertzellogs_head = gertzellogs_head & ((LOG_GOERTZEL_LIST*2)-1);
//
// int32_t zp = gertzellogs[glread++];
// int32_t zp2 = gertzellogs[glread++];
// int32_t rr = (((int64_t)(g_goertzel_coefficient ) * (int64_t)zp<<1)>>32) - (zp2);
// int32_t ri = (((int64_t)(g_goertzel_coefficient_s) * (int64_t)zp<<1)>>32);
int32_t zp = g_goertzelp_store; int32_t zp = g_goertzelp_store;
int32_t zp2 = g_goertzelp2_store; int32_t zp2 = g_goertzelp2_store;
int32_t rr = (((int64_t)(g_goertzel_coefficient ) * (int64_t)zp<<1)>>32) - (zp2); int32_t rr = (((int64_t)(g_goertzel_coefficient ) * (int64_t)zp<<1)>>32) - (zp2);
int32_t ri = (((int64_t)(g_goertzel_coefficient_s) * (int64_t)zp<<1)>>32); int32_t ri = (((int64_t)(g_goertzel_coefficient_s) * (int64_t)zp<<1)>>32);
qibaselogs[qibaselogs_head++] = rr; qibaselogs[qibaselogs_head] = ((uint16_t)rr) | (((uint16_t)ri)<<16);
qibaselogs[qibaselogs_head++] = ri; qibaselogs_head = ( qibaselogs_head + 1 ) & ((LOG_GOERTZEL_LIST)-1);
qibaselogs_head = qibaselogs_head & ((LOG_GOERTZEL_LIST*2)-1);
rr>>=2; rr>>=2;
ri>>=2; ri>>=2;
@@ -392,7 +391,6 @@ void DMA1_Channel1_IRQHandler( void )
intensity = 1; intensity = 1;
intensity = (intensity + s/intensity)/2; intensity = (intensity + s/intensity)/2;
intensity = (intensity + s/intensity)/2; intensity = (intensity + s/intensity)/2;
intensity = (intensity + s/intensity)/2;
intensity_average = intensity_average - (intensity_average>>10) + (intensity); intensity_average = intensity_average - (intensity_average>>10) + (intensity);
@@ -407,6 +405,10 @@ void DMA1_Channel1_IRQHandler( void )
goertzel = g_goertzel_omega_per_sample>>(29-16); goertzel = g_goertzel_omega_per_sample>>(29-16);
goertzelp = 0; goertzelp = 0;
goertzel_samples = 0; goertzel_samples = 0;
#ifdef PROFILING_PIN
funDigitalWrite( PROFILING_PIN, 1 );
#endif
} }
} }
@@ -421,6 +423,10 @@ void DMA1_Channel1_IRQHandler( void )
#ifdef PROFILING_PIN #ifdef PROFILING_PIN
funDigitalWrite( PROFILING_PIN, 0 ); // For profiling funDigitalWrite( PROFILING_PIN, 0 ); // For profiling
#endif #endif
int32_t end = SysTick->CNT;
g_lastper = start - g_laststart;
g_laststart = start;
g_lastlen = end - start;
} }
static inline uint32_t gets2() static inline uint32_t gets2()
@@ -449,16 +455,17 @@ void InnerLoop()
// Only display half of the list so the other half could // Only display half of the list so the other half could
// be updated by the ISR. // be updated by the ISR.
int glread = qibaselogs_head+LOG_GOERTZEL_LIST*2/2; int glread = qibaselogs_head;
int intensity = 0; int intensity = 0;
for( pxa = 0; pxa < LOG_GOERTZEL_LIST/2; pxa++ ) for( pxa = 0; pxa < LOG_GOERTZEL_LIST; pxa++ )
{ {
glread = (glread)&(LOG_GOERTZEL_LIST*2-1); uint32_t combiq = qibaselogs[glread];
int rr = qibaselogs[glread++]; glread = ( glread + 1 ) & ( LOG_GOERTZEL_LIST -1 );
int ri = qibaselogs[glread++];
int16_t rr = combiq & 0xffff;
int16_t ri = combiq >> 16;
rr = rr * 512 / (intensity_average>>4); rr = rr * 512 / (intensity_average>>4);
ri = ri * 512 / (intensity_average>>4); ri = ri * 512 / (intensity_average>>4);
@@ -477,10 +484,9 @@ void InnerLoop()
} }
#ifdef ENABLE_OLED #ifdef ENABLE_OLED
char cts[32]; //char cts[32];
snprintf( cts, 32, "%d", intensity_average ); //snprintf( cts, 32, "%d", intensity_average );
//ssd1306_drawstr( 0, 0, cts, 1 );
ssd1306_drawstr( 0, 0, cts, 1 );
ssd1306_refresh(); ssd1306_refresh();
//static int ik = 0; //static int ik = 0;
@@ -599,21 +605,19 @@ int main()
uint8_t scratchpad[256]; uint8_t scratchpad[512];
int g_isConfigurePacket = 0; int g_isConfigurePacket = 0;
int HandleHidUserSetReportSetup( struct _USBState * ctx, tusb_control_request_t * req ) int HandleHidUserSetReportSetup( struct _USBState * ctx, tusb_control_request_t * req )
{ {
int id = req->wValue & 0xff; int id = req->wValue & 0xff;
g_isConfigurePacket = 0; g_isConfigurePacket = 0;
if( id == 0xaa && req->wLength < sizeof( scratchpad ) ) if( id == 0xaa && req->wLength <= sizeof( scratchpad ) )
{ {
// memset( scratchpad, 0x55, sizeof(scratchpad) );
//printf( "SET REPORT! %d [%02x]\n", req->wLength, scratchpad[200] );
ctx->pCtrlPayloadPtr = scratchpad; ctx->pCtrlPayloadPtr = scratchpad;
return req->wLength; return req->wLength;
} }
else if( id == 0xac && req->wLength < sizeof( scratchpad ) ) else if( id == 0xac && req->wLength <= sizeof( scratchpad ) )
{ {
g_isConfigurePacket = 1; g_isConfigurePacket = 1;
ctx->pCtrlPayloadPtr = scratchpad; ctx->pCtrlPayloadPtr = scratchpad;
@@ -627,10 +631,40 @@ int HandleHidUserGetReportSetup( struct _USBState * ctx, tusb_control_request_t
int id = req->wValue & 0xff; int id = req->wValue & 0xff;
if( id == 0xaa ) if( id == 0xaa )
{ {
//printf( "GET REPORT! %d\n", req->wLength );
ctx->pCtrlPayloadPtr = scratchpad; ctx->pCtrlPayloadPtr = scratchpad;
return 255; return 255;
} }
else if( id == 0xac )
{
g_isConfigurePacket = 1;
ctx->pCtrlPayloadPtr = scratchpad;
return 63;
}
else if( id == 0xad )
{
static int last_baselog;
int samps_to_send = (qibaselogs_head - last_baselog + LOG_GOERTZEL_LIST * 2 - 1) & (LOG_GOERTZEL_LIST-1);
if( samps_to_send > 120 ) samps_to_send = 120;
((uint32_t*)scratchpad)[0] = (intensity_average<<8) | samps_to_send;
((uint32_t*)scratchpad)[1] = (g_lastper<<16) | g_lastlen;
((uint32_t*)scratchpad)[2] = 0; //Reserved.
int i;
for( i = 3; i < samps_to_send + 3; i++ )
{
last_baselog = (last_baselog+1)&(LOG_GOERTZEL_LIST-1);
((uint32_t*)(scratchpad))[i] = ((int32_t*)qibaselogs)[last_baselog];
}
for( ; i < 128; i++ )
((uint32_t*)(scratchpad))[i] = 0;
ctx->pCtrlPayloadPtr = scratchpad;
return 510;
}
return 0; return 0;
} }
+1 -1
View File
@@ -50,7 +50,7 @@ static const uint8_t HIDAPIRepDesc[ ] =
HID_REPORT_ID ( 0xac ) HID_REPORT_ID ( 0xac )
HID_USAGE ( 0x01 ), HID_USAGE ( 0x01 ),
HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,
HID_REPORT_COUNT ( 254 ), // For receiving IQ data on host. HID_REPORT_COUNT_N ( 510,2 ), // For receiving IQ data on host.
HID_REPORT_ID ( 0xad ) HID_REPORT_ID ( 0xad )
HID_USAGE ( 0x01 ), HID_USAGE ( 0x01 ),
HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,
+15 -4
View File
@@ -198,23 +198,34 @@ function onLoad()
</HEAD> </HEAD>
<BODY onLoad="onLoad()"> <BODY onLoad="onLoad()">
<TABLE WIDTH=100%>
<TR>
<TD COLSPAN=3>
<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> <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> </TD>
<TD ROWSPAN=2 VALIGN=TOP WIDTH=100% ID=LiveGraphContainer>
<CANVAS WIDTH=100% HEIGHT=200 ID=LiveGraph> </CANVAS>
</TD>
</TR>
<TR> <TR>
<TD VALIGN=TOP> <TD VALIGN=TOP>
<TABLE> <TABLE WIDTH=480>
<TR><TD>Crystal MHz</TD><TD><INPUT ID=crystalmhz VALUE=144></TD></TR> <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>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</TD><TD><INPUT ID=quanta VALUE=1024> (Goertzel's Only)</TD></TR>
<TR><TD>Quanta Search Range</TD><TD><INPUT ID=quantasearch VALUE=64> (Goertzel's Algorithm Only)</TD></TR> <TR><TD>Quanta Search Range</TD><TD><INPUT ID=quantasearch VALUE=64> (Goertzel's 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>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> <TR><TD COLSPAN=2><INPUT TYPE=SUBMIT VALUE="Compute" ONCLICK="computeTable()"></TD></TR>
</TABLE> </TABLE>
</TD> </TD>
<TD VALIGN=TOP> <TD VALIGN=TOP>
Live Control: Live Control:
<TABLE><TR><TD><INPUT TYPE=SUBMIT onClick="reqConnect()" VALUE="Open Device" ID=connectButton></TD><TD><DIV ID=STATUS></DIV></TD></TR></TABLE> <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> <DIV ID="StatusPerf"></DIV>
</TD>
</TD>
</TR> </TR>
</TABLE> </TABLE>
+101 -25
View File
@@ -3,6 +3,23 @@ const filter = { vendorId : 0x1209, productId : 0xd035 };
let dev = null; let dev = null;
let loopAbort = false; let loopAbort = false;
const IQHistoryLen = 2048;
var IQHistoryArray = new Uint32Array(IQHistoryLen);
var IQHistoryHead = 0|0;
var lastIntensity = 1.0;
var lastNumQ = 0;
var lastTotalTime = 1;
var lastTimeUsed = 1;
var graphIsClicked = false;
function graphClick( e )
{
if( e.type == "mousedown" ) graphIsClicked = true;
if( e.type == "mouseup" ) graphIsClicked = false;
return true;
}
function setStatus( msg ) function setStatus( msg )
{ {
document.getElementById( "STATUS" ).innerHTML = msg; document.getElementById( "STATUS" ).innerHTML = msg;
@@ -43,6 +60,10 @@ async function closeDeviceTool()
function onLoadWebHidControl() function onLoadWebHidControl()
{ {
liveGraph = document.getElementById( "LiveGraph" );
liveGraph.addEventListener( "mousedown", graphClick );
liveGraph.addEventListener( "mouseup", graphClick );
setTimeout( sendLoop, 1 ); setTimeout( sendLoop, 1 );
if( !navigator.hid ) if( !navigator.hid )
@@ -118,25 +139,26 @@ async function sendLoopError( e )
async function sendLoop() async function sendLoop()
{ {
const sleep = ms => new Promise(r => setTimeout(r, ms)); const sleep = ms => new Promise(r => setTimeout(r, ms));
var arraySend = new Uint8Array(255); //var arraySend = new Uint8Array(255);
var frameNo = 0|0; var frameNo = 0|0;
var lastTime = performance.now(); var lastTime = performance.now();
let goodCount = 0; let goodCount = 0;
let badCount = 0; let badCount = 0;
let kBsecAvg = 0; let kBsecAvg = 0;
let xActionSecAvg = 0; let xActionSecAvg = 0;
while( true ) while( true )
{ {
if( dev && !loopAbort ) if( dev && !loopAbort )
{ {
var i = 0|0; //var i = 0|0;
for( var i = 0|0; i < 255|0; i++ ) //for( var i = 0|0; i < 255|0; i++ )
arraySend[i] = (Math.random()*256)|0; // arraySend[i] = (Math.random()*256)|0;
sendReport = dev.sendFeatureReport( 0xAA, arraySend ).catch( sendLoopError ); //sendReport = dev.sendFeatureReport( 0xAA, arraySend ).catch( sendLoopError );
if( !sendReport ) sendLoopError( "error creating sendFeatureReport" ); //if( !sendReport ) sendLoopError( "error creating sendFeatureReport" );
receiveReport = dev.receiveFeatureReport( 0xAA ).catch( sendLoopError ); receiveReport = dev.receiveFeatureReport( 0xAD ).catch( sendLoopError );
if( !receiveReport ) sendLoopError( "error creating receiveReport" ); if( !receiveReport ) sendLoopError( "error creating receiveReport" );
frameNo++; frameNo++;
@@ -157,6 +179,63 @@ async function sendLoop()
"Good Count: " + goodCount + "<BR>Bad Count: " + badCount; "Good Count: " + goodCount + "<BR>Bad Count: " + badCount;
lastTime = thisTime; lastTime = thisTime;
} }
else if( frameNo % updateStatsPerfPer == 2 )
{
const ctx = liveGraph.getContext("2d");
if( !graphIsClicked )
{
let liveGraphContainer = document.getElementById( "LiveGraphContainer" );
liveGraph.width = liveGraphContainer.clientWidth;
liveGraph.style.position = 'absolute';
ctx.clearRect(0, 0, liveGraph.width, liveGraph.height);
var filledness = lastNumQ * 198 / 120;
ctx.fillStyle = "rgb( 240 240 240 )";
ctx.fillRect( 2, 2 + 198 - filledness, 18, filledness - 2);
filledness = ( lastTimeUsed * 1.0 / lastTotalTime ) * 198;
ctx.fillStyle = "rgb( 240 240 240 )";
ctx.fillRect( 26, 2 + 198 - filledness, 18, filledness - 2 );
ctx.fillStyle = `rgb( 255 255 255 )`;
let mulcoeff = 10000.0 / lastIntensity;
var lot = 1.2;
var x = 253+IQHistoryLen;
for( var i = (IQHistoryHead+1) & (IQHistoryLen-1); i != IQHistoryHead|0; i = (i + 1) & (IQHistoryLen-1) )
{
let v = IQHistoryArray[i];
let real = (v >> 16);
let imag = (v & 0xffff);
if( real > 32767 ) real -= 65536;
if( imag > 32767 ) imag -= 65536;
let power = Math.sqrt( real * real + imag * imag ) * mulcoeff;
let phase = Math.atan2( real, imag ) * 0.159155078*0.5;
real = real * mulcoeff + 100;
imag = imag * mulcoeff + 100;
if( real < 0 ) real = 0; if( real > 255 ) real = 255;
if( imag < 0 ) imag = 0; if( imag > 255 ) imag = 255;
ctx.fillRect(x,power+10,2,2);
ctx.fillRect(x,phase*140+150,2,2);
x--;
ctx.globalAlpha = (lot>0)?lot:0;
ctx.fillRect(real+50,imag,2,2);
ctx.globalAlpha = 1.0;
lot -= 0.0015;
}
ctx.strokeStyle = "rgb( 128 128 128 )";
ctx.fillStyle = "rgb( 128 0 0 )";
ctx.strokeRect( 1, 1, 20, 198 );
ctx.strokeRect( 25, 1, 20, 198 );
ctx.strokeRect( 49, 1, 200, 198 );
ctx.strokeRect( 253, 1, liveGraph.width, 198 );
}
}
if( sendReport ) if( sendReport )
{ {
@@ -164,28 +243,25 @@ async function sendLoop()
} }
if( receiveReport ) if( receiveReport )
{ {
// Validate Data.
let receiveData = await receiveReport; let receiveData = await receiveReport;
if( receiveData && receiveData.buffer ) if( receiveData && receiveData.buffer )
{ {
let data = new Uint8Array( receiveData.buffer ); let data = new Uint32Array( receiveData.buffer.slice( 0, 508 ) );
let intensity = data[0]>>8;
// Tricky: Data goes: let numq = data[0] & 0xff;
// reportID -> Payload... let time_total = data[1]>>16;
let failed = false; let time_used = data[1]&0xffff;
for( var i = 0|0; i < 254|0; i++ ) //console.log( data );
for( var i = 0|0; i < numq; i++ )
{ {
if( data[i+1] != arraySend[i] ) IQHistoryArray[IQHistoryHead++] = data[i+3];
{ if( IQHistoryHead == IQHistoryLen ) IQHistoryHead = 0;
console.log( "Disagreement at index " + i );
console.log( data );
console.log( arraySend );
badCount++;
failed = true;
break;
}
} }
if( !failed ) goodCount++; lastIntensity = intensity;
lastNumQ = numq;
lastTotalTime = time_total;
lastTimeUsed = time_used;
goodCount++;
} }
else else
{ {
@@ -217,7 +293,7 @@ async function sendLoop()
await sleep(100); await sleep(100);
if( dev ) if( dev )
{ {
break; //break;
} }
} }
} }