SimTX API/Packets/IqBlock
Appearance
| Frame | ServerFrame, field 12
|
|---|---|
| Member | iq
|
| Direction | Server → client |
| Session | Receiver |
| Roles | ROLE_RECEIVER.
|
| Permission | None |
| Defined in | session.proto
|
IqBlock carries one block of received complex baseband samples. A receiver gets a continuous stream of them after the IqStreamDescriptor, at the rate of the simulation. With timestamped set in the ReceiverStart, every block also carries the UTC instant of its first sample; v24's separate TimedIqBlock is gone.
Definition
message IqBlock {
float scale = 1;
bytes samples = 2;
int64 first_sample_epoch_seconds = 3; // timestamped streams only
int32 first_sample_nanos = 4;
fixed64 sequence = 5;
}
Fields
| # | Field | Type | Description |
|---|---|---|---|
| 1 | scale |
float |
Scale of this block: the peak component magnitude, at least 10−9. |
| 2 | samples |
bytes |
chunk_samples × (I, Q), interleaved, big-endian int16 (or int8). Length is exactly chunk_samples × 2 × 2 (or × 1) bytes.
|
| 3 | first_sample_epoch_seconds |
int64 |
Timestamped streams only: UTC instant of the first sample on the server's RF timeline, Unix seconds. |
| 4 | first_sample_nanos |
int32 |
Nanoseconds added to first_sample_epoch_seconds.
|
| 5 | sequence |
fixed64 |
Block number within the stream: 1 for the first block, +1 for each block after it. A step larger than 1 means blocks were dropped. 0 = the sender does not number blocks. |
Decoding
I = i_raw × scale / 32767 (INT16; use 127 for INT8)
Q = q_raw × scale / 32767
- The sample bytes are big-endian, unlike the rest of the frame, which follows protobuf encoding.
- Check that
samplesis exactlychunk_samples × 2 × bytesPerComponentbytes long and treat anything else as a protocol error. scaleis the block's peak component magnitude. The server quantises each component asround(x × 32767 / scale), so the integers always use the full range.- A magnitude of 1.0 is −12 dBm at the receiver input. Components are clipped at ±1.0 before quantisation, so strong signals overload the receiver as they would a real one.
Delivery
- Blocks are sent in real time. The server queues at most 8 blocks per connection and drops the oldest when the queue is full.
sequencecounts blocks from 1 and continues across retunes and moves between server nodes. A step larger than 1 means blocks were dropped. A sender that does not number blocks sends 0.sequenceis afixed64, so it occupies 9 bytes of the frame (tag and 8 bytes) even when small.- A client that does not read for 5 seconds is disconnected.
Examples
Complete frames, including the varint length prefix, from the protocol's golden test vectors (protocol/simtx/v25/testdata/frames.json).
iq_block_int16 (server to client, 27 bytes):
1A frame length 26
62 18 iq (IqBlock), 24 bytes
0D 00 00 00 3F scale = 0.5
12 08 7F FF 80 01 40 00 C0 00 samples, 8 bytes
29 01 00 00 00 00 00 00 00 sequence = 1
iq_block_int16_timestamped (server to client, 38 bytes):
25 frame length 37
62 23 iq (IqBlock), 35 bytes
0D 00 00 00 3F scale = 0.5
12 08 7F FF 80 01 40 00 C0 00 samples, 8 bytes
18 C0 84 FC D6 06 first_sample_epoch_seconds = 1793000000
20 95 9A EF 3A first_sample_nanos = 123456789
29 02 00 00 00 00 00 00 00 sequence = 2