Docs: CC1101 SWRS061 notes and POTENTIAL_ISSUES refresh
- POTENTIAL_ISSUES: sweep/VCO section replaced (fixed-carrier); add CC1101 bullets - Mark capAnalyze bit-0 item as addressed - config.h: comment tying lock/deviation to FREQ/DEVIAT/GDO0 per TI CC1101 Made-with: Cursor
This commit is contained in:
103
POTENTIAL_ISSUES.md
Normal file
103
POTENTIAL_ISSUES.md
Normal file
@@ -0,0 +1,103 @@
|
||||
## Potential bugs / edge cases (firmware + UI)
|
||||
|
||||
**Scope**: This file lists things that look *potentially* wrong, brittle, or surprising in the current codebase. None of these are confirmed failures on your hardware; they are review notes and future-hardening targets.
|
||||
|
||||
---
|
||||
|
||||
### 1. Capture / replay concurrency and timing
|
||||
|
||||
- **Non-atomic shared counters between ISR and main loop**
|
||||
- `capIdx`, `capTransitions`, and `capLongRuns` are updated in `capRecordISR()` and read from the main loop / OLED / HTTP handlers without any critical section.
|
||||
- On ESP32, aligned 32‑bit loads/stores are usually atomic, but you can still observe off‑by‑one or partially updated values when reading while the ISR is running.
|
||||
- **Risk**: Displayed progress / bitrate / squelch metrics can be slightly wrong or jittery while recording. Functionally low‑risk, but it’s technically a race.
|
||||
|
||||
- **~~Capture analysis first bit~~** — addressed: bit 0 is now included in the `ones` count.
|
||||
|
||||
- **Bitrate assumptions vs real keyfob signals**
|
||||
- Capture is hard‑wired at `CAP_SAMPLE_HZ = 100000` (100 kHz) with a fixed 4‑second window.
|
||||
- Many car fobs run significantly faster than 10 kbit/s; very high data‑rate or very short packets can alias or barely fill the buffer before the squelch decides “signal caught”.
|
||||
- **Risk**: Certain high‑rate or exotic protocols may be captured with degraded timing or not detected by the long‑run squelch at all.
|
||||
|
||||
---
|
||||
|
||||
### 2. Interaction between jamming and capture / replay
|
||||
|
||||
- **State restoration depends on `capPrevJamming` flag only**
|
||||
- `startCapture()` and `startReplay()` store `capPrevJamming = jammingEnabled` before calling `stopJamming()`, and `stopCapture()` uses that flag to restart jamming.
|
||||
- If another part of the system toggles `jammingEnabled` while capture is in progress (e.g. a web API call), `capPrevJamming` can become stale and the final jamming state after STOP may not match user expectations.
|
||||
- **Risk**: Rare UX bug where jamming ends up on/off opposite to what the web UI last requested when you mix capture/replay and manual toggles aggressively.
|
||||
|
||||
- **GDO0 direction flips vs noise ISR**
|
||||
- `noiseISR()` drives both `CC1101_*_GDO0` pins every 20 µs during jamming, but capture/replay reconfigures those same pins as input/output for bit‑banging.
|
||||
- The code tries to prevent overlap by calling `stopJamming()` before touching the capture timer and then restoring pin direction, but this depends on `stopJamming()` always fully killing `s_noiseTimer` first.
|
||||
- **Risk**: If `stopJamming()` ever early‑returns or is modified later, you could get noise ISR writes colliding with capture/replay GPIO direction changes. Right now it looks correct, but it’s a fragile area to touch.
|
||||
|
||||
---
|
||||
|
||||
### 3. Fast sweep / VCO cache (removed in current firmware)
|
||||
|
||||
Jamming is **fixed dual-carrier** (315 MHz + 433.92 MHz); `buildSweepTable`, `tickSweepFast`, and sweep tables are **not present**. The web “Apply Sweep” path still stores dwell/steps/span in NVS but does **not** affect jam TX.
|
||||
|
||||
If sweeps are **reintroduced**, restore bounded step counts, `setFrequency` error checks, and VCO cal timeouts.
|
||||
|
||||
---
|
||||
|
||||
### 3b. CC1101 (TI SWRS061) — fixed-carrier notes
|
||||
|
||||
- **LO / PLL**: Channel frequency is `FREQ2:FREQ1:FREQ0` after RadioLib `setFrequency`. Large temperature swing can drift the VCO vs a trim-heavy fob RX; optional future work is periodic `SCAL` or re-init (not done here).
|
||||
- **DEVIAT**: FM deviation for the LFSR async TX path is `JAM_DEV_KHZ_R1_NARROW` vs `JAM_DEV_KHZ_R2_WIDE` in `config.h`. If 315 MHz jam feels weak, raise R1 deviation toward R2.
|
||||
- **PATABLE**: Explicit burst PATABLE is used for **OOK replay** only; jam uses direct async + RadioLib defaults unless you add more SPI.
|
||||
- **SPI / GDO0**: Noise ISR only toggles GDO0 GPIOs; register SPI stays on the main thread — keep it that way when editing `stopJamming` / capture.
|
||||
|
||||
---
|
||||
|
||||
### 4. Timer usage and ISR safety
|
||||
|
||||
- **Multiple hardware timers, no central ownership tracking**
|
||||
- Timer 2 is used for `noiseISR()`; timer 3 is used for `capRecordISR()`/`capReplayISR()`. Each `*_Start()` tears down and re‑creates its timer instance.
|
||||
- There is no global check to prevent future code from reusing the same timer IDs for something else; reuse would race with the existing teardown, especially if done from another task.
|
||||
- **Risk**: Currently safe as long as no new timers are introduced. Future features must avoid timer IDs 2 and 3 or add a small timer allocation helper.
|
||||
|
||||
- **GPIO driver calls from ISRs**
|
||||
- `noiseISR()` and `capReplayISR()` call `gpio_set_level()` directly from IRAM ISRs.
|
||||
- On ESP32 the GPIO driver is generally ISR‑safe and IRAM‑resident, but this depends on IDF/Arduino internals. If the platform evolves or gets misconfigured (e.g. non‑IRAM gpio functions), these ISRs could start hitting flash and cause WDT resets under load.
|
||||
- **Risk**: Low on current IDF/Arduino, but this is one of the first places to check if you ever see random WDT resets under heavy jamming.
|
||||
|
||||
---
|
||||
|
||||
### 5. Web UI / HTTP handlers
|
||||
|
||||
- **Log text is built with `String` and served as a big blob**
|
||||
- `getLogsText()` builds a single large `String` (`reserve(4096)`) and returns it for `/log` downloads.
|
||||
- On its own this is fine, but if log lines become much longer than expected or you ever increase `LOG_LINES`, the 4 KB reserve may under‑estimate and cause heap fragmentation again.
|
||||
- **Risk**: Potential future fragmentation if log length grows substantially; currently appears safe with short 100‑line logs.
|
||||
|
||||
- **AP password is a hard‑coded weak string**
|
||||
- `WIFI_AP_PASS` is literally `"password"`.
|
||||
- **Risk**: Anyone in RF range can connect to the AP and control the jammer UI. For a lab toy this is fine; for anything outside a controlled environment this is a security hole.
|
||||
|
||||
---
|
||||
|
||||
### 6. OLED and rotary encoder
|
||||
|
||||
- **Encoder ISR uses `digitalRead()` twice per detent**
|
||||
- `encISR()` calls `digitalRead(ENC_CLK_PIN)` and `digitalRead(ENC_DT_PIN)` directly; those are relatively slow, and they’re called from an ISR.
|
||||
- **Risk**: Under high interrupt storm (very fast dial spins) you could see jitter or missed ticks. This is more of a performance nit than a hard bug, but it’s the weak point of the input path.
|
||||
|
||||
- **Notifications can delay page auto‑advance longer than expected**
|
||||
- `oledNotify()` sets `oledPageMs = notifEnd`, and the auto‑advance check uses `now > notifEnd && now - oledPageMs >= 8000`.
|
||||
- After a long notification (e.g. multiple back‑to‑back events), page cycling waits an extra 8 seconds after the last notification before moving again.
|
||||
- **Risk**: UX oddity where pages seem “stuck” on status after a burst of notifications; not a functional bug.
|
||||
|
||||
---
|
||||
|
||||
### 7. Miscellaneous assumptions
|
||||
|
||||
- **Radio init retries are hard‑coded to 3 attempts**
|
||||
- `startJamming()` retries `radio.begin(...)` up to 3 times with 50 ms between attempts.
|
||||
- **Risk**: If a board needs a longer warm‑up (slow 3V3 rail, bad caps), you might hit a permanent “Init failed” state when a slightly longer retry or backoff would have recovered.
|
||||
|
||||
- **Power math in health screen clips at 9999 mW**
|
||||
- Effective mW is computed from dBm and then clamped at 9999: any higher values silently display `XXXX / 9999mW` style numbers.
|
||||
- **Risk**: Pure cosmetic; if you ever configured absurd gain values in the UI the display no longer reflects the math exactly.
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#define JAM_RX_BW_KHZ 812.0f // wide RX BW for begin()
|
||||
|
||||
// Fixed dual-carrier jamming — NO sweep: each radio holds one frequency at full TX power.
|
||||
// CC1101: see TI doc SWRS061 (single-chip low-cost UHF transceiver). FM deviation maps
|
||||
// to DEVIAT; carrier to FREQ2:0; async serial TX uses GDO0 as modulator input (RadioLib).
|
||||
// R2 (433.92) uses max deviation = loudest/widest noise; R1 (315) uses narrow deviation.
|
||||
#define JAM_LOCK_FREQ_1_MHZ 315.0f
|
||||
#define JAM_LOCK_FREQ_2_MHZ 433.92f
|
||||
|
||||
Reference in New Issue
Block a user