g4klx / MMDVMHost

The host program for the MMDVM
GNU General Public License v2.0
369 stars 268 forks source link

Support for the OpenGD77 Radioddity GD-77 firmware #513

Closed rogerclarkmelbourne closed 4 years ago

rogerclarkmelbourne commented 4 years ago

I'm trying to use MMDVMHost with effectively custom hardware which handles all the DMR syncing and framing etc

So I just need the the DMR data that comes in from the network to be sent to the modem, with a small amount of processing to strip off any network related data, not a 4FSK bitstream with all the syncing etc etc

I think potentially what I need is a different type of DMRSlot class, but I don't know where to start with this.

I've checked the branches, and I can't see anything which is suitable.

e.g. What my hardware needs is just the TS, CC, TG and DMR ID in DMR START, and only the bytes of the audio data in subsequent frames

e.g. This is our hardware's DMR setup code prior to transmission

https://github.com/hamdv/OpenGD77/blob/master/firmware/source/chips/fw_HR-C6000.c#L392-L407

Subsequent frames just get sent the audio data

g4klx commented 4 years ago

Hi Roger

Interesting thoughts. The DMR Start doesn't do what you think it does, and so isn't suitable for what you want. What would be better would be an new message type that contains the meta data for the following data stream. That would be easy to achieve without upsetting the rest of the operation of the system. The data stream is essentially complete DMR data frames (from what I remember). If the changes are deeper than that then I would suggest a completely new alternative to the MMDVMHost as the changes would be too deep to allow me to be comfortable with it.

The only issue is time of which I have zero currently..... :-(

rogerclarkmelbourne commented 4 years ago

Hi Jonathan

No worries.

Since posting the issue, I've built the code from source in VS2017 and have looked at the data being sent to a Zumspot libra

It looks like the internal data in DMRControl.cpp is what I need, but beyond that I've not had time to work out the best way to change the code.

Potentially, i may need to treat this a bit like a completely different mode, e.g. like P25 or YSF (the simpler the better), where there is new top level mode class, like CDMRControl

I'd also come to the same conclusion about message types, and that it would be best not to try to re-use existing message types, to send alternative data, but that I should create some new message types.

I realise the scope of these changes are possibly beyond what can be merged into your repo, as its going to be very specific to one piece of hardware + firmware.

Anyway, thanks for the reply.

rogerclarkmelbourne commented 4 years ago

Deleted last comment as the information in it was completely wrong ;-)

rogerclarkmelbourne commented 4 years ago

I think in hindsight, its probably going to be equally difficult to modify MMDVMHost as it would be to mimic what the MMDVM_HS sends to the normal version of MMDVMHost

I've modified the firmware in one of my radios to have the values 0x01,0x02,0x03 - 0x1B instead of the audio data and I can clearly see most of those numbers in the frames labelled "DMR Slot 2, audio sequence no. ..."

But what I still don't understand is how to construct the "voice header" frames

In this capture I'm using the DMR ID of 234435 = 0x23C52B to TG 505 = 0x0013BA and I can clearly see that in the data sent to the network, I can also see that a large portion of the RX DMR Data 2 frames at the start of the transmission, are sent unmodified in the network traffic

i.e the data from the modem starting from the 5th byte 03 F6 18 92 17 E0 21 F8 16 D0 9A 21 44 6D 5D 7F 77 FD 75 7E 32 A8 03 C8 2C 70 80 21 6B 42 B1 83 15

is sent at bytes 0x14 onwards

The 4th byte with value 0x41 which seems to indicate this is a voice header frame.

But somehow MMDVM is reading that raw data from the modem and making this data

44 4D 52 44 00 23 C5 2B 00 13 BA 00 4D 1B 36 A1    *DMRD.#.+....M.6.*
0010:  1D 31

Albeit the first 4 bytes are a header.

Anyway, I need a way to construct the voice frame header data, but there seems to be far more data in the header than I can possibly have in the radio.

Since I only have Call Type, Source ID and Destination ID.

-------------------- Full data capture -------------------------------

