Remove the .../lib/superfox directory and its contents.

This commit is contained in:
Joe Taylor 2024-03-05 11:03:43 -05:00
parent ce08913e3a
commit ca18e58c77
28 changed files with 1 additions and 2331 deletions

View File

@ -342,7 +342,6 @@ set (wsjt_FSRCS
lib/wavhdr.f90
lib/qra/q65/q65_encoding_modules.f90
lib/ft8/ft8_a7.f90
lib/superfox/sfox_mod.f90
# remaining non-module sources
lib/addit.f90
@ -428,9 +427,6 @@ set (wsjt_FSRCS
lib/fspread_lorentz.f90
lib/ft8/foxfilt.f90
lib/ft8/foxgen.f90
lib/superfox/foxgen2.f90
lib/superfox/sfox_assemble.f90
lib/superfox/sfox_wave.f90
lib/ft8/foxgen_wrap.f90
lib/freqcal.f90
lib/ft8/ft8apset.f90
@ -525,6 +521,7 @@ set (wsjt_FSRCS
lib/sec0.f90
lib/sec_midn.f90
lib/setup65.f90
lib/sfox_wave.f90
lib/sh65.f90
lib/sh65snr.f90
lib/slasubs.f
@ -590,13 +587,6 @@ set (wsjt_FSRCS
lib/fst4/get_crc24.f90
lib/fst4/fst4_baseline.f90
lib/77bit/hash22calc.f90
lib/superfox/sfox_gen.f90
lib/superfox/sfox_sync.f90
lib/superfox/sfox_demod.f90
lib/superfox/sym_prob.f90
lib/superfox/getpp3.f90
lib/superfox/ftrsd3.f90
lib/superfox/ran1.f90
)
# temporary workaround for a gfortran v7.3 ICE on Fedora 27 64-bit
@ -637,10 +627,6 @@ set (wsjt_CSRCS
lib/vit213.c
lib/wisdom.c
lib/wrapkarn.c
lib/superfox/init_rs.c
lib/superfox/encode_rs.c
lib/superfox/decode_rs.c
lib/superfox/rs_sf.c
${ldpc_CSRCS}
${qra_CSRCS}
)
@ -1169,12 +1155,6 @@ target_link_libraries (test_snr wsjt_fort)
add_executable (q65sim lib/qra/q65/q65sim.f90)
target_link_libraries (q65sim wsjt_fort wsjt_cxx)
#add_executable (rstest lib/superfox/rstest.f90)
#target_link_libraries (rstest wsjt_fort wsjt_cxx)
add_executable (sfoxtest lib/superfox/sfoxtest.f90)
target_link_libraries (sfoxtest wsjt_fort wsjt_cxx)
add_executable (q65code lib/qra/q65/q65code.f90)
target_link_libraries (q65code wsjt_fort wsjt_cxx)

View File

@ -1,27 +0,0 @@
CC = gcc
FC = gfortran
FFLAGS = -O2 -Wall -fbounds-check
CFLAGS= -O9 -Wall
# Default rules
%.o: %.c
${CC} ${CFLAGS} -c $<
%.o: %.f
${FC} ${FFLAGS} -c $<
%.o: %.F
${FC} ${FFLAGS} -c $<
%.o: %.f90
${FC} ${FFLAGS} -c $<
%.o: %.F90
${FC} ${FFLAGS} -c $<
all: sfox_tx
OBJS1 = sfox_tx.o foxgen2.o sfox_assemble.o
sfox_tx: $(OBJS1)
$(FC) -o sfox_tx $(OBJS1) libwsjt_fort.a
.PHONY : clean
clean:
-rm -f *.o *.exe

View File

@ -1,263 +0,0 @@
/* Reed-Solomon decoder
* Copyright 2002 Phil Karn, KA9Q
* May be used under the terms of the GNU General Public License (GPL)
*/
#ifdef DEBUG
#include <stdio.h>
#endif
#include <string.h>
#define NULL ((void *)0)
#define min(a,b) ((a) < (b) ? (a) : (b))
#ifdef FIXED
#include "fixed.h"
#elif defined(BIGSYM)
#include "int_sf.h"
#else
#include "char.h"
#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;
#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<NROOTS;i++)
s[i] = data[0];
for(j=1;j<NN-PAD;j++){
for(i=0;i<NROOTS;i++){
if(s[i] == 0){
s[i] = data[j];
} else {
s[i] = data[j] ^ ALPHA_TO[MODNN(INDEX_OF[s[i]] + (FCR+i)*PRIM)];
}
}
}
/* Convert syndromes to index form, checking for nonzero condition */
syn_error = 0;
for(i=0;i<NROOTS;i++){
syn_error |= s[i];
s[i] = INDEX_OF[s[i]];
}
if (!syn_error) {
/* if syndrome is zero, data[] is a codeword and there are no
* errors to correct. So return data[] unmodified
*/
count = 0;
goto finish;
}
memset(&lambda[1],0,NROOTS*sizeof(lambda[0]));
lambda[0] = 1;
if (no_eras > 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");
#endif
#endif
}
for(i=0;i<NROOTS+1;i++)
// printf("%d %d %d\n",i,lambda[i],INDEX_OF[lambda[i]]);
b[i] = INDEX_OF[lambda[i]];
/*
* 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]));
}
}
/* Convert lambda to index form and compute deg(lambda(x)) */
deg_lambda = 0;
for(i=0;i<NROOTS+1;i++){
lambda[i] = INDEX_OF[lambda[i]];
if(lambda[i] != A0)
deg_lambda = i;
}
/* Find roots of the error+erasure locator polynomial by Chien search */
memcpy(&reg[1],&lambda[1],NROOTS*sizeof(reg[0]));
count = 0; /* Number of roots of lambda(x) */
for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) {
q = 1; /* lambda[0] is always 0 */
for (j = deg_lambda; j > 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;
/* 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 DEBUG >= 1
if (den == 0) {
printf("\n ERROR: denominator = 0\n");
count = -1;
goto finish;
}
#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])];
}
}
finish:
if(eras_pos != NULL){
for(i=0;i<count;i++)
eras_pos[i] = loc[i];
}
return count;
}

View File

@ -1,52 +0,0 @@
/* Reed-Solomon encoder
* Copyright 2002, Phil Karn, KA9Q
* May be used under the terms of the GNU General Public License (GPL)
*/
#include <string.h>
#ifdef FIXED
#include "fixed.h"
#elif defined(BIGSYM)
#include "int_sf.h"
#else
#include "char.h"
#endif
void ENCODE_RS(
#ifdef FIXED
DTYPE *data, DTYPE *bb,int pad){
#else
void *p,DTYPE *data, DTYPE *bb){
struct rs *rs = (struct rs *)p;
#endif
int i, j;
DTYPE feedback;
#ifdef FIXED
/* Check pad parameter for validity */
if(pad < 0 || pad >= NN)
return;
#endif
memset(bb,0,NROOTS*sizeof(DTYPE));
for(i=0;i<NN-NROOTS-PAD;i++){
feedback = INDEX_OF[data[i] ^ bb[0]];
if(feedback != A0){ /* feedback term is non-zero */
#ifdef UNNORMALIZED
/* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
* always be for the polynomials constructed by init_rs()
*/
feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
#endif
for(j=1;j<NROOTS;j++)
bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
}
/* Shift */
memmove(&bb[0],&bb[1],sizeof(DTYPE)*(NROOTS-1));
if(feedback != A0)
bb[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
else
bb[NROOTS-1] = 0;
}
}

View File

@ -1,128 +0,0 @@
subroutine foxgen2(nslots,cmsg,line)
! Called from foxgen() when it's time to encode a SuperFox message and
! generate the waveform to be transmitted. We need to parse the old-style
! Fox messages and extract the necessary pieces.
! use packjt77
character*120 line
character*40 cmsg(5) !Old-style Fox messages are here
character*37 msg
character*26 sfmsg
character*13 mycall
character*4 mygrid
character*6 hiscall_1,hiscall_2
character*4 rpt1,rpt2
character*13 w(19)
integer nw(19)
integer ntype !Message type: 0 Free Text
! 1 CQ MyCall MyGrid
! 2 Call_1 MyCall RR73
! 3 Call_1 MyCall rpt1
! 4 Call_1 RR73; Call_2 <MyCall> rpt2
if(nslots.lt.1 .or. nslots.gt.5) return
k=0
do i=1,nslots
hiscall_1=''
hiscall_2=''
mycall=''
mygrid=''
rpt1=''
rpt2=''
msg=cmsg(i)(1:37)
call split77(msg,nwords,nw,w)
ntype=0
if(msg(1:3).eq.'CQ ') then
ntype=1
mycall=w(2)(1:12)
mygrid=w(3)(1:4)
else if(index(msg,';').gt.0) then
ntype=4
hiscall_1=w(1)(1:6)
hiscall_2=w(3)(1:6)
rpt1='RR73'
rpt2=w(5)(1:4)
mycall=w(4)(2:nw(4)-1)
else if(index(msg,' RR73').gt.0) then
ntype=2
hiscall_1=w(1)(1:6)
mycall=w(2)(1:12)
rpt1='RR73'
else if(nwords.eq.3 .and. nw(3).eq.3 .and. &
(w(3)(1:1).eq.'-' .or. w(3)(1:1).eq.'+')) then
ntype=3
hiscall_1=w(1)(1:6)
mycall=w(2)(1:12)
rpt1=w(3)(1:4)
endif
! write(*,3001) ntype,cmsg(i),hiscall_1,rpt1,hiscall_2,rpt2, &
! mycall(1:6),mygrid
!3001 format(i1,2x,a37,1x,a6,1x,a4,1x,a6,1x,a4,1x,a6,1x,a4)
k=k+1
if(ntype.le.3) call sfox_assemble(ntype,k,msg(1:26),mycall,mygrid,line)
if(ntype.eq.4) then
sfmsg=w(1)(1:nw(1))//' '//mycall(1:len(trim(mycall))+1)//'RR73'
call sfox_assemble(2,k,sfmsg,mycall,mygrid,line)
sfmsg=w(3)(1:nw(3))//' '//mycall(1:len(trim(mycall))+1)//w(5)(1:3)
k=k+1
call sfox_assemble(3,k,sfmsg,mycall,mygrid,line)
endif
enddo
call sfox_assemble(ntype,11,msg(1:26),mycall,mygrid,line) !k=11 to finish up
return
end subroutine foxgen2
subroutine split77(msg,nwords,nw,w)
! Convert msg to upper case; collapse multiple blanks; parse into words.
character*37 msg
character*13 w(19)
character*1 c,c0
character*6 bcall_1
logical ok1
integer nw(19)
iz=len(trim(msg))
j=0
k=0
n=0
c0=' '
w=' '
do i=1,iz
if(ichar(msg(i:i)).eq.0) msg(i:i)=' '
c=msg(i:i) !Single character
if(c.eq.' ' .and. c0.eq.' ') cycle !Skip leading/repeated blanks
if(c.ne.' ' .and. c0.eq.' ') then
k=k+1 !New word
n=0
endif
j=j+1 !Index in msg
n=n+1 !Index in word
if(c.ge.'a' .and. c.le.'z') c=char(ichar(c)-32) !Force upper case
msg(j:j)=c
if(n.le.13) w(k)(n:n)=c !Copy character c into word
c0=c
enddo
iz=j !Message length
nwords=k !Number of words in msg
if(nwords.le.0) go to 900
do i=1,nwords
nw(i)=len(trim(w(i)))
enddo
msg(iz+1:)=' '
if(nwords.lt.3) go to 900
call chkcall(w(3),bcall_1,ok1)
if(ok1 .and. w(1)(1:3).eq.'CQ ') then
w(1)='CQ_'//w(2)(1:10) !Make "CQ " into "CQ_"
w(2:12)=w(3:13) !Move all remaining words down by one
nwords=nwords-1
endif
900 return
end subroutine split77

View File

@ -1,217 +0,0 @@
/*
ftrsd3.c
A soft-decision decoder for Reed-Solomon codes.
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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include "rs2.h"
static void *rs;
void getpp3_(int workdat[], float *pp);
void ftrsd3_(int rxdat[], int rxprob[], int rxdat2[], int rxprob2[],
int* ntrials0, int correct[], int param[], int ntry[])
{
// int rxdat[127], rxprob[127], rxdat2[127], rxprob2[127];
int workdat[127];
int indexes[127];
int era_pos[79];
int i, j, numera, nerr, nn=127;
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}};
printf("A\n");
// Initialize the KA9Q Reed-Solomon encoder/decoder
unsigned int symsize=7, gfpoly=0x89, fcr=3, prim=1, nroots=79;
rs=init_rs_int(symsize, gfpoly, fcr, prim, nroots, 0);
printf("B\n");
// Sort rxprob to find indexes of the least reliable symbols
int k, pass, tmp, nsym=127;
int probs[127];
for (i=0; i<127; i++) {
indexes[i]=i;
probs[i]=rxprob[i];
}
printf("C\n");
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;
}
}
}
printf("D\n");
// See if we can decode using BM HDD, and calculate the syndrome vector.
memset(era_pos,0,79*sizeof(int));
numera=0;
memcpy(workdat,rxdat,127*sizeof(int));
nerr=decode_rs_int(rs,workdat,era_pos,numera,1);
printf("E\n");
if( nerr >= 0 ) {
// Hard-decision decoding succeeded. Save codeword and some parameters.
nhard=0;
for (i=0; i<127; i++) {
if( workdat[i] != rxdat[i] ) nhard=nhard+1;
}
memcpy(correct,workdat,127*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;
}
if(nerr==-1) {
printf("nerr:', %d\n",nerr);
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[127];
ncandidates=0;
nsum=0;
int ii,jj;
for (i=0; i<nn; i++) {
nsum=nsum+rxprob[i];
j = indexes[126-i];
ratio = (float)rxprob2[j]/((float)rxprob[j]+0.01);
ii = 7.999*ratio;
jj = (126-i)/8;
thresh0[i] = 1.3*perr[ii][jj];
}
if(nsum<=0) return;
pp1=0.0;
pp2=0.0;
for (k=1; k<=ntrials; k++) {
memset(era_pos,0,79*sizeof(int));
memcpy(workdat,rxdat,127*sizeof(int));
/*
Mark a subset of the symbols as erasures.
Run through the ranked symbols, starting with the worst, i=0.
NB: j is the symbol-vector index of the symbol with rank i.
*/
numera=0;
for (i=0; i<nn; i++) {
j = indexes[126-i];
thresh=thresh0[i];
long int ir;
// Generate a random number ir, 0 <= ir < 100 (see POSIX.1-2001 example).
nseed = nseed * 1103515245 + 12345;
ir = (unsigned)(nseed/65536) % 32768;
ir = (100*ir)/32768;
if((ir < thresh ) && numera < 79) {
era_pos[numera]=j;
numera=numera+1;
}
}
nerr=decode_rs_int(rs,workdat,era_pos,numera,0);
if( nerr >= 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,127) of synchronized symbol spectra.
ncandidates=ncandidates+1;
nhard=0;
nsoft=0;
for (i=0; i<127; i++) {
if(workdat[i] != rxdat[i]) {
nhard=nhard+1;
if(workdat[i] != rxdat2[i]) {
nsoft=nsoft+rxprob[i];
}
}
}
nsoft=127*nsoft/nsum;
ntotal=nsoft+nhard;
pp=0.;
// getpp3_(workdat,&pp);
if(pp>pp1) {
pp2=pp1;
pp1=pp;
nsoft_min=nsoft;
nhard_min=nhard;
ntotal_min=ntotal;
memcpy(correct,workdat,127*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]= pp1 > 0 ? 1000.0*pp2/pp1 : 1000.0;
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;
}

View File

@ -1,192 +0,0 @@
subroutine ftrsd3(s3,chansym0,rxdat,rxprob,rxdat2,rxprob2,ntrials0, &
correct,param,ntry)
! Soft-decision decoder for Reed-Solomon codes.
! 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
use sfox_mod
real s3(0:NQ-1,0:NN-1) !Symbol spectra
integer chansym0(0:NN-1) !Transmitted codeword
integer rxdat(0:NN-1) !Hard-decision symbol values
integer rxprob(0:NN-1) !Probabilities that rxdat values are correct
integer rxdat2(0:NN-1) !Second most probable symbol values
integer rxprob2(0:NN-1) !Probabilities that rxdat2 values are correct
integer workdat(0:NN-1) !Work array
integer correct(0:NN-1) !Corrected codeword
integer indexes(0:NN-1) !For sorting probabilities
integer probs(0:NN-1) !Temp array for sorting probabilities
integer thresh0(0:NN-1) !Temp array for thresholds
integer era_pos(0:NN-KK-1) !Index values for erasures
integer param(0:8)
integer*8 nseed,ir !No unsigned int in Fortran
integer pass,tmp,thresh
integer perr(0:7,0:7)
data perr/ 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/
ntrials=ntrials0
nhard=0
nhard_min=32768
nsoft=0
nsoft_min=32768
ntotal=0
ntotal_min=32768
nera_best=0
nsym=nn
do i=0,NN-1
indexes(i)=i
probs(i)=rxprob(i)
enddo
do pass=1,nsym-1
do k=0,nsym-pass-1
if(probs(k).lt.probs(k+1)) then
tmp=probs(k)
probs(k)=probs(k+1)
probs(k+1)=tmp
tmp=indexes(k)
indexes(k)=indexes(k+1)
indexes(k+1)=tmp
endif
enddo
enddo
correct=-1
era_pos=0
numera=0
workdat=rxdat
call rs_decode_sf(workdat,era_pos,numera,nerr) !Call the decoder
nerr=-1
if(nerr.ge.0) then
! Hard-decision decoding succeeded. Save codeword and some parameters.
nhard=count(workdat.ne.rxdat)
correct=workdat
param(0)=0
param(1)=nhard
param(2)=0
param(3)=0
param(4)=0
param(5)=0
param(7)=1000*1000 !???
ntry=0
go to 900
endif
! 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
ncandidates=0
nsum=0
do i=0,NN-1
nsum=nsum+rxprob(i)
j=indexes(NN-1-i)
ratio=float(rxprob2(j))/(float(rxprob(j))+0.01)
ii=7.999*ratio
jj=int((7.999/NN)*(NN-1-i))
thresh0(i)=0.90*perr(jj,ii)
enddo
if(nsum.le.0) return
pp1=0.
pp2=0.
do k=1,ntrials
era_pos=0
workdat=rxdat
! Mark a subset of the symbols as erasures.
! Run through the ranked symbols, starting with the worst, i=0.
! NB: j is the symbol-vector index of the symbol with rank i.
ncaught=0
numera=0
do i=0,NN-1
j=indexes(NN-1-i)
thresh=thresh0(i)
! Generate a random number ir, 0 <= ir <= 100 (see POSIX.1-2001 example).
ir=100.0*ran1(nseed)
if((ir.lt.thresh) .and. numera.lt. 0.69*(NN-KK)) then
era_pos(numera)=j
numera=numera+1
if(rxdat(j).ne.chansym0(j)) then
ncaught=ncaught+1
endif
endif
enddo
call rs_decode_sf(workdat,era_pos,numera,nerr) !Call the decoder
if( nerr.ge.0) then
! 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(NQ,NN) of synchronized symbol spectra.
ncandidates=ncandidates+1
nhard=0
nsoft=0
do i=0,NN-1
if(workdat(i).ne. rxdat(i)) then
nhard=nhard+1;
if(workdat(i) .ne. rxdat2(i)) nsoft=nsoft+rxprob(i)
endif
enddo
nsoft=NN*nsoft/nsum
ntotal=nsoft+nhard
pp=0.
call getpp3(s3,workdat,pp)
! write(*,5001) ncandidates,nhard,nsoft,ntotal,pp,pp1,pp2
!5001 format(4i8,3f7.3)
if(pp.gt.pp1) then
pp2=pp1
pp1=pp
nsoft_min=nsoft
nhard_min=nhard
ntotal_min=ntotal
correct=workdat
nera_best=numera
ntry=k
else
if(pp.gt.pp2 .and. pp.ne.pp1) pp2=pp
endif
if(nhard_min.le.60 .and. ntotal_min.le.90) exit !### Needs tuning
endif
if(k.eq.ntrials) ntry=k
enddo
param(0)=ncandidates
param(1)=nhard_min
param(2)=nsoft_min
param(3)=nera_best
param(4)=1000
if(pp1.gt.0.0) param(4)=1000.0*pp2/pp1
param(5)=ntotal_min
param(6)=ntry
param(7)=1000.0*pp2
param(8)=1000.0*pp1
if(param(0).eq.0) param(2)=-1
900 return
end subroutine ftrsd3

View File

@ -1,25 +0,0 @@
subroutine get_crc14(mc,len,ncrc)
!
! 1. To calculate 14-bit CRC, mc(1:len-14) is the message and mc(len-13:len) are zero.
! 2. To check a received CRC, mc(1:len is the received message plus CRC.
! ncrc will be zero if the received message/CRC are consistent
!
character c14*14
integer*1 mc(len)
integer*1 r(15),p(15)
integer ncrc
! polynomial for 14-bit CRC 0x6757
data p/1,1,0,0,1,1,1,0,1,0,1,0,1,1,1/
! divide by polynomial
r=mc(1:15)
do i=0,len-15
r(15)=mc(i+15)
r=mod(r+r(1)*p,2)
r=cshift(r,1)
enddo
write(c14,'(14b1)') r(1:14)
read(c14,'(b14.14)') ncrc
end subroutine get_crc14

View File

@ -1,22 +0,0 @@
subroutine getpp3(s3,workdat,p)
use sfox_mod
real s3(NQ,NN)
integer workdat(NN)
integer a(NN)
! a(1:NN)=workdat(NN:1:-1)
a=workdat
psum=0.
do j=1,NN
i=a(j)+1
x=s3(i,j)
s3(i,j)=0.
psum=psum + x
s3(i,j)=x
enddo
p=psum/NN
return
end subroutine getpp3

View File

@ -1,126 +0,0 @@
/* Initialize a RS codec
*
* Copyright 2002 Phil Karn, KA9Q
* May be used under the terms of the GNU General Public License (GPL)
*/
#include <stdlib.h>
#ifdef CCSDS
#include "ccsds.h"
#elif defined(BIGSYM)
#include "int_sf.h"
#else
#include "char.h"
#endif
#define NULL ((void *)0)
void FREE_RS(void *p){
struct rs *rs = (struct rs *)p;
free(rs->alpha_to);
free(rs->index_of);
free(rs->genpoly);
free(rs);
}
/* Initialize a Reed-Solomon codec
* symsize = symbol size, bits (1-8)
* gfpoly = Field generator polynomial coefficients
* 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){
struct rs *rs;
int i, j, sr,root,iprim;
/* Check parameter ranges */
if(symsize < 0 || symsize > 8*sizeof(DTYPE))
return NULL; /* Need version with ints rather than chars */
if(fcr < 0 || fcr >= (1<<symsize))
return NULL;
if(prim <= 0 || prim >= (1<<symsize))
return NULL;
if(nroots < 0 || nroots >= (1<<symsize))
return NULL; /* Can't have more roots than symbol values! */
if(pad < 0 || pad >= ((1<<symsize) -1 - nroots))
return NULL; /* Too much padding */
rs = (struct rs *)calloc(1,sizeof(struct rs));
rs->mm = symsize;
rs->nn = (1<<symsize)-1;
rs->pad = pad;
rs->alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1));
if(rs->alpha_to == NULL){
free(rs);
return NULL;
}
rs->index_of = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1));
if(rs->index_of == NULL){
free(rs->alpha_to);
free(rs);
return NULL;
}
/* Generate Galois field lookup tables */
rs->index_of[0] = A0; /* log(zero) = -inf */
rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */
sr = 1;
for(i=0;i<rs->nn;i++){
rs->index_of[sr] = i;
rs->alpha_to[i] = sr;
sr <<= 1;
if(sr & (1<<symsize))
sr ^= gfpoly;
sr &= rs->nn;
}
if(sr != 1){
/* field generator polynomial is not primitive! */
free(rs->alpha_to);
free(rs->index_of);
free(rs);
return NULL;
}
/* Form RS code generator polynomial from its roots */
rs->genpoly = (DTYPE *)malloc(sizeof(DTYPE)*(nroots+1));
if(rs->genpoly == NULL){
free(rs->alpha_to);
free(rs->index_of);
free(rs);
return NULL;
}
rs->fcr = fcr;
rs->prim = prim;
rs->nroots = nroots;
/* Find prim-th root of 1, used in decoding */
for(iprim=1;(iprim % prim) != 0;iprim += rs->nn)
;
rs->iprim = iprim / prim;
rs->genpoly[0] = 1;
for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) {
rs->genpoly[i+1] = 1;
/* Multiply rs->genpoly[] by @**(root + x) */
for (j = i; j > 0; j--){
if (rs->genpoly[j] != 0)
rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)];
else
rs->genpoly[j] = rs->genpoly[j-1];
}
/* rs->genpoly[0] can never be zero */
rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)];
}
/* convert rs->genpoly[] to index form for quicker encoding */
for (i = 0; i <= nroots; i++)
rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
return rs;
}

