Triggered RX example

Discussions related to embedded firmware, driver, and user mode application software development
Post Reply
eliu@dgs
Posts: 2
Joined: Thu Feb 19, 2026 7:55 am

Triggered RX example

Post by eliu@dgs »

I could not find examples of triggered RX. I have BladeRF xA9 with 1PPS from LBE-1421 GPSDO connected to pin 1 of J51. The RX timeout without the trigger. I expect 10 captures should finish in 10 seconds with 1PPS as trigger but all 10 captures finished within 1s even I disarmed the trigger after each capture. The code is below, thanks in advance for helps.

typedef struct {
bool rx;
bool mimo;
size_t num_samples;
uint64_t sample_rate;
uint64_t frequency;
uint32_t bandwidth;
int16_t *rx_samples;
bladerf_format format;
struct bladerf_metadata rx_meta;
size_t num_buffers;
size_t buffer_size;
size_t num_transfers;
size_t timeout_ms;
} test_config;

int main(int argc, char *argv[])
{
int status = 0;
struct bladerf *dev = NULL;
const char *fpga_file = "hostedxA9-latest.rbf";
// const char *fpga_file = NULL;

test_config config;
config.rx = true;
config.mimo = false;
config.num_samples = 1048576;
config.sample_rate = 61.44e6;
config.frequency = 2424000000;
config.bandwidth = 50000000;
config.rx_samples = (short *) malloc(4 * config.num_samples * sizeof(int16_t));
if (config.rx_samples == NULL) {
fprintf(stderr, "Failed to allocate memory for samples\n");
exit(EXIT_FAILURE);
};
config.format = BLADERF_FORMAT_SC16_Q11;
config.rx_meta.flags = BLADERF_META_FLAG_RX_NOW;
config.num_buffers = 512;
config.buffer_size = 4096;
config.num_transfers = 64;
config.timeout_ms = 10000; // 10s time out

// bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_INFO);

bladerf_open(&dev, NULL);

// if (fpga_file != NULL) {
if (!bladerf_is_fpga_configured(dev)) {
printf("Loading the FPGA image...\n");
bladerf_load_fpga(dev, fpga_file);
}

printf("Setting sample rate to %0.3f MHz...\n", config.sample_rate / 1e6);
bladerf_set_sample_rate(dev, BLADERF_CHANNEL_RX(0), config.sample_rate, NULL);


printf("Setting frequency to %.6f MHz...\n", config.frequency/1000000.0);
bladerf_set_frequency(dev, BLADERF_CHANNEL_RX(0), config.frequency);

bladerf_set_gain_mode(dev, BLADERF_CHANNEL_RX(0), BLADERF_GAIN_FASTATTACK_AGC);

uint32_t actual;
bladerf_set_bandwidth(dev, BLADERF_CHANNEL_RX(0), config.bandwidth, &actual);
printf("Setting bandwidth to %.6f MHz, actual bandwidth %.6f MHz\n", config.bandwidth/1000000.0, actual/1000000.0);

bladerf_trigger trigger_slave;
bladerf_trigger_signal trig = BLADERF_TRIGGER_J51_1;
bladerf_trigger_init(dev, BLADERF_RX_X1, trig, &trigger_slave);

printf("Streaming RX...\n");
bladerf_sync_config(
dev, BLADERF_RX_X1,
config.format, config.num_buffers, config.buffer_size,
config.num_transfers, config.timeout_ms);


bladerf_enable_module(dev, BLADERF_CHANNEL_RX(0), true);
bladerf_set_pll_enable(dev, true);
bladerf_set_pll_refclk(dev, 40000000);

/* Retrieve the current timestamp */
config.rx_meta.flags = 0;
for (int i = 0; i < 10; i++) {
trigger_slave.role = BLADERF_TRIGGER_ROLE_SLAVE;
bladerf_trigger_arm(dev, &trigger_slave, true, 0, 0);

status = bladerf_get_timestamp(dev, BLADERF_RX, &config.rx_meta.timestamp);
if (status != 0) {
fprintf(stderr, "Failed to get current RX timestamp: %s\n",
bladerf_strerror(status));
} else {
// printf("Current RX timestamp: 0x%016" PRIx64 "\n", config.rx_meta.timestamp);
}

// config.rx_meta.timestamp += config.sample_rate / 100;
config.rx_meta.timestamp += config.sample_rate * 100;

// printf("Scheduling RX for 0x%016" PRIx64 "\n", config.rx_meta.timestamp);
status = bladerf_sync_rx(dev, config.rx_samples, config.num_samples,
&config.rx_meta, config.timeout_ms);
if (status != 0) {
fprintf(stderr, "RX failed: %s\n", bladerf_strerror(status));
} else if (config.rx_meta.status & BLADERF_META_STATUS_OVERRUN) {
fprintf(stderr, "Overrun detected. %u valid samples were read.\n",
config.rx_meta.actual_count);
// print_bladerf_flag_statuses(config.rx_meta.status);
} else {
// printf("RX'd %u samples at t=0x%016" PRIx64 "\n", config.rx_meta.actual_count,
printf("RX'd %u samples, ", config.rx_meta.actual_count);
save_iq_file(0, config.rx_samples, config.num_samples, i + 1);
}
int32_t gain;
float temp;
int32_t pre_rssi, sym_rssi;
bool locked;
bladerf_get_gain(dev, BLADERF_CHANNEL_RX(0), &gain);
bladerf_get_rfic_temperature(dev, &temp);
bladerf_get_rfic_rssi(dev, BLADERF_CHANNEL_RX(0), &pre_rssi, &sym_rssi);
bladerf_get_pll_lock_state(dev, &locked);
printf("Gain %d, temp %.3f, RSSI %d %d, locked %d\n", gain, temp, pre_rssi, sym_rssi, locked);
trigger_slave.role = BLADERF_TRIGGER_ROLE_DISABLED;
bladerf_trigger_arm(dev, &trigger_slave, false, 0, 0);


}
bladerf_enable_module(dev, BLADERF_CHANNEL_RX(0), false);


if (config.rx_samples)
free(config.rx_samples);
if (dev)
bladerf_close(dev);

return status;
}
eliu@dgs
Posts: 2
Joined: Thu Feb 19, 2026 7:55 am

Re: Triggered RX example

Post by eliu@dgs »

The "test_streaming" example in the SDK doesn't seem to work:
The timestamp always read as 0 and "bladerf_sync_rx" returns without waiting for the scheduled time:
streaming RX...
Current RX timestamp: 0x0000000000000000
Scheduling RX for 0x00000000005dc000
RX'd 1048576 samples at t=0x00000000005dc000

When I changed timeout to 10s and scheduled time to 2s later, the "bladerf_sync_rx" returns without delay:
streaming RX...
Current RX timestamp: 0x0000000000000000
Scheduling RX for 0x0000000007530000
RX'd 1048576 samples at t=0x0000000007530000
jumoo
Posts: 1
Joined: Tue Jul 21, 2026 4:20 am

Re: Triggered RX example

Post by jumoo »

If the RX timestamp never advances from zero, I'd verify that the RX stream is actually running before relying on scheduled or triggered captures. Until the timestamp starts incrementing, the trigger logic won't behave as expected no matter how far ahead you schedule the capture.文字数 カウント
Post Reply