RX DMR Data 2
0000:  E0 25 1A 41 03 F6 18 92 17 E0 21 F8 16 D0 9A 21    *.%.A......!....!*
0010:  44 6D 5D 7F 77 FD 75 7E 32 A8 03 C8 2C 70 80 21    *Dm].w.u~2...,p.!*
0020:  6B 42 B1 83 15                                     *kB...*
Network Transmitted
0000:  44 4D 52 44 00 23 C5 2B 00 13 BA 00 4D 1B 36 A1    *DMRD.#.+....M.6.*
0010:  1D 31 00 00 03 F6 18 92 17 E0 21 F8 16 D0 9A 21    *.1........!....!*
0020:  44 6D 5D 7F 77 FD 75 7E 32 A8 03 C8 2C 70 80 21    *Dm].w.u~2...,p.!*
0030:  6B 42 B1 83 15 00 00                               *kB.....*
DMR Slot 2, received RF voice header from G4KYF to TG 5050
RX DMR Data 2
0000:  E0 25 1A 41 03 F6 18 92 17 E0 21 F8 16 D0 9A 21    *.%.A......!....!*
0010:  44 6D 5D 7F 77 FD 75 7E 32 A8 03 C8 2C 70 80 21    *Dm].w.u~2...,p.!*
0020:  6B 42 B1 83 15                                     *kB...*
RX DMR Data 2
0000:  E0 25 1A 41 03 F6 18 92 17 E0 21 F8 16 D0 9A 21    *.%.A......!....!*
0010:  44 6D 5D 7F 77 FD 75 7E 32 A8 03 C8 2C 70 80 21    *Dm].w.u~2...,p.!*
0020:  6B 42 B1 8B 15                                     *kB...*
RX DMR Data 2
0000:  E0 25 1A 20 01 02 03 04 04 06 03 08 09 0A 0B 0C    *.%. ............*
0010:  0D 03 F7 D5 DD 17 DF DE 0F 10 11 12 13 14 15 16    *................*
0020:  17 18 19 1A 1B                                     *.....*
DMR Slot 2, audio sequence no. 0, errs: 18/141 (12.8%)
Network Transmitted
0000:  44 4D 52 44 01 23 C5 2B 00 13 BA 00 4D 1B 36 90    *DMRD.#.+....M.6.*
0010:  1D 31 00 00 01 00 03 04 00 26 03 00 01 8E A8 42    *.1.......&.....B*
0020:  00 07 F7 D5 DD 57 DF D4 44 00 80 84 8E A8 42 00    *.....W..D.....B.*
0030:  04 44 00 80 84 12 00                               *.D.....*
RX DMR Data 2
0000:  E0 25 1A 01 01 02 03 04 05 06 07 08 09 0A 0B 0C    *.%..............*
0010:  0D 01 30 90 A0 C1 49 1E 0F 10 11 12 13 14 15 16    *..0...I.........*
0020:  17 18 19 1A 1B                                     *.....*
DMR Slot 2, audio sequence no. 1, errs: 18/141 (12.8%)
Network Transmitted
0000:  44 4D 52 44 02 23 C5 2B 00 13 BA 00 4D 1B 36 81    *DMRD.#.+....M.6.*
0010:  1D 31 00 00 01 02 03 44 45 06 47 00 01 8E A8 42    *.1.....DE.G....B*
0020:  00 01 30 90 A0 C1 49 14 44 00 80 84 8E A8 42 00    *..0...I.D.....B.*
0030:  04 44 00 80 84 12 00                               *.D.....*
g4klx commented 4 years ago

You need to look at https://github.com/pd0mz/go-dmr/blob/master/docs/MMDVM%20Specification%2020151208.pdf to get understand the format. The DMR data (the 33 bytes it mentions) is unmodified DMR data from/to over the air, complete with FEC, interleaving, etc. The network side is similar, although the network header includes meta data like the source and destination ids to make routing and interpretation of the packets by the network easier without having to delve into the raw DMR data. You obviously need to look at the official DMR ETSI specification to understand those 33 bytes whose format varies depending on their use.

rogerclarkmelbourne commented 4 years ago

Jonathan

Thanks.

I have the MMDVM interface working OK, its the internals of the DMR ETSI standard, that I need to understand.

Because I need to generate the voice header frame

0000:  E0 25 1A 41 03 F6 18 92 17 E0 21 F8 16 D0 9A 21    *.%.A......!....!*
0010:  44 6D 5D 7F 77 FD 75 7E 32 A8 03 C8 2C 70 80 21    *Dm].w.u~2...,p.!*
0020:  6B 42 B1 83 15                                     *kB...*

I think I'll take a look at how the hotspots generate the calibration data, or how the YSF to DMR works, because that will need to generate the same thing from just the IDs and call type

rogerclarkmelbourne commented 4 years ago

@g4klx

I think I've figured out what I need to do.

When MMDVMHost sends the voice header frame to the modem (in my case the OpenGD77 firmware), I need the src and dst Id's as well as the call type, because that's what the DMR DSP chip in the GD-77 needs.

Looking in your code, I see that going in the opposite direction, when you receive a voice header frame from the modem, you need to extract the src and dst Id's etc, because you need to build the wrapper data that is sent to the network server.

