1
0
mirror of https://github.com/JvanKatwijk/qt-dab.git synced 2025-10-06 08:12:40 +02:00
Files
SDR-DAB_Qt-DAB/sources/backend/data/pad-handler.cpp

658 lines
20 KiB
C++
Raw Normal View History

2017-02-06 14:09:08 +01:00
#
/*
2024-04-14 12:47:14 +02:00
* Copyright (C) 2015 .. 2023
2017-02-06 14:09:08 +01:00
* Jan van Katwijk (J.vanKatwijk@gmail.com)
* Lazy Chair Computing
*
2017-03-23 18:32:25 +01:00
* This file is part of the Qt-DAB
2021-08-03 15:13:54 +02:00
*
2017-03-23 18:32:25 +01:00
* Qt-DAB is free software; you can redistribute it and/or modify
2017-02-06 14:09:08 +01:00
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
2017-03-23 18:32:25 +01:00
* Qt-DAB is distributed in the hope that it will be useful,
2017-02-06 14:09:08 +01:00
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
2017-03-28 18:40:11 +02:00
* along with Qt-DAB; if not, write to the Free Software
2017-02-06 14:09:08 +01:00
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
2024-01-03 12:26:08 +01:00
//#define _PAD_TRACE_
2017-02-06 14:09:08 +01:00
#include "pad-handler.h"
#include <cstring>
#include "radio.h"
2023-10-14 11:27:18 +02:00
#include "crc-handlers.h"
2017-02-06 14:09:08 +01:00
#include "charsets.h"
2018-05-25 13:46:09 +02:00
#include "mot-object.h"
2017-02-06 14:09:08 +01:00
/**
* \class padHandler
2017-03-27 16:32:49 +02:00
* Handles the pad segments passed on from mp2- and mp4Processor
2017-02-06 14:09:08 +01:00
*/
2023-09-23 11:50:09 +02:00
padHandler::padHandler (RadioInterface *mr,
2025-05-27 18:50:45 +02:00
bool backgroundFlag):
myRadioInterface (mr) {
2023-09-23 11:50:09 +02:00
this -> backgroundFlag = backgroundFlag;
2024-04-14 12:47:14 +02:00
connect (this, &padHandler::show_label,
mr, &RadioInterface::show_label);
connect (this, &padHandler::show_mothandling,
mr, &RadioInterface::show_mothandling);
2025-06-09 15:04:46 +02:00
connect (this, &padHandler::show_title,
mr, &RadioInterface::show_title);
2025-05-27 18:50:45 +02:00
// currentSlide = nullptr;
2017-03-27 16:32:49 +02:00
//
// mscGroupElement indicates whether we are handling an
// msc datagroup or not.
mscGroupElement = false;
2017-12-27 19:11:36 +01:00
dataGroupLength = 0;
2017-03-27 16:32:49 +02:00
// xpadLength tells - if mscGroupElement is "on" - the size of the
// xpadfields, needed for handling xpads without CI's
xpadLength = -1;
//
// and for the shortPad we maintain
still_to_go = 0;
lastSegment = false;
firstSegment = false;
2017-08-25 21:24:45 +02:00
segmentNumber = -1;
2025-05-27 18:50:45 +02:00
//
//
segmentno = -1;
remainDataLength = 0;
isLastSegment = false;
moreXPad = false;
2025-06-07 18:45:00 +02:00
the_DL2. dlsText = "";
the_DL2. IT = 10;
the_DL2. IR = 10;
for (int i = 0; i < 4; i ++)
the_DL2. entity [i]. ct = 65;
2017-02-06 14:09:08 +01:00
}
2019-07-08 23:30:45 +02:00
padHandler::~padHandler() {
2025-05-27 18:50:45 +02:00
// if (currentSlide != nullptr)
// delete currentSlide;
2017-02-06 14:09:08 +01:00
}
2017-03-27 16:32:49 +02:00
// Data is stored reverse, we pass the vector and the index of the
// last element of the XPad data.
// L0 is the "top" byte of the L field, L1 the next to top one.
2025-06-09 15:04:46 +02:00
void padHandler::processPAD (const uint8_t *buffer, int16_t last,
2017-03-27 16:32:49 +02:00
uint8_t L1, uint8_t L0) {
uint8_t fpadType = (L1 >> 6) & 03;
2018-05-27 12:58:08 +02:00
if (fpadType != 00) {
2024-12-23 13:19:21 +01:00
// fprintf (stderr, "fPadtype = %x_padInd\n");
2017-02-06 14:09:08 +01:00
return;
2018-05-27 12:58:08 +02:00
}
2017-02-06 14:09:08 +01:00
//
// OK, we'll try
2017-03-27 16:32:49 +02:00
2017-08-24 19:30:52 +02:00
uint8_t x_padInd = (L1 >> 4) & 03;
uint8_t CI_flag = L0 & 02;
2017-02-06 14:09:08 +01:00
switch (x_padInd) {
2017-03-27 16:32:49 +02:00
default:
break;
2017-02-06 14:09:08 +01:00
case 01 :
handle_shortPAD (buffer, last, CI_flag);
2017-02-06 14:09:08 +01:00
break;
case 02:
handle_variablePAD (buffer, last, CI_flag);
2017-02-06 14:09:08 +01:00
break;
}
}
2017-03-27 16:32:49 +02:00
// Since the data is stored in reversed order, we pass
// on the vector address and the offset of the last element
// in that vector
2018-02-12 16:55:26 +01:00
//
2018-05-27 12:58:08 +02:00
// shortPad's are 4 byte values. If the CI is on, then type 2
2018-02-12 16:55:26 +01:00
// indicates the start of a segment. Type 3 the continuation.
// The start of a message, i.e. segment 0 is (a.o) found by
// a (1, 0) value of the firstSegment/lastSegment values.
// The end of a segment might be indicated by a specific pattern
// of these 2 values, but it is not clear to me how.
// For me, the end of a segment is when we collected the amount
// of values specified for the segment.
2025-06-09 15:04:46 +02:00
void padHandler::handle_shortPAD (const uint8_t *b,
int16_t last, uint8_t CIf) {
2017-02-06 14:09:08 +01:00
int16_t i;
2017-08-24 19:30:52 +02:00
if (CIf != 0) { // has a CI flag
2017-08-25 21:24:45 +02:00
uint8_t CI = b [last];
firstSegment = (b [last - 1] & 0x40) != 0;
lastSegment = (b [last - 1] & 0x20) != 0;
charSet = b [last - 2] & 0x0F;
uint8_t AcTy = CI & 037; // application type
2018-05-26 21:18:22 +02:00
2024-04-14 12:47:14 +02:00
if (firstSegment)
2023-02-12 13:04:38 +01:00
dynamicLabelText. clear ();
2017-08-24 19:30:52 +02:00
switch (AcTy) {
default:
break;
case 0: // end marker
break;
2018-02-12 16:55:26 +01:00
//
2018-07-16 11:33:39 +02:00
case 2: // start of fragment, extract the length
if (firstSegment && !lastSegment) {
segmentNumber = b [last - 2] >> 4;
2024-12-23 13:19:21 +01:00
if (dynamicLabelText. size () > 0) {
QString displayText = toQStringUsingCharset
((char *)(dynamicLabelText. data()),
(CharacterSet)charSet,
dynamicLabelText. size());
2025-01-13 19:13:10 +01:00
show_label (displayText, (int)charSet);
2024-01-03 12:26:08 +01:00
}
2024-12-23 13:19:21 +01:00
dynamicLabelText = "";
2018-07-16 11:33:39 +02:00
}
still_to_go = b [last - 1] & 0x0F;
shortpadData. resize (0);
shortpadData. push_back (b [last - 3]);
break;
2018-02-12 16:55:26 +01:00
case 3: // continuation of fragment
for (i = 0; (i < 3) && (still_to_go > 0); i ++) {
still_to_go --;
shortpadData. push_back (b [last - 1 - i]);
}
2019-07-08 23:30:45 +02:00
if ((still_to_go <= 0) && (shortpadData. size() > 1)) {
2025-01-13 19:13:10 +01:00
// shortpadData. push_back (0);
2024-12-23 13:19:21 +01:00
dynamicLabelText. append ((const char *)shortpadData. data (),
shortpadData. size ());
shortpadData. resize (0);
2018-02-12 16:55:26 +01:00
}
break;
2017-08-24 19:30:52 +02:00
}
}
else { // No CI flag
// X-PAD field is all data
for (i = 0; (i < 4) && (still_to_go > 0); i ++) {
2018-02-12 16:55:26 +01:00
shortpadData. push_back (b [last - i]);
still_to_go --;
}
2021-08-03 15:13:54 +02:00
2017-08-25 21:24:45 +02:00
// at the end of a frame
2019-07-08 23:30:45 +02:00
if ((still_to_go <= 0) && (shortpadData. size() > 0)) {
2025-01-13 19:13:10 +01:00
// shortpadData . push_back (0);
2017-08-25 21:24:45 +02:00
//
// just to avoid doubling by unsollicited shortpads
2024-12-23 13:19:21 +01:00
dynamicLabelText. append ((const char *)shortpadData. data (),
2024-04-14 12:47:14 +02:00
shortpadData. size ());
2018-02-12 16:55:26 +01:00
shortpadData. resize (0);
2017-08-25 21:24:45 +02:00
// if we are at the end of the last segment (and the text is not empty)
// then show it.
2018-02-12 16:55:26 +01:00
if (!firstSegment && lastSegment) {
2024-01-03 12:26:08 +01:00
if (dynamicLabelText. size() > 0) {
2024-12-23 13:19:21 +01:00
QString displayText =
toQStringUsingCharset (
(const char *)dynamicLabelText. data (),
(CharacterSet) charSet,
dynamicLabelText. size ());
2025-06-09 15:04:46 +02:00
// fprintf (stderr, "%s \n", displayText. toLatin1 (). data ());
2025-01-13 19:13:10 +01:00
show_label (displayText, (int)charSet);
2024-01-03 12:26:08 +01:00
}
2019-07-08 23:30:45 +02:00
dynamicLabelText. clear();
2017-08-25 21:24:45 +02:00
}
}
2017-08-24 19:30:52 +02:00
}
2017-02-06 14:09:08 +01:00
}
///////////////////////////////////////////////////////////////////////
//
// Here we end up when F_PAD type = 00 and X-PAD Ind = 02
static
int16_t lengthTable [] = {4, 6, 8, 12, 16, 24, 32, 48};
2017-03-27 16:32:49 +02:00
// Since the data is reversed, we pass on the vector address
// and the offset of the last element in the vector,
// i.e. we start (downwards) beginning at b [last];
2025-06-09 15:04:46 +02:00
void padHandler::handle_variablePAD (const uint8_t *b,
2017-03-27 16:32:49 +02:00
int16_t last, uint8_t CI_flag) {
int16_t CI_Index = 0;
uint8_t CI_table [4];
int16_t base = last;
2018-01-06 19:37:34 +01:00
std::vector<uint8_t> data; // for the local addition
2017-02-06 14:09:08 +01:00
2017-03-27 16:32:49 +02:00
// If an xpadfield shows with a CI_flag == 0, and if we are
// dealing with an msc field, the size to be taken is
// the size of the latest xpadfield that had a CI_flag != 0
if (CI_flag == 0) {
2025-05-27 18:50:45 +02:00
// if (mscGroupElement && (xpadLength > 0)) {
if (xpadLength > 0) {
if (last < xpadLength - 1) {
2024-12-27 12:39:00 +01:00
// fprintf(stderr, "handle_variablePAD: last < xpadLength - 1\n");
return;
}
2023-09-26 13:05:25 +02:00
2017-03-27 16:32:49 +02:00
data. resize (xpadLength);
2025-05-27 18:50:45 +02:00
for (int16_t j = 0; j < xpadLength; j ++)
2017-03-27 16:32:49 +02:00
data [j] = b [last - j];
2025-05-27 18:50:45 +02:00
switch (last_appType) {
// Dynamic label segment, start of X-PAD data group
case 2:
// Dynamic label segment, continuation of X-PAD data group
case 3:
dynamicLabel((uint8_t *)(data.data()), xpadLength, 3);
break;
case 12: // MOT, start of X-PAD data group
case 13: // MOT, continuation of X-PAD data group
if (mscGroupElement)
add_MSC_element(data);
break;
default:
break;
}
2017-03-27 16:32:49 +02:00
}
2017-02-06 14:09:08 +01:00
return;
2017-03-27 16:32:49 +02:00
}
2017-02-06 14:09:08 +01:00
//
// The CI flag in the F_PAD data is set, so we have local CI's
// 7.4.2.2: Contents indicators are one byte long
2017-03-27 16:32:49 +02:00
while (((b [base] & 037) != 0) && (CI_Index < 4))
CI_table [CI_Index ++] = b [base --];
2017-02-06 14:09:08 +01:00
2017-03-27 16:32:49 +02:00
if (CI_Index < 4) // we have a "0" indicator, adjust base
2017-02-06 14:09:08 +01:00
base -= 1;
2017-03-27 16:32:49 +02:00
2023-09-26 13:05:25 +02:00
// The space for the CI's does belong to the CPadfield, so
// do not forget to take into account the '0'field if CI_Index < 4
2025-05-27 18:50:45 +02:00
// if (mscGroupElement) {
{
2017-03-27 16:32:49 +02:00
xpadLength = 0;
2025-05-27 18:50:45 +02:00
for (int16_t i = 0; i < CI_Index; i ++)
2017-03-27 16:32:49 +02:00
xpadLength += lengthTable [CI_table [i] >> 5];
xpadLength += CI_Index == 4 ? 4 : CI_Index + 1;
2018-05-27 12:58:08 +02:00
// fprintf (stderr, "xpadLength set to %d\n", xpadLength);
2017-03-27 16:32:49 +02:00
}
2018-05-27 12:58:08 +02:00
2017-03-27 16:32:49 +02:00
// Handle the contents
2025-05-27 18:50:45 +02:00
for (int16_t i = 0; i < CI_Index; i ++) {
2017-02-06 14:09:08 +01:00
uint8_t appType = CI_table [i] & 037;
int16_t length = lengthTable [CI_table [i] >> 5];
2018-05-27 12:58:08 +02:00
2023-09-26 13:05:25 +02:00
if (appType == 1) { // length spec
2017-03-27 16:32:49 +02:00
dataGroupLength = ((b [base] & 077) << 8) | b [base - 1];
2017-02-06 14:09:08 +01:00
base -= 4;
last_appType = 1;
continue;
}
2017-03-27 16:32:49 +02:00
// collect data, reverse the reversed bytes
data. resize (length);
2025-05-27 18:50:45 +02:00
for (int16_t j = 0; j < length; j ++)
2017-02-06 14:09:08 +01:00
data [j] = b [base - j];
switch (appType) {
default:
2018-02-08 16:32:45 +01:00
return; // sorry, we do not handle this
2017-02-06 14:09:08 +01:00
2025-06-09 15:04:46 +02:00
case 1: //
// fprintf (stderr, "Need to fix this\n");
return;
case 2: // Dynamic label segment, start of X-PAD data group
case 3: // Dynamic label segment, continuation of X-PAD data group
2019-07-08 23:30:45 +02:00
dynamicLabel ((uint8_t *)(data. data()),
data. size(), CI_table [i]);
2017-02-06 14:09:08 +01:00
break;
2018-02-08 16:32:45 +01:00
case 12: // MOT, start of X-PAD data group
2018-05-27 12:58:08 +02:00
new_MSC_element (data);
2017-02-06 14:09:08 +01:00
break;
2018-02-08 16:32:45 +01:00
case 13: // MOT, continuation of X-PAD data group
2017-03-27 16:32:49 +02:00
add_MSC_element (data);
2017-02-06 14:09:08 +01:00
break;
}
last_appType = appType;
base -= length;
2017-03-27 16:32:49 +02:00
if (base < 0 && i < CI_Index - 1) {
// fprintf (stderr, "Hier gaat het fout, base = %d\n", base);
2017-02-06 14:09:08 +01:00
return;
}
}
}
//
// A dynamic label is created from a sequence of (dynamic) xpad
// fields, starting with CI = 2, continuing with CI = 3
2025-06-09 15:04:46 +02:00
void padHandler::dynamicLabel (const uint8_t *data, int16_t length, uint8_t CI) {
2017-02-06 14:09:08 +01:00
int16_t dataLength = 0;
if ((CI & 037) == 02) { // start of segment
uint16_t prefix = (data [0] << 8) | data [1];
uint8_t field_1 = (prefix >> 8) & 017;
uint8_t Cflag = (prefix >> 12) & 01;
uint8_t first = (prefix >> 14) & 01;
uint8_t last = (prefix >> 13) & 01;
dataLength = length - 2; // The length with header removed
2024-01-03 12:26:08 +01:00
#ifdef _PAD_TRACE_
2023-09-26 13:05:25 +02:00
fprintf (stderr, "first %d last %d Cflag %d\n",
first, last, Cflag);
#endif
2017-02-06 14:09:08 +01:00
if (first) {
2024-01-02 12:52:57 +01:00
segmentno = 1;
2024-01-03 12:26:08 +01:00
#ifdef _PAD_TRACE_
fprintf (stderr, "segment 1\n");
#endif
2017-02-06 14:09:08 +01:00
charSet = (prefix >> 4) & 017;
2024-12-23 13:19:21 +01:00
dynamicLabelText. clear ();
2017-02-06 14:09:08 +01:00
}
2024-01-02 12:52:57 +01:00
else {
int test = ((prefix >> 4) & 07) + 1;
if (test != segmentno + 1) {
2024-01-03 12:26:08 +01:00
#ifdef _PAD_TRACE_
fprintf (stderr, "mismatch %d %d\n", test, segmentno);
#endif
2024-01-02 12:52:57 +01:00
segmentno = -1;
return;
}
segmentno = ((prefix >> 4) & 07) + 1;
2024-01-03 12:26:08 +01:00
#ifdef _PAD_TRACE_
fprintf (stderr, "segment %d\n", segmentno);
#endif
2024-01-02 12:52:57 +01:00
}
2025-06-03 19:44:20 +02:00
//
// etsi TS 102 980 specifies the DL plus objects, I just let it go
// for the time being
2024-01-02 12:52:57 +01:00
if (Cflag) { // special dynamic label command
2025-06-03 19:44:20 +02:00
uint16_t Command = (prefix >> 8) & 0x0f;
switch (Command) {
case 1:
#ifdef _PAD_TRACE_
fprintf (stderr, "clear command\n");
#endif
dynamicLabelText. clear ();
segmentno = -1;
break;
case 2:
2024-01-03 12:26:08 +01:00
#ifdef _PAD_TRACE_
2025-06-03 19:44:20 +02:00
fprintf (stderr, "DL plus command\n");
2024-01-03 12:26:08 +01:00
#endif
2025-06-07 18:45:00 +02:00
if (!backgroundFlag)
add_toDL2 (&data [2]);
2025-06-03 19:44:20 +02:00
break;
default:
// fprintf (stderr, "unknown command %d\n", Command);
break;
}
2017-02-06 14:09:08 +01:00
}
else { // Dynamic text length
int16_t totalDataLength = field_1 + 1;
if (length - 2 < totalDataLength) {
dataLength = length - 2; // the length is shortened by header
moreXPad = true;
}
else {
dataLength = totalDataLength; // no more xpad app's 3
moreXPad = false;
}
// convert dynamic label
2024-12-23 13:19:21 +01:00
dynamicLabelText. append ((const char *)(&data [2]), dataLength);
2017-02-06 14:09:08 +01:00
// if at the end, show the label
if (last) {
if (!moreXPad) {
2024-12-23 13:19:21 +01:00
QString displayText =
toQStringUsingCharset (
(const char *) dynamicLabelText. data (),
(CharacterSet) charSet,
dynamicLabelText. size ());
2025-06-07 18:45:00 +02:00
if (!backgroundFlag) {
add_toDL2 (displayText);
show_label (displayText, (int)charSet);
}
2024-01-02 12:52:57 +01:00
segmentno = -1;
2017-02-06 14:09:08 +01:00
}
else
isLastSegment = true;
}
else
isLastSegment = false;
// calculate remaining data length
remainDataLength = totalDataLength - dataLength;
}
}
else
if (((CI & 037) == 03) && moreXPad) {
if (remainDataLength > length) {
dataLength = length;
remainDataLength -= length;
}
else {
dataLength = remainDataLength;
moreXPad = false;
}
2024-12-23 13:19:21 +01:00
dynamicLabelText. append ((const char *)data, dataLength);
2017-02-06 14:09:08 +01:00
if (!moreXPad && isLastSegment) {
2024-12-23 13:19:21 +01:00
QString displayText = toQStringUsingCharset
((char *)(dynamicLabelText. data()),
(CharacterSet)charSet,
dynamicLabelText. size());
2025-06-07 18:45:00 +02:00
if (!backgroundFlag) {
add_toDL2 (displayText);
show_label (displayText, (int)charSet);
}
2017-02-06 14:09:08 +01:00
}
}
}
//
2017-03-27 16:32:49 +02:00
// Called at the start of the msc datagroupfield,
// the msc_length was given by the preceding appType "1"
2025-06-09 15:04:46 +02:00
void padHandler::new_MSC_element (const std::vector<uint8_t> &data) {
2018-08-20 20:22:09 +02:00
// if (mscGroupElement) {
2019-07-08 23:30:45 +02:00
//// if (msc_dataGroupBuffer. size() < dataGroupLength)
2018-08-20 20:22:09 +02:00
//// fprintf (stderr, "short ? %d %d\n",
2019-07-08 23:30:45 +02:00
//// msc_dataGroupBuffer. size(),
2018-08-20 20:22:09 +02:00
//// dataGroupLength);
2019-07-08 23:30:45 +02:00
// msc_dataGroupBuffer. clear();
2018-08-20 20:22:09 +02:00
// build_MSC_segment (data);
// mscGroupElement = true;
2023-11-03 17:47:31 +01:00
// show_mothandling (true);
2018-08-20 20:22:09 +02:00
// }
2018-05-27 12:58:08 +02:00
2020-03-02 15:13:34 +01:00
if (data. size() >= (uint16_t)dataGroupLength) { // msc element is single item
2019-07-08 23:30:45 +02:00
msc_dataGroupBuffer. clear();
2018-05-27 12:58:08 +02:00
build_MSC_segment (data);
mscGroupElement = false;
2023-11-03 17:47:31 +01:00
show_mothandling (true);
2018-08-21 09:30:07 +02:00
// fprintf (stderr, "msc element is single\n");
2018-05-27 12:58:08 +02:00
return;
2018-05-26 21:18:22 +02:00
}
2018-05-27 12:58:08 +02:00
2018-08-20 15:22:36 +02:00
mscGroupElement = true;
2019-07-08 23:30:45 +02:00
msc_dataGroupBuffer. clear();
2018-05-27 12:58:08 +02:00
msc_dataGroupBuffer = data;
2023-11-03 17:47:31 +01:00
show_mothandling (true);
2017-03-27 16:32:49 +02:00
}
2017-02-06 14:09:08 +01:00
//
2025-06-09 15:04:46 +02:00
void padHandler::add_MSC_element (const std::vector<uint8_t> &data) {
2019-07-08 23:30:45 +02:00
int32_t currentLength = msc_dataGroupBuffer. size();
2017-03-27 16:32:49 +02:00
//
// just to ensure that, when a "12" appType is missing, the
2018-05-17 10:48:38 +02:00
// data of "13" appType elements is not endlessly collected.
2018-05-26 21:18:22 +02:00
if (currentLength == 0) {
2017-02-06 14:09:08 +01:00
return;
2018-05-26 21:18:22 +02:00
}
2017-02-06 14:09:08 +01:00
2018-01-06 19:37:34 +01:00
msc_dataGroupBuffer. insert (std::end (msc_dataGroupBuffer),
std::begin (data), std::end (data));
2020-03-02 15:13:34 +01:00
if (msc_dataGroupBuffer. size() >= (uint32_t)dataGroupLength) {
2018-05-27 12:58:08 +02:00
build_MSC_segment (msc_dataGroupBuffer);
2019-07-08 23:30:45 +02:00
msc_dataGroupBuffer. clear();
2018-08-20 20:22:09 +02:00
// mscGroupElement = false;
2023-11-03 17:47:31 +01:00
show_mothandling (false);
2017-03-27 16:32:49 +02:00
}
2017-02-06 14:09:08 +01:00
}
2025-06-09 15:04:46 +02:00
void padHandler::build_MSC_segment (const std::vector<uint8_t> &data) {
2017-02-06 14:09:08 +01:00
// we have a MOT segment, let us look what is in it
// according to DAB 300 401 (page 37) the header (MSC data group)
// is
2020-03-02 15:13:34 +01:00
int32_t size = data. size() < (uint32_t)dataGroupLength ? data. size() :
2018-05-27 13:17:14 +02:00
dataGroupLength;
2022-01-04 12:00:11 +01:00
if (size < 2) {
fprintf (stderr, "build_MSC_segment: data size < 2\n");
return;
}
2018-05-27 13:17:14 +02:00
2025-07-20 19:25:14 +02:00
const uint8_t groupType = data [0] & 0xF;
2020-03-02 15:13:34 +01:00
//uint8_t continuityIndex = (data [1] & 0xF0) >> 4;
//uint8_t repetitionIndex = data [1] & 0xF;
uint16_t transportId = 0; // default
2025-07-20 19:25:14 +02:00
int16_t segmentNumber = -1; // default
2020-03-02 15:13:34 +01:00
bool lastFlag = false; // default
uint16_t index;
2017-02-06 14:09:08 +01:00
2017-03-27 16:32:49 +02:00
if ((data [0] & 0x40) != 0) {
2019-07-08 23:30:45 +02:00
bool res = check_crc_bytes (data. data(), size - 2);
2017-02-06 14:09:08 +01:00
if (!res) {
2018-05-27 12:58:08 +02:00
// fprintf (stderr, "build_MSC_segment fails on crc check\n");
2017-02-06 14:09:08 +01:00
return;
}
2017-03-31 16:44:07 +02:00
// else
2017-04-04 14:04:25 +02:00
// fprintf (stderr, "crc success ");
2017-02-06 14:09:08 +01:00
}
2018-05-26 21:18:22 +02:00
if ((groupType != 3) && (groupType != 4)) {
// fprintf (stderr, "groupType %d\n", groupType);
2017-02-06 14:09:08 +01:00
return; // do not know yet
2018-05-26 21:18:22 +02:00
}
2017-02-06 14:09:08 +01:00
// extensionflag
2017-03-27 16:32:49 +02:00
bool extensionFlag = (data [0] & 0x80) != 0;
2017-02-06 14:09:08 +01:00
// if the segmentflag is on, then a lastflag and segmentnumber are
2018-08-20 15:22:36 +02:00
// available, i.e. 2 bytes more.
// Theoretically, the segment number can be as large as 16384
2017-02-06 14:09:08 +01:00
index = extensionFlag ? 4 : 2;
2017-03-27 16:32:49 +02:00
bool segmentFlag = (data [0] & 0x20) != 0;
2017-02-06 14:09:08 +01:00
if ((segmentFlag) != 0) {
2017-03-27 16:32:49 +02:00
lastFlag = data [index] & 0x80;
2018-08-20 15:22:36 +02:00
segmentNumber = ((data [index] & 0x7F) << 8) |
data [index + 1];
2017-02-06 14:09:08 +01:00
index += 2;
}
2017-04-04 14:04:25 +02:00
2017-02-06 14:09:08 +01:00
// if the user access flag is on there is a user accessfield
2017-03-27 16:32:49 +02:00
if ((data [0] & 0x10) != 0) {
int16_t lengthIndicator = data [index] & 0x0F;
if ((data [index] & 0x10) != 0) { //transportid flag
transportId = data [index + 1] << 8 |
data [index + 2];
2022-01-04 12:00:11 +01:00
// fprintf (stderr, "transportId = %d\n", transportId);
2017-02-06 14:09:08 +01:00
index += 3;
}
2022-01-04 12:00:11 +01:00
// else {
2018-08-07 10:31:17 +02:00
// fprintf (stderr, "sorry no transportId\n");
2022-01-04 12:00:11 +01:00
// return;
// }
2017-02-06 14:09:08 +01:00
index += (lengthIndicator - 2);
}
2017-03-27 16:32:49 +02:00
2022-01-04 12:00:11 +01:00
// if (transportId == 0) // no idea wat it means
// return;
uint32_t segmentSize = ((data [index + 0] & 0x1F) << 8) |
data [index + 1];
2022-01-04 12:00:11 +01:00
// handling MOT in the PAD, we only deal here with type 3/4
switch (groupType) {
case 3:
if (currentSlide == nullptr) {
2018-05-27 12:58:08 +02:00
// fprintf (stderr, "creating %d\n", transportId);
2025-05-27 18:50:45 +02:00
currentSlide. reset (new motObject (myRadioInterface,
2018-05-25 13:46:09 +02:00
false,
transportId,
&data [index + 2],
segmentSize,
2023-09-23 11:50:09 +02:00
lastFlag,
2025-05-27 18:50:45 +02:00
backgroundFlag));
2018-05-25 13:46:09 +02:00
}
else {
2019-07-08 23:30:45 +02:00
if (currentSlide -> get_transportId() == transportId)
2018-05-25 13:46:09 +02:00
break;
2018-05-27 12:58:08 +02:00
// fprintf (stderr, "out goes %d, in comes %d\n",
2019-07-08 23:30:45 +02:00
// currentSlide -> get_transportId(),
2018-05-27 12:58:08 +02:00
// transportId);
2025-05-27 18:50:45 +02:00
// delete currentSlide;
currentSlide. reset (new motObject (myRadioInterface,
2018-05-25 13:46:09 +02:00
false,
transportId,
&data [index + 2],
segmentSize,
2023-09-23 11:50:09 +02:00
lastFlag,
backgroundFlag
2025-05-27 18:50:45 +02:00
));
2018-05-25 13:46:09 +02:00
}
break;
case 4:
if (currentSlide == nullptr)
2018-05-26 21:18:22 +02:00
return;
2019-07-08 23:30:45 +02:00
if (currentSlide -> get_transportId() == transportId) {
2018-05-27 12:58:08 +02:00
// fprintf (stderr, "add segment %d of %d\n",
// segmentNumber, transportId);
currentSlide -> addBodySegment (&data [index + 2],
segmentNumber,
segmentSize,
lastFlag);
2018-05-27 12:58:08 +02:00
}
break;
default: // cannot happen
2025-03-02 20:15:42 +01:00
fprintf (stderr, "Not yet handled mot in pad %d (%X)\n",
groupType, transportId);
break;
}
2017-02-06 14:09:08 +01:00
}
2025-06-07 18:45:00 +02:00
void padHandler::add_toDL2 (const QString &text) {
if (the_DL2. dlsText != text) {
the_DL2. dlsText = text;
2025-07-20 19:25:14 +02:00
// fprintf (stderr, "dl2 fragment %s\n", text. toLatin1 (). data ());
2025-06-07 18:45:00 +02:00
the_DL2. valid = true; // non existent key
for (int i = 0; i < 4; i ++)
the_DL2. entity [i]. ct = 65;
}
}
2025-06-09 15:04:46 +02:00
void padHandler::add_toDL2 (const uint8_t *data) {
2025-06-07 18:45:00 +02:00
int IT = (data [0] & 0x08) >> 3;
int IR = (data [2] & 0x04) >> 2;
int NT = data [2] & 0x03;
2025-07-20 19:25:14 +02:00
if ((the_DL2. IT == IT) && (the_DL2. IR == IR))
2025-06-07 18:45:00 +02:00
return;
2025-06-09 15:04:46 +02:00
2025-07-20 19:25:14 +02:00
if (the_DL2. IT != IT) { // toggle bit changed
the_DL2. IT = IT;
// if (IR != 0)
// fprintf (stderr, "Show a message\n");
// else
// fprintf (stderr, "hide a message\n");
}
else
if (the_DL2. IR != IR) {
// if (IR == 0)
// fprintf (stderr, "Stop met de message\n");
// else
// fprintf (stderr, "Restart de message\n");
the_DL2. IR = IR;
2025-06-07 18:45:00 +02:00
}
}