UI rearranging, Move mic gain to main tab, Add DMR slot/cc selection, always default to S2 CC1, add ambe and mmdvm info, fix Dstar streamid and user text issue, fix intermittent YSF audio decode issue

pull/3/head
Doug McLain 3 years ago
parent 811755ac50
commit 5bf704c482

@ -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);
}
droidstar.set_cc(_comboCC.currentIndex);
}
}
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)
}
}
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

@ -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

File diff suppressed because it is too large Load Diff

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1027" product-id="24597" />
<usb-device vendor-id="1027" product-id="24577" />
<usb-device vendor-id="3405" product-id="567" />
<usb-device vendor-id="1155" product-id="22336" />
<usb-device vendor-id="7855" product-id="0004" />

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

@ -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;

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

@ -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;

@ -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];

@ -31,6 +31,8 @@
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QFont>
#include <QFontDatabase>
#include <stdio.h>
#include <fcntl.h>
#include <iostream>
@ -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();
}

@ -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;

@ -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;

@ -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";

@ -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{

@ -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;

@ -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<uint16_t>((::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){

@ -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 *);
};

@ -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<const char*>(AMBE3000_PRODID), sizeof(AMBE3000_PRODID));
m_serial->write(a);
QThread::msleep(100);
a.clear();
a.append(reinterpret_cast<const char*>(AMBE3000_VERSION), sizeof(AMBE3000_VERSION));
m_serial->write(a);
QThread::msleep(100);
a.clear();
}
if(m_protocol == "DMR"){
@ -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) &&

@ -33,6 +33,9 @@ public:
~SerialAMBE();
static QMap<QString, QString> 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<char> m_serialdata;
@ -62,6 +67,7 @@ private:
void process_serial_2020();
void process_serial_3000();
signals:
void connected(bool);
void data_ready();
};

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

@ -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<QString, QString> 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<char> m_serialdata;
@ -95,6 +98,7 @@ private:
signals:
void data_ready();
void modem_data_ready(QByteArray);
void connected(bool);
};
#endif // SERIALMODEM_H

@ -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;

@ -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,26 +1303,16 @@ void YSFCodec::process_rx_data()
cnt = 0;
}
if(m_modeinfo.type == 3){
if(m_rxcodecq.size() > 10){
if((!m_tx) && (m_rximbecodecq.size() > 10)){
for(int i = 0; i < 11; ++i){
imbe[i] = m_rxcodecq.dequeue();
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_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";
}
}
else{
if((!m_tx) && (m_rxcodecq.size() > 6) ){
else if((!m_tx) && (m_rxcodecq.size() > 6) ){
for(int i = 0; i < 7; ++i){
ambe[i] = m_rxcodecq.dequeue();
}
@ -1342,15 +1335,16 @@ void YSFCodec::process_rx_data()
emit update_output_level(m_audio->level());
}
}
else if ( (m_modeinfo.stream_state == STREAM_END) || (m_modeinfo.stream_state == STREAM_LOST) ){
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 VD playback stopped";
qDebug() << "YSF playback stopped";
return;
}
}
}

@ -18,34 +18,36 @@
#ifndef YSFCODEC_H
#define YSFCODEC_H
const unsigned int YSF_FRAME_LENGTH_BYTES = 120U;
#include <cstdint>
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 <string>
#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<uint8_t> m_rximbecodecq;
};
#endif

Loading…
Cancel
Save