diff --git a/libm65/CMakeLists.txt b/libm65/CMakeLists.txt index f80199df4..77cd2454e 100644 --- a/libm65/CMakeLists.txt +++ b/libm65/CMakeLists.txt @@ -71,6 +71,7 @@ set (FSRCS ftnquit.f90 gen65.f90 getdphi.f90 + graycode65.f90 iqcal.f90 iqfix.f90 jt65code.f90 @@ -138,6 +139,7 @@ set (FSRCS set (CSRCS decode_rs.c encode_rs.c + ftrsd2.c gran.c igray.c init_rs.c diff --git a/libm65/decode_rs.c b/libm65/decode_rs.c index aecc47faf..91f582ac1 100644 --- a/libm65/decode_rs.c +++ b/libm65/decode_rs.c @@ -1,6 +1,7 @@ /* Reed-Solomon decoder * Copyright 2002 Phil Karn, KA9Q * May be used under the terms of the GNU General Public License (GPL) + * Modified by Steve Franke, K9AN, for use in a soft-symbol RS decoder */ #ifdef DEBUG @@ -21,243 +22,247 @@ #endif int DECODE_RS( -#ifdef FIXED -DTYPE *data, int *eras_pos, int no_eras,int pad){ -#else -void *p,DTYPE *data, int *eras_pos, int no_eras){ - struct rs *rs = (struct rs *)p; +#ifndef FIXED + void *p, #endif - int deg_lambda, el, deg_omega; - int i, j, r,k; - DTYPE u,q,tmp,num1,num2,den,discr_r; - DTYPE lambda[NROOTS+1], s[NROOTS]; /* Err+Eras Locator poly - * and syndrome poly */ - DTYPE b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1]; - DTYPE root[NROOTS], reg[NROOTS+1], loc[NROOTS]; - int syn_error, count; - -#ifdef FIXED - /* Check pad parameter for validity */ - if(pad < 0 || pad >= NN) - return -1; -#endif - - /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ - for(i=0;i 0) { - /* Init lambda to be the erasure locator polynomial */ - lambda[1] = ALPHA_TO[MODNN(PRIM*(NN-1-eras_pos[0]))]; - for (i = 1; i < no_eras; i++) { - u = MODNN(PRIM*(NN-1-eras_pos[i])); - for (j = i+1; j > 0; j--) { - tmp = INDEX_OF[lambda[j - 1]]; - if(tmp != A0) - lambda[j] ^= ALPHA_TO[MODNN(u + tmp)]; - } - } - -#if DEBUG >= 1 - /* Test code that verifies the erasure locator polynomial just constructed - Needed only for decoder debugging. */ + DTYPE *data, int *eras_pos, int no_eras, int calc_syn){ - /* find roots of the erasure location polynomial */ - for(i=1;i<=no_eras;i++) - reg[i] = INDEX_OF[lambda[i]]; - - count = 0; - for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) { - q = 1; - for (j = 1; j <= no_eras; j++) - if (reg[j] != A0) { - reg[j] = MODNN(reg[j] + j); - q ^= ALPHA_TO[reg[j]]; - } - if (q != 0) - continue; - /* store root and error location number indices */ - root[count] = i; - loc[count] = k; - count++; - } - if (count != no_eras) { - printf("count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras); - count = -1; - goto finish; +#ifndef FIXED + struct rs *rs = (struct rs *)p; +#endif + int deg_lambda, el, deg_omega; + int i, j, r,k; + DTYPE u,q,tmp,num1,num2,den,discr_r; + DTYPE lambda[NROOTS+1]; // Err+Eras Locator poly + static DTYPE s[51]; // and syndrome poly + DTYPE b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1]; + DTYPE root[NROOTS], reg[NROOTS+1], loc[NROOTS]; + int syn_error, count; + + if( calc_syn ) { + /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ + for(i=0;i 0) { + /* Init lambda to be the erasure locator polynomial */ + lambda[1] = ALPHA_TO[MODNN(PRIM*(NN-1-eras_pos[0]))]; + for (i = 1; i < no_eras; i++) { + u = MODNN(PRIM*(NN-1-eras_pos[i])); + for (j = i+1; j > 0; j--) { + tmp = INDEX_OF[lambda[j - 1]]; + if(tmp != A0) + lambda[j] ^= ALPHA_TO[MODNN(u + tmp)]; + } + } + +#if DEBUG >= 1 + /* Test code that verifies the erasure locator polynomial just constructed + Needed only for decoder debugging. */ + + /* find roots of the erasure location polynomial */ + for(i=1;i<=no_eras;i++) + reg[i] = INDEX_OF[lambda[i]]; + + count = 0; + for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) { + q = 1; + for (j = 1; j <= no_eras; j++) + if (reg[j] != A0) { + reg[j] = MODNN(reg[j] + j); + q ^= ALPHA_TO[reg[j]]; + } + if (q != 0) + continue; + /* store root and error location number indices */ + root[count] = i; + loc[count] = k; + count++; + } + if (count != no_eras) { + printf("count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras); + count = -1; + goto finish; + } #if DEBUG >= 2 - printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); - for (i = 0; i < count; i++) - printf("%d ", loc[i]); - printf("\n"); + printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); + for (i = 0; i < count; i++) + printf("%d ", loc[i]); + printf("\n"); #endif #endif - } - for(i=0;i 0; j--){ - if (reg[j] != A0) { - reg[j] = MODNN(reg[j] + j); - q ^= ALPHA_TO[reg[j]]; - } - } - if (q != 0) - continue; /* Not a root */ - /* store root (index-form) and error location number */ -#if DEBUG>=2 - printf("count %d root %d loc %d\n",count,i,k); -#endif - root[count] = i; - loc[count] = k; - /* If we've already found max possible roots, - * abort the search to save time - */ - if(++count == deg_lambda) - break; - } - if (deg_lambda != count) { - /* - * deg(lambda) unequal to number of roots => uncorrectable - * error detected - */ - count = -1; - goto finish; - } - /* - * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo - * x**NROOTS). in index form. Also find deg(omega). - */ - deg_omega = deg_lambda-1; - for (i = 0; i <= deg_omega;i++){ - tmp = 0; - for(j=i;j >= 0; j--){ - if ((s[i - j] != A0) && (lambda[j] != A0)) - tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])]; - } - omega[i] = INDEX_OF[tmp]; - } - - /* - * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = - * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form - */ - for (j = count-1; j >=0; j--) { - num1 = 0; - for (i = deg_omega; i >= 0; i--) { - if (omega[i] != A0) - num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])]; - } - num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)]; - den = 0; + for(i=0;i= 0; i -=2) { - if(lambda[i+1] != A0) - den ^= ALPHA_TO[MODNN(lambda[i+1] + i * root[j])]; + /* + * Begin Berlekamp-Massey algorithm to determine error+erasure + * locator polynomial + */ + r = no_eras; + el = no_eras; + while (++r <= NROOTS) { /* r is the step number */ + /* Compute discrepancy at the r-th step in poly-form */ + discr_r = 0; + for (i = 0; i < r; i++){ + if ((lambda[i] != 0) && (s[r-i-1] != A0)) { + discr_r ^= ALPHA_TO[MODNN(INDEX_OF[lambda[i]] + s[r-i-1])]; + } + } + discr_r = INDEX_OF[discr_r]; /* Index form */ + if (discr_r == A0) { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1],b,NROOTS*sizeof(b[0])); + b[0] = A0; + } else { + /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ + t[0] = lambda[0]; + for (i = 0 ; i < NROOTS; i++) { + if(b[i] != A0) + t[i+1] = lambda[i+1] ^ ALPHA_TO[MODNN(discr_r + b[i])]; + else + t[i+1] = lambda[i+1]; + } + if (2 * el <= r + no_eras - 1) { + el = r + no_eras - el; + /* + * 2 lines below: B(x) <-- inv(discr_r) * + * lambda(x) + */ + for (i = 0; i <= NROOTS; i++) + b[i] = (lambda[i] == 0) ? A0 : MODNN(INDEX_OF[lambda[i]] - discr_r + NN); + } else { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1],b,NROOTS*sizeof(b[0])); + b[0] = A0; + } + memcpy(lambda,t,(NROOTS+1)*sizeof(t[0])); + } } -#if DEBUG >= 1 - if (den == 0) { - printf("\n ERROR: denominator = 0\n"); - count = -1; - goto finish; + + /* Convert lambda to index form and compute deg(lambda(x)) */ + deg_lambda = 0; + for(i=0;i 0; j--){ + if (reg[j] != A0) { + reg[j] = MODNN(reg[j] + j); + q ^= ALPHA_TO[reg[j]]; + } + } + if (q != 0) + continue; /* Not a root */ + /* store root (index-form) and error location number */ +#if DEBUG>=2 + printf("count %d root %d loc %d\n",count,i,k); #endif - /* Apply error to data */ - if (num1 != 0 && loc[j] >= PAD) { - data[loc[j]-PAD] ^= ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])]; + root[count] = i; + loc[count] = k; + /* If we've already found max possible roots, + * abort the search to save time + */ + if(++count == deg_lambda) + break; } - } - finish: - if(eras_pos != NULL){ - for(i=0;i uncorrectable + * error detected + */ + count = -1; + goto finish; + } + /* + * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**NROOTS). in index form. Also find deg(omega). + */ + deg_omega = 0; + for (i = 0; i < NROOTS;i++){ + tmp = 0; + j = (deg_lambda < i) ? deg_lambda : i; + for(;j >= 0; j--){ + if ((s[i - j] != A0) && (lambda[j] != A0)) + tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])]; + } + if(tmp != 0) + deg_omega = i; + omega[i] = INDEX_OF[tmp]; + } + omega[NROOTS] = A0; + + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for (j = count-1; j >=0; j--) { + num1 = 0; + for (i = deg_omega; i >= 0; i--) { + if (omega[i] != A0) + num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])]; + } + num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)]; + den = 0; + + /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ + for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) { + if(lambda[i+1] != A0) + den ^= ALPHA_TO[MODNN(lambda[i+1] + i * root[j])]; + } + if (den == 0) { +#if DEBUG >= 1 + printf("\n ERROR: denominator = 0\n"); +#endif + count = -1; + goto finish; + } + /* Apply error to data */ + if (num1 != 0) { + data[loc[j]] ^= ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])]; + } + } +finish: + if(eras_pos != NULL){ + for(i=0;i= NN) - return; -#endif - memset(bb,0,NROOTS*sizeof(DTYPE)); - for(i=0;i dev_null') -!#else - iret=system('kvasd -q > dev_null') -!#endif -! call timer('kvasd ',1) - if(iret.ne.0) then - if(first) write(*,1000) iret -1000 format('Error in KV decoder, or no KV decoder present.'/ & - 'Return code:',i8,'. Will use BM algorithm.') - ndec=0 - first=.false. - go to 20 - endif + ntry=0 + param=0 - read(22,rec=2) nsec2,ncount,dat4 - j=nsec2 !Silence compiler warning - decoded=' ' - ltext=.false. - if(ncount.ge.0) then - call unpackmsg(dat4,decoded) !Unpack the user message - if(iand(dat4(10),8).ne.0) ltext=.true. - do i=2,12 - if(dat4(i).ne.dat4(1)) go to 20 - enddo - write(13,*) 'Bad decode?',nhist,nfail,ipk,' ',dat4,decoded - ncount=-1 !Suppress supposedly bogus decodes - decoded=' ' - endif - endif -20 if(ndec.eq.0) then - call indexx(63,mrprob,indx) - do i=1,nemax - j=indx(i) - if(mrprob(j).gt.120) then - ne2=i-1 - go to 2 - endif - era(i)=j-1 - enddo - ne2=nemax -2 decoded=' ' - do nerase=0,ne2,2 - call rs_decode(mrsym,era,nerase,dat4,ncount) - if(ncount.ge.0) then - call unpackmsg(dat4,decoded) - go to 900 - endif - enddo + call timer('ftrsd ',0) + call ftrsd2(mrsym,mrprob,mr2sym,mr2prob,ntrials,correct,param,ntry) + call timer('ftrsd ',1) + ncandidates=param(0) + nhard=param(1) + nsoft=param(2) + nerased=param(3) + rtt=0.001*param(4) + ntotal=param(5) + qual=0.001*param(7) + nd0=81 + r00=0.87 + if(naggressive.eq.10) then + nd0=83 + r00=0.90 endif + if(ntotal.le.nd0 .and. rtt.le.r00) nft=1 + n=naggressive + if(nhard.gt.50) nft=0 + if(nhard.gt.h0(n)) nft=0 + if(ntotal.gt.d0(n)) nft=0 + if(rtt.gt.r0(n)) nft=0 -900 return + ncount=-1 + decoded=' ' + ltext=.false. + if(nft.gt.0) then +! Turn the corrected symbol array into channel symbols for subtraction; +! pass it back to jt65a via common block "chansyms65". + do i=1,12 + dat4(i)=correct(13-i) + enddo + do i=1,63 + itmp(i)=correct(64-i) + enddo + correct(1:63)=itmp(1:63) + call interleave63(correct,63,1) + call graycode65(correct,63,1) + call unpackmsg(dat4,decoded) !Unpack the user message + ncount=0 + if(iand(dat4(10),8).ne.0) ltext=.true. + endif +900 continue + if(nft.eq.1 .and. nhard.lt.0) decoded=' ' +! write(81,3001) naggressive,ncandidates,nhard,ntotal,rtt,qual,decoded +!3001 format(i2,i6,i3,i4,2f8.2,2x,a22) + + return end subroutine extract + +subroutine getpp(workdat,p) + + integer workdat(63) + integer a(63) + common/test001/s3a(64,63),mrs(63),mrs2(63) + + a(1:63)=workdat(63:1:-1) + call interleave63(a,1) + call graycode(a,63,1,a) + + psum=0. + do j=1,63 + i=a(j)+1 + x=s3a(i,j) + s3a(i,j)=0. + psum=psum + x + s3a(i,j)=x + enddo + p=psum/63.0 + + return +end subroutine getpp diff --git a/libm65/ftrsd2.c b/libm65/ftrsd2.c new file mode 100644 index 000000000..241312483 --- /dev/null +++ b/libm65/ftrsd2.c @@ -0,0 +1,213 @@ +/* + ftrsd2.c + + A soft-decision decoder for the JT65 (63,12) Reed-Solomon code. + + This decoding scheme is built around Phil Karn's Berlekamp-Massey + errors and erasures decoder. The approach is inspired by a number of + publications, including the stochastic Chase decoder described + in "Stochastic Chase Decoding of Reed-Solomon Codes", by Leroux et al., + IEEE Communications Letters, Vol. 14, No. 9, September 2010 and + "Soft-Decision Decoding of Reed-Solomon Codes Using Successive Error- + and-Erasure Decoding," by Soo-Woong Lee and B. V. K. Vijaya Kumar. + + Steve Franke K9AN and Joe Taylor K1JT + */ + +#include +#include +#include +#include +#include +#include "rs2.h" + +static void *rs; +void getpp_(int workdat[], float *pp); + +void ftrsd2_(int mrsym[], int mrprob[], int mr2sym[], int mr2prob[], + int* ntrials0, int correct[], int param[], int ntry[]) +{ + int rxdat[63], rxprob[63], rxdat2[63], rxprob2[63]; + int workdat[63]; + int indexes[63]; + int era_pos[51]; + int i, j, numera, nerr, nn=63; + int ntrials = *ntrials0; + int nhard=0,nhard_min=32768,nsoft=0,nsoft_min=32768; + int ntotal=0,ntotal_min=32768,ncandidates; + int nera_best=0; + float pp,pp1,pp2; + static unsigned int nseed; + +// Power-percentage symbol metrics - composite gnnf/hf + int perr[8][8] = { + { 4, 9, 11, 13, 14, 14, 15, 15}, + { 2, 20, 20, 30, 40, 50, 50, 50}, + { 7, 24, 27, 40, 50, 50, 50, 50}, + {13, 25, 35, 46, 52, 70, 50, 50}, + {17, 30, 42, 54, 55, 64, 71, 70}, + {25, 39, 48, 57, 64, 66, 77, 77}, + {32, 45, 54, 63, 66, 75, 78, 83}, + {51, 58, 57, 66, 72, 77, 82, 86}}; + + +// Initialize the KA9Q Reed-Solomon encoder/decoder + unsigned int symsize=6, gfpoly=0x43, fcr=3, prim=1, nroots=51; + rs=init_rs_int(symsize, gfpoly, fcr, prim, nroots, 0); + +// Reverse the received symbol vectors for BM decoder + for (i=0; i<63; i++) { + rxdat[i]=mrsym[62-i]; + rxprob[i]=mrprob[62-i]; + rxdat2[i]=mr2sym[62-i]; + rxprob2[i]=mr2prob[62-i]; + } + +// Sort rxprob to find indexes of the least reliable symbols + int k, pass, tmp, nsym=63; + int probs[63]; + for (i=0; i<63; i++) { + indexes[i]=i; + probs[i]=rxprob[i]; + } + for (pass = 1; pass <= nsym-1; pass++) { + for (k = 0; k < nsym - pass; k++) { + if( probs[k] < probs[k+1] ) { + tmp = probs[k]; + probs[k] = probs[k+1]; + probs[k+1] = tmp; + tmp = indexes[k]; + indexes[k] = indexes[k+1]; + indexes[k+1] = tmp; + } + } + } + +// See if we can decode using BM HDD, and calculate the syndrome vector. + memset(era_pos,0,51*sizeof(int)); + numera=0; + memcpy(workdat,rxdat,sizeof(rxdat)); + nerr=decode_rs_int(rs,workdat,era_pos,numera,1); + if( nerr >= 0 ) { + // Hard-decision decoding succeeded. Save codeword and some parameters. + nhard=0; + for (i=0; i<63; i++) { + if( workdat[i] != rxdat[i] ) nhard=nhard+1; + } + memcpy(correct,workdat,63*sizeof(int)); + param[0]=0; + param[1]=nhard; + param[2]=0; + param[3]=0; + param[4]=0; + param[5]=0; + param[7]=1000*1000; + ntry[0]=0; + return; + } + +/* +Hard-decision decoding failed. Try the FT soft-decision method. +Generate random erasure-locator vectors and see if any of them +decode. This will generate a list of "candidate" codewords. The +soft distance between each candidate codeword and the received +word is estimated by finding the largest (pp1) and second-largest +(pp2) outputs from a synchronized filter-bank operating on the +symbol spectra, and using these to decide which candidate +codeword is "best". +*/ + + nseed=1; //Seed for random numbers + float ratio; + int thresh, nsum; + int thresh0[63]; + ncandidates=0; + nsum=0; + int ii,jj; + for (i=0; i= 0 ) { + // We have a candidate codeword. Find its hard and soft distance from + // the received word. Also find pp1 and pp2 from the full array + // s3(64,63) of synchronized symbol spectra. + ncandidates=ncandidates+1; + nhard=0; + nsoft=0; + for (i=0; i<63; i++) { + if(workdat[i] != rxdat[i]) { + nhard=nhard+1; + if(workdat[i] != rxdat2[i]) { + nsoft=nsoft+rxprob[i]; + } + } + } + nsoft=63*nsoft/nsum; + ntotal=nsoft+nhard; + + getpp_(workdat,&pp); + if(pp>pp1) { + pp2=pp1; + pp1=pp; + nsoft_min=nsoft; + nhard_min=nhard; + ntotal_min=ntotal; + memcpy(correct,workdat,63*sizeof(int)); + nera_best=numera; + ntry[0]=k; + } else { + if(pp>pp2 && pp!=pp1) pp2=pp; + } + if(nhard_min <= 41 && ntotal_min <= 71) break; + } + if(k == ntrials) ntry[0]=k; + } + + param[0]=ncandidates; + param[1]=nhard_min; + param[2]=nsoft_min; + param[3]=nera_best; + param[4]=1000.0*pp2/pp1; + param[5]=ntotal_min; + param[6]=ntry[0]; + param[7]=1000.0*pp2; + param[8]=1000.0*pp1; + if(param[0]==0) param[2]=-1; + return; +} diff --git a/libm65/graycode65.f90 b/libm65/graycode65.f90 new file mode 100644 index 000000000..bb2c669ce --- /dev/null +++ b/libm65/graycode65.f90 @@ -0,0 +1,9 @@ +subroutine graycode65(dat,n,idir) + + integer dat(n) + do i=1,n + dat(i)=igray(dat(i),idir) + enddo + + return +end subroutine graycode65 diff --git a/libm65/init_rs.c b/libm65/init_rs.c index 7e1e09e5b..ce9e8cb70 100644 --- a/libm65/init_rs.c +++ b/libm65/init_rs.c @@ -30,30 +30,25 @@ void FREE_RS(void *p){ * fcr = first root of RS code generator polynomial, index form * prim = primitive element to generate polynomial roots * nroots = RS code generator polynomial degree (number of roots) - * pad = padding bytes at front of shortened block */ -void *INIT_RS(int symsize,int gfpoly,int fcr,int prim, - int nroots,int pad){ +void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigned prim, + unsigned int nroots){ struct rs *rs; int i, j, sr,root,iprim; - /* Check parameter ranges */ - if(symsize < 0 || symsize > 8*sizeof(DTYPE)) + if(symsize > 8*sizeof(DTYPE)) return NULL; /* Need version with ints rather than chars */ - if(fcr < 0 || fcr >= (1<= (1<= (1<= (1<= (1<= (1<= ((1<mm = symsize; rs->nn = (1<pad = pad; rs->alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); if(rs->alpha_to == NULL){ diff --git a/libm65/int.h b/libm65/int.h index 056241e12..ada5bfd4c 100644 --- a/libm65/int.h +++ b/libm65/int.h @@ -7,19 +7,18 @@ /* Reed-Solomon codec control block */ struct rs { - int mm; /* Bits per symbol */ - int nn; /* Symbols per block (= (1<= rs->nn) { x -= rs->nn; x = (x >> rs->mm) + (x & rs->nn); @@ -33,12 +32,10 @@ static int modnn(struct rs *rs,int x){ #define ALPHA_TO (rs->alpha_to) #define INDEX_OF (rs->index_of) #define GENPOLY (rs->genpoly) -//#define NROOTS (rs->nroots) -#define NROOTS (51) +#define NROOTS (rs->nroots) #define FCR (rs->fcr) #define PRIM (rs->prim) #define IPRIM (rs->iprim) -#define PAD (rs->pad) #define A0 (NN) #define ENCODE_RS encode_rs_int @@ -47,9 +44,9 @@ static int modnn(struct rs *rs,int x){ #define FREE_RS free_rs_int void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); -int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras); -void *INIT_RS(int symsize,int gfpoly,int fcr, - int prim,int nroots,int pad); +int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras, int calc_syn); +void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, + unsigned int prim,unsigned int nroots); void FREE_RS(void *p); diff --git a/libm65/rs2.h b/libm65/rs2.h new file mode 100644 index 000000000..c2b807d15 --- /dev/null +++ b/libm65/rs2.h @@ -0,0 +1,16 @@ +/* User include file for the Reed-Solomon codec + * Copyright 2002, Phil Karn KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ + +/* General purpose RS codec, integer symbols */ +void encode_rs_int(void *rs,int *data,int *parity); +int decode_rs_int(void *rs,int *data,int *eras_pos,int no_eras, int calc_syn); +void *init_rs_int(int symsize,int gfpoly,int fcr, + int prim,int nroots,int pad); +void free_rs_int(void *rs); + +/* Tables to map from conventional->dual (Taltab) and + * dual->conventional (Tal1tab) bases + */ +extern unsigned char Taltab[],Tal1tab[]; diff --git a/mainwindow.cpp b/mainwindow.cpp index 19a5a3707..c11b80783 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -33,7 +33,7 @@ TxTune* g_pTxTune = NULL; QSharedMemory mem_m65("mem_m65"); QString rev="$Rev$"; //Must update by hand ???? -QString Program_Title_Version=" MAP65 v2.5, r" + rev.mid(6,4) + +QString Program_Title_Version=" MAP65 v2.6, r" + rev.mid(6,4) + " by K1JT"; extern const int RxDataFrequency = 96000;