Fix firmware potential issues from code review
- encISR: now uses direct REG_READ instead of digitalRead for massive speedup - capAnalyze: fixed off-by-one where bit 0 wasn't counted in duty cycle - tickSweepFast: added step boundary guard (< 100) - main loop/OLED: volatile capture counters (capIdx, capTransitions, capLongRuns) are now read inside noInterrupts()/interrupts() blocks to prevent race conditions Made-with: Cursor
This commit is contained in:
38
src/main.cpp
38
src/main.cpp
@@ -112,11 +112,12 @@ static volatile int8_t encDelta = 0; // +1 CW / -1 CCW per detent
|
||||
static uint8_t encLastClk = HIGH;
|
||||
|
||||
void IRAM_ATTR encISR() {
|
||||
const uint8_t clk = digitalRead(ENC_CLK_PIN);
|
||||
const uint32_t in = REG_READ(GPIO_IN_REG);
|
||||
const uint8_t clk = (in >> ENC_CLK_PIN) & 1u;
|
||||
if (clk == encLastClk) return; // filter glitch
|
||||
encLastClk = clk;
|
||||
if (clk == LOW) { // falling edge = one detent
|
||||
encDelta += (digitalRead(ENC_DT_PIN) == HIGH) ? +1 : -1;
|
||||
encDelta += ((in >> ENC_DT_PIN) & 1u) ? +1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,6 +355,7 @@ static String capAnalyze() {
|
||||
|
||||
uint32_t ones = 0, transitions = 0;
|
||||
uint8_t prev = (capBuf[0] >> 0) & 1u;
|
||||
if (prev) ones++; // count bit 0
|
||||
for (uint32_t i = 1; i < capRecBits; i++) {
|
||||
const uint8_t b = (capBuf[i >> 3] >> (i & 7)) & 1u;
|
||||
if (b) ones++;
|
||||
@@ -694,13 +696,18 @@ static void oledDrawStatus() {
|
||||
|
||||
// Progress bar for recording
|
||||
if (cm == CapMode::RECORDING) {
|
||||
const uint32_t pct = capIdx * 100 / (CAP_BUF_BYTES * 8);
|
||||
uint32_t currentIdx, currentTransitions;
|
||||
noInterrupts();
|
||||
currentIdx = capIdx;
|
||||
currentTransitions = capTransitions;
|
||||
interrupts();
|
||||
const uint32_t pct = currentIdx * 100 / (CAP_BUF_BYTES * 8);
|
||||
u8g2.drawFrame(0, 26, 128, 5);
|
||||
u8g2.drawBox(0, 26, (uint8_t)(pct * 128 / 100), 5);
|
||||
snprintf(buf, sizeof(buf), "%lus / %us %lu tr",
|
||||
(unsigned long)(capIdx / CAP_SAMPLE_HZ),
|
||||
(unsigned long)(currentIdx / CAP_SAMPLE_HZ),
|
||||
(unsigned)CAP_DURATION_S,
|
||||
(unsigned long)capTransitions);
|
||||
(unsigned long)currentTransitions);
|
||||
} else {
|
||||
// Replaying — show loop position
|
||||
const uint32_t pct = capRecBits ? capIdx * 100 / capRecBits : 0;
|
||||
@@ -1744,6 +1751,8 @@ static void handleCaptureReplay() {
|
||||
static void handleCaptureStatus() {
|
||||
static const char* const modeStr[] = {"idle","recording","recorded","replaying"};
|
||||
const uint8_t m = (uint8_t)capMode;
|
||||
uint32_t currentIdx;
|
||||
noInterrupts(); currentIdx = capIdx; interrupts();
|
||||
static char buf[512];
|
||||
int n = snprintf(buf, sizeof(buf),
|
||||
"{\"mode\":%u,\"mode_str\":\"%s\","
|
||||
@@ -1751,10 +1760,10 @@ static void handleCaptureStatus() {
|
||||
"\"pct\":%lu,\"freq\":%.3f",
|
||||
(unsigned)m,
|
||||
modeStr[m < 4 ? m : 0],
|
||||
(unsigned long)capIdx,
|
||||
(unsigned long)currentIdx,
|
||||
(unsigned long)(CAP_BUF_BYTES * 8),
|
||||
(unsigned long)capRecBits,
|
||||
(unsigned long)(capIdx * 100UL / (CAP_BUF_BYTES * 8)),
|
||||
(unsigned long)(currentIdx * 100UL / (CAP_BUF_BYTES * 8)),
|
||||
(double)capFreq);
|
||||
|
||||
if (capMode == CapMode::RECORDED || capMode == CapMode::REPLAYING) {
|
||||
@@ -2003,6 +2012,8 @@ static void tickSweepFast(uint8_t csPin, uint8_t& step, uint8_t steps,
|
||||
// Jump to IDLE to safely change registers
|
||||
spiStrobe(csPin, 0x36); // SIDLE
|
||||
|
||||
if (step >= 100) step = 0; // bounds check
|
||||
|
||||
// Write cached FREQ registers (0x0D, 0x0E, 0x0F)
|
||||
spiWriteReg(csPin, 0x0D, table[step].freqRegs[0]);
|
||||
spiWriteReg(csPin, 0x0E, table[step].freqRegs[1]);
|
||||
@@ -2039,15 +2050,24 @@ void loop() {
|
||||
// Signal-present detection: fire OLED "SIGNAL!" once per session when
|
||||
// the ISR has seen enough stable bits to indicate a real RF burst.
|
||||
// capLongRuns > 10 filters out thermal noise which transitions almost constantly.
|
||||
if (capMode == CapMode::RECORDING && !capSigNotified && capLongRuns > 10) {
|
||||
uint32_t currentLongRuns;
|
||||
noInterrupts();
|
||||
currentLongRuns = capLongRuns;
|
||||
interrupts();
|
||||
|
||||
if (capMode == CapMode::RECORDING && !capSigNotified && currentLongRuns > 10) {
|
||||
capSigNotified = true;
|
||||
uint32_t currentIdx;
|
||||
noInterrupts(); currentIdx = capIdx; interrupts();
|
||||
oledNotify("SIGNAL!", "CAUGHT -- PRESS STOP", 3000);
|
||||
logLine("[CAP] Signal detected: " + String(capLongRuns) + " valid symbols @ bit " + String(capIdx));
|
||||
logLine("[CAP] Signal detected: " + String(currentLongRuns) + " valid symbols @ bit " + String(currentIdx));
|
||||
}
|
||||
|
||||
if (capMode == CapMode::RECORDING && capBufFull) {
|
||||
capTimerStop();
|
||||
noInterrupts();
|
||||
capRecBits = capIdx;
|
||||
interrupts();
|
||||
capBufFull = false;
|
||||
capMode = CapMode::RECORDED;
|
||||
gpio_set_direction(capGdoPin, GPIO_MODE_OUTPUT);
|
||||
|
||||
Reference in New Issue
Block a user