Skip to content

Commit

Permalink
Merge pull request f4exb#1914 from srcejon/freq_scanner
Browse files Browse the repository at this point in the history
Instant Replay
  • Loading branch information
f4exb authored Dec 6, 2023
2 parents 364dfc1 + 30497b5 commit cb97263
Show file tree
Hide file tree
Showing 31 changed files with 789 additions and 369 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/sdrangel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ jobs:
id: get_filename
run: echo "filename=$(grep CPACK_PACKAGE_FILE_NAME build/CMakeCache.txt | cut -d "=" -f2)" >> $GITHUB_OUTPUT
- name: Build SDRangel on Mac
run: |
cd build
make -j3
- name: Stop XProtectBehaviorService
run: |
echo "killing XProject as it can interfere with hdiutil"; sudo pkill -9 XProtect >/dev/null || true;
echo "waiting..."; while pgrep XProtect; do sleep 3; done;
- name: Build DMG
run: |
cd build
make package -j3
Expand Down
5 changes: 5 additions & 0 deletions plugins/samplesource/airspyhf/airspyhfgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,11 @@ void AirspyHFGui::on_replayLoop_toggled(bool checked)
sendSettings();
}

void AirspyHFGui::setReplayTime(float time)
{
ui->replayOffset->setValue(std::ceil(time * 10.0f));
}

