205 lines
7.8 KiB
Markdown
205 lines
7.8 KiB
Markdown
TASK_ID = RF001A_OTA_CAPTURE_004
|
|
TASK_TITLE = Start hardened RF-001A common-clock OTA capture
|
|
SOURCE_BRANCH = video-development
|
|
EXPECTED_HEAD = 168e03d9e778ab2ec63502552d385ec7be3ef677
|
|
REQUIRES_APPROVAL = YES
|
|
HARDWARE_ACCESS = YES
|
|
RF_RX = YES
|
|
RF_TX = NO
|
|
ALLOW_COMMIT = NO
|
|
ALLOW_PUSH = RX_RESULT_ONLY
|
|
RISK_LEVEL = YELLOW
|
|
|
|
---
|
|
|
|
# RF-001A RX capture 004
|
|
|
|
This file is the authoritative current task for the RX laptop. Read
|
|
`RX_NODE_STATE.md` first. If chat history conflicts with these files or the
|
|
current Git HEAD, stop and report the conflict.
|
|
|
|
This task is prepared only. A previous approval does not apply to this new
|
|
TASK_ID. Do not access HackRF until the user approves this exact YELLOW task.
|
|
|
|
## 1. Software and Git gates
|
|
|
|
1. Run `git pull --ff-only origin video-development`.
|
|
2. Require branch `video-development` and a clean tracked worktree.
|
|
3. Require local HEAD to equal `origin/video-development`; `EXPECTED_HEAD`
|
|
must be its ancestor.
|
|
4. Confirm the historical channel-test READY and COMPLETE acknowledgements
|
|
from `origin/tx-node` through the RX watcher.
|
|
5. Before opening HackRF, run the authenticated no-change publication check:
|
|
|
|
python -B tools/rx_agent_watcher.py --check-result-write --result-branch rx-node
|
|
|
|
Require `RX-NODE WRITE PREFLIGHT = PASS`. This command fetches the branch,
|
|
performs `git push --dry-run` of its existing HEAD to the same ref, and
|
|
confirms that the remote HEAD did not change. It creates no commit and no
|
|
production READY event.
|
|
6. Run the targeted tests, Ruff, Pyright and `git diff --check` according to
|
|
the tracked project instructions.
|
|
7. Validate `configs/rf/rf001a_truth_metadata.json`: waveform SHA256, seed,
|
|
PHY settings, 100 sequence numbers and 100 packet hashes must agree with
|
|
`configs/rf/rf001a_common_clock.json`.
|
|
|
|
If any gate fails, do not open HackRF and stop. In particular, a failed Git
|
|
write preflight blocks the hardware task.
|
|
|
|
## 2. Optional offline check of capture 003
|
|
|
|
If the existing `RF001A_OTA_CAPTURE_003` file is present locally, analyze it
|
|
read-only with the streaming cs8 decoder before starting new hardware work:
|
|
|
|
python -B -X utf8 tools/qpsk_rf_rx.py --iq-file <capture-003-path>\rf001a_ota_capture.cs8 --iq-format cs8 --truth-metadata configs/rf/rf001a_truth_metadata.json --report <new-path-outside-git>\capture003_streaming_report.json
|
|
|
|
No RF-001A transmission occurred during capture 003. The expected exact
|
|
packet count is 0. CRC-valid background candidates must not be reported as
|
|
exact unless their complete packet SHA256 matches the tracked truth metadata.
|
|
The analysis must use memmap/chunks and must not materialize the full 1.92 GB
|
|
capture as complex64.
|
|
|
|
If capture 003 is unavailable, report `CAPTURE_003 ANALYSIS = NOT_RUN` and
|
|
continue only after all mandatory gates pass.
|
|
|
|
## 3. Hardware preflight after YELLOW approval
|
|
|
|
1. Run `hackrf_info` and require RX serial
|
|
`000000000000000097c063dc2e5327d3`.
|
|
2. With `MASTER CLKOUT -> SLAVE CLKIN` connected, run:
|
|
|
|
hackrf_clock.exe -d 000000000000000097c063dc2e5327d3 -i
|
|
|
|
3. Require `CLKIN status: clock signal detected`.
|
|
4. Repeat the Git write preflight immediately before the finite RX command.
|
|
5. Require antennas connected, approximately 2 m distance, clear LOS, and
|
|
video disabled.
|
|
6. Require at least 1500000000 free bytes on the capture volume and record the
|
|
measured value.
|
|
|
|
Do not reconfigure clocks. If CLKIN or the second Git preflight fails, stop
|
|
before capture.
|
|
|
|
## 4. Finite RX capture
|
|
|
|
Use a unique directory outside Git. Never overwrite an earlier capture.
|
|
|
|
RX serial = 000000000000000097c063dc2e5327d3
|
|
center frequency = 1400000000 Hz
|
|
sample rate = 8000000 samples/s
|
|
RX LNA = 24 dB
|
|
RX VGA = 24 dB
|
|
RF amp = OFF
|
|
antenna bias = OFF
|
|
duration = 60 s
|
|
sample count = 480000000 complex samples
|
|
hardware format = cs8
|
|
expected file size = 960000000 bytes
|
|
|
|
Use these fixed `hackrf_transfer.exe` arguments:
|
|
|
|
-d 000000000000000097c063dc2e5327d3
|
|
-r <unique_capture_path>\rf001a_ota_capture.cs8
|
|
-f 1400000000
|
|
-s 8000000
|
|
-n 480000000
|
|
-l 24
|
|
-g 24
|
|
-a 0
|
|
-p 0
|
|
-B
|
|
|
|
Use `tools/capture_process_runner.ps1` as a controlled background process.
|
|
Preserve its complete stdout, stderr, start JSON and result JSON outside Git.
|
|
The runner must start exactly one finite child, record the actual child PID and
|
|
UTC start time, set the expected end to start plus 60 seconds, wait for that
|
|
exact process, record its integer exit code, size and duration, and calculate
|
|
SHA256 after the output file closes. Never retry the capture automatically.
|
|
|
|
Within five seconds require the runner and child to be alive and the file to
|
|
exist and grow. Otherwise publish no READY and stop.
|
|
|
|
## 5. READY publication
|
|
|
|
Create the strict schema-version-1 READY JSON outside Git for TASK_ID
|
|
`RF001A_OTA_CAPTURE_004`. Use the actual child PID and UTC timestamps,
|
|
`expected_capture_end = capture_started_at + 60 s`, current source HEAD,
|
|
`common_clock_verified = true`, `rf_tx = 0`, and null final result fields.
|
|
|
|
Publish it once with:
|
|
|
|
python -B tools/rx_agent_watcher.py --publish-result <ready-json> --result-branch rx-node
|
|
|
|
The publisher creates one immutable READY commit. On a recognized transient
|
|
network or authentication failure it checks the remote branch and may retry
|
|
the exact same commit once. It never creates a second READY commit or changes
|
|
the payload between attempts. If the remote already contains that commit, the
|
|
publication is successful. A second failure means:
|
|
|
|
READY publication = FAIL
|
|
RX READY FOR TX = NO
|
|
RF TX = 0
|
|
|
|
Do not publish READY after the capture window has ended. After the process
|
|
exits, publish only a `CAPTURE_COMPLETE` result with the actual exit code,
|
|
size, duration and error counters, including nonzero failure values.
|
|
|
|
After the remote HEAD confirms the READY commit, immediately print:
|
|
|
|
TASK_ID = RF001A_OTA_CAPTURE_004
|
|
RX CAPTURE STARTED = YES
|
|
RX READY FOR TX = YES
|
|
CAPTURE PID =
|
|
CAPTURE PATH =
|
|
CAPTURE START TIME =
|
|
EXPECTED CAPTURE END =
|
|
RX RESULT HEAD =
|
|
RF TX = 0
|
|
|
|
Return control without waiting for capture completion.
|
|
|
|
## 6. Completion and offline decode
|
|
|
|
After the child exits, record exact exit code, actual size, duration, overruns,
|
|
USB errors, file-write errors and SHA256. A complete capture is exactly
|
|
960000000 bytes; a smaller file is incomplete. Run the CLKIN check again and
|
|
require detected status.
|
|
|
|
Publish an honest schema-version-1 COMPLETE result with final values. Keep IQ,
|
|
stdout, stderr and large logs outside Git.
|
|
|
|
After `origin/tx-node` contains `TX_STARTED` and `TX_COMPLETE` for
|
|
`RF001A_OTA_TX_004`, run the streaming decoder with RX/TX timestamps:
|
|
|
|
python -B -X utf8 tools/qpsk_rf_rx.py --iq-file <capture-path>\rf001a_ota_capture.cs8 --iq-format cs8 --truth-metadata configs/rf/rf001a_truth_metadata.json --capture-started-at <CAPTURE_STARTED_AT> --tx-started-at <TX_STARTED_AT> --tx-finished-at <TX_FINISHED_AT> --report <new-path-outside-git>\rf001a_streaming_report.json
|
|
|
|
The decoder uses a two-second margin before and after the timestamped burst.
|
|
Without complete timestamps it uses the streaming power locator. Chunk overlap
|
|
is derived from the real 256-byte RF-001 waveform and duplicate detections from
|
|
overlap are suppressed.
|
|
|
|
## 7. Prohibited actions
|
|
|
|
RF TX, firmware update, CPLD update, Zadig, USB driver changes, clock
|
|
reconfiguration, commit or push to `video-development`, repeated capture, raw
|
|
IQ/video/waveform publication and large-log publication are forbidden.
|
|
|
|
Final report:
|
|
|
|
TASK_ID = RF001A_OTA_CAPTURE_004
|
|
RX-NODE WRITE PREFLIGHT = PASS / FAIL
|
|
COMMON CLOCK = VERIFIED / NOT_VERIFIED
|
|
RX CAPTURE COMPLETE = YES / NO
|
|
CAPTURE SIZE =
|
|
CAPTURE DURATION =
|
|
RX OVERRUNS =
|
|
USB ERRORS =
|
|
FILE WRITE ERRORS =
|
|
RAW IQ SHA256 =
|
|
STREAMING DECODE = PASS / FAIL / NOT_RUN
|
|
EXACT RF001A PACKETS =
|
|
PEAK ANALYSIS MEMORY =
|
|
RF TX = 0
|
|
|
|
STOP.
|