mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-11-16 13:13:41 -05:00
BldeRF2 MIMO and Beam steering plugins enhancements and fixes
This commit is contained in:
parent
0a1dec4a23
commit
f9d7be11cc
@ -97,6 +97,7 @@ void BeamSteeringCWMod::applySettings(const BeamSteeringCWModSettings& settings,
|
|||||||
{
|
{
|
||||||
qDebug() << "BeamSteeringCWMod::applySettings: "
|
qDebug() << "BeamSteeringCWMod::applySettings: "
|
||||||
<< "m_steerDegrees: " << settings.m_steerDegrees
|
<< "m_steerDegrees: " << settings.m_steerDegrees
|
||||||
|
<< "m_channelOutput: " << settings.m_channelOutput
|
||||||
<< "m_filterChainHash: " << settings.m_filterChainHash
|
<< "m_filterChainHash: " << settings.m_filterChainHash
|
||||||
<< "m_log2Interp: " << settings.m_log2Interp
|
<< "m_log2Interp: " << settings.m_log2Interp
|
||||||
<< "m_useReverseAPI: " << settings.m_useReverseAPI
|
<< "m_useReverseAPI: " << settings.m_useReverseAPI
|
||||||
@ -118,6 +119,17 @@ void BeamSteeringCWMod::applySettings(const BeamSteeringCWModSettings& settings,
|
|||||||
m_source->setSteeringDegrees(settings.m_steerDegrees);
|
m_source->setSteeringDegrees(settings.m_steerDegrees);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((m_settings.m_channelOutput != settings.m_channelOutput) || force)
|
||||||
|
{
|
||||||
|
if (settings.m_channelOutput == 0) { // A and B
|
||||||
|
m_source->muteChannel(false, false);
|
||||||
|
} else if (settings.m_channelOutput == 1) { // A only
|
||||||
|
m_source->muteChannel(false, true);
|
||||||
|
} else if (settings.m_channelOutput == 2) { // B only
|
||||||
|
m_source->muteChannel(true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -264,6 +264,12 @@ void BeamSteeringCWModGUI::onMenuDialogCalled(const QPoint &p)
|
|||||||
resetContextMenuType();
|
resetContextMenuType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BeamSteeringCWModGUI::on_channelOutput_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
m_settings.m_channelOutput = index;
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
void BeamSteeringCWModGUI::on_interpolationFactor_currentIndexChanged(int index)
|
void BeamSteeringCWModGUI::on_interpolationFactor_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
m_settings.m_log2Interp = index;
|
m_settings.m_log2Interp = index;
|
||||||
@ -279,6 +285,7 @@ void BeamSteeringCWModGUI::on_position_valueChanged(int value)
|
|||||||
void BeamSteeringCWModGUI::on_steeringDegrees_valueChanged(int value)
|
void BeamSteeringCWModGUI::on_steeringDegrees_valueChanged(int value)
|
||||||
{
|
{
|
||||||
m_settings.m_steerDegrees = value;
|
m_settings.m_steerDegrees = value;
|
||||||
|
ui->steeringDegreesText->setText(tr("%1").arg(m_settings.m_steerDegrees));
|
||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -86,6 +86,7 @@ private:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleSourceMessages();
|
void handleSourceMessages();
|
||||||
|
void on_channelOutput_currentIndexChanged(int index);
|
||||||
void on_interpolationFactor_currentIndexChanged(int index);
|
void on_interpolationFactor_currentIndexChanged(int index);
|
||||||
void on_position_valueChanged(int value);
|
void on_position_valueChanged(int value);
|
||||||
void on_steeringDegrees_valueChanged(int value);
|
void on_steeringDegrees_valueChanged(int value);
|
||||||
|
|||||||
@ -75,6 +75,28 @@
|
|||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="decimationStageLayer">
|
<layout class="QHBoxLayout" name="decimationStageLayer">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="channelOutput">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Channel output</string>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>A,B</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>A</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>B</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="interpolationLabel">
|
<widget class="QLabel" name="interpolationLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|||||||
@ -35,6 +35,7 @@ void BeamSteeringCWModSettings::resetToDefaults()
|
|||||||
m_title = "Beam Steering CW Modulator";
|
m_title = "Beam Steering CW Modulator";
|
||||||
m_log2Interp = 0;
|
m_log2Interp = 0;
|
||||||
m_filterChainHash = 0;
|
m_filterChainHash = 0;
|
||||||
|
m_channelOutput = 0;
|
||||||
m_channelMarker = nullptr;
|
m_channelMarker = nullptr;
|
||||||
m_useReverseAPI = false;
|
m_useReverseAPI = false;
|
||||||
m_reverseAPIAddress = "127.0.0.1";
|
m_reverseAPIAddress = "127.0.0.1";
|
||||||
@ -56,6 +57,7 @@ QByteArray BeamSteeringCWModSettings::serialize() const
|
|||||||
s.writeU32(11, m_reverseAPIChannelIndex);
|
s.writeU32(11, m_reverseAPIChannelIndex);
|
||||||
s.writeU32(12, m_log2Interp);
|
s.writeU32(12, m_log2Interp);
|
||||||
s.writeU32(13, m_filterChainHash);
|
s.writeU32(13, m_filterChainHash);
|
||||||
|
s.writeS32(14, m_channelOutput);
|
||||||
|
|
||||||
return s.final();
|
return s.final();
|
||||||
}
|
}
|
||||||
@ -97,6 +99,8 @@ bool BeamSteeringCWModSettings::deserialize(const QByteArray& data)
|
|||||||
d.readU32(12, &tmp, 0);
|
d.readU32(12, &tmp, 0);
|
||||||
m_log2Interp = tmp > 6 ? 6 : tmp;
|
m_log2Interp = tmp > 6 ? 6 : tmp;
|
||||||
d.readU32(13, &m_filterChainHash, 0);
|
d.readU32(13, &m_filterChainHash, 0);
|
||||||
|
d.readS32(14, &stmp, 0);
|
||||||
|
m_channelOutput = tmp < 0 ? 0 : tmp > 2 ? 2 : tmp;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,7 @@ struct BeamSteeringCWModSettings
|
|||||||
QString m_title;
|
QString m_title;
|
||||||
uint32_t m_log2Interp;
|
uint32_t m_log2Interp;
|
||||||
uint32_t m_filterChainHash;
|
uint32_t m_filterChainHash;
|
||||||
|
int m_channelOutput; //!< 0: 1&2, 1: 1, 2: 2
|
||||||
bool m_useReverseAPI;
|
bool m_useReverseAPI;
|
||||||
QString m_reverseAPIAddress;
|
QString m_reverseAPIAddress;
|
||||||
uint16_t m_reverseAPIPort;
|
uint16_t m_reverseAPIPort;
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgConfigureChannelizer, Message)
|
MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgConfigureChannelizer, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgSignalNotification, Message)
|
MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgSignalNotification, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgConfigureSteeringAngle, Message)
|
MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgConfigureSteeringAngle, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(BeamSteeringCWModSource::MsgConfigureChannelMute, Message)
|
||||||
|
|
||||||
BeamSteeringCWModSource::BeamSteeringCWModSource() :
|
BeamSteeringCWModSource::BeamSteeringCWModSource() :
|
||||||
m_steeringDegrees(90),
|
m_steeringDegrees(90),
|
||||||
@ -78,6 +79,12 @@ void BeamSteeringCWModSource::setSteeringDegrees(int steeringDegrees)
|
|||||||
m_inputMessageQueue.push(msg);
|
m_inputMessageQueue.push(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BeamSteeringCWModSource::muteChannel(bool mute0, bool mute1)
|
||||||
|
{
|
||||||
|
MsgConfigureChannelMute *msg = MsgConfigureChannelMute::create(mute0, mute1);
|
||||||
|
m_inputMessageQueue.push(msg);
|
||||||
|
}
|
||||||
|
|
||||||
void BeamSteeringCWModSource::pull(const SampleVector::iterator& begin, unsigned int nbSamples, unsigned int streamIndex)
|
void BeamSteeringCWModSource::pull(const SampleVector::iterator& begin, unsigned int nbSamples, unsigned int streamIndex)
|
||||||
{
|
{
|
||||||
if (streamIndex > 1) {
|
if (streamIndex > 1) {
|
||||||
@ -225,6 +232,19 @@ bool BeamSteeringCWModSource::handleMessage(const Message& cmd)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (MsgConfigureChannelMute::match(cmd))
|
||||||
|
{
|
||||||
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
|
MsgConfigureChannelMute& cfg = (MsgConfigureChannelMute&) cmd;
|
||||||
|
m_streamSources[0].muteChannel(cfg.getMute0());
|
||||||
|
m_streamSources[1].muteChannel(cfg.getMute1());
|
||||||
|
|
||||||
|
qDebug() << "BeamSteeringCWModSource::handleMessage: MsgConfigureChannelMute:"
|
||||||
|
<< " mute0: " << cfg.getMute0()
|
||||||
|
<< " mute1: " << cfg.getMute1();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug("BeamSteeringCWModSource::handleMessage: unhandled: %s", cmd.getIdentifier());
|
qDebug("BeamSteeringCWModSource::handleMessage: unhandled: %s", cmd.getIdentifier());
|
||||||
|
|||||||
@ -93,6 +93,27 @@ public:
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MsgConfigureChannelMute : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool getMute0() const { return m_mute0; }
|
||||||
|
bool getMute1() const { return m_mute1; }
|
||||||
|
|
||||||
|
static MsgConfigureChannelMute* create(bool mute0, bool mute1) {
|
||||||
|
return new MsgConfigureChannelMute(mute0, mute1);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool m_mute0;
|
||||||
|
bool m_mute1;
|
||||||
|
|
||||||
|
MsgConfigureChannelMute(bool mute0, bool mute1) :
|
||||||
|
Message(),
|
||||||
|
m_mute0(mute0),
|
||||||
|
m_mute1(mute1)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
BeamSteeringCWModSource();
|
BeamSteeringCWModSource();
|
||||||
~BeamSteeringCWModSource();
|
~BeamSteeringCWModSource();
|
||||||
void reset();
|
void reset();
|
||||||
@ -100,6 +121,7 @@ public:
|
|||||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||||
|
|
||||||
void setSteeringDegrees(int steeringDegrees);
|
void setSteeringDegrees(int steeringDegrees);
|
||||||
|
void muteChannel(bool mute0, bool mute1);
|
||||||
void pull(const SampleVector::iterator& begin, unsigned int nbSamples, unsigned int streamIndex);
|
void pull(const SampleVector::iterator& begin, unsigned int nbSamples, unsigned int streamIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -15,10 +15,12 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "dsp/dsptypes.h"
|
||||||
#include "beamsteeringcwmodstreamsource.h"
|
#include "beamsteeringcwmodstreamsource.h"
|
||||||
|
|
||||||
BeamSteeringCWModStreamSource::BeamSteeringCWModStreamSource() :
|
BeamSteeringCWModStreamSource::BeamSteeringCWModStreamSource() :
|
||||||
m_amp(0.5f)
|
m_amp(SDR_TX_SCALEF/sqrt(2.0f)),
|
||||||
|
m_phase(0)
|
||||||
{
|
{
|
||||||
m_real = m_amp;
|
m_real = m_amp;
|
||||||
m_imag = 0.0f;
|
m_imag = 0.0f;
|
||||||
@ -27,16 +29,30 @@ BeamSteeringCWModStreamSource::BeamSteeringCWModStreamSource() :
|
|||||||
BeamSteeringCWModStreamSource::~BeamSteeringCWModStreamSource()
|
BeamSteeringCWModStreamSource::~BeamSteeringCWModStreamSource()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void BeamSteeringCWModStreamSource::muteChannel(bool mute)
|
||||||
|
{
|
||||||
|
if (mute)
|
||||||
|
{
|
||||||
|
m_real = 0;
|
||||||
|
m_imag = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setPhase(m_phase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BeamSteeringCWModStreamSource::setPhase(float phase)
|
void BeamSteeringCWModStreamSource::setPhase(float phase)
|
||||||
{
|
{
|
||||||
float normPhase = phase < -M_PI ? -M_PI : phase > M_PI ? M_PI : phase;
|
float normPhase = phase < -M_PI ? -M_PI : phase > M_PI ? M_PI : phase;
|
||||||
m_real = m_amp * cos(normPhase);
|
m_real = m_amp * cos(normPhase);
|
||||||
m_imag = m_amp * sin(normPhase);
|
m_imag = m_amp * sin(normPhase);
|
||||||
|
m_phase = phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BeamSteeringCWModStreamSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
|
void BeamSteeringCWModStreamSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
|
||||||
{
|
{
|
||||||
std::fill(begin, begin + nbSamples, Sample{m_real, m_imag});
|
std::fill(begin, begin + nbSamples, Sample{(int) m_real, m_imag});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BeamSteeringCWModStreamSource::pullOne(Sample& sample)
|
void BeamSteeringCWModStreamSource::pullOne(Sample& sample)
|
||||||
@ -46,4 +62,4 @@ void BeamSteeringCWModStreamSource::pullOne(Sample& sample)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BeamSteeringCWModStreamSource::reset()
|
void BeamSteeringCWModStreamSource::reset()
|
||||||
{}
|
{}
|
||||||
|
|||||||
@ -33,10 +33,12 @@ public:
|
|||||||
void setPhase(float phase);
|
void setPhase(float phase);
|
||||||
unsigned int getStreamIndex() const { return m_streamIndex; }
|
unsigned int getStreamIndex() const { return m_streamIndex; }
|
||||||
void setStreamIndex(unsigned int streamIndex) { m_streamIndex = streamIndex; }
|
void setStreamIndex(unsigned int streamIndex) { m_streamIndex = streamIndex; }
|
||||||
|
void muteChannel(bool mute);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int m_streamIndex;
|
unsigned int m_streamIndex;
|
||||||
float m_amp;
|
float m_amp;
|
||||||
|
float m_phase;
|
||||||
FixReal m_real;
|
FixReal m_real;
|
||||||
FixReal m_imag;
|
FixReal m_imag;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -72,8 +72,8 @@ BladeRF2MIMO::BladeRF2MIMO(DeviceAPI *deviceAPI) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_mimoType = MIMOHalfSynchronous;
|
m_mimoType = MIMOHalfSynchronous;
|
||||||
m_sampleMIFifo.init(2, 96000 * 4);
|
m_sampleMIFifo.init(2, 4096 * 64);
|
||||||
m_sampleMOFifo.init(2, 96000 * 4);
|
m_sampleMOFifo.init(2, 4096 * 64);
|
||||||
m_deviceAPI->setNbSourceStreams(2);
|
m_deviceAPI->setNbSourceStreams(2);
|
||||||
m_deviceAPI->setNbSinkStreams(2);
|
m_deviceAPI->setNbSinkStreams(2);
|
||||||
m_networkManager = new QNetworkAccessManager();
|
m_networkManager = new QNetworkAccessManager();
|
||||||
@ -885,26 +885,26 @@ bool BladeRF2MIMO::setRxDeviceCenterFrequency(struct bladerf *dev, quint64 freq_
|
|||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
qWarning("BladeRF2MIMO::setDeviceCenterFrequency: RX0: bladerf_set_frequency(%lld) failed: %s",
|
qWarning("BladeRF2MIMO::setRxDeviceCenterFrequency: RX0: bladerf_set_frequency(%lld) failed: %s",
|
||||||
freq_hz, bladerf_strerror(status));
|
freq_hz, bladerf_strerror(status));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug("BladeRF2MIMO::setDeviceCenterFrequency: RX0: bladerf_set_frequency(%lld)", freq_hz);
|
qDebug("BladeRF2MIMO::setRxDeviceCenterFrequency: RX0: bladerf_set_frequency(%lld)", freq_hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = bladerf_set_frequency(dev, BLADERF_CHANNEL_RX(1), freq_hz);
|
status = bladerf_set_frequency(dev, BLADERF_CHANNEL_RX(1), freq_hz);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
qWarning("BladeRF2MIMO::setDeviceCenterFrequency: RX1: bladerf_set_frequency(%lld) failed: %s",
|
qWarning("BladeRF2MIMO::setRxDeviceCenterFrequency: RX1: bladerf_set_frequency(%lld) failed: %s",
|
||||||
freq_hz, bladerf_strerror(status));
|
freq_hz, bladerf_strerror(status));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug("BladeRF2MIMO::setDeviceCenterFrequency: RX1: bladerf_set_frequency(%lld)", freq_hz);
|
qDebug("BladeRF2MIMO::setRxDeviceCenterFrequency: RX1: bladerf_set_frequency(%lld)", freq_hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -918,28 +918,28 @@ bool BladeRF2MIMO::setTxDeviceCenterFrequency(struct bladerf *dev, quint64 freq_
|
|||||||
int status = bladerf_set_frequency(dev, BLADERF_CHANNEL_TX(0), freq_hz);
|
int status = bladerf_set_frequency(dev, BLADERF_CHANNEL_TX(0), freq_hz);
|
||||||
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
qWarning("BladeRF2Output::setDeviceCenterFrequency: TX0: bladerf_set_frequency(%lld) failed: %s",
|
qWarning("BladeRF2Output::setTxDeviceCenterFrequency: TX0: bladerf_set_frequency(%lld) failed: %s",
|
||||||
freq_hz, bladerf_strerror(status));
|
freq_hz, bladerf_strerror(status));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug("BladeRF2Output::setDeviceCenterFrequency: TX0: bladerf_set_frequency(%lld)", freq_hz);
|
qDebug("BladeRF2Output::setTxDeviceCenterFrequency: TX0: bladerf_set_frequency(%lld)", freq_hz);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status = bladerf_set_frequency(dev, BLADERF_CHANNEL_TX(1), freq_hz);
|
status = bladerf_set_frequency(dev, BLADERF_CHANNEL_TX(1), freq_hz);
|
||||||
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
qWarning("BladeRF2Output::setDeviceCenterFrequency: TX1: bladerf_set_frequency(%lld) failed: %s",
|
qWarning("BladeRF2Output::setTxDeviceCenterFrequency: TX1: bladerf_set_frequency(%lld) failed: %s",
|
||||||
freq_hz, bladerf_strerror(status));
|
freq_hz, bladerf_strerror(status));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug("BladeRF2Output::setDeviceCenterFrequency: TX1: bladerf_set_frequency(%lld)", freq_hz);
|
qDebug("BladeRF2Output::setTxDeviceCenterFrequency: TX1: bladerf_set_frequency(%lld)", freq_hz);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BladeRF2MIMO::getRxFrequencyRange(uint64_t& min, uint64_t& max, int& step)
|
void BladeRF2MIMO::getRxFrequencyRange(uint64_t& min, uint64_t& max, int& step)
|
||||||
|
|||||||
@ -51,6 +51,7 @@ BladeRF2MIMOGui::BladeRF2MIMOGui(DeviceUISet *deviceUISet, QWidget* parent) :
|
|||||||
m_streamIndex(0),
|
m_streamIndex(0),
|
||||||
m_spectrumRxElseTx(true),
|
m_spectrumRxElseTx(true),
|
||||||
m_spectrumStreamIndex(0),
|
m_spectrumStreamIndex(0),
|
||||||
|
m_gainLock(false),
|
||||||
m_doApplySettings(true),
|
m_doApplySettings(true),
|
||||||
m_forceSettings(true),
|
m_forceSettings(true),
|
||||||
m_sampleMIMO(nullptr),
|
m_sampleMIMO(nullptr),
|
||||||
@ -420,6 +421,7 @@ void BladeRF2MIMOGui::on_spectrumSide_currentIndexChanged(int index)
|
|||||||
m_spectrumRxElseTx = (index == 0);
|
m_spectrumRxElseTx = (index == 0);
|
||||||
m_deviceUISet->m_spectrum->setDisplayedStream(m_spectrumRxElseTx, m_spectrumStreamIndex);
|
m_deviceUISet->m_spectrum->setDisplayedStream(m_spectrumRxElseTx, m_spectrumStreamIndex);
|
||||||
m_deviceUISet->m_deviceAPI->setSpectrumSinkInput(m_spectrumRxElseTx, m_spectrumStreamIndex);
|
m_deviceUISet->m_deviceAPI->setSpectrumSinkInput(m_spectrumRxElseTx, m_spectrumStreamIndex);
|
||||||
|
m_deviceUISet->setSpectrumScalingFactor(m_spectrumRxElseTx ? SDR_RX_SCALEF : SDR_TX_SCALEF);
|
||||||
updateSampleRateAndFrequency();
|
updateSampleRateAndFrequency();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,6 +559,19 @@ void BladeRF2MIMOGui::on_decim_currentIndexChanged(int index)
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BladeRF2MIMOGui::on_gainLock_toggled(bool checked)
|
||||||
|
{
|
||||||
|
if (!m_gainLock && checked)
|
||||||
|
{
|
||||||
|
m_settings.m_rx1GlobalGain = m_settings.m_rx0GlobalGain;
|
||||||
|
m_settings.m_rx1GainMode = m_settings.m_rx0GainMode;
|
||||||
|
m_settings.m_tx1GlobalGain = m_settings.m_tx0GlobalGain;
|
||||||
|
sendSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_gainLock = checked;
|
||||||
|
}
|
||||||
|
|
||||||
void BladeRF2MIMOGui::on_gainMode_currentIndexChanged(int index)
|
void BladeRF2MIMOGui::on_gainMode_currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
if (!m_rxElseTx) { // not for Tx
|
if (!m_rxElseTx) { // not for Tx
|
||||||
@ -570,7 +585,7 @@ void BladeRF2MIMOGui::on_gainMode_currentIndexChanged(int index)
|
|||||||
{
|
{
|
||||||
BladeRF2MIMO::GainMode mode = modes[index];
|
BladeRF2MIMO::GainMode mode = modes[index];
|
||||||
|
|
||||||
if (m_streamIndex == 0)
|
if (m_streamIndex == 0 || m_gainLock)
|
||||||
{
|
{
|
||||||
if (m_settings.m_rx0GainMode != mode.m_value)
|
if (m_settings.m_rx0GainMode != mode.m_value)
|
||||||
{
|
{
|
||||||
@ -585,7 +600,8 @@ void BladeRF2MIMOGui::on_gainMode_currentIndexChanged(int index)
|
|||||||
|
|
||||||
m_settings.m_rx0GainMode = mode.m_value;
|
m_settings.m_rx0GainMode = mode.m_value;
|
||||||
}
|
}
|
||||||
else if (m_streamIndex == 1)
|
|
||||||
|
if (m_streamIndex == 1 || m_gainLock)
|
||||||
{
|
{
|
||||||
if (m_settings.m_rx1GainMode != mode.m_value)
|
if (m_settings.m_rx1GainMode != mode.m_value)
|
||||||
{
|
{
|
||||||
@ -611,17 +627,19 @@ void BladeRF2MIMOGui::on_gain_valueChanged(int value)
|
|||||||
|
|
||||||
if (m_rxElseTx)
|
if (m_rxElseTx)
|
||||||
{
|
{
|
||||||
if (m_streamIndex == 0) {
|
if (m_streamIndex == 0 || m_gainLock) {
|
||||||
m_settings.m_rx0GlobalGain = value;
|
m_settings.m_rx0GlobalGain = value;
|
||||||
} else {
|
}
|
||||||
|
if (m_streamIndex == 1 || m_gainLock) {
|
||||||
m_settings.m_rx1GlobalGain = value;
|
m_settings.m_rx1GlobalGain = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_streamIndex == 0) {
|
if (m_streamIndex == 0 || m_gainLock) {
|
||||||
m_settings.m_tx0GlobalGain = value;
|
m_settings.m_tx0GlobalGain = value;
|
||||||
} else {
|
}
|
||||||
|
if (m_streamIndex == 1 || m_gainLock) {
|
||||||
m_settings.m_tx1GlobalGain = value;
|
m_settings.m_tx1GlobalGain = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,6 +60,7 @@ private:
|
|||||||
int m_streamIndex; //!< Current stream index being dealt with
|
int m_streamIndex; //!< Current stream index being dealt with
|
||||||
bool m_spectrumRxElseTx;
|
bool m_spectrumRxElseTx;
|
||||||
int m_spectrumStreamIndex; //!< Index of the stream displayed on main spectrum
|
int m_spectrumStreamIndex; //!< Index of the stream displayed on main spectrum
|
||||||
|
bool m_gainLock; //!< Lock Rx or Tx channel gains (set channel gains to gain of channel 0 when engaged)
|
||||||
QTimer m_updateTimer;
|
QTimer m_updateTimer;
|
||||||
QTimer m_statusTimer;
|
QTimer m_statusTimer;
|
||||||
bool m_doApplySettings;
|
bool m_doApplySettings;
|
||||||
@ -113,6 +114,7 @@ private slots:
|
|||||||
void on_sampleRate_changed(quint64 value);
|
void on_sampleRate_changed(quint64 value);
|
||||||
void on_fcPos_currentIndexChanged(int index);
|
void on_fcPos_currentIndexChanged(int index);
|
||||||
void on_decim_currentIndexChanged(int index);
|
void on_decim_currentIndexChanged(int index);
|
||||||
|
void on_gainLock_toggled(bool checked);
|
||||||
void on_gainMode_currentIndexChanged(int index);
|
void on_gainMode_currentIndexChanged(int index);
|
||||||
void on_gain_valueChanged(int value);
|
void on_gain_valueChanged(int value);
|
||||||
void on_biasTee_toggled(bool checked);
|
void on_biasTee_toggled(bool checked);
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>366</width>
|
<width>366</width>
|
||||||
<height>220</height>
|
<height>228</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -700,21 +700,24 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout_decim" columnstretch="0,0,0,0,0">
|
<layout class="QGridLayout" name="gridLayout_decim" columnstretch="0,0,0,0,0,0">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="2">
|
<item row="0" column="3">
|
||||||
<widget class="QSlider" name="gain">
|
<widget class="QSlider" name="gain">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Gain value</string>
|
<string>Gain value</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="2">
|
||||||
<widget class="QComboBox" name="gainMode">
|
<widget class="QComboBox" name="gainMode">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Gain mode</string>
|
<string>Gain mode</string>
|
||||||
@ -728,7 +731,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="3">
|
<item row="0" column="4">
|
||||||
<widget class="QLabel" name="gainText">
|
<widget class="QLabel" name="gainText">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
@ -744,7 +747,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="4">
|
<item row="0" column="5">
|
||||||
<widget class="ButtonSwitch" name="biasTee">
|
<widget class="ButtonSwitch" name="biasTee">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Bias Tee</string>
|
<string>Bias Tee</string>
|
||||||
@ -754,6 +757,24 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QToolButton" name="gainLock">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Lock both channels gain</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||||
|
<normaloff>:/unlocked.png</normaloff>
|
||||||
|
<normalon>:/locked.png</normalon>:/unlocked.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@ -116,7 +116,7 @@ bool BladeRF2MIMOSettings::deserialize(const QByteArray& data)
|
|||||||
uint32_t uintval;
|
uint32_t uintval;
|
||||||
|
|
||||||
d.readS32(1, &m_devSampleRate, 3072000);
|
d.readS32(1, &m_devSampleRate, 3072000);
|
||||||
d.readS32(2, &m_LOppmTenths);
|
d.readS32(2, &m_LOppmTenths, 0);
|
||||||
|
|
||||||
d.readU64(10, &m_rxCenterFrequency, 435000*1000);
|
d.readU64(10, &m_rxCenterFrequency, 435000*1000);
|
||||||
d.readU32(11, &m_log2Decim);
|
d.readU32(11, &m_log2Decim);
|
||||||
|
|||||||
@ -96,9 +96,10 @@ void BladeRF2MOThread::run()
|
|||||||
m_running = false;
|
m_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BladeRF2MOThread::setLog2Interpolation(unsigned int log2_interp)
|
void BladeRF2MOThread::setLog2Interpolation(unsigned int log2Interp)
|
||||||
{
|
{
|
||||||
m_log2Interp = log2_interp;
|
qDebug("BladeRF2MOThread::setLog2Interpolation: %u", log2Interp);
|
||||||
|
m_log2Interp = log2Interp;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int BladeRF2MOThread::getLog2Interpolation() const
|
unsigned int BladeRF2MOThread::getLog2Interpolation() const
|
||||||
@ -123,13 +124,13 @@ void BladeRF2MOThread::callback(qint16* buf, qint32 samplesPerChannel)
|
|||||||
|
|
||||||
if (iPart1Begin != iPart1End)
|
if (iPart1Begin != iPart1End)
|
||||||
{
|
{
|
||||||
callbackPart(buf, samplesPerChannel, iPart1Begin, iPart1End - iPart1Begin);
|
callbackPart(buf, (iPart1End - iPart1Begin)*(1<<m_log2Interp), iPart1Begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iPart2Begin != iPart2End)
|
if (iPart2Begin != iPart2End)
|
||||||
{
|
{
|
||||||
unsigned int part1Size = iPart1End - iPart1End;
|
unsigned int shift = (iPart1End - iPart1Begin)*(1<<m_log2Interp);
|
||||||
callbackPart(buf + 2*part1Size, samplesPerChannel, iPart2Begin, iPart2End - iPart2Begin);
|
callbackPart(buf + 2*shift, (iPart2End - iPart2Begin)*(1<<m_log2Interp), iPart2Begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
int status = bladerf_interleave_stream_buffer(BLADERF_TX_X2, BLADERF_FORMAT_SC16_Q11 , samplesPerChannel*2, (void *) buf);
|
int status = bladerf_interleave_stream_buffer(BLADERF_TX_X2, BLADERF_FORMAT_SC16_Q11 , samplesPerChannel*2, (void *) buf);
|
||||||
@ -142,7 +143,7 @@ void BladeRF2MOThread::callback(qint16* buf, qint32 samplesPerChannel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Interpolate according to specified log2 (ex: log2=4 => decim=16). len is a number of samples (not a number of I or Q)
|
// Interpolate according to specified log2 (ex: log2=4 => decim=16). len is a number of samples (not a number of I or Q)
|
||||||
void BladeRF2MOThread::callbackPart(qint16* buf, qint32 samplesPerChannel, int iBegin, qint32 nSamples)
|
void BladeRF2MOThread::callbackPart(qint16* buf, qint32 nSamples, int iBegin)
|
||||||
{
|
{
|
||||||
for (unsigned int channel = 0; channel < 2; channel++)
|
for (unsigned int channel = 0; channel < 2; channel++)
|
||||||
{
|
{
|
||||||
@ -150,7 +151,7 @@ void BladeRF2MOThread::callbackPart(qint16* buf, qint32 samplesPerChannel, int i
|
|||||||
|
|
||||||
if (m_log2Interp == 0)
|
if (m_log2Interp == 0)
|
||||||
{
|
{
|
||||||
m_interpolators[channel].interpolate1(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate1(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -159,22 +160,22 @@ void BladeRF2MOThread::callbackPart(qint16* buf, qint32 samplesPerChannel, int i
|
|||||||
switch (m_log2Interp)
|
switch (m_log2Interp)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
m_interpolators[channel].interpolate2_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate2_inf(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
m_interpolators[channel].interpolate4_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate4_inf(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
m_interpolators[channel].interpolate8_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate8_inf(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
m_interpolators[channel].interpolate16_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate16_inf(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
m_interpolators[channel].interpolate32_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate32_inf(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
m_interpolators[channel].interpolate64_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate64_inf(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -185,22 +186,22 @@ void BladeRF2MOThread::callbackPart(qint16* buf, qint32 samplesPerChannel, int i
|
|||||||
switch (m_log2Interp)
|
switch (m_log2Interp)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
m_interpolators[channel].interpolate2_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate2_sup(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
m_interpolators[channel].interpolate4_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate4_sup(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
m_interpolators[channel].interpolate8_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate8_sup(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
m_interpolators[channel].interpolate16_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate16_sup(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
m_interpolators[channel].interpolate32_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate32_sup(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
m_interpolators[channel].interpolate64_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate64_sup(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -211,22 +212,22 @@ void BladeRF2MOThread::callbackPart(qint16* buf, qint32 samplesPerChannel, int i
|
|||||||
switch (m_log2Interp)
|
switch (m_log2Interp)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
m_interpolators[channel].interpolate2_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate2_cen(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
m_interpolators[channel].interpolate4_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate4_cen(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
m_interpolators[channel].interpolate8_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate8_cen(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
m_interpolators[channel].interpolate16_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate16_cen(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
m_interpolators[channel].interpolate32_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate32_cen(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
m_interpolators[channel].interpolate64_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2);
|
m_interpolators[channel].interpolate64_cen(&begin, &buf[channel*2*nSamples], 2*nSamples);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -37,7 +37,7 @@ public:
|
|||||||
void startWork();
|
void startWork();
|
||||||
void stopWork();
|
void stopWork();
|
||||||
bool isRunning() const { return m_running; }
|
bool isRunning() const { return m_running; }
|
||||||
void setLog2Interpolation(unsigned int log2_interp);
|
void setLog2Interpolation(unsigned int log2Interp);
|
||||||
unsigned int getLog2Interpolation() const;
|
unsigned int getLog2Interpolation() const;
|
||||||
void setFcPos(int fcPos);
|
void setFcPos(int fcPos);
|
||||||
int getFcPos() const;
|
int getFcPos() const;
|
||||||
@ -58,7 +58,7 @@ private:
|
|||||||
|
|
||||||
void run();
|
void run();
|
||||||
unsigned int getNbFifos();
|
unsigned int getNbFifos();
|
||||||
void callbackPart(qint16* buf, qint32 samplesPerChannel, int iBegin, qint32 nSamples);
|
void callbackPart(qint16* buf, qint32 nSamples, int iBegin);
|
||||||
void callback(qint16* buf, qint32 samplesPerChannel);
|
void callback(qint16* buf, qint32 samplesPerChannel);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user