i.e thats called here https://github.com/g4klx/MMDVMHost/blob/master/DMRSlot.cpp#L206-L212

So, in theory I think I can use your FullLC.decode() function when the OpenGD77 receives the voice header frame from MMDVMHost.

I've copied all your files that handle the FulLC decode into the OpenGD77 firmware, but I've had to port them to C, because the official NXP MCU SDK that we are using, is a C project. (It may have been possible to compile some files at C++ but I decided its better to keep everything in C for stability etc)

Unfortunately at the moment, when I feed the same voice header data into the code in MMDVMHost on my PC (in Visual Studio), and into the OpenGD77 firmware

const uint8_t frameData[] = {0x0B,0xE6,0x08,0x92,0x13,0xE0,0x20,0xF8,0x12,0xD0,0x9A,0x21,0x44,0x6D,0x5D,0x3F,0x77,0xFD,0x35,0x7E,0x32,0xA8,0x03,0xC8,0x2C,0x70,0x80,0x21,0x6B,0x42,0xB1,0x83,0x15};

At the moment I don't send up with the correct data in the CDMRLC data struct.

So either the problem is something to do with the Endianness of the ARM MK22 MCU in the GD-77 being LittleEndian and the X86 in the PC being BigEndian, or I've screwed up somewhere in my port from C++ to C.

And I'll probably have to send several hours debugging where the data starts to differ.

What makes things more difficult is neither the VS2017 or in MCUExpesso (for the firmware), debuggers, want to show me the the bool array's used for the bit manipulation. So I'll have to write some functions to log each bitstream and confirm that process is working OK before I move on to looking at the Hamming decode etc etc

g4klx commented 4 years ago

I can't comment on your ported code, but to say that my code is endian-ness agnostic. It was designed that way from the start. Indeed the MMDVMHost compiles and runs on Raspberry Pis as you know. I am not a fan of the code in the LC processing as it is the oldest part of the system and I'd love to rewrite it at some point. However it works and that's enough for now.

rogerclarkmelbourne commented 4 years ago

@g4klx

Thanks.

I debugged my code and its working now.

