📡
RDS AI Predictor
Technical Documentation
Application: TEF Logger App
Version: v6.0
Author: Highpoint
Date: May 2026
v6.0 Android
Table of Contents
1What is RDS?3
2Getting Started & UI Indicators4
3Why an AI Predictor?5
4Architecture Overview6
5Core Algorithms7
5.1Character-Level Voting Engine7
5.2Hardware Lag Filter (200ms Window)8
5.3FMDX.org Reference Database9
5.4Garbage Protection Filter10
5.5Snap-Lock Stability Engine11
5.6Dynamic/Scrolling PS Detection12
5.7Bigram Statistical Correction13
5.8Reverse-Lookup (Text-to-PI) with AF Validation14
5.9Forward-Lookup (PI-to-Text) with AF Validation15
5.10Local Learning & Persistence16
5.11Anti-Hallucination (Scatter Mode) v6.017
5.12Local Truth Override (FMDX Bypass) v6.018
6Integration with Main UI19
6.1UDP Packet Processing Flow19
6.2UI Color Coding System20
6.3Frequency Change Handling21
7Troubleshooting & FAQ22
1 · What is RDS?
RDS (Radio Data System) is a digital communication standard that transmits data as an inaudible signal modulated onto FM broadcasts (87.5–108 MHz). It was standardized under ETSI EN 50067 and has been in use across Europe since the 1980s. In North America, a nearly identical standard exists called RBDS.
RDS carries a variety of continuous digital metadata alongside the analog audio signal. The most commonly used data fields are:
| Code |
Name |
Meaning |
Size |
| PI |
Programme Identification |
Unique 16-bit station identifier (hex, e.g. D3C3). Essential for auto-tuning. |
16 bit |
| PS |
Programme Service Name |
Station name, max. 8 characters (e.g. "NRJ ") |
8 × 8 bit |
| RT |
RadioText |
Scrolling text, max. 64 characters (title, artist, show name) |
64 × 8 bit |
| PTY |
Programme Type |
Programme category (0–31, e.g. 10 = Pop Music) |
5 bit |
| TP |
Traffic Programme |
Flag indicating if the station broadcasts traffic announcements |
1 bit |
| TA |
Traffic Announcement |
Flag indicating if a traffic announcement is currently active |
1 bit |
| AF |
Alternate Frequencies |
List of alternative frequencies carrying the same programme |
8 bit each |
| ECC |
Extended Country Code |
Extended country identifier (combined with PI to determine country) |
8 bit |
2 · Getting Started & UI Indicators
2.1 · Enabling the Plugin
To activate the RDS AI Predictor, open the main menu (three dots icon) in the TEF Logger App and check the RDS AI option. Once activated, the AI indicator icon will appear in the top toolbar.
2.2 · AI Indicator Icons
The AI icon provides real-time feedback on the predictor's status:
| Icon State |
Meaning |
| Disabled / Crossed out |
The RDS AI Predictor is turned off in the settings. Statistical prediction is entirely bypassed. |
| Standby / Inactive |
The plugin is enabled but is currently waiting for valid RDS fragments, or the signal is too weak to generate a confident prediction. |
| Active |
The predictor is actively intercepting fragments and is currently generating or maintaining a stabilized PS string on the screen. |
2.3 · Offline Spectrum Caching (Mandatory)
The AI Predictor heavily relies on the offline TX Database to validate station names and reject corrupted "garbage" text. For the engine to work accurately across the entire FM band without interruptions, it is highly recommended to cache the complete spectrum (87.5 MHz to 108.0 MHz).
Incomplete Cache Alert: The standard FM spectrum consists of 206 frequencies (in 0.1 MHz steps). If you enable the AI Predictor and your device has fewer than 206 freq_*.json files in the cache folder, the app will automatically display an "Incomplete Offline Cache" warning. You should click "Start Caching" on this prompt to download the full reference database for seamless AI prediction.
3 · Why an AI Predictor?
Under local reception conditions with a strong antenna, RDS decoding is instantaneous and error-free. However, during long-distance FM reception (DX) – especially via tropospheric ducting, meteor scatter, or Sporadic-E propagation – signals are often extremely weak, rapidly fading, and severely affected by multipath interference or co-channel interference.
When the signal-to-noise ratio drops, the native RDS decoder built into the receiver chips (like TEF6686 / TEF6687 / NXP) struggles:
- Packet loss: Entire RDS groups are lost in transit due to sudden deep fades.
- Bit errors: Individual bits flip, causing incorrect characters to be parsed.
- Incomplete PS names: Because the PS name is sent 2 characters at a time, severe fading often results in only 2 or 4 of the 8 characters being received correctly. The UI flickers between spaces, correct letters, and garbage.
- False Identifications: Extreme noise can occasionally trick the hardware CRC (Cyclic Redundancy Check) into accepting a garbage block as "valid", injecting random ghost PI codes or phantom PS characters.
Plugin Goal: Rather than relying on the receiver's real-time, volatile interpretation of the data, the AI Predictor intercepts the raw UDP packets before they reach the UI. By collecting and statistically evaluating thousands of received fragments – including those with minor errors – a highly reliable probability model of the station is constructed.
Known stations are recognized instantly from the FMDX.ORG database. Corrupted characters are filtered out mathematically, and the user interface displays a stable, perfectly locked station name, completely eliminating UI flicker.
4 · Architecture Overview
The RDS AI Predictor operates as a real-time character-level voting engine that intercepts UDP packets from the TEF hardware before they reach the UI layer.
┌──────────────────────────────────────────────────────────────┐
│ TEF Hardware (UDP Port 9100) │
│ TEF6686 / TEF6687 / NXP Receiver Chip │
│ │
│ Raw RDS Data Stream (CSV format over UDP) │
└──────────────────┬───────────────────────────────────────────┘
│
│ UDP Packets
│ (version,firmware,scan,date,time,freq,
│ signal,pi,ps,stereo,ta,tp,ecc,pty,af,rt)
▼
┌──────────────────────────────────────────────────────────────┐
│ Core App Logic │
│ │
│ • Listens on Port 9100 │
│ • Main packet handler │
│ • Hardware Lag Filter (200ms window) │
│ • Passes PS fragments to AI Predictor │
│ • Applies final prediction to UI Layout │
└──────────────────┬───────────────────────────────────────────┘
│
│ PS Fragments (2 chars/packet)
│
▼
┌─────────────────────────────────────────────────────────────┐
│ AI Predictor Engine │
│ │
│ Core Algorithms: │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ • Character-Level Statistical Voting │ │
│ │ • Snap-Lock Stability Engine │ │
│ │ • Dynamic/Scrolling PS Detection │ │
│ │ • FMDX.org Reference Matching │ │
│ │ • Bigram Statistical Correction │ │
│ │ • Garbage Protection Filter │ │
│ │ • Reverse-Lookup (Text-to-PI) │ │
│ │ • Local Learning & Persistence │ │
│ │ • Anti-Hallucination (Scatter Mode) [v6.0] │ │
│ │ • Local Truth Override (FMDX Bypass) [v6.0] │ │
│ └────────────────────────────────────────────────────────┘ │
└──────────────────┬──────────────────────────────────────────┘
│
│ Final Prediction
│ (8-char PS string)
▼
┌──────────────────────────────────────────────────────────────┐
│ App Internal Memory Storage │
│ │
│ • Learned stations (PI → PS mapping) │
│ • Frequency-based learning (freq_XXX → Set
) │
│ • Persistent across app restarts │
└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ Local JSON Cache Storage │
│ Downloads/jsonCache/ │
│ │
│ • freq_87.6.json ... freq_107.9.json │
│ • FMDX.org transmitter database (offline cache) │
│ • Updated automatically when available │
└──────────────────────────────────────────────────────────────┘
5 · Core Algorithms
5.1 · Character-Level Voting Engine
Unlike traditional decoders that treat the entire 8-character PS string as a single unit, the AI Predictor votes on each character position independently.
When a PS fragment arrives (e.g., 2 characters at positions 0 and 1):
- Check hardware lag: If received within 200ms of a frequency change, discard it (compensates for TEF chip buffer lag).
- Extract character: Read the character at each index position.
- Award points: The engine maintains internal vote storage for all 8 character positions. Each appearance increments a vote counter for that specific character at that specific index.
- Require threshold: A character must appear a required number of times (e.g., 2 hits) to be mathematically accepted.
- Lock position: Once the threshold is reached, the character is locked for that position and its competitive votes are cleared.
Example
Received fragments for position 0:
Packet 1: 'N' → 1 vote
Packet 2: 'N' → 2 votes ✓ LOCKED (threshold reached)
Packet 3: 'M' → ignored (N already locked)
Packet 4: '?' (noise) → ignored
Result: Position 0 = 'N'
Why Independent Voting Works: During weak signal conditions, different character positions may be received at different times. Traditional decoders wait for all 8 characters to arrive error-free in one transmission. The AI Predictor assembles the name piece-by-piece, accepting positions 0-1 from packet #5, positions 2-3 from packet #12, positions 4-5 from packet #7, etc. This dramatically speeds up identification during fading.
5.2 · Hardware Lag Filter (200ms Window)
The TEF chip contains an internal RDS buffer. When you change frequencies, the chip continues outputting data from the previous station for approximately 200 milliseconds.
If this stale data is fed into the voting engine, it causes instant corruption of the new station's PS name by mixing characters from two different stations.
Problem Scenario
Time: 0ms - User tunes from 100.5 MHz to 104.3 MHz
Time: 50ms - TEF chip still outputting "R T L _ _ _ _" (old station)
Time: 150ms - TEF chip still outputting "R T L _ _ _ _" (old station)
Time: 300ms - TEF chip still outputting "R T L _ _ _ _" (old station)
Time: 850ms - TEF chip finally outputs "A N T E N N E" (new station)
❌ Without filter: AI learns mixed "R T L E N N E _" (garbage)
✅ With filter: AI ignores packets 0-200ms, learns "A N T E N N E" cleanly
Application Logic
The app tracks the precise timestamp of every frequency change. When incoming UDP packets are processed, the time elapsed since the last frequency change is calculated. If this duration falls within the hardware lag window, the packet's PI and PS info are securely bypassed and not fed to the AI Engine.
Critical Timing: The 200ms window is based on empirical testing with real TEF6686/TEF6687 hardware. Reducing this window risks contamination; increasing it delays new station identification. The value is optimized for the fastest safe identification.
5.3 · FMDX.org Reference Database
The app maintains a local offline cache of transmitter data downloaded from maps.fmdx.org. Each frequency has a corresponding JSON file (e.g., freq_104.3.json) stored in the app's internal cache directories.
Database Structure
{
"update": "15-01-2025",
"locations": {
"Berlin": {
"name": "Berlin/Scholzplatz",
"itu": "D",
"lat": 52.5200,
"lon": 13.4050,
"stations": [
{
"id": "D-123-BE",
"pi": "D3C3",
"pireg": "D3C4",
"ps": "RTL Radio_One",
"station": "RTL Radio",
"freq": 104.3,
"erp": 100,
"pol": "H"
}
]
}
}
}
PS Variant Parsing and Caching
The ps field can contain multiple space-separated variants of the station name. The AI reads these raw strings and isolates them into individual 8-character normalized blocks.
When the frequency changes, the AI loads the corresponding JSON file directly into RAM and indexes all stations by PI code. This means the system instantly pairs incoming data with cached possibilities.
Instant Matching: Because the entire frequency's transmitter database is loaded into RAM, the AI can perform PI-to-PS lookups in microseconds. No network latency, no API calls – everything happens locally and instantly.
5.4 · Garbage Protection Filter
Not all PS strings that mathematically "complete" are valid. Sometimes noise creates a perfectly plausible 8-character string that is not the actual station name. This is especially common during deep fades when hardware CRC checks occasionally accept corrupted blocks as "valid".
Validation Rules
The AI applies strict validation before accepting a candidate PS string:
- FMDX Database Presence: If the PI code exists in the FMDX database, the PS string MUST match one of the known variants.
- Exact Match: The candidate exactly matches a known variant (case-insensitive).
- Prefix Match: The candidate is a prefix of a known variant (e.g., "RTL" matches "RTL ").
- Single-Variant Strict Mode: If FMDX has only ONE PS variant mapped to a station, non-matching suffixes are NEVER allowed.
- Multi-Variant Relaxed Mode: If FMDX has multiple variants, alphanumeric suffixes are permitted to accommodate minor regional variations.
Example Scenarios
| FMDX Database |
Live Received |
Result |
Reason |
["RTL "] |
"RTL " |
✅ Accept |
Exact match |
["RTL "] |
"RTL HITS" |
❌ Reject |
Single-variant station cannot have suffix |
["RTL ", "RTL BERL"] |
"RTL PLUS" |
✅ Accept |
Multi-variant allows alphanumeric suffix |
["ANTENNE"] |
"ANT€NN€$" |
❌ Reject |
Invalid characters (noise corruption) |
| (not in DB) |
"PIRATE99" |
✅ Accept |
Unknown PI codes bypass validation |
Why This Matters: During Sporadic-E openings, you might briefly receive a weak signal from a distant transmitter on the same frequency as your local station. Without garbage protection, the AI could mix characters from both transmitters, creating a nonsense name like "RTLTENNE" (mixing "RTL" and "ANTENNE"). The strict validation prevents this corruption.
5.5 · Snap-Lock Stability Engine
Once a PS string is fully assembled and validated, the AI "locks" it to prevent further changes. This eliminates UI flicker completely and provides a rock-solid display even during severe fading.
Locking Conditions
A PS string is locked when ALL of the following conditions are met:
- All 8 positions verified: Every character index in the 8-character block contains a validated candidate.
- Non-blank name: At least 2 non-space characters are present.
- PI code present: A valid PI code has been successfully decoded.
- String stable: The AI predicts the exact same combination for multiple consecutive frames.
- Not flagged as dynamic: The string is not recognized as a scrolling text broadcast.
- Passes FMDX validation: The string aligns with expected values per the garbage protection filter.
State Transitions
┌─────────────┐
│ UNLOCKED │ ← Initial state after frequency change
└──────┬──────┘
│
│ Receive PS fragments
│ Vote on characters
▼
┌─────────────┐
│ VERIFYING │ ← All 8 positions have candidates
└──────┬──────┘ but not yet stable
│
│ Same string for 2+ frames
│ Passes FMDX validation
▼
┌─────────────┐
│ LOCKED │ ← PS locked, UI frozen
└─────────────┘ Only frequency change can unlock
User Experience: Once locked, the station name remains perfectly stable on screen even if the signal drops to complete noise for several seconds. When the signal returns, the AI instantly resumes tracking, verifying the locked string is still correct.
5.6 · Dynamic/Scrolling PS Detection
Some stations (especially in Italy and Eastern Europe) illegally use their PS field to transmit scrolling text (song titles, phone numbers) instead of a static station name. This is officially prohibited under the RDS standard but widely practiced.
Detection Algorithm
The AI maintains a rolling memory buffer of the last 8 complete PS strings received. It constantly analyzes these buffered entries mathematically to check for clear scrolling patterns or severe character rotation.
Example: Scrolling Detection
Buffer contents (received over 8 transmissions):
Position: 0 1 2 3 4 5 6 7
String: "WELCOME " → "ELCOME T" → "LCOME TO" → "COME TO " → ...
Analysis:
- String[1] = String[0] rotated by 1 position ✓
- String[2] = String[1] rotated by 1 position ✓
- String[3] = String[2] rotated by 1 position ✓
Scroll ratio: 3/3 = 100% > 60% threshold
Result: Dynamic PS Active
Behavior Changes
When a station is flagged as dynamic:
- Snap-Lock disabled: The PS string is never locked.
- Voting bypassed: Statistical aggregation is skipped so that fragments aren't merged incorrectly.
- Raw pass-through: The most recent complete fragment is displayed directly.
- Flag stored: The
⚡ symbol appears in logs/UI to indicate dynamic behavior.
Why This Matters: Without dynamic detection, the voting engine would attempt to statistically aggregate scrolling text. This produces total garbage like "W LC ME T O" (mixing letters from different scroll positions). By detecting scrolling and bypassing voting, the AI correctly displays the moving text.
5.7 · Bigram Statistical Correction
When the signal is extremely weak, some character positions may never receive a valid fragment. The AI uses bigram statistical analysis to predict missing characters based on the characters immediately before them.
Bigram Probability Engine
An internal scoring system evaluates known European FM station names (extracted from over 10,000 real stations). It understands that an 'R' is highly likely to be followed by an 'A', 'E', or 'O', while it is very unlikely to be followed by an 'X' or 'Z'.
Gap Filling Algorithm
When a character position remains completely empty after all voting attempts, the AI looks at the previous character and assigns a statistically likely fill-in to bridge the gap.
Example
Received fragments: "R _ D _ O _ _ _"
Bigram correction:
Position 1: 'R' → most likely next = 'A' (score 20)
Position 3: 'D' → most likely next = 'I' (score 10)
Position 5: 'O' → most likely next = ' ' (space)
Position 6: ' ' → most likely next = 'R' (score 25)
Position 7: 'R' → most likely next = 'E' (score 18)
Result: "R A D I O R E" (likely "RADIO RE" = Radio RE regional network)
Confidence Penalty: Bigram-predicted characters are flagged as unverified internally and displayed in a dimmer color in the UI. The AI will never lock a PS string that contains bigram predictions – it waits for real hardware verification.
5.8 · Reverse-Lookup (Text-to-PI) with AF Validation
When the TEF hardware fails to decode the PI code (due to extreme noise), but the AI has successfully reconstructed at least 3-4 characters of the PS name, the AI searches the frequency database backwards to guess which PI code the fragments belong to.
The Problem
Traditional flow:
Hardware decodes PI → AI searches DB for matching PS variants
❌ Problem: If PI decoding fails, AI has ZERO reference context
New Reverse-Lookup flow:
AI reconstructs PS fragments → Searches DB for stations with matching text
→ Finds matching PI → Uses that PI for validation
✅ Result: Station identified even when PI is completely missing
Search Engine Logic
When the PI is completely blank but there are enough valid character fragments, the engine iterates over all known offline stations on the current frequency. It calculates a "match score" by comparing the incoming character indices strictly against the reference names. If a dominant match is found, the missing PI code is injected retroactively.
Ambiguity Resolution via AF Cross-Referencing
When relying solely on partial PS strings, fragments like ANTENNE_ can be highly ambiguous in regions with many similar station names (e.g., Antenne Brandenburg vs. Antenne Bayern). Because the predictor evaluates text matches, multiple stations could achieve identical confidence scores.
To break these ties, the predictor uses Alternative Frequencies (AF) as a secondary verification factor. If the engine guesses a specific PI code, it instantly cross-references the received AF list against the known AFs for that PI. A successful AF match applies a massive bonus score, virtually eliminating incorrect guesses and instantly resolving ambiguous fragments.
5.9 · Forward-Lookup (PI-to-Text) with AF Validation
The logical counterpart to Reverse-Lookup, the Forward-Lookup is a highly reliable mechanism that instantly reconstructs missing PS characters when the PI code is known but the PS text is still fragmentary due to poor reception.
The Mechanism
Unlike the PS name, the PI code is a machine-readable, unambiguous identifier that is typically transmitted more frequently and decoded much faster by the hardware. When the receiver successfully decodes a valid PI code (e.g., D373) but the PS text remains incomplete (e.g., _D___UM_):
- The AI Predictor intercepts the valid PI code.
- It instantly searches the frequency database (the local
freq_XX.X.json cache) for a station broadcasting on the current frequency with that specific PI code.
- If a match is found, it verifies the incoming AF list against the database. If the AFs align, the AI immediately extracts the perfect, complete PS name from the database.
- The AI forces the UI to display the complete station name instantly, entirely bypassing the need to wait for further PS character fragments to arrive over the air.
5.10 · Local Learning & Persistence
Every time the AI successfully locks a PS string, it saves the PI→PS mapping to persistent storage. This creates a growing personal database of stations you've received, enabling instant identification on subsequent receptions.
Storage Mechanism
Two types of persistence are maintained automatically by the application:
- PI-based memory: Directly associates a known PI code with a verified PS name.
- Frequency-based memory: Associates specific frequencies with groups of PI-to-PS mappings received in the past.
Instant Prediction on Frequency Change
When you tune to a new frequency, before the first UDP packet even arrives, the AI checks if it has previously learned stations on this frequency. If found, it instantly prepares the predicted PS name.
User tunes to 104.3 MHz
AI checks: Local frequency memory for 104.3
→ Found: "D3C3 = RTL "
✨ Instantly displays "RTL " in grey
(grey = prediction, waiting for hardware confirmation)
First UDP packet arrives (500ms later):
→ PI = D3C3 ✓
→ Prediction confirmed
→ Display turns white (confirmed)
5.11 · Anti-Hallucination (Scatter Mode) v6.0
During extreme DXing scenarios like Meteor Scatter, a signal may briefly reflect off an ionized meteor trail for just a fraction of a second. The receiver hardware often captures the PI code (which is transmitted most frequently) but fails to decode any PS text characters before the signal vanishes.
Previously, if the AI Predictor received a valid PI code, it would eagerly search the FMDX database and "guess" or hallucinate the full station name, even if no actual text was received over the air. In version 6.0, the Anti-Hallucination filter checks the live fragment buffer. If exactly zero valid PS characters were decoded, the engine refuses to hallucinate a name. The PI code is correctly logged, but the PS field remains safely blank, preserving the absolute integrity of your DX logbook.
5.12 · Local Truth Override (FMDX Bypass) v6.0
The Garbage Protection filter (Section 5.4) is highly aggressive to prevent noise-corrupted text from appearing on the screen. However, this strict enforcement created a problem for DXers using personal local test transmitters, or when a legitimate station recently rebranded and hasn't been updated on FMDX.org yet.
The Local Truth Override solves this. If the AI Predictor determines that the incoming live PS string is 100% mathematically perfect (all 8 character positions received and verified flawlessly from the hardware) AND contains actual text, it will automatically bypass the strict FMDX sanity filter. The app will trust the perfect live radio signal over the outdated or mismatched global database, allowing bespoke texts or new station names to instantly lock and learn.
6 · Integration with Main UI
6.1 · UDP Packet Processing Flow
The AI Predictor is tightly integrated into the main UDP packet processing pipeline. Every UDP packet from the TEF hardware passes through multiple filtering and validation stages before reaching the UI:
┌──────────────────────────────────────────────────────────────┐
│ UDP Listener (Listening on Port 9100) │
└──────────────────┬───────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ Packet Processing Logic │
│ │
│ Step 1: Parse CSV format │
│ Extracts all fields (freq, signal, pi, ps, pty, etc.) │
│ │
│ Step 2: Frequency change detection │
│ If frequency shifted: Clear internal cache and timers │
│ │
│ Step 3: Hardware lag filter │
│ If time since change < 200ms: Strip out stale PI/PS info│
│ │
│ Step 4: Feed to AI Engine │
│ Push safely filtered fragments into the AI algorithms │
│ │
│ Step 5: Get AI prediction │
│ Engine returns stabilized PS and inferred/verified PI │
│ │
│ Step 6: Apply to UI Layout │
│ Update user-facing text elements │
│ │
│ Step 7: Async database validation │
│ Evaluate database matches to apply final coloring logic │
└──────────────────────────────────────────────────────────────┘
6.2 · UI Color Coding System
The AI Predictor uses a sophisticated color-coding system to communicate confidence levels to the user. Each character position in the PS display can have a different color based on its verification status:
| Color |
Meaning |
Condition |
| White |
Verified character - matches FMDX database |
Character at this position matches the reference database entry |
| Gray |
Unverified character - statistical prediction only |
Character from voting engine but no database confirmation yet |
| Gray + strikethrough |
Database missing - cannot verify |
PI exists in FMDX but on a different frequency (not cached locally) |
Visual Example
Scenario: Weak signal, partial reception
Database: "A N T E N N E _"
Received: "A _ T _ N N _ _"
AI fills: "A N T E N N E _" (N,E from bigram prediction)
Display colors:
'A' → White (matches DB exactly)
'N' → Gray (bigram prediction)
'T' → White (matches DB exactly)
'E' → Gray (bigram prediction)
'N' → White (matches DB exactly)
'N' → White (matches DB exactly)
'E' → Gray (missing from hardware)
'_' → Gray (empty)
User sees: ANTENNE_
6.3 · Frequency Change Handling
Frequency changes trigger a complete reset of the AI Predictor's internal state to prevent contamination from the previous station. This is one of the most critical parts of the integration:
Complete Reset Sequence
- Mark exact moment: Timestamps precisely when the frequency shifted.
- Clear AI internal state: All voting engines, locks, and fragments are wiped clean.
- Clear caches: Any "sticky" reference or alternate frequency validations are dumped.
- Reset UI state: Clears global variables holding prior signals and comments.
- Reset Station IDs: Overridden values and known active IDs are reset.
- Unlock views: Allows frozen UI panels to dynamically update again.
- Render default view: Forces the UI to show neutral, default layouts waiting for new station info.
Performance Note: The complete reset executes in microseconds. It's intentionally comprehensive to guarantee zero contamination between stations. There is no "soft reset" option – every frequency change triggers a full wipe.
7 · Troubleshooting & FAQ
Q: The AI displays "________" (all blanks) even though I can hear the station clearly.
A: This means the TEF hardware is not decoding any RDS data at all (error level 2 or 3 on every packet). Possible causes:
- RDS modulation is extremely weak (signal <20 dBf)
- Heavy multipath interference destroying RDS synchronization
- Co-channel interference from another station on the same frequency
- The station is not transmitting RDS (audio-only broadcast)
Solution: Try rotating your antenna for better multipath cancellation, or wait for the signal to strengthen.
Q: The PS name keeps changing between two different stations on frequency changes.
A: The 200ms hardware lag filter is being bypassed or you are switching too rapidly. Ensure you are not changing frequencies faster than 200ms (wait at least 1 second between changes).
Q: The AI locked onto a wrong station name and won't update.
A: Once locked, the PS only changes on frequency change or PI change. Solutions:
- Tune away to a blank frequency (e.g., 87.5 MHz)
- Wait 2 seconds (ensures complete reset)
- Tune back to the original frequency
The AI will rebuild from scratch. If the wrong name returns, it means the FMDX database has incorrect data for that PI code.
Q: Why is the PI code shown with an asterisk (e.g., "D3C3*")?
A: The asterisk indicates the PI code was guessed by the Reverse-Lookup engine. The hardware never successfully decoded the PI – the AI inferred it from the PS fragments. This is normal during extremely weak signal conditions.
Q: Some characters are white and some are gray. What does this mean?
A:
- White: Character was verified against the FMDX.org database – definitely correct
- Gray: Character is a statistical prediction or bigram fill – probably correct but not database-confirmed
As the signal improves, more characters will turn white. A fully-white display means perfect match.
Q: The AI Icon shows "ON" but nothing is happening.
A: Check the app settings:
- Open the menu (three dots)
- Verify "RDS AI" is enabled (checkbox ticked)
- Check if the AI Indicator Icon is visible and what state it shows (Crossed out vs. Highlighted).
- Restart the app if the icon state is inconsistent
Q: Does the AI work offline?
A: Yes, with limitations:
- ✅ Learned stations: Stations you've previously received are identified instantly offline
- ✅ Cached FMDX data: If
freq_XXX.json files exist locally, database matching works offline
- ❌ New frequencies: First-time reception of an unknown frequency requires internet to download FMDX data
Q: The AI displays a station name in ALL CAPS but FMDX.org shows mixed-case. Why?
A: The station is transmitting its PS in uppercase. The AI respects the actual transmitted data. If you want to enforce the FMDX mixed-case variant, the station must appear in your local learned database first (so the AI knows both variants exist).
Q: Can I delete learned stations from the AI's memory?
A: Yes. Go to Android Settings → Apps → TEF Logger → Storage → Clear Data. This will erase all learned stations. Warning: This also deletes all app settings.
Q: How do I report a bug or incorrect station identification?
A: Please report via our official support channels.
Include:
- Frequency (MHz)
- PI code (hex)
- What the AI displayed
- What the correct station name should be
- Your approximate location (city/country)
- Screenshot if possible
Community Contributions: The RDS AI Predictor improves with every report. Incorrect identifications are usually caused by outdated FMDX.org data or stations using non-standard PI codes. Your feedback helps fix these edge cases for all users.