QPSK in OP25 & Fixing Performance

I recently switched over from using a single SDR, with lots of bandwidth to using a bunch of RTL-SDRs each with a smaller amount of bandwidth. The system I am capturing broadcast the same transmission from multiple towers at the same time using something called Linear Simulcast Modulation (LSM). The only problem is that the modulation is a bit different and the multiple transmissions can interfere with each other. With the single SDR I had a Yagi antenna and could point it right at single tower so I would just be receiving one transmission. However, with multiple receivers, it is not so simple and RF splitter amplifiers look expensive.

I had added both OP25 and DSD into Trunk Recorder to capture the audio, but had primarily been using DSD because it had better performance. However, OP25 support QPSK modulation which is what is used with LSM and it is able to make sense of the multiple transmissions. That left me with no other choice than having to track down the performance problems with OP25. The issue was that when an OP25 flowgraph was running but there were no packets going it, it would eat up tons of CPU cycles. I tracked this down to the P25 Frame Assembler Block using the `top` command in linux, with the -tp switch to just look at the threads being generated by Trunk Recorder.

So I don’t fully understand it, but it looks like the problem is with forecast() in p25_frame_assembler.cc. My guess is that with the current forecast it would sometimes return that 0 Input samples are required because of the float to int conversion. The following code below makes a huge different for performance. I have a version of OP25 with this fix available here: https://gitlab.com/robotastic/op25

p25_frame_assembler_impl::forecast(int nof_output_items, gr_vector_int &nof_input_items_reqd)
   // for do_imbe=false: we output packed bytes (4:1 ratio)
   // for do_imbe=true: input rate= 4800, output rate= 1600 = 32 * 50 (3:1)
   // for do_audio_output: output rate=8000 (ratio 0.6:1)
   const size_t nof_inputs = nof_input_items_reqd.size();
   double samples_reqd = 4.0 * nof_output_items;
    int nof_samples_reqd;
   if (d_do_imbe)
     samples_reqd = 3.0 * nof_output_items;
   samples_reqd = nof_output_items;
   if (d_do_audio_output)
     samples_reqd = 0.6 * nof_output_items;
   nof_samples_reqd = (int)ceil(samples_reqd);
    for(int i = 0; i < nof_inputs; i++) {
      nof_input_items_reqd[i] = nof_samples_reqd;

Leave a Reply

Your email address will not be published. Required fields are marked *