1
0
mirror of https://github.com/JvanKatwijk/qt-dab.git synced 2025-10-06 16:22:41 +02:00
Files
SDR-DAB_Qt-DAB/src/backend/data/pad-handler.cpp

333 lines
9.5 KiB
C++
Raw Normal View History

2017-02-06 14:09:08 +01:00
#
/*
2017-03-23 18:32:25 +01:00
* Copyright (C) 2015 .. 2017
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
* 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
* along with SDR-J; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "pad-handler.h"
#include <cstring>
#include "radio.h"
#include "charsets.h"
#include "mot-data.h"
/**
* \class padHandler
* Handles the pad sectors passed on from mp4Processor
*/
padHandler::padHandler (RadioInterface *mr) {
myRadioInterface = mr;
connect (this, SIGNAL (showLabel (QString)),
mr, SLOT (showLabel (QString)));
my_motHandler = new motHandler (mr);
}
padHandler::~padHandler (void) {
delete my_motHandler;
}
/**
* processPad takes the AU's from the mp4processor and
* dispatches the kind of PAD info
*/
void padHandler::processPAD (uint8_t *theAU) {
uint8_t buffer [255];
int16_t count = theAU [1];
/// first we copy the data into a local buffer
memcpy (buffer, &theAU[2], theAU [1]);
//
// for now we only handle f_padType 0
uint8_t fpadType = (buffer [count - 2] >> 6) & 03;
if (fpadType != 00)
return;
//
// OK, we'll try
uint8_t x_padInd = (buffer [count - 2] >> 4) & 03;
switch (x_padInd) {
case 01 :
handle_shortPAD (buffer, count);
break;
case 02:
// uint8_t Z_bit = (buffer [count - 1] & 01);
// uint8_t CI_flag = (buffer [count - 1] >> 1) & 01;
handle_variablePAD (buffer, count,
(buffer [count - 1] >> 1) & 01);
break;
default:;
}
}
void padHandler::handle_shortPAD (uint8_t *b, int16_t count) {
uint8_t CI = b [count - 3];
uint8_t data [4];
int16_t i;
for (i = 0; i < 3; i ++)
data [i] = b [count - 4 - i];
data [3] = 0;
if ((CI & 037) == 02 || (CI & 037) == 03)
dynamicLabel (data, 3, CI);
}
///////////////////////////////////////////////////////////////////////
//
//
// 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};
void padHandler::handle_variablePAD (uint8_t *b,
int16_t count, uint8_t CI_flag) {
int16_t CI_index = 0;
uint8_t CI_table [16];
int16_t i, j;
int16_t base = count - 2 - 1; // for the F-pad
if (CI_flag == 0) // I do not understand
return;
//
// 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
while (((b [base] & 037) != 0) && CI_index < 4) {
CI_table [CI_index ++] = b [base];
base -= 1;
}
if (CI_index < 4) // we have a "0" indicator, adjust base
base -= 1;
//
for (i = 0; i < CI_index; i ++) {
uint8_t appType = CI_table [i] & 037;
int16_t length = lengthTable [CI_table [i] >> 5];
uint8_t *data = (uint8_t *)alloca (length + 1);
if (appType == 1) {
msc_dataGroupLength = ((b [base] & 077) << 8) | b [base - 1];
msc_dataGroupIndex = 0;
base -= 4;
last_appType = 1;
continue;
}
for (j = 0; j < length; j ++)
data [j] = b [base - j];
data [length] = 0;
fprintf (stderr, "pad with appType %d\n", appType);
2017-02-06 14:09:08 +01:00
switch (appType) {
// with these apptypes we need further study
default:
last_appType = appType;
return; // sorry, we do not handle this
case 2:
case 3:
dynamicLabel (data, length, CI_table [i]);
break;
case 12:
if (last_appType == 01)
add_MSC_element (data, length);
break;
case 13:
if ((last_appType == 12) || (last_appType == 13))
add_MSC_element (data, length);
break;
}
last_appType = appType;
base -= length;
if (base < 0 && i < CI_index - 1) {
fprintf (stderr, "Hier gaat het fout, base = %d\n", base);
return;
}
}
}
//
// A dynamic label is created from a sequence of (dynamic) xpad
// fields, starting with CI = 2, continuing with CI = 3
void padHandler::dynamicLabel (uint8_t *data, int16_t length, uint8_t CI) {
static int16_t segmentno = 0;
static int16_t remainDataLength = 0;
static bool isLastSegment = false;
static bool moreXPad = false;
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
if (first) {
segmentno = 1;
charSet = (prefix >> 4) & 017;
dynamicLabelText. clear ();
}
else
segmentno = (prefix >> 4) & 07 + 1;
if (Cflag) { // special dynamic label command
// the only specified command is to clear the display
dynamicLabelText. clear ();
}
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
QString segmentText = toQStringUsingCharset (
(const char *)&data [2],
(CharacterSet) charSet,
dataLength);
dynamicLabelText. append (segmentText);
// if at the end, show the label
if (last) {
if (!moreXPad) {
showLabel (dynamicLabelText);
}
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;
}
QString segmentText = toQStringUsingCharset (
(const char *) data,
(CharacterSet) charSet,
dataLength);
dynamicLabelText. append(segmentText);
if (!moreXPad && isLastSegment) {
showLabel (dynamicLabelText);
}
}
}
//
// building an MSC segment by integrating the elements sent per XPAD
//
void padHandler::add_MSC_element (uint8_t *data, int16_t length) {
int16_t i;
if (msc_dataGroupIndex < 0)
return;
if (length < 0)
return;
if (msc_dataGroupIndex + length >= 8192) // just ignore
return;
for (i = 0; i < length; i ++)
msc_dataGroupBuffer [msc_dataGroupIndex ++] = data [i];
if (msc_dataGroupIndex < msc_dataGroupLength)
return;
build_MSC_segment (msc_dataGroupBuffer, msc_dataGroupLength);
msc_dataGroupIndex = 0;
}
void padHandler::build_MSC_segment (uint8_t *mscdataGroup, int16_t length) {
// 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
uint8_t groupType = mscdataGroup [0] & 0xF;
uint8_t continuityIndex = (mscdataGroup [1] & 0xF) >> 4;
uint8_t repetitionIndex = mscdataGroup [1] & 0xF;
int16_t segmentNumber = -1; // default
int16_t transportId = -1; // default
bool lastFlag = false; // default
uint16_t index;
if ((mscdataGroup [0] & 0x40) != 0) {
bool res = check_crc_bytes (mscdataGroup, length - 2);
if (!res) {
// fprintf (stderr, "crc failed\n");
return;
}
}
if ((groupType != 3) && (groupType != 4))
return; // do not know yet
//
// extensionflag
bool extensionFlag = (mscdataGroup [0] & 0x80) != 0;
// if the segmentflag is on, then a lastflag and segmentnumber are
// available, i.e. 2 bytes more
index = extensionFlag ? 4 : 2;
bool segmentFlag = (mscdataGroup [0] & 0x20) != 0;
if ((segmentFlag) != 0) {
lastFlag = mscdataGroup [index] & 0x80;
segmentNumber = ((mscdataGroup [index] & 0x7F) << 8) |
mscdataGroup [index + 1];
index += 2;
}
//
// if the user access flag is on there is a user accessfield
if ((mscdataGroup [0] & 0x10) != 0) {
int16_t lengthIndicator = mscdataGroup [index] & 0x0F;
if ((mscdataGroup [index] & 0x10) != 0) { //transportid flag
transportId = mscdataGroup [index + 1] << 8 |
mscdataGroup [index + 2];
index += 3;
}
else {
fprintf (stderr, "sorry no transportId\n");
return;
}
index += (lengthIndicator - 2);
}
//
// the segment is handled by the mot handler
my_motHandler -> process_mscGroup (&mscdataGroup [index],
groupType,
lastFlag,
segmentNumber,
transportId);
}
//