View File

@ -1,56 +0,0 @@
/* Include file to configure the RS codec for integer symbols
*
* Copyright 2002, Phil Karn, KA9Q
* May be used under the terms of the GNU General Public License (GPL)
*/
#define DTYPE int
/* Reed-Solomon codec control block */
struct rs {
int mm; /* Bits per symbol */
int nn; /* Symbols per block (= (1<<mm)-1) */
DTYPE *alpha_to; /* log lookup table */
DTYPE *index_of; /* Antilog lookup table */
DTYPE *genpoly; /* Generator polynomial */
int nroots; /* Number of generator roots = number of parity symbols */
int fcr; /* First consecutive root, index form */
int prim; /* Primitive element, index form */
int iprim; /* prim-th root of 1, index form */
int pad; /* Padding bytes in shortened block */
};
static inline int modnn(struct rs *rs,int x){
while (x >= rs->nn) {
x -= rs->nn;
x = (x >> rs->mm) + (x & rs->nn);
}
return x;
}
#define MODNN(x) modnn(rs,x)
#define MM (rs->mm)
#define NN (rs->nn)
#define ALPHA_TO (rs->alpha_to)
#define INDEX_OF (rs->index_of)
#define GENPOLY (rs->genpoly)
#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_sf
#define DECODE_RS decode_rs_sf
#define INIT_RS init_rs_sf
#define FREE_RS free_rs_sf
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);
void FREE_RS(void *p);

