Esempio n. 1
0
static int write_header(avro_file_writer_t w)
{
	int rval;
	uint8_t version = 1;
	/* TODO: remove this static buffer */
	avro_writer_t schema_writer;
	char schema_buf[64 * 1024];
	const avro_encoding_t *enc = &avro_binary_encoding;

	/* Generate random sync */
	generate_sync(w);

	check(rval, avro_write(w->writer, "Obj", 3));
	check(rval, avro_write(w->writer, &version, 1));

	check(rval, enc->write_long(w->writer, 3));
	check(rval, enc->write_string(w->writer, "avro.sync"));
	check(rval, enc->write_bytes(w->writer, w->sync, sizeof(w->sync)));
	check(rval, enc->write_string(w->writer, "avro.codec"));
	check(rval, enc->write_bytes(w->writer, "null", 4));
	check(rval, enc->write_string(w->writer, "avro.schema"));
	schema_writer = avro_writer_memory(schema_buf, sizeof(schema_buf));
	rval = avro_schema_to_json(w->writers_schema, schema_writer);
	if (rval) {
		avro_writer_free(schema_writer);
		return rval;
	}
	check(rval,
	      enc->write_bytes(w->writer, schema_buf,
			       avro_writer_tell(schema_writer)));
	check(rval, enc->write_long(w->writer, 0));
	return write_sync(w);
}
Esempio n. 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);
}