@@ -173,7 +173,7 @@ size_t SoapyPlutoSDR::getStreamMTU( SoapySDR::Stream *handle) const
173173 }
174174
175175 if (IsValidTxStreamHandle (handle)) {
176- return 4096 ;
176+ return this -> tx_stream -> get_mtu_size () ;
177177 }
178178
179179 return 0 ;
@@ -605,14 +605,11 @@ tx_streamer::tx_streamer(const iio_device *_dev, const plutosdrStreamFormat _for
605605 iio_channel_enable (chn);
606606 channel_list.push_back (chn);
607607 }
608+ long long samplerate;
608609
609- buf_size = 4096 ;
610- items_in_buf = 0 ;
611- buf = iio_device_create_buffer (dev, buf_size, false );
612- if (!buf) {
613- SoapySDR_logf (SOAPY_SDR_ERROR, " Unable to create buffer!" );
614- throw std::runtime_error (" Unable to create buffer!" );
615- }
610+ iio_channel_attr_read_longlong (iio_device_find_channel (dev, " voltage0" , true )," sampling_frequency" ,&samplerate);
611+
612+ this ->set_buffer_size_by_samplerate (samplerate);
616613
617614 direct_copy = has_direct_copy ();
618615
@@ -629,6 +626,66 @@ tx_streamer::~tx_streamer(){
629626
630627}
631628
629+ void tx_streamer::set_buffer_size_by_samplerate (const size_t samplerate) {
630+
631+ // The original buffer size of 4096 is not enough for a full duplex stream at sample rates above 1 Msps
632+ // Avoid samples getting dropped in the TX stream by setting a high enough buffer size.
633+ // Apply the same logic as for the rx_streamer buffer. Keep it a power of 2 which seems to be better.
634+ int rounded_nb_samples_per_call = (int )::round (samplerate / 60.0 );
635+
636+ int power_of_2_nb_samples = 0 ;
637+
638+ while (rounded_nb_samples_per_call > (1 << power_of_2_nb_samples)) {
639+ power_of_2_nb_samples++;
640+ }
641+
642+ this ->set_buffer_size (1 << power_of_2_nb_samples);
643+
644+ SoapySDR_logf (SOAPY_SDR_INFO, " Auto setting TX Buffer Size: %lu" , (unsigned long )buffer_size);
645+
646+ // Recompute transmit MTU from buffer size change.
647+ // We always set MTU size = Buffer Size.
648+ // On buffer size adjustment to sample rate,
649+ // MTU can be changed accordingly safely here.
650+ set_mtu_size (this ->buffer_size );
651+ }
652+
653+ void tx_streamer::set_mtu_size (const size_t mtu_size) {
654+
655+ this ->mtu_size = mtu_size;
656+
657+ SoapySDR_logf (SOAPY_SDR_INFO, " Set TX MTU Size: %lu" , (unsigned long )mtu_size);
658+ }
659+
660+ void tx_streamer::set_buffer_size (const size_t _buffer_size){
661+
662+ if (!buf || this ->buffer_size != _buffer_size) {
663+ // cancel first
664+ if (buf) {
665+ iio_buffer_cancel (buf);
666+ }
667+ // then destroy
668+ if (buf) {
669+ iio_buffer_destroy (buf);
670+ }
671+
672+ items_in_buf = 0 ;
673+
674+ buf = iio_device_create_buffer (dev, _buffer_size, false );
675+ if (!buf) {
676+ SoapySDR_logf (SOAPY_SDR_ERROR, " Unable to create TX buffer!" );
677+ throw std::runtime_error (" Unable to create TX buffer!\n " );
678+ }
679+
680+ }
681+
682+ this ->buffer_size =_buffer_size;
683+ }
684+
685+ size_t tx_streamer::get_mtu_size () {
686+ return this ->mtu_size ;
687+ }
688+
632689int tx_streamer::send ( const void * const *buffs,
633690 const size_t numElems,
634691 int &flags,
@@ -640,7 +697,7 @@ int tx_streamer::send( const void * const *buffs,
640697 return 0 ;
641698 }
642699
643- size_t items = std::min (buf_size - items_in_buf, numElems);
700+ size_t items = std::min (this -> buffer_size - items_in_buf, numElems);
644701
645702 int16_t src = 0 ;
646703 int16_t const *src_ptr = &src;
@@ -729,14 +786,14 @@ int tx_streamer::send( const void * const *buffs,
729786
730787 items_in_buf += items;
731788
732- if (items_in_buf == buf_size || (flags & SOAPY_SDR_END_BURST && numElems == items)) {
789+ if (items_in_buf == this -> buffer_size || (flags & SOAPY_SDR_END_BURST && numElems == items)) {
733790 int ret = send_buf ();
734791
735792 if (ret < 0 ) {
736793 return SOAPY_SDR_ERROR;
737794 }
738795
739- if ((size_t )ret != buf_size ) {
796+ if ((size_t )ret != this -> buffer_size ) {
740797 return SOAPY_SDR_ERROR;
741798 }
742799 }
@@ -757,7 +814,7 @@ int tx_streamer::send_buf()
757814 }
758815
759816 if (items_in_buf > 0 ) {
760- if (items_in_buf < buf_size ) {
817+ if (items_in_buf < this -> buffer_size ) {
761818 ptrdiff_t buf_step = iio_buffer_step (buf);
762819 uint8_t *buf_ptr = (uint8_t *)iio_buffer_start (buf) + items_in_buf * buf_step;
763820 uint8_t *buf_end = (uint8_t *)iio_buffer_end (buf);
0 commit comments