SDRPlusPlus/decoder_modules/radio/src/rds.h
2022-07-06 22:32:27 +02:00

179 lines
6.4 KiB
C++

#pragma once
#include <stdint.h>
#include <string>
#include <chrono>
#include <mutex>
namespace rds {
enum BlockType {
BLOCK_TYPE_A,
BLOCK_TYPE_B,
BLOCK_TYPE_C,
BLOCK_TYPE_CP,
BLOCK_TYPE_D,
_BLOCK_TYPE_COUNT
};
enum GroupVersion {
GROUP_VER_A,
GROUP_VER_B
};
enum AreaCoverage {
AREA_COVERAGE_LOCAL,
AREA_COVERAGE_INTERNATIONAL,
AREA_COVERAGE_NATIONAL,
AREA_COVERAGE_SUPRA_NATIONAL,
AREA_COVERAGE_REGIONAL1,
AREA_COVERAGE_REGIONAL2,
AREA_COVERAGE_REGIONAL3,
AREA_COVERAGE_REGIONAL4,
AREA_COVERAGE_REGIONAL5,
AREA_COVERAGE_REGIONAL6,
AREA_COVERAGE_REGIONAL7,
AREA_COVERAGE_REGIONAL8,
AREA_COVERAGE_REGIONAL9,
AREA_COVERAGE_REGIONAL10,
AREA_COVERAGE_REGIONAL11,
AREA_COVERAGE_REGIONAL12
};
enum ProgramType {
// US Types
PROGRAM_TYPE_US_NONE = 0,
PROGRAM_TYPE_US_NEWS = 1,
PROGRAM_TYPE_US_INFOMATION = 2,
PROGRAM_TYPE_US_SPORTS = 3,
PROGRAM_TYPE_US_TALK = 4,
PROGRAM_TYPE_US_ROCK = 5,
PROGRAM_TYPE_US_CLASSIC_ROCK = 6,
PROGRAM_TYPE_US_ADULT_HITS = 7,
PROGRAM_TYPE_US_SOFT_ROCK = 8,
PROGRAM_TYPE_US_TOP_40 = 9,
PROGRAM_TYPE_US_COUNTRY = 10,
PROGRAM_TYPE_US_OLDIES = 11,
PROGRAM_TYPE_US_SOFT = 12,
PROGRAM_TYPE_US_NOSTALGIA = 13,
PROGRAM_TYPE_US_JAZZ = 14,
PROGRAM_TYPE_US_CLASSICAL = 15,
PROGRAM_TYPE_US_RHYTHM_AND_BLUES = 16,
PROGRAM_TYPE_US_SOFT_RHYTHM_AND_BLUES = 17,
PROGRAM_TYPE_US_FOREIGN_LANGUAGE = 18,
PROGRAM_TYPE_US_RELIGIOUS_MUSIC = 19,
PROGRAM_TYPE_US_RELIGIOUS_TALK = 20,
PROGRAM_TYPE_US_PERSONALITY = 21,
PROGRAM_TYPE_US_PUBLIC = 22,
PROGRAM_TYPE_US_COLLEGE = 23,
PROGRAM_TYPE_US_UNASSIGNED0 = 24,
PROGRAM_TYPE_US_UNASSIGNED1 = 25,
PROGRAM_TYPE_US_UNASSIGNED2 = 26,
PROGRAM_TYPE_US_UNASSIGNED3 = 27,
PROGRAM_TYPE_US_UNASSIGNED4 = 28,
PROGRAM_TYPE_US_WEATHER = 29,
PROGRAM_TYPE_US_EMERGENCY_TEST = 30,
PROGRAM_TYPE_US_EMERGENCY = 31,
// EU Types
PROGRAM_TYPE_EU_NONE = 0,
PROGRAM_TYPE_EU_NEWS = 1,
PROGRAM_TYPE_EU_CURRENT_AFFAIRS = 2,
PROGRAM_TYPE_EU_INFORMATION = 3,
PROGRAM_TYPE_EU_SPORTS = 4,
PROGRAM_TYPE_EU_EDUCATION = 5,
PROGRAM_TYPE_EU_DRAMA = 6,
PROGRAM_TYPE_EU_CULTURE = 7,
PROGRAM_TYPE_EU_SCIENCE = 8,
PROGRAM_TYPE_EU_VARIED = 9,
PROGRAM_TYPE_EU_POP_MUSIC = 10,
PROGRAM_TYPE_EU_ROCK_MUSIC = 11,
PROGRAM_TYPE_EU_EASY_LISTENING_MUSIC = 12,
PROGRAM_TYPE_EU_LIGHT_CLASSICAL = 13,
PROGRAM_TYPE_EU_SERIOUS_CLASSICAL = 14,
PROGRAM_TYPE_EU_OTHER_MUSIC = 15,
PROGRAM_TYPE_EU_WEATHER = 16,
PROGRAM_TYPE_EU_FINANCE = 17,
PROGRAM_TYPE_EU_CHILDRENS_PROGRAM = 18,
PROGRAM_TYPE_EU_SOCIAL_AFFAIRS = 19,
PROGRAM_TYPE_EU_RELIGION = 20,
PROGRAM_TYPE_EU_PHONE_IN = 21,
PROGRAM_TYPE_EU_TRAVEL = 22,
PROGRAM_TYPE_EU_LEISURE = 23,
PROGRAM_TYPE_EU_JAZZ_MUSIC = 24,
PROGRAM_TYPE_EU_COUNTRY_MUSIC = 25,
PROGRAM_TYPE_EU_NATIONAL_MUSIC = 26,
PROGRAM_TYPE_EU_OLDIES_MUSIC = 27,
PROGRAM_TYPE_EU_FOLK_MUSIC = 28,
PROGRAM_TYPE_EU_DOCUMENTARY = 29,
PROGRAM_TYPE_EU_ALARM_TEST = 30,
PROGRAM_TYPE_EU_ALARM = 31
};
enum DecoderIdentification {
DECODER_IDENT_STEREO = (1 << 0),
DECODER_IDENT_ARTIFICIAL_HEAD = (1 << 1),
DECODER_IDENT_COMPRESSED = (1 << 2),
DECODER_IDENT_VARIABLE_PTY = (1 << 0)
};
class RDSDecoder {
public:
void process(uint8_t* symbols, int count);
bool countryCodeValid() { std::lock_guard<std::mutex> lck(groupMtx); return anyGroupValid(); }
uint8_t getCountryCode() { std::lock_guard<std::mutex> lck(groupMtx); return countryCode; }
bool programCoverageValid() { std::lock_guard<std::mutex> lck(groupMtx); return anyGroupValid(); }
uint8_t getProgramCoverage() { std::lock_guard<std::mutex> lck(groupMtx); return programCoverage; }
bool programRefNumberValid() { std::lock_guard<std::mutex> lck(groupMtx); return anyGroupValid(); }
uint8_t getProgramRefNumber() { std::lock_guard<std::mutex> lck(groupMtx); return programRefNumber; }
bool programTypeValid() { std::lock_guard<std::mutex> lck(groupMtx); return anyGroupValid(); }
ProgramType getProgramType() { std::lock_guard<std::mutex> lck(groupMtx); return programType; }
bool musicValid() { std::lock_guard<std::mutex> lck(groupMtx); return group0Valid(); }
bool getMusic() { std::lock_guard<std::mutex> lck(groupMtx); return music; }
bool PSNameValid() { std::lock_guard<std::mutex> lck(groupMtx); return group0Valid(); }
std::string getPSName() { std::lock_guard<std::mutex> lck(groupMtx); return programServiceName; }
bool radioTextValid() { std::lock_guard<std::mutex> lck(groupMtx); return group2Valid(); }
std::string getRadioText() { std::lock_guard<std::mutex> lck(groupMtx); return radioText; }
private:
static uint16_t calcSyndrome(uint32_t block);
static uint32_t correctErrors(uint32_t block, BlockType type);
void decodeGroup();
bool anyGroupValid();
bool group0Valid();
bool group2Valid();
// State machine
uint32_t shiftReg = 0;
int sync = 0;
int skip = 0;
BlockType lastType = BLOCK_TYPE_A;
int contGroup = 0;
uint32_t blocks[_BLOCK_TYPE_COUNT];
// All groups
std::mutex groupMtx;
std::chrono::time_point<std::chrono::high_resolution_clock> anyGroupLastUpdate;
uint8_t countryCode;
AreaCoverage programCoverage;
uint8_t programRefNumber;
bool trafficProgram;
ProgramType programType;
// Group type 0
std::chrono::time_point<std::chrono::high_resolution_clock> group0LastUpdate;
bool trafficAnnouncement;
bool music;
uint8_t decoderIdent;
uint16_t alternateFrequency;
std::string programServiceName = " ";
// Group type 2
std::chrono::time_point<std::chrono::high_resolution_clock> group2LastUpdate;
bool rtAB = false;
std::string radioText = " ";
};
}