Feedback: Multi and Hirate Demodulators
I added your demod to my airspy/hirate stack and using the same 10 second capture file...
| HiRate | Multi | |
|---|---|---|
| preambles | 155088 | 55043 |
| usable messages | 12828 | 11383 |
| unique acrft | 178 | 170 |
| cpu | 32% | 11% |
HiRate doesn't yet use the starch stuff yet.
I think I'm going to look at your preamble detection code since your preamble/usable ratio is much better.
I cut my CPU utilization down 5 points using boxcar_u16 but I'm still letting way too many unusable preambles through, which is where the CPU time is. I'll look more at that tomorrow as well as looking at if there's anything I can do to bring the demod_multi usable messages and aircraft up.
Since the only thing changing in the demod function variations is DEMOD_SAMPLES_PER_HALFBIT, why not just pass it in to the function? Saves the complexity of the includes which allows editors like Eclipse to function better, and the Makefile to detect changes and there's no decrease in performance as far as I can see.
Might want to consider parameterizing the boxcar window for tuning purposes. Using a 12 MS/s rate, more messages are decoded if the boxcar window is actually 4 rather than 6 (DEMOD_SAMPLES_PER_HALFBIT).
What's your plan for signal and noise? Right now I'm keeping track of the message marks and spaces and using the average of the marks for the signal and the average of the spaces for the noise.
why not just pass it in to the function?
The halfbit value is used in busy parts of the loop; I wanted to encourage the compiler to take advantage of it being constant without relying on constant propagation. More generally I wanted to vary a bunch of parameters that might not be so easy to pass in as arguments. I'm sure you can convince Eclipse etc to treat it as C (that's what the emacs mode line does for emacs..)
Might want to consider parameterizing the boxcar window for tuning purposes.
Yes, my previous experimentation showed something similar, I haven't got as far as reimplementing that in the clean version. Most of my testing so far has been done at 6MHz for USB bandwidth reasons (was running a rtlsdr in parallel on the same USB bus) where it has less of an effect.
What's your plan for signal and noise?
Average of marks is a reasonable thing for signal (I'm considering updating the definition for the 2.4MHz demodulator too).
Noise is an interesting one and I have been playing with a few ideas there, both for overall stats & for computing the noise estimate fed into the threshold calculation. The general shape so far is:
-
break demodulation up into predictable blocks (probably implemented as a wrapper around the actual demodulator); do noise calculations aligned with those block boundaries only, so that demodulation that depends on the noise values is independent of the SDR block size and can be made independent of the sampling rate. (The current multirate demodulator will not produce identical results with different block sizes, because it doesn't do this and just averages the whole block it was given; it may also behave subtly differently at different sampling rates since that effectively makes it average over a different time period)
-
look at blocks of non-signal data, skip over decoded messages. That is, when a message gets decoded or we hit the end of the calculation block, feed the data from the end of the last good message to the start of the next message (or end of block) into the noise calculation
-
perhaps look at a subset of raw data per processing block, or only every Nth block, if the calculation is expensive (on the assumption that the noise level isn't expected to change rapidly)
-
perhaps do some smoothing (EMA, something like that) of the noise value
-
do something smarter than just a mean across each block. Some ideas: a) Nth-percentile of magnitudes. Since we only have 16 bits of magnitude this can actually be done in O(n) with essentially a radix sort into 64k buckets. b) FFT of the original IQ data, sort bins by power level, take the Nth percentile. In other contexts I've found this works well for signals with sharp peaks, but I'm not sure how good it would be with ADS-B data.
I've tested with a combination of 2+3+4+5a and it seemed to work out OK
Cool!!
I'm sure you can convince Eclipse etc to treat it as C (that's what the emacs mode line does for emacs..)
Oh yeah. I had by something similar. :) demod_multi.inc does need to be added to the Makefile as a dependency though.
perhaps look at a subset of raw data per processing block, or only every Nth block, if the calculation is expensive (on the assumption that the noise level isn't expected to change rapidly)
I was actually thinking along these lines to create some sort of adaptive tuning mechanism. I.E. every "so often" run the same block through the decoder several times (not capturing and maybe in another thread) with a range of parameters and use the parameters of the best decode for the subsequent N blocks.
Just a few FYIs...
I had to change fabs to abs in tables.c and add -Wno-error=address-of-packed-member to the compile options. gcc-10 complains about alignment...
dsp/generated/../impl/magnitude_power_uc8.c:27:5: warning: converting a packed ‘uc8_t’ pointer (alignment 1) to a ‘uc8_u16_t’ pointer (alignment 2) may result in an unaligned pointer value [-Waddress-of-packed-member]
27 | const uc8_u16_t * restrict in_align = (const uc8_u16_t *) STARCH_ALIGNED(in);
| ^~~~~
I had to change fabs to abs in tables.c and add -Wno-error=address-of-packed-member to the compile options. gcc-10 complains about alignment...
Huh, I thought I already fixed those: https://github.com/flightaware/dump1090/commit/3eb2783cdf85688e7babef7b912cd02210901cfe https://github.com/flightaware/dump1090/commit/dbdf18dcc0c90b2fce178f317c40db3eb8c8c024
Yeah in the dev branch, bu they weren't cherry-picked to the pxsdr branch.
I just pushed up a branch to my fork that has everything in it. https://github.com/gtjoseph/dump1090/tree/airspy-multi-hirate-complete
It's NOT meant to be a source of pull requests but rather a consolidation of what I've done for information, testing and feedback. It has the AirSpy support plus the 3 demodulators and a bunch of options to tune the multi and hirate demods. I also took the things common to both new demodulators and pull them up into demod.c (preamble search and signal/noise reporting).
I've been running both new demods side-by-side (2 airspys connected through a splitter to the same antenna) as well as using a 10 second 12MS/s file and the ifile sdr. The results are interesting. :)
When/If you're ready, just ell me what chunks you want in each poll request and I'll create new branches with 1 commit/pull request each.
I also picked up the latest mode_s changes you made.
Great! Thanks for looking at this. I'm working through a bit of a backlog of other stuff at the moment but I should be back on demodulator work soon.
Did you have some results somewhere that I could look at?
Did you have some results somewhere that I could look at?
I'm running an automated script to test all the combinations of parameters and collecting the results into a json file. There are 2688 combinations at about 12 seconds apiece. :) Should be done sometime overnight. I'll zip and attach the results in the (GMT-7) morning.
Here are some results...
Tested on a [email protected] desktop. Input file for all runs was the same 10 seconds at 12MS/s unsigned 12-bit offset captured by airspy_rx. Contains about 13500 messages but it's hard to tell.
The attached zip file contains...
- looptester: Runs all possible combinations of demodulator and demodulator options (5040 runs) and creates a zip file for each run containing the normal json output plus the new demod.json. The zip files for each run aren't included here.
- demodtosql: Extracts the demod.json file from each run's zip file, concatenates them all into a single demod.json, creates a demod_brief.json file containing the info needed to asses demod performance, and creates an sqlite database of the results.
- demodstats: Just runs the SQL queries that produced the below results.
- demod.json: The combined demod.json from all runs.
- demod_brief.json: Just the info from demod.json needed to asses demod performance.
- demod_brief.csv: A CSV version of the above for import to the sqlite3 database.
- demod.db; The sqlite3 database with one "stats" table with the results.
| Demod | Ptdb | Sw | Pwl | Pwh | Dwl | Dwh | NML | CPU | Preambles | No Fix | 1-Bit Fix | messages |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| multi | 1 | 4 | 0 | 0 | 0 | 0 | 0 | 969 | 130477 | 11715 | 973 | 12688 |
| multi | 1 | 4 | 0 | 0 | 0 | 0 | 0 | 933 | 130477 | 11715 | 973 | 12688 |
| multi | 1 | 5 | 0 | 0 | 0 | 0 | 0 | 870 | 105965 | 11925 | 751 | 12676 |
| multi | 1 | 5 | 0 | 0 | 0 | 0 | 0 | 985 | 105965 | 11925 | 751 | 12676 |
| multi | 1 | 4 | -1 | 1 | 0 | 0 | 0 | 1045 | 149081 | 11906 | 677 | 12583 |
| multi | 1 | 4 | -1 | 1 | 0 | 0 | 0 | 1011 | 149081 | 11906 | 677 | 12583 |
| multi | 2 | 4 | 0 | 0 | 0 | 0 | 0 | 973 | 120731 | 11634 | 937 | 12571 |
| multi | 2 | 4 | 0 | 0 | 0 | 0 | 0 | 951 | 120731 | 11634 | 937 | 12571 |
| multi | 1 | 3 | 0 | 0 | 0 | 0 | 0 | 1070 | 153769 | 11510 | 1049 | 12559 |
| multi | 1 | 3 | 0 | 0 | 0 | 0 | 0 | 1061 | 153769 | 11510 | 1049 | 12559 |
| Demod | Ptdb | Sw | Pwl | Pwh | Mwl | Mwh | NML | CPU | Preambles | No Fix | 1-Bit Fix | messages |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hirate | 1 | 4 | 0 | 0 | -6 | 6 | 0 | 1520 | 117650 | 11478 | 1714 | 13192 |
| hirate | 1 | 4 | 0 | 0 | -5 | 5 | 0 | 1485 | 117651 | 11478 | 1714 | 13192 |
| hirate | 1 | 4 | 0 | 0 | -6 | 6 | 0 | 1637 | 117650 | 11478 | 1714 | 13192 |
| hirate | 1 | 4 | 0 | 0 | -5 | 5 | 0 | 1491 | 117651 | 11478 | 1714 | 13192 |
| hirate | 1 | 4 | 0 | 0 | -4 | 4 | 0 | 1354 | 117659 | 11477 | 1713 | 13190 |
| hirate | 1 | 4 | 0 | 0 | -4 | 4 | 0 | 1419 | 117659 | 11477 | 1713 | 13190 |
| hirate | 1 | 4 | 0 | 0 | -3 | 3 | 0 | 1352 | 117835 | 11470 | 1711 | 13181 |
| hirate | 1 | 4 | 0 | 0 | -3 | 3 | 0 | 1401 | 117835 | 11470 | 1711 | 13181 |
| hirate | 1 | 4 | 0 | 0 | -2 | 2 | 0 | 1212 | 118435 | 11460 | 1695 | 13155 |
| hirate | 1 | 4 | 0 | 0 | -2 | 2 | 0 | 1209 | 118435 | 11460 | 1695 | 13155 |
| Column | Option | Notes |
|---|---|---|
| Ptdb | preamble-threshold | |
| Sw | smoother-window | |
| Pwl | preamble-window-low | |
| PwH | preamble-window-high | |
| Mwl | msg-window-low | only hirate |
| Mwh | msg-window-high | only hirate |
| NML | no-marl-limits | only hirate |
| CPU | ms over 10 second run |
Example command line:
$ ./dump1090 --device-type ifile --net-bo-port 33005 --quiet --stats --wisdom [email protected] \
--ifile ../../airspy/dump109012u2.bin --sample-format u16o12 --sample-rate 12 \
--demod hirate --demod-preamble-threshold 1.0 --demod-smoother-window 4 \
--demod-preamble-window -3:3 --demod-msg-window -5:5 --fix --demod-no-mark-limits
@mutability Had a chance to look at any of this stuff yet?
Not yet, sorry :/ Quite a lot of balls in the air at the moment.
@mutability Any update?
Hi! Unfortunately I've got a lot of other work going on at the moment and it'll probably be at least a month before I can get back to looking at this.
@mutability Is there any hope at all here? Would you be OK with me creating a fork with the demod and airspy stuff and would you be OK with announcing it in the forums?
Oh hey I don't want to slow you down with this - if you've got stuff you'd like to release yourself, absolutely go for it!
I'd definitely like to get this integrated in some form eventually, but higher priority stuff keeps popping up, sorry :(
We need a high-rate demodulator for some new hardware support, but that has been somewhat delayed by a pandemic + a global semiconductor shortage; once it bubbles back to the top I'll be working on this again.