void AirspyHFGui::makeUIConnections()
{
QObject::connect(ui->centerFrequency, &ValueDial::changed, this, &AirspyHFGui::on_centerFrequency_changed);
Expand Down
1 change: 1 addition & 0 deletions plugins/samplesource/airspyhf/airspyhfgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class AirspyHFGui : public DeviceGUI {
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; }
void setReplayTime(float time) override;

uint32_t getDevSampleRate(unsigned int index);
int getDevSampleRateIndex(uint32_t sampleRate);
Expand Down
68 changes: 34 additions & 34 deletions plugins/samplesource/airspyhf/airspyhfworker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,27 +77,27 @@ void AirspyHFWorker::setLog2Decimation(unsigned int log2_decim)
// Decimate according to specified log2 (ex: log2=4 => decim=16)
void AirspyHFWorker::callbackIQ(const float* inBuf, qint32 len)
{
SampleVector::iterator it = m_convertBuffer.begin();
SampleVector::iterator it = m_convertBuffer.begin();

// Save data to replay buffer
m_replayBuffer->lock();
bool replayEnabled = m_replayBuffer->getSize() > 0;
if (replayEnabled) {
m_replayBuffer->write(inBuf, len);
}
m_replayBuffer->lock();
bool replayEnabled = m_replayBuffer->getSize() > 0;
if (replayEnabled) {
m_replayBuffer->write(inBuf, len);
}

const float* buf = inBuf;
qint32 remaining = len;
const float* buf = inBuf;
qint32 remaining = len;

while (remaining > 0)
{
// Choose between live data or replayed data
if (replayEnabled && m_replayBuffer->useReplay()) {
len = m_replayBuffer->read(remaining, buf);
} else {
len = remaining;
}
remaining -= len;
{
// Choose between live data or replayed data
if (replayEnabled && m_replayBuffer->useReplay()) {
len = m_replayBuffer->read(remaining, buf);
} else {
len = remaining;
}
remaining -= len;

switch (m_log2Decim)
{
Expand Down Expand Up @@ -135,32 +135,32 @@ void AirspyHFWorker::callbackIQ(const float* inBuf, qint32 len)

m_replayBuffer->unlock();

m_sampleFifo->write(m_convertBuffer.begin(), it);
m_sampleFifo->write(m_convertBuffer.begin(), it);
}

void AirspyHFWorker::callbackQI(const float* inBuf, qint32 len)
{
SampleVector::iterator it = m_convertBuffer.begin();
SampleVector::iterator it = m_convertBuffer.begin();

// Save data to replay buffer
m_replayBuffer->lock();
bool replayEnabled = m_replayBuffer->getSize() > 0;
if (replayEnabled) {
m_replayBuffer->write(inBuf, len);
}
m_replayBuffer->lock();
bool replayEnabled = m_replayBuffer->getSize() > 0;
if (replayEnabled) {
m_replayBuffer->write(inBuf, len);
}

const float* buf = inBuf;
qint32 remaining = len;
const float* buf = inBuf;
qint32 remaining = len;

while (remaining > 0)
{
// Choose between live data or replayed data
if (replayEnabled && m_replayBuffer->useReplay()) {
len = m_replayBuffer->read(remaining, buf);
} else {
len = remaining;
}
remaining -= len;
{
// Choose between live data or replayed data
if (replayEnabled && m_replayBuffer->useReplay()) {
len = m_replayBuffer->read(remaining, buf);
} else {
len = remaining;
}
remaining -= len;

switch (m_log2Decim)
{
Expand Down Expand Up @@ -198,7 +198,7 @@ void AirspyHFWorker::callbackQI(const float* inBuf, qint32 len)

m_replayBuffer->unlock();

m_sampleFifo->write(m_convertBuffer.begin(), it);
m_sampleFifo->write(m_convertBuffer.begin(), it);
}

int AirspyHFWorker::rx_callback(airspyhf_transfer_t* transfer)
Expand Down
24 changes: 23 additions & 1 deletion plugins/samplesource/limesdrinput/limesdrinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgGetDeviceInfo, Message)
MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgReportStreamInfo, Message)
MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgStartStop, Message)
MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgCalibrationResult, Message)
MESSAGE_CLASS_DEFINITION(LimeSDRInput::MsgSaveReplay, Message)

LimeSDRInput::LimeSDRInput(DeviceAPI *deviceAPI) :
m_deviceAPI(deviceAPI),
Expand Down Expand Up @@ -422,7 +423,7 @@ bool LimeSDRInput::start()

// start / stop streaming is done in the thread.

m_limeSDRInputThread = new LimeSDRInputThread(&m_streamId, &m_sampleFifo);
m_limeSDRInputThread = new LimeSDRInputThread(&m_streamId, &m_sampleFifo, &m_replayBuffer);
qDebug("LimeSDRInput::start: thread created");

applySettings(m_settings, QList<QString>(), true);
Expand Down Expand Up @@ -778,6 +779,12 @@ bool LimeSDRInput::handleMessage(const Message& message)

return true;
}
else if (MsgSaveReplay::match(message))
{
MsgSaveReplay& cmd = (MsgSaveReplay&) message;
m_replayBuffer.save(cmd.getFilename(), m_settings.m_devSampleRate, getCenterFrequency());
return true;
}
else
{
return false;
Expand Down Expand Up @@ -977,6 +984,9 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, const QLi
settings.m_devSampleRate,
1<<settings.m_log2HardDecim);
}
if (settings.m_devSampleRate != m_settings.m_devSampleRate) {
m_replayBuffer.clear();
}
}
}

Expand Down Expand Up @@ -1168,6 +1178,18 @@ bool LimeSDRInput::applySettings(const LimeSDRInputSettings& settings, const QLi
m_settings.applySettings(settingsKeys, settings);
}

if (settingsKeys.contains("replayLength") || settingsKeys.contains("devSampleRate") || force) {
m_replayBuffer.setSize(m_settings.m_replayLength, m_settings.m_devSampleRate);
}

if (settingsKeys.contains("replayOffset") || settingsKeys.contains("devSampleRate") || force) {
m_replayBuffer.setReadOffset(((unsigned)(m_settings.m_replayOffset * m_settings.m_devSampleRate)) * 2);
}

if (settingsKeys.contains("replayLoop") || force) {
m_replayBuffer.setLoop(m_settings.m_replayLoop);
}

double clockGenFreqAfter;

if (LMS_GetClockFreq(m_deviceShared.m_deviceParams->getDevice(), LMS_CLOCK_CGEN, &clockGenFreqAfter) != 0)
Expand Down
23 changes: 22 additions & 1 deletion plugins/samplesource/limesdrinput/limesdrinput.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <QNetworkRequest>

