Autogenerated from https://www.improwis.com/projects/sw_si4703-RDS/
si4703 RDS dumper
Why
RDS
packet structure
groups
details
How
hardware
gotcha
antenna
woes
software
hardware configuration
noninteractive modes
interactive mode
Files
Todo
Because it is there.
The Radio Data System is a packet based digital data transmission over FM radio.
The low-level transfer is done by modulating the data on a 57kHz subcarrier, Manchester-encoded, 1187.5 bit/s, in 104-bit group. The group consists of four pairs of 16 and 10 bits, where the latter is a checksum and data-recovery portion. Only recovered data (and two-bit error-recovery status for each word) are available from the Si4703 chip. Raw data can be acquired with software-defined radio, eg. by the GNU Radio module https://github.com/bastibl/gr-rds/.
The data are sent as fixed-size packets of four 16-bit words (A,B,C,D). The "header" is fixed, the variable payload consists of 37 bits (5 bits in word B, and 16 each in words C and D).
The header contains inter alia the packet group ID, the type of the subprotocol used. There are 32 possible groups (16, each with variant A and B). Some are fixed, others can be assigned to specific application.
The groups are well-documented here: http://www.g.laroche.free.fr/english/rds/groupes/listeGroupesRDS.htm
The 5 bits in word B are often used as a packet subvariant, or a pointer to text buffer, and/or various flags. Or they can be used as part of the whole payload.
The signal is received on a 57kHz subcarrier (3x the pilot 19kHz), as four block of 16 bits of data plus 10 bits of corrections.
The four blocks, A-B-C-D, are the elementary packets of the protocol, with header and payload. The payload is specific to a group type, a sub-protocol specified in the header.
The header consists of 16+11 bits.
- block A, 16 bits
- A[15..0] - PI, program identifier
- A[15..12] - country identifier, overloaded, no two neighbouring countries share a country ID
- A[11..8] - coverage area, usually static, can be dynamically changed by some stations
- A[7..0] - program reference number, arbitrary assignment
- block B, 16 bits
- B[15..5] - group type, program type, flags
- B[15..12] - group type, 0..15
- B[11] - B0, group subtype, A/B
- B[10] - TP - Traffic Program, 1 if station contains periodic traffic reports
- B[9..5] - PTY - program type, in a 5-bit lookup table
- B[4..0] - VARY - payload, often flags and index bits
- block C, 16 bits
- payload, group dependent; in some group subtypes B it contains repeated block A, the PI
- block D, 16 bits
- payload, group dependent
Common fixed groups are:
- 0A - 8-byte station name and its alternative frequencies; station name sent by 2 bytes per packet
- 2A - Radiotext, 64-byte freeform text, sent by 4 bytes per packet
- 3A - ODA (Open Data Applications), arbitrary services and their group assignments; mapping the 16-bit ODAAID identifier to a 5-bit group ID (effectively 4-bit as B subgroup is rarely used)
- 4A - clock, time/date sent once per minute
- 8A - TMC (Traffic message channel), usually also in conjunction with 3A
- 10A - PTYN (program type name), a 8-byte ASCII-encoded program type (music, sport...) instead of type by enumeration from a list
- 14A - EON, Enhanced other networks, eg. presence of traffic announcement on other stations
Less common fixed groups are:
- 0B - station name without alternative frequencies; rarely used
- 1A - program item number, slow label
- 1B - program item number
- 2B - Radiotext, 2x 32-byte freeform text, rarely used
- 14B - EON, Enhanced other networks, eg. presence of traffic announcement on other stations; rarely used
- 15B - fast switching, essentially blocks A and B repeated in blocks C and D, for faster acquisition of data; rarely used
Groups that can be used for specific applications or as ODA are:
- 5A, 5B - transparent data channels
- 6A, 6B - in-house applications
- 7A - radio data paging
- 8A - TMC
- 9A - EWS (Emergency Warning System)
- 13A - Enhanced Radio Paging
The other groups (7B, 8B, 9B, 10A, 10B, 11A, 11B, 12A, 12B) can be assigned as ODA, Open Data Application. The application and associated group are specified in the 3A group packets. The application is specified by ODAAID, ODA application identifier. These are assigned centrally. E.g. the TMC data are sent as AID=0xCD46 (and group 8A), and RT+ (Radiotext+) tags as AID=0x4BD7.
The online documentation is often lacking, the official specs are heavily paywalled. Other people's source code can be a substitute. A good parser is in the v4l-ctl utils, https://github.com/gjasny/v4l-utils/blob/master/lib/libv4l2rds/libv4l2rds.c
A module with Si4703 chip by Silicon Laboratories was obtained. Cheap one, with older Si4703-B16 flavor (variant B, firmware version 16); more modern one is Si4703-C19.
There are many other Si47xx receivers. One of the best is Si4743, able to handle not just VHF FM (64-108 MHz) but also LW (153-288 kHz), MW (520-1710 kHz) and SW (2.3-30 MHz), and WB, the NOAA weather band (162.4-162.55 MHz)
The chip was attached to a Raspberry Pi via I2C and a pair of GPIO. One for RESET signal, the optional other for interrupt from the chip.
The interrupt wire is optional. As-is, it is used only for the tuning operations; the RDS reception is done by I2C polling. Which is grossly suboptimal but works.
The module uses headphones as an antenna. External antenna of better quality can be attached. The antenna is a major performance factor.
The chip has to be initialized to 2-wire mode (aka I2C).
The chip can run either in 3-wire (SPI) or 2-wire (I2C/TWI) mode. If it is not seen on the I2C bus, it is in the wrong mode.
As-connected, the chip does not appear on the I2C bus. It is necessary to pulse low the RESET pin, while holding the SDIO (I2C SDA) pin low. Then it appears on i2c-detect at address 0x10.
The "internal crystal oscillator" in the datasheet is only the support circuitry, the crystal is external. It is possible to get rid of it by replacing the crystal with an oscillator. The crystal uses two pins, GPIO3 and RCLK, both available on the crystal solder pads. In theory, after removal of the xtal and pulling GPIO3 up to 3.3v, the init dance of mode1 can be replaced with much easier mode2 init without fiddling with SDIO. This may be needed when using an I2C-to-USB interface, or other way where we do not have bitbang-class access to SDIO. (A diode to some random GPIO on-hand, to pull down the line, may be a solution. This will however interfere with existing bus traffic, if it is shared with other processes.)
Using the internal oscillator, the chip is sensitive to spurious signals from the SDIO line during seeking/tuning. This may impair performance when the bus is shared.
If the application (research?) requires extra luxurious frequency stability, a 32.768kHz TCXO can be used.
The FM antenna is connected to the FMI input of the chip.
It's just around 100 MHz, that's almost DC.
The antenna guidelines are described in the AN383 appnote.
The on-chip tuning VCO runs at high frequency and its harmonics at gigahertz range are subject to leakage to chip's pins and cause various parasitic emissions from there. Various optional RC or LC filters can be applied. Including the antenna connection filter, using a 6pF capacitor between FMI and ground, and a ferrite bead (Murata BLM15GA750SN1, or anything with low DC resistance and high resistance at around 100 MHz) between FMI and antenna.
The FM wavelength is about 3.4m (88 MHz) to 2.8m (108 MHz), requiring 1.7-1.4m for half-wave and 0.85-0.7m for quarter-wave. Headphones are often used as the antenna, due to their cable's approximately correct length.
On the module, the ground wire of the headphones (from the onboard connector) is connected to the FMI pin, via a L-C filter (capacitor to the FMI pin to pass the high frequency, inductor to ground to stop the high frequency but allow the return current from the audio to go through).
ESD diodes, with parasitic capacitance below 1 pF, may be a good idea. The antenna will be exposed to all sorts of interference, including direct discharges when touched.
It should be easy to break it out to a SMA connector or even just a header pin. Remove the capacitor (or use it to bypass the new antenna connector), and optionally short the inductor. Or use a pair of header pins to select between the headphones and a real antenna.
The module itself has a tendency to insensitivity after initialization. Multiple inits with different antenna positions may be necessary. Possibility for manual deinit and init was added to the interactive user interface to mitigate the annoyance.
Python was chosen as the platform, for simplicity and ease. The si4703RaspberryPi project was chosen as the basis. Then it grew.
The software can run even without the chip, but only for the parsing of rds-spy logs coming from stdin.
in main code source file (TODO: arguments and/or config file)
The chip-interacting code is hardware-dependent, due to the reset requiring pulsing the GPIO for the RESET pin. The hardware reset is segregated to a routine selectable by the "hw" parameter in the radio object creation. Currently supported are "raspi" for raspberry pi, and "none" for skipping the hardware init.
However, parsing of the stdin-input .spy files does not require any hardware initialization and should therefore run on any machine.
si4703 FM radio RDS data handler
Usage: ./si4703rds.py [command] [arguments...]
Where:
info print expected hardware configuration
-n do not access hardware
-i force hardware init
-v verbose init (with -i)
scan perform scan of radio stations, list names and RDS groups encountered
-i force hardware init
dump connect to chip, dump raw data to stdout in rds-spy log format
-n skip attempt to get station name from RDS
parse read rds-spy raw data from stdin, parse, output to stdout
-n do not print parsed data (use with -s, -t)
-s print RDS statistics
-t print RDS-TMC data
-v some extra verbosity/debug data somewhere
cmd <cmd> command for the chip (volume up/down, seek up/down)
-h list of commands
-i force init
help print help (also -h, --help)
-i print interactive commands help instead of commandline
<none> enter interactive mode
-i force hardware init
The software can dump and and analyze RDS datastream in RDS-Spy format.
To dump data from a station:
- run the interactive console, tune the radio, exit with shift-Q
- dump the data: si4703rds dump >> file.spy
<recorder="Si4703-shad" date="2023-11-27" time="19-00-06" source="1" name="COUNTRY " location="" notes="89.5 MHz">
2337 2725 6E65 2072 @2023/11/27 18:00:06.95
2337 A720 2020 2020 @2023/11/27 18:00:07.04
2337 0729 0250 594D @2023/11/27 18:00:07.13
2337 2726 6168 696F @2023/11/27 18:00:07.22
2337 A721 2022 2020 @2023/11/27 18:00:07.30
2337 072A DF8F 5452 @2023/11/27 18:00:07.39
2337 2727 2064 6F20 @2023/11/27 18:00:07.48
2337 A730 2020 2020 @2023/11/27 18:00:07.56
6337 512F BBCD 5920 @2023/11/27 18:00:07.65
2337 2728 6E65 6B6C @2023/11/27 18:00:07.74
2337 A731 2020 0323 @2023/11/27 18:00:07.83
2337 0728 E614 434F @2023/11/27 18:00:07.91
2337 2729 6964 6E65 @2023/11/27 18:00:08.01
2337 A720 2020 2020 @2023/11/27 18:00:08.09
...
To analyze a rds-spy format dump, send it to stdin of the program: cat file.spy | si4703rds parse
It is possible to simultaneously dump and analyze the RDS data: si4703rds dump | tee -a file.spy | si4703rds parse
A number of RDS-Spy logs from different countries can be found at https://github.com/walczakp/rds-spy-logs.
The dump can be also easily shared through eg. MQTT, for remote decoding: si4703rds dump | mosquitto_pub -t "RDS"mosquitto_sub -t "RDS" | si4703rds parse
Keyboard keypress controls:
===========================
<space> pause/resume output
- + volume
[ ] prev/next station
? help
f filter RDS, hide 0A and 2A "spam"
h hide/show fixed header
g toggle 2A radiotext string vs group stats
s show RDS string buffers
t show RDS-TMC traffic data log
S stations scan
i reset/initialize chip
I powerdown chip
r show chip registers
q quit, switch off radio
Q quit, keep radio running
status line format:
freq RSSI "station" state current-group seen-groups "radiotext"/stats [<paused/filtered>]
state can be P for paused, F for filtering, R flashing when group was received
Filters: [[], ['0A', '2A'], ['=2A'], ['=3A'], ['=8A']]
Example output:
92.6 9 0000 2424:0443:c5a1:2020 PIC=2424 TP=1 PTY=2 VARY=03 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=3 "R-PLUS " [b' '] Dx=0000 AF=107.2 AF=103.6
92.6 9 0000 2424:8446:cb29:11b7 PIC=2424 TP=1 PTY=2 VARY=06 GTYPE=8A:TMC 06:cb29:11b7 userMsg multi 1st contIdx=6 diversion=1 dir=1 scale=1 event=809 loc=11b7
92.6 9 0000 2424:0440:2885:522d PIC=2424 TP=1 PTY=2 VARY=00 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=0 "R-PLUS " [b'R-'] Dx=0000 AF=091.5 AF=100.8
92.6 9 0000 2424:244b:736b:6120 PIC=2424 TP=1 PTY=2 VARY=0b GTYPE=2A:radioText 11 [ska ] "Pro a proti - Nejvetsi protest v historii Ceska ____d pondeln..."
92.6 9 0000 2424:0441:428c:504c PIC=2424 TP=1 PTY=2 VARY=01 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=1 "R-PLUS " [b'PL'] Dx=0000 AF=094.1 AF=101.5
92.6 9 3103 241f:3450:4080:cd46 bad blocks, skipping
92.6 9 3100 9027:8446:cb29:11b7 bad blocks, skipping
92.6 9 0000 2424:0442:673c:5553 PIC=2424 TP=1 PTY=2 VARY=02 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=2 "R-PLUS " [b'US'] Dx=0000 AF=097.8 AF=093.5
92.6 9 0000 2424:244c:7369:206f PIC=2424 TP=1 PTY=2 VARY=0c GTYPE=2A:radioText 12 [si o] "Pro a proti - Nejvetsi protest v historii Ceska si od pondeln..."
92.6 9 0000 2424:0443:4035:2020 PIC=2424 TP=1 PTY=2 VARY=03 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=3 "R-PLUS " [b' '] Dx=0000 AF=093.9 AF=092.8
92.6 10 0000 2424:8446:61a2:ac00 PIC=2424 TP=1 PTY=2 VARY=06 GTYPE=8A:TMC 06:61a2:ac00 userMsg multi 2ndGrp=1 grpOrder=2 data=1a2ac00
92.6 9 0000 2424:0440:ef33:522d PIC=2424 TP=1 PTY=2 VARY=00 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=0 "R-PLUS " [b'R-'] Dx=0000 AF=[follow:15] AF=092.6
92.6 10 0000 2424:244d:6420:706f PIC=2424 TP=1 PTY=2 VARY=0d GTYPE=2A:radioText 13 [d po] "Pro a proti - Nejvetsi protest v historii Ceska si od pondeln..."
92.6 10 0000 2424:8446:61a2:ac00 PIC=2424 TP=1 PTY=2 VARY=06 GTYPE=8A:TMC 06:61a2:ac00 userMsg multi 2ndGrp=1 grpOrder=2 data=1a2ac00
92.6 10 0000 2424:0441:3a4f:504c PIC=2424 TP=1 PTY=2 VARY=01 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=1 "R-PLUS " [b'PL'] Dx=0000 AF=093.3 AF=095.4
92.6 10 0001 2424:3450:0647:cd46 PIC=2424 TP=1 PTY=2 VARY=10 GTYPE=3A:openDataAppId 10:0647:cd46 grp=8A msg=0647 appId=cd46(TMC ALERT-C) varcode=0 loctable=0019 altfreq=0 transmode=0 internat=0 national=1 regional=1 urban=1
92.6 10 0000 2424:0442:9026:5553 PIC=2424 TP=1 PTY=2 VARY=02 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=2 "R-PLUS " [b'US'] Dx=0000 AF=101.9 AF=091.3
92.6 9 0000 2424:244e:6e64:656c PIC=2424 TP=1 PTY=2 VARY=0e GTYPE=2A:radioText 14 [ndel] "Pro a proti - Nejvetsi protest v historii Ceska si od pondeln..."
92.6 10 0310 2424:044c:49ad:2020 bad blocks, skipping
92.6 9 0030 2424:8446:1c45:0158 bad blocks, skipping
92.6 9 0000 2424:0440:2885:522d PIC=2424 TP=1 PTY=2 VARY=00 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=0 "R-PLUS " [b'R-'] Dx=0000 AF=091.5 AF=100.8
92.6 9 0000 2424:244f:6e2e:2e2e PIC=2424 TP=1 PTY=2 VARY=0f GTYPE=2A:radioText 15 [n...] "Pro a proti - Nejvetsi protest v historii Ceska si od pondeln..."
92.6 9 0000 2424:8446:1025:0158 PIC=2424 TP=1 PTY=2 VARY=06 GTYPE=8A:TMC 06:1025:0158 userMsg multi 2ndGrp=0 grpOrder=1 data=0250158
92.6 9 0000 2424:0441:428c:504c PIC=2424 TP=1 PTY=2 VARY=01 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=1 "R-PLUS " [b'PL'] Dx=0000 AF=094.1 AF=101.5
92.6 10 0010 2424:0442:673c:5553 PIC=2424 TP=1 PTY=2 VARY=02 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=2 "R-PLUS " [b'US'] Dx=0000 AF=097.8 AF=093.5
92.6 9 0000 2424:2440:5072:6f20 PIC=2424 TP=1 PTY=2 VARY=00 GTYPE=2A:radioText 00 [Pro ] "Pro a proti - Nejvetsi protest v historii Ceska si od pondeln..."
92.6 10 0000 2424:0443:4035:2020 PIC=2424 TP=1 PTY=2 VARY=03 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=3 "R-PLUS " [b' '] Dx=0000 AF=093.9 AF=092.8
92.6 9 0000 2424:8446:0000:0000 PIC=2424 TP=1 PTY=2 VARY=06 GTYPE=8A:TMC 06:0000:0000 userMsg multi 2ndGrp=0 grpOrder=0 data=0000000
92.6 9 0000 2424:0440:ef33:522d PIC=2424 TP=1 PTY=2 VARY=00 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=0 "R-PLUS " [b'R-'] Dx=0000 AF=[follow:15] AF=092.6
92.6 8 "R-PLUS " R 8A 0123488^ "Pro a proti - Nejvetsi protest vp@istorii Ceska si od pondeln..."
The event lines are as follows:
92.6 10 0010 2424:0442:673c:5553 PIC=2424 TP=1 PTY=2 VARY=02 GTYPE=0A:basicTuning TA=0 MS=0 DI=0 C=2 "R-PLUS " [b'US'] Dx=0000 AF=097.8 AF=093.5
freq | | | | | |
RSSI, signal strength | | |
data recovery flags (0=received ok, 1=1-2 errors, 2=3-5 errors, 3=uncorrectable (>5 errors or error in checkword
raw data, A:B:C:D | | |
fixed header data from A:B | |
group type, name if known
group-specific data, if format known and decoder implemented
The status line at bottom is as follows:
92.6 8 "R-PLUS " R 8A 0123488^ "Pro a proti - Nejvetsi protest vp@istorii Ceska si od pondeln..." <paused>
freq | | | | | | |
RSSI| | | | | |
8-byte station name from group 0A |
P=paused, F=filtered, R=RDS packet received |
most recent RDS group received |
list of groups seen, hex, lowercase=variant-A, uppercase or with ^ suffix=variant B, shows misreceived group 8B
radiotext from group 2A/2B |
paused/filtered (with filter designation), or none when running
Strings and statistics (key "S"):
0A "COUNTRY "
0Ab "0001"
2 "GLEN CAMPBELL - OL NORWOODS COMING HOME "
PTYN " "
TMCID "________"
clock 2118-12-10 04:13
stat: [-- 289x 7.2%] [0A 1227x 33.1%] [2A 1242x 33.5%] [4A 2x 0.1%] [10A 1235x 33.3%]
stat: suspected bad: [3A 1x 0.0%] [11B 1x 0.0%]
ODA:
stats from poorly received station, with show of corrupted data fields
0A "R-PLUS "
0Ab "0000"
2 "Cesk____zhlas Plus - politika-spolecnost-byznys-veda ____ "
PTYN b(b'____a\xb6@@')
TMCID "DIC ____"
clock 2169-7-7 22:17
stat: [-- 3046x 95.1%] [0A 69x 43.7%] [2A 37x 23.4%] [3A 15x 9.5%] [4A 2x 1.3%] [8A 29x 18.4%]
stat: suspected bad: [1A 1x 0.6%] [2B 1x 0.6%] [9A 1x 0.6%] [10A 1x 0.6%] [12A 2x 1.3%]
ODA: [8A 0xCD46(TMC) 7x]
another stats block, from a highly noisy source, shows spurious ODA data
0A "COUNTRY "
0Ab "0001"
2 "ZALM!~ A SPOL - HO HO WATANAY &# "
PTYN "@8 "
TMCID "________"
clock 1959-11-29 20:17
stat: [-- 8588x 46.7%] [0A 3295x 33.6%] [2A 3276x 33.5%] [4A 2x 0.0%] [10A 3157x 32.2%]
stat: suspected bad: [0B 1x 0.0%] [1A 4x 0.0%] [2B 2x 0.0%] [3A 10x 0.1%] [6A 13x 0.1%] [8A 5x 0.1%] [9A 6x 0.1%] [11A 4x 0.0%] [11B 1x 0.0%] [12A 9x 0.1%] [14A 7x 0.1%] [15A 1x 0.0%]
ODA: [8A 0x434F 1x] [11B 0x5920 1x] [9A 0x5452 1x] [8B 0x554E 1x]
- 0A = station name from group 0A
- 0Ab = D bits from group 0A
- PTYN = program type/name, from group 10A
- TMCID = TMC identification string, from group 8A
- clock = clock from group 4 (shown miscalculated clock from corrupted data)
- stat = statistic of groups; -- for rejected packet (shows horribly weak signal), group:count,percentage (shows lots of misreceived groups, the sub-percent ones are misread)
- rejected packet percenteage is from packets total, other percentage is from nonrejected
- suspected bad are packets with less than 2% prevalence, except group 4A which is only once per minute
- ODA = list of open-data groups assigned from group 3A, [group number(name) count]
- ODA list is populated only from packets received without error correction; on weaker stations this may take time
Filters can be applied to the realtime output; f key cycles through the presets which are possible to edit in the main program file, or switch off with F. Preset filters are:
- none - show everything
- 0A, 2A - hide the most common "spam"
- =2A - show only the radiotext, good to get a feel for the packet-based string transfer
- =3A - show only the ODA declarations
- =8A - show only the TMC data
Example scan output:
scan start
freq rssi name badgrp seen RDS group counts
STATION: 88.2 12 [EVROPA 2] --:1 0A:38 1A:3 2A:18
STATION: 89.5 12 [COUNTRY ] --:0 0A:20 2A:20 10A:20
STATION: 90.3 12 [EXPRESFM] --:10 0A:45 2A:5
STATION: 92.6 9 [R-PLUS ] --:36 0A:12 2A:6 3A:1 8A:4 ODA:8A:1:0xCD46(TMC)
STATION: 93.7 4 [HITRADIO] --:0 0A:36 2A:18 3A:3 11A:2 ODA:11A:3:0x4BD7(RT+)
STATION: 94.1 9 [ FAJN ] --:27 0A:22 2A:8 3A:1 11A:1 ODA:11A:1:0x4BD7(RT+)
STATION: 94.6 3 [R-ZURNAL] --:0 0A:30 1A:5 2A:7 3A:4 8A:11 ODA:8A:4:0xCD46(TMC)
STATION: 95.3 15 [ BEAT ] --:0 0A:20 2A:20 10A:19
STATION: 95.7 13 [ SIGNAL ] --:1 0A:29 2A:30
STATION: 96.6 15 [ IMPULS ] --:16 0A:25 2A:19
STATION: 98.7 10 [CLASSIC ] --:6 0A:46 2A:6
STATION: 102.5 9 [RADIO F1] --:0 0A:38 1A:4 2A:18
STATION: 105.0 3 [R-VLTAVA] --:0 0A:40 2A:10 14A:10
scan end
- si4703rds.zip - all files
- si4703rds.py - main code
- _libsi4703.py - chip library
- _rdslists.py - lists/dicts of RDS-related data
- !!! solve the post-initialization sensitivity issues (how???)
- option for non-Europe band settings
- more hardware options (eg. for USB-I2C dongles)
- dump to RFtap protocol, for wireshark and other tools
- segregate hardware-specific code - interrupts, GPIOs... - to separate code module
- commandline options for hardware config
- commandline options for individual commands for the chip
- TMC event codes, support for TMC location codes
- alt-frequencies list
- get a si4743 chip, try multiband radio
- MQTT, for remote control/status/messages
- for areas with EWS, consider a module monitoring the data stream, sending to home automation; can be tested with 8A/TMC traffic