Compare commits

...

3 Commits

Author SHA1 Message Date
cnlohr ccf9c1305b Update with remote clock precision checking 2024-10-15 05:50:57 -04:00
cnlohr 2cb413d827 Fix formatting + Prevent LCD from failing at startup 2024-10-15 04:50:19 -04:00
cnlohr fc83ea3c40 Add narrow FSK test 2024-10-15 03:09:55 -04:00
4 changed files with 89 additions and 115 deletions
+7 -1
View File
@@ -636,7 +636,10 @@ int main()
//ssd1306_drawPixel( i+1, i, 1 ); //ssd1306_drawPixel( i+1, i, 1 );
} }
// Not sure why, need to do it a few times to make it stick?
ssd1306_refresh(); ssd1306_refresh();
ssd1306_refresh();
uint8_t force_two_row_mode[] = { uint8_t force_two_row_mode[] = {
0xa8, 0, // Set MUX ratio (Actually # of lines to scan) (But it's this + 1) You can make this 1 for wider. 0xa8, 0, // Set MUX ratio (Actually # of lines to scan) (But it's this + 1) You can make this 1 for wider.
@@ -776,8 +779,11 @@ int HandleHidUserGetReportSetup( struct _USBState * ctx, tusb_control_request_t
((uint32_t*)scratchpad)[1] = (g_lastper<<16) | g_lastlen; ((uint32_t*)scratchpad)[1] = (g_lastper<<16) | g_lastlen;
((uint32_t*)scratchpad)[2] = (0<<16) | (((g_pwm_period+1)*g_goertzel_buffer)); //LSW = 144MHz / X ((uint32_t*)scratchpad)[2] = (0<<16) | (((g_pwm_period+1)*g_goertzel_buffer)); //LSW = 144MHz / X
((uint32_t*)scratchpad)[3] = SysTick->CNT;
((uint32_t*)scratchpad)[4] = *((uint32_t*)adc_buffer);
int i; int i;
for( i = 3; i < samps_to_send + 3; i++ ) for( i = 5; i < samps_to_send + 5; i++ )
{ {
last_baselog = (last_baselog+1)&(LOG_GOERTZEL_LIST-1); last_baselog = (last_baselog+1)&(LOG_GOERTZEL_LIST-1);
((uint32_t*)(scratchpad))[i] = ((int32_t*)qibaselogs)[last_baselog]; ((uint32_t*)(scratchpad))[i] = ((int32_t*)qibaselogs)[last_baselog];
+53 -5
View File
@@ -297,6 +297,45 @@ FMiirphase = 0.0; /* for FM */
FMlastphase = 0.0; /* for FM */ FMlastphase = 0.0; /* for FM */
FMphaseout = 0.0; /* for FM */ FMphaseout = 0.0; /* for FM */
lastadc = 0|0;
remote_clock_mhz = 0;
remote_clock_last_timestamp = 0|0;
remote_clock_last_timems = 0.0;
remote_clock_initted = false;
remote_clock_refinement = 1.0;
remote_clock_total_s = 0;
remote_clock_total_ticks = 0.0;
function ComputeRemoteClock( remote_time_ticks, now_ms )
{
if( !remote_clock_initted )
{
remote_clock_last_timestamp = remote_time_ticks;
remote_clock_last_timems = now_ms;
remote_clock_refinement = 1.0;
remote_clock_initted = true;
remote_clock_total_ms = 0;
remote_clock_total_ticks = 0|0;
return;
}
var delta_s = (now_ms - remote_clock_last_timems)/1000.0;
var delta_clock = ((remote_time_ticks - remote_clock_last_timestamp)|0)*2; // convert 144MHz to 288MHz
var this_mhz = delta_clock / delta_s;
remote_clock_total_s += delta_s;
remote_clock_total_ticks += delta_clock * 1.0;
remote_clock_mhz = remote_clock_total_ticks / remote_clock_total_s;
remote_clock_total_s *= 0.99999;
remote_clock_total_ticks *= 0.99999;
remote_clock_last_timestamp = remote_time_ticks;
remote_clock_last_timems = now_ms;
}
async function sendLoop() async function sendLoop()
{ {
@@ -328,10 +367,16 @@ async function sendLoop()
xActionSecAvg = xActionSecAvg * 0.9 + xActionSec * 0.1; xActionSecAvg = xActionSecAvg * 0.9 + xActionSec * 0.1;
document.getElementById( "StatusPerf" ).innerHTML = document.getElementById( "StatusPerf" ).innerHTML =
(kBsecAvg).toFixed(2) + " kBytes/s<br>" + (kBsecAvg).toFixed(2) + " kB/s<br>" +
(xActionSecAvg).toFixed(2) + "transactions/sec<br>"; (xActionSecAvg).toFixed(2) + "x/s<br>";
document.getElementById( "GeneralData" ).innerHTML = document.getElementById( "GeneralData" ).innerHTML =
"Count: " + goodCount + " / " + badCount + "<br>Inten: " + ((Math.log( lastIntensity * lastIntensity )/Math.log(10)) * 10-120).toFixed(2) + "db (" + lastIntensity + ")"; "<TABLE WIDTH=100%><TR><TD width=25%>Count: " + goodCount + " / " + badCount + "</td>" +
"<td width=20%>Inten: " + ((Math.log( lastIntensity * lastIntensity )/Math.log(10)) * 10-120).toFixed(2) + "db (" + lastIntensity + ")</td>" +
"<td width=20%>ADCs: " + (lastadc>>16).toFixed(0) + " / " + (lastadc&0xffff).toFixed(0) + "</td>" +
"<td width=20%>Remote clock: <INPUT TYPE=SUBMIT VALUE=" + (remote_clock_mhz/1000000.0).toFixed(6) + ` ONMOUSEDOWN="document.getElementById('crystalmhz').value = ${remote_clock_mhz/1000000.0};">MHz ` + "</TD>" +
"<td width=20%>" + ((remote_clock_mhz-288000000)/288).toFixed(3) + " PPM</td>" +
"</tr></table>";
lastTime = thisTime; lastTime = thisTime;
} }
else if( frameNo % updateStatsPerfPer == 2 ) else if( frameNo % updateStatsPerfPer == 2 )
@@ -407,17 +452,21 @@ async function sendLoop()
let receiveData = await receiveReport; let receiveData = await receiveReport;
if( receiveData && receiveData.buffer ) if( receiveData && receiveData.buffer )
{ {
// Receive data from USB (from HandleHidUserGetReportSetup)
let data = new Uint32Array( receiveData.buffer.slice( 0, 508 ) ); let data = new Uint32Array( receiveData.buffer.slice( 0, 508 ) );
let intensity = data[0]>>8; let intensity = data[0]>>8;
let numq = data[0] & 0xff; let numq = data[0] & 0xff;
let time_total = data[1]>>16; let time_total = data[1]>>16;
let time_used = data[1]&0xffff; let time_used = data[1]&0xffff;
let sample_divisor = data[2]&0xffff; let sample_divisor = data[2]&0xffff;
let remote_time = data[3];
ComputeRemoteClock( remote_time, performance.now() );
lastadc = data[4];
let demodbuffer = new Float32Array(numq); let demodbuffer = new Float32Array(numq);
let mulcoeff = 16.0 / lastIntensity; let mulcoeff = 16.0 / lastIntensity;
for( var i = 0|0; i < numq; i++ ) for( var i = 0|0; i < numq; i++ )
{ {
let vv = IQHistoryArray[IQHistoryHead] = data[i+3]; let vv = IQHistoryArray[IQHistoryHead] = data[i+5];
let vi = vv >> 16; let vi = vv >> 16;
let vq = vv & 0xffff; let vq = vv & 0xffff;
if( vi >= 32768 ) vi = vi-65535; if( vi >= 32768 ) vi = vi-65535;
@@ -455,7 +504,6 @@ async function sendLoop()
if( audioContext != null && playingAudioProcessor != null ) if( audioContext != null && playingAudioProcessor != null )
{ {
// TODO: Use crystalmhz
let sampleAdvance = (system_rate/sample_divisor) / audioContext.sampleRate; let sampleAdvance = (system_rate/sample_divisor) / audioContext.sampleRate;
let sampleAdvanceParam = playingAudioProcessor.parameters.get("sampleAdvance"); let sampleAdvanceParam = playingAudioProcessor.parameters.get("sampleAdvance");
sampleAdvanceParam.setValueAtTime( sampleAdvance, audioContext.currentTime); sampleAdvanceParam.setValueAtTime( sampleAdvance, audioContext.currentTime);
+28 -108
View File
@@ -185,14 +185,25 @@ static inline uint32_t getCycleCount()
#define I2C_APLL 0X6D #define I2C_APLL 0X6D
// Number of discrete frequencies
// NOTE: This must be pretty high to keep
// accuracy of specific target frequencies.
#define CHIPSSPREAD 8192
int lastend = 0; int lastend = 0;
// This generates a slow sweep over 17.8 seconds of exactly one full SDM0 iteration
// this is to measure how good dithering can be.
const float fRadiator = 28.08; // In MHz 28.08MHz = in RTTY section of 10 Meters HAM band.
const float fHarmonic = 1.0;
const float fXTAL = 40;
// Set to 2 for highest possible frequencies (up to 69MHz) Lower to get more control at lower frequencies. This is the part in parenthesis (ODIV+2)
// Higher numbers will give you more control. But, there is a limit. 350<40 * (SDM2 + SDM1/(2^8) + SDM0/(2^16) + 4)<500
// Set to 3 for up to 46MHz
// Set to 4 for up to 34MHz
// set to 5 for up to 27MHz (well 27MHzish, you can go a tad higher)
const float nPLLDivisorD2 = 5;
// Configures APLL = 480 / 4 = 120 // Configures APLL = 480 / 4 = 120
// 40 * (SDM2 + SDM1/(2^8) + SDM0/(2^16) + 4) / ( 2 * (ODIV+2) ); // 40 * (SDM2 + SDM1/(2^8) + SDM0/(2^16) + 4) / ( 2 * (ODIV+2) );
// Datasheet recommends that numerator does not exceed 500MHz. // Datasheet recommends that numerator does not exceed 500MHz.
@@ -214,8 +225,8 @@ void IRAM_ATTR local_rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sd
// Settings determined experimentally. // Settings determined experimentally.
REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OC_TSCHGP, 0 ); // 0 or 1 REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OC_TSCHGP, 0 ); // 0 or 1
REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_EN_FAST_CAL, 1 ); // 0 or 1 REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_EN_FAST_CAL, 1 ); // 0 or 1
REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OC_DHREF_SEL, 0 ); // 0..3 REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OC_DHREF_SEL, 3 ); // 0..3
REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OC_DLREF_SEL, 0 ); // 0..3 REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OC_DLREF_SEL, 2 ); // 0..3
REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_SDM_DITHER, 1 ); // 0 or 1 REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_SDM_DITHER, 1 ); // 0 or 1
REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OC_DVDD, 25 ); // 0 .. 31 REGI2C_WRITE_MASK(I2C_APLL, I2C_APLL_OC_DVDD, 25 ); // 0 .. 31
@@ -291,7 +302,7 @@ void sandbox_main()
int sdm0 = 100; int sdm0 = 100;
int sdm1 = 230; int sdm1 = 230;
int sdm2 = 8; int sdm2 = 8;
int odiv = 0; int odiv = nPLLDivisorD2-2;
local_rtc_clk_apll_enable( use_apll, sdm0, sdm1, sdm2, odiv ); local_rtc_clk_apll_enable( use_apll, sdm0, sdm1, sdm2, odiv );
@@ -319,123 +330,33 @@ void sandbox_main()
uint32_t frame = 0; uint32_t frame = 0;
void sandbox_tick() void sandbox_tick()
{ {
//uprintf( "%08x\n", REGI2C_READ(I2C_APLL, I2C_APLL_DSDM2 ));
// 40 * (SDM2 + SDM1/(2^8) + SDM0/(2^16) + 4) / ( 2 * (ODIV+2) );\n
// 13rd harmonic.
const float fRadiator = 50.50 + 0.00; // 0.02 is specific to this device.
const float fBandwidth = 1;
const float fHarmonic = 1.0;
const float fOffset = -(fBandwidth/2);
const float fXTAL = 40;
const float fTarg = (fRadiator+fOffset)/fHarmonic; const float fTarg = (fRadiator)/fHarmonic;
const float fAPLL = fTarg * 2; const float fAPLL = fTarg * 2;
const uint32_t sdmBaseTarget = ( fAPLL * 4 / fXTAL - 4 ) * 65536 + 0.5; // ~649134 const uint32_t sdmBaseTarget = ( fAPLL * (nPLLDivisorD2*2) / fXTAL - 4 ) * 65536 + 0.5; // ~649134
const float fRange = (fBandwidth)/fHarmonic;
const float fAPLLRange = fRange * 2;
const float sdmRange = ( fAPLLRange * 4 / fXTAL ) * 65536; // ~126
// 491520 clocks per chip @ SF8 (2.048ms per chirp)
const uint32_t sdmDivisor = ( CHIPSSPREAD / sdmRange ) + 0.5;
#if 0
// For DEBUGGING ONLY
int k;
//DisableISR();
for( k = 0; k < 33; k++ )
{
int fplv = 0;
// Send every second
// If you want to dialate time, do it here.
frame = (getCycleCount()/200) % 24000000;
fplv = SigGen( frame, codeTarg );
uint32_t codeTargUse = codeTarg + fplv;
uint32_t sdm = (codeTargUse * 2 / 40 - 4 * 65536); //XXX WARNING CHARLES, why does this move in pairs?
apll_quick_update( sdm );
if( fplv < 0 ) break;
if( fplv > 0 )
uprintf( "%d %d\n", (int)sdm, (int)fplv );
}
//EnableISR();
#else
uint32_t start = getCycleCount();
frame = (start) % 24000000;
int do_send = false;
if( (uint32_t)(start - lastend) > 240000000 )
{
do_send = true;
}
{
int spin;
gpio_matrix_out( 39, PRO_ALONEGPIO_OUT0_IDX, 0, 0 );
gpio_set_drive_capability( 39, GPIO_DRIVE_CAP_3 );
// Create an RGB Rainbow value
uint32_t ws_out = 0xff00ff;//do_send? 0 : 0xff;
#define nop __asm__ __volatile__("nop\n")
int i;
// Shift out all 24 bits, note the 1 and 3 for timing is baesed off an XTAL clock.
for( i = 0; i < 24; i++ )
{
__asm__ __volatile__ ("set_bit_gpio_out 0x1");
int high_for = ( ws_out & 0x800000 )?3:1;
for( spin = 0; spin < high_for; spin++ ) nop;
__asm__ __volatile__ ("clr_bit_gpio_out 0x1");
int low_for = ( ws_out & 0x800000 )?1:3;
for( spin = 0; spin < low_for; spin++ ) nop;
ws_out<<=1;
}
esp_rom_delay_us( 5000 );
}
if( do_send )
{ {
int iterct = 0; int iterct = 0;
int dither = 0; int dither = 0;
gpio_matrix_out( GPIO_NUM(RF1_PIN), CLK_I2S_MUX_IDX, 1, 0 ); gpio_matrix_out( GPIO_NUM(RF1_PIN), CLK_I2S_MUX_IDX, 1, 0 );
gpio_matrix_out( GPIO_NUM(RF2_PIN), CLK_I2S_MUX_IDX, 0, 0 ); gpio_matrix_out( GPIO_NUM(RF2_PIN), CLK_I2S_MUX_IDX, 0, 0 );
//REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD, 0);
//REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, 1);
//DisableISR(); //DisableISR();
while(1) while(1)
{ {
int fplv = 0; int fplv = 0;
// Send every second frame = (getCycleCount());
// If you want to dialate time, do it here. fplv = 0;
frame = (getCycleCount()) - start; int microtone = ((frame & 0xfff00000 ) >> 20);
//fplv = SigGen( frame, sdmBaseTarget ); dither = (((iterct)&0xffff)<microtone)?1:0;
uint32_t sdm = sdmBaseTarget + fplv + dither;//( fplv ) / sdmDivisor + dither;
//fplv = ((frame & 0x30000000 ) >> 28) * CHIPSSPREAD / 4;
fplv = ((frame & 0x30000000 ) >> 28) *sdmDivisor;
//XXX TODO: Experiment more with dither. It doesn't appear to have an immediate effect?
//dither = ( dither + sdmDivisor/4) % sdmDivisor;
uint32_t sdm = sdmBaseTarget + ( fplv + dither ) / sdmDivisor;
if( fplv < 0 ) break;
apll_quick_update( sdm ); apll_quick_update( sdm );
iterct++; iterct++;
} }
//EnableISR();
//REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, 0);
//REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD, 1);
gpio_matrix_out( GPIO_NUM(RF1_PIN), CLK_I2S_MUX_IDX, 1, 1 ); gpio_matrix_out( GPIO_NUM(RF1_PIN), CLK_I2S_MUX_IDX, 1, 1 );
gpio_matrix_out( GPIO_NUM(RF2_PIN), CLK_I2S_MUX_IDX, 0, 1 ); gpio_matrix_out( GPIO_NUM(RF2_PIN), CLK_I2S_MUX_IDX, 0, 1 );
@@ -443,7 +364,6 @@ void sandbox_tick()
printf( "Iter: %d\n", iterct ); printf( "Iter: %d\n", iterct );
lastend = getCycleCount(); lastend = getCycleCount();
} }
#endif
// vTaskDelay( 1 ); // vTaskDelay( 1 );
} }