View File

@ -1,39 +0,0 @@
subroutine plotspec(dat)
use sfox_mod
real dat(NMAX)
real s(0:NSPS/2)
complex c(0:NSPS-1)
integer ipk(1)
nblks=NZ/NSPS
s=0.
fac=1.0/NSPS
do j=1,nblks
ib=j*NSPS
ia=ib-NSPS+1
c=fac*dat(ia:ib)
call four2a(c,NSPS,1,-1,1)
do i=0,NSPS/2
s(i)=s(i) + real(c(i))**2 + aimag(c(i))**2
enddo
enddo
df=12000.0/NSPS
ipk=maxloc(s)
f0=df*(ipk(1)-1)
p_sig_plus_noise=maxval(s)
p_noise=0.
do i=0,NSPS/2
f=i*df
if(f.le.2500+df .and. abs(f-f0).gt.0.5*df) p_noise=p_noise + s(i)
write(40,1000) f,s(i)
1000 format(2f10.3)
enddo
p_sig=p_sig_plus_noise - p_noise*df/2500.0
snr=p_sig/p_noise
snrdb=db(snr)
write(*,1100) snrdb
1100 format('Measured SNR:',f7.2)
end subroutine plotspec

View File

@ -1,28 +0,0 @@
FUNCTION ran1(idum)
INTEGER idum,IA,IM,IQ,IR,NTAB,NDIV
REAL ran1,AM,EPS,RNMX
PARAMETER (IA=16807,IM=2147483647,AM=1./IM,IQ=127773,IR=2836, &
NTAB=32,NDIV=1+(IM-1)/NTAB,EPS=1.2e-7,RNMX=1.-EPS)
INTEGER j,k,iv(NTAB),iy
SAVE iv,iy
DATA iv /NTAB*0/, iy /0/
if (idum.le.0.or.iy.eq.0) then
idum=max(-idum,1)
do j=NTAB+8,1,-1
k=idum/IQ
idum=IA*(idum-k*IQ)-IR*k
if (idum.lt.0) idum=idum+IM
if (j.le.NTAB) iv(j)=idum
enddo
iy=iv(1)
endif
k=idum/IQ
idum=IA*(idum-k*IQ)-IR*k
if (idum.lt.0) idum=idum+IM
j=1+iy/NDIV
iy=iv(j)
iv(j)=idum
ran1=min(AM*iy,RNMX)
return
END FUNCTION ran1

