Much improved USB handling for Android, Add MMDVM_DIRECT as a settings option to allow host combo to be used for M17 destination on TX

main
Doug McLain 1 year ago
parent 2f695e63eb
commit c23865d1c9

@ -2,7 +2,7 @@ QT += quick quickcontrols2 network multimedia
equals(QT_MAJOR_VERSION, 5){
android:QT += androidextras
}
}
unix:!ios:QT += serialport
CONFIG += c++11
@ -34,6 +34,7 @@ ios:QMAKE_INFO_PLIST = Info.plist
VERSION_BUILD='$(shell cd $$PWD;git rev-parse --short HEAD)'
DEFINES += VERSION_NUMBER=\"\\\"$${VERSION_BUILD}\\\"\"
DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DEBUG_PLUGINS=1
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
DEFINES += VOCODER_PLUGIN
#DEFINES += USE_FLITE

@ -180,7 +180,6 @@ Item {
}
onCurrentTextChanged: {
droidstar.set_slot(_comboSlot.currentIndex);
}
visible: false
}
@ -262,6 +261,7 @@ Item {
droidstar.set_modemP25TxLevel(settingsTab.modemYSFTXLevelEdit.text);
droidstar.set_modemNXDNTxLevel(settingsTab.modemNXDNTXLevelEdit.text);
droidstar.set_modemBaud(settingsTab.modemBaudEdit.text);
//droidstar.set_mmdvm_direct(settingsTab.mmdvmBox.checked)
droidstar.process_connect();
}
}
@ -282,7 +282,10 @@ Item {
color: _comboHost.enabled ? "white" : "darkgrey"
}
onCurrentTextChanged: {
if(!droidstar.get_modelchange()){
if(settingsTab.mmdvmBox.checked){
droidstar.set_dst(_comboHost.currentText);
}
else if(!droidstar.get_modelchange()){
droidstar.process_host_change(_comboHost.currentText);
}
}
@ -296,7 +299,7 @@ Item {
font.pixelSize: parent.height / 35
currentIndex: -1
displayText: currentIndex === -1 ? "Mod..." : currentText
model: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
model: [" ", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
contentItem: Text {
text: _comboModule.displayText
font: _comboModule.font
@ -406,12 +409,11 @@ Item {
droidstar.set_modemM17CAN(_comboM17CAN.currentText);
}
}
CheckBox {
id: _swtxBox
x: (parent.width * 2 / 5) + 5
y: (parent.height / rows + 1) * 2;
width: parent.width / 4
width: parent.width / 4
height: parent.height / rows
font.pixelSize: parent.height / 40;
text: qsTr("SWTX")

@ -70,13 +70,14 @@ Item {
property alias modemP25TXLevelEdit: _modemP25TXLevelEdit
property alias modemNXDNTXLevelEdit: _modemNXDNTXLevelEdit
property alias modemBaudEdit: _modemBaudEdit
property alias mmdvmBox: _mmdvmBox
Flickable {
id: flickable
anchors.fill: parent
contentWidth: parent.width
contentHeight: _modemBaudLabel.y +
_modemBaudLabel.height + 10
contentHeight: _mmdvmBox.y +
_mmdvmBox.height + 10
flickableDirection: Flickable.VerticalFlick
clip: true
ScrollBar.vertical: ScrollBar {}
@ -1067,5 +1068,16 @@ Item {
selectByMouse: true
inputMethodHints: "ImhPreferNumbers"
}
CheckBox {
id: _mmdvmBox
x: 10
y: 1360
width: parent.width
height: 25
text: qsTr("MMDVM_DIRECT")
onClicked:{
droidstar.set_mmdvm_direct(_mmdvmBox.checked)
}
}
}
}

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<manifest package="org.dudetronics.droidstar" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="71" android:installLocation="auto">
<manifest package="org.dudetronics.droidstar" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="73" android:installLocation="auto">
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.

@ -16,9 +16,12 @@
*/
package DroidStar;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.app.PendingIntent;
import android.content.Context;
import android.hardware.usb.UsbManager;
@ -43,14 +46,37 @@ public class USBSerialWrapper implements SerialInputOutputManagerTest.Listener {
UsbSerialPort m_port;
SerialInputOutputManagerTest usbIoManager;
private static final String ACTION_USB_PERMISSION = "org.dudetronics.droidstar.USB_PERMISSION";
//private final ArrayBlockingQueue<PendingUsbPermission> queuedPermissions = new ArrayBlockingQueue<>(100);
//private volatile boolean processingPermission = false;
//private PendingUsbPermission currentPendingPermission;
IntentFilter m_filter = new IntentFilter(ACTION_USB_PERMISSION);
UsbManager m_manager;
UsbSerialDriver m_driver;
public BroadcastReceiver m_usbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
System.out.println("BroadcastReceiver() onReceive() action == " + action);
if (ACTION_USB_PERMISSION.equals(action)) {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
System.out.println("USB Permission Granted");
if(open_device() > 0) device_open();
}
else {
System.out.println("USB Permission Denied");
}
}
if ( (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) || (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) ) {
devices_changed();
System.out.println("USB devices changed");
}
}
};
public USBSerialWrapper() {
this.id = counter;
System.out.println("Created USBSerialWrapper object with id: " + this.id);
counter++;
m_filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
m_filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
}
public void set_port_name(String d)
@ -98,8 +124,8 @@ public class USBSerialWrapper implements SerialInputOutputManagerTest.Listener {
public String[] discover_devices(Context c)
{
System.out.println("Java: discover_devices()");
UsbManager manager = (UsbManager) c.getSystemService(Context.USB_SERVICE);
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
m_manager = (UsbManager) c.getSystemService(Context.USB_SERVICE);
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(m_manager);
String[] devices = new String[availableDrivers.size()];
if (availableDrivers.isEmpty()) {
@ -116,6 +142,7 @@ public class USBSerialWrapper implements SerialInputOutputManagerTest.Listener {
System.out.println("USB device getVendorId() == " + availableDrivers.get(i).getDevice().getVendorId());
}
}
c.registerReceiver(m_usbReceiver, m_filter);
return devices;
}
@ -123,8 +150,7 @@ public class USBSerialWrapper implements SerialInputOutputManagerTest.Listener {
{
m_context = c;
int devicenum = 0;
UsbManager manager = (UsbManager) m_context.getSystemService(Context.USB_SERVICE);
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(m_manager);
if (availableDrivers.isEmpty()) {
System.out.println("No drivers found");
@ -138,7 +164,6 @@ public class USBSerialWrapper implements SerialInputOutputManagerTest.Listener {
System.out.println("USB device getProductId() == " + availableDrivers.get(i).getDevice().getProductId());
System.out.println("USB device getVendorId() == " + availableDrivers.get(i).getDevice().getVendorId());
//if((availableDrivers.get(i).getDevice().getDeviceName()) == m_devicename){
if(m_devicename.equals(availableDrivers.get(i).getDevice().getDeviceName())){
devicenum = i;
System.out.println("Found device == " + devicenum);
@ -147,18 +172,21 @@ public class USBSerialWrapper implements SerialInputOutputManagerTest.Listener {
}
}
UsbSerialDriver driver = availableDrivers.get(devicenum);
UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
m_driver = availableDrivers.get(devicenum);
PendingIntent mPendingIntent = PendingIntent.getBroadcast(c, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_MUTABLE);
m_manager.requestPermission(m_driver.getDevice(), mPendingIntent);
return "Yipee!";
}
public int open_device()
{
UsbDeviceConnection connection = m_manager.openDevice(m_driver.getDevice());
if (connection == null) {
// add UsbManager.requestPermission(driver.getDevice(), ..) handling here
PendingIntent mPendingIntent = PendingIntent.getBroadcast(c, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_MUTABLE);
manager.requestPermission(driver.getDevice(), mPendingIntent);
return "No connection, need permission?";
return 0;
}
m_port = driver.getPorts().get(0); // Most devices have just one port (port 0)
m_port = m_driver.getPorts().get(0); // Most devices have just one port (port 0)
try {
m_port.open(connection);
@ -173,8 +201,7 @@ public class USBSerialWrapper implements SerialInputOutputManagerTest.Listener {
usbIoManager = new SerialInputOutputManagerTest(m_port, this);
usbIoManager.start();
return "Yipee!";
return 1;
}
public void write(byte[] data)
@ -201,6 +228,19 @@ public class USBSerialWrapper implements SerialInputOutputManagerTest.Listener {
return returnbytes;
}
public void close(int c)
{
if(usbIoManager != null) {
usbIoManager.setListener(null);
usbIoManager.stop();
}
usbIoManager = null;
try {
m_port.close();
} catch (IOException ignored) {}
m_port = null;
}
@Override
public void onNewData(byte[] data) {
data_received(data);
@ -212,4 +252,6 @@ public class USBSerialWrapper implements SerialInputOutputManagerTest.Listener {
}
private static native void data_received(byte[] data);
private static native void device_open();
private static native void devices_changed();
}

@ -19,13 +19,13 @@
#ifdef Q_OS_ANDROID
AndroidSerialPort::AndroidSerialPort(QObject * parent)
AndroidSerialPort::AndroidSerialPort(QObject *)
{
if(QAndroidJniObject::isClassAvailable("com.hoho.android.usbserial.driver/UsbSerialDriver")) {
qDebug() << "com.hoho.android.usbserial.driver/UsbSerialDriver available";
serialJavaObject = QAndroidJniObject("DroidStar/USBSerialWrapper");
QAndroidJniEnvironment env;
JNINativeMethod methods[] = { {"data_received", "([B)V", reinterpret_cast<void*>(java_data_received)} };
QAndroidJniEnvironment env;
JNINativeMethod methods[] = { {"data_received", "([B)V", reinterpret_cast<void*>(java_data_received)}, {"device_open", "()V", reinterpret_cast<void*>(java_device_open)}, {"devices_changed", "()V", reinterpret_cast<void*>(java_devices_changed)}};
jclass objectClass = env->GetObjectClass(serialJavaObject.object<jobject>());
env->RegisterNatives(objectClass, methods, sizeof(methods) / sizeof(methods[0]));
env->DeleteLocalRef(objectClass);
@ -59,13 +59,19 @@ QStringList AndroidSerialPort::discover_devices()
int AndroidSerialPort::open(int p)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
qDebug() << serialJavaObject.callObjectMethod("setup_serial", "(Landroid/content/Context;)Ljava/lang/String;", QtAndroid::androidContext().object()).toString();
QString s = serialJavaObject.callObjectMethod("setup_serial", "(Landroid/content/Context;)Ljava/lang/String;", QtAndroid::androidContext().object()).toString();
qDebug() << s;
#else
serialJavaObject.callObjectMethod("setup_serial", "(Landroid/content/Context;)Ljava/lang/String;", QNativeInterface::QAndroidApplication::context());
#endif
return p;
}
void AndroidSerialPort::close()
{
serialJavaObject.callMethod<void>("close", "(I)V", 1);
}
int AndroidSerialPort::write(char *data, int s)
{
QAndroidJniEnvironment env;
@ -141,4 +147,13 @@ void AndroidSerialPort::java_data_received(JNIEnv *env, jobject t, jbyteArray da
emit AndroidSerialPort::GetInstance().data_received(r);
}
void AndroidSerialPort::java_device_open(JNIEnv *, jobject)
{
emit AndroidSerialPort::GetInstance().device_ready();
}
void AndroidSerialPort::java_devices_changed(JNIEnv *, jobject)
{
emit AndroidSerialPort::GetInstance().devices_changed();
}
#endif

@ -40,7 +40,7 @@ public:
QStringList discover_devices();
int open(int);
void close(){}
void close();
void setPortName(QString);
void setBaudRate(int);
void setDataBits(int);
@ -53,9 +53,13 @@ public:
signals:
void readyRead();
void data_received(QByteArray);
void device_ready();
void devices_changed();
private:
explicit AndroidSerialPort(QObject * parent = nullptr);
static void java_data_received(JNIEnv *env, jobject t, jbyteArray data);
static void java_device_open(JNIEnv *env, jobject t);
static void java_devices_changed(JNIEnv *env, jobject t);
#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
QAndroidJniObject serialJavaObject;
#else

@ -24,6 +24,7 @@
DCS::DCS()
{
m_mode = "DCS";
m_attenuation = 5;
}
@ -61,31 +62,6 @@ void DCS::process_udp()
qDebug() << "Connected to DCS";
m_modeinfo.status = CONNECTED_RW;
m_modeinfo.sw_vocoder_loaded = load_vocoder_plugin();
if(m_vocoder != ""){
m_hwrx = true;
m_hwtx = true;
m_modeinfo.hw_vocoder_loaded = true;
#if !defined(Q_OS_IOS)
m_ambedev = new SerialAMBE("DCS");
m_ambedev->connect_to_serial(m_vocoder);
connect(m_ambedev, SIGNAL(connected(bool)), this, SLOT(ambe_connect_status(bool)));
connect(m_ambedev, SIGNAL(data_ready()), this, SLOT(get_ambe()));
#endif
}
else{
m_hwrx = false;
m_hwtx = false;
}
if(m_modemport != ""){
#if !defined(Q_OS_IOS)
m_modem = new SerialModem("DCS");
m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex);
m_modem->set_modem_params(m_baud, m_rxfreq, m_txfreq, m_txDelay, m_rxLevel, m_rfLevel, m_ysfTXHang, m_cwIdTXLevel, m_dstarTXLevel, m_dmrTXLevel, m_ysfTXLevel, m_p25TXLevel, m_nxdnTXLevel, m_pocsagTXLevel, m_m17TXLevel);
m_modem->connect_to_serial(m_modemport);
connect(m_modem, SIGNAL(connected(bool)), this, SLOT(mmdvm_connect_status(bool)));
connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray)));
#endif
}
m_rxtimer = new QTimer();
connect(m_rxtimer, SIGNAL(timeout()), this, SLOT(process_rx_data()));
m_txtimer = new QTimer();

@ -24,7 +24,7 @@
#include "CRCenc.h"
#include "MMDVMDefines.h"
//#define DEBUG
#define DEBUG
const uint32_t ENCODING_TABLE_1676[] =
{0x0000U, 0x0273U, 0x04E5U, 0x0696U, 0x09C9U, 0x0BBAU, 0x0D2CU, 0x0F5FU, 0x11E2U, 0x1391U, 0x1507U, 0x1774U,
@ -43,6 +43,7 @@ DMR::DMR() :
m_txslot(2),
m_txcc(1)
{
m_mode = "DMR";
m_dmrcnt = 0;
m_flco = FLCO_GROUP;
m_attenuation = 5;
@ -304,31 +305,6 @@ void DMR::setup_connection()
m_ping_timer = new QTimer();
connect(m_ping_timer, SIGNAL(timeout()), this, SLOT(send_ping()));
m_ping_timer->start(5000);
if(m_vocoder != ""){
m_hwrx = true;
m_hwtx = true;
m_modeinfo.hw_vocoder_loaded = true;
#if !defined(Q_OS_IOS)
m_ambedev = new SerialAMBE("DMR");
m_ambedev->connect_to_serial(m_vocoder);
connect(m_ambedev, SIGNAL(connected(bool)), this, SLOT(ambe_connect_status(bool)));
connect(m_ambedev, SIGNAL(data_ready()), this, SLOT(get_ambe()));
#endif
}
else{
m_hwrx = false;
m_hwtx = false;
}
if(m_modemport != ""){
#if !defined(Q_OS_IOS)
m_modem = new SerialModem("DMR");
m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex);
m_modem->set_modem_params(m_baud, m_rxfreq, m_txfreq, m_txDelay, m_rxLevel, m_rfLevel, m_ysfTXHang, m_cwIdTXLevel, m_dstarTXLevel, m_dmrTXLevel, m_ysfTXLevel, m_p25TXLevel, m_nxdnTXLevel, m_pocsagTXLevel, m_m17TXLevel);
m_modem->connect_to_serial(m_modemport);
connect(m_modem, SIGNAL(connected(bool)), this, SLOT(mmdvm_connect_status(bool)));
connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray)));
#endif
}
m_audio = new AudioEngine(m_audioin, m_audioout);
m_audio->init();
}
@ -438,7 +414,7 @@ void DMR::process_modem_data(QByteArray d)
++m_dmrcnt;
}
#ifdef DEBUG
fprintf(stderr, "SEND:%d: ", txdata.size());
fprintf(stderr, "SEND:%lld: ", txdata.size());
for(int i = 0; i < txdata.size(); ++i){
fprintf(stderr, "%02x ", (uint8_t)txdata.data()[i]);
}
@ -558,7 +534,7 @@ void DMR::send_frame()
emit update_output_level(m_audio->level() * 8);
emit update(m_modeinfo);
#ifdef DEBUG
fprintf(stderr, "SEND:%d: ", txdata.size());
fprintf(stderr, "SEND:%lld: ", txdata.size());
for(int i = 0; i < txdata.size(); ++i){
fprintf(stderr, "%02x ", (uint8_t)txdata.data()[i]);
}
@ -576,7 +552,7 @@ uint8_t * DMR::get_eot()
void DMR::build_frame()
{
//qDebug() << "DMR: slot:cc == " << m_txslot << ":" << m_txcc;
qDebug() << "DMR: slot:cc == " << m_txslot << ":" << m_txcc;
m_dmrFrame[0U] = 'D';
m_dmrFrame[1U] = 'M';
m_dmrFrame[2U] = 'R';

@ -34,6 +34,7 @@
#include <QDir>
#include <QFont>
#include <QFontDatabase>
#include <cstring>
#include <stdio.h>
#include <fcntl.h>
#include <iostream>
@ -44,7 +45,8 @@ DroidStar::DroidStar(QObject *parent) :
m_essid(0),
m_dmr_destid(0),
m_outlevel(0),
m_tts(0)
m_mdirect(false),
m_tts(0)
{
qRegisterMetaType<Mode::MODEINFO>("Mode::MODEINFO");
m_settings_processed = false;
@ -57,6 +59,8 @@ DroidStar::DroidStar(QObject *parent) :
#endif
#if defined(Q_OS_ANDROID)
keepScreenOn();
m_USBmonitor = &AndroidSerialPort::GetInstance();
connect(m_USBmonitor, SIGNAL(devices_changed()), this, SLOT(discover_devices()));
#endif
check_host_files();
discover_devices();
@ -140,6 +144,7 @@ void DroidStar::discover_devices()
m_modems.append(i.value());
++i;
}
emit update_devices();
#endif
}
@ -255,7 +260,6 @@ void DroidStar::process_connect()
#ifdef Q_OS_IOS
MicPermission::check_permission();
#endif
if(m_protocol == "REF"){
m_refname = m_saved_refhost;
}
@ -282,7 +286,7 @@ void DroidStar::process_connect()
}
else if(m_protocol == "M17"){
m_refname = m_saved_m17host;
}
}
emit connect_status_changed(1);
connect_status = Mode::CONNECTING;
@ -292,7 +296,7 @@ void DroidStar::process_connect()
m_host = m_hostmap[m_refname];
sl = m_host.split(',');
if( (m_protocol == "M17") && (m_refname != "MMDVM_DIRECT") && (m_ipv6) && (sl.size() > 2) && (sl.at(2) != "none") ){
if( (m_protocol == "M17") && !m_mdirect && (m_ipv6) && (sl.size() > 2) && (sl.at(2) != "none") ){
m_host = sl.at(2).simplified();
m_port = sl.at(1).toInt();
}
@ -300,7 +304,7 @@ void DroidStar::process_connect()
m_host = sl.at(0).simplified();
m_port = sl.at(1).toInt();
}
else if( (m_protocol == "M17") && (m_refname == "MMDVM_DIRECT") ){
else if( (m_protocol == "M17") && m_mdirect ){
qDebug() << "Going MMDVM_DIRECT";
}
else{
@ -340,14 +344,14 @@ void DroidStar::process_connect()
m_mode = Mode::create_mode(m_protocol);
m_modethread = new QThread;
m_mode->moveToThread(m_modethread);
m_mode->init(m_callsign, m_dmrid, nxdnid, m_module, m_refname, m_host, m_port, m_ipv6, vocoder, modem, m_capture, m_playback);
m_mode->init(m_callsign, m_dmrid, nxdnid, m_module, m_refname, m_host, m_port, m_ipv6, vocoder, modem, m_capture, m_playback, m_mdirect);
m_mode->set_modem_flags(rxInvert, txInvert, pttInvert, useCOSAsLockout, duplex);
m_mode->set_modem_params(m_modemBaud.toUInt(), rxfreq, txfreq, m_modemTxDelay.toInt(), m_modemRxLevel.toFloat(), m_modemRFLevel.toFloat(), ysfTXHang, m_modemCWIdTxLevel.toFloat(), m_modemDstarTxLevel.toFloat(), m_modemDMRTxLevel.toFloat(), m_modemYSFTxLevel.toFloat(), m_modemP25TxLevel.toFloat(), m_modemNXDNTxLevel.toFloat(), pocsagTXLevel, m17TXLevel);
connect(this, SIGNAL(module_changed(char)), m_mode, SLOT(module_changed(char)));
connect(m_mode, SIGNAL(update(Mode::MODEINFO)), this, SLOT(update_data(Mode::MODEINFO)));
connect(m_mode, SIGNAL(update_output_level(unsigned short)), this, SLOT(update_output_level(unsigned short)));
connect(m_modethread, SIGNAL(started()), m_mode, SLOT(send_connect()));
connect(m_modethread, SIGNAL(started()), m_mode, SLOT(begin_connect()));
connect(m_modethread, SIGNAL(finished()), m_mode, SLOT(deleteLater()));
connect(this, SIGNAL(input_source_changed(int,QString)), m_mode, SLOT(input_src_changed(int,QString)));
connect(this, SIGNAL(swrx_state_changed(int)), m_mode, SLOT(swrx_state_changed(int)));
@ -394,6 +398,9 @@ void DroidStar::process_connect()
if(m_protocol == "M17"){
connect(this, SIGNAL(m17_rate_changed(int)), m_mode, SLOT(rate_changed(int)));
connect(this, SIGNAL(m17_can_changed(int)), m_mode, SLOT(can_changed(int)));
if(m_mdirect){
connect(this, SIGNAL(dst_changed(QString)), m_mode, SLOT(dst_changed(QString)));
}
}
if(m_protocol == "IAX"){
@ -1031,7 +1038,6 @@ void DroidStar::process_m17_hosts()
{
m_hostmap.clear();
m_hostsmodel.clear();
m_hostmap["MMDVM_DIRECT"] = "MMDVM_DIRECT";
QFileInfo check_file(config_path + "/M17Hosts-full.csv");
if(check_file.exists() && check_file.isFile()){
@ -1056,7 +1062,12 @@ void DroidStar::process_m17_hosts()
m_hostmap[line.at(1).simplified()] = line.at(2).simplified() + "," + line.at(3).simplified();
}
}
if(m_mdirect){
m_hostmap["ALL"] = "ALL";
m_hostmap["UNLINK"] = "UNLINK";
m_hostmap["ECHO"] = "ECHO";
m_hostmap["INFO"] = "INFO";
}
QMap<QString, QString>::const_iterator i = m_hostmap.constBegin();
while (i != m_hostmap.constEnd()) {
m_hostsmodel.append(i.key());
@ -1392,7 +1403,7 @@ void DroidStar::update_data(Mode::MODEINFO info)
}
else if(m_protocol == "M17"){
m_data1 = info.src;
m_data2 = info.dst;
m_data2 = info.dst + " " + info.module;
m_data3 = info.type ? "3200 Voice" : "1600 V/D";
if(info.frame_number){
QString n = QString("%1").arg(info.frame_number, 4, 16, QChar('0'));

@ -60,6 +60,8 @@ signals:
void mycall_changed(QString);
void urcall_changed(QString);
void usrtxt_changed(QString);
void dst_changed(QString);
void update_devices();
public slots:
void set_callsign(const QString &callsign) { m_callsign = callsign.simplified(); save_settings(); }
void set_dmrtgid(const QString &dmrtgid) { m_dmr_destid = dmrtgid.simplified().toUInt(); save_settings(); }
@ -114,7 +116,9 @@ public slots:
void set_swtx(bool swtx) { emit swtx_state_changed(swtx); }
void set_swrx(bool swrx) { emit swrx_state_changed(swrx); }
void set_agc(bool agc) { emit agc_state_changed(agc); }
void set_mmdvm_direct(bool mmdvm) { m_mdirect = mmdvm; process_mode_change(m_protocol); }
void set_iaxport(const QString &port){ m_iaxport = port.simplified().toUInt(); save_settings(); }
void set_dst(QString dst){emit dst_changed(dst);}
void set_modemRxFreq(QString m) { m_modemRxFreq = m; save_settings(); }
void set_modemTxFreq(QString m) { m_modemTxFreq = m; save_settings(); }
@ -342,6 +346,7 @@ private:
QStringList m_modems;
QStringList m_playbacks;
QStringList m_captures;
bool m_mdirect;
int m_tts;
QString m_ttstxt;
@ -367,6 +372,9 @@ private:
bool m_modemTxInvert;
bool m_modemRxInvert;
bool m_modemPTTInvert;
#ifdef Q_OS_ANDROID
AndroidSerialPort *m_USBmonitor;
#endif
private slots:
#ifdef Q_OS_ANDROID

@ -59,7 +59,9 @@ void HttpManager::http_finished(QNetworkReply *reply)
QStringList l = m_filename.split('/');
m_filename = "/" + l.at(l.size() - 1);
}
QStringList l = m_filename.split('_');
qDebug() << "m_filename = " << m_filename;
if(l.at(0) != "vocoder") return;
QFile *hosts_file = new QFile(m_config_path + m_filename);
qDebug() << "m_config_path + m_filename = " << m_config_path + m_filename;
hosts_file->open(QIODevice::WriteOnly);

@ -93,6 +93,7 @@ M17::M17() :
#else
m_txcan = 0;
#endif
m_mode = "M17";
m_attenuation = 1;
}
@ -222,17 +223,6 @@ void M17::process_udp()
if((buf.size() == 4) && (::memcmp(buf.data(), "ACKN", 4U) == 0)){
if(m_modeinfo.status == CONNECTING){
m_modeinfo.status = CONNECTED_RW;
if(m_modemport != ""){
#if !defined(Q_OS_IOS)
m_modem = new SerialModem("M17");
m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex);
m_modem->set_modem_params(m_baud, m_rxfreq, m_txfreq, m_txDelay, m_rxLevel, m_rfLevel, m_ysfTXHang, m_cwIdTXLevel, m_dstarTXLevel, m_dmrTXLevel, m_ysfTXLevel, m_p25TXLevel, m_nxdnTXLevel, m_pocsagTXLevel, m_m17TXLevel);
m_modem->connect_to_serial(m_modemport);
connect(m_modem, SIGNAL(connected(bool)), this, SLOT(mmdvm_connect_status(bool)));
connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray)));
#endif
}
#ifndef USE_EXTERNAL_CODEC2
m_c2 = new CCodec2(true);
#endif
@ -362,16 +352,9 @@ void M17::hostname_lookup(QHostInfo i)
void M17::mmdvm_direct_connect()
{
if(m_modemport != ""){
#if !defined(Q_OS_IOS)
m_modem = new SerialModem("M17");
m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex);
m_modem->set_modem_params(m_baud, m_rxfreq, m_txfreq, m_txDelay, m_rxLevel, m_rfLevel, m_ysfTXHang, m_cwIdTXLevel, m_dstarTXLevel, m_dmrTXLevel, m_ysfTXLevel, m_p25TXLevel, m_nxdnTXLevel, m_pocsagTXLevel, m_m17TXLevel);
m_modem->connect_to_serial(m_modemport);
connect(m_modem, SIGNAL(connected(bool)), this, SLOT(mmdvm_connect_status(bool)));
connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray)));
#endif
if(m_modeinfo.status == CONNECTING){
m_modeinfo.status = CONNECTED_RW;
m_modeinfo.sw_vocoder_loaded = true;
}
}
else{
@ -417,7 +400,7 @@ void M17::send_ping()
void M17::send_disconnect()
{
if(m_modeinfo.host == "MMDVM_DIRECT"){
if(m_mdirect){
return;
}
@ -453,11 +436,6 @@ void M17::send_modem_data(QByteArray d)
uint8_t txframe[M17_FRAME_LENGTH_BYTES];
uint8_t tmp[M17_FRAME_LENGTH_BYTES];
// FIXME: Hard code dst to "ALL " until I better understand what to do here
::memset(&d.data()[6], 0, 4);
d.data()[10] = 0x4c;
d.data()[11] = 0xe1;
if(m_modeinfo.stream_state == STREAM_NEW){
::memcpy(lsf, &d.data()[6], M17_LSF_LENGTH_BYTES);
encodeCRC16(lsf, M17_LSF_LENGTH_BYTES);
@ -550,7 +528,7 @@ void M17::process_modem_data(QByteArray d)
if((d.data()[2] == MMDVM_M17_LOST) || (d.data()[2] == MMDVM_M17_EOT)){
txstreamid = 0;
if(m_modeinfo.host == "MMDVM_DIRECT"){
if(m_mdirect){
m_modeinfo.streamid = 0;
m_modeinfo.dst.clear();
m_modeinfo.src.clear();
@ -568,7 +546,7 @@ void M17::process_modem_data(QByteArray d)
txstreamid = static_cast<uint16_t>((::rand() & 0xFFFF));
qDebug() << "M17 LSF received valid == " << validlsf << "ber: " << ber;
if(validlsf && (m_modeinfo.host == "MMDVM_DIRECT")){
if(validlsf && m_mdirect){
uint8_t cs[10];
::memcpy(cs, lsf, 6);
decode_callsign(cs);
@ -615,7 +593,7 @@ void M17::process_modem_data(QByteArray d)
}
}
if(m_modeinfo.host == "MMDVM_DIRECT"){
if(m_mdirect){
if( !m_tx && (m_modeinfo.streamid == 0) ){
if(txstreamid == 0){
qDebug() << "No header, late entry...";
@ -777,7 +755,7 @@ void M17::transmit()
if(m_tx){
if(txstreamid == 0){
txstreamid = static_cast<uint16_t>((::rand() & 0xFFFF));
if(!m_rxtimer->isActive() && (m_modeinfo.host == "MMDVM_DIRECT")){
if(!m_rxtimer->isActive() && m_mdirect){
m_rxmodemq.clear();
m_modeinfo.stream_state = STREAM_NEW;
#ifdef Q_OS_WIN
@ -789,7 +767,7 @@ void M17::transmit()
}
else{
if(m_modeinfo.host == "MMDVM_DIRECT"){
if(m_mdirect){
m_modeinfo.stream_state = STREAMING;
}
}
@ -799,6 +777,7 @@ void M17::transmit()
uint8_t lsf[30];
memset(dst, ' ', 9);
memcpy(dst, m_refname.toLocal8Bit(), m_refname.size());
dst[8] = m_module;
dst[9] = 0x00;
encode_callsign(dst);
@ -831,7 +810,7 @@ void M17::transmit()
txframe.append(lsf[28]);
txframe.append(lsf[29]);
if(m_modeinfo.host == "MMDVM_DIRECT"){
if(m_mdirect){
send_modem_data(txframe);
m_rxwatchdog = 0;
}
@ -842,6 +821,7 @@ void M17::transmit()
++tx_cnt;
m_modeinfo.src = m_modeinfo.callsign;
m_modeinfo.dst = m_refname;
m_modeinfo.module = m_module;
m_modeinfo.type = get_mode();
m_modeinfo.frame_number = tx_cnt;
m_modeinfo.streamid = txstreamid;
@ -890,7 +870,7 @@ void M17::transmit()
txframe.append((char *)quiet, 8);
txframe.append(2, 0x00);
if(m_modeinfo.host == "MMDVM_DIRECT"){
if(m_mdirect){
send_modem_data(txframe);
m_modeinfo.stream_state = STREAM_END;
}

@ -142,10 +142,10 @@ ApplicationWindow {
Component.onCompleted: {
mainTab.comboMode.loaded = true;
droidstar.process_settings();
settingsTab.comboVocoder.model = droidstar.get_vocoders();
settingsTab.comboModem.model = droidstar.get_modems();
settingsTab.comboPlayback.model = droidstar.get_playbacks();
settingsTab.comboCapture.model = droidstar.get_captures();
settingsTab.comboVocoder.model = droidstar.get_vocoders();
settingsTab.comboModem.model = droidstar.get_modems();
settingsTab.comboPlayback.model = droidstar.get_playbacks();
settingsTab.comboCapture.model = droidstar.get_captures();
mainTab.data1.font.family = droidstar.get_monofont();
mainTab.data2.font.family = droidstar.get_monofont();
mainTab.data3.font.family = droidstar.get_monofont();
@ -173,6 +173,12 @@ ApplicationWindow {
function onRptr2_changed(s){
settingsTab.rptr2Edit.text = s;
}
function onUpdate_devices(){
settingsTab.comboVocoder.model = droidstar.get_vocoders();
settingsTab.comboModem.model = droidstar.get_modems();
settingsTab.comboPlayback.model = droidstar.get_playbacks();
settingsTab.comboCapture.model = droidstar.get_captures();
}
function onMode_changed() {
//console.log("onMode_changed ", mainTab.comboMode.find(droidstar.get_mode()), ":", droidstar.get_mode(), ":", droidstar.get_ref_host(), ":", droidstar.get_module());
@ -494,6 +500,11 @@ ApplicationWindow {
settingsTab.m171600.checked = true;
}
if(mainTab.comboMode.currentText === "M17"){
if(settingsTab.mmdvmBox.checked){
mainTab.comboModule.enabled = true;
mainTab.comboHost.enabled = true;
}
settingsTab.m173200.checked = true;
}
@ -509,6 +520,9 @@ ApplicationWindow {
}
if(c === 5){
errorDialog.text = droidstar.get_error_text();
if(errorDialog.text == ""){
errorDialog.text = "Banned!"
}
errorDialog.open();
droidstar.onConnect_status_changed(0);
}

@ -82,7 +82,7 @@ Mode::~Mode()
{
}
void Mode::init(QString callsign, uint32_t dmrid, uint16_t nxdnid, char module, QString refname, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout)
void Mode::init(QString callsign, uint32_t dmrid, uint16_t nxdnid, char module, QString refname, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout, bool mdirect)
{
m_dmrid = dmrid;
m_nxdnid = nxdnid;
@ -93,6 +93,7 @@ void Mode::init(QString callsign, uint32_t dmrid, uint16_t nxdnid, char module,
m_modemport = modem;
m_audioin = audioin;
m_audioout = audioout;
m_mdirect = mdirect;
m_modem = nullptr;
m_ambedev = nullptr;
@ -172,28 +173,62 @@ void Mode::out_audio_vol_changed(qreal v)
void Mode::agc_state_changed(int s)
{
qDebug() << "Codec::agc_state_changed() called s == " << s;
m_audio->set_agc(s);
}
void Mode::send_connect()
void Mode::begin_connect()
{
m_modeinfo.status = CONNECTING;
if(m_modeinfo.host == "MMDVM_DIRECT"){
mmdvm_direct_connect();
}
else if(m_ipv6 && (m_modeinfo.host != "none")){
qDebug() << "Host == " << m_modeinfo.host;
QList<QHostAddress> h;
QHostInfo i;
h.append(QHostAddress(m_modeinfo.host));
i.setAddresses(h);
hostname_lookup(i);
}
else{
QHostInfo::lookupHost(m_modeinfo.host, this, SLOT(hostname_lookup(QHostInfo)));
}
if((m_vocoder != "") && (m_mode != "M17")){
m_hwrx = true;
m_hwtx = true;
m_modeinfo.hw_vocoder_loaded = true;
#if !defined(Q_OS_IOS)
m_ambedev = new SerialAMBE(m_mode);
connect(m_ambedev, SIGNAL(connected(bool)), this, SLOT(ambe_connect_status(bool)));
connect(m_ambedev, SIGNAL(data_ready()), this, SLOT(get_ambe()));
connect(m_ambedev, SIGNAL(ambedev_ready()), this, SLOT(host_lookup()));
m_ambedev->connect_to_serial(m_vocoder);
#endif
}
else{
m_hwrx = false;
m_hwtx = false;
if(m_modemport == ""){
host_lookup();
}
}
if(m_modemport != ""){
#if !defined(Q_OS_IOS)
m_modem = new SerialModem(m_mode);
m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex);
m_modem->set_modem_params(m_baud, m_rxfreq, m_txfreq, m_txDelay, m_rxLevel, m_rfLevel, m_ysfTXHang, m_cwIdTXLevel, m_dstarTXLevel, m_dmrTXLevel, m_ysfTXLevel, m_p25TXLevel, m_nxdnTXLevel, m_pocsagTXLevel, m_m17TXLevel);
connect(m_modem, SIGNAL(connected(bool)), this, SLOT(mmdvm_connect_status(bool)));
connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray)));
connect(m_modem, SIGNAL(modem_ready()), this, SLOT(host_lookup()));
m_modem->connect_to_serial(m_modemport);
#endif
}
}
void Mode::host_lookup()
{
if(m_mdirect && (m_mode == "M17")){ // MMDVM_DIRECT currently only supported by M17
mmdvm_direct_connect();
}
else if(m_ipv6 && (m_modeinfo.host != "none")){
qDebug() << "Host == " << m_modeinfo.host;
QList<QHostAddress> h;
QHostInfo i;
h.append(QHostAddress(m_modeinfo.host));
i.setAddresses(h);
hostname_lookup(i);
}
else{
QHostInfo::lookupHost(m_modeinfo.host, this, SLOT(hostname_lookup(QHostInfo)));
}
}
void Mode::toggle_tx(bool tx)

@ -42,7 +42,7 @@ public:
Mode();
~Mode();
static Mode* create_mode(QString);
void init(QString callsign, uint32_t dmrid, uint16_t nxdnid, char module, QString refname, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout);
void init(QString callsign, uint32_t dmrid, uint16_t nxdnid, char module, QString refname, QString host, int port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout, bool mdirect);
void set_modem_flags(bool rxInvert, bool txInvert, bool pttInvert, bool useCOSAsLockout, bool duplex)
{
m_rxInvert = rxInvert;
@ -97,6 +97,7 @@ public:
QString mmdvmdesc;
QString mmdvm;
QString host;
QString module;
int port;
bool path;
char type;
@ -138,7 +139,7 @@ protected slots:
void ambe_connect_status(bool);
void mmdvm_connect_status(bool);
void send_connect();
void begin_connect();
void input_src_changed(int id, QString t) { m_ttsid = id; m_ttstext = t; }
void start_tx();
void stop_tx();
@ -156,7 +157,10 @@ protected slots:
void rptr2_changed(QString r2) { m_txrptr2 = r2; }
void usrtxt_changed(QString t) { m_txusrtxt = t; }
void module_changed(char m) { m_module = m; m_modeinfo.streamid = 0; }
void dst_changed(QString dst){ m_refname = dst; }
void host_lookup();
protected:
QString m_mode;
QUdpSocket *m_udp = nullptr;
QHostAddress m_address;
char m_module;
@ -185,6 +189,7 @@ protected:
AudioEngine *m_audio;
QString m_audioin;
QString m_audioout;
bool m_mdirect;
uint32_t m_rxwatchdog;
uint8_t m_attenuation;
uint8_t m_rxtimerint;

@ -41,6 +41,7 @@ const uint8_t BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x0
NXDN::NXDN()
{
m_mode = "NXDN";
m_txcnt = 0;
m_txtimerint = 19;
m_attenuation = 5;
@ -78,21 +79,6 @@ void NXDN::process_udp()
connect(m_ping_timer, SIGNAL(timeout()), this, SLOT(send_ping()));
//m_mbeenc->set_gain_adjust(2.5);
m_modeinfo.sw_vocoder_loaded = load_vocoder_plugin();
if(m_vocoder != ""){
m_hwrx = true;
m_hwtx = true;
m_modeinfo.hw_vocoder_loaded = true;
#if !defined(Q_OS_IOS)
m_ambedev = new SerialAMBE("NXDN");
m_ambedev->connect_to_serial(m_vocoder);
connect(m_ambedev, SIGNAL(connected(bool)), this, SLOT(ambe_connect_status(bool)));
connect(m_ambedev, SIGNAL(data_ready()), this, SLOT(get_ambe()));
#endif
}
else{
m_hwrx = false;
m_hwtx = false;
}
m_audio = new AudioEngine(m_audioin, m_audioout);
m_audio->init();
m_ping_timer->start(1000);

@ -19,7 +19,7 @@
#include <cstring>
#include "p25.h"
//#define DEBUG
#define DEBUG
const uint8_t REC62[] = {0x62U, 0x02U, 0x02U, 0x0CU, 0x0BU, 0x12U, 0x64U, 0x00U, 0x00U, 0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const uint8_t REC63[] = {0x63U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U};
@ -47,6 +47,7 @@ const uint8_t REC80[] = {0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
P25::P25()
{
m_mode = "P25";
m_p25cnt = 0;
m_txtimerint = 19;
m_attenuation = 2;

@ -29,6 +29,7 @@ const uint8_t MMDVM_DSTAR_EOT = 0x13U;
REF::REF()
{
m_mode = "REF";
m_attenuation = 5;
}
@ -89,32 +90,6 @@ void REF::process_udp()
if((m_modeinfo.status == CONNECTING) && (buf.size() == 0x08)){
if((memcmp(&buf.data()[4], "OKRW", 4) == 0) || (memcmp(&buf.data()[4], "OKRO", 4) == 0) || (memcmp(&buf.data()[4], "BUSY", 4) == 0)){
m_modeinfo.sw_vocoder_loaded = load_vocoder_plugin();
if(m_vocoder != ""){
m_hwrx = true;
m_hwtx = true;
m_modeinfo.hw_vocoder_loaded = true;
#if !defined(Q_OS_IOS)
m_ambedev = new SerialAMBE("REF");
m_ambedev->connect_to_serial(m_vocoder);
connect(m_ambedev, SIGNAL(connected(bool)), this, SLOT(ambe_connect_status(bool)));
connect(m_ambedev, SIGNAL(data_ready()), this, SLOT(get_ambe()));
#endif
}
else{
m_hwrx = false;
m_hwtx = false;
}
if(m_modemport != ""){
#if !defined(Q_OS_IOS)
m_modem = new SerialModem("REF");
m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex);
m_modem->set_modem_params(m_baud, m_rxfreq, m_txfreq, m_txDelay, m_rxLevel, m_rfLevel, m_ysfTXHang, m_cwIdTXLevel, m_dstarTXLevel, m_dmrTXLevel, m_ysfTXLevel, m_p25TXLevel, m_nxdnTXLevel, m_pocsagTXLevel, m_m17TXLevel);
m_modem->connect_to_serial(m_modemport);
connect(m_modem, SIGNAL(connected(bool)), this, SLOT(mmdvm_connect_status(bool)));
connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray)));
#endif
}
m_rxtimer = new QTimer();
connect(m_rxtimer, SIGNAL(timeout()), this, SLOT(process_rx_data()));
m_txtimer = new QTimer();

@ -119,69 +119,20 @@ void SerialAMBE::connect_to_serial(QString p)
#else
m_serial = &AndroidSerialPort::GetInstance();
connect(m_serial, SIGNAL(device_ready()), this, SLOT(config_ambe()));
#endif
m_serial->setPortName(p);
m_serial->setBaudRate(br);
m_serial->setDataBits(QSerialPort::Data8);
m_serial->setStopBits(QSerialPort::OneStop);
m_serial->setParity(QSerialPort::NoParity);
//out << "Baud rate == " << serial->baudRate() << endl;
if (m_serial->open(QIODevice::ReadWrite)) {
#ifndef Q_OS_ANDROID
connect(m_serial, &QSerialPort::readyRead, this, &SerialAMBE::process_serial);
config_ambe();
#else
//connect(m_serial, &AndroidSerialPort::readyRead, this, &SerialAMBE::process_serial);
connect(m_serial, SIGNAL(data_received(QByteArray)), this, SLOT(receive_serial(QByteArray)));
#endif
QByteArray a;
a.clear();
if(m_description != "DV Dongle"){
m_serial->setFlowControl(QSerialPort::HardwareControl);
m_serial->setRequestToSend(true);
a.append(reinterpret_cast<const char*>(AMBE3000_PARITY_DISABLE), sizeof(AMBE3000_PARITY_DISABLE));
m_serial->write(a);
QThread::msleep(100);
a.clear();
a.append(reinterpret_cast<const char*>(AMBE3000_PRODID), sizeof(AMBE3000_PRODID));
m_serial->write(a);
QThread::msleep(100);
a.clear();
a.append(reinterpret_cast<const char*>(AMBE3000_VERSION), sizeof(AMBE3000_VERSION));
m_serial->write(a);
QThread::msleep(100);
a.clear();
}
if(m_protocol == "DMR"){
a.append(reinterpret_cast<const char*>(AMBE3000_2450_1150), sizeof(AMBE3000_2450_1150));
packet_size = 9;
}
else if( (m_protocol == "YSF") || (m_protocol == "NXDN") ){
a.append(reinterpret_cast<const char*>(AMBE3000_2450_0000), sizeof(AMBE3000_2450_0000));
packet_size = 7;
}
else if(m_protocol == "P25"){
a.append(reinterpret_cast<const char*>(AMBEP251_4400_2800), sizeof(AMBEP251_4400_2800));
}
else if(m_description != "DV Dongle"){ //D-Star with AMBE3000
a.append(reinterpret_cast<const char*>(AMBE2000_2400_1200), sizeof(AMBE2000_2400_1200));
packet_size = 9;
}
else{
a.append(reinterpret_cast<const char*>(AMBE2020), sizeof(AMBE2020));
packet_size = 9;
}
m_serial->write(a);
#ifdef DEBUG
fprintf(stderr, "SENDHW %d:%d:", a.size(), m_serialdata.size());
for(int i = 0; i < a.size(); ++i){
//if((d.data()[i] == 0x61) && (data.data()[i+1] == 0x01) && (data.data()[i+2] == 0x42) && (data.data()[i+3] == 0x02)){
// i+= 6;
//}
fprintf(stderr, "%02x ", (unsigned char)a.data()[i]);
}
fprintf(stderr, "\n");
fflush(stderr);
#endif
}
else{
@ -190,6 +141,61 @@ void SerialAMBE::connect_to_serial(QString p)
}
}
void SerialAMBE::config_ambe()
{
QByteArray a;
a.clear();
if(m_description != "DV Dongle"){
m_serial->setFlowControl(QSerialPort::HardwareControl);
m_serial->setRequestToSend(true);
a.append(reinterpret_cast<const char*>(AMBE3000_PARITY_DISABLE), sizeof(AMBE3000_PARITY_DISABLE));
m_serial->write(a);
QThread::msleep(100);
a.clear();
a.append(reinterpret_cast<const char*>(AMBE3000_PRODID), sizeof(AMBE3000_PRODID));
m_serial->write(a);
QThread::msleep(100);
a.clear();
a.append(reinterpret_cast<const char*>(AMBE3000_VERSION), sizeof(AMBE3000_VERSION));
m_serial->write(a);
QThread::msleep(100);
a.clear();
}
if(m_protocol == "DMR"){
a.append(reinterpret_cast<const char*>(AMBE3000_2450_1150), sizeof(AMBE3000_2450_1150));
packet_size = 9;
}
else if( (m_protocol == "YSF") || (m_protocol == "NXDN") ){
a.append(reinterpret_cast<const char*>(AMBE3000_2450_0000), sizeof(AMBE3000_2450_0000));
packet_size = 7;
}
else if(m_protocol == "P25"){
a.append(reinterpret_cast<const char*>(AMBEP251_4400_2800), sizeof(AMBEP251_4400_2800));
}
else if(m_description != "DV Dongle"){ //D-Star with AMBE3000
a.append(reinterpret_cast<const char*>(AMBE2000_2400_1200), sizeof(AMBE2000_2400_1200));
packet_size = 9;
}
else{
a.append(reinterpret_cast<const char*>(AMBE2020), sizeof(AMBE2020));
packet_size = 9;
}
m_serial->write(a);
#ifdef DEBUG
fprintf(stderr, "SENDHW %d:%d:", a.size(), m_serialdata.size());
for(int i = 0; i < a.size(); ++i){
//if((d.data()[i] == 0x61) && (data.data()[i+1] == 0x01) && (data.data()[i+2] == 0x42) && (data.data()[i+3] == 0x02)){
// i+= 6;
//}
fprintf(stderr, "%02x ", (unsigned char)a.data()[i]);
}
fprintf(stderr, "\n");
fflush(stderr);
#endif
emit ambedev_ready();
}
void SerialAMBE::receive_serial(QByteArray d)
{
for(int i = 0; i < d.size(); i++){
@ -445,7 +451,6 @@ bool SerialAMBE::get_audio(int16_t *audio)
((uint8_t)m_serialdata[3] == header[3]) &&
((uint8_t)m_serialdata[4] == header[4]) &&
((uint8_t)m_serialdata[5] == header[5])){
//m_serialdata.erase(m_serialdata.begin(), m_serialdata.begin() + 6);
m_serialdata.dequeue();
m_serialdata.dequeue();
m_serialdata.dequeue();

@ -45,6 +45,7 @@ public:
private slots:
void process_serial();
void receive_serial(QByteArray);
void config_ambe();
private:
#ifndef Q_OS_ANDROID
QSerialPort *m_serial;
@ -69,6 +70,7 @@ private:
signals:
void connected(bool);
void data_ready();
void ambedev_ready();
};
#endif // SERIALAMBE_H

@ -103,43 +103,48 @@ void SerialModem::connect_to_serial(QString p)
m_serial = new QSerialPort;
#else
m_serial = &AndroidSerialPort::GetInstance();
connect(m_serial, SIGNAL(device_ready()), this, SLOT(config_modem()));
#endif
m_serial->setPortName(p);
m_serial->setBaudRate(m_baudrate);
m_serial->setDataBits(QSerialPort::Data8);
m_serial->setStopBits(QSerialPort::OneStop);
m_serial->setParity(QSerialPort::NoParity);
//out << "Baud rate == " << serial->baudRate() << endl;
if (m_serial->open(QIODevice::ReadWrite)) {
m_modemtimer = new QTimer();
connect(m_modemtimer, SIGNAL(timeout()), this, SLOT(process_modem()));
m_modemtimer->start(19);
#ifndef Q_OS_ANDROID
connect(m_serial, &QSerialPort::readyRead, this, &SerialModem::process_serial);
config_modem();
#else
//connect(m_serial, &AndroidSerialPort::readyRead, this, &SerialModem::process_serial);
connect(m_serial, SIGNAL(data_received(QByteArray)), this, SLOT(receive_serial(QByteArray)));
#endif
//m_serial->setFlowControl(QSerialPort::HardwareControl);
m_serial->setRequestToSend(true);
QByteArray a;
a.clear();
a.append(MMDVM_FRAME_START);
a.append(3);
a.append(MMDVM_GET_VERSION);
m_serial->write(a);
}
}
void SerialModem::config_modem()
{
QByteArray a;
a.clear();
a.append(MMDVM_FRAME_START);
a.append(3);
a.append(MMDVM_GET_VERSION);
m_serial->write(a);
#ifdef DEBUGHW
fprintf(stderr, "MODEMTX %d:%d:", a.size(), m_serialdata.size());
for(int i = 0; i < a.size(); ++i){
//if((d.data()[i] == 0x61) && (data.data()[i+1] == 0x01) && (data.data()[i+2] == 0x42) && (data.data()[i+3] == 0x02)){
// i+= 6;
//}
fprintf(stderr, "%02x ", (uint8_t)a.data()[i]);
}
fprintf(stderr, "\n");
fflush(stderr);
fprintf(stderr, "MODEMTX %d:%d:", a.size(), m_serialdata.size());
for(int i = 0; i < a.size(); ++i){
//if((d.data()[i] == 0x61) && (data.data()[i+1] == 0x01) && (data.data()[i+2] == 0x42) && (data.data()[i+3] == 0x02)){
// i+= 6;
//}
fprintf(stderr, "%02x ", (uint8_t)a.data()[i]);
}
fprintf(stderr, "\n");
fflush(stderr);
#endif
}
emit modem_ready();
}
void SerialModem::receive_serial(QByteArray d)
@ -147,7 +152,6 @@ void SerialModem::receive_serial(QByteArray d)
for(int i = 0; i < d.size(); i++){
m_serialdata.enqueue(d[i]);
}
//qDebug() << "SerialModem::process_serial()" << d.toHex();
}
void SerialModem::process_serial()
@ -157,7 +161,6 @@ void SerialModem::process_serial()
for(int i = 0; i < d.size(); i++){
m_serialdata.enqueue(d[i]);
}
//qDebug() << "SerialModem::process_serial()" << d.toHex();
#ifdef DEBUGHW
fprintf(stderr, "MODEMRX %d:%d:", d.size(), m_serialdata.size());
for(int i = 0; i < d.size(); ++i){
@ -179,7 +182,6 @@ void SerialModem::process_modem()
return;
}
//qDebug() << "process_modem() " << (uint8_t)m_serialdata[0] << ":" << (uint8_t)m_serialdata[1] << ":" << m_serialdata.size();
if(((uint8_t)m_serialdata[0] == MMDVM_FRAME_START) && (m_serialdata.size() >= m_serialdata[1])){
const uint8_t r = (uint8_t)m_serialdata[2];
const uint8_t s = (uint8_t)m_serialdata[1];

@ -42,6 +42,7 @@ public:
private slots:
void process_serial();
void receive_serial(QByteArray);
void config_modem();
void process_modem();
void set_freq();
void set_config();
@ -105,6 +106,7 @@ signals:
void data_ready();
void modem_data_ready(QByteArray);
void connected(bool);
void modem_ready();
};
#endif // SERIALMODEM_H

@ -25,6 +25,7 @@
XRF::XRF()
{
m_mode = "XRF";
m_attenuation = 5;
}
@ -61,27 +62,6 @@ void XRF::process_udp()
if( (m_modeinfo.status == CONNECTING) && (buf.size() == 14) && (!memcmp(buf.data()+10, "ACK", 3)) ){
m_modeinfo.status = CONNECTED_RW;
m_modeinfo.sw_vocoder_loaded = load_vocoder_plugin();
if(m_vocoder != ""){
m_hwrx = true;
m_hwtx = true;
m_modeinfo.hw_vocoder_loaded = true;
#if !defined(Q_OS_IOS)
m_ambedev = new SerialAMBE("XRF");
m_ambedev->connect_to_serial(m_vocoder);
connect(m_ambedev, SIGNAL(connected(bool)), this, SLOT(ambe_connect_status(bool)));
connect(m_ambedev, SIGNAL(data_ready()), this, SLOT(get_ambe()));
#endif
}
if(m_modemport != ""){
#if !defined(Q_OS_IOS)
m_modem = new SerialModem("XRF");
m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex);
m_modem->set_modem_params(m_baud, m_rxfreq, m_txfreq, m_txDelay, m_rxLevel, m_rfLevel, m_ysfTXHang, m_cwIdTXLevel, m_dstarTXLevel, m_dmrTXLevel, m_ysfTXLevel, m_p25TXLevel, m_nxdnTXLevel, m_pocsagTXLevel, m_m17TXLevel);
m_modem->connect_to_serial(m_modemport);
connect(m_modem, SIGNAL(connected(bool)), this, SLOT(mmdvm_connect_status(bool)));
connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray)));
#endif
}
m_rxtimer = new QTimer();
connect(m_rxtimer, SIGNAL(timeout()), this, SLOT(process_rx_data()));
m_txtimer = new QTimer();

@ -24,7 +24,7 @@
#include <iostream>
#include <cstring>
//#define DEBUG
#define DEBUG
const uint32_t IMBE_INTERLEAVE[] = {
0, 7, 12, 19, 24, 31, 36, 43, 48, 55, 60, 67, 72, 79, 84, 91, 96, 103, 108, 115, 120, 127, 132, 139,
@ -103,6 +103,7 @@ YSF::YSF() :
m_fcs(false),
m_txfullrate(false)
{
m_mode = "YSF";
m_attenuation = 5;
}
@ -142,33 +143,6 @@ void YSF::process_udp()
m_rxtimer = new QTimer();
connect(m_rxtimer, SIGNAL(timeout()), this, SLOT(process_rx_data()));
if(m_vocoder != ""){
m_hwrx = true;
m_hwtx = true;
m_modeinfo.hw_vocoder_loaded = true;
#if !defined(Q_OS_IOS)
m_ambedev = new SerialAMBE("YSF");
m_ambedev->connect_to_serial(m_vocoder);
connect(m_ambedev, SIGNAL(connected(bool)), this, SLOT(ambe_connect_status(bool)));
connect(m_ambedev, SIGNAL(data_ready()), this, SLOT(get_ambe()));
#endif
}
else{
m_hwrx = false;
m_hwtx = false;
}
if(m_modemport != ""){
#if !defined(Q_OS_IOS)
m_modem = new SerialModem("YSF");
m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex);
m_modem->set_modem_params(m_baud, m_rxfreq, m_txfreq, m_txDelay, m_rxLevel, m_rfLevel, m_ysfTXHang, m_cwIdTXLevel, m_dstarTXLevel, m_dmrTXLevel, m_ysfTXLevel, m_p25TXLevel, m_nxdnTXLevel, m_pocsagTXLevel, m_m17TXLevel);
m_modem->connect_to_serial(m_modemport);
connect(m_modem, SIGNAL(connected(bool)), this, SLOT(mmdvm_connect_status(bool)));
connect(m_modem, SIGNAL(modem_data_ready(QByteArray)), this, SLOT(process_modem_data(QByteArray)));
#endif
}
m_audio = new AudioEngine(m_audioin, m_audioout);
m_audio->init();

Loading…
Cancel
Save