diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj
index ff38eb5..87db1a4 100644
--- a/MMDVMHost.vcxproj
+++ b/MMDVMHost.vcxproj
@@ -192,8 +192,8 @@
-
+
@@ -253,8 +253,8 @@
-
+
diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters
index 59775be..a189600 100644
--- a/MMDVMHost.vcxproj.filters
+++ b/MMDVMHost.vcxproj.filters
@@ -197,10 +197,10 @@
Header Files
-
+
Header Files
-
+
Header Files
@@ -370,10 +370,10 @@
Source Files
-
+
Source Files
-
+
Source Files
diff --git a/Makefile b/Makefile
index 6cbcfbc..ca7d2ad 100644
--- a/Makefile
+++ b/Makefile
@@ -10,8 +10,8 @@ OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRLookup.o DMRLC.o \
DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \
Golay24128.o Hamming.o Log.o MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o \
- QR1676.o RS.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o \
- YSFNetwork.o YSFPayload.o
+ QR1676.o RS129.o RS241213.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o \
+ YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost
diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit
index 52ee6fd..f1802d9 100644
--- a/Makefile.Pi.Adafruit
+++ b/Makefile.Pi.Adafruit
@@ -10,8 +10,8 @@ OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRLookup.o DMRLC.o \
DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \
Golay24128.o Hamming.o HD44780.o Log.o MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \
- P25Utils.o QR1676.o RS.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o \
- YSFFICH.o YSFNetwork.o YSFPayload.o
+ P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o \
+ YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost
diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780
index 84e0598..6a778d5 100644
--- a/Makefile.Pi.HD44780
+++ b/Makefile.Pi.HD44780
@@ -10,8 +10,8 @@ OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRLookup.o DMRLC.o \
DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \
Golay24128.o Hamming.o HD44780.o Log.o MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \
- P25Utils.o QR1676.o RS.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o \
- YSFFICH.o YSFNetwork.o YSFPayload.o
+ P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o \
+ YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost
diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED
index 762390c..a0a599c 100644
--- a/Makefile.Pi.OLED
+++ b/Makefile.Pi.OLED
@@ -10,8 +10,8 @@ OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRLookup.o DMRLC.o \
DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \
Golay24128.o Hamming.o OLED.o Log.o MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \
- P25Utils.o QR1676.o RS.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o \
- YSFFICH.o YSFNetwork.o YSFPayload.o
+ P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o \
+ YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost
diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574
index 7bf174c..c0f0ab5 100644
--- a/Makefile.Pi.PCF8574
+++ b/Makefile.Pi.PCF8574
@@ -10,8 +10,8 @@ OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRLookup.o DMRLC.o \
DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \
Golay24128.o Hamming.o HD44780.o Log.o MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \
- P25Utils.o QR1676.o RS.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o \
- YSFFICH.o YSFNetwork.o YSFPayload.o
+ P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o \
+ YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost
diff --git a/Makefile.Solaris b/Makefile.Solaris
index d4b43c0..c0d6836 100644
--- a/Makefile.Solaris
+++ b/Makefile.Solaris
@@ -10,8 +10,8 @@ OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRLookup.o DMRLC.o \
DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \
Golay24128.o Hamming.o Log.o MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o \
- QR1676.o RS.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o \
- YSFNetwork.o YSFPayload.o
+ QR1676.o RS129.o RS241213.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o \
+ YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost
diff --git a/P25Data.cpp b/P25Data.cpp
index b27af06..6b97a54 100644
--- a/P25Data.cpp
+++ b/P25Data.cpp
@@ -71,7 +71,7 @@ void CP25Data::encodeHeader(unsigned char* data)
CP25Utils::encode(DUMMY_HEADER, data, 114U, 780U);
}
-void CP25Data::processLDU1(unsigned char* data)
+bool CP25Data::processLDU1(unsigned char* data)
{
assert(data != NULL);
@@ -96,9 +96,11 @@ void CP25Data::processLDU1(unsigned char* data)
CP25Utils::decode(data, raw, 1356U, 1398U);
decodeLDUHamming(raw, rs + 15U);
- // CUtils::dump(1U, "P25, LDU1 Data before", rs, 18U);
-
- m_rs241213.decode(rs);
+ bool ret = m_rs241213.decode(rs);
+ if (!ret) {
+ LogDebug("P25, uncorrectable errors in the RS(24,12,13) code");
+ return false;
+ }
m_lcf = rs[0U];
m_mfId = rs[1U];
@@ -119,9 +121,7 @@ void CP25Data::processLDU1(unsigned char* data)
break;
}
- // m_rs241213.encode(rs);
-
- // CUtils::dump(1U, "P25, LDU1 Data after", rs, 18U);
+ m_rs241213.encode(rs);
encodeLDUHamming(raw, rs + 0U);
CP25Utils::encode(raw, data, 410U, 452U);
@@ -140,6 +140,8 @@ void CP25Data::processLDU1(unsigned char* data)
encodeLDUHamming(raw, rs + 15U);
CP25Utils::encode(raw, data, 1356U, 1398U);
+
+ return true;
}
void CP25Data::encodeLDU1(unsigned char* data)
@@ -174,9 +176,7 @@ void CP25Data::encodeLDU1(unsigned char* data)
break;
}
- // m_rs241213.encode(rs);
-
- // CUtils::dump(1U, "P25, LDU1 Data", rs, 18U);
+ m_rs241213.encode(rs);
unsigned char raw[5U];
encodeLDUHamming(raw, rs + 0U);
diff --git a/P25Data.h b/P25Data.h
index 6786c62..04d044c 100644
--- a/P25Data.h
+++ b/P25Data.h
@@ -19,7 +19,7 @@
#if !defined(P25Data_H)
#define P25Data_H
-#include "RS.h"
+#include "RS241213.h"
class CP25Data {
public:
@@ -28,7 +28,7 @@ public:
void encodeHeader(unsigned char* data);
- void processLDU1(unsigned char* data);
+ bool processLDU1(unsigned char* data);
void encodeLDU1(unsigned char* data);
void encodeLDU2(unsigned char* data);
diff --git a/RS.cpp b/RS.cpp
deleted file mode 100644
index 71174d9..0000000
--- a/RS.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
-* 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 "Log.h"
-
-#include
-#include
-
-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) {
- LogWarning("Unrecoverable errors in the RS(36,20,17) code");
- 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) {
- LogWarning("Unrecoverable errors in the RS(24,12,13) code");
- 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) {
- LogWarning("Unrecoverable errors in the RS(24,16,9) code");
- 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);
-}
diff --git a/RS.h b/RS.h
deleted file mode 100644
index beffa32..0000000
--- a/RS.h
+++ /dev/null
@@ -1,491 +0,0 @@
-#ifndef REEDSOLOMON_HPP_b1405fdab6374ba2a4e65e8d45ec3d80
-#define REEDSOLOMON_HPP_b1405fdab6374ba2a4e65e8d45ec3d80
-
-/**
-* Code taken and adapted from www.eccpage.com/rs.c
-* Credit goes to Mr Simon Rockliff.
-*
-* Tried before with the implementation from ITPP library but couldn't make it produce the same outputs
-* expected from the P25 transmissions that I have tested. This implementation does work.
-*/
-
-/* This program is an encoder/decoder for Reed-Solomon codes. Encoding is in
-systematic form, decoding via the Berlekamp iterative algorithm.
-In the present form , the constants mm, nn, tt, and kk=nn-2tt must be
-specified (the double letters are used simply to avoid clashes with
-other n,k,t used in other programs into which this was incorporated!)
-Also, the irreducible polynomial used to generate GF(2**mm) must also be
-entered -- these can be found in Lin and Costello, and also Clark and Cain.
-
-The representation of the elements of GF(2**m) is either in index form,
-where the number is the power of the primitive element alpha, which is
-convenient for multiplication (add the powers modulo 2**m-1) or in
-polynomial form, where the bits represent the coefficients of the
-polynomial representation of the number, which is the most convenient form
-for addition. The two forms are swapped between via lookup tables.
-This leads to fairly messy looking expressions, but unfortunately, there
-is no easy alternative when working with Galois arithmetic.
-
-The code is not written in the most elegant way, but to the best
-of my knowledge, (no absolute guarantees!), it works.
-However, when including it into a simulation program, you may want to do
-some conversion of global variables (used here because I am lazy!) to
-local variables where appropriate, and passing parameters (eg array
-addresses) to the functions may be a sensible move to reduce the number
-of global variables and thus decrease the chance of a bug being introduced.
-
-This program does not handle erasures at present, but should not be hard
-to adapt to do this, as it is just an adjustment to the Berlekamp-Massey
-algorithm. It also does not attempt to decode past the BCH bound -- see
-Blahut "Theory and practice of error control codes" for how to do this.
-
-Simon Rockliff, University of Adelaide 21/9/89
-
-26/6/91 Slight modifications to remove a compiler dependent bug which hadn't
-previously surfaced. A few extra comments added for clarity.
-Appears to all work fine, ready for posting to net!
-
-Notice
---------
-This program may be freely modified and/or given to whoever wants it.
-A condition of such distribution is that the author's contribution be
-acknowledged by his name being left in the comments heading the program,
-however no responsibility is accepted for any financial or other loss which
-may result from some unforseen errors or malfunctioning of the program
-during use.
-Simon Rockliff, 26th June 1991
-*/
-
-#include
-
-template class CReedSolomon63
-{
-private:
- static const int MM = 6; // RS code over GF(2**mm)
- static const int NN = 63; // nn=2**mm -1 length of codeword
- //int tt; number of errors that can be corrected
- //int kk; kk = nn-2*tt
- static const int KK = NN - 2 * TT;
- // distance = nn-kk+1 = 2*tt+1
-
- int* gg;
-
- // generate GF(2**mm) from the irreducible polynomial p(X) in pp[0]..pp[mm]
- // lookup tables: index->polynomial form alpha_to[] contains j=alpha**i;
- // polynomial form -> index form index_of[j=alpha**i] = i
- // alpha=2 is the primitive element of GF(2**mm)
- void generate_gf(const int* generator_polinomial)
- {
- register int i, mask;
-
- mask = 1;
- alpha_to[MM] = 0;
-
- for (i = 0; i < MM; i++) {
- alpha_to[i] = mask;
- index_of[alpha_to[i]] = i;
-
- if (generator_polinomial[i] != 0)
- alpha_to[MM] ^= mask;
-
- mask <<= 1;
- }
-
- index_of[alpha_to[MM]] = MM;
-
- mask >>= 1;
-
- for (i = MM + 1; i < NN; i++) {
- if (alpha_to[i - 1] >= mask)
- alpha_to[i] = alpha_to[MM] ^ ((alpha_to[i - 1] ^ mask) << 1);
- else
- alpha_to[i] = alpha_to[i - 1] << 1;
-
- index_of[alpha_to[i]] = i;
- }
-
- index_of[0] = -1;
- }
-
- // Obtain the generator polynomial of the tt-error correcting, length
- // nn=(2**mm -1) Reed Solomon code from the product of (X+alpha**i), i=1..2*tt
- void gen_poly()
- {
- register int i, j;
-
- gg[0] = 2; // primitive element alpha = 2 for GF(2**mm)
- gg[1] = 1; // g(x) = (X+alpha) initially
-
- for (i = 2; i <= NN - KK; i++) {
- gg[i] = 1;
-
- for (j = i - 1; j > 0; j--)
- if (gg[j] != 0)
- gg[j] = gg[j - 1] ^ alpha_to[(index_of[gg[j]] + i) % NN];
- else
- gg[j] = gg[j - 1];
-
- gg[0] = alpha_to[(index_of[gg[0]] + i) % NN]; // gg[0] can never be zero
- }
-
- // convert gg[] to index form for quicker encoding
- for (i = 0; i <= NN - KK; i++)
- gg[i] = index_of[gg[i]];
- }
-
-protected:
- int* alpha_to;
- int* index_of;
-
- CReedSolomon63()
- {
- alpha_to = new int[NN + 1];
- index_of = new int[NN + 1];
- gg = new int[NN - KK + 1];
-
- for (unsigned int i = 0U; i < (NN + 1); i++) {
- alpha_to[i] = 0;
- index_of[i] = 0;
- }
-
- for (unsigned int i = 0U; i < (NN - KK + 1); i++)
- gg[i] = 0;
-
- // Polynom used in P25 is alpha**6+alpha+1
- const int generator_polinomial[] = {1, 1, 0, 0, 0, 0, 1}; // specify irreducible polynomial coeffts
-
- generate_gf(generator_polinomial);
-
- gen_poly();
- }
-
- virtual ~CReedSolomon63()
- {
- delete[] gg;
- delete[] index_of;
- delete[] alpha_to;
- }
-
- // take the string of symbols in data[i], i=0..(k-1) and encode systematically
- // to produce 2*tt parity symbols in bb[0]..bb[2*tt-1]
- // data[] is input and bb[] is output in polynomial form.
- // Encoding is done by using a feedback shift register with appropriate
- // connections specified by the elements of gg[], which was generated above.
- // Codeword is c(X) = data(X)*X**(nn-kk)+ b(X)
- void encode(const int* data, int* bb)
- {
- register int i, j;
- int feedback;
-
- for (i = 0; i < NN - KK; i++)
- bb[i] = 0;
-
- for (i = KK - 1; i >= 0; i--) {
- feedback = index_of[data[i] ^ bb[NN - KK - 1]];
- if (feedback != -1) {
- for (j = NN - KK - 1; j > 0; j--)
- if (gg[j] != -1)
- bb[j] = bb[j - 1] ^ alpha_to[(gg[j] + feedback) % NN];
- else
- bb[j] = bb[j - 1];
-
- bb[0] = alpha_to[(gg[0] + feedback) % NN];
- } else {
- for (j = NN - KK - 1; j > 0; j--)
- bb[j] = bb[j - 1];
-
- bb[0] = 0;
- }
- }
- }
-
- /* assume we have received bits grouped into mm-bit symbols in recd[i],
- i=0..(nn-1), and recd[i] is polynomial form.
- We first compute the 2*tt syndromes by substituting alpha**i into rec(X) and
- evaluating, storing the syndromes in s[i], i=1..2tt (leave s[0] zero) .
- Then we use the Berlekamp iteration to find the error location polynomial
- elp[i]. If the degree of the elp is >tt, we cannot correct all the errors
- and hence just put out the information symbols uncorrected. If the degree of
- elp is <=tt, we substitute alpha**i , i=1..n into the elp to get the roots,
- hence the inverse roots, the error location numbers. If the number of errors
- located does not equal the degree of the elp, we have more than tt errors
- and cannot correct them. Otherwise, we then solve for the error value at
- the error location and correct the error. The procedure is that found in
- Lin and Costello. For the cases where the number of errors is known to be too
- large to correct, the information symbols as received are output (the
- advantage of systematic encoding is that hopefully some of the information
- symbols will be okay and that if we are in luck, the errors are in the
- parity part of the transmitted codeword). Of course, these insoluble cases
- can be returned as error flags to the calling routine if desired. */
- int decode(const int* input, int* recd)
- {
- register int i, j, u, q;
- int elp[NN - KK + 2][NN - KK], d[NN - KK + 2], l[NN - KK + 2], u_lu[NN - KK + 2], s[NN - KK + 1];
- int count = 0, syn_error = 0, root[TT], loc[TT], z[TT + 1], err[NN], reg[TT + 1];
-
- int irrecoverable_error = 0;
-
- for (int i = 0; i < NN; i++)
- recd[i] = index_of[input[i]]; /* put recd[i] into index form (ie as powers of alpha) */
-
- /* first form the syndromes */
- for (i = 1; i <= NN - KK; i++) {
- s[i] = 0;
-
- for (j = 0; j < NN; j++)
- if (recd[j] != -1)
- s[i] ^= alpha_to[(recd[j] + i * j) % NN]; /* recd[j] in index form */
- /* convert syndrome from polynomial form to index form */
-
- if (s[i] != 0)
- syn_error = 1; /* set flag if non-zero syndrome => error */
-
- s[i] = index_of[s[i]];
- }
-
- if (syn_error) /* if errors, try and correct */
- {
- /* compute the error location polynomial via the Berlekamp iterative algorithm,
- following the terminology of Lin and Costello : d[u] is the 'mu'th
- discrepancy, where u='mu'+1 and 'mu' (the Greek letter!) is the step number
- ranging from -1 to 2*tt (see L&C), l[u] is the
- degree of the elp at that step, and u_l[u] is the difference between the
- step number and the degree of the elp.
- */
-
- /* initialise table entries */
- d[0] = 0; /* index form */
- d[1] = s[1]; /* index form */
- elp[0][0] = 0; /* index form */
- elp[1][0] = 1; /* polynomial form */
-
- for (i = 1; i < NN - KK; i++) {
- elp[0][i] = -1; /* index form */
- elp[1][i] = 0; /* polynomial form */
- }
-
- l[0] = 0;
- l[1] = 0;
- u_lu[0] = -1;
- u_lu[1] = 0;
- u = 0;
-
- do {
- u++;
-
- if (d[u] == -1) {
- l[u + 1] = l[u];
-
- for (i = 0; i <= l[u]; i++) {
- elp[u + 1][i] = elp[u][i];
- elp[u][i] = index_of[elp[u][i]];
- }
- } else
- /* search for words with greatest u_lu[q] for which d[q]!=0 */
- {
- q = u - 1;
- while ((d[q] == -1) && (q > 0))
- q--;
-
- /* have found first non-zero d[q] */
- if (q > 0) {
- j = q;
- do {
- j--;
- if ((d[j] != -1) && (u_lu[q] < u_lu[j]))
- q = j;
- } while (j > 0);
- };
-
- /* have now found q such that d[u]!=0 and u_lu[q] is maximum */
- /* store degree of new elp polynomial */
- if (l[u] > l[q] + u - q)
- l[u + 1] = l[u];
- else
- l[u + 1] = l[q] + u - q;
-
- /* form new elp(x) */
- for (i = 0; i < NN - KK; i++)
- elp[u + 1][i] = 0;
-
- for (i = 0; i <= l[q]; i++)
- if (elp[q][i] != -1)
- elp[u + 1][i + u - q] = alpha_to[(d[u] + NN - d[q] + elp[q][i]) % NN];
-
- for (i = 0; i <= l[u]; i++) {
- elp[u + 1][i] ^= elp[u][i];
- elp[u][i] = index_of[elp[u][i]]; /*convert old elp value to index*/
- }
- }
-
- u_lu[u + 1] = u - l[u + 1];
-
- /* form (u+1)th discrepancy */
- if (u < NN - KK) /* no discrepancy computed on last iteration */
- {
- if (s[u + 1] != -1)
- d[u + 1] = alpha_to[s[u + 1]];
- else
- d[u + 1] = 0;
-
- for (i = 1; i <= l[u + 1]; i++)
- if ((s[u + 1 - i] != -1) && (elp[u + 1][i] != 0))
- d[u + 1] ^= alpha_to[(s[u + 1 - i]
- + index_of[elp[u + 1][i]]) % NN];
-
- d[u + 1] = index_of[d[u + 1]]; /* put d[u+1] into index form */
- }
- } while ((u < NN - KK) && (l[u + 1] <= TT));
-
- u++;
- if (l[u] <= TT) /* can correct error */
- {
- /* put elp into index form */
- for (i = 0; i <= l[u]; i++)
- elp[u][i] = index_of[elp[u][i]];
-
- /* find roots of the error location polynomial */
- for (i = 1; i <= l[u]; i++)
- reg[i] = elp[u][i];
-
- count = 0;
-
- for (i = 1; i <= NN; i++) {
- q = 1;
-
- for (j = 1; j <= l[u]; j++)
- if (reg[j] != -1) {
- reg[j] = (reg[j] + j) % NN;
- q ^= alpha_to[reg[j]];
- };
-
- if (!q) /* store root and error location number indices */
- {
- root[count] = i;
- loc[count] = NN - i;
- count++;
- };
- };
-
- if (count == l[u]) /* no. roots = degree of elp hence <= tt errors */
- {
- /* form polynomial z(x) */
- for (i = 1; i <= l[u]; i++) /* Z[0] = 1 always - do not need */
- {
- if ((s[i] != -1) && (elp[u][i] != -1))
- z[i] = alpha_to[s[i]] ^ alpha_to[elp[u][i]];
- else if ((s[i] != -1) && (elp[u][i] == -1))
- z[i] = alpha_to[s[i]];
- else if ((s[i] == -1) && (elp[u][i] != -1))
- z[i] = alpha_to[elp[u][i]];
- else
- z[i] = 0;
-
- for (j = 1; j < i; j++)
- if ((s[j] != -1) && (elp[u][i - j] != -1))
- z[i] ^= alpha_to[(elp[u][i - j] + s[j]) % NN];
-
- z[i] = index_of[z[i]]; /* put into index form */
- };
-
- /* evaluate errors at locations given by error location numbers loc[i] */
- for (i = 0; i < NN; i++) {
- err[i] = 0;
- if (recd[i] != -1) /* convert recd[] to polynomial form */
- recd[i] = alpha_to[recd[i]];
- else
- recd[i] = 0;
- }
-
- for (i = 0; i < l[u]; i++) /* compute numerator of error term first */
- {
- err[loc[i]] = 1; /* accounts for z[0] */
-
- for (j = 1; j <= l[u]; j++)
- if (z[j] != -1)
- err[loc[i]] ^= alpha_to[(z[j] + j * root[i]) % NN];
-
- if (err[loc[i]] != 0) {
- err[loc[i]] = index_of[err[loc[i]]];
- q = 0; /* form denominator of error term */
-
- for (j = 0; j < l[u]; j++)
- if (j != i)
- q += index_of[1 ^ alpha_to[(loc[j] + root[i]) % NN]];
-
- q = q % NN;
- err[loc[i]] = alpha_to[(err[loc[i]] - q + NN) % NN];
- recd[loc[i]] ^= err[loc[i]]; /*recd[i] must be in polynomial form */
- }
- }
- } else {
- /* no. roots != degree of elp => >tt errors and cannot solve */
- irrecoverable_error = 1;
- }
-
- } else {
- /* elp has degree >tt hence cannot solve */
- irrecoverable_error = 1;
- }
-
- } else {
- /* no non-zero syndromes => no errors: output received codeword */
- for (i = 0; i < NN; i++)
- if (recd[i] != -1) /* convert recd[] to polynomial form */
- recd[i] = alpha_to[recd[i]];
- else
- recd[i] = 0;
- }
-
- if (irrecoverable_error) {
- for (i = 0; i < NN; i++) /* could return error flag if desired */
- if (recd[i] != -1) /* convert recd[] to polynomial form */
- recd[i] = alpha_to[recd[i]];
- else
- recd[i] = 0; /* just output received codeword as is */
- }
-
- return irrecoverable_error;
- }
-};
-
-class CRS362017 : public CReedSolomon63<8>
-{
-public:
- CRS362017();
- ~CRS362017();
-
- bool decode(unsigned char* data);
-
- void encode(unsigned char* data);
-
-private:
-};
-
-class CRS241213 : public CReedSolomon63<6>
-{
-public:
- CRS241213();
- ~CRS241213();
-
- bool decode(unsigned char* data);
-
- void encode(unsigned char* data);
-
-private:
-};
-
-class CRS24169 : public CReedSolomon63<4>
-{
-public:
- CRS24169();
- ~CRS24169();
-
- bool decode(unsigned char* data);
-
- void encode(unsigned char* data);
-
-private:
-};
-
-#endif
diff --git a/RS241213.cpp b/RS241213.cpp
new file mode 100644
index 0000000..60fee2d
--- /dev/null
+++ b/RS241213.cpp
@@ -0,0 +1,370 @@
+/*
+* 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 "RS241213.h"
+
+#include
+#include
+
+const unsigned char ENCODE_MATRIX[12U][24U] = {
+ {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 062, 044, 003, 025, 014, 016, 027, 003, 053, 004, 036, 047},
+ {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 011, 012, 011, 011, 016, 064, 067, 055, 001, 076, 026, 073},
+ {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 003, 001, 005, 075, 014, 006, 020, 044, 066, 006, 070, 066},
+ {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 021, 070, 027, 045, 016, 067, 023, 064, 073, 033, 044, 021},
+ {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 030, 022, 003, 075, 015, 015, 033, 015, 051, 003, 053, 050},
+ {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 001, 041, 027, 056, 076, 064, 021, 053, 004, 025, 001, 012},
+ {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 061, 076, 021, 055, 076, 001, 063, 035, 030, 013, 064, 070},
+ {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 024, 022, 071, 056, 021, 035, 073, 042, 057, 074, 043, 076},
+ {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 072, 042, 005, 020, 043, 047, 033, 056, 001, 016, 013, 076},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 072, 014, 065, 054, 035, 025, 041, 016, 015, 040, 071, 026},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 073, 065, 036, 061, 042, 022, 017, 004, 044, 020, 025, 005},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 071, 005, 055, 003, 071, 034, 060, 011, 074, 002, 041, 050}};
+
+const unsigned int rsGFexp[64] = {
+ 1, 2, 4, 8, 16, 32, 3, 6, 12, 24, 48, 35, 5, 10, 20, 40,
+ 19, 38, 15, 30, 60, 59, 53, 41, 17, 34, 7, 14, 28, 56, 51, 37,
+ 9, 18, 36, 11, 22, 44, 27, 54, 47, 29, 58, 55, 45, 25, 50, 39,
+ 13, 26, 52, 43, 21, 42, 23, 46, 31, 62, 63, 61, 57, 49, 33, 0 };
+
+const unsigned int rsGFlog[64] = {
+ 63, 0, 1, 6, 2, 12, 7, 26, 3, 32, 13, 35, 8, 48, 27, 18,
+ 4, 24, 33, 16, 14, 52, 36, 54, 9, 45, 49, 38, 28, 41, 19, 56,
+ 5, 62, 25, 11, 34, 31, 17, 47, 15, 23, 53, 51, 37, 44, 55, 40,
+ 10, 61, 46, 30, 50, 22, 39, 43, 29, 60, 42, 21, 20, 59, 57, 58 };
+
+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 unsigned char bin2Hex(const unsigned char* input, unsigned int offset)
+{
+ unsigned char output = 0x00U;
+
+ output |= READ_BIT(input, offset + 0U) ? 0x20U : 0x00U;
+ output |= READ_BIT(input, offset + 1U) ? 0x10U : 0x00U;
+ output |= READ_BIT(input, offset + 2U) ? 0x08U : 0x00U;
+ output |= READ_BIT(input, offset + 3U) ? 0x04U : 0x00U;
+ output |= READ_BIT(input, offset + 4U) ? 0x02U : 0x00U;
+ output |= READ_BIT(input, offset + 5U) ? 0x01U : 0x00U;
+
+ return output;
+}
+
+static void hex2Bin(unsigned char input, unsigned char* output, unsigned int offset)
+{
+ WRITE_BIT(output, offset + 0U, input & 0x20U);
+ WRITE_BIT(output, offset + 1U, input & 0x10U);
+ WRITE_BIT(output, offset + 2U, input & 0x08U);
+ WRITE_BIT(output, offset + 3U, input & 0x04U);
+ WRITE_BIT(output, offset + 4U, input & 0x02U);
+ WRITE_BIT(output, offset + 5U, input & 0x01U);
+}
+
+CRS241213::CRS241213()
+{
+}
+
+CRS241213::~CRS241213()
+{
+}
+
+bool CRS241213::decode(unsigned char* data)
+{
+ assert(data != NULL);
+
+ unsigned char HB[24U];
+
+ unsigned int offset = 0U;
+ for (unsigned int i = 0U; i < 24U; i++, offset += 6U)
+ HB[i] = bin2Hex(data, offset);
+
+ //RS (63,63-nroots,nroots+1) decoder where nroots = number of parity bits
+ // rsDec(8, 39) rsDec(16, 27) rsDec(12, 39)
+
+ const int nroots = 12;
+ int lambda[18];//Err+Eras Locator poly
+ int S[17];//syndrome poly
+ int b[18];
+ int t[18];
+ int omega[18];
+ int root[17];
+ int reg[18];
+ int locn[17];
+
+ int i, j, count, r, el, SynError, DiscrR, q, DegOmega, tmp, num1, num2, den, DegLambda;
+
+ //form the syndromes; i.e., evaluate HB(x) at roots of g(x)
+ for (i = 0; i <= nroots - 1; i++) {
+ S[i] = HB[0];
+ }
+
+ for (j = 1; j <= 62; j++) {
+ for (i = 0; i <= nroots - 1; i++) {
+ if (S[i] == 0) {
+ S[i] = HB[j];
+ } else {
+ S[i] = HB[j] ^ rsGFexp[(rsGFlog[S[i]] + i + 1) % 63];
+ }
+ }
+ }
+
+ //convert syndromes to index form, checking for nonzero condition
+ SynError = 0;
+
+ for (i = 0; i <= nroots - 1; i++) {
+ SynError = SynError | S[i];
+ S[i] = rsGFlog[S[i]];
+ }
+
+ if (SynError == 0) {
+ //if syndrome is zero, rsData[] is a codeword and there are
+ //no errors to correct. So return rsData[] unmodified
+ count = 0;
+ return true;
+ }
+
+ for (i = 1; i <= nroots; i++) {
+ lambda[i] = 0;
+ }
+
+ lambda[0] = 1;
+
+ for (i = 0; i <= nroots; i++) {
+ b[i] = rsGFlog[lambda[i]];
+ }
+
+ //begin Berlekamp-Massey algorithm to determine error+erasure
+ //locator polynomial
+ r = 0;
+ el = 0;
+ while (r < nroots) { //r is the step number
+ r = r + 1;
+ //compute discrepancy at the r-th step in poly-form
+ DiscrR = 0;
+
+ for (i = 0; i <= r - 1; i++) {
+ if ((lambda[i] != 0) && (S[r - i - 1] != 63)) {
+ DiscrR = DiscrR ^ rsGFexp[(rsGFlog[lambda[i]] + S[r - i - 1]) % 63];
+ }
+ }
+
+ DiscrR = rsGFlog[DiscrR];//index form
+
+ if (DiscrR == 63) {
+ //shift elements upward one step
+ for (i = nroots; i >= 1; i += -1) {
+ b[i] = b[i - 1];
+ }
+
+ b[0] = 63;
+ } else {
+ //t(x) <-- lambda(x) - DiscrR*x*b(x)
+ t[0] = lambda[0];
+
+ for (i = 0; i <= nroots - 1; i++) {
+ if (b[i] != 63) {
+ t[i + 1] = lambda[i + 1] ^ rsGFexp[(DiscrR + b[i]) % 63];
+ } else {
+ t[i + 1] = lambda[i + 1];
+ }
+ }
+
+ if (2 * el <= r - 1) {
+ el = r - el;
+ //b(x) <-- inv(DiscrR) * lambda(x)
+
+ for (i = 0; i <= nroots; i++) {
+ if (lambda[i]) {
+ b[i] = (rsGFlog[lambda[i]] - DiscrR + 63) % 63;
+ } else {
+ b[i] = 63;
+ }
+ }
+ } else {
+ //shift elements upward one step
+ for (i = nroots; i >= 1; i += -1) {
+ b[i] = b[i - 1];
+ }
+
+ b[0] = 63;
+ }
+
+ for (i = 0; i <= nroots; i++) {
+ lambda[i] = t[i];
+ }
+ }
+ } /* end while() */
+
+ //convert lambda to index form and compute deg(lambda(x))
+ DegLambda = 0;
+ for (i = 0; i <= nroots; i++) {
+ lambda[i] = rsGFlog[lambda[i]];
+
+ if (lambda[i] != 63) {
+ DegLambda = i;
+ }
+ }
+
+ //Find roots of the error+erasure locator polynomial by Chien search
+ for (i = 1; i <= nroots; i++) {
+ reg[i] = lambda[i];
+ }
+
+ count = 0;//number of roots of lambda(x)
+
+ for (i = 1; i <= 63; i++) {
+ q = 1;//lambda[0] is always 0
+
+ for (j = DegLambda; j >= 1; j += -1) {
+ if (reg[j] != 63) {
+ reg[j] = (reg[j] + j) % 63;
+ q = q ^ rsGFexp[reg[j]];
+ }
+ }
+
+ if (q == 0) { //it is a root
+ //store root (index-form) and error location number
+ root[count] = i;
+ locn[count] = i - 1;
+ //if wehave max possible roots, abort search to save time
+ count = count + 1;
+
+ if (count == DegLambda) {
+ break;
+ }
+ }
+ }
+
+ if (DegLambda != count) {
+ //deg(lambda) unequal to number of roots => uncorrectable error detected
+ return false;
+ }
+
+ //compute err+eras evaluator poly omega(x)
+ // = s(x)*lambda(x) (modulo x**nroots). in index form. Also find deg(omega).
+ DegOmega = 0;
+ for (i = 0; i <= nroots - 1; i++) {
+ tmp = 0;
+ if (DegLambda < i) {
+ j = DegLambda;
+ } else {
+ j = i;
+ }
+
+ for ( /* j = j */; j >= 0; j += -1) {
+ if ((S[i - j] != 63) && (lambda[j] != 63)) {
+ tmp = tmp ^ rsGFexp[(S[i - j] + lambda[j]) % 63];
+ }
+ }
+
+ if (tmp) {
+ DegOmega = i;
+ }
+
+ omega[i] = rsGFlog[tmp];
+ }
+
+ omega[nroots] = 63;
+
+ //compute error values in poly-form:
+ // num1 = omega(inv(X(l)))
+ // num2 = inv(X(l))**(FCR - 1)
+ // den = lambda_pr(inv(X(l)))
+ for (j = count - 1; j >= 0; j += -1) {
+ num1 = 0;
+
+ for (i = DegOmega; i >= 0; i += -1) {
+ if (omega[i] != 63) {
+ num1 = num1 ^ rsGFexp[(omega[i] + i * root[j]) % 63];
+ }
+ }
+
+ num2 = rsGFexp[0];
+ den = 0;
+
+ // lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i]
+ if (DegLambda < nroots) {
+ i = DegLambda;
+ } else {
+ i = nroots;
+ }
+
+ for (i = i & ~1; i >= 0; i += -2) {
+ if (lambda[i + 1] != 63) {
+ den = den ^ rsGFexp[(lambda[i + 1] + i * root[j]) % 63];
+ }
+ }
+
+ if (den == 0) {
+ return false;
+ }
+
+ // apply error to data
+ if (num1 != 0) {
+ HB[locn[j]] = HB[locn[j]] ^ (rsGFexp[(rsGFlog[num1] + rsGFlog[num2] + 63 - rsGFlog[den]) % 63]);
+ }
+ }
+
+ offset = 0U;
+ for (unsigned int i = 0U; i < 12U; i++, offset += 6U)
+ hex2Bin(HB[i], data, offset);
+
+ return true;
+}
+
+void CRS241213::encode(unsigned char* data)
+{
+ assert(data != NULL);
+
+ unsigned char codeword[24U];
+
+ for (unsigned int i = 0U; i < 24U; i++) {
+ codeword[i] = 0x00U;
+
+ unsigned int offset = 0U;
+ for (unsigned int j = 0U; j < 12U; j++, offset += 6U) {
+ unsigned char hexbit = bin2Hex(data, offset);
+ codeword[i] ^= gf6Mult(hexbit, ENCODE_MATRIX[j][i]);
+ }
+ }
+
+ unsigned int offset = 0U;
+ for (unsigned int i = 0U; i < 24U; i++, offset += 6U)
+ hex2Bin(codeword[i], data, offset);
+}
+
+// GF(2 ^ 6) multiply(for Reed - Solomon encoder)
+unsigned char CRS241213::gf6Mult(unsigned char a, unsigned char b) const
+{
+ unsigned char p = 0x00U;
+
+ for (unsigned int i = 0U; i < 6U; i++) {
+ if ((b & 0x01U) == 0x01U)
+ p ^= a;
+
+ a <<= 1;
+
+ if ((a & 0x40U) == 0x40U)
+ a ^= 0x43U; // primitive polynomial : x ^ 6 + x + 1
+
+ b >>= 1;
+ }
+
+ return p;
+}
diff --git a/RS241213.h b/RS241213.h
new file mode 100644
index 0000000..523e06a
--- /dev/null
+++ b/RS241213.h
@@ -0,0 +1,36 @@
+/*
+* 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.
+*/
+
+#if !defined(RS241213_H)
+#define RS241213
+
+class CRS241213
+{
+public:
+ CRS241213();
+ ~CRS241213();
+
+ bool decode(unsigned char* data);
+
+ void encode(unsigned char* data);
+
+private:
+ unsigned char gf6Mult(unsigned char a, unsigned char b) const;
+};
+
+#endif