#include "dsp/devicesamplesource.h"
#include "dsp/replaybuffer.h"
#include "limesdr/devicelimesdrshared.h"
#include "limesdrinputsettings.h"

Expand Down Expand Up @@ -209,7 +210,26 @@ class LimeSDRInput : public DeviceSampleSource
{ }
};

LimeSDRInput(DeviceAPI *deviceAPI);
class MsgSaveReplay : public Message {
MESSAGE_CLASS_DECLARATION

public:
QString getFilename() const { return m_filename; }

static MsgSaveReplay* create(const QString& filename) {
return new MsgSaveReplay(filename);
}

protected:
QString m_filename;

MsgSaveReplay(const QString& filename) :
Message(),
m_filename(filename)
{ }
};

LimeSDRInput(DeviceAPI *deviceAPI);
virtual ~LimeSDRInput();
virtual void destroy();

Expand Down Expand Up @@ -280,6 +300,7 @@ class LimeSDRInput : public DeviceSampleSource
lms_stream_t m_streamId;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
ReplayBuffer<qint16> m_replayBuffer;

bool openDevice();
void closeDevice();
Expand Down
110 changes: 110 additions & 0 deletions plugins/samplesource/limesdrinput/limesdrinputgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,10 @@ void LimeSDRInputGUI::displaySettings()
setNCODisplay();

ui->ncoEnable->setChecked(m_settings.m_ncoEnable);
displayReplayLength();
displayReplayOffset();
displayReplayStep();
ui->replayLoop->setChecked(m_settings.m_replayLoop);
}

void LimeSDRInputGUI::setNCODisplay()
Expand Down Expand Up @@ -805,6 +809,9 @@ void LimeSDRInputGUI::openDeviceSettingsDialog(const QPoint& p)
if (m_contextMenuType == ContextMenuDeviceSettings)
{
BasicDeviceSettingsDialog dialog(this);
dialog.setReplayBytesPerSecond(m_settings.m_devSampleRate * 2 * sizeof(qint16));
dialog.setReplayLength(m_settings.m_replayLength);
dialog.setReplayStep(m_settings.m_replayStep);
dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress);
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
Expand All @@ -818,17 +825,114 @@ void LimeSDRInputGUI::openDeviceSettingsDialog(const QPoint& p)
m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress();
m_settings.m_reverseAPIPort = dialog.getReverseAPIPort();
m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex();
m_settings.m_replayLength = dialog.getReplayLength();
m_settings.m_replayStep = dialog.getReplayStep();
displayReplayLength();
displayReplayOffset();
displayReplayStep();
m_settingsKeys.append("useReverseAPI");
m_settingsKeys.append("reverseAPIAddress");
m_settingsKeys.append("reverseAPIPort");
m_settingsKeys.append("reverseAPIDeviceIndex");
m_settingsKeys.append("replayLength");
m_settingsKeys.append("replayStep");

sendSettings();
}

resetContextMenuType();
}

void LimeSDRInputGUI::displayReplayLength()
{
bool replayEnabled = m_settings.m_replayLength > 0.0f;
if (!replayEnabled) {
ui->replayOffset->setMaximum(0);
} else {
ui->replayOffset->setMaximum(m_settings.m_replayLength * 10 - 1);
}
ui->replayLabel->setEnabled(replayEnabled);
ui->replayOffset->setEnabled(replayEnabled);
ui->replayOffsetText->setEnabled(replayEnabled);
ui->replaySave->setEnabled(replayEnabled);
}

void LimeSDRInputGUI::displayReplayOffset()
{
bool replayEnabled = m_settings.m_replayLength > 0.0f;
ui->replayOffset->setValue(m_settings.m_replayOffset * 10);
ui->replayOffsetText->setText(QString("%1s").arg(m_settings.m_replayOffset, 0, 'f', 1));
ui->replayNow->setEnabled(replayEnabled && (m_settings.m_replayOffset > 0.0f));
ui->replayPlus->setEnabled(replayEnabled && (std::round(m_settings.m_replayOffset * 10) < ui->replayOffset->maximum()));
ui->replayMinus->setEnabled(replayEnabled && (m_settings.m_replayOffset > 0.0f));
}

