sendiq: raw I/Q samples
Transmits I/Q samples from a file. Anything you can produce as I/Q, from GNU Radio, csdr or your own code, goes on the air this way. With a shared memory token, another program can change the frequency and power while it runs. Code: sendiq.go.
Fields
The frequency field is freq here, not frequency, and it is in Hz.
| JSON | Go field | Type | Required | Rules |
|---|---|---|---|---|
inputFile | InputFile | string | yes | Path to an existing file, or - (see below) |
freq | Freq | float64 | yes | Hz, 5000 to 1500000000 |
sampleRate | SampleRate | *int | no | 10000 to 2000000; the program defaults to 48000 |
harmonic | Harmonic | *int | no | 1 or more; the program defaults to 1 |
iqType | IQType | *string | no | i16, u8, float or double (gorpitx.IQType* constants); the program defaults to i16 |
power | Power | *float64 | no | Drive level 0 to 7, clamped into that range rather than refused; the program defaults to 0.1 |
sharedMemToken | SharedMemToken | *int | no | Non-zero shared memory key for run-time control |
loopMode | LoopMode | bool | no | true adds -l and restarts the file at its end |
The package exports the program’s defaults as DefaultSampleRate, DefaultHarmonic, DefaultIQType and DefaultPower. gorpitx does not send them; it leaves a flag out when you leave its field out.
sampleRate above 200000 is reduced by sendiq itself: it divides by the smallest factor from 2 to 11 that brings the rate under 200000 and decimates the samples by that factor.
power is printed with two decimals, so 9 becomes -p 7.00.
inputFile: "-" passes -i -, which makes sendiq read its own stdin. This module gives the process no stdin data, so in practice - reads nothing. Write the samples to a file or a named pipe and pass that path instead.
Example
{
"inputFile": "/home/pi/signal.iq",
"freq": 434000000,
"sampleRate": 96000,
"power": 2.5,
"sharedMemToken": 12345,
"loopMode": true
}
Runs:
stdbuf -oL "$GORPITX_PATH/sendiq" -i /home/pi/signal.iq -f 434000000 \
-s 96000 -p 2.50 -m 12345 -l
With loopMode, the program never exits by itself. Give Exec a timeout or call Stop.
Run-time control over shared memory
With sharedMemToken set, sendiq creates a System V shared memory segment with that key and checks it while it transmits. It also forces the I/Q type to float, whatever iqType says.
The segment holds this C struct from rpitx’s sendiq.cpp:
struct shared_memory_struct {
bool updated;
int command;
float data;
char common_data[1024];
};
Write a command and set updated to true. The commands:
| Command | Effect | data |
|---|---|---|
1111 | Switch to I/Q mode | unused |
2222 | Switch to frequency and amplitude mode | unused |
3333 | Set the drive level | level, 0 to 7 |
4444 | Change the frequency | frequency in Hz |
From Python with the sysv_ipc package, for example:
import struct
import sysv_ipc
shm = sysv_ipc.SharedMemory(12345)
# updated=True, command=4444, data=144.5 MHz
shm.write(struct.pack("?if", True, 4444, 144500000.0))
?if uses native alignment, which matches the C struct on the Pi. A 32-bit float holds about seven significant digits, so a frequency sent this way lands on the nearest value a float can hold, within a few tens of Hz at 144 MHz.