View File

@ -1,33 +0,0 @@
#include <stdio.h>
#include "rs_sf.h"
static void *rs_sf;
static int first=1;
static int nn,kk,nroots,npad;
void rs_init_sf_(int *mm, int *nq, int *nn0, int *kk0, int *nfz)
// Initialize the RS decoder.
{
// Save parameters nn, kk, nroots, npad for global access
nn=*nn0;
kk=*kk0;
nroots=nn-kk;
npad=*nq-1-nn;
int gfpoly=0x43; //For *mm=6
if(*mm==7) gfpoly=0x89;
if(*mm==8) gfpoly=0x11d;
rs_sf=init_rs_sf(*mm,gfpoly,*nfz,1,nroots,npad);
first=0;
}
void rs_encode_sf_(int *msg, int *parsym)
// Encode information symbols msg[KK], producing parity symbols parsym[nroots].
{
encode_rs_sf(rs_sf,msg,parsym); //Compute the parity symbols
}
void rs_decode_sf_(int *recd, int *era_pos, int *numera, int *nerr)
{
*nerr=decode_rs_sf(rs_sf,recd,era_pos,*numera);
}

View File

@ -1,35 +0,0 @@
/* 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, 8-bit symbols */
void encode_rs_char(void *rs,unsigned char *data,unsigned char *parity);
int decode_rs_char(void *rs,unsigned char *data,int *eras_pos,
int no_eras);
void *init_rs_char(int symsize,int gfpoly,
int fcr,int prim,int nroots,
int pad);
void free_rs_char(void *rs);
/* General purpose RS codec, integer symbols */
void encode_rs_sf(void *rs,int *data,int *parity);
int decode_rs_sf(void *rs,int *data,int *eras_pos,int no_eras);
void *init_rs_sf(int symsize,int gfpoly,int fcr,
int prim,int nroots,int pad);
void free_rs_sf(void *rs);
/* CCSDS standard (255,223) RS codec with conventional (*not* dual-basis)
* symbol representation
*/
void encode_rs_8(unsigned char *data,unsigned char *parity,int pad);
int decode_rs_8(unsigned char *data,int *eras_pos,int no_eras,int pad);
/* CCSDS standard (255,223) RS codec with dual-basis symbol representation */
void encode_rs_ccsds(unsigned char *data,unsigned char *parity,int pad);
int decode_rs_ccsds(unsigned char *data,int *eras_pos,int no_eras,int pad);
/* Tables to map from conventional->dual (Taltab) and
* dual->conventional (Tal1tab) bases
*/
extern unsigned char Taltab[],Tal1tab[];

View File

@ -1,71 +0,0 @@
program rst8
character arg*8
integer*1 dat0(223) !Generated data
integer*1 parsym(32) !Parity symbols
integer*1 cword0(255) !Generated codeword
integer*1 cword(255) !Rcvd codeword with errors; will be corrected in place
integer iera(0:200) !Positions of additional erasures
integer decode_rs_8
nargs=iargc()
if(nargs.ne.3) then
print*,'Usage: rst8 npad nera nerr'
print*,'Example: rst8 178 0 16'
go to 999
endif
nkv=0
call getarg(1,arg)
read(arg,*) npad
call getarg(2,arg)
read(arg,*) nera
call getarg(3,arg)
read(arg,*) nerr
! The basic code RS(255,223) is punctured with npad leading zeros.
nn=255-npad
kk=223-npad
write(*,1000) nn,kk
1000 format('Basic code is RS(255,223). npad:',i4,' N:',i4,' K:',i4)
! Generate a message, kk symbols with values 1 to kk.
do i=1,kk
dat0(i)=i
enddo
write(*,1002)
1002 format('Generated message symbols:')
write(*,1004) dat0(1:kk)
1004 format(20i4)
call encode_rs_8(dat0,parsym,npad) !Get parity symbols
cword0(1:kk)=dat0(1:kk) !Genetated codeword
cword0(kk+1:nn)=parsym(1:nn-kk)
write(*,1006)
1006 format(/'Encoded channel symbols')
write(*,1004) cword0(1:nn)
cword=cword0
do i=1,nerr !Introduce errors
j=nn+1-i
cword(j)=mod(cword(j)+1,256)
enddo
write(*,1008) nera
1008 format(/'Received channel symbols, with',i4,' errors at the end:')
write(*,1004) cword(1:nn)
do i=0,nera-1
iera(i)=i
enddo
nfixed=decode_rs_8(cword,iera,nera,npad)
ibad=count(cword(1:kk).ne.cword0(1:kk))
write(*,1010)
1010 format(/'Decoded result:')
write(*,1004) cword(1:kk)
maxfix=(nn-kk)/2 + nera/2
write(*,1100) nerr,nera,nfixed,maxfix
1100 format(/'nerr:',i3,' nera:',i3,' nfixed:',i3,' maxfix:',i3)
999 end program rst8

View File

