juribeparada / MMDVM_CM

Cross-mode conversion tools for MMDVM software
43 stars 53 forks source link

DMR2YSF Modifications to allow communication over new Wires-X software #27

Closed nostar closed 3 years ago

nostar commented 4 years ago

It seems that Yaesu has recently released new server software that broke the DMR2YSF feature of MMDVM based hotspots like Pi-Star. DMR users can no longer be heard across Wires-X links that run this new server software, which is causing all kinds of confusion on various repeaters/reflectors because people have been hearing a lot of one sided conversations lately. I made some changes that overcome this problem, and posted a detailed description of the changes on the QRZ forum. A link to that post can be found on my QRZ page for AD8DP. I wanted to create that post on the Pi-Star forum, but I'm going on day 2 now waiting for manual activation.

My patch simply hard codes everything in the source code as sort of a proof of concept, but I think maybe it could be implemented in a way that would require the end user to specifically enable these changes by way of an ini/conf file which could be accessed by the Expert menu, for example.

diff --git a/DMR2YSF/DMR2YSF.cpp b/DMR2YSF/DMR2YSF.cpp
index ebec9ef..63e0502 100644
--- a/DMR2YSF/DMR2YSF.cpp
+++ b/DMR2YSF/DMR2YSF.cpp
@@ -33,6 +33,9 @@
 const unsigned char dt1_temp[] = {0x31, 0x22, 0x62, 0x5F, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00};
 const unsigned char dt2_temp[] = {0x00, 0x00, 0x00, 0x00, 0x6C, 0x20, 0x1C, 0x20, 0x03, 0x08};

+// Added by AD8DP for FICH FT=6 transmissions
+const uint8_t dt1[10] = {0x01, 0x22, 0x61, 0x5f, 0x2b, 0x03, 0x11, 0x00, 0x00, 0x00};
+
 const unsigned char CONN_RESP[] = {0x5DU, 0x41U, 0x5FU, 0x26U};

 #define DMR_FRAME_PER       55U
@@ -48,6 +51,7 @@ const char* HEADER1 = "This software is for use on amateur radio networks only,"
 const char* HEADER2 = "it is to be used for educational purposes only. Its use on";
 const char* HEADER3 = "commercial networks is strictly prohibited.";
 const char* HEADER4 = "Copyright(C) 2018 by CA6JAU, G4KLX and others";
+const char ysf_radioid[] = {'H', '5', '0', '0', '0'};

 #include <functional>
 #include <algorithm>
@@ -649,17 +653,22 @@ int CDMR2YSF::run()
                CYSFFICH fich;
                fich.setFI(YSF_FI_HEADER);
                fich.setCS(2U);
+               fich.setCM(1U);
+               fich.setBN(0U);
+               fich.setBT(0U);
                fich.setFN(0U);
-               fich.setFT(7U);
+               fich.setFT(6U);
                fich.setDev(0U);
-               fich.setMR(2U);
+               fich.setMR(0U);
+               fich.setVoIP(false);
                fich.setDT(YSF_DT_VD_MODE2);
                fich.setSQL(0U);
                fich.setSQ(0U);
                fich.encode(m_ysfFrame + 35U);

                unsigned char csd1[20U], csd2[20U];
-               memset(csd1, '*', YSF_CALLSIGN_LENGTH);
+               memset(csd1, '*', YSF_CALLSIGN_LENGTH/2);
+               memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2);
                memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH);
                memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);

@@ -685,17 +694,22 @@ int CDMR2YSF::run()
                CYSFFICH fich;
                fich.setFI(YSF_FI_TERMINATOR);
                fich.setCS(2U);
+               fich.setCM(1U);
+               fich.setBN(0U);
+               fich.setBT(0U);
                fich.setFN(0U);
-               fich.setFT(7U);
+               fich.setFT(6U);
                fich.setDev(0U);
-               fich.setMR(2U);
+               fich.setMR(0U);
+               fich.setVoIP(false);
                fich.setDT(YSF_DT_VD_MODE2);
                fich.setSQL(0U);
                fich.setSQ(0U);
                fich.encode(m_ysfFrame + 35U);

                unsigned char csd1[20U], csd2[20U];
-               memset(csd1, '*', YSF_CALLSIGN_LENGTH);
+               memset(csd1, '*', YSF_CALLSIGN_LENGTH/2);
+               memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2);
                memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH);
                memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);

