Beispiel #1
0
static int cdf_erfc (lua_State *L) {
  lua_Number x = luaL_checknumber(L, 1);
  int ind = 0;
  lua_pushnumber(L, erfc1(&ind, &x));
  return 1;
}
Beispiel #2
0
int main(int argc,char *argv[]){
  unsigned char data[FRAMEBITS/8]; // One minor frame
  unsigned char symbols[2*FRAMEBITS];
  unsigned char nsymbols[2*FRAMEBITS];
  int i,fd;
  char *filename;
  struct stat statbuf;
  off_t length;
  short *samples;
  int  nsamples;
  int start;
  int startsync = SYNC_FAIL,endsync = SYNC_FAIL;
  void *vd; // Viterbi decoder handle
  int symerrors;
  int firstsample;
  int frame;
  int begin;
  int maxmetric,minmetric;
  int ind;
  char *locale;
  double clock_tolerance = 5; // Maximum allowable clock offset, samples/frame
  
  if((locale = getenv("LANG")) != NULL)
    setlocale(LC_ALL,locale);
  else
    setlocale(LC_ALL,"en_US.utf8");

  begin = 0;
  while((i = getopt(argc,argv,"c:o:r:t:")) != EOF){
    switch(i){
    case 't':
      clock_tolerance = atof(optarg);
      break;
    case 'c':
      Symrate = atof(optarg);
      break;
    case 'r':
      Samprate = atof(optarg);
      break;
    case 'o':
      begin = atoi(optarg); // Starting sample, default 0
      break;
    }
  }
  Symbolsamples = Samprate/Symrate;
  Framesamples = Symbolsamples * 2*FRAMEBITS;

  // Read baseband samples, downsampled to Samprate (important!) and look for sync vector 
  filename = argv[optind];
  if(lstat(filename,&statbuf) == -1){
    fprintf(stderr,"lstat(%s) failed: %s\n",filename,strerror(errno));
    exit(1);
  }
  if(!S_ISREG(statbuf.st_mode)){
    fprintf(stderr,"%s is not an ordinary file\n",filename);
    exit(1);
  }
  length = statbuf.st_size;
  if((fd = open(filename,O_RDONLY)) == -1){
    fprintf(stderr,"open(%s,readonly) failed; %s\n",filename,strerror(errno));
    exit(1);
  }
  if((samples = mmap(NULL,length,PROT_READ,MAP_SHARED,fd,0)) == MAP_FAILED){
    fprintf(stderr,"mmap(%s,%lld) failed: %s\n",filename,
	    (long long)length,strerror(errno));
    close(fd);
    exit(1);
  }
  nsamples = length / sizeof(*samples);
  printf("%s: %'d samples, %'.3lf seconds @ %.1lf Hz\n",filename,
	  nsamples,nsamples/Samprate,Samprate);
  generate_sync(Symrate);
  vd = create_viterbi224(FRAMEBITS);
  if(vd == NULL){
    fprintf(stderr,"Can't create viterbi decoder\n");
    exit(2);
  }
  
  for(frame=1;begin + Framesamples < nsamples;frame++){
    int low,high;

    // Look for starting frame sync
    if(startsync == SYNC_FAIL){
      // No endsync from previous frame, find initial sync
      while(1){
	startsync = fft_sync_search(&samples[begin],0,(int)Framesamples,begin);
	if(startsync != SYNC_FAIL){
	  startsync += begin;
	  break;
	}
	begin += Framesamples; // Skip a frame time and try again
	printf("Start sync search failure, skip to %'d\n",begin);
      }
    }
    assert(startsync != SYNC_FAIL);
    // Look for ending frame sync
    // Start halfway through the frame, but actually search the middle
    // of the result, which straddles the next sync. Only search in the
    // allowable range to keep the clock from being driven into the weeds by noise
    while(1){
      start = startsync + Framesamples/2;
      low = 0.5 * Framesamples - clock_tolerance; // very tight tolerance, +/- 5 samples
      high = 0.5 * Framesamples + clock_tolerance;
      endsync = fft_sync_search(&samples[start],low,high,-1);
      if(endsync != SYNC_FAIL){
	endsync += start;
	break;
      }
      // Go back to look for another start sync
      begin = startsync + Framesamples;
      printf("End sync search failure, skip to %'d\n",begin);
      startsync = SYNC_FAIL;
      goto again;
    }
    // Got both start and end sync, proceed
    i = startsync/Samprate;
    printf("Frame %'d @ sample %'d (%'d:%02d)\n",frame,startsync,i/60,i % 60);

    // Update estimate of sample clock rate et al
#if 0 // Hack - not let it change
    Framesamples = endsync - startsync; // Actual samples in current frame (int)
    Symbolsamples = Framesamples/(2*FRAMEBITS); // Actual samples in symbol (float)
    Symrate = Samprate / Symbolsamples;
#endif
    printf("Symbol rate: %'.3lf Hz; samples/sym: %'.3lf; samples/frame: %'.1lf\n",
	  Symrate,Symbolsamples,Framesamples);
#if 0    
    // If clock estimate has changed a lot, regenerate the sync vector with the new clock
    if(abs(SYNCBITS*Samprate/Symrate - Synclen) > Symbolsamples/10.){
      printf("Clock changed; regenerate sync\n");
      generate_sync(Symrate);
    }
#endif
    // startsync points to the first symbol in the 34-bit sync sequence,
    // so we want to skip past it to the first symbol in the new frame
    firstsample = SYNCBITS*Symbolsamples + startsync;
    for(i=0; i < 2*FRAMEBITS; i++){
      double sum;
      int midpoint,last;
      
      ind = firstsample + i * Symbolsamples;
      midpoint = firstsample + (i+0.5)*Symbolsamples;
      last = firstsample + (i+1.0)*Symbolsamples;
      // Integrate bit, remove manchester
      sum = 0;
      for(;ind < midpoint;ind++)   // first half of symbol
	sum -= samples[ind];
      for(; ind < last;ind++)
	sum += samples[ind];
      
      sum += 128; // Offset-128 for Viterbi decoder
      symbols[i] = (sum > 255) ? 255 : ((sum < 0) ? 0 : sum); // Clip to range 0-255
    }
    // We start with the encoder having just transmitted these five fixed bytes,
    // 3 bytes of coder dump and 2 bytes of sync:
    // 12 fc 81 9f be
    init_viterbi224(vd,0x819fbe);
    update_viterbi224_blk(vd,symbols,FRAMEBITS);
    chainback_viterbi224(vd,data,FRAMEBITS,0x819fbe);
    maxmetric = max_metric_viterbi224(vd);
    minmetric = min_metric_viterbi224(vd);

    for(i=0; i<128; i++){
      printf("%02x",data[i]);
      if((i % 16) == 15)
	putchar('\n');
      else
	putchar(' ');
    }
    // Re-encode and compare to received symbols to count channel errors
    encode(nsymbols,data,FRAMEBITS/8,0x819fbe);
    symerrors = 0;
    for(i=0;i<2*FRAMEBITS;i++){
      if(nsymbols[i] != (symbols[i] > 128)){
	symerrors++;
#if 0
	printf("sym error %d: %d != %d\n",i,nsymbols[i],symbols[i]);
#endif
      }
    }
    printf("Viterbi path metric range %'d - %'d, diff %'d\n",minmetric,maxmetric,maxmetric-minmetric);
    if(symerrors){
      double esn0;

      esn0 = erfc1(2.*symerrors/(2*FRAMEBITS)); // Amplitude ratio
      esn0 *= esn0; // square to get power ratio
      // ebn0 = 2 * esn0 for rate 1/2 code
      printf("re-encode symbol errors: %'d/%'d; estimated Eb/No = %.2lf dB\n",
	       symerrors,2*FRAMEBITS,10*log10(2*esn0));
    } else {
      printf("No re-encode symbol errors; estimated Eb/No > %.2lf dB\n",10.5); // hack; 7.5 dB has a BER < 1/2048
    }
    putchar('\n');
    fflush(stdout);
    startsync = endsync;
  again:;
  }
  delete_viterbi224(vd);

  exit(0);
}
Beispiel #3
0
void grat1(double *a,double *x,double *r,double *p,double *q,
	   double *eps)
{
static int K2 = 0;
static double a2n,a2nm1,am0,an,an0,b2n,b2nm1,c,cma,g,h,j,l,sum,t,tol,w,z,T1,T3;
/*
     ..
     .. Executable Statements ..
*/
/*
-----------------------------------------------------------------------
        EVALUATION OF THE INCOMPLETE GAMMA RATIO FUNCTIONS
                      P(A,X) AND Q(A,X)
     IT IS ASSUMED THAT A .LE. 1.  EPS IS THE TOLERANCE TO BE USED.
     THE INPUT ARGUMENT R HAS THE VALUE E**(-X)*X**A/GAMMA(A).
-----------------------------------------------------------------------
*/
    if(*a**x == 0.0e0) goto S120;
    if(*a == 0.5e0) goto S100;
    if(*x < 1.1e0) goto S10;
    goto S60;
S10:
/*
             TAYLOR SERIES FOR P(A,X)/X**A
*/
    an = 3.0e0;
    c = *x;
    sum = *x/(*a+3.0e0);
    tol = 0.1e0**eps/(*a+1.0e0);
S20:
    an += 1.0e0;
    c = -(c*(*x/an));
    t = c/(*a+an);
    sum += t;
    if(fabs(t) > tol) goto S20;
    j = *a**x*((sum/6.0e0-0.5e0/(*a+2.0e0))**x+1.0e0/(*a+1.0e0));
    z = *a*log(*x);
    h = gam1(a);
    g = 1.0e0+h;
    if(*x < 0.25e0) goto S30;
    if(*a < *x/2.59e0) goto S50;
    goto S40;
S30:
    if(z > -.13394e0) goto S50;
S40:
    w = exp(z);
    *p = w*g*(0.5e0+(0.5e0-j));
    *q = 0.5e0+(0.5e0-*p);
    return;
S50:
    l = rexp(&z);
    w = 0.5e0+(0.5e0+l);
    *q = (w*j-l)*g-h;
    if(*q < 0.0e0) goto S90;
    *p = 0.5e0+(0.5e0-*q);
    return;
S60:
/*
              CONTINUED FRACTION EXPANSION
*/
    a2nm1 = a2n = 1.0e0;
    b2nm1 = *x;
    b2n = *x+(1.0e0-*a);
    c = 1.0e0;
S70:
    a2nm1 = *x*a2n+c*a2nm1;
    b2nm1 = *x*b2n+c*b2nm1;
    am0 = a2nm1/b2nm1;
    c += 1.0e0;
    cma = c-*a;
    a2n = a2nm1+cma*a2n;
    b2n = b2nm1+cma*b2n;
    an0 = a2n/b2n;
    if(fabs(an0-am0) >= *eps*an0) goto S70;
    *q = *r*an0;
    *p = 0.5e0+(0.5e0-*q);
    return;
S80:
/*
                SPECIAL CASES
*/
    *p = 0.0e0;
    *q = 1.0e0;
    return;
S90:
    *p = 1.0e0;
    *q = 0.0e0;
    return;
S100:
    if(*x >= 0.25e0) goto S110;
    T1 = sqrt(*x);
    *p = erf1(&T1);
    *q = 0.5e0+(0.5e0-*p);
    return;
S110:
    T3 = sqrt(*x);
    *q = erfc1(&K2,&T3);
    *p = 0.5e0+(0.5e0-*q);
    return;
S120:
    if(*x <= *a) goto S80;
    goto S90;
}