@ -1,84 +0,0 @@
program rstest
character arg*8
integer dat0(255) !Message symbols
integer parsym(255) !Parity symbols
integer chansym0(255) !Encoded data, Karn
integer chansym(255) !Encoded data with errors
integer dat(235) !Decoded data, i*4
! integer, target :: parsym(255)
integer iera(0:200) !Positions of erasures
integer gfpoly
! type(c_ptr) :: rs
data gfpoly/z'11d'/
nargs=iargc()
if(nargs.ne.5) then
print*,'Usage: rstest M N K nera nerr'
print*,'Examples: rstest 6 63 12 0 25'
print*,' rstest 7 127 51 0 38'
print*,' rstest 8 255 51 0 102'
print*,' rstest 8 255 223 0 16'
go to 999
endif
nkv=0
call getarg(1,arg)
read(arg,*) mm
call getarg(2,arg)
read(arg,*) nn
call getarg(3,arg)
read(arg,*) kk
call getarg(4,arg)
read(arg,*) nera
call getarg(5,arg)
read(arg,*) nerr
! Initialize the Karn codec
nq=2**mm
nfz=3
call rs_init_sf(mm,nq,nn,kk,nfz) !Initialize the Karn RS codec
! Generate kk message symbols. (Values must be in range 0 to nq-1.)
do i=1,kk
dat0(i)=i
enddo
write(*,1000) mm,nn,kk,nera,nerr
1000 format('M:',i2,' N:',i4,' K:',i4,' nera:',i4,' nerr:',i4/ &
'Generated data symbols')
write(*,1002) dat0(1:kk)
1002 format(20i4)
call rs_encode_sf(dat0,parsym) !Compute parity symbols
chansym0(1:kk)=dat0(1:kk)
chansym0(kk+1:nn)=parsym(1:nn-kk)
write(*,1004)
1004 format(/'Encoded channel symbols')
write(*,1002) chansym0(1:nn)
chansym=chansym0
do i=1,nerr !Introduce errors
chansym(i)=mod(chansym(i)+1,nq)
enddo
write(*,1006) nera
1006 format(/'Recovered channel symbols, with',i4,' errors at the start:')
write(*,1002) chansym(1:nn)
do i=0,nera-1
iera(i)=i
enddo
call rs_decode_sf(chansym,iera,nera,nfixed)
dat(1:kk)=chansym(1:kk)
ibad=count(dat(1:kk).ne.dat0(1:kk))
write(*,1008)
1008 format(/'Decoded result:')
write(*,1002) dat(1:kk)
maxfix=(nn-kk)/2 + nera/2
write(*,1100) nerr,nera,nfixed,maxfix
1100 format(/'nerr:',i3,' nera:',i3,' nfixed:',i3,' maxfix:',i3)
999 end program rstest

View File

@ -1,92 +0,0 @@
subroutine sfox_assemble(ntype,k,msg,mycall0,mygrid0,line)
! In subsequent calls, assemble all necessary information for a SuperFox
! transmission.
character*120 line
character*26 msg
character*26 msg0,msg1,msg2(5),msg3(5)
character*4 rpt2(5)
character*6 hiscall(10)
character*13 mycall0,mycall
character*4 mygrid0,mygrid
integer ntype !Message type: 0 Free Text
! 1 CQ MyCall MyGrid
! 2 Call_1 MyCall RR73
! 3 Call_1 MyCall rpt
integer nmsg(0:3) !Number of messages of type ntype
data nmsg/0,0,0,0/,nbits/0/,ntx/0/,nb_mycall/0/
save
if(mycall0(1:1).ne.' ') mycall=mycall0
if(mygrid0(1:1).ne.' ') mygrid=mygrid0
if(ntype.ge.1) nb_mycall=28 !### Allow for nonstandard MyCall ###
if(sum(nmsg).eq.0) then
hiscall=' '
rpt2=' '
endif
if(k.le.10) then
if(ntype.eq.0) then
if(nbits+nb_mycall.le.191) then !Enough room for a free text message?
nmsg(ntype)=nmsg(ntype)+1
nbits=nbits+142
msg0=msg
endif
else if(ntype.eq.1) then
if(nbits+nb_mycall.le.318) then !Enough room for a CQ ?
nmsg(ntype)=nmsg(ntype)+1
nbits=nbits+15
msg1=msg
endif
else if(ntype.eq.2) then
if(nbits+nb_mycall.le.305) then !Enough room for a RR73 message?
nmsg(ntype)=nmsg(ntype)+1
nbits=nbits+28
j=nmsg(ntype)
msg2(j)=msg
i1=index(msg,' ')
hiscall(j+5)=msg(1:i1-1)
endif
else if(ntype.eq.3) then
if(nbits+nb_mycall.le.300) then !Enough room for a message with report?
nmsg(ntype)=nmsg(ntype)+1
nbits=nbits+33
j=nmsg(ntype)
msg3(j)=msg
i1=index(msg,' ')
hiscall(j)=msg(1:i1-1)
i1=max(index(msg,'-'),index(msg,'+'))
rpt2(j)=msg(i1:i1+3)
endif
endif
return
endif
if(k.ge.11) then
! All pieces are now available. Put them into a command line for external
! program sfox_tx.
ntx=ntx+1 !Transmission number
nbits=nbits+nb_mycall !Add bits for MyCall
if(nmsg(1).ge.1) then
line=msg1
else
line=trim(mycall)
do i=1,nmsg(3)
line=trim(line)//' '//trim(hiscall(i))//' '//rpt2(i)
enddo
do i=1,nmsg(2)
line=trim(line)//' '//trim(hiscall(i+5))
enddo
endif
nmsg=0
nbits=0
nb_mycall=0
hiscall=' '
rpt2=' '
endif
return
end subroutine sfox_assemble

View File

@ -1,33 +0,0 @@
subroutine sfox_demod(crcvd,f,t,isync,s3)
use sfox_mod
complex crcvd(NMAX) !Signal as received
complex c(0:NSPS-1) !Work array, one symbol long
real s3(0:NQ-1,0:NN-1) !Synchronized symbol spectra
integer isync(44)
! integer ipk(1)
j0=nint(12000.0*(t+0.5))
df=12000.0/NSPS
i0=nint(f/df)-NQ/2
k=-1
do n=1,NDS !Loop over all symbols
if(any(isync(1:NS).eq.n)) cycle
jb=n*NSPS + j0
ja=jb-NSPS+1
if(ja.lt.1 .or. jb.gt.NMAX) cycle
k=k+1
c=crcvd(ja:jb)
call four2a(c,NSPS,1,-1,1) !Compute symbol spectrum
do i=0,NQ-1
s3(i,k)=real(c(i0+i))**2 + aimag(c(i0+i))**2
enddo
! ipk=maxloc(s3(0:NQ-1,k))
! if(k.lt.10) print*,'AAA',k,ipk(1)-1
enddo
call pctile(s3,NQ*NN,50,base)
s3=s3/base
return
end subroutine sfox_demod

View File

@ -1,41 +0,0 @@
subroutine sfox_gen(idat,f0,fsample,isync,itone,cdat)
use sfox_mod
complex cdat(NMAX) !Generated complex waveform
complex w,wstep
integer idat(NN)
integer isync(44)
integer itone(171)
twopi=8.0*atan(1.0)
! Create the itone sequence: data symbols and interspersed sync symbols
j=1
k=0
do i=1,NDS
if(j.le.NS .and. i.eq.isync(j)) then
if(j.lt.NS) j=j+1 !Index for next sync symbol
itone(i)=0 !Insert sync symbol at tone 0
else
k=k+1
itone(i)=idat(k) + 1 !Symbol value 0 is transmitted at tone 1, etc.
endif
enddo
df=fsample/NSPS
w=1.0
j=0
i0=NQ/2
! Generate the waveform
do k=1,NDS !Loop over all symbols
dphi=(f0 + (itone(k)-i0)*df)*(twopi/fsample)
wstep=cmplx(cos(dphi),sin(dphi))
do i=1,NSPS !NSPS samples per symbol
j=j+1
w=w*wstep
cdat(j)=w
enddo
enddo
return
end subroutine sfox_gen

View File

