282 lines
7.8 KiB
C++
282 lines
7.8 KiB
C++
/*
|
|
* Copyright (C) 2016 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 "RS.h"
|
|
|
|
#include <cstdio>
|
|
#include <cassert>
|
|
|
|
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
|
|
|
|
#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
|
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
|
|
|
static int bin2Hex(const unsigned char* input, unsigned int offset)
|
|
{
|
|
int output = 0;
|
|
|
|
output |= READ_BIT(input, offset + 0U) ? 0x20 : 0x00;
|
|
output |= READ_BIT(input, offset + 1U) ? 0x10 : 0x00;
|
|
output |= READ_BIT(input, offset + 2U) ? 0x08 : 0x00;
|
|
output |= READ_BIT(input, offset + 3U) ? 0x04 : 0x00;
|
|
output |= READ_BIT(input, offset + 4U) ? 0x02 : 0x00;
|
|
output |= READ_BIT(input, offset + 5U) ? 0x01 : 0x00;
|
|
|
|
return output;
|
|
}
|
|
|
|
static void hex2Bin(int input, unsigned char* output, unsigned int offset)
|
|
{
|
|
WRITE_BIT(output, offset + 0U, input & 0x20);
|
|
WRITE_BIT(output, offset + 1U, input & 0x10);
|
|
WRITE_BIT(output, offset + 2U, input & 0x08);
|
|
WRITE_BIT(output, offset + 3U, input & 0x04);
|
|
WRITE_BIT(output, offset + 4U, input & 0x02);
|
|
WRITE_BIT(output, offset + 5U, input & 0x01);
|
|
}
|
|
|
|
// tt = (dd-1)/2
|
|
// dd = 17 --> tt = 8
|
|
CRS362017::CRS362017() :
|
|
CReedSolomon63<8>()
|
|
{
|
|
}
|
|
|
|
CRS362017::~CRS362017()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Does a Reed-Solomon decode adapting the input and output to the expected DSD data format.
|
|
* \param hex_data Data packed bits, originally a char[20][6], so containing 20 hex works, each char
|
|
* is a bit. Bits are corrected in place.
|
|
* \param hex_parity Parity packed bits, originally a char[16][6], 16 hex words.
|
|
* \return 1 if irrecoverable errors have been detected, 0 otherwise.
|
|
*/
|
|
bool CRS362017::decode(unsigned char* data)
|
|
{
|
|
assert(data != NULL);
|
|
|
|
int input[63];
|
|
int output[63];
|
|
|
|
// Fill up with zeros to complete the 47 expected hex words of data
|
|
for (unsigned int i = 0U; i < 63U; i++)
|
|
input[i] = 0;
|
|
|
|
// First put the parity data, 16 hex words
|
|
unsigned int offset = 120U;
|
|
for (unsigned int i = 0U; i < 16U; i++, offset += 6U)
|
|
input[i] = bin2Hex(data, offset);
|
|
|
|
// Then the 20 hex words of data
|
|
offset = 0U;
|
|
for (unsigned int i = 16U; i < 36U; i++, offset += 6U)
|
|
input[i] = bin2Hex(data, offset);
|
|
|
|
// Now we can call decode on the base class
|
|
int irrecoverable_errors = CReedSolomon63<8>::decode(input, output);
|
|
if (irrecoverable_errors != 0)
|
|
return false;
|
|
|
|
// Convert it back to binary and put it into hex_data.
|
|
offset = 0U;
|
|
for (unsigned int i = 16U; i < 36U; i++, offset += 6U)
|
|
hex2Bin(output[i], data, offset);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CRS362017::encode(unsigned char* data)
|
|
{
|
|
assert(data != NULL);
|
|
|
|
int input[47];
|
|
int output[63];
|
|
|
|
// Fill up with zeros to complete the 47 expected hex words of data
|
|
for (unsigned int i = 0U; i < 47U; i++)
|
|
input[i] = 0;
|
|
|
|
// Put the 20 hex words of data
|
|
unsigned int offset = 0U;
|
|
for (unsigned int i = 0U; i < 20U; i++, offset += 6U)
|
|
input[i] = bin2Hex(data, offset);
|
|
|
|
// Now we can call encode on the base class
|
|
CReedSolomon63<8>::encode(input, output);
|
|
|
|
// Convert it back to binary form and put it into the parity
|
|
offset = 120U;
|
|
for (unsigned int i = 0U; i < 16U; i++, offset += 6U)
|
|
hex2Bin(output[i], data, offset);
|
|
}
|
|
|
|
// tt = (dd-1)/2
|
|
// dd = 13 --> tt = 6
|
|
CRS241213::CRS241213() :
|
|
CReedSolomon63<6>()
|
|
{
|
|
}
|
|
|
|
CRS241213::~CRS241213()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Does a Reed-Solomon decode adapting the input and output to the expected DSD data format.
|
|
* \param hex_data Data packed bits, originally a char[12][6], so containing 12 hex works, each char
|
|
* is a bit. Bits are corrected in place.
|
|
* \param hex_parity Parity packed bits, originally a char[12][6], 12 hex words.
|
|
* \return 1 if irrecoverable errors have been detected, 0 otherwise.
|
|
*/
|
|
bool CRS241213::decode(unsigned char* data)
|
|
{
|
|
assert(data != NULL);
|
|
|
|
int input[63];
|
|
int output[63];
|
|
|
|
// Fill up with zeros to complete the 51 expected hex words of data
|
|
for (unsigned int i = 0U; i < 63U; i++)
|
|
input[i] = 0;
|
|
|
|
// First put the parity data, 12 hex words
|
|
unsigned int offset = 72U;
|
|
for (unsigned int i = 0U; i < 12U; i++, offset += 6U)
|
|
input[i] = bin2Hex(data, offset);
|
|
|
|
// Then the 12 hex words of data
|
|
offset = 0U;
|
|
for (unsigned int i = 12U; i < 24U; i++, offset += 6U)
|
|
input[i] = bin2Hex(data, offset);
|
|
|
|
// Now we can call decode on the base class
|
|
int irrecoverable_errors = CReedSolomon63<6>::decode(input, output);
|
|
if (irrecoverable_errors != 0)
|
|
return false;
|
|
|
|
// Convert it back to binary and put it into hex_data.
|
|
offset = 0U;
|
|
for (unsigned int i = 12U; i < 24U; i++, offset += 6U)
|
|
hex2Bin(output[i], data, offset);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CRS241213::encode(unsigned char* data)
|
|
{
|
|
assert(data != NULL);
|
|
|
|
int input[51];
|
|
int output[63];
|
|
|
|
// Fill up with zeros to complete the 51 expected hex words of data
|
|
for (unsigned int i = 0U; i < 51U; i++)
|
|
input[i] = 0;
|
|
|
|
// Put the 12 hex words of data
|
|
unsigned int offset = 0U;
|
|
for (unsigned int i = 0U; i < 12U; i++, offset += 6U)
|
|
input[i] = bin2Hex(data, offset);
|
|
|
|
// Now we can call encode on the base class
|
|
CReedSolomon63<6>::encode(input, output);
|
|
|
|
// Convert it back to binary form and put it into the parity
|
|
offset = 72U;
|
|
for (unsigned int i = 0U; i < 12U; i++, offset += 6U)
|
|
hex2Bin(output[i], data, offset);
|
|
}
|
|
|
|
// tt = (dd-1)/2
|
|
// dd = 9 --> tt = 4
|
|
CRS24169::CRS24169() :
|
|
CReedSolomon63<4>()
|
|
{
|
|
}
|
|
|
|
CRS24169::~CRS24169()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Does a Reed-Solomon decode adapting the input and output to the expected DSD data format.
|
|
* \param hex_data Data packed bits, originally a char[16][6], so containing 16 hex works, each char
|
|
* is a bit. Bits are corrected in place.
|
|
* \param hex_parity Parity packed bits, originally a char[8][6], 8 hex words.
|
|
* \return 1 if irrecoverable errors have been detected, 0 otherwise.
|
|
*/
|
|
bool CRS24169::decode(unsigned char* data)
|
|
{
|
|
assert(data != NULL);
|
|
|
|
int input[63];
|
|
int output[63];
|
|
|
|
// Fill up with zeros to complete the 55 expected hex words of data
|
|
for (unsigned int i = 0U; i < 63U; i++)
|
|
input[i] = 0;
|
|
|
|
// First put the parity data, 8 hex words
|
|
unsigned int offset = 96U;
|
|
for (unsigned int i = 0U; i < 8U; i++, offset += 6U)
|
|
input[i] = bin2Hex(data, offset);
|
|
|
|
// Then the 16 hex words of data
|
|
offset = 0U;
|
|
for (unsigned int i = 8U; i < 24U; i++, offset += 6U)
|
|
input[i] = bin2Hex(data, offset);
|
|
|
|
// Now we can call decode on the base class
|
|
int irrecoverable_errors = CReedSolomon63<4>::decode(input, output);
|
|
if (irrecoverable_errors != 0)
|
|
return false;
|
|
|
|
// Convert it back to binary and put it into hex_data.
|
|
offset = 0U;
|
|
for (unsigned int i = 8U; i < 24U; i++, offset += 6U)
|
|
hex2Bin(output[i], data, offset);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CRS24169::encode(unsigned char* data)
|
|
{
|
|
assert(data != NULL);
|
|
|
|
int input[55];
|
|
int output[63];
|
|
|
|
// Fill up with zeros to complete the 55 expected hex words of data
|
|
for (unsigned int i = 0U; i < 55U; i++)
|
|
input[i] = 0;
|
|
|
|
// Put the 16 hex words of data
|
|
unsigned int offset = 0U;
|
|
for (unsigned int i = 0U; i < 16U; i++, offset += 6U)
|
|
input[i] = bin2Hex(data, offset);
|
|
|
|
// Now we can call encode on the base class
|
|
CReedSolomon63<4>::encode(input, output);
|
|
|
|
// Convert it back to binary form and put it into the parity
|
|
offset = 96U;
|
|
for (unsigned int i = 0U; i < 8U; i++, offset += 6U)
|
|
hex2Bin(output[i], data, offset);
|
|
}
|