Airspy ADS-B decoder

It’s sensitive specifically to message loss, because all the timing relies on seeing samples at a fixed rate; if any data is dropped then that looks like the clock jumped. It is very sensitive and there’s not really any flexibility there - when a jump like this happens the mlat server has to resynchronize the receiver all over again. Keep in mind that dropping only one sample is effectively about a 100 metre error for mlat, and more typically it’ll drop anywhere between 64 and 64k samples at a go..

AFAIK there’s no mechanism in the rtlsdr hardware to do retransmission of any data that gets lost on the USB bus (so it’s sensitive to bus noise, bad cables etc), and I’d guess that there’s very limited send-side buffers so if the USB bus is monopolized by another device for more than a short time then data will get dropped that way too.

Oh and if you want to add the throttling info to the cpu graph:

########################################################################
# Extract CPU information
#  Page: 1
#  Information               Status     Statistics
#  - cpu frequency           - yes      - no
#  - cpu voltage             - yes      - no
#  - cpu load 1, 5, 15       - yes      - yes
#  - cpu scaling governor    - yes      - no
########################################################################
dynamic.1.name=cpu_frequency
dynamic.1.source=/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
dynamic.1.regexp=(.*)
dynamic.1.postprocess=$1/1000
dynamic.1.rrd=

dynamic.2.name=cpu_voltage
dynamic.2.source=vcgencmd measure_volts core
dynamic.2.regexp=(\d+.\d+)V
dynamic.2.postprocess=
dynamic.2.rrd=

dynamic.3.name=load1,load5,load15
dynamic.3.source=/proc/loadavg
dynamic.3.regexp=^(\S+)\s(\S+)\s(\S+)
dynamic.3.postprocess=
dynamic.3.rrd=GAUGE

dynamic.4.name=scaling_governor
dynamic.4.source=/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
dynamic.4.regexp=(.*)
dynamic.4.postprocess=
dynamic.4.rrd=

dynamic.26.name=undervolted
dynamic.26.source=vcgencmd get_throttled
dynamic.26.regexp=throttled=(.*)
dynamic.26.postprocess=$1&0x1
dynamic.26.rrd=

dynamic.27.name=capped
dynamic.27.source=vcgencmd get_throttled
dynamic.27.regexp=throttled=(.*)
dynamic.27.postprocess=$1&0x2
dynamic.27.rrd=

dynamic.28.name=throttled
dynamic.28.source=vcgencmd get_throttled
dynamic.28.regexp=throttled=(.*)
dynamic.28.postprocess=$1&0x4
dynamic.28.rrd=

dynamic.29.name=hasundervolted
dynamic.29.source=vcgencmd get_throttled
dynamic.29.regexp=throttled=(.*)
dynamic.29.postprocess=$1&0x10000
dynamic.29.rrd=

dynamic.30.name=hascapped
dynamic.30.source=vcgencmd get_throttled
dynamic.30.regexp=throttled=(.*)
dynamic.30.postprocess=$1&0x20000
dynamic.30.rrd=

dynamic.31.name=hasthrottled
dynamic.31.source=vcgencmd get_throttled
dynamic.31.regexp=throttled=(.*)
dynamic.31.postprocess=$1&0x40000
dynamic.31.rrd=

static.9.name=max_proc
static.9.source=nproc
static.9.regexp=(.*)
static.9.postprocess=$1 + 1