@@ -708,8 +722,9 @@ int CDMR2YSF::run()

                CYSFFICH fich;
                CYSFPayload ysfPayload;
+               unsigned char dch[10U];

-               unsigned int fn = (ysf_cnt - 1U) % 8U;
+               unsigned int fn = (ysf_cnt - 1U) % 7U;

                ::memcpy(m_ysfFrame + 0U, "YSFD", 4U);
                ::memcpy(m_ysfFrame + 4U, m_ysfNetwork->getCallsign().c_str(), YSF_CALLSIGN_LENGTH);
@@ -721,7 +736,9 @@ int CDMR2YSF::run()

                switch (fn) {
                    case 0:
-                       ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)"**********");
+                       memset(dch, '*', YSF_CALLSIGN_LENGTH/2);
+                       memcpy(dch + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2);
+                       ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch);
                        break;
                    case 1:
                        ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)m_netSrc.c_str());
@@ -729,11 +746,16 @@ int CDMR2YSF::run()
                    case 2:
                        ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)m_netDst.c_str());
                        break;
+                   case 5:
+                       memset(dch, ' ', YSF_CALLSIGN_LENGTH/2);
+                       memcpy(dch + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2);
+                       ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch); // Rem3/4
+                       break;
                    case 6:
-                       ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, gps_buffer);
+                       ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt1);
                        break;
                    case 7:
-                       ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, gps_buffer+10U);
+                       ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt2_temp);
                        break;
                    default:
                        ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)"          ");
@@ -742,10 +764,14 @@ int CDMR2YSF::run()
                // Set the FICH
                fich.setFI(YSF_FI_COMMUNICATIONS);
                fich.setCS(2U);
+               fich.setCM(1U);
+               fich.setBN(0U);
+               fich.setBT(0U);
                fich.setFN(fn);
-               fich.setFT(7U);
+               fich.setFT(6U);
                fich.setDev(0U);
-               fich.setMR(YSF_MR_BUSY);
+               fich.setMR(0U);
+               fich.setVoIP(false);
                fich.setDT(YSF_DT_VD_MODE2);
                fich.setSQL(0U);
                fich.setSQ(0U);
diff --git a/DMR2YSF/YSFFICH.cpp b/DMR2YSF/YSFFICH.cpp
index d1c7468..07b07da 100644
--- a/DMR2YSF/YSFFICH.cpp
+++ b/DMR2YSF/YSFFICH.cpp
@@ -232,6 +232,12 @@ void CYSFFICH::setCS(unsigned char cs)
    m_fich[0U] |= (cs << 4) & 0x30U;
 }

+void CYSFFICH::setCM(unsigned char cm)
+{
+   m_fich[0U] &= 0xF3U;
+   m_fich[0U] |= (cm << 2) & 0x0CU;
+}
+
 void CYSFFICH::setFN(unsigned char fn)
 {
    m_fich[1U] &= 0xC7U;
diff --git a/DMR2YSF/YSFFICH.h b/DMR2YSF/YSFFICH.h
index 3b49a68..d349886 100644
--- a/DMR2YSF/YSFFICH.h
+++ b/DMR2YSF/YSFFICH.h
@@ -44,6 +44,7 @@ public:

    void setFI(unsigned char fi);
    void setCS(unsigned char cs);
+   void setCM(unsigned char cm);
    void setFN(unsigned char fn);
    void setFT(unsigned char ft);
    void setBN(unsigned char bn);
nostar commented 4 years ago

I rewrote my changes as configuration variables for radio ID, DT1/DT2 (DCH bytes for VD2 frames 6 and 7), and the required FICH variables. Now, no longer is anything hard coded into the source code, and it is up to the end user to make setting changes and provide a radio ID via the ini file in order to use DMR2YSF over networks using Wires-X. I created a fork of this repo with these changes, since it sounds like you aren't around to look at this much these days. The default ini settings in this fork keep things pretty much as they were without my changes. I hope when you see this you decide to apply the changes to your repo, then I will ditch my fork.

-Doug AD8DP

juribeparada commented 4 years ago

Thank you very much Doug AD8DP for your work. Sorry to respond to this so late, I haven't had enough time for checking this properly due to my work load. Fortunately @AndyTaylorTweet has tested your work in Pi-Star and summited another PR recently based in your work.

Alpamayo57 commented 2 years ago

Hi Doug,

Any chance that this awesome work might be exported to DVSwitch? Thanks Mike IK7VXC