I had a typo (paste'o) but also the final part of conversion where the individual bytes are shifted and or'ed to make the src and dst Id's wasn't working on my platform.

https://github.com/g4klx/MMDVMHost/blob/master/DMRLC.cpp#L57-L58

I had to cast the bytes to unit32_t before shifting them.. And the frame decode is now giving the correct results.

Next job is to get the frame encode working, because I'll need that as well ;-)

Thanks...

BTW. I'm retaining your copyright on the top of the files and adding in a note that I have ported them.

I'll post a link once I've committed the files to my repo.

rogerclarkmelbourne commented 4 years ago

@g4klx

I think I've got the voice frame encoding working now, but its a bit odd, because if I decode a known byte array to the FullLC and then re-encode the same LC data, I get a different byte array, but if I decode the array I've just encoded, I seem to get the correct LC data.

I've compared the byte array from my ported version of the encode funtion with the same your code, and my encoded byte array is the same as yours.

So it looks like its working OK. But its odd that the encoded and original byte arrays are totally dissimilar.

g4klx commented 4 years ago

That's odd and worrying. Did you try feeding my encoder (or yours) into my decoder to see what happens? I'm always interested in bugs, and that would be a serious one!

rogerclarkmelbourne commented 4 years ago

@g4klx

I wrote some code in MMDVMHost to decode, then re-encode the LC params and then decode and then re-encode again.

I've pasted the results and my test code below

As you can see the encoded bytes are different for 2 different reasons.

  1. I noticed my initial data was not 100% error free, and the decode bit pattern was error corrected as part of the decode process. Hence why I think there are single bit differences in a number of the bytes.

  2. The encode does not seem to populate all of the frame. The bytes from 0x0C for a length of 7 bytes are zeros in the encoded data, but have data in the original bytes.

The encoder never seems to populate those bytes.

Perhaps its my misunderstanding of what the encode function does.

I was hoping to generate a valid Voice Header frame from Src, Dst etc, since thats the only data I get from the hardware in the radio. Actually I get 12 bytes of data from the hardware, which but the data is not in exactly the same position. The Dst seems to be in the 4th, 5th and 6th bytes of the LC data from the hardware, but are in the 3rd,4th and 5th bytes in the decoded LC in MMDVMHost, but that's not a problem for me.

Note the initial data was captured in DMRSlot.cpp when I transmitted from my radio into my Zumspot Libre

Thanks

Roger

D: 2019-08-16 22:40:11.612 Initial frame data
D: 2019-08-16 22:40:11.612 0000:  0B E6 08 92 13 E0 20 F8 12 D0 9A 21 44 6D 5D 3F    *...... ....!Dm]?*
D: 2019-08-16 22:40:11.612 0010:  77 FD 35 7E 32 A8 03 C8 2C 70 80 21 6B 42 B1 83    *w.5~2...,p.!kB..*
D: 2019-08-16 22:40:11.612 0020:  15                                                 *.*
M: 2019-08-16 22:40:11.612 LC params are SrcId=2344235 DstId=5050 RF=0 FCLO=0 FID=0x00
M: 2019-08-16 22:40:11.612 Re-encoding LC params
D: 2019-08-16 22:40:11.612 re-encoded frame data
D: 2019-08-16 22:40:11.613 0000:  03 F6 18 92 17 E0 21 F8 16 D0 9A 21 40 00 00 00    *......!....!@...*
D: 2019-08-16 22:40:11.613 0010:  00 00 00 00 02 A8 03 C8 2C 70 80 21 6B 42 B1 83    *........,p.!kB..*
D: 2019-08-16 22:40:11.613 0020:  15                                                 *.*
M: 2019-08-16 22:40:11.613 Decoding the re-encoded frame data
M: 2019-08-16 22:40:11.613 re-encoded params are SrcId=2344235 DstId=5050 RF=0 FCLO=0 FID=0x00
D: 2019-08-16 22:40:11.613 Re-encode again
D: 2019-08-16 22:40:11.613 0000:  03 F6 18 92 17 E0 21 F8 16 D0 9A 21 40 00 00 00    *......!....!@...*
D: 2019-08-16 22:40:11.613 0010:  00 00 00 00 02 A8 03 C8 2C 70 80 21 6B 42 B1 83    *........,p.!kB..*
D: 2019-08-16 22:40:11.613 0020:  15                                                 *.*
```

const uint8_t frameData[DMR_FRAME_LENGTH_BYTES] = { 0x0B,0xE6,0x08,0x92,0x13,0xE0,0x20,0xF8,0x12,0xD0,0x9A,0x21,0x44,0x6D,0x5D,0x3F,0x77,0xFD,0x35,0x7E,0x32,0xA8,0x03,0xC8,0x2C,0x70,0x80,0x21,0x6B,0x42,0xB1,0x83,0x15 }; CUtils::dump(1U, "Initial frame data", frameData, DMR_FRAME_LENGTH_BYTES);

CDMRFullLC fullLC;
CDMRLC* lc = fullLC.decode(frameData, DT_VOICE_LC_HEADER);
if (lc == NULL)
    return false;
LogMessage("LC params are SrcId=%d DstId=%d RF=%d FCLO=%d FID=0x%02x", lc->getSrcId(), lc->getDstId(), lc->getPF(), lc->getFLCO(), lc->getFID());

uint8_t frameReEncoded[DMR_FRAME_LENGTH_BYTES];
memset(frameReEncoded, 0, DMR_FRAME_LENGTH_BYTES);// clear
CDMRFullLC fullLCEncoded;
fullLCEncoded.encode(*lc, frameReEncoded, DT_VOICE_LC_HEADER);
LogMessage("Re-encoding LC params");
CUtils::dump(1U, "re-encoded frame data", frameReEncoded, DMR_FRAME_LENGTH_BYTES);
LogMessage("Decoding the re-encoded frame data");
CDMRLC* lc2 = fullLC.decode(frameReEncoded, DT_VOICE_LC_HEADER);
if (lc2 == NULL)
    return false;
LogMessage("re-encoded params are SrcId=%d DstId=%d RF=%d FCLO=%d FID=0x%02x", lc2->getSrcId(), lc2->getDstId(), lc2->getPF(), lc2->getFLCO(), lc2->getFID());

fullLCEncoded.encode(*lc, frameReEncoded, DT_VOICE_LC_HEADER);
CUtils::dump(1U, "Re-encode again", frameReEncoded, DMR_FRAME_LENGTH_BYTES);
g4klx commented 4 years ago

Hi Roger I think those zero bytes are where the sync pattern goes, and that is added elsewhere. This pattern depends on usage. They are certainly not a function that the LC code provides. You need to look at the ETSI standard to understand what goes where since the data is in DMR on air format throughout the MMDVM system. Jonathan G4KLX 

Sent from Yahoo Mail for iPhone

On Saturday, August 17, 2019, 02:16, Roger Clark notifications@github.com wrote:

@g4klx

I wrote some code in MMDVMHost to decode, then re-encode the LC params and then decode and then re-encode again.

I've pasted the results and my test code below

As you can see the encoded bytes are different for 2 different reasons.

The encoder never seems to populate those bytes.

Perhaps its my misunderstanding of what the encode function does.

I was hoping to generate a valid Voice Header frame from Src, Dst etc, since thats the only data I get from the hardware in the radio. Actually I get 12 bytes of data from the hardware, which but the data is not in exactly the same position. The Dst seems to be in the 4th, 5th and 6th bytes of the LC data from the hardware, but are in the 3rd,4th and 5th bytes in the decoded LC in MMDVMHost, but that's not a problem for me.

Note the initial data was captured in DMRSlot.cpp when I transmitted from my radio into my Zumspot Libre

Thanks

Roger D: 2019-08-16 22:40:11.612 Initial frame data D: 2019-08-16 22:40:11.612 0000: 0B E6 08 92 13 E0 20 F8 12 D0 9A 21 44 6D 5D 3F ...... ....!Dm]? D: 2019-08-16 22:40:11.612 0010: 77 FD 35 7E 32 A8 03 C8 2C 70 80 21 6B 42 B1 83 w.5~2...,p.!kB.. D: 2019-08-16 22:40:11.612 0020: 15 . M: 2019-08-16 22:40:11.612 LC params are SrcId=2344235 DstId=5050 RF=0 FCLO=0 FID=0x00 M: 2019-08-16 22:40:11.612 Re-encoding LC params D: 2019-08-16 22:40:11.612 re-encoded frame data D: 2019-08-16 22:40:11.613 0000: 03 F6 18 92 17 E0 21 F8 16 D0 9A 21 40 00 00 00 ......!....!@... D: 2019-08-16 22:40:11.613 0010: 00 00 00 00 02 A8 03 C8 2C 70 80 21 6B 42 B1 83 ........,p.!kB.. D: 2019-08-16 22:40:11.613 0020: 15 . M: 2019-08-16 22:40:11.613 Decoding the re-encoded frame data M: 2019-08-16 22:40:11.613 re-encoded params are SrcId=2344235 DstId=5050 RF=0 FCLO=0 FID=0x00 D: 2019-08-16 22:40:11.613 Re-encode again D: 2019-08-16 22:40:11.613 0000: 03 F6 18 92 17 E0 21 F8 16 D0 9A 21 40 00 00 00 ......!....!@... D: 2019-08-16 22:40:11.613 0010: 00 00 00 00 02 A8 03 C8 2C 70 80 21 6B 42 B1 83 ........,p.!kB.. D: 2019-08-16 22:40:11.613 0020: 15 .



const uint8_t frameData[DMR_FRAME_LENGTH_BYTES] = { 0x0B,0xE6,0x08,0x92,0x13,0xE0,0x20,0xF8,0x12,0xD0,0x9A,0x21,0x44,0x6D,0x5D,0x3F,0x77,0xFD,0x35,0x7E,0x32,0xA8,0x03,0xC8,0x2C,0x70,0x80,0x21,0x6B,0x42,0xB1,0x83,0x15 };
CUtils::dump(1U, "Initial frame data", frameData, DMR_FRAME_LENGTH_BYTES);
CDMRFullLC fullLC;
CDMRLC* lc = fullLC.decode(frameData, DT_VOICE_LC_HEADER);
if (lc == NULL)
    return false;
LogMessage("LC params are SrcId=%d DstId=%d RF=%d FCLO=%d FID=0x%02x", lc->getSrcId(), lc->getDstId(), lc->getPF(), lc->getFLCO(), lc->getFID());

uint8_t frameReEncoded[DMR_FRAME_LENGTH_BYTES];
memset(frameReEncoded, 0, DMR_FRAME_LENGTH_BYTES);// clear
CDMRFullLC fullLCEncoded;
fullLCEncoded.encode(*lc, frameReEncoded, DT_VOICE_LC_HEADER);
LogMessage("Re-encoding LC params");
CUtils::dump(1U, "re-encoded frame data", frameReEncoded, DMR_FRAME_LENGTH_BYTES);
LogMessage("Decoding the re-encoded frame data");
CDMRLC* lc2 = fullLC.decode(frameReEncoded, DT_VOICE_LC_HEADER);
if (lc2 == NULL)
    return false;
LogMessage("re-encoded params are SrcId=%d DstId=%d RF=%d FCLO=%d FID=0x%02x", lc2->getSrcId(), lc2->getDstId(), lc2->getPF(), lc2->getFLCO(), lc2->getFID());

fullLCEncoded.encode(*lc, frameReEncoded, DT_VOICE_LC_HEADER);
CUtils::dump(1U, "Re-encode again", frameReEncoded, DMR_FRAME_LENGTH_BYTES);

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
rogerclarkmelbourne commented 4 years ago

@g4klx

I see you have code to add the sync, so I'll take a look at that.

I was surprised that the data that is sent to and from the network is the On-Air data, but I guess that makes sense if that's the domain the modem is working in.

Unfortunately, I'm partially working in the other domain, so I'll have to create a version of the On-Air data, to send to MMDVMHost (to send to the network) but this data is normally generated by the DMR DSP chip in the radio, and AFIK, I can't access the On-AIR side of the DMR DSP chip, as it handles everything including the FM modulation to produce the 4FSK signal.

rogerclarkmelbourne commented 4 years ago

@g4klx

Sorry to keep asking you dumb questions, but I'm not sure who else would know the answer (probably hardly anyone else)

I'm a bit confused about why the data bytes from the modem, look totally different from the data bytes going to the modem.

e.g. Using PC 9990 parrot.

I have my radio setup to put 0x55, 0xAA , 0x55 , 0xAA into its audio data pipeline

And the Zumspot libra seems to receive my raw audio data and send it to MMDVMHost

e.g.

D: 2019-08-17 10:27:02.814 TX DMR Data 2
D: 2019-08-17 10:27:02.894 0000:  E0 25 1A 01 55 AA 55 AA 55 AA 55 AA 55 AA 55 AA    *.%..U.U.U.U.U.U.*
D: 2019-08-17 10:27:02.895 0010:  55 A1 30 00 31 40 C9 1A 55 AA 55 AA 55 AA 55 AA    *U.0.1@..U.U.U.U.*
D: 2019-08-17 10:27:02.896 0020:  55 AA 55 AA 55   

MMDVMHost then processes the data to send this

8E A8 42 00 04 44 00 80 84 8E A8 42 00 01 70 F1  49 39 07 44 44 00 80 84 8E A8 42 00 04 44 00 80 84

i.e.

D: 2019-08-17 10:27:02.606 Network Transmitted
D: 2019-08-17 10:27:02.606 0000:  44 4D 52 44 03 23 C5 2B 00 27 06 00 23 C5 2B C2    *DMRD.#.+.'..#.+.*
D: 2019-08-17 10:27:02.607 0010:  37 4A 00 00 8E A8 42 00 04 44 00 80 84 8E A8 42    *7J....B..D.....B*
D: 2019-08-17 10:27:02.608 0020:  00 01 70 F1 49 39 07 44 44 00 80 84 8E A8 42 00    *..p.I9.DD.....B.*
D: 2019-08-17 10:27:02.608 0030:  04 44 00 80 84 14 00     

And the network received data looks almost identical to whats been sent (which is no surprise)

D: 2019-08-17 10:27:09.856 Network Received
D: 2019-08-17 10:27:09.856 0000:  44 4D 52 44 06 00 27 06 23 C5 2B 00 23 C5 2B C3    *DMRD..'.#.+.#.+.*
D: 2019-08-17 10:27:09.856 0010:  00 00 00 00 8E A8 42 00 04 44 00 80 84 8E A8 42    *......B..D.....B*
D: 2019-08-17 10:27:09.856 0020:  00 01 72 22 41 BA 97 44 44 00 80 84 8E A8 42 00    *..r"A..DD.....B.*
D: 2019-08-17 10:27:09.857 0030:  04 44 00 80 84 00 00   

But MMDVMHost does not reverse the process it does during transmission, and just sends


D: 2019-08-17 10:27:10.087 TX DMR Data 2
D: 2019-08-17 10:27:10.087 0000:  E0 25 1A 00 8E A8 42 20 00 44 04 80 84 8E A8 42    *.%....B .D.....B*
D: 2019-08-17 10:27:10.087 0010:  20 01 72 22 41 BA 97 40 44 04 80 84 8E A8 42 20    * .r"A..@D.....B *
D: 2019-08-17 10:27:10.088 0020:  00 44 04 80 84   

So either the Zumspot firmware is processing the incoming 4FSK data to get the raw bytes that I recognise and sent them to MMDVMHost. Or the Zumspot must be processing the bytes from MMDVMHost prior to transmission

I can't see how RX DMR Data 2 and TX DMR Data 2 are both in the On-Air format.

It looks like TX DMR Data 2 is the network format, and possibly RX DMR Data 2 is the On-Air format.

I guess, I'll need to start going through the modem code as well, to see where the asymmetric conversion is happening :-(

Because I can generate the RX DMR Data 2 directly from the data I get from the DMR DSP chip in the GD-77 but I will somehow need to convert the TX DMR Data 2 to look like RX DMR Data 2

rogerclarkmelbourne commented 4 years ago

@g4klx

I have worked out why the data on the network is not the data from the modem.

I didn't realise that the bytes that I send to the DMR hardware, need to have error correction encoded into them, because if not, MMDVMHost's error correction system ends up totally changing the bytes.

rogerclarkmelbourne commented 4 years ago

@g4klx

I have one half of my "modem" working, but I have a problem with generating the embedded LC content which I need to send to MMDVMHost

I can use DMREmbedded.c to generate the embedded LC for audio sequence numbers 1 - 4, but the sequence counts up to 5.

Currently DMREmbedded returns zeros' for sequence numbers 0 and 5

Sequence 0 is OK because it contains the MS_SOURCED_AUDIO_SYNC data

But 5 will have zeros in it, which is different from what I've observed in the logs.

I'll try using zero's but I suspect it will cause problems :-(

Edit. It looks like MMDVMCal functionality, also has zero's in this data, so perhaps its acceptable

// Embedded LC MS: CC: 1, srcID: 1, dstID: TG9 const uint8_t SYNCEMB_DMO1K[6][7] = { {0x07U, 0xF7U, 0xD5U, 0xDDU, 0x57U, 0xDFU, 0xD0U}, // MS VOICE SYNC (audio seq 0) {0x01U, 0x30U, 0x00U, 0x00U, 0x90U, 0x09U, 0x10U}, // EMB + Embedded LC1 (audio seq 1) {0x01U, 0x70U, 0x00U, 0x90U, 0x00U, 0x07U, 0x40U}, // EMB + Embedded LC2 (audio seq 2) {0x01U, 0x70U, 0x00U, 0x31U, 0x40U, 0x07U, 0x40U}, // EMB + Embedded LC3 (audio seq 3) {0x01U, 0x50U, 0xA1U, 0x71U, 0xD1U, 0x70U, 0x70U}, // EMB + Embedded LC4 (audio seq 4) {0x01U, 0x10U, 0x00U, 0x00U, 0x00U, 0x0EU, 0x20U}}; // EMB (audio seq 5)

g4klx commented 4 years ago

Hi Roger

I think the zeros are correct. The Embedded LC is designed to be a general purpose extensible way to incorporate data into the audio stream, as well as ID data, it also used for embedded GPS and talker alias. In the case of id data, then only four of the slots are used and the fifth is set to zeros. In fact all of them can be set to zeros but that would remove the ability to handle late entry at the receiving end.

rogerclarkmelbourne commented 4 years ago

Hi Jonathan

OK. I''ll try using zero's.

I've just starting to test my frame generation code now ;-), so hopefully over the weekend I'll be able to test what happens when I send zero's with real data

BTW. My data flow is as follows

the 4FSK signal gets decoded by the HR-C6000 DMR DSP chip (its basically the same chip thats in the TYT-MD380 and a whole load of other radios, including the Baofengs) This gives me the LC data bytes as well as the audio bytes, from separate "pages" of registers in the chip.

So to create data for MMDVMHost, I have to recreate the full frame data, as if its the output of the 4FSK decoder as well as the MMDVMHost protocol header, and the embedded data has been the stumbling block for a day.

Anyway, I'm still curious about what is potentially being sent in sequence 5 e.g. I happened to capture an frame with no audio at the end of my transmission, with embedded bytes

0F 3A D5 EE 20

and when I checked previous sequence frame 5 that had been transmitted,

I can see the xF 3A D5 EE 2x in the data

I'm not transmitting TA in the RF, but even if I was transmitting TA I don't think it takes any more bytes than a regular LC, as thought the TA data was effectively a union applied to the LC data struct.

Thanks

Roger

VK3KYY/G4KYF

D: 2019-08-22 03:15:31.934 RX DMR Data 2
D: 2019-08-22 03:15:31.934 0000:  E0 25 1A 05 00 00 00 00 00 00 00 00 00 00 00 00    *.%..............*
D: 2019-08-22 03:15:31.935 0010:  00 01 19 0F 3A D5 EE 20 00 00 00 00 00 00 00 00    *....:.. ........*
D: 2019-08-22 03:15:31.935 0020:  00 00 00 00 00                                     *.....*
D: 2019-08-22 03:15:31.936 DMR Slot 2, audio sequence no. 5, errs: 9/141 (6.4%)
rogerclarkmelbourne commented 4 years ago

@g4klx

FYI.

I've finally got the OpenGD77 firmware working like a MMDVM_HS modem.

Its a bit unreliable at the moment, and I still need to implement Private Calls and also still need to extract the TA data from the embedded data and use it to configure the DMR DSP so that it gets transmitted on air,..... but its definitely working !

There are still a new things I don't understand, but hopefully I won't need to bother you again, and I don't need a special customised version of MMDVMHost, and it should work withe PiStar (Though I'm still testing using a PC at the moment)

Thanks

Roger

VK3KYY / G4KYF

shawnchain commented 4 years ago

@rogerclarkmelbourne That's cool ! Wish my MD380 could run as a hotspot with your work.

PS: You can get the FLCO/PDU info from - http://www.etsi.org/deliver/etsi_ts/102300_102399/10236102/02.03.01_60/ts_10236102v020301p.pdf page 52

rogerclarkmelbourne commented 4 years ago

The MD-380 uses the same basic hardware, except for the MCU and the display, and in the long term the project aim is to port to the MD-380 etc, but we have a lot more work to do on GD-77 first

Re: FCLO/PDU. I've ported a lot of the MMDVMHost utility classes to the OpenGD77 firmware and I can detect frame type and also extract the FCLO etc from the Voice LC frame and I also construct the frame data from the Src and Dst etc.

I also construct the audio frames embed data using the MMDVMHost code and it seems to be working OK.

I've had to add a USB Serial ring buffer to my code today, because the RPi was giving me a lot of "busy" notifications when I tried to write the USB data, but the ring buffer seems to have fixed all of these.

I still need to add a lot more error handling to my code but it now seems to be usable on PiStar.

rogerclarkmelbourne commented 4 years ago

@g4klx

Jonathan, is there a way to decode sequence number from the DMR data that MMDVMHosts sends to the hotspot.

MMDVMHost does not seem to send the sequence number to the hotspot in the first byte of the data payload (after the 3 byte header), as that byte always seems to be zero.

But I need to decode the embedded data to handle Late Start but also to decode the TA data, as I need the raw LC data to send to the DMR DSP chip in the GD-77

Initially I thought I could inspect the sync bytes before and after the embedded data bytes, however there doesnt seem to be a unique pattern, because sequence number 3 and 4 seem to use the same pattern (unless I've missinterpreted mydata captures)

I guess I could look for the sequence zero pattern
0x04U, 0x6DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x7EU, 0x30U and then assume the next frames are arriving in the correct sequence,

But I was hoping to be able to identify individual sequence numbers from the data

iw0red commented 4 years ago

Great job! I'll be waiting some other news. 73 Marco IW0RED.

On Sat, Aug 24, 2019 at 1:30 PM Roger Clark notifications@github.com wrote:

@g4klx https://github.com/g4klx

FYI.

I've finally got the OpenGD77 firmware working like a MMDVM_HS modem.

Its a bit unreliable at the moment, and I still need to implement Private Calls and also still need to extract the TA data from the embedded data and use it to configure the DMR DSP so that it gets transmitted on air,..... but its definitely working !

There are still a new things I don't understand, but hopefully I won't need to bother you again, and I don't need a special customised version of MMDVMHost, and it should work withe PiStar (Though I'm still testing using a PC at the moment)

Thanks

Roger

VK3KYY / G4KYF

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/g4klx/MMDVMHost/issues/513?email_source=notifications&email_token=ACGLPS6FWEM6XOT5O5262LLQGELURA5CNFSM4IG7UVRKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD5B6ILY#issuecomment-524543023, or mute the thread https://github.com/notifications/unsubscribe-auth/ACGLPS43TR2FAPZQDHWQOMLQGELURANCNFSM4IG7UVRA .

-- Marco Brunozzi

Tel. +14152360004 Cel. +393483343274 Skype: marco.brunozzi Twitter: marcobrunozzi

g4klx commented 4 years ago

Hi Roger

I really really really suggest that you read the ETSI specification for DMR so you can get a handle on the format. There is no sequence number between the host and modem, nor is there one on-air. The only fixed items are the sync patterns, both the data and audio syncs and everything else is variable. The sequence number you refer to, isn't. It indicates the start of the data, the end of the data, or data in between, it cannot be used for synchronisation.

Jonathan G4KLX

rogerclarkmelbourne commented 4 years ago

OK.

I have read various part for the spec, but I could not find what I was looking for, which is how to decode the embedded data.

I ported your embedded data class, and I'm using it to generate the embedded LC data bytes which are inserted into 3 of the 6 frame sequence.

However I could not see how to do the reverse to extract the TA information from the embedded data (or the Link Connect data when there is a Late Start).

Anyway. I'll look in the spec again to see if it described how to decode the data which is spread across multiple frames

rogerclarkmelbourne commented 4 years ago

Thanks everyone.

Its all working now.

I just needed to use the same code that the TA inspection stuff in MMDVMHost uses, and I was able to recover both the Group or User LC and also the TA data.