web.status.1.content.1.name=CPU
web.status.1.content.1.icon=cpu.png
#web.status.1.content.1.line.1="Loads: <b>" + data.load1 + "</b> [1min] - <b>" + data.load5 + "</b> [5min] - <b>" + data.load15 + "</b> [15min]"
web.status.1.content.1.line.1=JustGageBar("Load", "1min", 0, data.load1, data.max_proc, 100, 80)+" "+JustGageBar("Load", "5min", 0, data.load5, data.max_proc, 100, 80)+" "+JustGageBar("Load", "15min", 0, data.load15, data.max_proc, 100, 80)
web.status.1.content.1.line.2="CPU frequency: <b>" + data.cpu_frequency + "MHz</b> Voltage: <b>" + data.cpu_voltage + "V</b>"
web.status.1.content.1.line.3="Scaling governor: <b>" + data.scaling_governor + "</b>"
web.status.1.content.1.line.4="<table class='table'><thead><tr><th>Power</th><th>Current Status</th><th>Previous Status</tr></thead><tbody>"
web.status.1.content.1.line.5="<tr>"
web.status.1.content.1.line.6="<td>Under Voltage:</td><td>" + Label(data.undervolted,"==0","no","success") + Label(data.undervolted,"!=0","yes","danger")+ "</td><td>" + Label(data.hasundervolted,"==0","no","success") + Label(data.hasundervolted,"!=0","yes","danger")+ "</td>"
web.status.1.content.1.line.7="</tr>"
web.status.1.content.1.line.8="<tr>"
web.status.1.content.1.line.9="<td>Throttled:</td><td>" + Label(data.throttled,"==0","no","success") + Label(data.throttled,"!=0","yes","danger")+ "</td><td>" + Label(data.hasthrottled,"==0","no","success") + Label(data.hasthrottled,"!=0","yes","danger")+ "</td>"
web.status.1.content.1.line.10="</tr>"
web.status.1.content.1.line.11="<tr>"
web.status.1.content.1.line.12="<td>Frequency Capped:</td><td>" + Label(data.capped,"==0","no","success") + Label(data.capped,"!=0","yes","danger")+ "</td><td>" + Label(data.hascapped,"==0","no","success") + Label(data.hascapped,"!=0","yes","danger")+ "</td>"
web.status.1.content.1.line.13="</tr>"
web.status.1.content.1.line.14="</tbody></table>"
#web.status.1.content.1.line.4=InsertHTML("/addons/top3/top3.html")

web.statistics.1.content.1.name=CPU Loads
web.statistics.1.content.1.graph.1=load1
web.statistics.1.content.1.graph.2=load5
web.statistics.1.content.1.graph.3=load15
web.statistics.1.content.1.ds_graph_options.load1.label=Load 1min
web.statistics.1.content.1.ds_graph_options.load5.label=Load 5min
web.statistics.1.content.1.ds_graph_options.load15.label=Load 15min
1 Like

That’s awesome!..

Along the USB lines, I agree that the bus seems to be shared,
When I added a dongle for UAT978 to my RPI4 I lost some airspy traffic. I think I removed bit packing for some reason at the same time. I just re-enabled bit packing and the airspy is back to 1800 msg/sec(from 1600msg/sec).

My UAT messages are also up. They fluctuate so much and there hasn’t been enough time to see if this is real or not.

I did a similar test on an Odroid XU4 (I assume it will be similar in the N2). It looks like there are two buses (one of the front and one on the back).
I just pluged three different USB devices into the ports.
The U-Blox AG is a cheap USB dongle.

jonha@odroid:~$ lsusb
Bus 006 Device 002: ID 0bda:8153 Realtek Semiconductor Corp. RTL8153 Gigabit Ethernet Adapter
Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 002: ID 05e3:0616 Genesys Logic, Inc. hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
**Bus 003 Device 006: ID 1d50:60a1 OpenMoko, Inc. Airspy**
**Bus 003 Device 007: ID 1546:01a7 U-Blox AG [u-blox 7]**
Bus 003 Device 002: ID 05e3:0610 Genesys Logic, Inc. 4-port hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
**Bus 001 Device 003: ID 0bda:2832 Realtek Semiconductor Corp. RTL2832U DVB-T**
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
jonha@odroid:~$ lsusb -t
/:  Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
    |__ Port 1: Dev 2, If 0, Class=Vendor Specific Class, Driver=r8152, 5000M
/:  Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 5000M
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 480M
        **|__ Port 1: Dev 7, If 0, Class=Communications, Driver=cdc_acm, 12M**
**        |__ Port 1: Dev 7, If 1, Class=CDC Data, Driver=cdc_acm, 12M**
        **|__ Port 2: Dev 6, If 0, Class=Vendor Specific Class, Driver=usbfs, 480M**
Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p, 12M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=exynos-ehci/3p, 480M
    **|__ Port 1: Dev 3, If 0, Class=Vendor Specific Class, Driver=usbfs, 480M**
jonha@odroid:~$

Use dump978-fa on the the Mac Mini, it’s open source so you can compile it on there.

Have you tried running the Aispy as the only USB device with the RPi4 since then?