void LimeSDRInputGUI::displayReplayStep()
{
QString step;
float intpart;
float frac = modf(m_settings.m_replayStep, &intpart);
if (frac == 0.0f) {
step = QString::number((int)intpart);
} else {
step = QString::number(m_settings.m_replayStep, 'f', 1);
}
ui->replayPlus->setText(QString("+%1s").arg(step));
ui->replayPlus->setToolTip(QString("Add %1 seconds to time delay").arg(step));
ui->replayMinus->setText(QString("-%1s").arg(step));
ui->replayMinus->setToolTip(QString("Remove %1 seconds from time delay").arg(step));
}

void LimeSDRInputGUI::on_replayOffset_valueChanged(int value)
{
m_settings.m_replayOffset = value / 10.0f;
displayReplayOffset();
m_settingsKeys.append("replayOffset");
sendSettings();
}

void LimeSDRInputGUI::on_replayNow_clicked()
{
ui->replayOffset->setValue(0);
}

void LimeSDRInputGUI::on_replayPlus_clicked()
{
ui->replayOffset->setValue(ui->replayOffset->value() + m_settings.m_replayStep * 10);
}

void LimeSDRInputGUI::on_replayMinus_clicked()
{
ui->replayOffset->setValue(ui->replayOffset->value() - m_settings.m_replayStep * 10);
}

void LimeSDRInputGUI::on_replaySave_clicked()
{
QFileDialog fileDialog(nullptr, "Select file to save IQ data to", "", "*.wav");
fileDialog.setAcceptMode(QFileDialog::AcceptSave);
if (fileDialog.exec())
{
QStringList fileNames = fileDialog.selectedFiles();
if (fileNames.size() > 0)
{
LimeSDRInput::MsgSaveReplay *message = LimeSDRInput::MsgSaveReplay::create(fileNames[0]);
m_limeSDRInput->getInputMessageQueue()->push(message);
}
}
}

void LimeSDRInputGUI::on_replayLoop_toggled(bool checked)
{
m_settings.m_replayLoop = checked;
m_settingsKeys.append("replayLoop");
sendSettings();
}

void LimeSDRInputGUI::setReplayTime(float time)
{
ui->replayOffset->setValue(std::ceil(time * 10.0f));
}

void LimeSDRInputGUI::makeUIConnections()
{
QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &LimeSDRInputGUI::on_startStop_toggled);
Expand All @@ -852,4 +956,10 @@ void LimeSDRInputGUI::makeUIConnections()
QObject::connect(ui->extClock, &ExternalClockButton::clicked, this, &LimeSDRInputGUI::on_extClock_clicked);
QObject::connect(ui->transverter, &TransverterButton::clicked, this, &LimeSDRInputGUI::on_transverter_clicked);
QObject::connect(ui->sampleRateMode, &QToolButton::toggled, this, &LimeSDRInputGUI::on_sampleRateMode_toggled);
QObject::connect(ui->replayOffset, &QSlider::valueChanged, this, &LimeSDRInputGUI::on_replayOffset_valueChanged);
QObject::connect(ui->replayNow, &QToolButton::clicked, this, &LimeSDRInputGUI::on_replayNow_clicked);
QObject::connect(ui->replayPlus, &QToolButton::clicked, this, &LimeSDRInputGUI::on_replayPlus_clicked);
QObject::connect(ui->replayMinus, &QToolButton::clicked, this, &LimeSDRInputGUI::on_replayMinus_clicked);
QObject::connect(ui->replaySave, &QToolButton::clicked, this, &LimeSDRInputGUI::on_replaySave_clicked);
QObject::connect(ui->replayLoop, &ButtonSwitch::toggled, this, &LimeSDRInputGUI::on_replayLoop_toggled);
}
Loading

0 comments on commit cb97263

Please sign in to comment.