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();