@ -1,73 +0,0 @@
module sfox_mod
parameter (NMAX=15*12000) !Samples in iwave (180,000)
integer MM,NQ,NN,KK,NS,NDS,NFZ,NSPS,NSYNC,NZ,NFFT1
real baud,tsym,bw
contains
subroutine sfox_init(mm0,nn0,kk0,itu,fspread,delay,fsample,ns0)
character*2 itu
integer isps(54)
integer iloc(1)
data isps/ 896, 960, 972, 980,1000,1008,1024,1029,1050,1080, &
1120,1125,1134,1152,1176,1200,1215,1225,1250,1260, &
1280,1296,1323,1344,1350,1372,1400,1440,1458,1470, &
1500,1512,1536,1568,1575,1600,1620,1680,1701,1715, &
1728,1750,1764,1792,1800,1875,1890,1920,1944,1960, &
2000,2016,2025,2048/
MM=mm0 !Bits per symbol
NQ=2**MM !Q, number of MFSK tones
NN=nn0 !Codeword length
KK=kk0 !Number of information symbols
NS=ns0 !Number of sync symbols
NDS=NN+NS !Total number of channel symbols
NFZ=3 !First zero
jsps=nint(12.8*fsample/NDS)
iloc=minloc(abs(isps-jsps))
NSPS=isps(iloc(1)) !Samples per symbol
NSYNC=NS*NSPS !Samples in sync waveform
NZ=NSPS*NDS !Samples in full Tx waveform
NFFT1=2*NSPS !Length of FFTs for symbol spectra
baud=fsample/NSPS
tsym=1.0/baud
bw=NQ*baud
fspread=0.0
delay=0.0
if(itu.eq.'LQ') then
fspread=0.5
delay=0.5
else if(itu.eq.'LM') then
fspread=1.5
delay=2.0
else if(itu.eq.'LD') then
fspread=10.0
delay=6.0
else if(itu.eq.'MQ') then
fspread=0.1
delay=0.5
else if(itu.eq.'MM') then
fspread=0.5
delay=1.0
else if(itu.eq.'MD') then
fspread=1.0
delay=2.0
else if(itu.eq.'HQ') then
fspread=0.5
delay=1.0
else if(itu.eq.'HM') then
fspread=10.0
delay=3.0
else if(itu.eq.'HD') then
fspread=30.0
delay=7.0
endif
return
end subroutine sfox_init
end module sfox_mod

View File

@ -1,153 +0,0 @@
subroutine sfox_sync(iwave,fsample,isync,f,t,fwidth)
use sfox_mod
parameter (NSTEP=8)
integer*2 iwave(0:NMAX-1)
integer isync(44)
integer ipeak(2)
integer ipeak2(1)
complex, allocatable :: c(:) !Work array
real, allocatable :: s(:,:) !Symbol spectra, stepped by NSTEP
real, allocatable :: savg(:) !Average spectrum
real, allocatable :: ccf(:,:)
real, allocatable :: s2(:) !Fine spectrum of sync tone
nfft=nsps
nh=nfft/2
istep=NSPS/NSTEP
jz=(13.5*fsample)/istep
df=fsample/nfft
dtstep=istep/fsample
fsync=1500.0-bw/2
ftol=50.0
ia=nint((fsync-ftol)/df)
ib=nint((fsync+ftol)/df)
lagmax=1.5/dtstep
lag1=-lagmax
lag2=lagmax
allocate(s(0:nh/2,jz))
allocate(savg(0:nh/2))
allocate(c(0:nfft-1))
allocate(ccf(ia:ib,lag1:lag2))
s=0.
savg=0.
fac=1.0/nfft
! Compute symbol spectra with df=baud/2 and NSTEP steps per symbol.
do j=1,jz
i1=(j-1)*istep
i2=i1+nsps-1
k=-1
do i=i1,i2,2 !Load iwave data into complex array c0, for r2c FFT
xx=iwave(i)
yy=iwave(i+1)
k=k+1
c(k)=fac*cmplx(xx,yy)
enddo
c(k+1:)=0.
call four2a(c,nfft,1,-1,0) !r2c FFT
do i=1,nh/2
s(i,j)=real(c(i))**2 + aimag(c(i))**2
savg(i)=savg(i) + s(i,j)
enddo
enddo
savg=savg/jz
ccfbest=0.
ibest=0
lagpk=0
lagbest=0
j0=0.5/dtstep !Nominal start-signal index
do i=ia,ib
ccfmax=0.
do lag=lag1,lag2
ccft=0.
do m=1,NS
k=isync(m)
n=NSTEP*(k-1) + 1
j=n+lag+j0
if(j.ge.1 .and. j.le.jz) ccft=ccft + s(i,j)
enddo ! m
ccft=ccft - NS*savg(i)
ccf(i,lag)=ccft
if(ccft.gt.ccfmax) then
ccfmax=ccft
lagpk=lag
endif
enddo ! lag
if(ccfmax.gt.ccfbest) then
ccfbest=ccfmax
ibest=i
lagbest=lagpk
endif
enddo ! i
ipeak=maxloc(ccf)
ipk=ipeak(1)-1+ia
jpk=ipeak(2)-1+lag1
dxj=0.
if(jpk.gt.lag1 .and. jpk.lt.lag2) then
call peakup(ccf(ipk,jpk-1),ccf(ipk,jpk),ccf(ipk,jpk+1),dxj)
endif
f=ibest*df + bw/2 + dxi*df
t=(lagbest+dxj)*dtstep
t=t-0.01 !### Why is this needed? ###
nfft2=4*NSPS
deallocate(c)
allocate(c(0:nfft2-1))
allocate(s2(0:nfft2-1))
i0=(t+0.5)*fsample
s2=0.
df2=fsample/nfft2
do m=1,NS
i1=i0+(isync(m)-1)*NSPS
i2=i1+NSPS-1
k=-1
do i=i1,i2,2 !Load iwave data into complex array c0, for r2c FFT
if(i.gt.0) then
xx=iwave(i)
yy=iwave(i+1)
else
xx=0.
yy=0.
endif
k=k+1
c(k)=fac*cmplx(xx,yy)
enddo
c(k+1:)=0.
call four2a(c,nfft2,1,-1,0) !r2c FFT
do i=1,nfft2/4
s2(i)=s2(i) + real(c(i))**2 + aimag(c(i))**2
enddo
enddo
ia=nint((fsync-ftol)/df2)
ib=nint((fsync+ftol)/df2)
ipeak2=maxloc(s2(ia:ib))
ipk=ipeak2(1)-1+ia
dxi=0.
if(ipk.gt.1 .and. ipk.lt.nfft/4) then
call peakup(s2(ipk-1),s2(ipk),s2(ipk+1),dxi)
endif
f=(ipk+dxi)*df2 + bw/2.0
fwidth=0.
if(ipk.gt.100 .and. ipk.lt.nfft2/4-100) then
call pctile(s2(ipk-100:ipk+100),201,48,base)
s2=s2-base
smax=maxval(s2(ipk-10:ipk+10))
w=count(s2(ipk-10:ipk+10).gt.0.5*smax)
if(w.gt.4.0) fwidth=sqrt(w*w - 4*4)*df2
endif
return
end subroutine sfox_sync

View File

@ -1,46 +0,0 @@
program sfox_tx
! This program is required in order to create a SuperFox transmission.
! The present version goes through the following steps:
! 1. Read old-style Fox messages from file 'sfox_1.dat' in the WSJT-X
! writable data directory.
! 2. Parse up to NSlots=5 messages to extract MyCall, up to 10 Hound
! calls, and the report or RR73 to be sent to each Hound.
! 3. Assemble and encode a single SuperFox message to produce itone(1:151),
! the array of channel symbol values.
! 4. Write the contents of array itone to file 'sfox_2.dat'.
character*120 fname !Full path for sfox.dat
character*120 line !List of SuperFox message pieces
character*40 cmsg(5) !Old-style Fox messages
integer itone(151) !SuperFox channel-symbol values
open(70,file='fort.70',status='unknown',position='append')
call getarg(1,fname)
open(25,file=trim(fname),status='unknown')
do i=1,5
read(25,1000,end=10) cmsg(i)
1000 format(a40)
write(70,*) 'AAA',i,cmsg(i)
enddo
i=6
10 close(25)
nslots=i-1
write(70,*) 'BBB',nslots
call foxgen2(nslots,cmsg,line)
write(70,*) 'CCC ',trim(line)
do i=1,151 !Dummy loop to populate itone during tests
itone(i)=i-1
enddo
i1=index(fname,'sfox_1.dat')
fname(i1:i1+9)='sfox_2.dat'
open(25,file=trim(fname),status='unknown')
write(25,1100) itone
1100 format(20i4)
close(25)
end program sfox_tx

View File

