cmMath.h/c : Added cmLFSR() and cmGenGoldCode().

This commit is contained in:
kevin 2015-07-03 12:36:27 -04:00
parent c262a44e72
commit 032d359a90
2 changed files with 166 additions and 2 deletions

131
cmMath.c
View File

@ -1,5 +1,10 @@
#include "cmPrefix.h"
#include "cmGlobal.h"
#include "cmRpt.h"
#include "cmErr.h"
#include "cmCtx.h"
#include "cmMem.h"
#include "cmMallocDebug.h"
#include "cmFloatTypes.h"
#include "cmMath.h"
#include <sys/types.h> // u_char
@ -464,6 +469,128 @@ bool cmIsCloseU( unsigned x0, unsigned x1, double eps )
{
if( x0 == x1 )
return true;
return abs(x0-x1)/(x0+x1) < eps;
if( x0 > x1 )
return (x0-x1)/(x0+x1) < eps;
else
return (x1-x0)/(x0+x1) < eps;
}
//=================================================================
// cmLFSR() implementation based on note at bottom of:
// http://www.ece.cmu.edu/~koopman/lfsr/index.html
void cmLFSR( unsigned lfsrN, unsigned tapMask, unsigned seed, unsigned* yV, unsigned yN )
{
assert( 0 < lfsrN && lfsrN < 32 );
unsigned i;
for(i=0; i<yN; ++i)
{
if( (yV[i] = seed & 1)==1 )
seed = (seed >> 1) ^ tapMask;
else
seed = (seed >> 1);
}
}
bool cmMLS_IsBalanced( const unsigned* xV, int xN)
{
int a = 0;
unsigned i;
for(i=0; i<xN; ++i)
if( xV[i] == 1 )
++a;
return abs(a - (xN-a)) == 1;
}
unsigned _cmGenGoldCopy( int* y, unsigned yi, unsigned yN, unsigned* x, unsigned xN)
{
unsigned i;
for(i=0; i<xN; ++i,++yi)
y[yi] = x[i]==1 ? -1 : 1;
assert(yi <= yN);
return yi;
}
bool cmGenGoldCodes( unsigned lfsrN, unsigned poly_coeff0, unsigned poly_coeff1, unsigned goldN, int* yM, unsigned mlsN )
{
bool retFl = true;
unsigned yi = 0;
unsigned yN = goldN * mlsN;
unsigned* mls0V = cmMemAllocZ(unsigned,mlsN);
unsigned* mls1V = cmMemAllocZ(unsigned,mlsN);
unsigned* xorV = cmMemAllocZ(unsigned,mlsN);
unsigned i,j;
cmLFSR(lfsrN, poly_coeff0, 1 << (lfsrN-1), mls0V, mlsN);
cmLFSR(lfsrN, poly_coeff1, 1 << (lfsrN-1), mls1V, mlsN);
if( cmMLS_IsBalanced(mls0V,mlsN) )
yi = _cmGenGoldCopy(yM, yi, yN, mls0V, mlsN);
if( yi<yN && cmMLS_IsBalanced(mls1V,mlsN) )
yi = _cmGenGoldCopy(yM, yi, yN, mls1V, mlsN);
for(i=0; yi < yN && i<mlsN-1; ++i )
{
for(j=0; j<mlsN; ++j)
xorV[j] = (mls0V[j] + mls1V[ (i+j) % mlsN ]) % 2;
if( cmMLS_IsBalanced(xorV,mlsN) )
yi = _cmGenGoldCopy(yM,yi,yN,xorV,mlsN);
}
if(yi < yN )
{
//rc = cmErrMsg(err,kOpFailAtRC,"Gold code generation failed. Insuffient balanced pairs.");
retFl = false;
}
cmMemFree(mls0V);
cmMemFree(mls1V);
cmMemFree(xorV);
return retFl;
}
bool cmLFSR_Test()
{
// lfsrN = 5; % 5 6 7;
// poly_coeff0 = 0x12; % 0x12 0x21 0x41;
// poly_coeff1 = 0x1e; % 0x1e 0x36 0x72;
unsigned lfsrN = 7;
unsigned pc0 = 0x41;
unsigned pc1 = 0x72;
unsigned mlsN = (1 << lfsrN)-1;
unsigned yN = mlsN*2;
unsigned yV[ yN ];
unsigned i;
cmLFSR( lfsrN, pc0, 1 << (lfsrN-1), yV, yN );
for(i=0; i<mlsN; ++i)
if( yV[i] != yV[i+mlsN] )
return false;
//atVOU_PrintL(NULL,"0x12",yV,mlsN,2);
cmLFSR( lfsrN, pc1, 1 << (lfsrN-1), yV, yN );
//atVOU_PrintL(NULL,"0x17",yV,mlsN,2);
for(i=0; i<mlsN; ++i)
if( yV[i] != yV[i+mlsN] )
return false;
return true;
}

View File

@ -74,4 +74,41 @@ bool cmIsCloseF( float x0, float x1, double eps );
bool cmIsCloseI( int x0, int x1, double eps );
bool cmIsCloseU( unsigned x0, unsigned x1, double eps );
//=================================================================
// Run a length 'lfsrN' linear feedback shift register (LFSR) for 'yN' iterations to
// produce a length 'yN' bit string in yV[yN].
// 'lfsrN' count of bits in the shift register range: 2<= lfsrN <= 32.
// 'tapMask' is a bit mask which gives the tap indexes positions for the LFSR.
// The least significant bit corresponds to the maximum delay tap position.
// The min tap position is therefore denoted by the tap mask bit location 1 << (lfsrN-1).
// A minimum of two taps must exist.
// 'seed' sets the initial delay state.
// 'yV[yN]' is the the output vector
// 'yN' is count of elements in yV.
// The function resturn kOkAtRC on success or kInvalidArgsRCRC if any arguments are invalid.
// /sa cmLFSR_Test.
void cmLFSR( unsigned lfsrN, unsigned tapMask, unsigned seed, unsigned* yV, unsigned yN );
// Example and test code for cmLFSR()
bool cmLFSR_Test();
// Generate a set of 'goldN' Gold codes using the Maximum Length Sequences (MLS) generated
// by a length 'lfsrN' linear feedback shift register.
// 'err' is an error object to be set if the the function fails.
// 'lfsrN' is the length of the Linear Feedback Shift Registers (LFSR) used to generate the MLS.
// 'poly_coeff0' tap mask for the first LFSR.
// 'coeff1' tap mask the the second LFSR.
// 'goldN' is the count of Gold codes to generate.
// 'yM[mlsN', goldN] is a column major output matrix where each column contains a Gold code.
// 'mlsN' is the length of the maximum length sequence for each Gold code which can be
// calculated as mlsN = (1 << a->lfsrN) - 1.
// Note that values of 'lfsrN' and the 'poly_coeffx' must be carefully selected such that
// they will produce a MLS. For example to generate a MLS with length 31 set 'lfsrN' to 5 and
// then select poly_coeff from two different elements of the set {0x12 0x14 0x17 0x1B 0x1D 0x1E}.
// See http://www.ece.cmu.edu/~koopman/lfsr/index.html for a complete set of MSL polynomial
// coefficients for given LFSR lengths.
// Returns false if insufficient balanced pairs exist.
bool cmGenGoldCodes( unsigned lfsrN, unsigned poly_coeff0, unsigned poly_coeff1, unsigned goldN, int* yM, unsigned mlsN );
#endif