Problem with triggered TX

Discussions related to embedded firmware, driver, and user mode application software development
Post Reply
nils
Posts: 2
Joined: Thu Mar 02, 2023 12:59 am

Problem with triggered TX

Post 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
jennyarora
Posts: 2
Joined: Fri Jun 26, 2026 4:26 am

Re: Problem with triggered TX

Post 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.
Post Reply