This isn't so much as something that is coming out soon, as much as it is some ideas and things I am trying to test out regarding NXDN Frame Sync related woes, in particular, the short Framesync Pattern (10 symbols FSW) can cause tons of false positives on plain noise if you don't squelch it. The simple answer is to say 'just use squelch' and I highly recommend that squelch is used on NXDN to prevent false positives. There is a reason NXDN is currently disabled by default in DSD-FME unless explicitly turned on.
All that being said, I have been doing some testing and trying things to see how to mitigate the FSW issues.
First, the easiest thing to say, is that currently I have (or will be with the next batch of commits) have where the user will not see any sync or false sync (unless payload printing is turned on) until it passes with a good lich parity. That being said, lich parity is 1 bit parity, so false positives happen on that all the time. I've made a few tweaks to not even turn on carrier until after the parity check passes, so that will also help with the Sync: No Sync: happening quite often.
The other thing I have tried to do is to, in addition to above, is to change the conditions of the FSW. Up to current, going way back to 'DSD Author' the symbol_p buffer holds demodulated symbols as a hard 1 and 3 symbol, which is fine for most sync patterns, except NXDN, which has a FSW pattern of (-3, +1, -3, +3, -3, -3, +3, +3, -1, +3), or hex value of 0xCDF59 when converted to dibit values. If you take this pattern and convert it to how the open source dsd project handles framesync patterns, the value for FSW would need to be something like 3031331121, which, if you can only work with 1s and 3s, you can't get this value out of the current demodulator when looking at framesync. (I should note that during framesync, we don't attempt to demodulate actual 4-level dibits, which, if it could do that, would be a lot more beneficial here and take away half the problems with this issue)
The way Louis Erig Herve found to work around is to compare the string in the synctest and say if it has one error, then we can proceed, which works well enough for most sync when you turn on squelch and don't feed it noise. The issue with this comparison, is which symbol is allowed to be in error. If any of them can be in error, but only up to one, that allows a lot more framesync issues than we need. Instead, we can narrow this down to symbol errors in 2 positions, where the 0 and the 2 are. Even further, I think we can rule out the 0 position, since that should always be the low and result in a '1' from the demodulator. Currently, I have in testing some code for doing an exact comparison between 4 values for FSW (as opposed to checking the string and letting it pick if any of those 10 symbols and saying this is a FSW but in reality, its just noise. I think this may also be able to be down to check for two FSW values, but currently it is at four. We can look for the exact string values and I have had pretty good luck in testing with getting good patterns with just these four, implemented like this
else if ( (strcmp (synctest10, "3131331131") == 0 ) ||
(strcmp (synctest10, "3331331131") == 0 ) ||
(strcmp (synctest10, "3131331111") == 0 ) ||
(strcmp (synctest10, "3331331111") == 0 ) )
These four values above, 3131331131, 3331331131, 3131331111, 3331331111, are all the variations you get from 3031331121 when the 0 and the 2 will be filled with a 1 or a 3. I believe I may be able to narrow this down further to just two of these four values, 3131331131 and 3131331111 since i believe that 0 will always result in a 1 during framesync here.
The inverse values are used to check for inverted polarity.
Another thing I am trying out is the theory, that when there is just plain noise, or lack of signal, the audio level is much louder than an organized signal. We can use that to say, limit when we allow FSW frame sync based off of the state->max value. If the value or its average is extremely high, then we most likely just have a ton of noise. If the max drops down to a certain range, then it is more likely organized signal. I made a secondary condition to check the state->max value, which is essentially like the inlvl, and say if it is above a value, then don't proceed, but if it falls low enough, then allow it to sync up. I've found this works extremely well and allows me to turn off squelch on nxdn decoding and rarely get false sync. The downside to doing is is that the user will need to be mindful of the audio input gain level, and may need to lower the gain in order to get good frame sync on signal and not on noise. Another downside is that this still will not allow NXDN to be autodetected as opposed to intentionally turned on as is, as any organized signal (DMR, etc) will still trigger a false sync pattern.
In the upcoming batch of updates, NXDN sync tests will be a cmake option, so users can toggle them on if they want to try it. It will be highly volatile and subject to change though, so probably don't use it unless you just want to see it in action or similar.
cmake -DNXDN=ON ..
will enable the test sync patterns and conditions for NXDN and building without it will be the same as before.
One last thought or two on NXDN Framesync and related problems, however.
First, one idea regarding NXDN framesync, we currently store patterns in a long synctest_p buffer. What we currently do for most synctests is to just grab the last x bits off of the buffer and compare it for framesync. The thing is, the buffer goes back pretty far, so we could just look at the current offset for a sync, then go backwards an nxdn frame worth of symbols and see if there was a FSW back there too, and then judge based off of that and say, okay, now we are really in a framesync. This one might be easier to implement since its already there, just needs to be tested/evaluated. Another idea would be a buffer where we store dibits, and when we get a framesync, we can store dibits. When we have a few FSW, then we can start to decode them and see if its just garbage data, and then if it is good data, then start voice and presenting data to the user. If its just garbage after several syncs then just discard all of it and the user never sees this happen behind the scenes. This option would require rewriting and careful layout. Something like a circular buffer for dibits. The only thing this idea brings me to logically is my second point.
Second, the most obvious solution to a lot of the issues with the framesync (along with DMR dibit buffer storage and P25 LSM), and other related issues. Is to re-write the code for framesync, the symbol buffer, demodulator, etc. Basically, in the long run, I will want to start at framesync, working backwards to everything involved, and rip it out and rewrite it entirely, or do major overhauls to it. I must admit, that would probably take me a year or more to do, and most of it would be spent learning as I go and/or trial and error. I really need to study demodulation, dsp, and buffers better and get a better grasp on it. For now however, I am okay with just working on things I can work on, adding a little here and there, and making what works today work a little better. I honestly think that starting from scratch would be a better option than rewriting tons of the demodulator related issues.