@mikkyo - It’s a beautiful thing, thanks again!

Just so this isn’t a complete hijack: addition for airspy info:

dynamic.13.name=airspy
dynamic.13.source=service airspy_adsb status
dynamic.13.regexp=Active: (.*) \(
...
static.11.name=airspyver
static.11.source=/usr/local/bin/airspy_adsb -h 2>&1 | grep "airspy_adsb" | awk '{print $2}'
static.11.regexp=(.*)
...
web.status.1.content.1.line.38="<td><a href='https://airspy.com' target=_blank>airspy_adsb</a></td><td>" + Label(data.airspy,"=='active'","active","success") + Label(data.airspy,"!='active'","inactive","danger") + "</td><td>" + data.airspyver + "</td><td><a href='http://127.0.0.1/al/' target=_blank>Dump1090-fa/al/</a></td>"
web.status.1.content.1.line.39="</tr>"

I currently have it linked to Al’s overlay, but that can be changed to suit needs.

Back on track, total change of subject:
@prog - Is decimation a thing of the past in airspy_adsb?

1 Like

It’s no longer used with the new algo (since a year or so).

1 Like

Thanks for it !
On my Pi4 for the version number to work, I had to remove the \ before $2 on this line :

static.11.source=/usr/local/bin/airspy_adsb -h 2>&1 | grep "airspy_adsb" | awk '{print \$2}'

But status keep always inactive in red color. Do you have an idea ?

Thanks.

Looking more closely at the avionics.conf, it seems that it misses the part “dynamic” in the code that you gave, can you tell me what you put as value in your conf file ?

Thanks !

Ooops! I forgot to tear that escape out. I have that as part of my script inside a tee function and strings need to be escaped or they disappear. Be sure to double-check the absolute path on your airspy_adsb install (yours is fine as it picked up the version). AND I forgot the dynamic code like a dumdum. I fixed it in the above post so it doesn’t catch anyone else. Thx for the head’s-up!

1 Like

Thanks it works perfectly now !

Sans-titre-1

Loaded the new version and my stats are up quite nicely.
Keeping me ahead of the other local feeders, where we were usually neck and neck.

2 Likes

Anyone considered this SBC?
https://www.friendlyarm.com/index.php?route=product/product&path=69&product_id=266

That’s cute but kind of… underpowered.
I already have a H5 based Orange Pi that wasn’t much more expensive. Money spent for nothing, now I that know that I need more processing power :roll_eyes:
On the other hand their M4 looks tempting with RK3399 at $50…
https://www.friendlyarm.com/index.php?route=product/product&product_id=234

There are those and also a v2 of the SBC pasted above. RockPi also makes an RK3399 based board. I’ve had both on the radar, but have been held back by distro support - there’s always that when looking to get these things. Have been stung before. The RK3399 does look really good I’m pretty sure I seen something on the RockPi where they have separate USB hubs. Orange Pi now as well evidently, so they are gaining traction, which could be great for distro support, but it still seems somewhat sketchy even a year after their release. Best bet when looking for pure performance is to find and old NUC - will cost the same in the end and run circles around these SBC’s.

EDIT: Just found this: RK3399 SBC Showdown! 6 Single Board Computers Tested Rk3399 VS RK 3399 - YouTube

What is really important is the way the USB controller is wired to the system bus. If done right, this small SBC can work just fine as a dedicated receiver. The processing power seems sufficient for the task, but I don’t know about the I/Os.

I agree with this guy. I have two Intel Atom based UP-Board SBC’s and they just outperform every ARM SBC I have tried so far, but they are overkill for ADSB.

Please check the updated airspy_adsb decoder version 1.41.
A higher CPU usage is to be expected, but also more decodes for 20 and 24 MHz modes.
Let me know how it works for you.

2 Likes

Airspy_Mini, v1.41 @ 20 Mhz, no applicable change - may not be focused on the Mini @ 20 Mhz however:

Shot from Airspy rig:

Shot from Mirror rig, but RTL as waterline:

At least it gives side-by-side perspective. 15:11 is when the switch was made on the Airspy rig. Very little CPU gain as well, perhaps 2%

Just installed v1.41, difficult to judge after a few minutes with traffic going down but CPU usage is somewhat up.
airspy1_41