You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1096 lines
40 KiB
1096 lines
40 KiB
/*
|
|
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* 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.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* 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 this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "CCITTChecksumReverse.h"
|
|
#include "SoundCardController.h"
|
|
#include "DStarDefines.h"
|
|
|
|
// #define AUDIO_LOOPBACK
|
|
|
|
const unsigned int BUFFER_LENGTH = 200U;
|
|
|
|
const unsigned int NIBBLE_BITS[] = {0U, 1U, 1U, 2U, 1U, 2U, 2U, 3U, 1U, 2U, 2U, 3U, 2U, 3U, 3U, 4U};
|
|
|
|
const unsigned int DV_FRAME_LENGTH_BITS = DV_FRAME_LENGTH_BYTES * 8U;
|
|
|
|
const unsigned int MAX_SYNC_BITS = 50U * DV_FRAME_LENGTH_BITS;
|
|
|
|
const unsigned int FEC_SECTION_LENGTH_BITS = 660U;
|
|
|
|
// D-Star bit order version of 0x55 0x55 0x6E 0x0A
|
|
const wxUint32 FRAME_SYNC_DATA = 0x00557650U;
|
|
const wxUint32 FRAME_SYNC_MASK = 0x00FFFFFFU;
|
|
const unsigned int FRAME_SYNC_ERRS = 2U;
|
|
|
|
// D-Star bit order version of 0x55 0x2D 0x16
|
|
const wxUint32 DATA_SYNC_DATA = 0x00AAB468U;
|
|
const wxUint32 DATA_SYNC_MASK = 0x00FFFFFFU;
|
|
const unsigned int DATA_SYNC_ERRS = 2U;
|
|
|
|
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
|
|
const wxUint32 END_SYNC_DATA = 0xAAAA135EU;
|
|
const wxUint32 END_SYNC_MASK = 0xFFFFFFFFU;
|
|
const unsigned int END_SYNC_ERRS = 3U;
|
|
|
|
const unsigned char BIT_SYNC = 0xAAU;
|
|
|
|
const unsigned char FRAME_SYNC0 = 0xEAU;
|
|
const unsigned char FRAME_SYNC1 = 0xA6U;
|
|
const unsigned char FRAME_SYNC2 = 0x00U;
|
|
|
|
const unsigned char BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU};
|
|
const unsigned char BIT_MASK_TABLE1[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
|
|
const unsigned char BIT_MASK_TABLE2[] = {0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU};
|
|
const unsigned char BIT_MASK_TABLE3[] = {0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U};
|
|
|
|
#define WRITE_BIT1(p,i,b) p[(i)/8] = (b) ? (p[(i)/8] | BIT_MASK_TABLE1[(i)%8]) : (p[(i)/8] & BIT_MASK_TABLE0[(i)%8])
|
|
#define READ_BIT1(p,i) (p[(i)/8] & BIT_MASK_TABLE1[(i)%8])
|
|
|
|
#define WRITE_BIT2(p,i,b) p[(i)/8] = (b) ? (p[(i)/8] | BIT_MASK_TABLE3[(i)%8]) : (p[(i)/8] & BIT_MASK_TABLE2[(i)%8])
|
|
#define READ_BIT2(p,i) (p[(i)/8] & BIT_MASK_TABLE3[(i)%8])
|
|
|
|
const unsigned char INTERLEAVE_TABLE_TX[] = {
|
|
0x00U, 0x04U, 0x04U, 0x00U, 0x07U, 0x04U, 0x0BU, 0x00U, 0x0EU, 0x04U,
|
|
0x12U, 0x00U, 0x15U, 0x04U, 0x19U, 0x00U, 0x1CU, 0x04U, 0x20U, 0x00U,
|
|
0x23U, 0x04U, 0x27U, 0x00U, 0x2AU, 0x04U, 0x2DU, 0x07U, 0x31U, 0x02U,
|
|
0x34U, 0x05U, 0x38U, 0x00U, 0x3BU, 0x03U, 0x3EU, 0x06U, 0x42U, 0x01U,
|
|
0x45U, 0x04U, 0x48U, 0x07U, 0x4CU, 0x02U, 0x4FU, 0x05U, 0x00U, 0x05U,
|
|
0x04U, 0x01U, 0x07U, 0x05U, 0x0BU, 0x01U, 0x0EU, 0x05U, 0x12U, 0x01U,
|
|
0x15U, 0x05U, 0x19U, 0x01U, 0x1CU, 0x05U, 0x20U, 0x01U, 0x23U, 0x05U,
|
|
0x27U, 0x01U, 0x2AU, 0x05U, 0x2EU, 0x00U, 0x31U, 0x03U, 0x34U, 0x06U,
|
|
0x38U, 0x01U, 0x3BU, 0x04U, 0x3EU, 0x07U, 0x42U, 0x02U, 0x45U, 0x05U,
|
|
0x49U, 0x00U, 0x4CU, 0x03U, 0x4FU, 0x06U, 0x00U, 0x06U, 0x04U, 0x02U,
|
|
0x07U, 0x06U, 0x0BU, 0x02U, 0x0EU, 0x06U, 0x12U, 0x02U, 0x15U, 0x06U,
|
|
0x19U, 0x02U, 0x1CU, 0x06U, 0x20U, 0x02U, 0x23U, 0x06U, 0x27U, 0x02U,
|
|
0x2AU, 0x06U, 0x2EU, 0x01U, 0x31U, 0x04U, 0x34U, 0x07U, 0x38U, 0x02U,
|
|
0x3BU, 0x05U, 0x3FU, 0x00U, 0x42U, 0x03U, 0x45U, 0x06U, 0x49U, 0x01U,
|
|
0x4CU, 0x04U, 0x4FU, 0x07U, 0x00U, 0x07U, 0x04U, 0x03U, 0x07U, 0x07U,
|
|
0x0BU, 0x03U, 0x0EU, 0x07U, 0x12U, 0x03U, 0x15U, 0x07U, 0x19U, 0x03U,
|
|
0x1CU, 0x07U, 0x20U, 0x03U, 0x23U, 0x07U, 0x27U, 0x03U, 0x2AU, 0x07U,
|
|
0x2EU, 0x02U, 0x31U, 0x05U, 0x35U, 0x00U, 0x38U, 0x03U, 0x3BU, 0x06U,
|
|
0x3FU, 0x01U, 0x42U, 0x04U, 0x45U, 0x07U, 0x49U, 0x02U, 0x4CU, 0x05U,
|
|
0x50U, 0x00U, 0x01U, 0x00U, 0x04U, 0x04U, 0x08U, 0x00U, 0x0BU, 0x04U,
|
|
0x0FU, 0x00U, 0x12U, 0x04U, 0x16U, 0x00U, 0x19U, 0x04U, 0x1DU, 0x00U,
|
|
0x20U, 0x04U, 0x24U, 0x00U, 0x27U, 0x04U, 0x2BU, 0x00U, 0x2EU, 0x03U,
|
|
0x31U, 0x06U, 0x35U, 0x01U, 0x38U, 0x04U, 0x3BU, 0x07U, 0x3FU, 0x02U,
|
|
0x42U, 0x05U, 0x46U, 0x00U, 0x49U, 0x03U, 0x4CU, 0x06U, 0x50U, 0x01U,
|
|
0x01U, 0x01U, 0x04U, 0x05U, 0x08U, 0x01U, 0x0BU, 0x05U, 0x0FU, 0x01U,
|
|
0x12U, 0x05U, 0x16U, 0x01U, 0x19U, 0x05U, 0x1DU, 0x01U, 0x20U, 0x05U,
|
|
0x24U, 0x01U, 0x27U, 0x05U, 0x2BU, 0x01U, 0x2EU, 0x04U, 0x31U, 0x07U,
|
|
0x35U, 0x02U, 0x38U, 0x05U, 0x3CU, 0x00U, 0x3FU, 0x03U, 0x42U, 0x06U,
|
|
0x46U, 0x01U, 0x49U, 0x04U, 0x4CU, 0x07U, 0x50U, 0x02U, 0x01U, 0x02U,
|
|
0x04U, 0x06U, 0x08U, 0x02U, 0x0BU, 0x06U, 0x0FU, 0x02U, 0x12U, 0x06U,
|
|
0x16U, 0x02U, 0x19U, 0x06U, 0x1DU, 0x02U, 0x20U, 0x06U, 0x24U, 0x02U,
|
|
0x27U, 0x06U, 0x2BU, 0x02U, 0x2EU, 0x05U, 0x32U, 0x00U, 0x35U, 0x03U,
|
|
0x38U, 0x06U, 0x3CU, 0x01U, 0x3FU, 0x04U, 0x42U, 0x07U, 0x46U, 0x02U,
|
|
0x49U, 0x05U, 0x4DU, 0x00U, 0x50U, 0x03U, 0x01U, 0x03U, 0x04U, 0x07U,
|
|
0x08U, 0x03U, 0x0BU, 0x07U, 0x0FU, 0x03U, 0x12U, 0x07U, 0x16U, 0x03U,
|
|
0x19U, 0x07U, 0x1DU, 0x03U, 0x20U, 0x07U, 0x24U, 0x03U, 0x27U, 0x07U,
|
|
0x2BU, 0x03U, 0x2EU, 0x06U, 0x32U, 0x01U, 0x35U, 0x04U, 0x38U, 0x07U,
|
|
0x3CU, 0x02U, 0x3FU, 0x05U, 0x43U, 0x00U, 0x46U, 0x03U, 0x49U, 0x06U,
|
|
0x4DU, 0x01U, 0x50U, 0x04U, 0x01U, 0x04U, 0x05U, 0x00U, 0x08U, 0x04U,
|
|
0x0CU, 0x00U, 0x0FU, 0x04U, 0x13U, 0x00U, 0x16U, 0x04U, 0x1AU, 0x00U,
|
|
0x1DU, 0x04U, 0x21U, 0x00U, 0x24U, 0x04U, 0x28U, 0x00U, 0x2BU, 0x04U,
|
|
0x2EU, 0x07U, 0x32U, 0x02U, 0x35U, 0x05U, 0x39U, 0x00U, 0x3CU, 0x03U,
|
|
0x3FU, 0x06U, 0x43U, 0x01U, 0x46U, 0x04U, 0x49U, 0x07U, 0x4DU, 0x02U,
|
|
0x50U, 0x05U, 0x01U, 0x05U, 0x05U, 0x01U, 0x08U, 0x05U, 0x0CU, 0x01U,
|
|
0x0FU, 0x05U, 0x13U, 0x01U, 0x16U, 0x05U, 0x1AU, 0x01U, 0x1DU, 0x05U,
|
|
0x21U, 0x01U, 0x24U, 0x05U, 0x28U, 0x01U, 0x2BU, 0x05U, 0x2FU, 0x00U,
|
|
0x32U, 0x03U, 0x35U, 0x06U, 0x39U, 0x01U, 0x3CU, 0x04U, 0x3FU, 0x07U,
|
|
0x43U, 0x02U, 0x46U, 0x05U, 0x4AU, 0x00U, 0x4DU, 0x03U, 0x50U, 0x06U,
|
|
0x01U, 0x06U, 0x05U, 0x02U, 0x08U, 0x06U, 0x0CU, 0x02U, 0x0FU, 0x06U,
|
|
0x13U, 0x02U, 0x16U, 0x06U, 0x1AU, 0x02U, 0x1DU, 0x06U, 0x21U, 0x02U,
|
|
0x24U, 0x06U, 0x28U, 0x02U, 0x2BU, 0x06U, 0x2FU, 0x01U, 0x32U, 0x04U,
|
|
0x35U, 0x07U, 0x39U, 0x02U, 0x3CU, 0x05U, 0x40U, 0x00U, 0x43U, 0x03U,
|
|
0x46U, 0x06U, 0x4AU, 0x01U, 0x4DU, 0x04U, 0x50U, 0x07U, 0x01U, 0x07U,
|
|
0x05U, 0x03U, 0x08U, 0x07U, 0x0CU, 0x03U, 0x0FU, 0x07U, 0x13U, 0x03U,
|
|
0x16U, 0x07U, 0x1AU, 0x03U, 0x1DU, 0x07U, 0x21U, 0x03U, 0x24U, 0x07U,
|
|
0x28U, 0x03U, 0x2BU, 0x07U, 0x2FU, 0x02U, 0x32U, 0x05U, 0x36U, 0x00U,
|
|
0x39U, 0x03U, 0x3CU, 0x06U, 0x40U, 0x01U, 0x43U, 0x04U, 0x46U, 0x07U,
|
|
0x4AU, 0x02U, 0x4DU, 0x05U, 0x51U, 0x00U, 0x02U, 0x00U, 0x05U, 0x04U,
|
|
0x09U, 0x00U, 0x0CU, 0x04U, 0x10U, 0x00U, 0x13U, 0x04U, 0x17U, 0x00U,
|
|
0x1AU, 0x04U, 0x1EU, 0x00U, 0x21U, 0x04U, 0x25U, 0x00U, 0x28U, 0x04U,
|
|
0x2CU, 0x00U, 0x2FU, 0x03U, 0x32U, 0x06U, 0x36U, 0x01U, 0x39U, 0x04U,
|
|
0x3CU, 0x07U, 0x40U, 0x02U, 0x43U, 0x05U, 0x47U, 0x00U, 0x4AU, 0x03U,
|
|
0x4DU, 0x06U, 0x51U, 0x01U, 0x02U, 0x01U, 0x05U, 0x05U, 0x09U, 0x01U,
|
|
0x0CU, 0x05U, 0x10U, 0x01U, 0x13U, 0x05U, 0x17U, 0x01U, 0x1AU, 0x05U,
|
|
0x1EU, 0x01U, 0x21U, 0x05U, 0x25U, 0x01U, 0x28U, 0x05U, 0x2CU, 0x01U,
|
|
0x2FU, 0x04U, 0x32U, 0x07U, 0x36U, 0x02U, 0x39U, 0x05U, 0x3DU, 0x00U,
|
|
0x40U, 0x03U, 0x43U, 0x06U, 0x47U, 0x01U, 0x4AU, 0x04U, 0x4DU, 0x07U,
|
|
0x51U, 0x02U, 0x02U, 0x02U, 0x05U, 0x06U, 0x09U, 0x02U, 0x0CU, 0x06U,
|
|
0x10U, 0x02U, 0x13U, 0x06U, 0x17U, 0x02U, 0x1AU, 0x06U, 0x1EU, 0x02U,
|
|
0x21U, 0x06U, 0x25U, 0x02U, 0x28U, 0x06U, 0x2CU, 0x02U, 0x2FU, 0x05U,
|
|
0x33U, 0x00U, 0x36U, 0x03U, 0x39U, 0x06U, 0x3DU, 0x01U, 0x40U, 0x04U,
|
|
0x43U, 0x07U, 0x47U, 0x02U, 0x4AU, 0x05U, 0x4EU, 0x00U, 0x51U, 0x03U,
|
|
0x02U, 0x03U, 0x05U, 0x07U, 0x09U, 0x03U, 0x0CU, 0x07U, 0x10U, 0x03U,
|
|
0x13U, 0x07U, 0x17U, 0x03U, 0x1AU, 0x07U, 0x1EU, 0x03U, 0x21U, 0x07U,
|
|
0x25U, 0x03U, 0x28U, 0x07U, 0x2CU, 0x03U, 0x2FU, 0x06U, 0x33U, 0x01U,
|
|
0x36U, 0x04U, 0x39U, 0x07U, 0x3DU, 0x02U, 0x40U, 0x05U, 0x44U, 0x00U,
|
|
0x47U, 0x03U, 0x4AU, 0x06U, 0x4EU, 0x01U, 0x51U, 0x04U, 0x02U, 0x04U,
|
|
0x06U, 0x00U, 0x09U, 0x04U, 0x0DU, 0x00U, 0x10U, 0x04U, 0x14U, 0x00U,
|
|
0x17U, 0x04U, 0x1BU, 0x00U, 0x1EU, 0x04U, 0x22U, 0x00U, 0x25U, 0x04U,
|
|
0x29U, 0x00U, 0x2CU, 0x04U, 0x2FU, 0x07U, 0x33U, 0x02U, 0x36U, 0x05U,
|
|
0x3AU, 0x00U, 0x3DU, 0x03U, 0x40U, 0x06U, 0x44U, 0x01U, 0x47U, 0x04U,
|
|
0x4AU, 0x07U, 0x4EU, 0x02U, 0x51U, 0x05U, 0x02U, 0x05U, 0x06U, 0x01U,
|
|
0x09U, 0x05U, 0x0DU, 0x01U, 0x10U, 0x05U, 0x14U, 0x01U, 0x17U, 0x05U,
|
|
0x1BU, 0x01U, 0x1EU, 0x05U, 0x22U, 0x01U, 0x25U, 0x05U, 0x29U, 0x01U,
|
|
0x2CU, 0x05U, 0x30U, 0x00U, 0x33U, 0x03U, 0x36U, 0x06U, 0x3AU, 0x01U,
|
|
0x3DU, 0x04U, 0x40U, 0x07U, 0x44U, 0x02U, 0x47U, 0x05U, 0x4BU, 0x00U,
|
|
0x4EU, 0x03U, 0x51U, 0x06U, 0x02U, 0x06U, 0x06U, 0x02U, 0x09U, 0x06U,
|
|
0x0DU, 0x02U, 0x10U, 0x06U, 0x14U, 0x02U, 0x17U, 0x06U, 0x1BU, 0x02U,
|
|
0x1EU, 0x06U, 0x22U, 0x02U, 0x25U, 0x06U, 0x29U, 0x02U, 0x2CU, 0x06U,
|
|
0x30U, 0x01U, 0x33U, 0x04U, 0x36U, 0x07U, 0x3AU, 0x02U, 0x3DU, 0x05U,
|
|
0x41U, 0x00U, 0x44U, 0x03U, 0x47U, 0x06U, 0x4BU, 0x01U, 0x4EU, 0x04U,
|
|
0x51U, 0x07U, 0x02U, 0x07U, 0x06U, 0x03U, 0x09U, 0x07U, 0x0DU, 0x03U,
|
|
0x10U, 0x07U, 0x14U, 0x03U, 0x17U, 0x07U, 0x1BU, 0x03U, 0x1EU, 0x07U,
|
|
0x22U, 0x03U, 0x25U, 0x07U, 0x29U, 0x03U, 0x2CU, 0x07U, 0x30U, 0x02U,
|
|
0x33U, 0x05U, 0x37U, 0x00U, 0x3AU, 0x03U, 0x3DU, 0x06U, 0x41U, 0x01U,
|
|
0x44U, 0x04U, 0x47U, 0x07U, 0x4BU, 0x02U, 0x4EU, 0x05U, 0x52U, 0x00U,
|
|
0x03U, 0x00U, 0x06U, 0x04U, 0x0AU, 0x00U, 0x0DU, 0x04U, 0x11U, 0x00U,
|
|
0x14U, 0x04U, 0x18U, 0x00U, 0x1BU, 0x04U, 0x1FU, 0x00U, 0x22U, 0x04U,
|
|
0x26U, 0x00U, 0x29U, 0x04U, 0x2DU, 0x00U, 0x30U, 0x03U, 0x33U, 0x06U,
|
|
0x37U, 0x01U, 0x3AU, 0x04U, 0x3DU, 0x07U, 0x41U, 0x02U, 0x44U, 0x05U,
|
|
0x48U, 0x00U, 0x4BU, 0x03U, 0x4EU, 0x06U, 0x52U, 0x01U, 0x03U, 0x01U,
|
|
0x06U, 0x05U, 0x0AU, 0x01U, 0x0DU, 0x05U, 0x11U, 0x01U, 0x14U, 0x05U,
|
|
0x18U, 0x01U, 0x1BU, 0x05U, 0x1FU, 0x01U, 0x22U, 0x05U, 0x26U, 0x01U,
|
|
0x29U, 0x05U, 0x2DU, 0x01U, 0x30U, 0x04U, 0x33U, 0x07U, 0x37U, 0x02U,
|
|
0x3AU, 0x05U, 0x3EU, 0x00U, 0x41U, 0x03U, 0x44U, 0x06U, 0x48U, 0x01U,
|
|
0x4BU, 0x04U, 0x4EU, 0x07U, 0x52U, 0x02U, 0x03U, 0x02U, 0x06U, 0x06U,
|
|
0x0AU, 0x02U, 0x0DU, 0x06U, 0x11U, 0x02U, 0x14U, 0x06U, 0x18U, 0x02U,
|
|
0x1BU, 0x06U, 0x1FU, 0x02U, 0x22U, 0x06U, 0x26U, 0x02U, 0x29U, 0x06U,
|
|
0x2DU, 0x02U, 0x30U, 0x05U, 0x34U, 0x00U, 0x37U, 0x03U, 0x3AU, 0x06U,
|
|
0x3EU, 0x01U, 0x41U, 0x04U, 0x44U, 0x07U, 0x48U, 0x02U, 0x4BU, 0x05U,
|
|
0x4FU, 0x00U, 0x52U, 0x03U, 0x03U, 0x03U, 0x06U, 0x07U, 0x0AU, 0x03U,
|
|
0x0DU, 0x07U, 0x11U, 0x03U, 0x14U, 0x07U, 0x18U, 0x03U, 0x1BU, 0x07U,
|
|
0x1FU, 0x03U, 0x22U, 0x07U, 0x26U, 0x03U, 0x29U, 0x07U, 0x2DU, 0x03U,
|
|
0x30U, 0x06U, 0x34U, 0x01U, 0x37U, 0x04U, 0x3AU, 0x07U, 0x3EU, 0x02U,
|
|
0x41U, 0x05U, 0x45U, 0x00U, 0x48U, 0x03U, 0x4BU, 0x06U, 0x4FU, 0x01U,
|
|
0x52U, 0x04U, 0x03U, 0x04U, 0x07U, 0x00U, 0x0AU, 0x04U, 0x0EU, 0x00U,
|
|
0x11U, 0x04U, 0x15U, 0x00U, 0x18U, 0x04U, 0x1CU, 0x00U, 0x1FU, 0x04U,
|
|
0x23U, 0x00U, 0x26U, 0x04U, 0x2AU, 0x00U, 0x2DU, 0x04U, 0x30U, 0x07U,
|
|
0x34U, 0x02U, 0x37U, 0x05U, 0x3BU, 0x00U, 0x3EU, 0x03U, 0x41U, 0x06U,
|
|
0x45U, 0x01U, 0x48U, 0x04U, 0x4BU, 0x07U, 0x4FU, 0x02U, 0x52U, 0x05U,
|
|
0x03U, 0x05U, 0x07U, 0x01U, 0x0AU, 0x05U, 0x0EU, 0x01U, 0x11U, 0x05U,
|
|
0x15U, 0x01U, 0x18U, 0x05U, 0x1CU, 0x01U, 0x1FU, 0x05U, 0x23U, 0x01U,
|
|
0x26U, 0x05U, 0x2AU, 0x01U, 0x2DU, 0x05U, 0x31U, 0x00U, 0x34U, 0x03U,
|
|
0x37U, 0x06U, 0x3BU, 0x01U, 0x3EU, 0x04U, 0x41U, 0x07U, 0x45U, 0x02U,
|
|
0x48U, 0x05U, 0x4CU, 0x00U, 0x4FU, 0x03U, 0x52U, 0x06U, 0x03U, 0x06U,
|
|
0x07U, 0x02U, 0x0AU, 0x06U, 0x0EU, 0x02U, 0x11U, 0x06U, 0x15U, 0x02U,
|
|
0x18U, 0x06U, 0x1CU, 0x02U, 0x1FU, 0x06U, 0x23U, 0x02U, 0x26U, 0x06U,
|
|
0x2AU, 0x02U, 0x2DU, 0x06U, 0x31U, 0x01U, 0x34U, 0x04U, 0x37U, 0x07U,
|
|
0x3BU, 0x02U, 0x3EU, 0x05U, 0x42U, 0x00U, 0x45U, 0x03U, 0x48U, 0x06U,
|
|
0x4CU, 0x01U, 0x4FU, 0x04U, 0x52U, 0x07U, 0x03U, 0x07U, 0x07U, 0x03U,
|
|
0x0AU, 0x07U, 0x0EU, 0x03U, 0x11U, 0x07U, 0x15U, 0x03U, 0x18U, 0x07U,
|
|
0x1CU, 0x03U, 0x1FU, 0x07U, 0x23U, 0x03U, 0x26U, 0x07U, 0x2AU, 0x03U
|
|
};
|
|
|
|
const unsigned char INTERLEAVE_TABLE_RX[] = {
|
|
0x00U, 0x00U, 0x03U, 0x00U, 0x06U, 0x00U, 0x09U, 0x00U, 0x0CU, 0x00U,
|
|
0x0FU, 0x00U, 0x12U, 0x00U, 0x15U, 0x00U, 0x18U, 0x00U, 0x1BU, 0x00U,
|
|
0x1EU, 0x00U, 0x21U, 0x00U, 0x24U, 0x00U, 0x27U, 0x00U, 0x2AU, 0x00U,
|
|
0x2DU, 0x00U, 0x30U, 0x00U, 0x33U, 0x00U, 0x36U, 0x00U, 0x39U, 0x00U,
|
|
0x3CU, 0x00U, 0x3FU, 0x00U, 0x42U, 0x00U, 0x45U, 0x00U, 0x48U, 0x00U,
|
|
0x4BU, 0x00U, 0x4EU, 0x00U, 0x51U, 0x00U, 0x00U, 0x01U, 0x03U, 0x01U,
|
|
0x06U, 0x01U, 0x09U, 0x01U, 0x0CU, 0x01U, 0x0FU, 0x01U, 0x12U, 0x01U,
|
|
0x15U, 0x01U, 0x18U, 0x01U, 0x1BU, 0x01U, 0x1EU, 0x01U, 0x21U, 0x01U,
|
|
0x24U, 0x01U, 0x27U, 0x01U, 0x2AU, 0x01U, 0x2DU, 0x01U, 0x30U, 0x01U,
|
|
0x33U, 0x01U, 0x36U, 0x01U, 0x39U, 0x01U, 0x3CU, 0x01U, 0x3FU, 0x01U,
|
|
0x42U, 0x01U, 0x45U, 0x01U, 0x48U, 0x01U, 0x4BU, 0x01U, 0x4EU, 0x01U,
|
|
0x51U, 0x01U, 0x00U, 0x02U, 0x03U, 0x02U, 0x06U, 0x02U, 0x09U, 0x02U,
|
|
0x0CU, 0x02U, 0x0FU, 0x02U, 0x12U, 0x02U, 0x15U, 0x02U, 0x18U, 0x02U,
|
|
0x1BU, 0x02U, 0x1EU, 0x02U, 0x21U, 0x02U, 0x24U, 0x02U, 0x27U, 0x02U,
|
|
0x2AU, 0x02U, 0x2DU, 0x02U, 0x30U, 0x02U, 0x33U, 0x02U, 0x36U, 0x02U,
|
|
0x39U, 0x02U, 0x3CU, 0x02U, 0x3FU, 0x02U, 0x42U, 0x02U, 0x45U, 0x02U,
|
|
0x48U, 0x02U, 0x4BU, 0x02U, 0x4EU, 0x02U, 0x51U, 0x02U, 0x00U, 0x03U,
|
|
0x03U, 0x03U, 0x06U, 0x03U, 0x09U, 0x03U, 0x0CU, 0x03U, 0x0FU, 0x03U,
|
|
0x12U, 0x03U, 0x15U, 0x03U, 0x18U, 0x03U, 0x1BU, 0x03U, 0x1EU, 0x03U,
|
|
0x21U, 0x03U, 0x24U, 0x03U, 0x27U, 0x03U, 0x2AU, 0x03U, 0x2DU, 0x03U,
|
|
0x30U, 0x03U, 0x33U, 0x03U, 0x36U, 0x03U, 0x39U, 0x03U, 0x3CU, 0x03U,
|
|
0x3FU, 0x03U, 0x42U, 0x03U, 0x45U, 0x03U, 0x48U, 0x03U, 0x4BU, 0x03U,
|
|
0x4EU, 0x03U, 0x51U, 0x03U, 0x00U, 0x04U, 0x03U, 0x04U, 0x06U, 0x04U,
|
|
0x09U, 0x04U, 0x0CU, 0x04U, 0x0FU, 0x04U, 0x12U, 0x04U, 0x15U, 0x04U,
|
|
0x18U, 0x04U, 0x1BU, 0x04U, 0x1EU, 0x04U, 0x21U, 0x04U, 0x24U, 0x04U,
|
|
0x27U, 0x04U, 0x2AU, 0x04U, 0x2DU, 0x04U, 0x30U, 0x04U, 0x33U, 0x04U,
|
|
0x36U, 0x04U, 0x39U, 0x04U, 0x3CU, 0x04U, 0x3FU, 0x04U, 0x42U, 0x04U,
|
|
0x45U, 0x04U, 0x48U, 0x04U, 0x4BU, 0x04U, 0x4EU, 0x04U, 0x51U, 0x04U,
|
|
0x00U, 0x05U, 0x03U, 0x05U, 0x06U, 0x05U, 0x09U, 0x05U, 0x0CU, 0x05U,
|
|
0x0FU, 0x05U, 0x12U, 0x05U, 0x15U, 0x05U, 0x18U, 0x05U, 0x1BU, 0x05U,
|
|
0x1EU, 0x05U, 0x21U, 0x05U, 0x24U, 0x05U, 0x27U, 0x05U, 0x2AU, 0x05U,
|
|
0x2DU, 0x05U, 0x30U, 0x05U, 0x33U, 0x05U, 0x36U, 0x05U, 0x39U, 0x05U,
|
|
0x3CU, 0x05U, 0x3FU, 0x05U, 0x42U, 0x05U, 0x45U, 0x05U, 0x48U, 0x05U,
|
|
0x4BU, 0x05U, 0x4EU, 0x05U, 0x51U, 0x05U, 0x00U, 0x06U, 0x03U, 0x06U,
|
|
0x06U, 0x06U, 0x09U, 0x06U, 0x0CU, 0x06U, 0x0FU, 0x06U, 0x12U, 0x06U,
|
|
0x15U, 0x06U, 0x18U, 0x06U, 0x1BU, 0x06U, 0x1EU, 0x06U, 0x21U, 0x06U,
|
|
0x24U, 0x06U, 0x27U, 0x06U, 0x2AU, 0x06U, 0x2DU, 0x06U, 0x30U, 0x06U,
|
|
0x33U, 0x06U, 0x36U, 0x06U, 0x39U, 0x06U, 0x3CU, 0x06U, 0x3FU, 0x06U,
|
|
0x42U, 0x06U, 0x45U, 0x06U, 0x48U, 0x06U, 0x4BU, 0x06U, 0x4EU, 0x06U,
|
|
0x51U, 0x06U, 0x00U, 0x07U, 0x03U, 0x07U, 0x06U, 0x07U, 0x09U, 0x07U,
|
|
0x0CU, 0x07U, 0x0FU, 0x07U, 0x12U, 0x07U, 0x15U, 0x07U, 0x18U, 0x07U,
|
|
0x1BU, 0x07U, 0x1EU, 0x07U, 0x21U, 0x07U, 0x24U, 0x07U, 0x27U, 0x07U,
|
|
0x2AU, 0x07U, 0x2DU, 0x07U, 0x30U, 0x07U, 0x33U, 0x07U, 0x36U, 0x07U,
|
|
0x39U, 0x07U, 0x3CU, 0x07U, 0x3FU, 0x07U, 0x42U, 0x07U, 0x45U, 0x07U,
|
|
0x48U, 0x07U, 0x4BU, 0x07U, 0x4EU, 0x07U, 0x51U, 0x07U, 0x01U, 0x00U,
|
|
0x04U, 0x00U, 0x07U, 0x00U, 0x0AU, 0x00U, 0x0DU, 0x00U, 0x10U, 0x00U,
|
|
0x13U, 0x00U, 0x16U, 0x00U, 0x19U, 0x00U, 0x1CU, 0x00U, 0x1FU, 0x00U,
|
|
0x22U, 0x00U, 0x25U, 0x00U, 0x28U, 0x00U, 0x2BU, 0x00U, 0x2EU, 0x00U,
|
|
0x31U, 0x00U, 0x34U, 0x00U, 0x37U, 0x00U, 0x3AU, 0x00U, 0x3DU, 0x00U,
|
|
0x40U, 0x00U, 0x43U, 0x00U, 0x46U, 0x00U, 0x49U, 0x00U, 0x4CU, 0x00U,
|
|
0x4FU, 0x00U, 0x52U, 0x00U, 0x01U, 0x01U, 0x04U, 0x01U, 0x07U, 0x01U,
|
|
0x0AU, 0x01U, 0x0DU, 0x01U, 0x10U, 0x01U, 0x13U, 0x01U, 0x16U, 0x01U,
|
|
0x19U, 0x01U, 0x1CU, 0x01U, 0x1FU, 0x01U, 0x22U, 0x01U, 0x25U, 0x01U,
|
|
0x28U, 0x01U, 0x2BU, 0x01U, 0x2EU, 0x01U, 0x31U, 0x01U, 0x34U, 0x01U,
|
|
0x37U, 0x01U, 0x3AU, 0x01U, 0x3DU, 0x01U, 0x40U, 0x01U, 0x43U, 0x01U,
|
|
0x46U, 0x01U, 0x49U, 0x01U, 0x4CU, 0x01U, 0x4FU, 0x01U, 0x52U, 0x01U,
|
|
0x01U, 0x02U, 0x04U, 0x02U, 0x07U, 0x02U, 0x0AU, 0x02U, 0x0DU, 0x02U,
|
|
0x10U, 0x02U, 0x13U, 0x02U, 0x16U, 0x02U, 0x19U, 0x02U, 0x1CU, 0x02U,
|
|
0x1FU, 0x02U, 0x22U, 0x02U, 0x25U, 0x02U, 0x28U, 0x02U, 0x2BU, 0x02U,
|
|
0x2EU, 0x02U, 0x31U, 0x02U, 0x34U, 0x02U, 0x37U, 0x02U, 0x3AU, 0x02U,
|
|
0x3DU, 0x02U, 0x40U, 0x02U, 0x43U, 0x02U, 0x46U, 0x02U, 0x49U, 0x02U,
|
|
0x4CU, 0x02U, 0x4FU, 0x02U, 0x52U, 0x02U, 0x01U, 0x03U, 0x04U, 0x03U,
|
|
0x07U, 0x03U, 0x0AU, 0x03U, 0x0DU, 0x03U, 0x10U, 0x03U, 0x13U, 0x03U,
|
|
0x16U, 0x03U, 0x19U, 0x03U, 0x1CU, 0x03U, 0x1FU, 0x03U, 0x22U, 0x03U,
|
|
0x25U, 0x03U, 0x28U, 0x03U, 0x2BU, 0x03U, 0x2EU, 0x03U, 0x31U, 0x03U,
|
|
0x34U, 0x03U, 0x37U, 0x03U, 0x3AU, 0x03U, 0x3DU, 0x03U, 0x40U, 0x03U,
|
|
0x43U, 0x03U, 0x46U, 0x03U, 0x49U, 0x03U, 0x4CU, 0x03U, 0x4FU, 0x03U,
|
|
0x52U, 0x03U, 0x01U, 0x04U, 0x04U, 0x04U, 0x07U, 0x04U, 0x0AU, 0x04U,
|
|
0x0DU, 0x04U, 0x10U, 0x04U, 0x13U, 0x04U, 0x16U, 0x04U, 0x19U, 0x04U,
|
|
0x1CU, 0x04U, 0x1FU, 0x04U, 0x22U, 0x04U, 0x25U, 0x04U, 0x28U, 0x04U,
|
|
0x2BU, 0x04U, 0x2EU, 0x04U, 0x31U, 0x04U, 0x34U, 0x04U, 0x37U, 0x04U,
|
|
0x3AU, 0x04U, 0x3DU, 0x04U, 0x40U, 0x04U, 0x43U, 0x04U, 0x46U, 0x04U,
|
|
0x49U, 0x04U, 0x4CU, 0x04U, 0x4FU, 0x04U, 0x01U, 0x05U, 0x04U, 0x05U,
|
|
0x07U, 0x05U, 0x0AU, 0x05U, 0x0DU, 0x05U, 0x10U, 0x05U, 0x13U, 0x05U,
|
|
0x16U, 0x05U, 0x19U, 0x05U, 0x1CU, 0x05U, 0x1FU, 0x05U, 0x22U, 0x05U,
|
|
0x25U, 0x05U, 0x28U, 0x05U, 0x2BU, 0x05U, 0x2EU, 0x05U, 0x31U, 0x05U,
|
|
0x34U, 0x05U, 0x37U, 0x05U, 0x3AU, 0x05U, 0x3DU, 0x05U, 0x40U, 0x05U,
|
|
0x43U, 0x05U, 0x46U, 0x05U, 0x49U, 0x05U, 0x4CU, 0x05U, 0x4FU, 0x05U,
|
|
0x01U, 0x06U, 0x04U, 0x06U, 0x07U, 0x06U, 0x0AU, 0x06U, 0x0DU, 0x06U,
|
|
0x10U, 0x06U, 0x13U, 0x06U, 0x16U, 0x06U, 0x19U, 0x06U, 0x1CU, 0x06U,
|
|
0x1FU, 0x06U, 0x22U, 0x06U, 0x25U, 0x06U, 0x28U, 0x06U, 0x2BU, 0x06U,
|
|
0x2EU, 0x06U, 0x31U, 0x06U, 0x34U, 0x06U, 0x37U, 0x06U, 0x3AU, 0x06U,
|
|
0x3DU, 0x06U, 0x40U, 0x06U, 0x43U, 0x06U, 0x46U, 0x06U, 0x49U, 0x06U,
|
|
0x4CU, 0x06U, 0x4FU, 0x06U, 0x01U, 0x07U, 0x04U, 0x07U, 0x07U, 0x07U,
|
|
0x0AU, 0x07U, 0x0DU, 0x07U, 0x10U, 0x07U, 0x13U, 0x07U, 0x16U, 0x07U,
|
|
0x19U, 0x07U, 0x1CU, 0x07U, 0x1FU, 0x07U, 0x22U, 0x07U, 0x25U, 0x07U,
|
|
0x28U, 0x07U, 0x2BU, 0x07U, 0x2EU, 0x07U, 0x31U, 0x07U, 0x34U, 0x07U,
|
|
0x37U, 0x07U, 0x3AU, 0x07U, 0x3DU, 0x07U, 0x40U, 0x07U, 0x43U, 0x07U,
|
|
0x46U, 0x07U, 0x49U, 0x07U, 0x4CU, 0x07U, 0x4FU, 0x07U, 0x02U, 0x00U,
|
|
0x05U, 0x00U, 0x08U, 0x00U, 0x0BU, 0x00U, 0x0EU, 0x00U, 0x11U, 0x00U,
|
|
0x14U, 0x00U, 0x17U, 0x00U, 0x1AU, 0x00U, 0x1DU, 0x00U, 0x20U, 0x00U,
|
|
0x23U, 0x00U, 0x26U, 0x00U, 0x29U, 0x00U, 0x2CU, 0x00U, 0x2FU, 0x00U,
|
|
0x32U, 0x00U, 0x35U, 0x00U, 0x38U, 0x00U, 0x3BU, 0x00U, 0x3EU, 0x00U,
|
|
0x41U, 0x00U, 0x44U, 0x00U, 0x47U, 0x00U, 0x4AU, 0x00U, 0x4DU, 0x00U,
|
|
0x50U, 0x00U, 0x02U, 0x01U, 0x05U, 0x01U, 0x08U, 0x01U, 0x0BU, 0x01U,
|
|
0x0EU, 0x01U, 0x11U, 0x01U, 0x14U, 0x01U, 0x17U, 0x01U, 0x1AU, 0x01U,
|
|
0x1DU, 0x01U, 0x20U, 0x01U, 0x23U, 0x01U, 0x26U, 0x01U, 0x29U, 0x01U,
|
|
0x2CU, 0x01U, 0x2FU, 0x01U, 0x32U, 0x01U, 0x35U, 0x01U, 0x38U, 0x01U,
|
|
0x3BU, 0x01U, 0x3EU, 0x01U, 0x41U, 0x01U, 0x44U, 0x01U, 0x47U, 0x01U,
|
|
0x4AU, 0x01U, 0x4DU, 0x01U, 0x50U, 0x01U, 0x02U, 0x02U, 0x05U, 0x02U,
|
|
0x08U, 0x02U, 0x0BU, 0x02U, 0x0EU, 0x02U, 0x11U, 0x02U, 0x14U, 0x02U,
|
|
0x17U, 0x02U, 0x1AU, 0x02U, 0x1DU, 0x02U, 0x20U, 0x02U, 0x23U, 0x02U,
|
|
0x26U, 0x02U, 0x29U, 0x02U, 0x2CU, 0x02U, 0x2FU, 0x02U, 0x32U, 0x02U,
|
|
0x35U, 0x02U, 0x38U, 0x02U, 0x3BU, 0x02U, 0x3EU, 0x02U, 0x41U, 0x02U,
|
|
0x44U, 0x02U, 0x47U, 0x02U, 0x4AU, 0x02U, 0x4DU, 0x02U, 0x50U, 0x02U,
|
|
0x02U, 0x03U, 0x05U, 0x03U, 0x08U, 0x03U, 0x0BU, 0x03U, 0x0EU, 0x03U,
|
|
0x11U, 0x03U, 0x14U, 0x03U, 0x17U, 0x03U, 0x1AU, 0x03U, 0x1DU, 0x03U,
|
|
0x20U, 0x03U, 0x23U, 0x03U, 0x26U, 0x03U, 0x29U, 0x03U, 0x2CU, 0x03U,
|
|
0x2FU, 0x03U, 0x32U, 0x03U, 0x35U, 0x03U, 0x38U, 0x03U, 0x3BU, 0x03U,
|
|
0x3EU, 0x03U, 0x41U, 0x03U, 0x44U, 0x03U, 0x47U, 0x03U, 0x4AU, 0x03U,
|
|
0x4DU, 0x03U, 0x50U, 0x03U, 0x02U, 0x04U, 0x05U, 0x04U, 0x08U, 0x04U,
|
|
0x0BU, 0x04U, 0x0EU, 0x04U, 0x11U, 0x04U, 0x14U, 0x04U, 0x17U, 0x04U,
|
|
0x1AU, 0x04U, 0x1DU, 0x04U, 0x20U, 0x04U, 0x23U, 0x04U, 0x26U, 0x04U,
|
|
0x29U, 0x04U, 0x2CU, 0x04U, 0x2FU, 0x04U, 0x32U, 0x04U, 0x35U, 0x04U,
|
|
0x38U, 0x04U, 0x3BU, 0x04U, 0x3EU, 0x04U, 0x41U, 0x04U, 0x44U, 0x04U,
|
|
0x47U, 0x04U, 0x4AU, 0x04U, 0x4DU, 0x04U, 0x50U, 0x04U, 0x02U, 0x05U,
|
|
0x05U, 0x05U, 0x08U, 0x05U, 0x0BU, 0x05U, 0x0EU, 0x05U, 0x11U, 0x05U,
|
|
0x14U, 0x05U, 0x17U, 0x05U, 0x1AU, 0x05U, 0x1DU, 0x05U, 0x20U, 0x05U,
|
|
0x23U, 0x05U, 0x26U, 0x05U, 0x29U, 0x05U, 0x2CU, 0x05U, 0x2FU, 0x05U,
|
|
0x32U, 0x05U, 0x35U, 0x05U, 0x38U, 0x05U, 0x3BU, 0x05U, 0x3EU, 0x05U,
|
|
0x41U, 0x05U, 0x44U, 0x05U, 0x47U, 0x05U, 0x4AU, 0x05U, 0x4DU, 0x05U,
|
|
0x50U, 0x05U, 0x02U, 0x06U, 0x05U, 0x06U, 0x08U, 0x06U, 0x0BU, 0x06U,
|
|
0x0EU, 0x06U, 0x11U, 0x06U, 0x14U, 0x06U, 0x17U, 0x06U, 0x1AU, 0x06U,
|
|
0x1DU, 0x06U, 0x20U, 0x06U, 0x23U, 0x06U, 0x26U, 0x06U, 0x29U, 0x06U,
|
|
0x2CU, 0x06U, 0x2FU, 0x06U, 0x32U, 0x06U, 0x35U, 0x06U, 0x38U, 0x06U,
|
|
0x3BU, 0x06U, 0x3EU, 0x06U, 0x41U, 0x06U, 0x44U, 0x06U, 0x47U, 0x06U,
|
|
0x4AU, 0x06U, 0x4DU, 0x06U, 0x50U, 0x06U, 0x02U, 0x07U, 0x05U, 0x07U,
|
|
0x08U, 0x07U, 0x0BU, 0x07U, 0x0EU, 0x07U, 0x11U, 0x07U, 0x14U, 0x07U,
|
|
0x17U, 0x07U, 0x1AU, 0x07U, 0x1DU, 0x07U, 0x20U, 0x07U, 0x23U, 0x07U,
|
|
0x26U, 0x07U, 0x29U, 0x07U, 0x2CU, 0x07U, 0x2FU, 0x07U, 0x32U, 0x07U,
|
|
0x35U, 0x07U, 0x38U, 0x07U, 0x3BU, 0x07U, 0x3EU, 0x07U, 0x41U, 0x07U,
|
|
0x44U, 0x07U, 0x47U, 0x07U, 0x4AU, 0x07U, 0x4DU, 0x07U, 0x50U, 0x07U,
|
|
};
|
|
|
|
const unsigned char SCRAMBLE_TABLE_TX[] = {
|
|
0x00U, 0xF7U, 0x34U, 0x09U, 0x44U, 0x46U, 0xD7U, 0x06U, 0xB3U, 0x72U,
|
|
0xDEU, 0x42U, 0xF5U, 0xA5U, 0xD8U, 0xF1U, 0x87U, 0x7BU, 0x9AU, 0x04U,
|
|
0x22U, 0xA3U, 0x6BU, 0x83U, 0x59U, 0x39U, 0x6FU, 0xA1U, 0xFAU, 0x52U,
|
|
0xECU, 0xF8U, 0xC3U, 0x3DU, 0x4DU, 0x02U, 0x91U, 0xD1U, 0xB5U, 0xC1U,
|
|
0xACU, 0x9CU, 0xB7U, 0x50U, 0x7DU, 0x29U, 0x76U, 0xFCU, 0xE1U, 0x9EU,
|
|
0x26U, 0x81U, 0xC8U, 0xE8U, 0xDAU, 0x60U, 0x56U, 0xCEU, 0x5BU, 0xA8U,
|
|
0xBEU, 0x14U, 0x3BU, 0xFEU, 0x70U, 0x4FU, 0x93U, 0x40U, 0x64U, 0x74U,
|
|
0x6DU, 0x30U, 0x2BU, 0xE7U, 0x2DU, 0x54U, 0x5FU, 0x8AU, 0x1DU, 0x7FU,
|
|
0xB8U, 0xA7U, 0x49U, 0x20U, 0x32U, 0xBAU, 0x36U, 0x98U, 0x95U, 0xF3U,
|
|
0x06U};
|
|
|
|
const unsigned char SCRAMBLE_TABLE_RX[] = {
|
|
0x70U, 0x4FU, 0x93U, 0x40U, 0x64U, 0x74U, 0x6DU, 0x30U, 0x2BU, 0xE7U,
|
|
0x2DU, 0x54U, 0x5FU, 0x8AU, 0x1DU, 0x7FU, 0xB8U, 0xA7U, 0x49U, 0x20U,
|
|
0x32U, 0xBAU, 0x36U, 0x98U, 0x95U, 0xF3U, 0x16U, 0xAAU, 0x2FU, 0xC5U,
|
|
0x8EU, 0x3FU, 0xDCU, 0xD3U, 0x24U, 0x10U, 0x19U, 0x5DU, 0x1BU, 0xCCU,
|
|
0xCAU, 0x79U, 0x0BU, 0xD5U, 0x97U, 0x62U, 0xC7U, 0x1FU, 0xEEU, 0x69U,
|
|
0x12U, 0x88U, 0x8CU, 0xAEU, 0x0DU, 0x66U, 0xE5U, 0xBCU, 0x85U, 0xEAU,
|
|
0x4BU, 0xB1U, 0xE3U, 0x0FU, 0xF7U, 0x34U, 0x09U, 0x44U, 0x46U, 0xD7U,
|
|
0x06U, 0xB3U, 0x72U, 0xDEU, 0x42U, 0xF5U, 0xA5U, 0xD8U, 0xF1U, 0x87U,
|
|
0x7BU, 0x9AU, 0x04U, 0x22U, 0xA3U, 0x6BU, 0x83U, 0x59U, 0x39U, 0x6FU,
|
|
0x00U};
|
|
|
|
CSoundCardController::CSoundCardController(const wxString& rxDevice, const wxString& txDevice, bool rxInvert, bool txInvert, wxFloat32 rxLevel, wxFloat32 txLevel, unsigned int txDelay, unsigned int txTail) :
|
|
CModem(),
|
|
m_sound(rxDevice, txDevice, DSTAR_RADIO_SAMPLE_RATE, DSTAR_RADIO_BLOCK_SIZE),
|
|
m_rxLevel(rxLevel),
|
|
m_txLevel(txLevel),
|
|
m_txDelay(txDelay),
|
|
m_txTail(txTail),
|
|
m_txAudio(48000U),
|
|
m_rxAudio(4800U),
|
|
m_rxState(DSRSCCS_NONE),
|
|
m_patternBuffer(0x00U),
|
|
m_demodulator(),
|
|
m_modulator(),
|
|
m_rxBuffer(NULL),
|
|
m_rxBufferBits(0U),
|
|
m_dataBits(0U),
|
|
m_mar(0U),
|
|
m_pathMetric(NULL),
|
|
m_pathMemory0(NULL),
|
|
m_pathMemory1(NULL),
|
|
m_pathMemory2(NULL),
|
|
m_pathMemory3(NULL),
|
|
m_fecOutput(NULL)
|
|
{
|
|
wxASSERT(!rxDevice.IsEmpty());
|
|
wxASSERT(!txDevice.IsEmpty());
|
|
|
|
m_modulator.setInvert(txInvert);
|
|
m_demodulator.setInvert(rxInvert);
|
|
|
|
m_sound.setCallback(this, 0U);
|
|
|
|
m_rxBuffer = new unsigned char[FEC_SECTION_LENGTH_BYTES];
|
|
|
|
m_pathMetric = new int[4U];
|
|
m_pathMemory0 = new unsigned int[42U];
|
|
m_pathMemory1 = new unsigned int[42U];
|
|
m_pathMemory2 = new unsigned int[42U];
|
|
m_pathMemory3 = new unsigned int[42U];
|
|
m_fecOutput = new unsigned char[42U];
|
|
}
|
|
|
|
CSoundCardController::~CSoundCardController()
|
|
{
|
|
delete[] m_rxBuffer;
|
|
delete[] m_pathMetric;
|
|
delete[] m_pathMemory0;
|
|
delete[] m_pathMemory1;
|
|
delete[] m_pathMemory2;
|
|
delete[] m_pathMemory3;
|
|
delete[] m_fecOutput;
|
|
}
|
|
|
|
bool CSoundCardController::start()
|
|
{
|
|
bool ret = m_sound.open();
|
|
if (!ret)
|
|
return false;
|
|
|
|
Create();
|
|
SetPriority(100U);
|
|
Run();
|
|
|
|
return true;
|
|
}
|
|
|
|
void* CSoundCardController::Entry()
|
|
{
|
|
wxLogMessage(wxT("Starting Sound Card Controller thread"));
|
|
|
|
while (!m_stopped) {
|
|
wxFloat32 val;
|
|
while (m_rxAudio.getData(&val, 1U) == 1U) {
|
|
TRISTATE state = m_demodulator.decode(val * m_rxLevel);
|
|
switch (state) {
|
|
case STATE_TRUE:
|
|
switch (m_rxState) {
|
|
case DSRSCCS_NONE:
|
|
processNone(true);
|
|
break;
|
|
case DSRSCCS_HEADER:
|
|
processHeader(true);
|
|
break;
|
|
case DSRSCCS_DATA:
|
|
processData(true);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case STATE_FALSE:
|
|
switch (m_rxState) {
|
|
case DSRSCCS_NONE:
|
|
processNone(false);
|
|
break;
|
|
case DSRSCCS_HEADER:
|
|
processHeader(false);
|
|
break;
|
|
case DSRSCCS_DATA:
|
|
processData(false);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
Sleep(10UL);
|
|
}
|
|
|
|
wxLogMessage(wxT("Stopping Sound Card Controller thread"));
|
|
|
|
m_sound.close();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
bool CSoundCardController::writeHeader(const CHeaderData& header)
|
|
{
|
|
bool ret = m_txAudio.hasSpace((m_txDelay + 60U + 85U) * 8U * DSTAR_RADIO_BIT_LENGTH);
|
|
if (!ret) {
|
|
wxLogWarning(wxT("No space to write the header"));
|
|
return false;
|
|
}
|
|
|
|
unsigned char buffer1[RADIO_HEADER_LENGTH_BYTES];
|
|
|
|
::memset(buffer1, ' ', RADIO_HEADER_LENGTH_BYTES);
|
|
|
|
buffer1[0U] = header.getFlag1();
|
|
buffer1[1U] = header.getFlag2();
|
|
buffer1[2U] = header.getFlag3();
|
|
|
|
wxString rpt2 = header.getRptCall2();
|
|
for (unsigned int i = 0U; i < rpt2.Len() && i < LONG_CALLSIGN_LENGTH; i++)
|
|
buffer1[i + 3U] = rpt2.GetChar(i);
|
|
|
|
wxString rpt1 = header.getRptCall1();
|
|
for (unsigned int i = 0U; i < rpt1.Len() && i < LONG_CALLSIGN_LENGTH; i++)
|
|
buffer1[i + 11U] = rpt1.GetChar(i);
|
|
|
|
wxString your = header.getYourCall();
|
|
for (unsigned int i = 0U; i < your.Len() && i < LONG_CALLSIGN_LENGTH; i++)
|
|
buffer1[i + 19U] = your.GetChar(i);
|
|
|
|
wxString my1 = header.getMyCall1();
|
|
for (unsigned int i = 0U; i < my1.Len() && i < LONG_CALLSIGN_LENGTH; i++)
|
|
buffer1[i + 27U] = my1.GetChar(i);
|
|
|
|
wxString my2 = header.getMyCall2();
|
|
for (unsigned int i = 0U; i < my2.Len() && i < SHORT_CALLSIGN_LENGTH; i++)
|
|
buffer1[i + 35U] = my2.GetChar(i);
|
|
|
|
CCCITTChecksumReverse cksum1;
|
|
cksum1.update(buffer1 + 0U, RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
cksum1.result(buffer1 + 39U);
|
|
|
|
unsigned int bytes = m_txDelay + 60U;
|
|
for (unsigned int i = 0U; i < bytes; i++)
|
|
writeBits(BIT_SYNC);
|
|
|
|
unsigned char buffer2[86U];
|
|
txHeader(buffer1, buffer2 + 2U);
|
|
|
|
buffer2[0U] = FRAME_SYNC0;
|
|
buffer2[1U] = FRAME_SYNC1;
|
|
buffer2[2U] |= FRAME_SYNC2;
|
|
|
|
for (unsigned int i = 0U; i < 85U; i++)
|
|
writeBits(buffer2[i]);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CSoundCardController::writeData(const unsigned char* data, unsigned int length, bool end)
|
|
{
|
|
if (end) {
|
|
unsigned int tailBlocks = 3U + m_txTail / 10U;
|
|
|
|
bool ret = m_txAudio.hasSpace(tailBlocks * END_PATTERN_LENGTH_BYTES * 8U * DSTAR_RADIO_BIT_LENGTH);
|
|
if (!ret) {
|
|
wxLogWarning(wxT("No space to write end data"));
|
|
return false;
|
|
}
|
|
|
|
for (unsigned int j = 0U; j < tailBlocks; j++) {
|
|
for (unsigned int i = 0U; i < END_PATTERN_LENGTH_BYTES; i++)
|
|
writeBits(END_PATTERN_BYTES[i]);
|
|
}
|
|
} else {
|
|
bool ret = m_txAudio.hasSpace(length * 8U * DSTAR_RADIO_BIT_LENGTH);
|
|
if (!ret) {
|
|
wxLogWarning(wxT("No space to write data"));
|
|
return false;
|
|
}
|
|
|
|
for (unsigned int i = 0U; i < length; i++)
|
|
writeBits(data[i]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
unsigned int CSoundCardController::getSpace()
|
|
{
|
|
return m_txAudio.freeSpace() / (DV_FRAME_LENGTH_BYTES * 8U * DSTAR_RADIO_BIT_LENGTH);
|
|
}
|
|
|
|
bool CSoundCardController::isTXReady()
|
|
{
|
|
return m_txAudio.isEmpty();
|
|
}
|
|
|
|
bool CSoundCardController::isTX()
|
|
{
|
|
#if (defined(__APPLE__) && defined(__MACH__)) || defined(__WINDOWS__)
|
|
return m_txAudio.hasData();
|
|
#else
|
|
return m_sound.isWriterBusy() || m_txAudio.hasData();
|
|
#endif
|
|
}
|
|
|
|
void CSoundCardController::readCallback(const wxFloat32* input, unsigned int n, int id)
|
|
{
|
|
#if !defined(AUDIO_LOOPBACK)
|
|
if (!m_stopped)
|
|
m_rxAudio.addData(input, n);
|
|
#endif
|
|
}
|
|
|
|
void CSoundCardController::writeCallback(wxFloat32* output, int& n, int id)
|
|
{
|
|
if (n == 0U)
|
|
return;
|
|
|
|
::memset(output, 0x00, n * sizeof(wxFloat32));
|
|
|
|
if (!m_stopped) {
|
|
n = m_txAudio.getData(output, n);
|
|
#if defined(AUDIO_LOOPBACK)
|
|
n = m_rxAudio.addData(output, n);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void CSoundCardController::txHeader(const unsigned char* in, unsigned char* out)
|
|
{
|
|
unsigned char intermediate[84U];
|
|
unsigned int i;
|
|
|
|
for (i = 0U; i < 83U; i++) {
|
|
intermediate[i] = 0x00U;
|
|
out[i] = 0x00U;
|
|
}
|
|
|
|
// Convolve the header
|
|
unsigned char d, d1 = 0U, d2 = 0U, g0, g1;
|
|
unsigned int k = 0U;
|
|
for (i = 0U; i < 42U; i++) {
|
|
for (unsigned int j = 0U; j < 8U; j++) {
|
|
unsigned char mask = (0x01U << j);
|
|
d = 0U;
|
|
|
|
if (in[i] & mask)
|
|
d = 1U;
|
|
|
|
g0 = (d + d2) % 2U;
|
|
g1 = (d + d1 + d2) % 2U;
|
|
d2 = d1;
|
|
d1 = d;
|
|
|
|
if (g1)
|
|
intermediate[k / 8U] |= BIT_MASK_TABLE1[k % 8U];
|
|
|
|
k++;
|
|
|
|
if (g0)
|
|
intermediate[k / 8U] |= BIT_MASK_TABLE1[k % 8U];
|
|
|
|
k++;
|
|
}
|
|
}
|
|
|
|
// Interleave the header
|
|
i = 0U;
|
|
while (i < 660U) {
|
|
unsigned char d = intermediate[i / 8U];
|
|
|
|
if (d & 0x80U)
|
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x40U)
|
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x20U)
|
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x10U)
|
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (i < 660U) {
|
|
if (d & 0x08U)
|
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x04U)
|
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x02U)
|
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x01U)
|
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// Scramble the header
|
|
for (i = 0U; i < 83U; i++)
|
|
out[i] ^= SCRAMBLE_TABLE_TX[i];
|
|
}
|
|
|
|
void CSoundCardController::writeBits(unsigned char c)
|
|
{
|
|
wxFloat32 buffer[DSTAR_RADIO_BIT_LENGTH];
|
|
|
|
unsigned char mask = 0x01U;
|
|
for (unsigned int i = 0U; i < 8U; i++) {
|
|
bool bit = (c & mask) == mask;
|
|
|
|
m_modulator.code(bit, buffer, DSTAR_RADIO_BIT_LENGTH);
|
|
|
|
for (unsigned int j = 0U; j < DSTAR_RADIO_BIT_LENGTH; j++)
|
|
buffer[j] *= m_txLevel;
|
|
|
|
m_txAudio.addData(buffer, DSTAR_RADIO_BIT_LENGTH);
|
|
|
|
mask <<= 1;
|
|
}
|
|
}
|
|
|
|
void CSoundCardController::processNone(bool bit)
|
|
{
|
|
m_patternBuffer <<= 1;
|
|
if (bit)
|
|
m_patternBuffer |= 0x01U;
|
|
|
|
// Exact matching of the frame sync sequence
|
|
unsigned int errs = countBits((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA);
|
|
if (errs == 0U) {
|
|
// Lock the GMSK PLL to this signal
|
|
m_demodulator.lock(true);
|
|
|
|
::memset(m_rxBuffer, 0x00U, FEC_SECTION_LENGTH_BYTES);
|
|
m_rxBufferBits = 0U;
|
|
m_rxState = DSRSCCS_HEADER;
|
|
return;
|
|
}
|
|
|
|
// Exact matching of the data sync bit sequence
|
|
errs = countBits((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA);
|
|
if (errs == 0U) {
|
|
// Lock the GMSK PLL to this signal
|
|
m_demodulator.lock(true);
|
|
|
|
wxMutexLocker locker(m_mutex);
|
|
|
|
unsigned char data[2U];
|
|
data[0U] = DSMTT_DATA;
|
|
data[1U] = DV_FRAME_LENGTH_BYTES;
|
|
m_rxData.addData(data, 2U);
|
|
|
|
m_rxData.addData(NULL_AMBE_DATA_BYTES, VOICE_FRAME_LENGTH_BYTES);
|
|
m_rxData.addData(DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES);
|
|
|
|
::memset(m_rxBuffer, 0x00U, DV_FRAME_LENGTH_BYTES);
|
|
m_rxBufferBits = 0U;
|
|
|
|
m_dataBits = MAX_SYNC_BITS;
|
|
m_rxState = DSRSCCS_DATA;
|
|
return;
|
|
}
|
|
}
|
|
|
|
void CSoundCardController::processHeader(bool bit)
|
|
{
|
|
m_patternBuffer <<= 1;
|
|
if (bit)
|
|
m_patternBuffer |= 0x01U;
|
|
|
|
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
|
|
m_rxBufferBits++;
|
|
|
|
// A full FEC header
|
|
if (m_rxBufferBits == FEC_SECTION_LENGTH_BITS) {
|
|
// Process the scrambling, interleaving and FEC, then return if the chcksum was correct
|
|
unsigned char header[RADIO_HEADER_LENGTH_BYTES];
|
|
bool ok = rxHeader(m_rxBuffer, header);
|
|
if (ok) {
|
|
// The checksum is correct
|
|
wxMutexLocker locker(m_mutex);
|
|
|
|
unsigned char data[2U];
|
|
data[0U] = DSMTT_HEADER;
|
|
data[1U] = RADIO_HEADER_LENGTH_BYTES;
|
|
m_rxData.addData(data, 2U);
|
|
|
|
m_rxData.addData(header, RADIO_HEADER_LENGTH_BYTES);
|
|
|
|
::memset(m_rxBuffer, 0x00U, DV_FRAME_LENGTH_BYTES);
|
|
m_rxBufferBits = 0U;
|
|
|
|
m_rxState = DSRSCCS_DATA;
|
|
m_dataBits = MAX_SYNC_BITS;
|
|
} else {
|
|
// Release PLL ACQ
|
|
m_demodulator.lock(false);
|
|
|
|
// The checksum failed, return to looking for syncs
|
|
m_rxState = DSRSCCS_NONE;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSoundCardController::processData(bool bit)
|
|
{
|
|
m_patternBuffer <<= 1;
|
|
if (bit)
|
|
m_patternBuffer |= 0x01U;
|
|
|
|
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
|
|
m_rxBufferBits++;
|
|
|
|
// Fuzzy matching of the end frame sequences
|
|
unsigned int errs = countBits((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA);
|
|
if (errs <= END_SYNC_ERRS) {
|
|
// Release the GMSK PLL
|
|
m_demodulator.lock(false);
|
|
|
|
wxMutexLocker locker(m_mutex);
|
|
|
|
unsigned char data[2U];
|
|
data[0U] = DSMTT_EOT;
|
|
data[1U] = 0U;
|
|
m_rxData.addData(data, 2U);
|
|
|
|
m_rxState = DSRSCCS_NONE;
|
|
return;
|
|
}
|
|
|
|
// Fuzzy matching of the data sync bit sequence
|
|
bool syncSeen = false;
|
|
if (m_rxBufferBits >= (DV_FRAME_LENGTH_BITS - 3U)) {
|
|
errs = countBits((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA);
|
|
if (errs <= DATA_SYNC_ERRS) {
|
|
m_rxBufferBits = DV_FRAME_LENGTH_BITS;
|
|
m_dataBits = MAX_SYNC_BITS;
|
|
syncSeen = true;
|
|
}
|
|
}
|
|
|
|
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
|
|
m_dataBits--;
|
|
if (m_dataBits == 0U) {
|
|
// Release the GMSK PLL
|
|
m_demodulator.lock(false);
|
|
|
|
wxMutexLocker locker(m_mutex);
|
|
|
|
unsigned char data[2U];
|
|
data[0U] = DSMTT_LOST;
|
|
data[1U] = 0U;
|
|
m_rxData.addData(data, 2U);
|
|
|
|
m_rxState = DSRSCCS_NONE;
|
|
return;
|
|
}
|
|
|
|
// Check to see if the sync is arriving late
|
|
if (m_rxBufferBits == DV_FRAME_LENGTH_BITS && !syncSeen) {
|
|
for (unsigned int i = 1U; i <= 3U; i++) {
|
|
wxUint32 syncMask = DATA_SYNC_MASK >> i;
|
|
wxUint32 syncData = DATA_SYNC_DATA >> i;
|
|
errs = countBits((m_patternBuffer & syncMask) ^ syncData);
|
|
if (errs <= DATA_SYNC_ERRS) {
|
|
m_rxBufferBits -= i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen
|
|
if (m_rxBufferBits == DV_FRAME_LENGTH_BITS) {
|
|
if (syncSeen) {
|
|
m_rxBuffer[9U] = DATA_SYNC_BYTES[0U];
|
|
m_rxBuffer[10U] = DATA_SYNC_BYTES[1U];
|
|
m_rxBuffer[11U] = DATA_SYNC_BYTES[2U];
|
|
}
|
|
|
|
wxMutexLocker locker(m_mutex);
|
|
|
|
unsigned char data[2U];
|
|
data[0U] = DSMTT_DATA;
|
|
data[1U] = DV_FRAME_LENGTH_BYTES;
|
|
m_rxData.addData(data, 2U);
|
|
|
|
m_rxData.addData(m_rxBuffer, DV_FRAME_LENGTH_BYTES);
|
|
|
|
// Start the next frame
|
|
::memset(m_rxBuffer, 0x00U, DV_FRAME_LENGTH_BYTES);
|
|
m_rxBufferBits = 0U;
|
|
}
|
|
}
|
|
|
|
unsigned int CSoundCardController::countBits(wxUint32 num)
|
|
{
|
|
unsigned int count = 0U;
|
|
|
|
for (unsigned int i = 0U; i < 8U; i++)
|
|
count += NIBBLE_BITS[(num >> (i * 4U)) & 0x0FU];
|
|
|
|
return count;
|
|
}
|
|
|
|
bool CSoundCardController::rxHeader(unsigned char* in, unsigned char* out)
|
|
{
|
|
int i;
|
|
|
|
// Descramble the header
|
|
for (i = 0; i < int(FEC_SECTION_LENGTH_BYTES); i++)
|
|
in[i] ^= SCRAMBLE_TABLE_RX[i];
|
|
|
|
unsigned char intermediate[84U];
|
|
for (i = 0; i < 84; i++)
|
|
intermediate[i] = 0x00U;
|
|
|
|
// Deinterleave the header
|
|
i = 0;
|
|
while (i < 660) {
|
|
unsigned char d = in[i / 8];
|
|
|
|
if (d & 0x01U)
|
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x02U)
|
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x04U)
|
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x08U)
|
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (i < 660) {
|
|
if (d & 0x10U)
|
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x20U)
|
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x40U)
|
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
|
i++;
|
|
|
|
if (d & 0x80U)
|
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 4; i++)
|
|
m_pathMetric[i] = 0;
|
|
|
|
int decodeData[2U];
|
|
|
|
m_mar = 0U;
|
|
for (i = 0; i < 660; i += 2) {
|
|
if (intermediate[i / 8] & (0x80U >> i % 8))
|
|
decodeData[1U] = 1U;
|
|
else
|
|
decodeData[1U] = 0U;
|
|
|
|
if (intermediate[i / 8] & (0x40U >> i % 8))
|
|
decodeData[0U] = 1U;
|
|
else
|
|
decodeData[0U] = 0U;
|
|
|
|
viterbiDecode(decodeData);
|
|
}
|
|
|
|
traceBack();
|
|
|
|
for (i = 0; i < int(RADIO_HEADER_LENGTH_BYTES); i++)
|
|
out[i] = 0x00U;
|
|
|
|
unsigned int j = 0;
|
|
for (i = 329; i >= 0; i--) {
|
|
if (READ_BIT1(m_fecOutput, i))
|
|
out[j / 8] |= (0x01U << (j % 8));
|
|
|
|
j++;
|
|
}
|
|
|
|
CCCITTChecksumReverse cksum;
|
|
cksum.update(out, RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
|
|
return cksum.check(out + RADIO_HEADER_LENGTH_BYTES - 2U);
|
|
}
|
|
|
|
void CSoundCardController::acs(int* metric)
|
|
{
|
|
int tempMetric[4U];
|
|
|
|
unsigned int j = m_mar / 8U;
|
|
unsigned int k = m_mar % 8U;
|
|
|
|
// Pres. state = S0, Prev. state = S0 & S2
|
|
int m1 = metric[0U] + m_pathMetric[0U];
|
|
int m2 = metric[4U] + m_pathMetric[2U];
|
|
tempMetric[0U] = m1 < m2 ? m1 : m2;
|
|
if (m1 < m2)
|
|
m_pathMemory0[j] &= BIT_MASK_TABLE0[k];
|
|
else
|
|
m_pathMemory0[j] |= BIT_MASK_TABLE1[k];
|
|
|
|
// Pres. state = S1, Prev. state = S0 & S2
|
|
m1 = metric[1U] + m_pathMetric[0U];
|
|
m2 = metric[5U] + m_pathMetric[2U];
|
|
tempMetric[1U] = m1 < m2 ? m1 : m2;
|
|
if (m1 < m2)
|
|
m_pathMemory1[j] &= BIT_MASK_TABLE0[k];
|
|
else
|
|
m_pathMemory1[j] |= BIT_MASK_TABLE1[k];
|
|
|
|
// Pres. state = S2, Prev. state = S2 & S3
|
|
m1 = metric[2U] + m_pathMetric[1U];
|
|
m2 = metric[6U] + m_pathMetric[3U];
|
|
tempMetric[2U] = m1 < m2 ? m1 : m2;
|
|
if (m1 < m2)
|
|
m_pathMemory2[j] &= BIT_MASK_TABLE0[k];
|
|
else
|
|
m_pathMemory2[j] |= BIT_MASK_TABLE1[k];
|
|
|
|
// Pres. state = S3, Prev. state = S1 & S3
|
|
m1 = metric[3U] + m_pathMetric[1U];
|
|
m2 = metric[7U] + m_pathMetric[3U];
|
|
tempMetric[3U] = m1 < m2 ? m1 : m2;
|
|
if (m1 < m2)
|
|
m_pathMemory3[j] &= BIT_MASK_TABLE0[k];
|
|
else
|
|
m_pathMemory3[j] |= BIT_MASK_TABLE1[k];
|
|
|
|
for (unsigned int i = 0U; i < 4U; i++)
|
|
m_pathMetric[i] = tempMetric[i];
|
|
|
|
m_mar++;
|
|
}
|
|
|
|
void CSoundCardController::viterbiDecode(int* data)
|
|
{
|
|
int metric[8U];
|
|
|
|
metric[0] = (data[1] ^ 0) + (data[0] ^ 0);
|
|
metric[1] = (data[1] ^ 1) + (data[0] ^ 1);
|
|
metric[2] = (data[1] ^ 1) + (data[0] ^ 0);
|
|
metric[3] = (data[1] ^ 0) + (data[0] ^ 1);
|
|
metric[4] = (data[1] ^ 1) + (data[0] ^ 1);
|
|
metric[5] = (data[1] ^ 0) + (data[0] ^ 0);
|
|
metric[6] = (data[1] ^ 0) + (data[0] ^ 1);
|
|
metric[7] = (data[1] ^ 1) + (data[0] ^ 0);
|
|
|
|
acs(metric);
|
|
}
|
|
|
|
void CSoundCardController::traceBack()
|
|
{
|
|
// Start from the S0, t=31
|
|
unsigned int j = 0U;
|
|
unsigned int k = 0U;
|
|
for (int i = 329; i >= 0; i--) {
|
|
switch (j) {
|
|
case 0U: // if state = S0
|
|
if (READ_BIT1(m_pathMemory0, i) == 0)
|
|
j = 0U;
|
|
else
|
|
j = 2U;
|
|
WRITE_BIT1(m_fecOutput, k, 0);
|
|
k++;
|
|
break;
|
|
|
|
|
|
case 1U: // if state = S1
|
|
if (READ_BIT1(m_pathMemory1, i) == 0)
|
|
j = 0U;
|
|
else
|
|
j = 2U;
|
|
WRITE_BIT1(m_fecOutput, k, 1);
|
|
k++;
|
|
break;
|
|
|
|
case 2: // if state = S1
|
|
if (READ_BIT1(m_pathMemory2, i) == 0)
|
|
j = 1U;
|
|
else
|
|
j = 3U;
|
|
WRITE_BIT1(m_fecOutput, k, 0);
|
|
k++;
|
|
break;
|
|
|
|
case 3U: // if state = S1
|
|
if (READ_BIT1(m_pathMemory3, i) == 0)
|
|
j = 1U;
|
|
else
|
|
j = 3U;
|
|
WRITE_BIT1(m_fecOutput, k, 1);
|
|
k++;
|
|
break;
|
|
}
|
|
}
|
|
}
|