@ -1,116 +0,0 @@
program sfoxsim
! Generate a SuperFox waveform with specified SNR and channel parameters.
! Output is saved to a *.wav file.
! SuperFox uses a (127,51) code with 7-bit symbols, punctured to (125,49).
! The puncured symbols contain a 14-bit CRC.
! First tests use RS(127,51) code and Berlekamp-Massey decoder.
use wavhdr
! use packjt77
parameter (NMAX=15*12000)
parameter (NSPS=1024,NSYNC=2*12000)
parameter (NWAVE=125*NSPS+NSYNC)
type(hdr) h !Header for .wav file
character arg*12,fname*17
! character msg37*37,msgsent37*37
complex c0(0:NMAX-1)
complex c(0:NMAX-1)
complex cwave(0:NWAVE-1)
real wave(NMAX)
real xjunk(NWAVE)
real xdat(51)
integer*1 idat(51)
integer itone(125)
integer*1 msgbits(77)
integer*2 iwave(NMAX) !Generated full-length waveform
! Get command-line argument(s)
nargs=iargc()
if(nargs.ne.6) then
print*,'Usage: sfoxsim f0 DT fSpread del nfiles snr'
print*,'Example: sfoxsim 1500.0 0.0 0.1 1.0 10 -15'
go to 999
endif
call getarg(1,arg)
read(arg,*) f0 !Frequency (only used for single-signal
call getarg(2,arg)
read(arg,*) xdt !Time offset from nominal (s)
call getarg(3,arg)
read(arg,*) fspread !Watterson frequency spread (Hz)
call getarg(4,arg)
read(arg,*) delay !Watterson delay (ms)
call getarg(5,arg)
read(arg,*) nfiles !Number of files
call getarg(6,arg)
read(arg,*) snrdb !SNR_2500
twopi=8.0*atan(1.0)
fs=12000.0 !Sample rate (Hz)
dt=1.0/fs !Sample interval (s)
tt=NSPS*dt !Duration of symbols (s)
baud=1.0/tt !Keying rate (baud)
bw=128*baud !Occupied bandwidth (Hz)
tsync=NSYNC*dt !Duration of analog sync function
txt=tsync + 125*NSPS*dt !Overall transmission length (s)
bandwidth_ratio=2500.0/(fs/2.0)
sig=sqrt(2*bandwidth_ratio) * 10.0**(0.05*snrdb)
if(snrdb.gt.90.0) sig=1.0
write(*,1000) f0,xdt,fspread,delay,tsync,txt,bw,snrdb
1000 format('f0:',f7.1,' DT:',f6.2,' fSpread:',f5.1,' delay:',f4.1/ &
'Tsync:',f4.1,' TxT:',f6.1,' BW:',f7.1,' SNR:',f6.1)
write(*,*)
! Source-encode, then get itone()
call random_number(xdat)
idat=int(128*xdat)
itone=0
itone(1:49)=idat(1:49)
write(*,'(20i4)') idat
write(*,*)
write(*,'(a17)') 'Channel symbols: '
write(*,'(20i4)') itone
write(*,*)
if(nsps.ne.-99) go to 999
do ifile=1,nfiles
c0=0.
c0(0:NWAVE-1)=cwave
c0=cshift(c0,-nint((xdt+0.5)/dt))
! if(fspread.ne.0.0 .or. delay.ne.0.0) call watterson(c0,NMAX,NWAVE,fs,delay,fspread)
c=sig*c0
wave=imag(c)
peak=maxval(abs(wave))
nslots=1
if(snrdb.lt.90) then
do i=1,NMAX !Add gaussian noise at specified SNR
xnoise=gran()
wave(i)=wave(i) + xnoise
enddo
endif
gain=100.0
if(snrdb.lt.90.0) then
wave=gain*wave
else
datpk=maxval(abs(wave))
fac=32766.9/datpk
wave=fac*wave
endif
if(any(abs(wave).gt.32767.0)) print*,"Warning - data will be clipped."
iwave=nint(wave)
h=default_header(12000,NMAX)
write(fname,1102) ifile
1102 format('000000_',i6.6,'.wav')
open(10,file=fname,status='unknown',access='stream')
write(10) h,iwave !Save to *.wav file
close(10)
write(*,1110) ifile,xdt,f0,snrdb,fname
1110 format(i4,f7.2,f8.2,f7.1,2x,a17)
enddo
999 end program sfoxsim

View File

@ -1,285 +0,0 @@
program sfoxtest
! Generate and test possible waveforms for SuperFox signal.
use wavhdr
use sfox_mod
use timer_module, only: timer
use timer_impl, only: init_timer !, limtrace
type(hdr) h !Header for .wav file
integer*2 iwave(NMAX) !Generated i*2 waveform
integer param(0:8)
integer isync(44)
integer jsync(171)
integer itone(171)
integer nsb(10)
real*4 xnoise(NMAX) !Random noise
real*4 dat(NMAX) !Generated real data
complex cdat(NMAX) !Generated complex waveform
complex cnoise(NMAX) !Complex noise
complex crcvd(NMAX) !Signal as received
real a(3)
real, allocatable :: s3(:,:) !Symbol spectra: will be s3(NQ,NN)
integer, allocatable :: msg0(:) !Information symbols
integer, allocatable :: parsym(:) !Parity symbols
integer, allocatable :: chansym0(:) !Encoded data, 7-bit integers
integer, allocatable :: chansym(:) !Recovered hard-decision symbols
integer, allocatable :: iera(:) !Positions of erasures
integer, allocatable :: rxdat(:)
integer, allocatable :: rxprob(:)
integer, allocatable :: rxdat2(:)
integer, allocatable :: rxprob2(:)
integer, allocatable :: correct(:)
character fname*17,arg*12,itu*2
data isync/ 1, 2, 5, 11, 19, 24, 26, 28, 29, 35, &
39, 48, 51, 53, 55, 56, 66, 71, 74, 78, &
80, 82, 84, 85, 92, 98, 103, 107, 109, 111, &
116, 122, 130, 131, 134, 136, 137, 140, 146, 154, &
159, 161, 163, 165/
data nsb/1,2,4,7,11,16,22,29,37,39/
nargs=iargc()
if(nargs.ne.11) then
print*,'Usage: sfoxtest f0 DT ITU M N K NS v st nfiles snr'
print*,'Example: sfoxtest 1500 0.15 MM 7 127 48 33 0 3 10 -10'
print*,' f0=0 means f0, DT will assume suitable random values'
print*,' LQ: Low Latitude Quiet'
print*,' MM: Mid Latitude Moderate'
print*,' HD: High Latitude Disturbed'
print*,' ... and similarly for LM LD MQ MD HQ HM'
print*,' NS: number of sync symbols'
print*,' v=1 for .wav files, 2 for verbose output, 3 for both'
print*,' st: Sync type, 0 for hard-wired, otherwise 1-3'
print*,' snr=0 means loop over SNRs'
go to 999
endif
call getarg(1,arg)
read(arg,*) f0
call getarg(2,arg)
read(arg,*) xdt
call getarg(3,itu)
call getarg(4,arg)
read(arg,*) mm0
call getarg(5,arg)
read(arg,*) nn0
call getarg(6,arg)
read(arg,*) kk0
call getarg(7,arg)
read(arg,*) ns0
call getarg(8,arg)
read(arg,*) nv
call getarg(9,arg)
read(arg,*) nstype
call getarg(10,arg)
read(arg,*) nfiles
call getarg(11,arg)
read(arg,*) snrdb
call init_timer ('timer.out')
call timer('sfoxtest',0)
fsample=12000.0 !Sample rate (Hz)
call sfox_init(mm0,nn0,kk0,itu,fspread,delay,fsample,ns0)
tsync=NSYNC/fsample
txt=(NN+NS)*NSPS/fsample
write(*,1000) MM,NN,KK,NSPS,baud,bw,itu,NS,txt,nstype
1000 format('M:',i2,' Base code: (',i3,',',i3,') NSPS:',i5, &
' Baud:',f7.3,' BW:',f9.3/ &
'Channel: ',a2,' NS:',i3,' TxT:',f5.1,' SyncType:',i2/)
! Allocate storage for arrays that depend on code parameters.
allocate(s3(0:NQ-1,0:NN-1))
allocate(msg0(1:KK))
allocate(parsym(1:NN-KK))
allocate(chansym0(0:NN-1))
allocate(chansym(0:NN-1))
allocate(iera(0:NN-1))
allocate(rxdat(0:NN-1))
allocate(rxprob(0:NN-1))
allocate(rxdat2(0:NN-1))
allocate(rxprob2(0:NN-1))
allocate(correct(0:NN-1))
idum=-1
if(nstype.eq.2) then
jsync=0
jsync(1)=1
jsync(NDS)=1
ms=2
do i=1,100000
j=1 + (NDS-1)*ran1(idum)
if(jsync(j).eq.0) then
jsync(j)=1
ms=ms+1
if(ms.eq.NS) exit
endif
enddo
j=0
do i=1,NDS
if(jsync(i).eq.1) then
j=j+1
isync(j)=i
endif
enddo
else if(nstype.eq.3) then
isync(1:10)=nsb
isync(11:20)=nsb + isync(10) + 2
isync(21:30)=nsb + isync(20) + 2
isync(31:40)=nsb + isync(30) + 2
isync(41:44)=nsb(1:4) + isync(40) + 2
endif
rms=100.
baud=fsample/nsps !Keying rate, 11.719 baud for nsps=1024
bandwidth_ratio=2500.0/fsample
fgood0=1.0
! Generate a message
msg0=0
do i=1,KK
msg0(i)=int(NQ*ran1(idum))
enddo
call rs_init_sf(MM,NQ,NN,KK,NFZ) !Initialize the Karn codec
call rs_encode_sf(msg0,parsym) !Compute parity symbols
chansym0(0:kk-1)=msg0(1:kk)
chansym0(kk:nn-1)=parsym(1:nn-kk)
isnr0=-8
do isnr=isnr0,-20,-1
snr=isnr
if(snrdb.ne.0.0) snr=snrdb
sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*snr)
sigr=sqrt(2.)*sig
if(snr.gt.90.0) sig=1.0
ngoodsync=0
ngood=0
ntot=0
nworst=0
sqt=0.
sqf=0.
sumw=0.
do ifile=1,nfiles
xnoise=0.
cnoise=0.
if(snr.lt.90) then
do i=1,NMAX !Generate Gaussian noise
x=gran()
y=gran()
xnoise(i)=x
cnoise(i)=cmplx(x,y)
enddo
endif
f1=f0
if(f0.eq.0.0) then
f1=1500.0 + 20.0*(ran1(idum)-0.5)
xdt=ran1(idum)-0.5
endif
call timer('gen ',0)
! Generate cdat, the SuperFox waveform
call sfox_gen(chansym0,f1,fsample,isync,itone,cdat)
call timer('gen ',1)
crcvd=0.
crcvd(1:NMAX)=cshift(cdat(1:NMAX),-nint((0.5+xdt)*fsample))
call timer('watterso',0)
if(fspread.ne.0 .or. delay.ne.0) call watterson(crcvd,NMAX,NZ,fsample,&
delay,fspread)
call timer('watterso',1)
dat=aimag(sigr*crcvd(1:NMAX)) + xnoise !Add generated AWGN noise
fac=32767.0
if(snr.ge.90.0) iwave(1:NMAX)=nint(fac*dat(1:NMAX))
if(snr.lt.90.0) iwave(1:NMAX)=nint(rms*dat(1:NMAX))
crcvd=sig*crcvd+cnoise
if(nstype.eq.0) then
f=f1 !Hard-wired sync
t=xdt
else
call timer('sync ',0)
call sfox_sync(iwave,fsample,isync,f,t,fwidth) !Find freq, DT, width
call timer('sync ',1)
endif
ferr=f-f1
terr=t-xdt
igoodsync=0
if(abs(ferr).lt.baud/2.0 .and. abs(terr).lt.tsym/4.0) then
igoodsync=1
ngoodsync=ngoodsync+1
sqt=sqt + terr*terr
sqf=sqf + ferr*ferr
sumw=sumw+fwidth
endif
a=0.
a(1)=1500.0-f - baud !Shift frequencies down by one bin
call timer('twkfreq ',0)
call twkfreq(crcvd,crcvd,NMAX,fsample,a)
call timer('twkfreq ',1)
f=1500.0
call timer('demod ',0)
call sfox_demod(crcvd,f,t,isync,s3) !Get s3(0:NQ-1,0:127)
call timer('demod ',1)
call timer('prob ',0)
call sym_prob(s3,rxdat,rxprob,rxdat2,rxprob2)
call timer('prob ',1)
nera=0
chansym=mod(chansym,nq) !Enforce 0 to nq-1
nharderr=count(rxdat.ne.chansym0) !Count hard errors
ntot=ntot+nharderr
nworst=max(nworst,nharderr)
ntrials=1000
call timer('ftrsd3 ',0)
call ftrsd3(s3,chansym0,rxdat,rxprob,rxdat2,rxprob2,ntrials, &
correct,param,ntry)
call timer('ftrsd3 ',1)
if(iand(nv,1).ne.0) then
h=default_header(12000,NMAX)
fname='000000_000001.wav'
write(fname(8:13),'(i6.6)') ifile
open(10,file=trim(fname),access='stream',status='unknown')
write(10) h,iwave(1:NMAX) !Save the .wav file
close(10)
endif
if(count(correct.ne.chansym0).eq.0) ngood=ngood+1
enddo ! ifile
fgoodsync=float(ngoodsync)/nfiles
fgood=float(ngood)/nfiles
if(isnr.eq.isnr0) write(*,1300)
1300 format(' SNR Eb/No iters fsync fgood averr rmsf rmst avew'/ &
'-------------------------------------------------------------')
ave_harderr=float(ntot)/nfiles
rmst=sqrt(sqt/ngoodsync)
rmsf=sqrt(sqf/ngoodsync)
ebno=snr-10*log10(baud/2500*mm0*KK/NN)
avew=sumw/ngoodsync
write(*,1310) snr,ebno,nfiles,fgoodsync,fgood,ave_harderr,rmsf,rmst,avew
1310 format(f7.2,f7.2 i6,2f7.4,f7.1,f7.2,f7.4,f6.1)
if(fgood.le.0.5 .and. fgood0.gt.0.5) then
threshold=isnr + 1 - (fgood0-0.50)/(fgood0-fgood+0.000001)
endif
fgood0=fgood
if(snrdb.ne.0.0) exit
! if(fgood.eq.0.0) exit
if(fgoodsync.lt.0.5) exit
enddo ! isnr
if(snrdb.eq.0.0) write(*,1320) threshold
1320 format(/'Threshold sensitivity (50% decoding):',f6.1,' dB')
call timer('sfoxtest',1)
999 call timer('sfoxtest',101)
end program sfoxtest

