From 65c584ff7d2f680ff743e9eb57041b50e8817d43 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Thu, 23 Apr 2026 02:27:52 +0200 Subject: [PATCH] Spectrum/BK4829: interlace large sweeps and cut SPI overhead --- App/app/spectrum.c | 128 +++++++++++++++++++++++++++++++++++++------- App/driver/bk4829.c | 67 +++++++++++++++-------- 2 files changed, 155 insertions(+), 40 deletions(-) diff --git a/App/app/spectrum.c b/App/app/spectrum.c index e6732c9d..7308227a 100644 --- a/App/app/spectrum.c +++ b/App/app/spectrum.c @@ -104,6 +104,14 @@ static uint16_t scanReg30 = 0; // Bidirectional sweep: true = left→right (fStart→fEnd), false = right→left. static bool scanForward = true; +// Optional interlaced progression for large scans (>128 steps). +// 1 = enabled, 0 = disabled. +#ifndef SPECTRUM_INTERLACE_LARGE_SWEEPS +#define SPECTRUM_INTERLACE_LARGE_SWEEPS 1 +#endif +static uint16_t interlaceStride = 1; +static uint16_t interlacePhase = 0; + // Incremental display: one framebuffer page sent per tick instead of a full // BlitFullScreen burst. static uint8_t renderPage = 0; @@ -589,6 +597,16 @@ static void InitScanPosition() scanInfo.i = 0; scanInfo.f = GetFStart(); scanForward = true; +#if SPECTRUM_INTERLACE_LARGE_SWEEPS + interlacePhase = 0; + interlaceStride = 1; + if (scanInfo.measurementsCount > ARRAY_SIZE(rssiHistory)) + { + interlaceStride = + (scanInfo.measurementsCount + ARRAY_SIZE(rssiHistory) - 1) / + ARRAY_SIZE(rssiHistory); + } +#endif } static void InitScan() @@ -1859,10 +1877,100 @@ static void NextScanStep() } } +static bool UseInterlacedSweep() +{ +#if SPECTRUM_INTERLACE_LARGE_SWEEPS + return scanInfo.measurementsCount > ARRAY_SIZE(rssiHistory) && + interlaceStride > 1; +#else + return false; +#endif +} + +static bool NextScanStepInterlaced() +{ + uint16_t next = scanInfo.i + interlaceStride; + + if (next < scanInfo.measurementsCount) + { + scanInfo.i = next; + scanInfo.f += (uint32_t)interlaceStride * scanInfo.scanStep; + return false; + } + + for (uint16_t phase = interlacePhase + 1; phase < interlaceStride; ++phase) + { + if (phase < scanInfo.measurementsCount) + { + interlacePhase = phase; + scanInfo.i = phase; + scanInfo.f = GetFStart() + (uint32_t)phase * scanInfo.scanStep; + return false; + } + } + + interlacePhase = 0; + return true; +} + +static void FinalizeCompletedSweep() +{ + if (! (scanInfo.measurementsCount >> 7)) // if (scanInfo.measurementsCount < 128) + memset(&rssiHistory[scanInfo.measurementsCount], 0, + sizeof(rssiHistory) - scanInfo.measurementsCount * sizeof(rssiHistory[0])); + + // Auto-adjust dbMax unless the user has overridden it manually. + if (manualDbMaxTimer > 0) { + if (--manualDbMaxTimer == 0) + redrawStatus = true; + } else if (!manualSetFlag) { + int newMax = Rssi2DBm(scanInfo.rssiMax) + 5; + int dbMin = settings.dbMin + 10; + if (newMax < dbMin) + newMax = dbMin; + if (newMax > 10) + newMax = 10; + settings.dbMax = newMax; + } + + newScanStart = true; +} + static void UpdateScan() { Scan(); +#if SPECTRUM_INTERLACE_LARGE_SWEEPS + if (UseInterlacedSweep()) + { + bool atEnd = (scanInfo.i + interlaceStride >= scanInfo.measurementsCount); + + if (!atEnd) + { + ++peak.t; + (void)NextScanStepInterlaced(); + return; + } + + preventKeypress = false; + + UpdatePeakInfo(); + if (IsPeakOverLevel()) + { + ToggleRX(true); + TuneToPeak(); + return; + } + + ++peak.t; + if (!NextScanStepInterlaced()) + return; + + FinalizeCompletedSweep(); + return; + } +#endif + bool atEnd = scanForward ? (scanInfo.i >= scanInfo.measurementsCount - 1) : (scanInfo.i <= 1); @@ -1895,25 +2003,7 @@ static void UpdateScan() } // End of backward half-sweep: full round trip done. - if (! (scanInfo.measurementsCount >> 7)) // if (scanInfo.measurementsCount < 128) - memset(&rssiHistory[scanInfo.measurementsCount], 0, - sizeof(rssiHistory) - scanInfo.measurementsCount * sizeof(rssiHistory[0])); - - // Auto-adjust dbMax unless the user has overridden it manually. - if (manualDbMaxTimer > 0) { - if (--manualDbMaxTimer == 0) - redrawStatus = true; - } else if (!manualSetFlag) { - int newMax = Rssi2DBm(scanInfo.rssiMax) + 5; - int dbMin = settings.dbMin + 10; - if (newMax < dbMin) - newMax = dbMin; - if (newMax > 10) - newMax = 10; - settings.dbMax = newMax; - } - - newScanStart = true; + FinalizeCompletedSweep(); } static void UpdateStill() diff --git a/App/driver/bk4829.c b/App/driver/bk4829.c index 63d9ee3d..8d840031 100644 --- a/App/driver/bk4829.c +++ b/App/driver/bk4829.c @@ -39,6 +39,16 @@ static const uint16_t FSK_RogerTable[7] = {0xF1A2, 0x7446, 0x61A4, 0x6544, 0x4E8 static uint16_t gBK4819_GpioOutState; +#define SHORT_DELAY() \ + __asm volatile("nop\n nop\n nop\n nop\n nop\n" \ + "nop\n nop\n nop\n nop\n nop\n" \ + "nop\n nop\n nop\n nop\n nop\n" \ + "nop\n nop\n nop\n nop\n nop\n" \ + "nop\n nop\n nop\n nop\n nop\n" \ + "nop\n nop\n nop\n nop\n nop\n" \ + "nop\n nop\n nop\n nop\n nop\n" \ + "nop\n nop\n nop\n nop\n nop\n") + bool gRxIdleMode; static inline void CS_Assert() @@ -197,63 +207,78 @@ static uint16_t BK4819_ReadU16(void) uint16_t Value; SDA_SetDir(false); - SYSTICK_DelayUs(1); + SHORT_DELAY(); Value = 0; for (i = 0; i < 16; i++) { Value <<= 1; Value |= SDA_ReadInput(); SCL_Set(); - SYSTICK_DelayUs(1); + SHORT_DELAY(); SCL_Reset(); - SYSTICK_DelayUs(1); + SHORT_DELAY(); } SDA_SetDir(true); return Value; } +static uint16_t reg_30_cache = 0xFFFF; +static uint16_t reg_47_cache = 0xFFFF; + uint16_t BK4819_ReadRegister(BK4819_REGISTER_t Register) { uint16_t Value; CS_Release(); SCL_Reset(); - - SYSTICK_DelayUs(1); + SHORT_DELAY(); CS_Assert(); BK4819_WriteU8(Register | 0x80); Value = BK4819_ReadU16(); CS_Release(); - - SYSTICK_DelayUs(1); + SHORT_DELAY(); SCL_Set(); SDA_Set(); + if (Register == BK4819_REG_30) + reg_30_cache = Value; + else if (Register == BK4819_REG_47) + reg_47_cache = Value; + return Value; } void BK4819_WriteRegister(BK4819_REGISTER_t Register, uint16_t Data) { + if (Register == BK4819_REG_30) + { + if (Data == reg_30_cache) + return; + reg_30_cache = Data; + } + else if (Register == BK4819_REG_47) + { + if (Data == reg_47_cache) + return; + reg_47_cache = Data; + } + CS_Release(); SCL_Reset(); - - SYSTICK_DelayUs(1); + SHORT_DELAY(); CS_Assert(); BK4819_WriteU8(Register); - - SYSTICK_DelayUs(1); + SHORT_DELAY(); BK4819_WriteU16(Data); - - SYSTICK_DelayUs(1); + SHORT_DELAY(); CS_Release(); - - SYSTICK_DelayUs(1); + SHORT_DELAY(); SCL_Set(); SDA_Set(); @@ -271,14 +296,14 @@ void BK4819_WriteU8(uint8_t Data) else SDA_Set(); - SYSTICK_DelayUs(1); + SHORT_DELAY(); SCL_Set(); - SYSTICK_DelayUs(1); + SHORT_DELAY(); Data <<= 1; SCL_Reset(); - SYSTICK_DelayUs(1); + SHORT_DELAY(); } } @@ -294,14 +319,14 @@ void BK4819_WriteU16(uint16_t Data) else SDA_Set(); - SYSTICK_DelayUs(1); + SHORT_DELAY(); SCL_Set(); Data <<= 1; - SYSTICK_DelayUs(1); + SHORT_DELAY(); SCL_Reset(); - SYSTICK_DelayUs(1); + SHORT_DELAY(); } }