1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-23 10:05:46 -05:00

BFM demod: RDS GUI part #5: prepare groups 1, 2 and 8 implementation. Enhancements in the RDS GUI management

This commit is contained in:
Edouard Griffiths 2015-12-14 15:15:31 +01:00
parent 9eb271b218
commit 542877a454
4 changed files with 186 additions and 50 deletions

View File

@ -250,6 +250,7 @@ void BFMDemodGUI::on_showPilot_clicked()
void BFMDemodGUI::on_rds_clicked()
{
m_rdsParser.clearAllFields();
rdsUpdate(true);
applySettings();
}
@ -311,6 +312,9 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
rdsUpdateFixedFields();
rdsUpdate(true);
applySettings();
}
@ -396,7 +400,7 @@ void BFMDemodGUI::tick()
if (ui->rds->isChecked() && (m_rdsTimerCount == 0))
{
rdsUpdate();
rdsUpdate(false);
}
m_rdsTimerCount = (m_rdsTimerCount + 1) % 25;
@ -411,7 +415,34 @@ void BFMDemodGUI::channelSampleRateChanged()
ui->glSpectrum->setSampleRate(m_rate / 2);
}
void BFMDemodGUI::rdsUpdate()
void BFMDemodGUI::rdsUpdateFixedFields()
{
ui->g00Label->setText(m_rdsParser.rds_group_acronym_tags[0].c_str());
//ui->g01Label->setText(m_rdsParser.rds_group_acronym_tags[1].c_str());
//ui->g02Label->setText(m_rdsParser.rds_group_acronym_tags[2].c_str());
//ui->g03Label->setText(m_rdsParser.rds_group_acronym_tags[3].c_str());
ui->g04Label->setText(m_rdsParser.rds_group_acronym_tags[4].c_str());
//ui->g05Label->setText(m_rdsParser.rds_group_acronym_tags[5].c_str());
//ui->g06Label->setText(m_rdsParser.rds_group_acronym_tags[6].c_str());
//ui->g07Label->setText(m_rdsParser.rds_group_acronym_tags[7].c_str());
//ui->g08Label->setText(m_rdsParser.rds_group_acronym_tags[8].c_str());
//ui->g09Label->setText(m_rdsParser.rds_group_acronym_tags[9].c_str());
//ui->g14Label->setText(m_rdsParser.rds_group_acronym_tags[14].c_str());
ui->g00CountLabel->setText(m_rdsParser.rds_group_acronym_tags[0].c_str());
ui->g01CountLabel->setText(m_rdsParser.rds_group_acronym_tags[1].c_str());
ui->g02CountLabel->setText(m_rdsParser.rds_group_acronym_tags[2].c_str());
ui->g03CountLabel->setText(m_rdsParser.rds_group_acronym_tags[3].c_str());
ui->g04CountLabel->setText(m_rdsParser.rds_group_acronym_tags[4].c_str());
ui->g05CountLabel->setText(m_rdsParser.rds_group_acronym_tags[5].c_str());
ui->g06CountLabel->setText(m_rdsParser.rds_group_acronym_tags[6].c_str());
ui->g07CountLabel->setText(m_rdsParser.rds_group_acronym_tags[7].c_str());
ui->g08CountLabel->setText(m_rdsParser.rds_group_acronym_tags[8].c_str());
ui->g09CountLabel->setText(m_rdsParser.rds_group_acronym_tags[9].c_str());
ui->g14CountLabel->setText(m_rdsParser.rds_group_acronym_tags[14].c_str());
}
void BFMDemodGUI::rdsUpdate(bool force)
{
// Quality metrics
ui->demodQText->setText(QString("%1 %").arg(m_bfmDemod->getDemodQua(), 0, 'f', 0));
@ -421,7 +452,7 @@ void BFMDemodGUI::rdsUpdate()
ui->fclkText->setText(QString("%1 Hz").arg(m_bfmDemod->getDemodFclk(), 0, 'f', 2));
// PI group
if (m_rdsParser.m_pi_updated)
if (m_rdsParser.m_pi_updated || force)
{
ui->piLabel->setStyleSheet("QLabel { background-color : green; }");
ui->piCountText->setNum((int) m_rdsParser.m_pi_count);
@ -443,7 +474,7 @@ void BFMDemodGUI::rdsUpdate()
}
// G0 group
if (m_rdsParser.m_g0_updated)
if (m_rdsParser.m_g0_updated || force)
{
ui->g00Label->setStyleSheet("QLabel { background-color : green; }");
ui->g00CountText->setNum((int) m_rdsParser.m_g0_count);
@ -486,7 +517,7 @@ void BFMDemodGUI::rdsUpdate()
}
// G4 group
if (m_rdsParser.m_g4_updated)
if (m_rdsParser.m_g4_updated || force)
{
ui->g04Label->setStyleSheet("QLabel { background-color : green; }");
ui->g04CountText->setNum((int) m_rdsParser.m_g4_count);

View File

@ -93,7 +93,8 @@ private:
void blockApplySettings(bool block);
void applySettings();
void rdsUpdate();
void rdsUpdate(bool force);
void rdsUpdateFixedFields();
void leaveEvent(QEvent*);
void enterEvent(QEvent*);

View File

@ -124,6 +124,25 @@ const std::string RDSParser::rds_group_acronyms[16] = {
"___"
};
const std::string RDSParser::rds_group_acronym_tags[16] = {
"BAS",
"PIN",
"RTX",
"AID",
"TIM",
"TDC",
"IH_",
"RP_",
"TMC",
"EWS",
"___",
"___",
"___",
"___",
"EON",
"___"
};
/* page 74, Annex E, table E.1 in the standard: that's the ASCII table!!! */
/* see page 84, Annex J in the standard */
@ -224,7 +243,9 @@ void RDSParser::clearUpdateFlags()
m_pi_updated = false;
m_g0_updated = false;
m_g0_af_updated = false;
m_g2_updated = false;
m_g4_updated = false;
m_g8_updated = false;
}
void RDSParser::clearAllFields()
@ -238,7 +259,7 @@ void RDSParser::clearAllFields()
// Group 00 data
m_g0_count = 0;
std::memset(m_g0_program_service_name, ' ', sizeof(m_g0_program_service_name));
radiotext[sizeof(m_g0_program_service_name) - 1] = '\0';
m_g0_program_service_name[sizeof(m_g0_program_service_name) - 1] = '\0';
m_g0_traffic_announcement = false;
m_g0_music_speech = false;
m_g0_mono_stereo = false;
@ -247,12 +268,47 @@ void RDSParser::clearAllFields()
m_g0_static_pty = false;
m_g0_alt_freq.clear();
// Group 01 data
m_g1_count = 0;
m_g1_country_page_index = -1;
m_g1_country_index = -1;
m_g1_language_index = -1;
m_g1_pin_day = 0;
m_g1_pin_hour = 0;
m_g1_pin_minute = 0;
// Group 02 data
std::memset(radiotext, ' ', sizeof(radiotext));
radiotext[sizeof(radiotext) - 1] = '\0';
m_g2_count = 0;
std::memset(m_g2_radiotext, ' ', sizeof(m_g2_radiotext));
m_g2_radiotext[sizeof(m_g2_radiotext) - 1] = '\0';
// Group 03 data
m_g3_count = 0;
// Group 04 data
m_g4_count = 0;
m_g4_hours = 0;
m_g4_minutes = 0;
m_g4_seconds = 0;
m_g4_year = 0;
m_g4_month = 0;
m_g4_day = 0;
m_g4_local_time_offset = 0.0;
// Group 05..07 data
m_g5_count = 0;
m_g6_count = 0;
m_g7_count = 0;
// Group 08 data
m_g8_count = 0;
m_g8_diversion_recommended = false;
m_g8_dp_ci = 0;
m_g8_sign = false;
m_g8_extent = 0;
m_g8_event = 0;
m_g8_label_index = -1;
m_g8_content = 0;
clearUpdateFlags();
}
@ -513,17 +569,21 @@ void RDSParser::decode_type1(unsigned int *group, bool B)
char radio_paging_codes = group[1] & 0x1f;
int variant_code = (group[2] >> 12) & 0x7;
unsigned int slow_labelling = group[2] & 0xfff;
int day = (int)((group[3] >> 11) & 0x1f);
int hour = (int)((group[3] >> 6) & 0x1f);
int minute = (int) (group[3] & 0x3f);
m_g1_pin_day = (unsigned int)((group[3] >> 11) & 0x1f);
m_g1_pin_hour = (unsigned int)((group[3] >> 6) & 0x1f);
m_g1_pin_minute = (unsigned int) (group[3] & 0x3f);
m_g1_count++;
if (radio_paging_codes) {
qDebug() << "RDSParser::decode_type1: paging codes: " << int(radio_paging_codes) << " ";
//qDebug() << "RDSParser::decode_type1: paging codes: " << int(radio_paging_codes) << " ";
}
if (day || hour || minute) {
if (m_g1_pin_day || m_g1_pin_hour || m_g1_pin_minute) {
m_g1_updated = true;
/*
std::string s = str(boost::format("program item: %id, %i, %i ") % day % hour % minute);
qDebug() << "RDSParser::decode_type1: " << s.c_str();
qDebug() << "RDSParser::decode_type1: " << s.c_str();*/
}
if (!B)
@ -534,24 +594,30 @@ void RDSParser::decode_type1(unsigned int *group, bool B)
paging = (slow_labelling >> 8) & 0x0f;
ecc = slow_labelling & 0xff;
if (paging) {
qDebug() << "RDSParser::decode_type1: " << "paging: " << paging << " ";
//qDebug() << "RDSParser::decode_type1: " << "paging: " << paging << " ";
}
if ((ecc > 223) && (ecc < 229)) {
m_g1_updated = true;
m_g1_country_page_index = country_code - 1;
m_g1_country_index = ecc - 224;
/*
qDebug() << "RDSParser::decode_type1: " << "extended country code: "
<< (pi_country_codes[country_code-1][ecc-224]).c_str();
<< (pi_country_codes[country_code-1][ecc-224]).c_str();*/
} else {
qDebug() << "RDSParser::decode_type1: " << "invalid extended country code: " << ecc;
}
break;
case 1: // TMC identification
qDebug() << "RDSParser::decode_type1: TMC identification code received";
//qDebug() << "RDSParser::decode_type1: TMC identification code received";
break;
case 2: // Paging identification
qDebug() << "RDSParser::decode_type1: Paging identification code received";
//qDebug() << "RDSParser::decode_type1: Paging identification code received";
break;
case 3: // language codes
if (slow_labelling < 44) {
qDebug() << "RDSParser::decode_type1: " << "language: " << language_codes[slow_labelling].c_str();
m_g1_updated = true;
m_g1_language_index = slow_labelling;
//qDebug() << "RDSParser::decode_type1: " << "language: " << language_codes[slow_labelling].c_str();
} else {
qDebug() << "RDSParser::decode_type1: " << "language: invalid language code " << slow_labelling;
}
@ -566,38 +632,40 @@ void RDSParser::decode_type2(unsigned int *group, bool B)
{
unsigned char text_segment_address_code = group[1] & 0x0f;
m_g2_updated = true;
m_g2_count++;
// when the A/B flag is toggled, flush your current radiotext
if (radiotext_AB_flag != ((group[1] >> 4) & 0x01))
{
std::memset(radiotext, ' ', sizeof(radiotext));
radiotext[sizeof(radiotext) - 1] = '\0';
std::memset(m_g2_radiotext, ' ', sizeof(m_g2_radiotext));
m_g2_radiotext[sizeof(m_g2_radiotext) - 1] = '\0';
}
radiotext_AB_flag = (group[1] >> 4) & 0x01;
if (!B)
{
radiotext[text_segment_address_code * 4 ] = (group[2] >> 8) & 0xff;
radiotext[text_segment_address_code * 4 + 1] = group[2] & 0xff;
radiotext[text_segment_address_code * 4 + 2] = (group[3] >> 8) & 0xff;
radiotext[text_segment_address_code * 4 + 3] = group[3] & 0xff;
m_g2_radiotext[text_segment_address_code * 4 ] = (group[2] >> 8) & 0xff;
m_g2_radiotext[text_segment_address_code * 4 + 1] = group[2] & 0xff;
m_g2_radiotext[text_segment_address_code * 4 + 2] = (group[3] >> 8) & 0xff;
m_g2_radiotext[text_segment_address_code * 4 + 3] = group[3] & 0xff;
}
else
{
radiotext[text_segment_address_code * 2 ] = (group[3] >> 8) & 0xff;
radiotext[text_segment_address_code * 2 + 1] = group[3] & 0xff;
m_g2_radiotext[text_segment_address_code * 2 ] = (group[3] >> 8) & 0xff;
m_g2_radiotext[text_segment_address_code * 2 + 1] = group[3] & 0xff;
}
/*
qDebug() << "RDSParser::decode_type2: " << "Radio Text " << (radiotext_AB_flag ? 'B' : 'A')
<< ": " << std::string(radiotext, sizeof(radiotext)).c_str();
//send_message(4,std::string(radiotext, sizeof(radiotext)));
<< ": " << std::string(m_g2_radiotext, sizeof(m_g2_radiotext)).c_str();*/
}
void RDSParser::decode_type3(unsigned int *group, bool B)
{
if (B) {
qDebug() << "RDSParser::decode_type2: type 3B not implemented yet";
qDebug() << "RDSParser::decode_type3: type 3B not implemented yet";
return;
}
@ -702,9 +770,13 @@ void RDSParser::decode_type8(unsigned int *group, bool B)
return;
}
m_g8_updated = true;
m_g8_count++;
bool T = (group[1] >> 4) & 0x1; // 0 = user message, 1 = tuning info
bool F = (group[1] >> 3) & 0x1; // 0 = multi-group, 1 = single-group
bool D = (group[2] > 15) & 0x1; // 1 = diversion recommended
m_g8_diversion_recommended = D;
static unsigned long int free_format[4];
static int no_groups = 0;
@ -724,24 +796,24 @@ void RDSParser::decode_type8(unsigned int *group, bool B)
}
else if (F || D)
{ // single-group or 1st of multi-group
unsigned int dp_ci = group[1] & 0x7; // duration & persistence or continuity index
bool sign = (group[2] >> 14) & 0x1; // event direction, 0 = +, 1 = -
unsigned int extent = (group[2] >> 11) & 0x7; // number of segments affected
unsigned int event = group[2] & 0x7ff; // event code, defined in ISO 14819-2
m_g8_dp_ci = group[1] & 0x7; // duration & persistence or continuity index
m_g8_sign = (group[2] >> 14) & 0x1; // event direction, 0 = +, 1 = -
m_g8_extent = (group[2] >> 11) & 0x7; // number of segments affected
m_g8_event = group[2] & 0x7ff; // event code, defined in ISO 14819-2
unsigned int location = group[3]; // location code, defined in ISO 14819-3
qDebug() << "RDSParser::decode_type8: #user msg# " << (D ? "diversion recommended, " : "");
if (F) {
qDebug() << "RDSParser::decode_type8: single-grp, duration:" << (tmc_duration[dp_ci][0]).c_str();
qDebug() << "RDSParser::decode_type8: single-grp, duration:" << (tmc_duration[m_g8_dp_ci][0]).c_str();
} else {
qDebug() << "RDSParser::decode_type8: multi-grp, continuity index:" << dp_ci;
qDebug() << "RDSParser::decode_type8: multi-grp, continuity index:" << m_g8_dp_ci;
}
int event_line = RDSTMC::get_tmc_event_code_index(event, 1);
int event_line = RDSTMC::get_tmc_event_code_index(m_g8_event, 1);
qDebug() << "RDSParser::decode_type8: extent:" << (sign ? "-" : "") << extent + 1 << " segments"
<< ", event" << event << ":" << RDSTMC::get_tmc_events(event_line, 1).c_str()
qDebug() << "RDSParser::decode_type8: extent:" << (m_g8_sign ? "-" : "") << m_g8_extent + 1 << " segments"
<< ", event" << m_g8_event << ":" << RDSTMC::get_tmc_events(event_line, 1).c_str()
<< ", location:" << location;
}
@ -772,8 +844,6 @@ void RDSParser::decode_type8(unsigned int *group, bool B)
void RDSParser::decode_optional_content(int no_groups, unsigned long int *free_format)
{
int label = 0;
int content = 0;
int content_length = 0;
int ff_pointer = 0;
@ -784,13 +854,13 @@ void RDSParser::decode_optional_content(int no_groups, unsigned long int *free_f
while(ff_pointer > 0)
{
ff_pointer -= 4;
label = (free_format[i] && (0xf << ff_pointer));
content_length = optional_content_lengths[label];
m_g8_label_index = (free_format[i] && (0xf << ff_pointer));
content_length = optional_content_lengths[m_g8_label_index];
ff_pointer -= content_length;
content = (free_format[i] && (int(std::pow(2, content_length) - 1) << ff_pointer));
m_g8_content = (free_format[i] && (int(std::pow(2, content_length) - 1) << ff_pointer));
qDebug() << "RDSParser::decode_optional_content: TMC optional content (" << label_descriptions[label].c_str()
<< "):" << content;
qDebug() << "RDSParser::decode_optional_content: TMC optional content (" << label_descriptions[m_g8_label_index].c_str()
<< "):" << m_g8_content;
}
}
}

