Page 1 of 1

Problem with triggered TX

Posted: Thu Oct 08, 2026 6:04 am
by nils
Hi,
I am trying to send a signal synchronously and periodically with trigger input. For each trigger, I want to emit a fixed number of samples. So, if the trigger occurs every 10 milliseconds and I have samples for a 5-millisecond transmission, there will be a 5-millisecond gap between transmissions.
I have tried to achieve this using the gating mechanism, but I am unable to have a transmission where the tx burst does not drift and is always a constant distance relative to the trigger input.
I might have missed some functionality / misconfigured the radio, therefore any pointers would be greatly appreciated. Thanks
For reference this is the code i have used to try to get the specified behaviour:

Code: Select all

  status = bladerf_open(&dev, nullptr);
  if (status != 0) {
    fprintf(stderr, "Unable to open bladeRF: %s\n", bladerf_strerror(status));
    return 1;
  }

  status = bladerf_set_frequency(dev, BLADERF_CHANNEL_TX(0), frequency);
  if (status == 0) {
    status = bladerf_set_sample_rate(dev, BLADERF_CHANNEL_TX(0), (bladerf_sample_rate)requested_rate, &actual_rate);
  }
  if (status == 0) {
    status = bladerf_set_bandwidth(dev, BLADERF_CHANNEL_TX(0), actual_rate, &actual_bandwidth);
  }
  if (status == 0) {
    status = bladerf_set_gain(dev, BLADERF_CHANNEL_TX(0), (bladerf_gain)tx_gain_db);
  }
  if (status != 0) {
    fprintf(stderr, "Device configuration failed: %s\n", bladerf_strerror(status));
    goto cleanup;
  }

  if (actual_rate % 100 != 0) {
    fprintf(stderr, "Actual sample rate must produce an integral 10 ms frame.\n");
    status = BLADERF_ERR_INVAL;
    goto cleanup;
  }

  frame_samples = (size_t)(actual_rate / 100);
  trigger_samples = (size_t)llround((double)actual_rate * (double)trigger_high_us / 1000000.0);
  if (trigger_samples == 0 || trigger_samples >= frame_samples) {
    fprintf(stderr, "Trigger pulse width is outside the usable frame.\n");
    status = BLADERF_ERR_INVAL;
    goto cleanup;
  }

  playback_samples = frame_samples - trigger_samples;
  start_sample = (size_t)llround((double)actual_rate * start_ms / 1000.0);
  duration_samples = (size_t)llround((double)actual_rate * duration_ms / 1000.0);
  requested_end = start_sample + duration_samples;
  if (duration_samples == 0 || requested_end > frame_samples) {
    fprintf(stderr,
            "Requested interval must contain samples and end within "
            "the 10 ms frame.\n");
    status = BLADERF_ERR_INVAL;
    goto cleanup;
  }
  if (start_sample < trigger_samples) {
    start_sample = trigger_samples;
    if (start_sample >= requested_end) {
      fprintf(stderr,
              "Requested interval is entirely inside the "
              "trigger-high portion.\n");
      status = BLADERF_ERR_INVAL;
      goto cleanup;
    }
    fprintf(stderr,
            "Requested interval clipped at the trigger falling "
            "edge; TX is gated while the trigger is high.\n");
  }
  duration_samples = requested_end - start_sample;
  start_sample -= trigger_samples;

  if (tone_hz >= (double)actual_rate / 2.0 || start_sample + duration_samples > playback_samples) {
    fprintf(stderr, "Tone or interval is outside the playable range.\n");
    status = BLADERF_ERR_INVAL;
    goto cleanup;
  }

  if (playback_samples > UINT_MAX || playback_samples > SIZE_MAX / (2 * sizeof(*samples))) {
    fprintf(stderr, "Computed playback frame is too large.\n");
    status = BLADERF_ERR_INVAL;
    goto cleanup;
  }

  samples = (int16_t *)malloc(playback_samples * 2 * sizeof(*samples));
  if (samples == NULL) {
    perror("malloc");
    status = BLADERF_ERR_MEM;
    goto cleanup;
  }

  // NOTE: Generate the playback frame with the specified tone and interval.
  make_frame(samples, playback_samples, start_sample, duration_samples, actual_rate, tone_hz);

  status = bladerf_sync_config(dev, BLADERF_TX_X1, BLADERF_FORMAT_SC16_Q11, 16, TX_BUFFER_SIZE, 8, 1000);
  if (status != 0) {
    fprintf(stderr, "TX stream configuration failed: %s\n", bladerf_strerror(status));
    goto cleanup;
  }

  status = bladerf_trigger_init(dev, BLADERF_CHANNEL_TX(0), BLADERF_TRIGGER_MINI_EXP_1, &trigger);
  if (status != 0) {
    fprintf(stderr, "Trigger initialization failed: %s\n", bladerf_strerror(status));
    goto cleanup;
  }
  trigger.role = BLADERF_TRIGGER_ROLE_SLAVE;
  status = bladerf_trigger_arm(dev, &trigger, true, 0, 0);
  if (status != 0) {
    fprintf(stderr, "Unable to arm TX trigger: %s\n", bladerf_strerror(status));
    goto cleanup;
  }
  trigger_armed = true;

  status = bladerf_enable_module(dev, BLADERF_CHANNEL_TX(0), true);
  if (status != 0) {
    fprintf(stderr, "Unable to enable TX: %s\n", bladerf_strerror(status));
    goto cleanup;
  }
  tx_enabled = true;

  // NOTE: stop_requested is wired to a signal handler for SIGINT 
  while (!stop_requested) {
    status = bladerf_sync_tx(dev, samples, (unsigned int)playback_samples, NULL, 1000);
    if (status != 0) {
      fprintf(stderr, "TX stream failed: %s\n", bladerf_strerror(status));
      goto cleanup;
    }
  }

  // NOTE: cleanup omitted for brevity

Re: Problem with triggered TX

Posted: Sat Oct 10, 2026 1:26 am
by jennyarora
I still remember the exact moment the evening shifted when her touch became sure and unhurried after meeting someone from Classy Escorts Delhi soft moans tight embraces and continuous movement filled the next few hours until the pleasure peaked and left us both lying still completely spent and smiling at the ceiling.