216 lines
6.8 KiB
Markdown
216 lines
6.8 KiB
Markdown
TASK_ID = RF001A_OTA_TX_001
|
|
TASK_TITLE = Transmit first RF-001A QPSK packet burst
|
|
SOURCE_BRANCH = video-development
|
|
EXPECTED_HEAD = 1e3aa25d7007c7c8e84608cddb02f06f77e63396
|
|
REQUIRES_APPROVAL = YES
|
|
HARDWARE_ACCESS = YES
|
|
RF_RX = NO
|
|
RF_TX = YES
|
|
ALLOW_COMMIT = NO
|
|
ALLOW_PUSH = NO
|
|
RISK_LEVEL = RED
|
|
|
|
This file is the authoritative current task for the MAIN PC TX node.
|
|
Read TX_NODE_STATE.md first. If chat history, this file, the shared RF-001A spec and current Git HEAD conflict, stop and report the conflict.
|
|
|
|
# Current TX task
|
|
|
|
TASK =
|
|
TRANSMIT FIRST RF-001A QPSK PACKET BURST
|
|
|
|
This is a new RED task. It does not inherit the RX task approval. Publication of this file is not permission to transmit.
|
|
|
|
Before any RF TX, the user must:
|
|
|
|
1. separately provide the exact authorization `AUTHORIZE RF TX`;
|
|
2. confirm the live RX status `RX READY FOR TX = YES` for task `RF001A_OTA_CAPTURE_001`.
|
|
|
|
A normal approval, an earlier RF authorization, or an RX approval is insufficient.
|
|
|
|
## 1. Fixed RF-001A parameters
|
|
|
|
```text
|
|
center frequency = 1400000000 Hz
|
|
sample rate = 8000000 samples/s
|
|
modulation = QPSK
|
|
symbol rate = 500000 symbols/s
|
|
inner FEC = 2/3
|
|
payload = 256 bytes
|
|
packet count = 100
|
|
inter-packet gap = 5 ms
|
|
digital carrier offset = +125000 Hz
|
|
TX VGA = 20 dB
|
|
RF amp = OFF
|
|
antenna bias = OFF
|
|
common 10 MHz reference = VERIFIED
|
|
distance = approximately 2 m
|
|
LOS = YES
|
|
video = OFF
|
|
```
|
|
|
|
The waveform is one finite burst. Never add `-R`.
|
|
|
|
## 2. Preconditions
|
|
|
|
Before asking for RED authorization, prepare all read-only evidence:
|
|
|
|
1. Run `git pull --ff-only origin video-development`.
|
|
2. Require branch `video-development`.
|
|
3. Require `git status --short --untracked-files=no` to produce no output.
|
|
4. Require local HEAD to equal `origin/video-development` and `EXPECTED_HEAD` to be its ancestor.
|
|
5. Run `hackrf_info` and preserve complete stdout.
|
|
6. Require TX serial `000000000000000097c063dc323b97d3`.
|
|
7. Require the recorded MASTER CLKOUT command result = `PASS`.
|
|
8. Require the user to confirm both TX and RX antennas connected, approximately 2 m LOS and the intended antenna geometry.
|
|
9. Require the current RX report to show `RX READY FOR TX = YES`, task ID `RF001A_OTA_CAPTURE_001`, a live capture PID, capture path, start time and expected end time.
|
|
10. Require current time to be before the RX expected end time.
|
|
|
|
Verify the prepared waveform without accessing radio hardware:
|
|
|
|
```powershell
|
|
python -B -X utf8 tools/rf001a_prepare.py --verify-dir data/raw/rf001/rf001a_common_clock_001
|
|
```
|
|
|
|
Then verify the actual hardware-format bytes through the existing receiver. The report path must be new and outside Git:
|
|
|
|
```powershell
|
|
python -B -X utf8 tools/qpsk_rf_rx.py `
|
|
--iq-file data/raw/rf001/rf001a_common_clock_001/tx_waveform.cs8 `
|
|
--iq-format cs8 `
|
|
--truth-metadata data/raw/rf001/rf001a_common_clock_001/tx_metadata.json `
|
|
--report '<new unique path outside Git>\rf001a_tx_offline_verify.json'
|
|
```
|
|
|
|
Require the receiver report to contain `crc_valid_packets = 100`, `exact_packets = 100`, no missing packets and no duplicates.
|
|
|
|
Require:
|
|
|
|
```text
|
|
canonical waveform = PASS
|
|
hardware-format cs8 = PASS
|
|
offline hardware-format roundtrip = 100/100 exact
|
|
TX waveform path = data/raw/rf001/rf001a_common_clock_001/tx_waveform.cs8
|
|
TX waveform size = 17667656 bytes
|
|
TX waveform SHA256 = 75f3fa39bfa88b623b7e4e5a02e3a80b52185007397ea56ceaacc13353974b2
|
|
sample count = 8833828 complex samples
|
|
expected duration = 1.1042285 s
|
|
```
|
|
|
|
If any value differs, if RX is not ready, or if the RX capture window has ended, do not transmit and STOP.
|
|
|
|
Only after every precondition passes may the user provide the separate exact phrase `AUTHORIZE RF TX`.
|
|
|
|
## 3. One authorized TX execution
|
|
|
|
After the separate RED authorization and the live `RX READY FOR TX = YES` confirmation, create a new unique local evidence directory outside Git. Refuse an existing directory and never overwrite earlier evidence.
|
|
|
|
Use this single finite command:
|
|
|
|
```text
|
|
hackrf_transfer.exe
|
|
-d 000000000000000097c063dc323b97d3
|
|
-t data/raw/rf001/rf001a_common_clock_001/tx_waveform.cs8
|
|
-f 1400000000
|
|
-s 8000000
|
|
-n 8833828
|
|
-x 20
|
|
-a 0
|
|
-p 0
|
|
-B
|
|
```
|
|
|
|
Run it once, synchronously, and preserve the exact process exit code:
|
|
|
|
```powershell
|
|
$txRunId = '{0}_{1}' -f (Get-Date -Format 'yyyyMMdd_HHmmss'), ([guid]::NewGuid().ToString('N').Substring(0, 8))
|
|
$txEvidenceRoot = Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'SDR_Rover_TX_Evidence'
|
|
$txEvidenceDirectory = Join-Path $txEvidenceRoot "RF001A_OTA_TX_001_$txRunId"
|
|
if (Test-Path -LiteralPath $txEvidenceDirectory) { throw "TX evidence directory already exists: $txEvidenceDirectory" }
|
|
New-Item -ItemType Directory -Path $txEvidenceDirectory -ErrorAction Stop | Out-Null
|
|
|
|
$hackrfTransfer = 'C:\Users\user\Tools\HackRF\Library\bin\hackrf_transfer.exe'
|
|
$waveformPath = (Resolve-Path -LiteralPath 'data/raw/rf001/rf001a_common_clock_001/tx_waveform.cs8').Path
|
|
$stdoutPath = Join-Path $txEvidenceDirectory 'hackrf_transfer.stdout.log'
|
|
$stderrPath = Join-Path $txEvidenceDirectory 'hackrf_transfer.stderr.log'
|
|
$txArguments = @(
|
|
'-d', '000000000000000097c063dc323b97d3',
|
|
'-t', $waveformPath,
|
|
'-f', '1400000000',
|
|
'-s', '8000000',
|
|
'-n', '8833828',
|
|
'-x', '20',
|
|
'-a', '0',
|
|
'-p', '0',
|
|
'-B'
|
|
)
|
|
|
|
$txStartedAt = [DateTimeOffset]::Now
|
|
$txProcess = Start-Process -FilePath $hackrfTransfer -ArgumentList $txArguments `
|
|
-RedirectStandardOutput $stdoutPath -RedirectStandardError $stderrPath `
|
|
-PassThru -Wait -WindowStyle Hidden
|
|
$txFinishedAt = [DateTimeOffset]::Now
|
|
$txProcess.Refresh()
|
|
$txExitCode = $txProcess.ExitCode
|
|
```
|
|
|
|
Immediately write the exit code, process ID, timestamps, duration, command parameters, waveform size and waveform SHA256 to a new JSON metadata file in `$txEvidenceDirectory`. Preserve complete stdout and stderr.
|
|
|
|
Inspect every buffer-statistics line. Record:
|
|
|
|
```text
|
|
TX start time =
|
|
TX end time =
|
|
TX PID =
|
|
TX exit code =
|
|
TX underruns =
|
|
USB errors =
|
|
RF TX STOPPED =
|
|
YES / NO
|
|
```
|
|
|
|
Do not infer zero from a missing counter. Use `NOT_REPORTED` when no counter exists. Any nonzero intermediate or final underrun/error line remains evidence even if a later line reports zero.
|
|
|
|
Set `RF TX STOPPED = YES` only after the finite process exits. Do not start a second burst for any reason. Do not retry automatically.
|
|
|
|
## 4. Final TX report
|
|
|
|
```text
|
|
TASK_ID =
|
|
RF001A_OTA_TX_001
|
|
|
|
RED AUTHORIZATION =
|
|
AUTHORIZE RF TX / MISSING
|
|
|
|
RX READY FOR TX =
|
|
YES / NO
|
|
|
|
TX SERIAL =
|
|
|
|
TX WAVEFORM SHA256 =
|
|
|
|
TX START TIME =
|
|
|
|
TX END TIME =
|
|
|
|
TX EXIT CODE =
|
|
|
|
TX UNDERRUNS =
|
|
|
|
USB ERRORS =
|
|
|
|
RF TX STOPPED =
|
|
YES / NO
|
|
|
|
BURSTS TRANSMITTED =
|
|
0 / 1
|
|
|
|
RF TX =
|
|
0
|
|
```
|
|
|
|
At report time, `RF TX = 0` means no transmission process remains active.
|
|
|
|
## 5. Prohibited actions
|
|
|
|
Do not transmit before the separate exact RED authorization. Do not inherit approval from the RX task. Do not use repeat mode, start a second burst, change frequency, gains, clock configuration, waveform, firmware, CPLD, Zadig or USB drivers. Do not commit or push from this task.
|