View File

@ -1,55 +0,0 @@
subroutine sym_prob(s3,rxdat,rxprob,rxdat2,rxprob2)
! Demodulate the 64-bin spectra for each of 63 symbols in a frame.
! Parameters
! rxdat most reliable symbol value
! rxdat2 second most likely symbol value
! rxprob probability that rxdat was the transmitted value
! rxprob2 probability that rxdat2 was the transmitted value
use sfox_mod
implicit real*8 (a-h,o-z)
real*4 s3(0:NQ-1,0:NN-1)
integer rxdat(0:NN-1),rxprob(0:NN-1),rxdat2(0:NN-1),rxprob2(0:NN-1)
afac=1.1
! scale=255.999
scale=2047.999
! Compute average spectral value
ave=sum(s3)/(NQ*ND)
i1=1 !Silence warning
i2=1
! Compute probabilities for most reliable symbol values
do j=0,NN-1 !Loop over all symbols
s1=-1.e30
psum=0.
do i=0,NQ-1 !Loop over frequency bins
x=min(afac*s3(i,j)/ave,50.d0)
psum=psum+s3(i,j)
if(s3(i,j).gt.s1) then
s1=s3(i,j) !Find max signal+noise power
i1=i !Find most reliable symbol value
endif
enddo
if(psum.eq.0.0) psum=1.e-6 !Guard against zero signal+noise
s2=-1.e30
do i=0,NQ-1
if(i.ne.i1 .and. s3(i,j).gt.s2) then
s2=s3(i,j) !Second largest signal+noise power
i2=i !Bin number for second largest power
endif
enddo
p1=s1/psum !p1, p2 are symbol metrics for ftrsd
p2=s2/psum
rxdat(j)=i1
rxdat2(j)=i2
rxprob(j)=scale*p1 !Scaled probabilities, 0 - 255
rxprob2(j)=scale*p2
enddo
return
end subroutine sym_prob

View File

@ -1,18 +0,0 @@
#include <stdio.h>
void encode_rs_8(unsigned char *data, unsigned char *parity, int pad);
int decode_rs_8(unsigned char *data, int *eras_pos, int no_eras, int pad);
void encode_rs_8_(unsigned char data[], unsigned char parity[], int *npad)
{
encode_rs_8(data,parity,*npad); //Compute the parity symbols
}
int decode_rs_8_(unsigned char *data, int *era_pos, int *numera, int *npad)
{
int nerr;
nerr=decode_rs_8(data,era_pos,*numera,*npad);
return nerr;
}