diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt
index 925e1c481..5504cfc6e 100644
--- a/sdrbase/CMakeLists.txt
+++ b/sdrbase/CMakeLists.txt
@@ -50,6 +50,9 @@ endif(LIBSERIALDV_FOUND)
set(sdrbase_SOURCES
${sdrbase_SOURCES}
+ ambe/ambeengine.cpp
+ ambe/ambeworker.cpp
+
audio/audiocompressor.cpp
audio/audiocompressorsnd.cpp
audio/audiodevicemanager.cpp
@@ -152,6 +155,9 @@ set(sdrbase_SOURCES
set(sdrbase_HEADERS
${sdrbase_HEADERS}
+ ambe/ambeengine.h
+ ambe/ambeworker.h
+
audio/audiocompressor.h
audio/audiocompressorsnd.h
audio/audiodevicemanager.h
diff --git a/sdrbase/ambe/ambeengine.cpp b/sdrbase/ambe/ambeengine.cpp
new file mode 100644
index 000000000..b5b6db954
--- /dev/null
+++ b/sdrbase/ambe/ambeengine.cpp
@@ -0,0 +1,223 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2019 F4EXB //
+// written by Edouard Griffiths //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation as version 3 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include
+#include
+
+#ifndef _MSC_VER
+#include
+#include
+#include
+#endif
+
+#ifndef __WINDOWS__
+#include
+#include
+#ifndef __APPLE__
+#include
+#endif
+#endif
+
+#include
+
+#include "ambeworker.h"
+#include "ambeengine.h"
+
+AMBEEngine::AMBEEngine()
+{}
+
+AMBEEngine::~AMBEEngine()
+{}
+
+#ifdef __WINDOWS__
+void DVSerialEngine::getComList()
+{
+ m_comList.clear();
+ m_comList8250.clear();
+ char comCStr[16];
+
+ // Arbitrarily set the list to the 20 first COM ports
+ for (int i = 1; i <= 20; i++)
+ {
+ sprintf(comCStr, "COM%d", i);
+ m_comList.push_back(std::string(comCStr));
+ }
+}
+#else
+void AMBEEngine::getComList()
+{
+ int n;
+ struct dirent **namelist;
+ m_comList.clear();
+ m_comList8250.clear();
+ const char* sysdir = "/sys/class/tty/";
+
+ // Scan through /sys/class/tty - it contains all tty-devices in the system
+ n = scandir(sysdir, &namelist, NULL, alphasort);
+ if (n < 0)
+ {
+ perror("scandir");
+ }
+ else
+ {
+ while (n--)
+ {
+ if (strcmp(namelist[n]->d_name, "..") && strcmp(namelist[n]->d_name, "."))
+ {
+ // Construct full absolute file path
+ std::string devicedir = sysdir;
+ devicedir += namelist[n]->d_name;
+ // Register the device
+ register_comport(m_comList, m_comList8250, devicedir);
+ }
+
+ free(namelist[n]);
+ }
+
+ free(namelist);
+ }
+
+ // Only non-serial8250 has been added to comList without any further testing
+ // serial8250-devices must be probe to check for validity
+ probe_serial8250_comports(m_comList, m_comList8250);
+}
+#endif // not Windows
+
+#ifndef __WINDOWS__
+void AMBEEngine::register_comport(
+ std::list& comList,
+ std::list& comList8250,
+ const std::string& dir)
+{
+ // Get the driver the device is using
+ std::string driver = get_driver(dir);
+
+ // Skip devices without a driver
+ if (driver.size() > 0)
+ {
+ //std::cerr << "register_comport: dir: "<< dir << " driver: " << driver << std::endl;
+ std::string devfile = std::string("/dev/") + basename((char *) dir.c_str());
+
+ // Put serial8250-devices in a seperate list
+ if (driver == "serial8250") {
+ comList8250.push_back(devfile);
+ } else {
+ comList.push_back(devfile);
+ }
+ }
+}
+
+void AMBEEngine::probe_serial8250_comports(
+ std::list& comList,
+ std::list comList8250)
+{
+ struct serial_struct serinfo;
+ std::list::iterator it = comList8250.begin();
+
+ // Iterate over all serial8250-devices
+ while (it != comList8250.end())
+ {
+
+ // Try to open the device
+ int fd = open((*it).c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY);
+
+ if (fd >= 0)
+ {
+ // Get serial_info
+ if (ioctl(fd, TIOCGSERIAL, &serinfo) == 0)
+ {
+ // If device type is no PORT_UNKNOWN we accept the port
+ if (serinfo.type != PORT_UNKNOWN) {
+ comList.push_back(*it);
+ }
+ }
+
+ close(fd);
+ }
+ it++;
+ }
+}
+
+std::string AMBEEngine::get_driver(const std::string& tty)
+{
+ struct stat st;
+ std::string devicedir = tty;
+ // Append '/device' to the tty-path
+ devicedir += "/device";
+
+ // Stat the devicedir and handle it if it is a symlink
+ if (lstat(devicedir.c_str(), &st) == 0 && S_ISLNK(st.st_mode))
+ {
+ char buffer[1024];
+ memset(buffer, 0, sizeof(buffer));
+ // Append '/driver' and return basename of the target
+ devicedir += "/driver";
+
+ if (readlink(devicedir.c_str(), buffer, sizeof(buffer)) > 0) {
+ return basename(buffer);
+ }
+ }
+
+ return "";
+}
+#endif // not Windows
+
+bool AMBEEngine::scan(std::vector& ambeDevices)
+{
+ getComList();
+ std::list::iterator it = m_comList.begin();
+ ambeDevices.clear();
+
+ while (it != m_comList.end())
+ {
+ AMBEWorker *worker = new AMBEWorker();
+ qDebug("AMBEEngine::scan: com: %s", it->c_str());
+ if (worker->open(*it))
+ {
+ ambeDevices.push_back(*it);
+ worker->close();
+ }
+
+ delete worker;
+ ++it;
+ }
+}
+
+bool AMBEEngine::registerController(const std::string& ambeRef)
+{
+ AMBEWorker *worker = new AMBEWorker();
+
+ if (worker->open(ambeRef))
+ {
+ m_controllers.push_back(AMBEController());
+ m_controllers.back().worker = worker;
+ m_controllers.back().thread = new QThread();
+ m_controllers.back().device = ambeRef;
+
+ m_controllers.back().worker->moveToThread(m_controllers.back().thread);
+ connect(m_controllers.back().worker, SIGNAL(finished()), m_controllers.back().thread, SLOT(quit()));
+ connect(m_controllers.back().worker, SIGNAL(finished()), m_controllers.back().worker, SLOT(deleteLater()));
+ connect(m_controllers.back().thread, SIGNAL(finished()), m_controllers.back().thread, SLOT(deleteLater()));
+ connect(&m_controllers.back().worker->m_inputMessageQueue, SIGNAL(messageEnqueued()), m_controllers.back().worker, SLOT(handleInputMessages()));
+ m_controllers.back().thread->start();
+
+ return true;
+ }
+
+ return false;
+}
\ No newline at end of file
diff --git a/sdrbase/ambe/ambeengine.h b/sdrbase/ambe/ambeengine.h
new file mode 100644
index 000000000..35c193b7b
--- /dev/null
+++ b/sdrbase/ambe/ambeengine.h
@@ -0,0 +1,68 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2019 F4EXB //
+// written by Edouard Griffiths //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation as version 3 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef SDRBASE_AMBE_AMBEENGINE_H_
+#define SDRBASE_AMBE_AMBEENGINE_H_
+
+#include
+#include
+#include
+#include
+#include
+
+#include "export.h"
+
+class QThread;
+class AMBEWorker;
+
+class SDRBASE_API AMBEEngine : public QObject
+{
+ Q_OBJECT
+public:
+ AMBEEngine();
+ ~AMBEEngine();
+
+ bool scan(std::vector& ambeDevices);
+ void getDevicesNames(std::vector& devicesNames);
+ bool registerController(const std::string& ambeRef);
+
+private:
+ struct AMBEController
+ {
+ QThread *thread;
+ AMBEWorker *worker;
+ std::string device;
+ };
+
+#ifndef __WINDOWS__
+ static std::string get_driver(const std::string& tty);
+ static void register_comport(std::list& comList, std::list& comList8250, const std::string& dir);
+ static void probe_serial8250_comports(std::list& comList, std::list comList8250);
+#endif
+ void getComList();
+
+ std::list m_comList;
+ std::list m_comList8250;
+ std::vector m_ambeSerial;
+ std::vector m_controllers;
+ QMutex m_mutex;
+};
+
+
+
+#endif /* SDRBASE_AMBE_AMBEENGINE_H_ */
diff --git a/sdrbase/ambe/ambeworker.cpp b/sdrbase/ambe/ambeworker.cpp
new file mode 100644
index 000000000..07b84fe7a
--- /dev/null
+++ b/sdrbase/ambe/ambeworker.cpp
@@ -0,0 +1,35 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2019 F4EXB //
+// written by Edouard Griffiths //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation as version 3 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include "ambeworker.h"
+
+AMBEWorker::AMBEWorker()
+{}
+
+AMBEWorker::~AMBEWorker()
+{}
+
+bool AMBEWorker::open(const std::string& serialDevice)
+{
+ return m_dvController.open(serialDevice);
+}
+
+void AMBEWorker::close()
+{
+ m_dvController.close();
+}
diff --git a/sdrbase/ambe/ambeworker.h b/sdrbase/ambe/ambeworker.h
new file mode 100644
index 000000000..7327030a2
--- /dev/null
+++ b/sdrbase/ambe/ambeworker.h
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2019 F4EXB //
+// written by Edouard Griffiths //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation as version 3 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef SDRBASE_AMBE_AMBEWORKER_H_
+#define SDRBASE_AMBE_AMBEWORKER_H_
+
+#include
+
+#include "util/messagequeue.h"
+#include "export.h"
+#include "dvcontroller.h"
+
+class SDRBASE_API AMBEWorker : public QObject {
+ Q_OBJECT
+public:
+ AMBEWorker();
+ ~AMBEWorker();
+
+ bool open(const std::string& serialDevice);
+ void close();
+
+ MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
+
+private:
+ SerialDV::DVController m_dvController;
+};
+
+#endif // SDRBASE_AMBE_AMBEWORKER_H_
diff --git a/sdrbench/mainbench.cpp b/sdrbench/mainbench.cpp
index 931f8fb9a..927ab91ab 100644
--- a/sdrbench/mainbench.cpp
+++ b/sdrbench/mainbench.cpp
@@ -20,6 +20,8 @@
#include
#include
+#include "ambe/ambeengine.h"
+
#include "mainbench.h"
MainBench *MainBench::m_instance = 0;
@@ -60,6 +62,8 @@ void MainBench::run()
testDecimateFI();
} else if (m_parser.getTestType() == ParserBench::TestDecimatorsFF) {
testDecimateFF();
+ } else if (m_parser.getTestType() == ParserBench::TestAMBE) {
+ testAMBE();
} else {
qDebug() << "MainBench::run: unknown test type: " << m_parser.getTestType();
}
@@ -191,6 +195,18 @@ void MainBench::testDecimateFF()
delete[] buf;
}
+void MainBench::testAMBE()
+{
+ qDebug() << "MainBench::testAMBE";
+ AMBEEngine ambeEngine;
+ std::vector ambeDevices;
+ ambeEngine.scan(ambeDevices);
+
+ for (std::vector::const_iterator it = ambeDevices.begin(); it != ambeDevices.end(); ++it) {
+ qDebug("MainBench::testAMBE: detected AMBE device %s", it->c_str());
+ }
+}
+
void MainBench::decimateII(const qint16* buf, int len)
{
SampleVector::iterator it = m_convertBuffer.begin();
diff --git a/sdrbench/mainbench.h b/sdrbench/mainbench.h
index 8411b0a51..b5e9551f0 100644
--- a/sdrbench/mainbench.h
+++ b/sdrbench/mainbench.h
@@ -52,6 +52,7 @@ private:
void testDecimateIF();
void testDecimateFI();
void testDecimateFF();
+ void testAMBE();
void decimateII(const qint16 *buf, int len);
void decimateInfII(const qint16 *buf, int len);
void decimateSupII(const qint16 *buf, int len);
diff --git a/sdrbench/parserbench.cpp b/sdrbench/parserbench.cpp
index dc32ce61f..830fd5e56 100644
--- a/sdrbench/parserbench.cpp
+++ b/sdrbench/parserbench.cpp
@@ -125,6 +125,8 @@ ParserBench::TestType ParserBench::getTestType() const
return TestDecimatorsInfII;
} else if (m_testStr == "decimatesupii") {
return TestDecimatorsSupII;
+ } else if (m_testStr == "ambe") {
+ return TestAMBE;
} else {
return TestDecimatorsII;
}
diff --git a/sdrbench/parserbench.h b/sdrbench/parserbench.h
index 9454614d2..013578382 100644
--- a/sdrbench/parserbench.h
+++ b/sdrbench/parserbench.h
@@ -32,7 +32,8 @@ public:
TestDecimatorsFI,
TestDecimatorsFF,
TestDecimatorsInfII,
- TestDecimatorsSupII
+ TestDecimatorsSupII,
+ TestAMBE
} TestType;
ParserBench();