diff --git a/MainTab.qml b/MainTab.qml index e1890d0..a2032a0 100644 --- a/MainTab.qml +++ b/MainTab.qml @@ -23,16 +23,30 @@ import QtQuick.Controls 2.3 Item { id: mainTab - property alias element1: _element1 + property int rows: 18; + onWidthChanged:{ + if(_comboMode.currentText == "DMR"){ + _comboMode.width = (mainTab.width / 5) - 5; + _connectbutton.width = (mainTab.width * 2 / 5 ) - 5 + _connectbutton.x = (mainTab.width * 3 / 5 ) + } + else{ + _comboMode.width = (mainTab.width / 2) - 5; + _connectbutton.width = (mainTab.width / 2) - 5; + _connectbutton.x = mainTab.width / 2; + } + } + property alias element3: _element3 - property alias element4: _element4 property alias label1: _label1 property alias label2: _label2 property alias label3: _label3 property alias label4: _label4 property alias label5: _label5 property alias label6: _label6 - property alias status: _status + property alias ambestatus: _ambestatus + property alias mmdvmstatus: _mmdvmstatus + property alias netstatus: _netstatus property alias levelMeter: _levelMeter property alias uitimer: _uitimer property alias comboMode: _comboMode @@ -40,9 +54,12 @@ Item { property alias editIAXDTMF: _editIAXDTMF property alias dtmfsendbutton: _dtmfsendbutton property alias comboModule: _comboModule + property alias comboSlot: _comboSlot + property alias comboCC: _comboCC property alias dmrtgidEdit: _dmrtgidEdit property alias privateBox: _privateBox property alias connectbutton: _connectbutton + property alias sliderMicGain: _slidermicGain property alias data1: _data1 property alias data2: _data2 property alias data3: _data3 @@ -56,157 +73,12 @@ Item { property alias swrxBox: _swrxBox property alias agcBox: _agcBox - Text { - id: element - x: 10 - y: 0 - width: parent.width / 4 - height: parent.height / 15; - text: qsTr("Mode") - color: "white" - font.pixelSize: parent.height / 30; - verticalAlignment: Text.AlignVCenter - } - - Text { - id: _element1 - x: 10 - y: (parent.height / 15 + 3) * 1; - width: parent.width / 4 - height: parent.height / 15; - text: qsTr("Host") - color: "white" - font.pixelSize: parent.height / 30; - verticalAlignment: Text.AlignVCenter - } - - Text { - id: _element4 - x: 10 - y: (parent.height / 15 + 3) * 2; - width: parent.width / 5 - height: parent.height / 15; - text: qsTr("Mod") - color: "white" - font.pixelSize: parent.height / 30; - verticalAlignment: Text.AlignVCenter - } - - Text { - id: _element3 - x: 10 - y: (parent.height / 15 + 3) * 3; - width: parent.width / 4 - height: parent.height / 15; - text: qsTr("TG ID") - color: "white" - font.pixelSize: parent.height / 30; - verticalAlignment: Text.AlignVCenter - } - - Text { - id: _label1 - x: 10 - y: (parent.height / 15 + 3) * 4; - width: parent.width / 3 - height: parent.height / 20; - text: qsTr("MYCALL") - color: "white" - font.pixelSize: parent.height / 30; - } - - Text { - id: _label2 - x: 10 - y: (parent.height / 15 + 3) * 5; - width: parent.width / 3 - height: parent.height / 20; - text: qsTr("URCALL") - color: "white" - font.pixelSize: parent.height / 30; - } - - Text { - id: _label3 - x: 10 - y: (parent.height / 15 + 3) * 6; - width: parent.width / 3 - height: parent.height / 20; - text: qsTr("RPTR1") - color: "white" - font.pixelSize: parent.height / 30; - } - - Text { - id: _label4 - x: 10 - y: (parent.height / 15 + 3) * 7; - width: parent.width / 3 - height: parent.height / 20; - text: qsTr("RPTR2") - color: "white" - font.pixelSize: parent.height / 30; - } - - Text { - id: _label5 - x: 10 - y: (parent.height / 15 + 3) * 8; - width: parent.width / 3 - height: parent.height / 20; - text: qsTr("StrmID") - color: "white" - font.pixelSize: parent.height / 30; - } - - Text { - id: _label6 - x: 10 - y: (parent.height / 15 + 3) * 9; - width: parent.width / 3 - height: parent.height / 20; - text: qsTr("Text") - color: "white" - font.pixelSize: parent.height / 30; - } - - Text { - id: _status - x: 10 - y: (parent.height / 15 + 3) * 10; - width: parent.width - 20 - height: parent.height / 20; - text: qsTr("Not Connected") - color: "white" - font.pixelSize: parent.height / 35; - } - Rectangle { - x: 10 - y: (parent.height / 15 + 3) * 11; - width: parent.width - 20 - height: parent.height / 20; - color: "black" - border.color: "black" - border.width: 2 - radius: 5 - } - Rectangle { - id: _levelMeter - x: 10 - y: (parent.height / 15 + 3) * 11; - width: 0 - height: parent.height / 20; - color: "#80C342" - border.color: "black" - border.width: 2 - radius: 5 - } Timer { id: _uitimer interval: 20; running: true; repeat: true - property var cnt: 0; - property var rxcnt: 0; - property var last_rxcnt: 0; + property int cnt: 0; + property int rxcnt: 0; + property int last_rxcnt: 0; onTriggered: update_level(); function update_level(){ @@ -238,14 +110,17 @@ Item { } } } + ComboBox { id: _comboMode property bool loaded: false - x: parent.width / 4 + x: 5 y: 0 - width: (parent.width * 3 / 8) - 4 - height: parent.height / 15; - font.pixelSize: parent.height / 35 + width: (parent.width / 2) - 5 + height: parent.height / rows; + font.pixelSize: parent.height / 40 + currentIndex: -1 + displayText: currentIndex === -1 ? "Mode..." : currentText model: ["M17", "YSF", "FCS", "DMR", "P25", "NXDN", "REF", "XRF", "DCS", "IAX"] contentItem: Text { text: _comboMode.displayText @@ -258,143 +133,65 @@ Item { if(_comboMode.loaded){ droidstar.process_mode_change(_comboMode.currentText); } + if(_comboMode.currentText == "DMR"){ + _comboMode.width = (mainTab.width / 5) - 5; + _connectbutton.width = (mainTab.width * 2 / 5 ) - 5; + _connectbutton.x = (mainTab.width * 3 / 5 ); + } + else{ + _comboMode.width = (mainTab.width / 2) - 5; + _connectbutton.width = (mainTab.width / 2) - 5; + _connectbutton.x = mainTab.width / 2; + } } } - ComboBox { - id: _comboHost - x: (parent.width / 4) - y: (parent.height / 15 + 3) * 1; - width: ((parent.width * 3) / 4) - 5 - height: parent.height / 15; + id: _comboSlot + x: (parent.width / 5 ) + y: 0 + width: (parent.width / 5) + height: parent.height / rows; font.pixelSize: parent.height / 35 + model: ["S1", "S2"] + currentIndex: 1 contentItem: Text { - text: _comboHost.displayText - font: _comboHost.font + text: _comboSlot.displayText + font: _comboSlot.font leftPadding: 10 verticalAlignment: Text.AlignVCenter - color: _comboHost.enabled ? "white" : "darkgrey" + color: _comboSlot.enabled ? "white" : "darkgrey" } onCurrentTextChanged: { - if(!droidstar.get_modelchange()){ - droidstar.process_host_change(_comboHost.currentText); - } - } - } - TextField { - id: _editIAXDTMF - x: (parent.width / 4) - y: (parent.height / 15 + 3) * 1; - width: (parent.width * 3 / 8) - 4; - height: parent.height / 15; - font.pixelSize: parent.height / 35 - inputMethodHints: "ImhPreferNumbers" - } - Button { - id: _dtmfsendbutton - x: (parent.width * 5 / 8) - y: (parent.height / 15 + 3) * 1; - width: (parent.width * 3 / 8) - 5; - height: parent.height / 15; - text: qsTr("Send") - font.pixelSize: parent.height / 30 - onClicked: { - droidstar.dtmf_send_clicked(editIAXDTMF.text); + droidstar.set_slot(_comboSlot.currentIndex); + } } ComboBox { - id: _comboModule - x: parent.width / 5 - y: (parent.height / 15 + 3) * 2 - width: parent.width / 5 - height: parent.height / 15; + id: _comboCC + x: (parent.width * 2 / 5 ) + y: 0 + width: (parent.width / 5) + height: parent.height / rows; font.pixelSize: parent.height / 35 - 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: ["CC1", "CC2", "CC3", "CC4", "CC5", "CC6", "CC7"] contentItem: Text { - text: _comboModule.displayText - font: _comboModule.font + text: _comboCC.displayText + font: _comboCC.font leftPadding: 10 verticalAlignment: Text.AlignVCenter - color: _comboModule.enabled ? "white" : "darkgrey" + color: _comboCC.enabled ? "white" : "darkgrey" } onCurrentTextChanged: { - if(_comboMode.loaded){ - droidstar.set_module(_comboModule.currentText); - } - } - } - - CheckBox { - id: _swtxBox - x: (parent.width * 2 / 5) - y: (parent.height / 15 + 3) * 2; - width: parent.width / 4 - height: parent.height / 15 - text: qsTr("SWTX") - onClicked:{ - droidstar.set_swtx(_swtxBox.checked) + droidstar.set_cc(_comboCC.currentIndex); } } - - CheckBox { - id: _swrxBox - x: (parent.width * 3 / 5) - y: (parent.height / 15 + 3) * 2; - width: parent.width / 4 - height: parent.height / 15 - text: qsTr("SWRX") - onClicked:{ - droidstar.set_swrx(_swrxBox.checked) - } - } - - CheckBox { - id: _agcBox - x: (parent.width * 4 / 5) - y: (parent.height / 15 + 3) * 2; - width: parent.width / 4 - height: parent.height / 15 - text: qsTr("AGC") - onClicked:{ - droidstar.set_agc(_agcBox.checked) - } - } - - TextField { - visible: false - id: _dmrtgidEdit - x: parent.width / 4 - y: (parent.height / 15 + 3) * 3 - width: (parent.width * 3 / 8) - 4 - height: parent.height / 15 - font.pixelSize: parent.height / 30 - selectByMouse: true - inputMethodHints: "ImhPreferNumbers" - text: qsTr("") - onEditingFinished: { - droidstar.tgid_text_changed(dmrtgidEdit.text) - } - } - CheckBox { - id: _privateBox - x: (parent.width * 5 / 8) - y: (parent.height / 15 + 3) * 3; - width: (parent.width * 3 / 8) - 5 - height: parent.height / 15 - text: qsTr("Private") - onClicked:{ - droidstar.set_dmr_pc(privateBox.checked) - //console.log("screen size ", parent.width, " x ", parent.height); - } - } - Button { id: _connectbutton - x: (parent.width * 5 / 8) + x: parent.width / 2 y: 0 - width: (parent.width * 3 / 8) - 5 - height: parent.height / 15 + width: parent.width / 2 + height: parent.height / rows text: qsTr("Connect") font.pixelSize: parent.height / 30 onClicked: { @@ -450,13 +247,254 @@ Item { droidstar.process_connect(); } } + ComboBox { + id: _comboHost + x: 5 + y: (parent.height / rows + 1) * 1; + width: ((parent.width * 3) / 4) - 5 + height: parent.height / rows; + font.pixelSize: parent.height / 35 + currentIndex: -1 + displayText: currentIndex === -1 ? "Host..." : currentText + contentItem: Text { + text: _comboHost.displayText + font: _comboHost.font + leftPadding: 10 + verticalAlignment: Text.AlignVCenter + color: _comboHost.enabled ? "white" : "darkgrey" + } + onCurrentTextChanged: { + if(!droidstar.get_modelchange()){ + droidstar.process_host_change(_comboHost.currentText); + } + } + } + ComboBox { + id: _comboModule + x: ((parent.width * 3) / 4) + y: (parent.height / rows + 1) * 1 + width: (parent.width / 4) - 5 + height: parent.height / rows; + 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"] + contentItem: Text { + text: _comboModule.displayText + font: _comboModule.font + leftPadding: 10 + verticalAlignment: Text.AlignVCenter + color: _comboModule.enabled ? "white" : "darkgrey" + } + onCurrentTextChanged: { + if(_comboMode.loaded){ + droidstar.set_module(_comboModule.currentText); + } + } + } + CheckBox { + id: _privateBox + x: ((parent.width * 3) / 4) + y: (parent.height / rows + 1) * 1; + width: (parent.width / 4) - 5 + height: parent.height / rows + text: qsTr("Private") + onClicked:{ + droidstar.set_dmr_pc(privateBox.checked) + //console.log("screen size ", parent.width, " x ", parent.height); + } + } + TextField { + id: _editIAXDTMF + x: (parent.width / 4) + y: (parent.height / rows + 1) * 1; + width: (parent.width * 3 / 8) - 4; + height: parent.height / rows; + font.pixelSize: parent.height / 35 + inputMethodHints: "ImhPreferNumbers" + } + Button { + id: _dtmfsendbutton + x: (parent.width * 5 / 8) + y: (parent.height / rows + 1) * 1; + width: (parent.width * 3 / 8) - 5; + height: parent.height / rows; + text: qsTr("Send") + font.pixelSize: parent.height / 30 + onClicked: { + droidstar.dtmf_send_clicked(editIAXDTMF.text); + } + } + Text { + id: _element3 + x: 5 + y: (parent.height / rows + 1) * 2; + width: parent.width / 5 + height: parent.height / rows; + text: qsTr("TGID") + color: "white" + font.pixelSize: parent.height / 30; + verticalAlignment: Text.AlignVCenter + } + TextField { + visible: false + id: _dmrtgidEdit + x: parent.width / 5 + y: (parent.height / rows + 1) * 2 + width: parent.width /5 + height: parent.height / rows + font.pixelSize: parent.height / 35 + selectByMouse: true + inputMethodHints: "ImhPreferNumbers" + text: qsTr("") + onEditingFinished: { + droidstar.tgid_text_changed(dmrtgidEdit.text) + } + } + + CheckBox { + id: _swtxBox + x: (parent.width * 2 / 5) + 5 + y: (parent.height / rows + 1) * 2; + width: parent.width / 4 + height: parent.height / rows + font.pixelSize: parent.height / 40; + text: qsTr("SWTX") + onClicked:{ + droidstar.set_swtx(_swtxBox.checked) + } + } + + CheckBox { + id: _swrxBox + x: (parent.width * 3 / 5) + 5 + y: (parent.height / rows + 1) * 2; + width: parent.width / 4 + height: parent.height / rows + font.pixelSize: parent.height / 40; + text: qsTr("SWRX") + onClicked:{ + droidstar.set_swrx(_swrxBox.checked) + } + } + + CheckBox { + id: _agcBox + x: (parent.width * 4 / 5) + 5 + y: (parent.height / rows + 1) * 2; + width: parent.width / 4 + height: parent.height / rows + font.pixelSize: parent.height / 40; + text: qsTr("AGC") + onClicked:{ + droidstar.set_agc(_agcBox.checked) + } + } + Text { + id: micgain_label + x: 10 + y: (parent.height / rows + 1) * 3; + width: parent.width / 4; + height: parent.height / rows; + text: qsTr("Mic gain") + color: "white" + font.pixelSize: parent.height / 30; + verticalAlignment: Text.AlignVCenter + } + Slider { + visible: true + id: _slidermicGain + x: parent.width / 4 + y: (parent.height / rows + 1) * 3; + width: (parent.width * 3 / 4) - 10 + height: parent.height / rows; + value: 0.5 + onValueChanged: { + droidstar.set_input_volume(value); + } + } + Text { + id: _label1 + x: 10 + y: (parent.height / rows + 1) * 4; + width: parent.width / 3 + height: parent.height / rows; + text: qsTr("MYCALL") + color: "white" + font.pixelSize: parent.height / 30; + } + + Text { + id: _label2 + x: 10 + y: (parent.height / rows + 1) * 5; + width: parent.width / 3 + height: parent.height / rows; + text: qsTr("URCALL") + color: "white" + font.pixelSize: parent.height / 30; + } + + Text { + id: _label3 + x: 10 + y: (parent.height / rows + 1) * 6; + width: parent.width / 3 + height: parent.height / rows; + text: qsTr("RPTR1") + color: "white" + font.pixelSize: parent.height / 30; + } + + Text { + id: _label4 + x: 10 + y: (parent.height / rows + 1) * 7; + width: parent.width / 3 + height: parent.height / rows; + text: qsTr("RPTR2") + color: "white" + font.pixelSize: parent.height / 30; + } + + Text { + id: _label5 + x: 10 + y: (parent.height / rows + 1) * 8; + width: parent.width / 3 + height: parent.height / rows; + text: qsTr("StrmID") + color: "white" + font.pixelSize: parent.height / 30; + } + + Text { + id: _label6 + x: 10 + y: (parent.height / rows + 1) * 9; + width: parent.width / 3 + height: parent.height / rows; + text: qsTr("Text") + color: "white" + font.pixelSize: parent.height / 30; + } + Text { + id: _label7 + x: 10 + y: (parent.height / rows + 1) * 10; + width: parent.width / 3 + height: parent.height / rows; + text: qsTr("") + color: "white" + font.pixelSize: parent.height / 30; + } Text { id: _data1 x: parent.width / 3 - y: (parent.height / 15 + 3) * 4; + y: (parent.height / rows + 1) * 4; width: (parent.width * 2) / 3 - height: parent.height / 20; + height: parent.height / rows; text: qsTr("") color: "white" font.pixelSize: parent.height / 30; @@ -465,9 +503,9 @@ Item { Text { id: _data2 x: parent.width / 3 - y: (parent.height / 15 + 3) * 5; + y: (parent.height / rows + 1) * 5; width: (parent.width * 2) / 3 - height: parent.height / 20; + height: parent.height / rows; text: qsTr("") color: "white" font.pixelSize: parent.height / 30; @@ -476,9 +514,9 @@ Item { Text { id: _data3 x: parent.width / 3 - y: (parent.height / 15 + 3) * 6; + y: (parent.height / rows + 1) * 6; width: (parent.width * 2) / 3 - height: parent.height / 20; + height: parent.height / rows; text: qsTr("") color: "white" font.pixelSize: parent.height / 30; @@ -487,9 +525,9 @@ Item { Text { id: _data4 x: parent.width / 3 - y: (parent.height / 15 + 3) * 7; + y: (parent.height / rows + 1) * 7; width: (parent.width * 2) / 3 - height: parent.height / 20; + height: parent.height / rows; text: qsTr("") color: "white" font.pixelSize: parent.height / 30; @@ -498,9 +536,9 @@ Item { Text { id: _data5 x: parent.width / 3 - y: (parent.height / 15 + 3) * 8; + y: (parent.height / rows + 1) * 8; width: (parent.width * 2) / 3 - height: parent.height / 20; + height: parent.height / rows; text: qsTr("") color: "white" font.pixelSize: parent.height / 30; @@ -509,13 +547,75 @@ Item { Text { id: _data6 x: parent.width / 3 - y:(parent.height / 15 + 3) * 9; + y:(parent.height / rows + 1) * 9; width: (parent.width * 2) / 3 - height: parent.height / 20; + height: parent.height / rows; text: qsTr("") color: "white" font.pixelSize: parent.height / 30; } + Text { + id: _data7 + x: parent.width / 3 + y:(parent.height / rows + 1) * 10; + width: (parent.width * 2) / 3 + height: parent.height / rows; + text: qsTr("") + color: "white" + font.pixelSize: parent.height / 30; + } + + Text { + id: _ambestatus + x: 10 + y: (parent.height / rows + 1) * 11; + width: parent.width - 20 + height: parent.height / rows; + text: qsTr("No AMBE hardware connected") + color: "white" + font.pixelSize: parent.height / 35; + } + Text { + id: _mmdvmstatus + x: 10 + y: (parent.height / rows + 1) * 12; + width: parent.width - 20 + height: parent.height / rows; + text: qsTr("No MMDVM connected") + color: "white" + font.pixelSize: parent.height / 35; + } + Text { + id: _netstatus + x: 10 + y: (parent.height / rows + 1) * 13; + width: parent.width - 20 + height: parent.height / rows; + text: qsTr("Not Connected to network") + color: "white" + font.pixelSize: parent.height / 35; + } + Rectangle { + x: 10 + y: (parent.height / rows + 1) * 14; + width: parent.width - 20 + height: parent.height / 30; + color: "black" + border.color: "black" + border.width: 1 + radius: 5 + } + Rectangle { + id: _levelMeter + x: 10 + y: (parent.height / rows + 1) * 14; + width: 0 + height: parent.height / 30; + color: "#80C342" + border.color: "black" + border.width: 1 + radius: 5 + } Button { Timer { @@ -549,7 +649,7 @@ Item { } } x: 10 - y: (parent.height / 15 + 3) * 12; + y: (parent.height / rows + 1) * 15; //y: parent.height - ((parent.height / 5) + 5); width: parent.width - 20 height: parent.height - y - 10 diff --git a/README.md b/README.md index 80215ff..6e6f1cb 100644 --- a/README.md +++ b/README.md @@ -65,21 +65,15 @@ Port: UDP port of node, usually 4569. Add DTMF commands like \*3node, \*1node, \*70, etc in the IAX DTMF box and hit send to send the DTMF string. The asterisk (*) character is already added on the Droidstar app, so only input the numeric portion of the command (70 instead of *70, etc). Details on various commands can be found at the AllStar wiki and others. # General building instructions -This software is written primarily in C++ on Linux and requires Qt5 >= Qt5.15, and natually the devel packages to build. Java, QML (Javascript based), and C# code is also used where necessary. +This software is written primarily in C++ on Linux and requires Qt5 >= Qt5.15, and natually the devel packages to build. Java, QML (Javascript based), and C# code is also used where necessary. The preffered way to obtain Qt 5.15 is to use the Qt open source online installer from the Qt website. Run this installer as a user (not root) to keep the Qt installation separate from your system libs. Select the option as shown in this pic https://imgur.com/i0WuFCY which will install everything under ~/Qt. -Qt5 and Qt5-Quick development packages are required to build this software from source. With these requirements met, run the following: -``` -qmake -make -``` -qmake may have a different name on your distribution i.e. on Fedora it's called qmake-qt5 - -# Building on Raspbian/RaspiOS -DroidStar requires >= Qt 5.15 and RaspiOS currently packages Qt 5.11. Fortunately there is a great Qt 5.15.2 installer for RaspiOS: +## Note for building on Raspbian/RaspiOS +The Qt online installer does not support RPi, but fortunately there is a great Qt 5.15.2 installer for RaspiOS: https://github.com/koendv/qt5-opengl-raspberrypi -with this version of Qt installed, simply run the qmake from that version: +This installer puts everything in the same place as the Qt installer, so build instructions are the same for all: + ``` cd DroidStar mkdir build diff --git a/SettingsTab.qml b/SettingsTab.qml index 244a4dd..19cf1f0 100644 --- a/SettingsTab.qml +++ b/SettingsTab.qml @@ -40,11 +40,11 @@ Item { property alias iaxportEdit: iaxportedit property alias m173200: m17_3200 property alias m171600: m17_1600 - property alias sliderMicGain: slidermicGain property alias mycallEdit: mycalledit property alias urcallEdit: urcalledit property alias rptr1Edit: rptr1edit property alias rptr2Edit: rptr2edit + property alias usrtxtEdit: usrtxtedit property alias txtimerEdit: txtimeredit property alias toggleTX: toggletx property alias xrf2ref: xrf2Ref @@ -74,17 +74,86 @@ Item { id: flickable anchors.fill: parent contentWidth: parent.width - contentHeight: vocoderButton.y + - vocoderButton.height + 10 + contentHeight: _modemNXDNTXLevelLabel.y + + _modemNXDNTXLevelLabel.height + 10 flickableDirection: Flickable.VerticalFlick clip: true ScrollBar.vertical: ScrollBar {} + Text { - id: csLabel + id: vocoderLabel x: 10 y: 0 width: 80 height: 25 + text: qsTr("Vocoder") + color: "white" + verticalAlignment: Text.AlignVCenter + } + ComboBox { + id: _comboVocoder + x: 100 + y: vocoderLabel.y + width: parent.width - 110 + height: 30 + } + Text { + id: modemLabel + x: 10 + y: 30 + width: 80 + height: 25 + text: qsTr("Modem") + color: "white" + verticalAlignment: Text.AlignVCenter + } + ComboBox { + id: _comboModem + x: 100 + y: modemLabel.y + width: parent.width - 110 + height: 30 + } + Text { + id: playbackLabel + x: 10 + y: 60 + width: 80 + height: 25 + text: qsTr("Playback") + color: "white" + verticalAlignment: Text.AlignVCenter + } + ComboBox { + id: _comboPlayback + x: 100 + y: playbackLabel.y + width: parent.width - 110 + height: 30 + } + Text { + id: captureLabel + x: 10 + y: 90 + width: 80 + height: 25 + text: qsTr("Capture") + color: "white" + verticalAlignment: Text.AlignVCenter + } + ComboBox { + id: _comboCapture + x: 100 + y: captureLabel.y + width: parent.width - 110 + height: 30 + } + Text { + id: csLabel + x: 10 + y: 120 + width: 80 + height: 25 text: qsTr("Callsign") color: "white" verticalAlignment: Text.AlignVCenter @@ -92,7 +161,7 @@ Item { TextField { id: csedit x: 100 - y: 0 + y: csLabel.y width: 125 height: 25 text: qsTr("") @@ -102,7 +171,7 @@ Item { Text { id: dmridLabel x: 10 - y: 30 + y: 150 width: 80 height: 25 text: qsTr("DMRID") @@ -112,7 +181,7 @@ Item { TextField { id: dmridedit x: 100 - y: 30 + y: dmridLabel.y width: 125 height: 25 selectByMouse: true @@ -121,7 +190,7 @@ Item { Text { id: essidLabel x: 10 - y: 60 + y: 180 width: 80 height: 25 text: qsTr("ESSID") @@ -131,8 +200,8 @@ Item { ComboBox { id: comboessid x: 100 - y: 60 - width: 60 + y: essidLabel.y + width: 80 height: 30 function build_model(){ console.log("build_model() called"); @@ -153,7 +222,7 @@ Item { Text { id: bmpwLabel x: 10 - y: 95 + y: 210 width: 80 height: 25 text: qsTr("BM Pass") @@ -163,7 +232,7 @@ Item { TextField { id: bmpwedit x: 100 - y: 95 + y: bmpwLabel.y width: parent.width - 110 height: 25 selectByMouse: true @@ -172,7 +241,7 @@ Item { Text { id: tgifpwLabel x: 10 - y: 130 + y: 240 width: 80 height: 25 text: qsTr("TGIF Pass") @@ -182,7 +251,7 @@ Item { TextField { id: tgifpwedit x: 100 - y: 130 + y: tgifpwLabel.y width: parent.width - 110 height: 25 selectByMouse: true @@ -191,7 +260,7 @@ Item { Text { id: latLabel x: 10 - y: 160 + y: 270 width: 80 height: 25 text: qsTr("Latitude") @@ -201,7 +270,7 @@ Item { TextField { id: latedit x: 100 - y: 160 + y: latLabel.y width: 125 height: 25 selectByMouse: true @@ -209,7 +278,7 @@ Item { Text { id: lonLabel x: 10 - y: 190 + y: 300 width: 80 height: 25 text: qsTr("Longitude") @@ -219,7 +288,7 @@ Item { TextField { id: lonedit x: 100 - y: 190 + y: lonLabel.y width: 125 height: 25 selectByMouse: true @@ -227,7 +296,7 @@ Item { Text { id: locLabel x: 10 - y: 220 + y: 330 width: 80 height: 25 text: qsTr("Location") @@ -237,7 +306,7 @@ Item { TextField { id: locedit x: 100 - y: 220 + y: locLabel.y width: 125 height: 25 selectByMouse: true @@ -245,7 +314,7 @@ Item { Text { id: descLabel x: 10 - y: 250 + y: 360 width: 80 height: 25 text: qsTr("Description") @@ -255,7 +324,7 @@ Item { TextField { id: descedit x: 100 - y: 250 + y: descLabel.y width: 125 height: 25 selectByMouse: true @@ -263,7 +332,7 @@ Item { Text { id: urlLabel x: 10 - y: 280 + y: 390 width: 80 height: 25 text: qsTr("URL") @@ -273,7 +342,7 @@ Item { TextField { id: urledit x: 100 - y: 280 + y: urlLabel.y width: 125 height: 25 selectByMouse: true @@ -281,7 +350,7 @@ Item { Text { id: swidLabel x: 10 - y: 310 + y: 420 width: 80 height: 25 text: qsTr("SoftwareID") @@ -291,7 +360,7 @@ Item { TextField { id: swidedit x: 100 - y: 310 + y: swidLabel.y width: 125 height: 25 selectByMouse: true @@ -299,7 +368,7 @@ Item { Text { id: pkgidLabel x: 10 - y: 340 + y: 450 width: 80 height: 25 text: qsTr("PackageID") @@ -309,15 +378,15 @@ Item { TextField { id: pkgidedit x: 100 - y: 340 - width: 125 + y: pkgidLabel.y + width: parent.width - 110 height: 25 selectByMouse: true } Text { id: dmroptslabel x: 10 - y: 370 + y: 480 width: 80 height: 25 text: qsTr("DMR+ Opts") @@ -327,7 +396,7 @@ Item { TextField { id: dmroptsedit x: 100 - y: 370 + y: dmroptslabel.y width: parent.width - 110 height: 25 selectByMouse: true @@ -335,7 +404,7 @@ Item { Text { id: iaxuserlabel x: 10 - y: 400 + y: 510 width: 80 height: 25 text: qsTr("IAX User") @@ -345,7 +414,7 @@ Item { TextField { id: iaxuseredit x: 100 - y: 400 + y: iaxuserlabel.y width: 125 height: 25 selectByMouse: true @@ -353,7 +422,7 @@ Item { Text { id: iaxpasslabel x: 10 - y: 430 + y: 540 width: 80 height: 25 text: qsTr("IAX secret") @@ -363,7 +432,7 @@ Item { TextField { id: iaxpassedit x: 100 - y: 430 + y: iaxpasslabel.y width: 125 height: 25 selectByMouse: true @@ -372,7 +441,7 @@ Item { Text { id: iaxnodelabel x: 10 - y: 460 + y: 570 width: 80 height: 25 text: qsTr("IAX Node") @@ -382,7 +451,7 @@ Item { TextField { id: iaxnodeedit x: 100 - y: 460 + y: iaxnodelabel.y width: 125 height: 25 selectByMouse: true @@ -391,7 +460,7 @@ Item { Text { id: iaxhostlabel x: 10 - y: 490 + y: 600 width: 80 height: 25 text: qsTr("IAX Host") @@ -401,7 +470,7 @@ Item { TextField { id: iaxhostedit x: 100 - y: 490 + y: iaxhostlabel.y width: 125 height: 25 selectByMouse: true @@ -409,7 +478,7 @@ Item { Text { id: iaxportlabel x: 10 - y: 520 + y: 630 width: 80 height: 25 text: qsTr("IAX Port") @@ -419,99 +488,16 @@ Item { TextField { id: iaxportedit x: 100 - y: 520 + y: iaxportlabel.y width: 125 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" } - Text { - id: m17rateLabel - x: 10 - y: 550 - width: 100 - height: 25 - text: qsTr("M17/YSF rate") - color: "white" - verticalAlignment: Text.AlignVCenter - } - ButtonGroup { - id: m17rateGroup - onClicked: { - button.text == "Voice Full" ? droidstar.m17_rate_changed(true) : droidstar.m17_rate_changed(false) - } - } - CheckBox { - id: m17_3200 - x: 120 - y: 550 - //width: 100 - height: 25 - spacing: 1 - text: qsTr("Voice Full") - checked: true - ButtonGroup.group: m17rateGroup - } - CheckBox { - id: m17_1600 - x: 220 - y: 550 - //width: 100 - height: 25 - spacing: 1 - text: qsTr("Voice/Data") - ButtonGroup.group: m17rateGroup - } - Text { - id: micgain_label - x: 10 - y: 590 - width: 80 - height: 25 - text: qsTr("Mic gain") - color: "white" - verticalAlignment: Text.AlignVCenter - } - Slider { - visible: true - id: slidermicGain - x: 72 - y: 590 - width: parent.parent.width - 80 - height: parent.parent.height / 15 - value: 0.5 - onValueChanged: { - droidstar.set_input_volume(value); - } - } - Button { - id: updatehostsButton - x: 10 - y: 630 - width: 150 - height: 30 - text: qsTr("Update hosts") - onClicked: { - droidstar.update_host_files() - updateDialog.open() - } - } - Button { - id: updatedmridsButton - x: 170 - y: 630 - width: 150 - height: 30 - text: qsTr("Update ID files") - onClicked: { - droidstar.update_dmr_ids() - updateDialog.open() - } - } Text { id: mycallLabel x: 10 - y: 700 + y: 660 width: 80 height: 25 text: qsTr("MYCALL") @@ -521,7 +507,7 @@ Item { TextField { id: mycalledit x: 100 - y: 700 + y: mycallLabel.y width: 125 height: 25 selectByMouse: true @@ -533,7 +519,7 @@ Item { Text { id: urcallLabel x: 10 - y: 730 + y: 690 width: 80 height: 25 text: qsTr("URCALL") @@ -543,7 +529,7 @@ Item { TextField { id: urcalledit x: 100 - y: 730 + y: urcallLabel.y width: 125 height: 25 selectByMouse: true @@ -555,7 +541,7 @@ Item { Text { id: rptr1Label x: 10 - y: 760 + y: 720 width: 80 height: 25 text: qsTr("RPTR1") @@ -565,7 +551,7 @@ Item { TextField { id: rptr1edit x: 100 - y: 760 + y: rptr1Label.y width: 125 height: 25 selectByMouse: true @@ -577,7 +563,7 @@ Item { Text { id: rptr2Label x: 10 - y: 790 + y: 750 width: 80 height: 25 text: qsTr("RPTR2") @@ -587,7 +573,7 @@ Item { TextField { id: rptr2edit x: 100 - y: 790 + y: rptr2Label.y width: 125 height: 25 selectByMouse: true @@ -596,10 +582,31 @@ Item { droidstar.set_rptr2(rptr2edit.text.toUpperCase()) } } + Text { + id: usrtxtLabel + x: 10 + y: 780 + width: 80 + height: 25 + text: qsTr("USRTXT") + color: "white" + verticalAlignment: Text.AlignVCenter + } + TextField { + id: usrtxtedit + x: 100 + y: usrtxtLabel.y + width: parent.width - 110 + height: 25 + selectByMouse: true + onEditingFinished: { + droidstar.set_usrtxt(usrtxtedit.text) + } + } Text { id: txtimerLabel x: 10 - y: 820 + y: 810 width: 80 height: 25 text: qsTr("TX Timeout") @@ -609,15 +616,76 @@ Item { TextField { id: txtimeredit x: 100 - y: 820 + y: txtimerLabel.y width: 125 height: 25 selectByMouse: true } + Text { + id: m17rateLabel + x: 10 + y: 840 + width: 100 + height: 25 + text: qsTr("M17/YSF rate") + color: "white" + verticalAlignment: Text.AlignVCenter + } + ButtonGroup { + id: m17rateGroup + onClicked: { + button.text == "Voice Full" ? droidstar.m17_rate_changed(true) : droidstar.m17_rate_changed(false) + } + } + CheckBox { + id: m17_3200 + x: 120 + y: m17rateLabel.y + //width: 100 + height: 25 + spacing: 1 + text: qsTr("Voice Full") + checked: true + ButtonGroup.group: m17rateGroup + } + CheckBox { + id: m17_1600 + x: 220 + y: m17rateLabel.y + //width: 100 + height: 25 + spacing: 1 + text: qsTr("Voice/Data") + ButtonGroup.group: m17rateGroup + } + Button { + id: updatehostsButton + x: 10 + y: 870 + width: 150 + height: 30 + text: qsTr("Update hosts") + onClicked: { + droidstar.update_host_files() + updateDialog.open() + } + } + Button { + id: updatedmridsButton + x: 170 + y: updatehostsButton.y + width: 150 + height: 30 + text: qsTr("Update ID files") + onClicked: { + droidstar.update_dmr_ids() + updateDialog.open() + } + } CheckBox { id: toggletx x: 10 - y: 850 + y: 900 //width: 100 height: 25 spacing: 1 @@ -629,7 +697,7 @@ Item { CheckBox { id: xrf2Ref x: 10 - y: 880 + y: 930 //width: 100 height: 25 spacing: 1 @@ -638,85 +706,48 @@ Item { CheckBox { id: ipV6 x: 10 - y: 910 + y: 960 //width: 100 height: 25 spacing: 1 text: qsTr("Use IPv6 when available") } Text { - id: vocoderLabel - x: 10 - y: 940 - width: 80 - height: 25 - text: qsTr("Vocoder") - color: "white" - verticalAlignment: Text.AlignVCenter - } - ComboBox { - id: _comboVocoder - x: 100 - y: 940 - width: parent.width - 110 - height: 30 - } - Text { - id: modemLabel + id: _vocoderURLlabel x: 10 - y: 970 + y: 990 width: 80 height: 25 - text: qsTr("Modem") + text: qsTr("Vocoder URL") color: "white" verticalAlignment: Text.AlignVCenter } - ComboBox { - id: _comboModem + TextField { + id: _vocoderURLEdit x: 100 - y: 970 + y: _vocoderURLlabel.y width: parent.width - 110 - height: 30 - } - Text { - id: playbackLabel - x: 10 - y: 1000 - width: 80 height: 25 - text: qsTr("Playback") - color: "white" - verticalAlignment: Text.AlignVCenter - } - ComboBox { - id: _comboPlayback - x: 100 - y: 1000 - width: parent.width - 110 - height: 30 + selectByMouse: true } - Text { - id: captureLabel + Button { + id: vocoderButton x: 10 - y: 1030 - width: 80 - height: 25 - text: qsTr("Capture") - color: "white" - verticalAlignment: Text.AlignVCenter - } - ComboBox { - id: _comboCapture - x: 100 - y: 1030 - width: parent.width - 110 + y: 1020 + width: 150 height: 30 + text: qsTr("Download vocoder") + onClicked: { + droidstar.download_file(_vocoderURLEdit.text, true); + updateDialog.open(); + } } + Text { id: _modemRXFreqLabel x: 10 - y: 1070 - width: 80 + y: 1090 + width: 60 height: 25 text: qsTr("RX Freq") color: "white" @@ -724,18 +755,18 @@ Item { } TextField { id: _modemRXFreqEdit - x: 100 - y: 1070 - width: parent.width - 110 + x: _modemRXFreqLabel.width+20 + y: _modemRXFreqLabel.y + width: 100 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" } Text { id: _modemTXFreqLabel - x: 10 - y: 1100 - width: 80 + x: _modemRXFreqEdit.x + _modemRXFreqEdit.width + 10 + y: _modemRXFreqLabel.y + width: 60 height: 25 text: qsTr("TX Freq") color: "white" @@ -743,9 +774,9 @@ Item { } TextField { id: _modemTXFreqEdit - x: 100 - y: 1100 - width: parent.width - 110 + x: _modemTXFreqLabel.x + _modemTXFreqLabel.width + y: _modemRXFreqLabel.y + width: 100 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" @@ -753,8 +784,8 @@ Item { Text { id: _modemRXOffsetLabel x: 10 - y: 1130 - width: 80 + y: 1120 + width: 100 height: 25 text: qsTr("RX Offset") color: "white" @@ -762,18 +793,18 @@ Item { } TextField { id: _modemRXOffsetEdit - x: 100 - y: 1130 - width: parent.width - 110 + x: _modemRXOffsetLabel.x + _modemRXOffsetLabel.width + y: _modemRXOffsetLabel.y + width: 60 height: 25 selectByMouse: true //inputMethodHints: "ImhPreferNumbers" } Text { id: _modemTXOffsetLabel - x: 10 - y: 1160 - width: 80 + x: _modemRXOffsetEdit.x + _modemRXOffsetEdit.width + 10 + y: _modemRXOffsetLabel.y + width: 100 height: 25 text: qsTr("TX Offset") color: "white" @@ -781,9 +812,9 @@ Item { } TextField { id: _modemTXOffsetEdit - x: 100 - y: 1160 - width: parent.width - 110 + x: _modemTXOffsetLabel.x + _modemTXOffsetLabel.width + y: _modemRXOffsetLabel.y + width: 60 height: 25 selectByMouse: true //inputMethodHints: "ImhPreferNumbers" @@ -791,8 +822,8 @@ Item { Text { id: _modemRXLevelLabel x: 10 - y: 1190 - width: 80 + y: 1150 + width: 100 height: 25 text: qsTr("RX Level") color: "white" @@ -800,18 +831,18 @@ Item { } TextField { id: _modemRXLevelEdit - x: 100 - y: 1190 - width: parent.width - 110 + x: _modemRXLevelLabel.x + _modemRXLevelLabel.width + y: _modemRXLevelLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" } Text { id: _modemTXLevelLabel - x: 10 - y: 1220 - width: 80 + x: _modemRXLevelEdit.x + _modemRXLevelEdit.width + 10 + y: _modemRXLevelLabel.y + width: 100 height: 25 text: qsTr("TX Level") color: "white" @@ -819,9 +850,9 @@ Item { } TextField { id: _modemTXLevelEdit - x: 100 - y: 1220 - width: parent.width - 110 + x: _modemTXLevelLabel.x + _modemTXLevelLabel.width + y: _modemRXLevelLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" @@ -829,8 +860,8 @@ Item { Text { id: _modemRXDCOffsetLabel x: 10 - y: 1250 - width: 80 + y: 1180 + width: 100 height: 25 text: qsTr("RX DC Offset") color: "white" @@ -838,18 +869,18 @@ Item { } TextField { id: _modemRXDCOffsetEdit - x: 100 - y: 1250 - width: parent.width - 110 + x: _modemRXDCOffsetLabel.x + _modemRXDCOffsetLabel.width + y: _modemRXDCOffsetLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" } Text { id: _modemTXDCOffsetLabel - x: 10 - y: 1280 - width: 80 + x: _modemRXDCOffsetEdit.x + _modemRXDCOffsetEdit.width + 10 + y: _modemRXDCOffsetLabel.y + width: 100 height: 25 text: qsTr("TX DC Offset") color: "white" @@ -857,9 +888,9 @@ Item { } TextField { id: _modemTXDCOffsetEdit - x: 100 - y: 1280 - width: parent.width - 110 + x: _modemTXDCOffsetLabel.x + _modemTXDCOffsetLabel.width + y: _modemRXDCOffsetLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" @@ -867,8 +898,8 @@ Item { Text { id: _modemRFLevelLabel x: 10 - y: 1310 - width: 80 + y: 1210 + width: 100 height: 25 text: qsTr("RF Level") color: "white" @@ -876,18 +907,18 @@ Item { } TextField { id: _modemRFLevelEdit - x: 100 - y: 1310 - width: parent.width - 110 + x: _modemRFLevelLabel.x + _modemRFLevelLabel.width + y: _modemRFLevelLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" } Text { id: _modemTXDelayLabel - x: 10 - y: 1340 - width: 80 + x: _modemRFLevelEdit.x + _modemRFLevelEdit.width + 10 + y: _modemRFLevelLabel.y + width: 100 height: 25 text: qsTr("TX Delay") color: "white" @@ -895,9 +926,9 @@ Item { } TextField { id: _modemTXDelayEdit - x: 100 - y: 1340 - width: parent.width - 110 + x: _modemTXDelayLabel.x + _modemTXDelayLabel.width + y: _modemRFLevelLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" @@ -905,8 +936,8 @@ Item { Text { id: _modemCWIdTXLevelLabel x: 10 - y: 1370 - width: 80 + y: 1240 + width: 100 height: 25 text: qsTr("CWIdTXLevel") color: "white" @@ -914,18 +945,18 @@ Item { } TextField { id: _modemCWIdTXLevelEdit - x: 100 - y: 1370 - width: parent.width - 110 + x: _modemCWIdTXLevelLabel.x + _modemCWIdTXLevelLabel.width + y: _modemCWIdTXLevelLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" } Text { id: _modemDStarTXLevelLabel - x: 10 - y: 1400 - width: 80 + x: _modemCWIdTXLevelEdit.x + _modemCWIdTXLevelEdit.width + 10 + y: _modemCWIdTXLevelLabel.y + width: 100 height: 25 text: qsTr("DStarTXLevel") color: "white" @@ -933,9 +964,9 @@ Item { } TextField { id: _modemDStarTXLevelEdit - x: 100 - y: 1400 - width: parent.width - 110 + x: _modemDStarTXLevelLabel.x + _modemDStarTXLevelLabel.width + y: _modemCWIdTXLevelLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" @@ -943,8 +974,8 @@ Item { Text { id: _modemDMRTXLevelLabel x: 10 - y: 1430 - width: 80 + y: 1270 + width: 100 height: 25 text: qsTr("DMRTXLevel") color: "white" @@ -952,18 +983,18 @@ Item { } TextField { id: _modemDMRTXLevelEdit - x: 100 - y: 1430 - width: parent.width - 110 + x: _modemDMRTXLevelLabel.x + _modemDMRTXLevelLabel.width + y: _modemDMRTXLevelLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" } Text { id: _modemYSFTXLevelLabel - x: 10 - y: 1460 - width: 80 + x: _modemDMRTXLevelEdit.x + _modemDMRTXLevelEdit.width + 10 + y: _modemDMRTXLevelLabel.y + width: 100 height: 25 text: qsTr("YSFTXLevel") color: "white" @@ -971,9 +1002,9 @@ Item { } TextField { id: _modemYSFTXLevelEdit - x: 100 - y: 1460 - width: parent.width - 110 + x: _modemYSFTXLevelLabel.x + _modemYSFTXLevelLabel.width + y: _modemDMRTXLevelLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" @@ -981,8 +1012,8 @@ Item { Text { id: _modemP25TXLevelLabel x: 10 - y: 1490 - width: 80 + y: 1300 + width: 100 height: 25 text: qsTr("P25TXLevel") color: "white" @@ -990,18 +1021,18 @@ Item { } TextField { id: _modemP25TXLevelEdit - x: 100 - y: 1490 - width: parent.width - 110 + x: _modemP25TXLevelLabel.x + _modemP25TXLevelLabel.width + y: _modemP25TXLevelLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" } Text { id: _modemNXDNTXLevelLabel - x: 10 - y: 1520 - width: 80 + x: _modemP25TXLevelEdit.x + _modemP25TXLevelEdit.width + 10 + y: _modemP25TXLevelLabel.y + width: 100 height: 25 text: qsTr("NXDNTXLevel") color: "white" @@ -1009,42 +1040,13 @@ Item { } TextField { id: _modemNXDNTXLevelEdit - x: 100 - y: 1520 - width: parent.width - 110 + x: _modemNXDNTXLevelLabel.x + _modemNXDNTXLevelLabel.width + y: _modemP25TXLevelLabel.y + width: 60 height: 25 selectByMouse: true inputMethodHints: "ImhPreferNumbers" } - Text { - id: _vocoderURLlabel - x: 10 - y: 1550 - width: 80 - height: 25 - text: qsTr("Vocoder URL") - color: "white" - verticalAlignment: Text.AlignVCenter - } - TextField { - id: _vocoderURLEdit - x: 100 - y: 1550 - width: parent.width - 110 - height: 25 - selectByMouse: true - } - Button { - id: vocoderButton - x: 10 - y: 1580 - width: 150 - height: 30 - text: qsTr("Download vocoder") - onClicked: { - droidstar.download_file(_vocoderURLEdit.text, true); - updateDialog.open(); - } - } + } } diff --git a/android/res/xml/device_filter.xml b/android/res/xml/device_filter.xml index 623b3aa..f78cbf9 100644 --- a/android/res/xml/device_filter.xml +++ b/android/res/xml/device_filter.xml @@ -1,6 +1,7 @@ + diff --git a/codec.cpp b/codec.cpp index cf274af..e07a426 100644 --- a/codec.cpp +++ b/codec.cpp @@ -77,6 +77,32 @@ Codec::~Codec() { } +void Codec::ambe_connect_status(bool s) +{ + if(s){ + m_modeinfo.ambedesc = m_ambedev->get_ambe_description(); + m_modeinfo.ambeprodid = m_ambedev->get_ambe_prodid(); + m_modeinfo.ambeverstr = m_ambedev->get_ambe_verstring(); + } + else{ + m_modeinfo.ambeprodid = "Connect failed"; + m_modeinfo.ambeverstr = "Connect failed"; + } + emit update(m_modeinfo); +} + +void Codec::mmdvm_connect_status(bool s) +{ + if(s){ + //m_modeinfo.mmdvmdesc = m_modem->get_mmdvm_description(); + m_modeinfo.mmdvm = m_modem->get_mmdvm_version(); + } + else{ + m_modeinfo.mmdvm = "Connect failed"; + } + emit update(m_modeinfo); +} + void Codec::in_audio_vol_changed(qreal v) { m_audio->set_input_volume(v); diff --git a/codec.h b/codec.h index 9d0961a..f1a551d 100644 --- a/codec.h +++ b/codec.h @@ -72,6 +72,13 @@ public: uint32_t gwid; uint32_t srcid; uint32_t dstid; + uint8_t slot; + uint8_t cc; + QString ambedesc; + QString ambeprodid; + QString ambeverstr; + QString mmdvmdesc; + QString mmdvm; QString host; int port; bool path; @@ -111,6 +118,8 @@ protected slots: virtual void send_disconnect(){} virtual void hostname_lookup(QHostInfo){} virtual void mmdvm_direct_connect(){} + void ambe_connect_status(bool); + void mmdvm_connect_status(bool); void send_connect(); void input_src_changed(int id, QString t) { m_ttsid = id; m_ttstext = t; } void start_tx(); @@ -127,7 +136,8 @@ protected slots: void urcall_changed(QString uc) { m_txurcall = uc; } void rptr1_changed(QString r1) { m_txrptr1 = r1; } void rptr2_changed(QString r2) { m_txrptr2 = r2; } - void module_changed(char m) { m_module = m; m_modeinfo.streamid = 0; qDebug() << "Codec::module_changed() m == " << m; } + void usrtxt_changed(QString t) { m_txusrtxt = t; } + void module_changed(char m) { m_module = m; m_modeinfo.streamid = 0; } protected: QUdpSocket *m_udp = nullptr; QHostAddress m_address; @@ -142,6 +152,7 @@ protected: QString m_txurcall; QString m_txrptr1; QString m_txrptr2; + QString m_txusrtxt; #ifdef USE_FLITE cst_voice *voice_slt; cst_voice *voice_kal; diff --git a/dcscodec.cpp b/dcscodec.cpp index 2d3fb07..1742c2e 100755 --- a/dcscodec.cpp +++ b/dcscodec.cpp @@ -70,6 +70,7 @@ void DCSCodec::process_udp() m_modeinfo.hw_vocoder_loaded = true; 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())); } else{ @@ -81,6 +82,7 @@ void DCSCodec::process_udp() m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex); m_modem->set_modem_params(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))); } m_rxtimer = new QTimer(); @@ -152,7 +154,7 @@ void DCSCodec::process_udp() m_modeinfo.stream_state = STREAMING; } - m_modeinfo.frame_number = buf.data()[0x2d]; + m_modeinfo.frame_number = (uint8_t)buf.data()[0x2d]; if((buf.data()[45] == 0) && (buf.data()[55] == 0x55) && (buf.data()[56] == 0x2d) && (buf.data()[57] == 0x16)){ sd_sync = 1; @@ -434,8 +436,8 @@ void DCSCodec::send_frame(uint8_t *ambe) txdata.replace(23, 8, m_txurcall.toLocal8Bit().data()); txdata.replace(31, 8, m_txmycall.toLocal8Bit().data()); txdata.replace(39, 4, "AMBE"); - txdata[43] = txstreamid & 0xff; - txdata[44] = (txstreamid >> 8) & 0xff; + txdata[43] = (txstreamid >> 8) & 0xff; + txdata[44] = txstreamid & 0xff; txdata[45] = (m_txcnt % 21) & 0xff; memcpy(txdata.data() + 46, ambe, 9); diff --git a/dmrcodec.cpp b/dmrcodec.cpp index 13b3b2f..7f8c89a 100755 --- a/dmrcodec.cpp +++ b/dmrcodec.cpp @@ -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, @@ -52,11 +52,12 @@ DMRCodec::DMRCodec(QString callsign, uint32_t dmrid, uint8_t essid, QString pass m_swid(swid), m_pkid(pkid), m_txdstid(dstid), - m_pc(false), + m_txslot(2), + m_txcc(1), m_options(options) { m_dmrcnt = 0; - m_flco = FLCO(0); + m_flco = FLCO_GROUP; if (essid){ m_essid = m_dmrid * 100 + (essid-1); @@ -209,7 +210,8 @@ void DMRCodec::process_udp() m_modeinfo.dstid = (uint32_t)((buf.data()[8] << 16) | ((buf.data()[9] << 8) & 0xff00) | (buf.data()[10] & 0xff)); m_modeinfo.gwid = (uint32_t)((buf.data()[11] << 24) | ((buf.data()[12] << 16) & 0xff0000) | ((buf.data()[13] << 8) & 0xff00) | (buf.data()[14] & 0xff)); m_modeinfo.streamid = (uint32_t)((buf.data()[16] << 24) | ((buf.data()[17] << 16) & 0xff0000) | ((buf.data()[18] << 8) & 0xff00) | (buf.data()[19] & 0xff)); - m_modeinfo.frame_number = buf.data()[4]; + m_modeinfo.frame_number = (uint8_t)buf.data()[4]; + m_modeinfo.slot = (buf.data()[15] & 0x80) ? 2 : 1; t = 0x41; qDebug() << "New DMR stream from " << m_modeinfo.srcid << " to " << m_modeinfo.dstid; } @@ -261,7 +263,7 @@ void DMRCodec::process_udp() m_modeinfo.dstid = (uint32_t)((buf.data()[8] << 16) | ((buf.data()[9] << 8) & 0xff00) | (buf.data()[10] & 0xff)); m_modeinfo.gwid = (uint32_t)((buf.data()[11] << 24) | ((buf.data()[12] << 16) & 0xff0000) | ((buf.data()[13] << 8) & 0xff00) | (buf.data()[14] & 0xff)); m_modeinfo.streamid = (uint32_t)((buf.data()[16] << 24) | ((buf.data()[17] << 16) & 0xff0000) | ((buf.data()[18] << 8) & 0xff00) | (buf.data()[19] & 0xff)); - m_modeinfo.frame_number = buf.data()[4]; + m_modeinfo.frame_number = (uint8_t)buf.data()[4]; if(m_modem){ uint8_t t = ((uint8_t)buf.data()[15] & 0x0f); @@ -315,6 +317,7 @@ void DMRCodec::setup_connection() m_modeinfo.hw_vocoder_loaded = true; 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())); } else{ @@ -326,6 +329,7 @@ void DMRCodec::setup_connection() m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex); m_modem->set_modem_params(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))); } m_audio = new AudioEngine(m_audioin, m_audioout); @@ -499,15 +503,11 @@ void DMRCodec::transmit() void DMRCodec::send_frame() { QByteArray txdata; - if(m_pc){ - set_calltype(3); - } - else{ - set_calltype(0); - } + m_txsrcid = m_dmrid; if(m_tx){ m_modeinfo.stream_state = TRANSMITTING; + m_modeinfo.slot = m_txslot; if(!m_dmrcnt){ encode_header(DT_VOICE_LC_HEADER); @@ -578,6 +578,7 @@ unsigned char * DMRCodec::get_eot() void DMRCodec::build_frame() { + qDebug() << "DMR: slot:cc == " << m_txslot << ":" << m_txcc; m_dmrFrame[0U] = 'D'; m_dmrFrame[1U] = 'M'; m_dmrFrame[2U] = 'R'; @@ -594,7 +595,7 @@ void DMRCodec::build_frame() m_dmrFrame[13U] = m_essid >> 8; m_dmrFrame[14U] = m_essid >> 0; - m_dmrFrame[15U] = (m_slot == 1U) ? 0x00U : 0x80U; + m_dmrFrame[15U] = (m_txslot == 1U) ? 0x00U : 0x80U; m_dmrFrame[15U] |= (m_flco == FLCO_GROUP) ? 0x00U : 0x40U; if (m_dataType == DT_VOICE_SYNC) { @@ -661,7 +662,7 @@ void DMRCodec::encode_qr1676(uint8_t* data) void DMRCodec::get_emb_data(uint8_t* data, uint8_t lcss) { uint8_t DMREMB[2U]; - DMREMB[0U] = (m_colorcode << 4) & 0xF0U; + DMREMB[0U] = (m_modeinfo.cc << 4) & 0xF0U; //DMREMB[0U] |= m_PI ? 0x08U : 0x00U; DMREMB[0U] |= (lcss << 1) & 0x06U; DMREMB[1U] = 0x00U; @@ -867,7 +868,7 @@ void DMRCodec::full_lc_encode(uint8_t* data, uint8_t type) // for header void DMRCodec::get_slot_data(uint8_t* data) { uint8_t DMRSlotType[3U]; - DMRSlotType[0U] = (m_colorcode << 4) & 0xF0U; + DMRSlotType[0U] = (m_modeinfo.cc << 4) & 0xF0U; DMRSlotType[0U] |= (m_dataType << 0) & 0x0FU; DMRSlotType[1U] = 0x00U; DMRSlotType[2U] = 0x00U; diff --git a/dmrcodec.h b/dmrcodec.h index 49866d7..eaf13c3 100755 --- a/dmrcodec.h +++ b/dmrcodec.h @@ -30,9 +30,6 @@ public: DMRCodec(QString callsign, uint32_t dmrid, uint8_t essid, QString password, QString lat, QString lon, QString location, QString desc, QString freq, QString url, QString swid, QString pkid, QString options, uint32_t dstid, QString host, uint32_t port, bool ipv6, QString vocoder, QString modem, QString audioin, QString audioout); ~DMRCodec(); unsigned char * get_eot(); - void set_cc(uint32_t cc){m_colorcode = cc;} - void set_slot(uint32_t s){m_slot = s;} - void set_calltype(uint8_t c){m_flco = FLCO(c);} private slots: void process_udp(); void process_rx_data(); @@ -43,9 +40,9 @@ private slots: void transmit(); void hostname_lookup(QHostInfo i); void dmr_tgid_changed(unsigned int id) { m_txdstid = id; } - void dmr_cc_changed(int cc) {m_colorcode = cc + 1; } - void dmr_slot_changed(int s) {m_slot = s + 1; } - void dmrpc_state_changed(int pc){ m_pc = (pc ? true : false); } + void dmrpc_state_changed(int p){m_flco = p ? FLCO_USER_USER : FLCO_GROUP; } + void cc_changed(int cc) {m_txcc = cc + 1; } + void slot_changed(int s) {m_txslot = s + 1; } void send_frame(); private: uint32_t m_dmrid; @@ -62,15 +59,14 @@ private: uint32_t m_txsrcid; uint32_t m_txdstid; uint32_t m_txstreamid; + uint8_t m_txslot; + uint8_t m_txcc; uint8_t packet_size; uint8_t m_ambe[27]; uint32_t m_defsrcid; uint8_t m_dmrFrame[55]; uint8_t m_dataType; - uint32_t m_colorcode; - uint32_t m_slot; uint32_t m_dmrcnt; - bool m_pc; FLCO m_flco; CBPTC19696 m_bptc; bool m_raw[128U]; diff --git a/droidstar.cpp b/droidstar.cpp index db392e3..bcd8570 100644 --- a/droidstar.cpp +++ b/droidstar.cpp @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include #include @@ -327,11 +329,13 @@ void DroidStar::process_connect() connect(this, SIGNAL(urcall_changed(QString)), m_ref, SLOT(urcall_changed(QString))); connect(this, SIGNAL(rptr1_changed(QString)), m_ref, SLOT(rptr1_changed(QString))); connect(this, SIGNAL(rptr2_changed(QString)), m_ref, SLOT(rptr2_changed(QString))); + connect(this, SIGNAL(usrtxt_changed(QString)), m_ref, SLOT(usrtxt_changed(QString))); emit module_changed(m_module); emit mycall_changed(m_mycall); emit urcall_changed(m_urcall); emit rptr1_changed(m_rptr1); emit rptr2_changed(m_rptr2); + emit usrtxt_changed(m_dstarusertxt); m_modethread->start(); } if(m_protocol == "DCS"){ @@ -355,10 +359,12 @@ void DroidStar::process_connect() connect(this, SIGNAL(urcall_changed(QString)), m_dcs, SLOT(urcall_changed(QString))); connect(this, SIGNAL(rptr1_changed(QString)), m_dcs, SLOT(rptr1_changed(QString))); connect(this, SIGNAL(rptr2_changed(QString)), m_dcs, SLOT(rptr2_changed(QString))); + connect(this, SIGNAL(usrtxt_changed(QString)), m_dcs, SLOT(usrtxt_changed(QString))); emit mycall_changed(m_mycall); emit urcall_changed(m_urcall); emit rptr1_changed(m_rptr1); emit rptr2_changed(m_rptr2); + emit usrtxt_changed(m_dstarusertxt); m_modethread->start(); } if( (m_protocol == "XRF") && (m_xrf2ref == false) ){ @@ -382,10 +388,12 @@ void DroidStar::process_connect() connect(this, SIGNAL(urcall_changed(QString)), m_xrf, SLOT(urcall_changed(QString))); connect(this, SIGNAL(rptr1_changed(QString)), m_xrf, SLOT(rptr1_changed(QString))); connect(this, SIGNAL(rptr2_changed(QString)), m_xrf, SLOT(rptr2_changed(QString))); + connect(this, SIGNAL(usrtxt_changed(QString)), m_xrf, SLOT(usrtxt_changed(QString))); emit mycall_changed(m_mycall); emit urcall_changed(m_urcall); emit rptr1_changed(m_rptr1); emit rptr2_changed(m_rptr2); + emit usrtxt_changed(m_dstarusertxt); m_modethread->start(); } if(m_protocol == "DMR"){ @@ -406,7 +414,6 @@ void DroidStar::process_connect() m_dmr = new DMRCodec(m_callsign, m_dmrid, m_essid, dmrpass, m_latitude, m_longitude, m_location, m_description, m_freq, m_url, m_swid, m_pkgid, m_dmropts, m_dmr_destid, m_hostname, m_port, false, vocoder, modem, m_playback, m_capture); m_dmr->set_modem_flags(rxInvert, txInvert, pttInvert, useCOSAsLockout, duplex); m_dmr->set_modem_params(m_modemRxFreq.toInt(), m_modemTxFreq.toInt(), 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); - m_dmr->set_cc(1); m_modethread = new QThread; m_dmr->moveToThread(m_modethread); connect(m_dmr, SIGNAL(update(Codec::MODEINFO)), this, SLOT(update_dmr_data(Codec::MODEINFO))); @@ -421,6 +428,8 @@ void DroidStar::process_connect() connect(this, SIGNAL(tx_released()), m_dmr, SLOT(stop_tx())); connect(this, SIGNAL(dmr_tgid_changed(unsigned int)), m_dmr, SLOT(dmr_tgid_changed(unsigned int))); connect(this, SIGNAL(dmrpc_state_changed(int)), m_dmr, SLOT(dmrpc_state_changed(int))); + connect(this, SIGNAL(slot_changed(int)), m_dmr, SLOT(slot_changed(int))); + connect(this, SIGNAL(cc_changed(int)), m_dmr, SLOT(cc_changed(int))); connect(this, SIGNAL(in_audio_vol_changed(qreal)), m_dmr, SLOT(in_audio_vol_changed(qreal))); m_modethread->start(); } @@ -616,7 +625,7 @@ void DroidStar::process_mode_change(const QString &m) m_label2 = "SrcID"; m_label3 = "DestID"; m_label4 = "GWID"; - m_label5 = "Seq#"; + m_label5 = "Info"; m_label6 = ""; } if(m == "P25"){ @@ -1378,13 +1387,31 @@ void DroidStar::update_ref_data(Codec::MODEINFO info) emit update_log("No vocoder plugin found"); } } - m_statustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + + m_netstatustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + m_ambestatustxt = "AMBE: " + (info.ambeprodid.isEmpty() ? "No device" : info.ambeprodid); + m_mmdvmstatustxt = "MMDVM: "; + + if(info.mmdvm.isEmpty()){ + m_mmdvmstatustxt += "No device"; + } + + QStringList verlist = info.ambeverstr.split('.'); + if(verlist.size() > 7){ + m_ambestatustxt += " " + verlist.at(0) + " " + verlist.at(5); + } + + verlist = info.mmdvm.split(' '); + if(verlist.size() > 3){ + m_mmdvmstatustxt += verlist.at(0) + " " + verlist.at(1); + } + if(info.streamid){ m_data1 = info.src; m_data2 = info.dst; m_data3 = info.gw; m_data4 = info.gw2; - m_data5 = QString::number(info.streamid, 16) + " " + QString::number(info.frame_number, 16); + m_data5 = QString::number(info.streamid, 16) + " " + QString("%1").arg(info.frame_number, 2, 16, QChar('0')); m_data6 = info.usertxt; } else{ @@ -1433,13 +1460,31 @@ void DroidStar::update_dcs_data(Codec::MODEINFO info) emit update_log("No vocoder plugin found"); } } - m_statustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.status); + + m_netstatustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + m_ambestatustxt = "AMBE: " + (info.ambeprodid.isEmpty() ? "No device" : info.ambeprodid); + m_mmdvmstatustxt = "MMDVM: "; + + if(info.mmdvm.isEmpty()){ + m_mmdvmstatustxt += "No device"; + } + + QStringList verlist = info.ambeverstr.split('.'); + if(verlist.size() > 7){ + m_ambestatustxt += " " + verlist.at(0) + " " + verlist.at(5); + } + + verlist = info.mmdvm.split(' '); + if(verlist.size() > 3){ + m_mmdvmstatustxt += verlist.at(0) + " " + verlist.at(1); + } + if(info.streamid){ m_data1 = info.src; m_data2 = info.dst; m_data3 = info.gw; m_data4 = info.gw2; - m_data5 = QString::number(info.streamid, 16) + " " + QString::number(info.frame_number, 16); + m_data5 = QString::number(info.streamid, 16) + " " + QString("%1").arg(info.frame_number, 2, 16, QChar('0')); m_data6 = info.usertxt; } else{ @@ -1489,13 +1534,31 @@ void DroidStar::update_xrf_data(Codec::MODEINFO info) emit update_log("No vocoder plugin found"); } } - m_statustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + + m_netstatustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + m_ambestatustxt = "AMBE: " + (info.ambeprodid.isEmpty() ? "No device" : info.ambeprodid); + m_mmdvmstatustxt = "MMDVM: "; + + if(info.mmdvm.isEmpty()){ + m_mmdvmstatustxt += "No device"; + } + + QStringList verlist = info.ambeverstr.split('.'); + if(verlist.size() > 7){ + m_ambestatustxt += " " + verlist.at(0) + " " + verlist.at(5); + } + + verlist = info.mmdvm.split(' '); + if(verlist.size() > 3){ + m_mmdvmstatustxt += verlist.at(0) + " " + verlist.at(1); + } + if(info.streamid){ m_data1 = info.src; m_data2 = info.dst; m_data3 = info.gw; m_data4 = info.gw2; - m_data5 = QString::number(info.streamid, 16) + " " + QString::number(info.frame_number, 16); + m_data5 = QString::number(info.streamid, 16) + " " + QString("%1").arg(info.frame_number, 2, 16, QChar('0')); m_data6 = info.usertxt; } else{ @@ -1536,7 +1599,25 @@ void DroidStar::update_nxdn_data(Codec::MODEINFO info) emit update_log("No vocoder plugin found"); } } - m_statustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + + m_netstatustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + m_ambestatustxt = "AMBE: " + (info.ambeprodid.isEmpty() ? "No device" : info.ambeprodid); + m_mmdvmstatustxt = "MMDVM: "; + + if(info.mmdvm.isEmpty()){ + m_mmdvmstatustxt += "No device"; + } + + QStringList verlist = info.ambeverstr.split('.'); + if(verlist.size() > 7){ + m_ambestatustxt += " " + verlist.at(0) + " " + verlist.at(5); + } + + verlist = info.mmdvm.split(' '); + if(verlist.size() > 3){ + m_mmdvmstatustxt += verlist.at(0) + " " + verlist.at(1); + } + if(info.stream_state == Codec::STREAM_IDLE){ m_data1.clear(); m_data2.clear(); @@ -1599,7 +1680,25 @@ void DroidStar::update_dmr_data(Codec::MODEINFO info) emit update_log("No vocoder plugin found"); } } - m_statustxt = "Host: " + m_host + " Cnt: " + QString::number(info.count); + + m_netstatustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + m_ambestatustxt = "AMBE: " + (info.ambeprodid.isEmpty() ? "No device" : info.ambeprodid); + m_mmdvmstatustxt = "MMDVM: "; + + if(info.mmdvm.isEmpty()){ + m_mmdvmstatustxt += "No device"; + } + + QStringList verlist = info.ambeverstr.split('.'); + if(verlist.size() > 7){ + m_ambestatustxt += " " + verlist.at(0) + " " + verlist.at(5); + } + + verlist = info.mmdvm.split(' '); + if(verlist.size() > 3){ + m_mmdvmstatustxt += verlist.at(0) + " " + verlist.at(1); + } + if(info.stream_state == Codec::STREAM_IDLE){ m_data1.clear(); m_data2.clear(); @@ -1613,9 +1712,26 @@ void DroidStar::update_dmr_data(Codec::MODEINFO info) m_data2 = info.srcid ? QString::number(info.srcid) : ""; m_data3 = info.dstid ? QString::number(info.dstid) : ""; m_data4 = info.gwid ? QString::number(info.gwid) : ""; + QString s = "Slot" + QString::number(info.slot); + QString flco; + + switch( (info.slot & 0x40) >> 6){ + case 0: + flco = "Group"; + break; + case 3: + flco = "Private"; + break; + case 8: + flco = "GPS"; + break; + default: + flco = "Unknown"; + break; + } if(info.frame_number){ - QString n = QString("%1").arg(info.frame_number, 4, 16, QChar('0')); + QString n = s + " " + flco + " " + QString("%1").arg(info.frame_number, 2, 16, QChar('0')); m_data5 = n; } } @@ -1652,7 +1768,25 @@ void DroidStar::update_ysf_data(Codec::MODEINFO info) } } } - m_statustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + + m_netstatustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + m_ambestatustxt = "AMBE: " + (info.ambeprodid.isEmpty() ? "No device" : info.ambeprodid); + m_mmdvmstatustxt = "MMDVM: "; + + if(info.mmdvm.isEmpty()){ + m_mmdvmstatustxt += "No device"; + } + + QStringList verlist = info.ambeverstr.split('.'); + if(verlist.size() > 7){ + m_ambestatustxt += " " + verlist.at(0) + " " + verlist.at(5); + } + + verlist = info.mmdvm.split(' '); + if(verlist.size() > 3){ + m_mmdvmstatustxt += verlist.at(0) + " " + verlist.at(1); + } + if(info.stream_state == Codec::STREAM_IDLE){ m_data1.clear(); m_data2.clear(); @@ -1708,9 +1842,29 @@ void DroidStar::update_p25_data(Codec::MODEINFO info) connect_status = Codec::CONNECTED_RW; emit connect_status_changed(2); emit in_audio_vol_changed(0.3); + emit swtx_state(!m_p25->get_hwtx()); + emit swrx_state(!m_p25->get_hwrx()); emit update_log("Connected to " + m_protocol + " " + m_host + " " + m_hostname + ":" + QString::number(m_port)); } - m_statustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + + m_netstatustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + m_ambestatustxt = "AMBE: " + (info.ambeprodid.isEmpty() ? "No device" : info.ambeprodid); + m_mmdvmstatustxt = "MMDVM: "; + + if(info.mmdvm.isEmpty()){ + m_mmdvmstatustxt += "No device"; + } + + QStringList verlist = info.ambeverstr.split('.'); + if(verlist.size() > 7){ + m_ambestatustxt += " " + verlist.at(0) + " " + verlist.at(5); + } + + verlist = info.mmdvm.split(' '); + if(verlist.size() > 3){ + m_mmdvmstatustxt += verlist.at(0) + " " + verlist.at(1); + } + if(info.stream_state == Codec::STREAM_IDLE){ m_data1.clear(); m_data2.clear(); @@ -1725,7 +1879,7 @@ void DroidStar::update_p25_data(Codec::MODEINFO info) m_data3 = info.dstid ? QString::number(info.dstid) : ""; m_data4 = info.srcid ? QString::number(info.srcid) : ""; if(info.frame_number){ - QString n = QString("%1").arg(info.frame_number, 4, 16, QChar('0')); + QString n = QString("%1").arg(info.frame_number, 2, 16, QChar('0')); m_data5 = n; } } @@ -1748,9 +1902,28 @@ void DroidStar::update_m17_data(M17Codec::MODEINFO info) connect_status = Codec::CONNECTED_RW; emit connect_status_changed(2); emit in_audio_vol_changed(0.5); + emit swtx_state(!m_m17->get_hwtx()); + emit swrx_state(!m_m17->get_hwrx()); emit update_log("Connected to " + m_protocol + " " + m_host + " " + m_hostname + ":" + QString::number(m_port)); } - m_statustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + + m_netstatustxt = "Host: " + m_hostname + ":" + QString::number(m_port) + " Cnt: " + QString::number(info.count); + m_ambestatustxt = "AMBE: " + (info.ambeprodid.isEmpty() ? "No device" : info.ambeprodid); + m_mmdvmstatustxt = "MMDVM: "; + + if(info.mmdvm.isEmpty()){ + m_mmdvmstatustxt += "No device"; + } + + QStringList verlist = info.ambeverstr.split('.'); + if(verlist.size() > 7){ + m_ambestatustxt += " " + verlist.at(0) + " " + verlist.at(5) + " " + verlist.at(6); + } + + verlist = info.mmdvm.split(' '); + if(verlist.size() > 3){ + m_mmdvmstatustxt += verlist.at(0) + " " + verlist.at(1); + } if(info.streamid){ m_data1 = info.src; @@ -1795,8 +1968,8 @@ void DroidStar::update_iax_data() emit in_audio_vol_changed(0.5); emit update_log("Connected to " + m_protocol + " " + m_iaxhost + ":" + QString::number(m_iaxport)); } - m_statustxt = "Host: " + m_iaxhost + ":" + QString::number(m_iaxport) + " Cnt: " + QString::number(m_iax->get_cnt()); + m_netstatustxt = "Host: " + m_iaxhost + ":" + QString::number(m_iaxport) + " Cnt: " + QString::number(m_iax->get_cnt()); emit update_data(); } diff --git a/droidstar.h b/droidstar.h index 1d392b7..ddbf3a0 100644 --- a/droidstar.h +++ b/droidstar.h @@ -41,6 +41,8 @@ public: signals: void mode_changed(); void module_changed(char); + void slot_changed(int); + void cc_changed(int); void update_data(); void update_log(QString); void open_vocoder_dialog(); @@ -64,10 +66,13 @@ signals: void rptr2_changed(QString); void mycall_changed(QString); void urcall_changed(QString); + void usrtxt_changed(QString); 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(); } - void tgid_text_changed(QString s){ qDebug() << "dmrid_text_changed() called s == " << s; emit dmr_tgid_changed(s.toUInt());} + void set_slot(const int slot) {emit slot_changed(slot); } + void set_cc(const int cc) {emit cc_changed(cc); } + void tgid_text_changed(QString s){emit dmr_tgid_changed(s.toUInt());} void set_dmrid(const QString &dmrid) { m_dmrid = dmrid.simplified().toUInt(); save_settings(); } void set_essid(const QString &essid) { @@ -104,6 +109,7 @@ public slots: void set_urcall(const QString &urcall) { m_urcall = urcall; save_settings(); emit urcall_changed(urcall); } void set_rptr1(const QString &rptr1) { m_rptr1 = rptr1; save_settings(); emit rptr1_changed(rptr1); } void set_rptr2(const QString &rptr2) { m_rptr2 = rptr2; save_settings(); emit rptr2_changed(rptr2); } + void set_usrtxt(const QString &usrtxt) { m_dstarusertxt = usrtxt; save_settings(); emit usrtxt_changed(usrtxt); } void set_txtimeout(const QString &t) { m_txtimeout = t.simplified().toUInt(); save_settings();} void set_toggletx(bool x) { m_toggletx = x; save_settings(); } void set_xrf2ref(bool x) { m_xrf2ref = x; save_settings(); } @@ -134,7 +140,7 @@ public slots: void set_modemP25TxLevel(QString m) { m_modemP25TxLevel = m; save_settings(); } void set_modemNXDNTxLevel(QString m) { m_modemNXDNTxLevel = m; save_settings(); } - void m17_rate_changed(bool r) { qDebug() << "m17_rate_changed() r == " << r; emit m17_rate_changed((int)r); } + void m17_rate_changed(bool r) { emit m17_rate_changed((int)r); } void process_connect(); void press_tx(); void release_tx(); @@ -161,7 +167,9 @@ public slots: QString get_data4() { return m_data4; } QString get_data5() { return m_data5; } QString get_data6() { return m_data6; } - QString get_statustxt() { return m_statustxt; } + QString get_ambestatustxt() { return m_ambestatustxt; } + QString get_mmdvmstatustxt() { return m_mmdvmstatustxt; } + QString get_netstatustxt() { return m_netstatustxt; } QString get_mode() { return m_protocol; } QString get_host() { return m_host; } QString get_module() { return QString(m_module); } @@ -228,9 +236,15 @@ public slots: #if defined(Q_OS_ANDROID) QString get_platform() { return QSysInfo::productType(); } void reset_connect_status(); + QString get_monofont() { return "Droid Sans Mono"; } +#elif defined(Q_OS_WIN) + QString get_platform() { return QSysInfo::kernelType(); } + void reset_connect_status() {} + QString get_monofont() { return "Courier"; } #else QString get_platform() { return QSysInfo::kernelType(); } void reset_connect_status() {} + QString get_monofont() { return "monospace"; } #endif QString get_arch() { return QSysInfo::currentCpuArchitecture(); } QString get_build_abi() { return QSysInfo::buildAbi(); } @@ -292,7 +306,9 @@ private: QString m_data4; QString m_data5; QString m_data6; - QString m_statustxt; + QString m_ambestatustxt; + QString m_mmdvmstatustxt; + QString m_netstatustxt; QString m_mycall; QString m_urcall; QString m_rptr1; diff --git a/m17codec.cpp b/m17codec.cpp index e95429a..a84a86e 100755 --- a/m17codec.cpp +++ b/m17codec.cpp @@ -185,6 +185,7 @@ void M17Codec::process_udp() m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex); m_modem->set_modem_params(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))); } @@ -318,6 +319,7 @@ void M17Codec::mmdvm_direct_connect() m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex); m_modem->set_modem_params(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))); if(m_modeinfo.status == CONNECTING){ m_modeinfo.status = CONNECTED_RW; diff --git a/main.qml b/main.qml index bec4da6..e1e9134 100644 --- a/main.qml +++ b/main.qml @@ -25,7 +25,7 @@ ApplicationWindow { // @disable-check M16 visible: true // @disable-check M16 - width: 320 + width: 340 // @disable-check M16 height: 480 // @disable-check M16 @@ -151,6 +151,12 @@ ApplicationWindow { 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(); + mainTab.data4.font.family = droidstar.get_monofont(); + mainTab.data5.font.family = droidstar.get_monofont(); + mainTab.data6.font.family = droidstar.get_monofont(); } function onSwtx_state(s){ mainTab.swtxBox.checked = s; @@ -186,134 +192,144 @@ ApplicationWindow { droidstar.set_modelchange(false); mainTab.comboMode.currentIndex = mainTab.comboMode.find(droidstar.get_mode()); if(droidstar.get_mode() === "REF"){ + //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; - mainTab.element1.text = "Host"; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_ref_host()); mainTab.comboModule.visible = true; + mainTab.comboSlot.visible = false; + mainTab.comboCC.visible = false; mainTab.element3.visible = false; mainTab.dmrtgidEdit.visible = false; mainTab.privateBox.visible = false; - mainTab.element4.visible = true; - settingsTab.sliderMicGain.value = 0.0; + mainTab.sliderMicGain.value = 0.0; } if(droidstar.get_mode() === "DCS"){ + //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; - mainTab.element1.text = "Host"; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_dcs_host()); mainTab.comboModule.visible = true; + mainTab.comboSlot.visible = false; + mainTab.comboCC.visible = false; mainTab.element3.visible = false; mainTab.dmrtgidEdit.visible = false; mainTab.privateBox.visible = false; - mainTab.element4.visible = true; - settingsTab.sliderMicGain.value = 0.0; + mainTab.sliderMicGain.value = 0.0; } if(droidstar.get_mode() === "XRF"){ + //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; - mainTab.element1.text = "Host"; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_xrf_host()); mainTab.comboModule.visible = true; + mainTab.comboSlot.visible = false; + mainTab.comboCC.visible = false; mainTab.element3.visible = false; mainTab.dmrtgidEdit.visible = false; mainTab.privateBox.visible = false; - mainTab.element4.visible = true; - settingsTab.sliderMicGain.value = 0.0; + mainTab.sliderMicGain.value = 0.0; } if(droidstar.get_mode() === "YSF"){ + //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; - mainTab.element1.text = "Host"; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_ysf_host()); mainTab.comboModule.visible = false; + mainTab.comboSlot.visible = false; + mainTab.comboCC.visible = false; mainTab.element3.visible = false; mainTab.dmrtgidEdit.visible = false; mainTab.privateBox.visible = false; - mainTab.element4.visible = false; - settingsTab.sliderMicGain.value = 0.2; + mainTab.sliderMicGain.value = 0.2; } if(droidstar.get_mode() === "FCS"){ + //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; - mainTab.element1.text = "Host"; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_fcs_host()); mainTab.comboModule.visible = false; + mainTab.comboSlot.visible = false; + mainTab.comboCC.visible = false; mainTab.element3.visible = false; mainTab.dmrtgidEdit.visible = false; mainTab.privateBox.visible = false; - mainTab.element4.visible = false; - settingsTab.sliderMicGain.value = 0.2; + mainTab.sliderMicGain.value = 0.2; } if(droidstar.get_mode() === "DMR"){ + //mainTab.comboMode.width = (mainTab.width / 5) - 5; mainTab.comboHost.visible = true; - mainTab.element1.text = "Host"; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_dmr_host()); mainTab.comboModule.visible = false; + mainTab.comboSlot.visible = true; + mainTab.comboCC.visible = true; mainTab.element3.visible = true; mainTab.dmrtgidEdit.visible = true; mainTab.privateBox.visible = true; - mainTab.element4.visible = false; - settingsTab.sliderMicGain.value = 0.3; + mainTab.sliderMicGain.value = 0.3; } if(droidstar.get_mode() === "P25"){ + //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; - mainTab.element1.text = "Host"; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_p25_host()); mainTab.comboModule.visible = false; + mainTab.comboSlot.visible = false; + mainTab.comboCC.visible = false; mainTab.element3.visible = true; mainTab.dmrtgidEdit.visible = true; mainTab.privateBox.visible = false; - mainTab.element4.visible = false; - settingsTab.sliderMicGain.value = 0.3; + mainTab.sliderMicGain.value = 0.3; } if(droidstar.get_mode() === "NXDN"){ + //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; - mainTab.element1.text = "Host"; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_nxdn_host()); mainTab.comboModule.visible = false; + mainTab.comboSlot.visible = false; + mainTab.comboCC.visible = false; mainTab.element3.visible = false; mainTab.dmrtgidEdit.visible = false; mainTab.privateBox.visible = false; - mainTab.element4.visible = false; - settingsTab.sliderMicGain.value = 0.3; + mainTab.sliderMicGain.value = 0.3; } if(droidstar.get_mode() === "M17"){ + //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = true; - mainTab.element1.text = "Host"; mainTab.editIAXDTMF.visible = false; mainTab.dtmfsendbutton.visible = false; mainTab.comboHost.currentIndex = mainTab.comboHost.find(droidstar.get_m17_host()); mainTab.comboModule.currentIndex = mainTab.comboModule.find(droidstar.get_module()); mainTab.comboModule.visible = true; + mainTab.comboSlot.visible = false; + mainTab.comboCC.visible = false; mainTab.element3.visible = false; mainTab.dmrtgidEdit.visible = false; mainTab.privateBox.visible = false; - mainTab.element4.visible = true; - settingsTab.sliderMicGain.value = 0.5; + mainTab.sliderMicGain.value = 0.5; } if(droidstar.get_mode() === "IAX"){ + //mainTab.comboMode.width = mainTab.width / 2; mainTab.comboHost.visible = false; - mainTab.element1.text = "DTMF *"; mainTab.editIAXDTMF.visible = true; mainTab.dtmfsendbutton.visible = true; mainTab.comboModule.visible = false; + mainTab.comboSlot.visible = false; + mainTab.comboCC.visible = false; mainTab.element3.visible = false; mainTab.dmrtgidEdit.visible = false; mainTab.privateBox.visible = false; - mainTab.element4.visible = false; - settingsTab.sliderMicGain.value = 0.5; + mainTab.sliderMicGain.value = 0.5; } } function onUpdate_data() { @@ -323,7 +339,9 @@ ApplicationWindow { mainTab.data4.text = droidstar.get_data4(); mainTab.data5.text = droidstar.get_data5(); mainTab.data6.text = droidstar.get_data6(); - mainTab.status.text = droidstar.get_statustxt(); + mainTab.ambestatus.text = droidstar.get_ambestatustxt(); + mainTab.mmdvmstatus.text = droidstar.get_mmdvmstatustxt(); + mainTab.netstatus.text = droidstar.get_netstatustxt(); ++mainTab.uitimer.rxcnt; } function onUpdate_settings() { @@ -432,7 +450,7 @@ ApplicationWindow { mainTab.data4.text = ""; mainTab.data5.text = ""; mainTab.data6.text = ""; - mainTab.status.text = "Not connected"; + mainTab.netstatus.text = "Not connected"; } if(c === 1){ mainTab.connectbutton.text = "Connecting"; diff --git a/nxdncodec.cpp b/nxdncodec.cpp index caea928..ce33036 100755 --- a/nxdncodec.cpp +++ b/nxdncodec.cpp @@ -86,6 +86,7 @@ void NXDNCodec::process_udp() m_modeinfo.hw_vocoder_loaded = true; 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())); } else{ diff --git a/p25codec.cpp b/p25codec.cpp index 18fe442..2668763 100755 --- a/p25codec.cpp +++ b/p25codec.cpp @@ -113,7 +113,7 @@ void P25Codec::process_udp() } m_rxwatchdog = 0; int offset = 0; - m_modeinfo.frame_number = buf.data()[0U]; + m_modeinfo.frame_number = (uint8_t)buf.data()[0U]; switch ((uint8_t)buf.data()[0U]) { case 0x62U: offset = 10U; diff --git a/refcodec.cpp b/refcodec.cpp index 087eca6..5f62546 100755 --- a/refcodec.cpp +++ b/refcodec.cpp @@ -96,6 +96,7 @@ void REFCodec::process_udp() m_modeinfo.hw_vocoder_loaded = true; 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())); } else{ @@ -107,6 +108,7 @@ void REFCodec::process_udp() m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex); m_modem->set_modem_params(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))); } m_rxtimer = new QTimer(); @@ -152,7 +154,7 @@ void REFCodec::process_udp() memcpy(temp, buf.data() + 44, 8); temp[8] = '\0'; QString mycall = QString(temp); QString h = m_hostname + " " + m_module; - qDebug() << "h:r1:r2 == " << h.simplified() << ":" << rptr1.simplified() << ":" << rptr2.simplified(); + if( (rptr2.simplified() == h.simplified()) || (rptr1.simplified() == h.simplified()) ){ m_rxwatchdog = 0; const uint16_t streamid = (buf.data()[14] << 8) | (buf.data()[15] & 0xff); @@ -204,7 +206,7 @@ void REFCodec::process_udp() } m_rxwatchdog = 0; m_modeinfo.stream_state = STREAMING; - m_modeinfo.frame_number = buf.data()[16]; + m_modeinfo.frame_number = (uint8_t)buf.data()[16]; if(m_modem){ m_rxmodemq.append(0xe0); @@ -469,7 +471,6 @@ void REFCodec::send_frame(uint8_t *ambe) if(txstreamid == 0){ txstreamid = static_cast((::rand() & 0xFFFF)); - //std::cerr << "txstreamid == " << txstreamid << std::endl; } if(sendheader){ sendheader = 0; @@ -488,8 +489,8 @@ void REFCodec::send_frame(uint8_t *ambe) txdata[11] = 0x00; txdata[12] = 0x02; txdata[13] = 0x01; - txdata[14] = txstreamid & 0xff; - txdata[15] = (txstreamid >> 8) & 0xff; + txdata[14] = (txstreamid >> 8) & 0xff; + txdata[15] = txstreamid & 0xff; txdata[16] = 0x80; txdata[17] = 0x00; txdata[18] = 0x00; @@ -506,7 +507,7 @@ void REFCodec::send_frame(uint8_t *ambe) m_modeinfo.gw = m_txrptr1; m_modeinfo.gw2 = m_txrptr2; m_modeinfo.streamid = txstreamid; - m_modeinfo.frame_number = m_txcnt; + m_modeinfo.frame_number = m_txcnt % 21; m_udp->writeDatagram(txdata, m_address, m_modeinfo.port); } @@ -526,22 +527,13 @@ void REFCodec::send_frame(uint8_t *ambe) txdata[11] = 0x00; txdata[12] = 0x02; txdata[13] = 0x01; - txdata[14] = txstreamid & 0xff; - txdata[15] = (txstreamid >> 8) & 0xff; + txdata[14] = (txstreamid >> 8) & 0xff; + txdata[15] = txstreamid & 0xff; txdata[16] = m_txcnt % 21; memcpy(txdata.data() + 17, ambe, 9); - //for(int i = 0; i < 9; ++i){ - //txdata[17 + i] = ad8dp[(tx_cnt * 9) + i]; - //if(ambeq.size()){ - // txdata[17 + i] = ambeq.dequeue(); - //} - //else{ - // txdata[17 + i] = 0; - //} - //} - - //memset(txdata.data() + 17, 0x00, 9); + m_modeinfo.frame_number = m_txcnt % 21; + switch(txdata.data()[16]){ case 0: txdata[26] = 0x55; @@ -594,9 +586,7 @@ void REFCodec::send_frame(uint8_t *ambe) txdata[28] = 0xf5; break; } - //if((tx_cnt * 9) >= sizeof(ad8dp)){ - // tx_cnt = 0; - //} + if((m_txcnt % 21) == 0){ sendheader = 1; } @@ -632,7 +622,7 @@ void REFCodec::send_frame(uint8_t *ambe) m_udp->writeDatagram(txdata, m_address, m_modeinfo.port); emit update_output_level(m_audio->level()); - update(m_modeinfo); + emit update(m_modeinfo); #ifdef DEBUG fprintf(stderr, "SEND:%d: ", txdata.size()); for(int i = 0; i < txdata.size(); ++i){ diff --git a/refcodec.h b/refcodec.h index 0a54777..aeb02c5 100755 --- a/refcodec.h +++ b/refcodec.h @@ -28,7 +28,6 @@ public: ~REFCodec(); unsigned char * get_frame(unsigned char *ambe); private: - QString m_txusrtxt; uint8_t packet_size; private slots: void toggle_tx(bool); @@ -44,7 +43,6 @@ private slots: void hostname_lookup(QHostInfo i); void input_src_changed(int id, QString t) { m_ttsid = id; m_ttstext = t; } void module_changed(int m) { m_module = 0x41 + m; m_modeinfo.streamid = 0; } - void usrtxt_changed(QString t) { m_txusrtxt = t; } void send_frame(uint8_t *); }; diff --git a/serialambe.cpp b/serialambe.cpp index e6c1d83..fe54bbb 100755 --- a/serialambe.cpp +++ b/serialambe.cpp @@ -29,15 +29,26 @@ //#define DEBUG -const uint8_t AMBEP251_4400_2800[17] = {0x61, 0x00, 0x0d, 0x00, 0x0a, 0x05U, 0x58U, 0x08U, 0x6BU, 0x10U, 0x30U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x90U}; //DVSI P25 USB Dongle FEC -//const uint8_t AMBEP251_4400_0000[17] = {0x61, 0x00, 0x0d, 0x00, 0x0a, 0x05U, 0x58U, 0x08U, 0x6BU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x58U}; //DVSI P25 USB Dongle No-FEC -//const uint8_t AMBE1000_4400_2800[17] = {0x61, 0x00, 0x0d, 0x00, 0x0a, 0x00U, 0x58U, 0x08U, 0x87U, 0x30U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x44U, 0x90U}; -//const uint8_t AMBE2000_4400_2800[17] = {0x61, 0x00, 0x0d, 0x00, 0x0a, 0x02U, 0x58U, 0x07U, 0x65U, 0x00U, 0x09U, 0x1eU, 0x0cU, 0x41U, 0x27U, 0x73U, 0x90U}; -//const uint8_t AMBE3000_4400_2800[17] = {0x61, 0x00, 0x0d, 0x00, 0x0a, 0x04U, 0x58U, 0x09U, 0x86U, 0x80U, 0x20U, 0x00U, 0x00U, 0x00U, 0x00U, 0x73U, 0x90U}; -const uint8_t AMBE2000_2400_1200[17] = {0x61, 0x00, 0x0d, 0x00, 0x0a, 0x01U, 0x30U, 0x07U, 0x63U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x48U}; -const uint8_t AMBE3000_2450_1150[17] = {0x61, 0x00, 0x0d, 0x00, 0x0a, 0x04U, 0x31U, 0x07U, 0x54U, 0x24U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x6fU, 0x48U}; -const uint8_t AMBE3000_2450_0000[17] = {0x61, 0x00, 0x0d, 0x00, 0x0a, 0x04U, 0x31U, 0x07U, 0x54U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x70U, 0x31U}; -const uint8_t AMBE3000_PARITY_DISABLE[8] = {0x61, 0x00, 0x04, 0x00, 0x3f, 0x00, 0x2f, 0x14}; +#define AMBE3000_START_BYTE 0x61 +#define AMBE3000_TYPE_CONFIG 0x00 +#define AMBE3000_TYPE_CHANNEL 0x01 +#define AMBE3000_TYPE_SPEECH 0x02 +#define AMBE3000_PKT_RATEP 0x0a +#define AMBE3000_PKT_INIT 0x0b +#define AMBE3000_PKT_RATEP 0x0a +#define AMBE3000_PKT_PRODID 0x30 +#define AMBE3000_PKT_VERSTRING 0x31 +#define AMBE3000_PKT_READY 0x39 +#define AMBE3000_PKT_RESET 0x33 +#define AMBE3000_PKT_PARITYMODE 0x3f + +const uint8_t AMBEP251_4400_2800[17] = {AMBE3000_START_BYTE, 0x00, 0x0d, AMBE3000_TYPE_CONFIG, AMBE3000_PKT_RATEP, 0x05U, 0x58U, 0x08U, 0x6BU, 0x10U, 0x30U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x90U}; //DVSI P25 USB Dongle FEC +const uint8_t AMBE2000_2400_1200[17] = {AMBE3000_START_BYTE, 0x00, 0x0d, AMBE3000_TYPE_CONFIG, AMBE3000_PKT_RATEP, 0x01U, 0x30U, 0x07U, 0x63U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x48U}; +const uint8_t AMBE3000_2450_1150[17] = {AMBE3000_START_BYTE, 0x00, 0x0d, AMBE3000_TYPE_CONFIG, AMBE3000_PKT_RATEP, 0x04U, 0x31U, 0x07U, 0x54U, 0x24U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x6fU, 0x48U}; +const uint8_t AMBE3000_2450_0000[17] = {AMBE3000_START_BYTE, 0x00, 0x0d, AMBE3000_TYPE_CONFIG, AMBE3000_PKT_RATEP, 0x04U, 0x31U, 0x07U, 0x54U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x70U, 0x31U}; +const uint8_t AMBE3000_PARITY_DISABLE[8] = {AMBE3000_START_BYTE, 0x00, 0x04, AMBE3000_TYPE_CONFIG, AMBE3000_PKT_PARITYMODE, 0x00, 0x2f, 0x14}; +const uint8_t AMBE3000_PRODID[5] = {AMBE3000_START_BYTE, 0x00, 0x01, AMBE3000_TYPE_CONFIG, AMBE3000_PKT_PRODID}; +const uint8_t AMBE3000_VERSION[5] = {AMBE3000_START_BYTE, 0x00, 0x01, AMBE3000_TYPE_CONFIG, AMBE3000_PKT_VERSTRING}; //const uint8_t AMBE2020[48] = {0x13, 0xec, 0x00, 0x00, 0x10, 0x30, 0x00, 0x01, 0x00, 0x00, 0x42, 0x30, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //const uint8_t AMBE2020[4] = {0x04, 0x20, 0x01, 0x00}; @@ -136,6 +147,14 @@ void SerialAMBE::connect_to_serial(QString p) m_serial->write(a); QThread::msleep(100); a.clear(); + a.append(reinterpret_cast(AMBE3000_PRODID), sizeof(AMBE3000_PRODID)); + m_serial->write(a); + QThread::msleep(100); + a.clear(); + a.append(reinterpret_cast(AMBE3000_VERSION), sizeof(AMBE3000_VERSION)); + m_serial->write(a); + QThread::msleep(100); + a.clear(); } if(m_protocol == "DMR"){ @@ -228,7 +247,7 @@ void SerialAMBE::decode(uint8_t *ambe) void SerialAMBE::encode(int16_t *audio) { - uint8_t packet[327] = {0x61, 0x01, 0x43, 0x02, 0x40, 0x00, 0xa0}; + uint8_t packet[327] = {AMBE3000_START_BYTE, 0x01, 0x43, AMBE3000_TYPE_SPEECH, 0x40, 0x00, 0xa0}; for(int i = 0; i < 160; ++i){ packet [(i*2)+7] = (audio[i] >> 8) & 0xff; packet [(i*2)+8] = audio[i] & 0xff; @@ -261,7 +280,7 @@ void SerialAMBE::decode_2020(uint8_t *ambe) void SerialAMBE::decode_3000(uint8_t *ambe) { - uint8_t packet[15] = {0x61, 0x00, 0x0b, 0x01, 0x01, 0x48}; + uint8_t packet[15] = {AMBE3000_START_BYTE, 0x00, 0x0b, AMBE3000_TYPE_CHANNEL, 0x01, 0x48}; if( packet_size == 7 ){ packet[2] = 0x09; packet[5] = 0x31; @@ -293,19 +312,66 @@ void SerialAMBE::process_serial_2020() void SerialAMBE::process_serial_3000() { - if( (m_serialdata.size() > 3) && - (m_serialdata[0] == 0x61) && - (m_serialdata[3] == 0x00) + if(m_serialdata.size() < 3){ + return; + } + + while( (m_serialdata.size() > 3) && + (m_serialdata[0] == AMBE3000_START_BYTE) && + (m_serialdata[3] == 0x00) && + (m_serialdata.size() >= m_serialdata[2]) ) { + switch(m_serialdata[4]){ + case AMBE3000_PKT_PARITYMODE: + if(!m_serialdata[5]){ + qDebug() << "AMBE3000 Parity disabled"; + } + else{ + qDebug() << "ERROR: AMBE3000 Parity not disabled"; + } + break; + case AMBE3000_PKT_PRODID: + m_ambeprodid.clear(); + + for(int i = 0; i < (m_serialdata[2] - 2); ++i){ + m_ambeprodid.append(m_serialdata[5+i]); + } + + qDebug() << "PRODID == " << m_ambeprodid; + break; + case AMBE3000_PKT_VERSTRING: + m_ambeverstring.clear(); + + for(int i = 0; i < (m_serialdata[2] - 2); ++i){ + m_ambeverstring.append(m_serialdata[5+i]); + } + + qDebug() << "VERSTRING == " << m_ambeverstring; + break; + case AMBE3000_PKT_RATEP: + if(!m_serialdata[5]){ + qDebug() << "AMBE3000 Rate set"; + emit connected(true); + } + else{ + qDebug() << "ERROR: AMBE3000 Rate not set"; + emit connected(false); + } + break; + default: + break; + } + do { m_serialdata.dequeue(); } - while(m_serialdata.size() && m_serialdata[0] != 0x61); + while(m_serialdata.size() && m_serialdata[0] != AMBE3000_START_BYTE); } + if( (m_serialdata.size() >= (6 + packet_size)) && - (m_serialdata[0] == 0x61) && - (m_serialdata[3] == 0x01) + (m_serialdata[0] == AMBE3000_START_BYTE) && + (m_serialdata[3] == AMBE3000_TYPE_CHANNEL) ) { emit data_ready(); @@ -320,19 +386,19 @@ bool SerialAMBE::get_ambe(uint8_t *ambe) } if( (m_serialdata.size() > 3) && - (m_serialdata[0] == 0x61) && - (m_serialdata[3] != 0x01) + (m_serialdata[0] == AMBE3000_START_BYTE) && + (m_serialdata[3] != AMBE3000_TYPE_CHANNEL) ) { do { m_serialdata.dequeue(); } - while(m_serialdata.size() && m_serialdata[0] != 0x61); + while(m_serialdata.size() && m_serialdata[0] != AMBE3000_START_BYTE); } if( (m_serialdata.size() >= (6 + packet_size)) && - (m_serialdata[0] == 0x61) && - (m_serialdata[3] == 0x01) + (m_serialdata[0] == AMBE3000_START_BYTE) && + (m_serialdata[3] == AMBE3000_TYPE_CHANNEL) ) { for(int i = 0; i < 6; ++i){ @@ -352,7 +418,7 @@ bool SerialAMBE::get_audio(int16_t *audio) if(m_serialdata.isEmpty()){ return r; } - uint8_t header[] = {0x61, 0x01, 0x42, 0x02, 0x00, 0xA0}; + uint8_t header[] = {AMBE3000_START_BYTE, 0x01, 0x42, AMBE3000_TYPE_SPEECH, 0x00, 0xA0}; /* if( (m_serialdata.size() > 3) && (m_serialdata[0] == 0x61) && diff --git a/serialambe.h b/serialambe.h index 3d86451..c9e78a1 100755 --- a/serialambe.h +++ b/serialambe.h @@ -33,6 +33,9 @@ public: ~SerialAMBE(); static QMap discover_devices(); void connect_to_serial(QString); + QString get_ambe_description(){ return m_description; } + QString get_ambe_prodid(){ return m_ambeprodid; } + QString get_ambe_verstring(){ return m_ambeverstring; } bool get_audio(int16_t *); bool get_ambe(uint8_t *ambe); void decode(uint8_t *); @@ -52,6 +55,8 @@ private: QString m_manufacturer; QString m_serialnum; QString m_protocol; + QString m_ambeverstring; + QString m_ambeprodid; uint8_t packet_size; qreal m_decode_gain; QQueue m_serialdata; @@ -62,6 +67,7 @@ private: void process_serial_2020(); void process_serial_3000(); signals: + void connected(bool); void data_ready(); }; diff --git a/serialmodem.cpp b/serialmodem.cpp index 584b46a..649f39e 100644 --- a/serialmodem.cpp +++ b/serialmodem.cpp @@ -118,7 +118,7 @@ void SerialModem::connect_to_serial(QString p) //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->setFlowControl(QSerialPort::HardwareControl); m_serial->setRequestToSend(true); QByteArray a; a.clear(); @@ -185,16 +185,30 @@ void SerialModem::process_modem() for(int i = 0; i < s; ++i){ m_serialdata.dequeue(); } + if(m_serialdata[3] == 2){ + + } } else if(r == MMDVM_ACK){ qDebug() << "Received MMDVM_ACK"; + if(m_serialdata[3] == 2){ + emit connected(true); + } for(int i = 0; i < s; ++i){ m_serialdata.dequeue(); } } else if(r == MMDVM_GET_VERSION){ + if(m_serialdata.size() >= s){ + m_protocol = m_serialdata[3]; + m_version.clear(); + for(int i = 0; i < (s-4); ++i){ + m_version.append(m_serialdata[4+i]); + } + qDebug() << "MMDVM: " << m_version; + } QThread::msleep(100); set_freq(); QThread::msleep(100); diff --git a/serialmodem.h b/serialmodem.h index d625262..5ef83c0 100644 --- a/serialmodem.h +++ b/serialmodem.h @@ -37,6 +37,7 @@ public: void set_modem_params(uint32_t, uint32_t, uint32_t, float, float, uint32_t, float, float, float, float, float, float, float, float); static QMap discover_devices(); void connect_to_serial(QString); + QString get_mmdvm_version(){ return m_version; } void write(QByteArray); private slots: void process_serial(); @@ -51,6 +52,8 @@ private: #else AndroidSerialPort *m_serial; #endif + QString m_version; + uint8_t m_protocol; QTimer *m_modemtimer; uint8_t packet_size; QQueue m_serialdata; @@ -95,6 +98,7 @@ private: signals: void data_ready(); void modem_data_ready(QByteArray); + void connected(bool); }; #endif // SERIALMODEM_H diff --git a/xrfcodec.cpp b/xrfcodec.cpp index 4a1b234..596582f 100755 --- a/xrfcodec.cpp +++ b/xrfcodec.cpp @@ -67,6 +67,7 @@ void XRFCodec::process_udp() m_modeinfo.hw_vocoder_loaded = true; 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())); } if(m_modemport != ""){ @@ -74,6 +75,7 @@ void XRFCodec::process_udp() m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex); m_modem->set_modem_params(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))); } m_rxtimer = new QTimer(); @@ -162,7 +164,7 @@ void XRFCodec::process_udp() m_modeinfo.stream_state = STREAMING; } m_modeinfo.streamid = streamid; - m_modeinfo.frame_number = buf.data()[14]; + m_modeinfo.frame_number = (uint8_t)buf.data()[14]; if(m_modeinfo.frame_number & 0x40){ qDebug() << "XRF RX stream ended "; @@ -436,8 +438,8 @@ void XRFCodec::send_frame(uint8_t *ambe) txdata[9] = 0x00; txdata[10] = 0x01; txdata[11] = 0x02; - txdata[12] = txstreamid & 0xff; - txdata[13] = (txstreamid >> 8) & 0xff; + txdata[12] = (txstreamid >> 8) & 0xff; + txdata[13] = txstreamid & 0xff; txdata[14] = 0x80; txdata[15] = 0x00; txdata[16] = 0x00; @@ -454,7 +456,7 @@ void XRFCodec::send_frame(uint8_t *ambe) m_modeinfo.gw = m_txrptr1; m_modeinfo.gw2 = m_txrptr2; m_modeinfo.streamid = txstreamid; - m_modeinfo.frame_number = m_txcnt; + m_modeinfo.frame_number = m_txcnt % 21; } else{ txdata.resize(27); @@ -470,11 +472,13 @@ void XRFCodec::send_frame(uint8_t *ambe) txdata[9] = 0x00; txdata[10] = 0x01; txdata[11] = 0x02; - txdata[12] = txstreamid & 0xff; - txdata[13] = (txstreamid >> 8) & 0xff; + txdata[12] = (txstreamid >> 8) & 0xff; + txdata[13] = txstreamid & 0xff; txdata[14] = m_txcnt % 21; memcpy(txdata.data() + 15, ambe, 9); + m_modeinfo.frame_number = m_txcnt % 21; + switch(txdata.data()[14]){ case 0: txdata[24] = 0x55; diff --git a/ysfcodec.cpp b/ysfcodec.cpp index 4e54687..9f14e84 100755 --- a/ysfcodec.cpp +++ b/ysfcodec.cpp @@ -26,7 +26,7 @@ //#define DEBUG -const unsigned int IMBE_INTERLEAVE[] = { +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, 1, 6, 13, 18, 25, 30, 37, 42, 49, 54, 61, 66, 73, 78, 85, 90, 97, 102, 109, 114, 121, 126, 133, 138, 2, 9, 14, 21, 26, 33, 38, 45, 50, 57, 62, 69, 74, 81, 86, 93, 98, 105, 110, 117, 122, 129, 134, 141, @@ -41,7 +41,7 @@ const int dvsi_interleave[49] = { 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38 }; -const unsigned int INTERLEAVE_TABLE_5_20[] = { +const uint32_t INTERLEAVE_TABLE_5_20[] = { 0U, 40U, 80U, 120U, 160U, 2U, 42U, 82U, 122U, 162U, 4U, 44U, 84U, 124U, 164U, @@ -63,7 +63,7 @@ const unsigned int INTERLEAVE_TABLE_5_20[] = { 36U, 76U, 116U, 156U, 196U, 38U, 78U, 118U, 158U, 198U}; -const unsigned int INTERLEAVE_TABLE_9_20[] = { +const uint32_t INTERLEAVE_TABLE_9_20[] = { 0U, 40U, 80U, 120U, 160U, 200U, 240U, 280U, 320U, 2U, 42U, 82U, 122U, 162U, 202U, 242U, 282U, 322U, 4U, 44U, 84U, 124U, 164U, 204U, 244U, 284U, 324U, @@ -85,16 +85,16 @@ const unsigned int INTERLEAVE_TABLE_9_20[] = { 36U, 76U, 116U, 156U, 196U, 236U, 276U, 316U, 356U, 38U, 78U, 118U, 158U, 198U, 238U, 278U, 318U, 358U}; -const unsigned int INTERLEAVE_TABLE_26_4[] = { +const uint32_t INTERLEAVE_TABLE_26_4[] = { 0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U, 48U, 52U, 56U, 60U, 64U, 68U, 72U, 76U, 80U, 84U, 88U, 92U, 96U, 100U, 1U, 5U, 9U, 13U, 17U, 21U, 25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, 73U, 77U, 81U, 85U, 89U, 93U, 97U, 101U, 2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U, 46U, 50U, 54U, 58U, 62U, 66U, 70U, 74U, 78U, 82U, 86U, 90U, 94U, 98U, 102U, 3U, 7U, 11U, 15U, 19U, 23U, 27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U, 75U, 79U, 83U, 87U, 91U, 95U, 99U, 103U}; -const unsigned char WHITENING_DATA[] = {0x93U, 0xD7U, 0x51U, 0x21U, 0x9CU, 0x2FU, 0x6CU, 0xD0U, 0xEFU, 0x0FU, +const uint32_t WHITENING_DATA[] = {0x93U, 0xD7U, 0x51U, 0x21U, 0x9CU, 0x2FU, 0x6CU, 0xD0U, 0xEFU, 0x0FU, 0xF8U, 0x3DU, 0xF1U, 0x73U, 0x20U, 0x94U, 0xEDU, 0x1EU, 0x7CU, 0xD8U}; -const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; +const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; #define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) #define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) @@ -148,6 +148,7 @@ void YSFCodec::process_udp() m_modeinfo.hw_vocoder_loaded = true; 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())); } else{ @@ -160,6 +161,7 @@ void YSFCodec::process_udp() m_modem->set_modem_flags(m_rxInvert, m_txInvert, m_pttInvert, m_useCOSAsLockout, m_duplex); m_modem->set_modem_params(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))); } @@ -257,7 +259,7 @@ void YSFCodec::process_udp() if(m_modeinfo.type == 3){ decode_vw(p_data); } - else{ + else if(m_modeinfo.type != 1){ decode_dn(p_data); } } @@ -371,64 +373,65 @@ void YSFCodec::decode_vw(uint8_t* data) data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; - unsigned int offset = 0U; + uint32_t offset = 0U; // We have a total of 5 VCH sections, iterate through each - for (unsigned int j = 0U; j < 5U; j++, offset += 18U) { + for (uint32_t j = 0U; j < 5U; j++, offset += 18U) { ::memcpy(vch, data + offset, 18U); - for (unsigned int i = 0U; i < 144U; i++) { - unsigned int n = IMBE_INTERLEAVE[i]; + for (uint32_t i = 0U; i < 144U; i++) { + uint32_t n = IMBE_INTERLEAVE[i]; bit[i] = READ_BIT(vch, n); } - unsigned int c0data = 0U; - for (unsigned int i = 0U; i < 12U; i++) + uint32_t c0data = 0U; + for (uint32_t i = 0U; i < 12U; i++) c0data = (c0data << 1) | (bit[i] ? 0x01U : 0x00U); bool prn[114U]; // Create the whitening vector and save it for future use - unsigned int p = 16U * c0data; - for (unsigned int i = 0U; i < 114U; i++) { + uint32_t p = 16U * c0data; + for (uint32_t i = 0U; i < 114U; i++) { p = (173U * p + 13849U) % 65536U; prn[i] = p >= 32768U; } // De-whiten some bits - for (unsigned int i = 0U; i < 114U; i++) + for (uint32_t i = 0U; i < 114U; i++) bit[i + 23U] ^= prn[i]; - unsigned int offset = 0U; - for (unsigned int i = 0U; i < 12U; i++, offset++) + uint32_t offset = 0U; + for (uint32_t i = 0U; i < 12U; i++, offset++) WRITE_BIT(imbe, offset, bit[i + 0U]); - for (unsigned int i = 0U; i < 12U; i++, offset++) + for (uint32_t i = 0U; i < 12U; i++, offset++) WRITE_BIT(imbe, offset, bit[i + 23U]); - for (unsigned int i = 0U; i < 12U; i++, offset++) + for (uint32_t i = 0U; i < 12U; i++, offset++) WRITE_BIT(imbe, offset, bit[i + 46U]); - for (unsigned int i = 0U; i < 12U; i++, offset++) + for (uint32_t i = 0U; i < 12U; i++, offset++) WRITE_BIT(imbe, offset, bit[i + 69U]); - for (unsigned int i = 0U; i < 11U; i++, offset++) + for (uint32_t i = 0U; i < 11U; i++, offset++) WRITE_BIT(imbe, offset, bit[i + 92U]); - for (unsigned int i = 0U; i < 11U; i++, offset++) + for (uint32_t i = 0U; i < 11U; i++, offset++) WRITE_BIT(imbe, offset, bit[i + 107U]); - for (unsigned int i = 0U; i < 11U; i++, offset++) + for (uint32_t i = 0U; i < 11U; i++, offset++) WRITE_BIT(imbe, offset, bit[i + 122U]); - for (unsigned int i = 0U; i < 7U; i++, offset++) + for (uint32_t i = 0U; i < 7U; i++, offset++) WRITE_BIT(imbe, offset, bit[i + 137U]); for(int i = 0; i < 11; ++i){ - m_rxcodecq.append(imbe[i]); + m_rximbecodecq.append(imbe[i]); + //m_rxcodecq.append(imbe[i]); } } } void YSFCodec::decode_vd1(uint8_t* data, uint8_t *dt) { - unsigned char dch[45U]; + uint8_t dch[45U]; - const unsigned char* p1 = data; - unsigned char* p2 = dch; - for (unsigned int i = 0U; i < 5U; i++) { + const uint8_t* p1 = data; + uint8_t* p2 = dch; + for (uint32_t i = 0U; i < 5U; i++) { ::memcpy(p2, p1, 9U); p1 += 18U; p2 += 9U; } @@ -436,8 +439,8 @@ void YSFCodec::decode_vd1(uint8_t* data, uint8_t *dt) CYSFConvolution conv; conv.start(); - for (unsigned int i = 0U; i < 180U; i++) { - unsigned int n = INTERLEAVE_TABLE_9_20[i]; + for (uint32_t i = 0U; i < 180U; i++) { + uint32_t n = INTERLEAVE_TABLE_9_20[i]; uint8_t s0 = READ_BIT(dch, n) ? 1U : 0U; n++; @@ -446,12 +449,12 @@ void YSFCodec::decode_vd1(uint8_t* data, uint8_t *dt) conv.decode(s0, s1); } - unsigned char output[23U]; + uint8_t output[23U]; conv.chainback(output, 176U); bool ret = CCRC::checkCCITT162(output, 22U); if (ret) { - for (unsigned int i = 0U; i < 20U; i++){ + for (uint32_t i = 0U; i < 20U; i++){ output[i] ^= WHITENING_DATA[i]; } ::memcpy(dt, output, 20U); @@ -460,11 +463,11 @@ void YSFCodec::decode_vd1(uint8_t* data, uint8_t *dt) void YSFCodec::decode_vd2(uint8_t* data, uint8_t *dt) { - unsigned char dch[25U]; + uint8_t dch[25U]; - const unsigned char* p1 = data; - unsigned char* p2 = dch; - for (unsigned int i = 0U; i < 5U; i++) { + const uint8_t* p1 = data; + uint8_t* p2 = dch; + for (uint32_t i = 0U; i < 5U; i++) { ::memcpy(p2, p1, 5U); p1 += 18U; p2 += 5U; } @@ -472,8 +475,8 @@ void YSFCodec::decode_vd2(uint8_t* data, uint8_t *dt) CYSFConvolution conv; conv.start(); - for (unsigned int i = 0U; i < 100U; i++) { - unsigned int n = INTERLEAVE_TABLE_5_20[i]; + for (uint32_t i = 0U; i < 100U; i++) { + uint32_t n = INTERLEAVE_TABLE_5_20[i]; uint8_t s0 = READ_BIT(dch, n) ? 1U : 0U; n++; @@ -482,12 +485,12 @@ void YSFCodec::decode_vd2(uint8_t* data, uint8_t *dt) conv.decode(s0, s1); } - unsigned char output[13U]; + uint8_t output[13U]; conv.chainback(output, 96U); bool ret = CCRC::checkCCITT162(output, 12U); if (ret) { - for (unsigned int i = 0U; i < 10U; i++){ + for (uint32_t i = 0U; i < 10U; i++){ output[i] ^= WHITENING_DATA[i]; } ::memcpy(dt, output, YSF_CALLSIGN_LENGTH); @@ -747,7 +750,7 @@ void YSFCodec::send_frame() void YSFCodec::encode_header(bool eot) { - unsigned char callsign[12]; + uint8_t callsign[12]; ::memcpy(callsign, " ", 10); ::memcpy(callsign, m_modeinfo.callsign.toStdString().c_str(), ::strlen(m_modeinfo.callsign.toStdString().c_str())); @@ -802,7 +805,7 @@ void YSFCodec::encode_header(bool eot) void YSFCodec::encode_vw() { - unsigned char callsign[12]; + uint8_t callsign[12]; ::memcpy(callsign, " ", 10); ::memcpy(callsign, m_modeinfo.callsign.toStdString().c_str(), ::strlen(m_modeinfo.callsign.toStdString().c_str())); uint8_t *p_frame = m_ysfFrame; @@ -857,18 +860,18 @@ void YSFCodec::encode_vw() } } -void YSFCodec::encode_imbe(unsigned char* data, const unsigned char* imbe) +void YSFCodec::encode_imbe(uint8_t* data, const uint8_t* imbe) { bool bTemp[144U]; bool* bit = bTemp; // c0 - unsigned int c0 = 0U; - for (unsigned int i = 0U; i < 12U; i++) { + uint32_t c0 = 0U; + for (uint32_t i = 0U; i < 12U; i++) { bool b = READ_BIT(imbe, i); c0 = (c0 << 1) | (b ? 0x01U : 0x00U); } - unsigned int g2 = CGolay24128::encode23127(c0); + uint32_t g2 = CGolay24128::encode23127(c0); for (int i = 23; i >= 0; i--) { bit[i] = (g2 & 0x01U) == 0x01U; g2 >>= 1; @@ -876,8 +879,8 @@ void YSFCodec::encode_imbe(unsigned char* data, const unsigned char* imbe) bit += 23U; // c1 - unsigned int c1 = 0U; - for (unsigned int i = 12U; i < 24U; i++) { + uint32_t c1 = 0U; + for (uint32_t i = 12U; i < 24U; i++) { bool b = READ_BIT(imbe, i); c1 = (c1 << 1) | (b ? 0x01U : 0x00U); } @@ -889,8 +892,8 @@ void YSFCodec::encode_imbe(unsigned char* data, const unsigned char* imbe) bit += 23U; // c2 - unsigned int c2 = 0; - for (unsigned int i = 24U; i < 36U; i++) { + uint32_t c2 = 0; + for (uint32_t i = 24U; i < 36U; i++) { bool b = READ_BIT(imbe, i); c2 = (c2 << 1) | (b ? 0x01U : 0x00U); } @@ -902,8 +905,8 @@ void YSFCodec::encode_imbe(unsigned char* data, const unsigned char* imbe) bit += 23U; // c3 - unsigned int c3 = 0U; - for (unsigned int i = 36U; i < 48U; i++) { + uint32_t c3 = 0U; + for (uint32_t i = 36U; i < 48U; i++) { bool b = READ_BIT(imbe, i); c3 = (c3 << 1) | (b ? 0x01U : 0x00U); } @@ -915,50 +918,50 @@ void YSFCodec::encode_imbe(unsigned char* data, const unsigned char* imbe) bit += 23U; // c4 - for (unsigned int i = 0U; i < 11U; i++) + for (uint32_t i = 0U; i < 11U; i++) bit[i] = READ_BIT(imbe, i + 48U); CHamming::encode15113_1(bit); bit += 15U; // c5 - for (unsigned int i = 0U; i < 11U; i++) + for (uint32_t i = 0U; i < 11U; i++) bit[i] = READ_BIT(imbe, i + 59U); CHamming::encode15113_1(bit); bit += 15U; // c6 - for (unsigned int i = 0U; i < 11U; i++) + for (uint32_t i = 0U; i < 11U; i++) bit[i] = READ_BIT(imbe, i + 70U); CHamming::encode15113_1(bit); bit += 15U; // c7 - for (unsigned int i = 0U; i < 7U; i++) + for (uint32_t i = 0U; i < 7U; i++) bit[i] = READ_BIT(imbe, i + 81U); bool prn[114U]; // Create the whitening vector and save it for future use - unsigned int p = 16U * c0; - for (unsigned int i = 0U; i < 114U; i++) { + uint32_t p = 16U * c0; + for (uint32_t i = 0U; i < 114U; i++) { p = (173U * p + 13849U) % 65536U; prn[i] = p >= 32768U; } // Whiten some bits - for (unsigned int i = 0U; i < 114U; i++) + for (uint32_t i = 0U; i < 114U; i++) bTemp[i + 23U] ^= prn[i]; // Interleave - for (unsigned int i = 0U; i < 144U; i++) { - unsigned int n = IMBE_INTERLEAVE[i]; + for (uint32_t i = 0U; i < 144U; i++) { + uint32_t n = IMBE_INTERLEAVE[i]; WRITE_BIT(data, n, bTemp[i]); } } void YSFCodec::encode_dv2() { - unsigned char callsign[12]; + uint8_t callsign[12]; ::memcpy(callsign, " ", 10); ::memcpy(callsign, m_modeinfo.callsign.toStdString().c_str(), ::strlen(m_modeinfo.callsign.toStdString().c_str())); uint8_t *p_frame = m_ysfFrame; @@ -1148,7 +1151,7 @@ void YSFCodec::generate_vch_vd2(const uint8_t *a) { uint8_t buf[104]; uint8_t result[104]; - //unsigned char a[56]; + //uint8_t a[56]; uint8_t vch[13]; memset(vch, 0, 13); /* @@ -1300,57 +1303,48 @@ void YSFCodec::process_rx_data() cnt = 0; } - if(m_modeinfo.type == 3){ - if(m_rxcodecq.size() > 10){ - for(int i = 0; i < 11; ++i){ - imbe[i] = m_rxcodecq.dequeue(); - } - vocoder.decode_4400(pcm, imbe); - m_audio->write(pcm, 160); - emit update_output_level(m_audio->level()); - } - else if ( (m_modeinfo.stream_state == STREAM_END) || (m_modeinfo.stream_state == STREAM_LOST) ){ - m_rxtimer->stop(); - m_audio->stop_playback(); - m_rxwatchdog = 0; - m_modeinfo.streamid = 0; - m_rxcodecq.clear(); - qDebug() << "YSF FR playback stopped"; + if((!m_tx) && (m_rximbecodecq.size() > 10)){ + for(int i = 0; i < 11; ++i){ + imbe[i] = m_rximbecodecq.dequeue(); } + vocoder.decode_4400(pcm, imbe); + m_audio->write(pcm, 160); + emit update_output_level(m_audio->level()); } - else{ - if((!m_tx) && (m_rxcodecq.size() > 6) ){ - for(int i = 0; i < 7; ++i){ - ambe[i] = m_rxcodecq.dequeue(); - } - if(m_hwrx){ - m_ambedev->decode(ambe); - if(m_ambedev->get_audio(pcm)){ - m_audio->write(pcm, 160); - emit update_output_level(m_audio->level()); - } - } - else{ - if(m_modeinfo.sw_vocoder_loaded){ - m_mbevocoder->decode_2450(pcm, ambe); - } - else{ - memset(pcm, 0, 160 * sizeof(int16_t)); - } + else if((!m_tx) && (m_rxcodecq.size() > 6) ){ + for(int i = 0; i < 7; ++i){ + ambe[i] = m_rxcodecq.dequeue(); + } + if(m_hwrx){ + m_ambedev->decode(ambe); + + if(m_ambedev->get_audio(pcm)){ m_audio->write(pcm, 160); emit update_output_level(m_audio->level()); } } - else if ( (m_modeinfo.stream_state == STREAM_END) || (m_modeinfo.stream_state == STREAM_LOST) ){ - m_rxtimer->stop(); - m_audio->stop_playback(); - m_rxwatchdog = 0; - m_modeinfo.streamid = 0; - m_rxcodecq.clear(); - //m_ambedev->clear_queue(); - qDebug() << "YSF VD playback stopped"; - return; + else{ + if(m_modeinfo.sw_vocoder_loaded){ + m_mbevocoder->decode_2450(pcm, ambe); + } + else{ + memset(pcm, 0, 160 * sizeof(int16_t)); + } + m_audio->write(pcm, 160); + emit update_output_level(m_audio->level()); } } + + else if ( ((m_modeinfo.stream_state == STREAM_END) || (m_modeinfo.stream_state == STREAM_LOST)) && (m_rxmodemq.size() < 100) ){ + m_rxtimer->stop(); + m_audio->stop_playback(); + m_rxwatchdog = 0; + m_modeinfo.streamid = 0; + m_rxcodecq.clear(); + m_rximbecodecq.clear(); + //m_ambedev->clear_queue(); + qDebug() << "YSF playback stopped"; + return; + } } diff --git a/ysfcodec.h b/ysfcodec.h index b6550c7..d7221a6 100755 --- a/ysfcodec.h +++ b/ysfcodec.h @@ -18,34 +18,36 @@ #ifndef YSFCODEC_H #define YSFCODEC_H -const unsigned int YSF_FRAME_LENGTH_BYTES = 120U; +#include -const unsigned char YSF_SYNC_BYTES[] = {0xD4U, 0x71U, 0xC9U, 0x63U, 0x4DU}; -const unsigned int YSF_SYNC_LENGTH_BYTES = 5U; +const uint32_t YSF_FRAME_LENGTH_BYTES = 120U; -const unsigned int YSF_FICH_LENGTH_BYTES = 25U; +const uint8_t YSF_SYNC_BYTES[] = {0xD4U, 0x71U, 0xC9U, 0x63U, 0x4DU}; +const uint32_t YSF_SYNC_LENGTH_BYTES = 5U; -const unsigned char YSF_SYNC_OK = 0x01U; +const uint32_t YSF_FICH_LENGTH_BYTES = 25U; -const unsigned int YSF_CALLSIGN_LENGTH = 10U; +const uint8_t YSF_SYNC_OK = 0x01U; -const unsigned char YSF_FI_HEADER = 0x00U; -const unsigned char YSF_FI_COMMUNICATIONS = 0x01U; -const unsigned char YSF_FI_TERMINATOR = 0x02U; -const unsigned char YSF_FI_TEST = 0x03U; +const uint32_t YSF_CALLSIGN_LENGTH = 10U; -const unsigned char YSF_DT_VD_MODE1 = 0x00U; -const unsigned char YSF_DT_DATA_FR_MODE = 0x01U; -const unsigned char YSF_DT_VD_MODE2 = 0x02U; -const unsigned char YSF_DT_VOICE_FR_MODE = 0x03U; +const uint8_t YSF_FI_HEADER = 0x00U; +const uint8_t YSF_FI_COMMUNICATIONS = 0x01U; +const uint8_t YSF_FI_TERMINATOR = 0x02U; +const uint8_t YSF_FI_TEST = 0x03U; -const unsigned char YSF_CM_GROUP1 = 0x00U; -const unsigned char YSF_CM_GROUP2 = 0x01U; -const unsigned char YSF_CM_INDIVIDUAL = 0x03U; +const uint8_t YSF_DT_VD_MODE1 = 0x00U; +const uint8_t YSF_DT_DATA_FR_MODE = 0x01U; +const uint8_t YSF_DT_VD_MODE2 = 0x02U; +const uint8_t YSF_DT_VOICE_FR_MODE = 0x03U; -const unsigned char YSF_MR_DIRECT = 0x00U; -const unsigned char YSF_MR_NOT_BUSY = 0x01U; -const unsigned char YSF_MR_BUSY = 0x02U; +const uint8_t YSF_CM_GROUP1 = 0x00U; +const uint8_t YSF_CM_GROUP2 = 0x01U; +const uint8_t YSF_CM_INDIVIDUAL = 0x03U; + +const uint8_t YSF_MR_DIRECT = 0x00U; +const uint8_t YSF_MR_NOT_BUSY = 0x01U; +const uint8_t YSF_MR_BUSY = 0x02U; #include #include "codec.h" @@ -74,32 +76,33 @@ private: void decode_vw(uint8_t* data); void encode_header(bool eot = 0); void encode_vw(); - void encode_imbe(unsigned char* data, const unsigned char* imbe); + void encode_imbe(uint8_t* data, const uint8_t* imbe); void encode_dv2(); void decode_vd2(uint8_t* data, uint8_t *dt); void decode_vd1(uint8_t* data, uint8_t *dt); - void generate_vch_vd2(const unsigned char*); - void ysf_scramble(unsigned char *buf, const int len); - void writeDataFRModeData1(const unsigned char* dt, unsigned char* data); - void writeDataFRModeData2(const unsigned char* dt, unsigned char* data); - void writeVDMode2Data(unsigned char* data, const unsigned char* dt); + void generate_vch_vd2(const uint8_t*); + void ysf_scramble(uint8_t *buf, const int len); + void writeDataFRModeData1(const uint8_t* dt, uint8_t* data); + void writeDataFRModeData2(const uint8_t* dt, uint8_t* data); + void writeVDMode2Data(uint8_t* data, const uint8_t* dt); void interleave(uint8_t *ambe); uint8_t m_fi; uint8_t packet_size; - unsigned char gateway[12]; - unsigned char m_ysfFrame[200]; - unsigned char m_vch[13U]; - unsigned char m_ambe[55]; - //unsigned char m_imbe[55]; + uint8_t gateway[12]; + uint8_t m_ysfFrame[200]; + uint8_t m_vch[13U]; + uint8_t m_ambe[55]; + //uint8_t m_imbe[55]; CYSFFICH fich; - unsigned char ambe_fr[4][24]; - unsigned int ambe_a; - unsigned int ambe_b; - unsigned int ambe_c; + uint8_t ambe_fr[4][24]; + uint32_t ambe_a; + uint32_t ambe_b; + uint32_t ambe_c; bool m_fcs; std::string m_fcsname; bool m_txfullrate; + QQueue m_rximbecodecq; }; #endif