View File

@ -48,7 +48,7 @@ public:
bool m_g0_updated;
bool m_g0_af_updated;
unsigned int m_g0_count;
char m_g0_program_service_name[9];
char m_g0_program_service_name[8+1];
bool m_g0_traffic_announcement;
bool m_g0_music_speech;
bool m_g0_mono_stereo;
@ -57,6 +57,24 @@ public:
bool m_g0_static_pty;
std::set<double> m_g0_alt_freq;
// G1 data
bool m_g1_updated;
unsigned int m_g1_count;
int m_g1_country_page_index; //!< negative if not received
int m_g1_country_index; //!< negative if not received
int m_g1_language_index; //!< negative if not received
unsigned int m_g1_pin_day;
unsigned int m_g1_pin_hour;
unsigned int m_g1_pin_minute;
// G2 data
bool m_g2_updated;
unsigned int m_g2_count;
char m_g2_radiotext[64+1];
// G3 data
unsigned int m_g3_count;
// G4 data
bool m_g4_updated;
unsigned int m_g4_count;
@ -68,6 +86,22 @@ public:
unsigned int m_g4_day;
double m_g4_local_time_offset;
// G5..G7 data
unsigned int m_g5_count;
unsigned int m_g6_count;
unsigned int m_g7_count;
// G8 data
bool m_g8_updated;
unsigned int m_g8_count;
bool m_g8_diversion_recommended;
unsigned int m_g8_dp_ci;
bool m_g8_sign;
unsigned int m_g8_extent;
unsigned int m_g8_event;
int m_g8_label_index; //!< negative if not received
int m_g8_content;
// Static tables
static const unsigned int offset_pos[5];
static const unsigned int offset_word[5];
@ -77,6 +111,7 @@ public:
static const std::string pi_country_codes[15][5];
static const std::string coverage_area_codes[16];
static const std::string rds_group_acronyms[16];
static const std::string rds_group_acronym_tags[16];
static const std::string language_codes[44];
static const std::string tmc_duration[8][2];
static const int optional_content_lengths[16];
@ -104,7 +139,6 @@ private:
unsigned char pi_country_identification;
unsigned char pi_program_reference_number;
char radiotext[64+1];
bool radiotext_AB_flag;
bool debug;