⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 synch_complex_ics_rcv.c

📁 This a framework to test new ideas in transmission technology. Actual development is a LDPC-coder in
💻 C
📖 第 1 页 / 共 2 页
字号:
  S32 *synch;  SYMBOL_COMPLEX_S32 *in, *out;  //  SAMPLE_S12 *out, *in_s12;  short int gold_inner[] = { +1, -1, -1, +1, -1, +1, -1, +1,	-1, -1, +1, +1, +1, +1, +1, +1 };  short int gold_outer[] = { +1, +1, -1, +1, -1, +1, +1, +1,	-1, -1, +1, -1, -1, +1, +1, +1 };  INIT_WATCH(4);  swr_sdb_get_config_struct( context->id, (void**)&config );  swr_sdb_free_config_struct( context->id, (void**)&config );  slot_length_samples = private->slot_length_samples;  buffer = private->buffer + 240 * 2;  synch = private->synch;  // The size of the buffer is slot_length_samples + 32 of the  // gold_inner length and 4 for the 'shift'.  buffer_ics = swr_malloc( sizeof( complex double ) * 			  ( slot_length_samples + 32 + 4 ) );  in = buffer_in(0);  out = buffer_out(0);  port_out(0).data = port_in(0).data +     SYNCH_PRIM_LENGTH_SAMPLES_QI * sizeof( SYMBOL_COMPLEX_S32 ) * 2;  // As total_energy is divided by SLOT_LENGTH_SAMPLES and then used  // as a divisor itself, it has to be at least 1!!!  total_energy = slot_length_samples;  synch_amp = 0;  synch_pos = -1;#define RX_INDEX(i) ( (i) + ( (i) & ~3 ) )  p = (unsigned int)in;  shift = ( p & 0x3f ) / 0x10;  in = (SYMBOL_COMPLEX_S32*)(p & ~0x3f);  WATCH_CLOCK( "Initialized" );  // Prepare a first buffer for calculations  // buffer_ics[0] = in[ RC_INDEX( -32 ) ];  for ( i=0; i<slot_length_samples + 32 + shift; i++ ){    buffer_ics[i] = SC_TO_CD( in[ RX_INDEX( i - 32 ) ] );  }  // buffer_ics[0] = in[ RC_INDEX( 0 ) ];  // But this time we have some space to do the convolution  buffer_ics += shift + 32;  WATCH_CLOCK( "Init buffer_ics" );  // First make the convolution with gold_inner. As gold_inner is at  // symbol-level, and our input is at sample-level, we only take each  // second sample for the convolution. BUT we do the convolutions at  // every sample-position  for ( i=0; i<slot_length_samples; i++ ) {    complex double res = 0;    for ( j=0; j<16; j++ ){      res += buffer_ics[ i - 2 * j ] * gold_inner[ j ];    }    buffer[ i ] = res / ( 1 << 12 );  }  buffer_ics -= shift + 32;  swr_free( buffer_ics );  WATCH_CLOCK( "Init inner gold" );  // Copy the end of the buffer to the beginning, so we can more easily do  // the convolutions at the corners of the buffer  memcpy( private->buffer, private->buffer + slot_length_samples,	  240 * 2 * sizeof( complex double ) );  // Now do the outer convolution with gold_outer.  for ( i=0; i<slot_length_samples; i++ ) {    complex double res;    res = buffer[ i ] * gold_outer[ 0 ];    for ( j=1; j<16; j++ ){      res += buffer[ i - j * 16 * 2 ] * gold_outer[ j ];      // Debugging      if( ( i-j*16 ) < 0 ) {	PR_DBG( 4, "buffer[%i]=%g+%gi\n", i-j*16, 		creal( buffer[i-j*16] ), cimag( buffer[i-j*16] ) );      }    }    if ( private->mean > 1 ){      synch[i] = ( synch[i] * ( private->mean - 1 ) + cabs( res ) ) / 	private->mean;    } else {      synch[i] = cabs( res );    }    total_energy += cabs( res );    if (synch[i] > synch_amp) {      synch_pos = i % slot_length_samples;      synch_amp = synch[i];      PR_DBG(4,"amp[%i]=%i\n",i,synch_amp);      }  }  WATCH_CLOCK( "Init outer gold code" );  // Search for other, erroneous peaks  for ( other_peaks = 0, i=0; i<slot_length_samples; i++ ) {    if ( synch[i] > synch_amp / 2 &&	 synch_pos != i ){      // There is another peak with at least half the amplitude,      // let's search further      other_peaks++;    }  }  total_energy /= slot_length_samples;  // One of these magic numbers...  synch_pos -= SYNCH_PRIM_LENGTH_SAMPLES_QI - 2 + private->fine_adj;  // If there are too many other peaks, consider another place  if ( other_peaks > private->skip && private->skip ){    // The other peaks indicate that we aren't synchronised    PR_DBG( 2, "Other_peaks: %i\n", other_peaks );    synch_pos = -slot_length_samples / 2;    private->mean = 1;    synch_amp /= other_peaks * other_peaks;  } else {    if ( synch_pos == 0 ){      // Only do averaging on a correctly synchronised slot      private->mean = private->config_mean;    }      }  if ( synch_pos ){    PR_DBG( 4, "Synch-pos: %5i, we're at: %i\n", synch_pos, 	    private->offset_samples );  }  WATCH_CLOCK( "Recalculated positions" );  // Perhaps we have to synchronise?  if ( private->stfa_id >= 0 ) {    private->offset_samples += synch_pos;    length_frame = slot_length_samples * private->slots_per_frame;/*     if ( private->offset_samples > length_frame ){ *//*       private->offset_samples %= length_frame; *//*     } else if ( private->offset_samples < 0 ){ *//*       private->offset_samples += length_frame; *//*     } */    PR_DBG( 4, "Setting new synch: %i(%i)\n", private->offset_samples,	    private->fine_adj );    swr_sdb_set_config_int( private->stfa_id, "offset_chips_rcv", 			    private->offset_samples / 2 );    swr_sdb_set_config_int( private->stfa_id, "offset_samples_rcv",			    ( private->offset_samples % 2 ) );    WATCH_CLOCK( "Set up stfa" );  }  swr_sdb_get_stats_struct( context->id, (void**)&stats );  if ( synch_amp > ( 1 << 24 ) ) {    PR_DBG( 3, "Synch amp is REALLY big: %i\n", synch_amp );  }  stats->synch_amp = synch_amp;  // To have synch_pos in chips  stats->synch_pos = synch_pos / 2;  stats->fine_pos = fine_pos;  stats->fine_amp = fine_amp;  stats->mean = private->mean;  swr_sdb_free_stats_struct( context->id, (void**)&stats );  PR_DBG( 4, "Tot_energy: %i, synch_amp: %i, pos: %i, offset: %i\n",          total_energy, synch_amp, synch_pos, private->offset_samples );  WATCH_CLOCK( "Finished" );  return(0);}/* * This is the `destructor'. */int rcv_complex_ics_finalize( swr_sdb_t *context ) {  swr_free( private->buffer );  swr_free( private->synch );  swr_free( private );  MOD_DEC_USE_COUNT;  return(0);}/* * This function is called upon "insmod" and is used to register the * different parts of the module to the SPM. */swr_spc_id_t rcv_complex_ics_id;int rcv_complex_ics_module_init(void) {  swr_spc_desc_t *desc;  // Get a description-part from SPM  // Give the following parameters:  // In-ports, output-ports, config-params, stat-params  desc = swr_spc_get_new_desc( 1, 1, 4, 7 );  if ( !desc ) {    PR_DBG( 0, "Can't initialise the module. This is BAD!\n" );    return -1;  }  // Define the different parts of config and stats  UM_CONFIG_INT( "stfa_id" );  UM_CONFIG_INT( "fine_adj" );  UM_CONFIG_INT( "skip" );  UM_CONFIG_INT( "mean" );    UM_STATS_INT( "synch_pos" );  UM_STATS_INT( "synch_amp" );  UM_STATS_INT( "fine_pos" );  UM_STATS_INT( "fine_amp" );  UM_STATS_BLOCK( "buffer" );  UM_STATS_BLOCK( "synch" );  UM_STATS_INT( "mean" );  UM_INPUT( SIG_SYMBOL_COMPLEX_S32, 0 );  UM_OUTPUT( SIG_SYMBOL_COMPLEX_S32, 0 );  // Initialise the callback-functions. NULL for not-used functions  desc->fn_init              = rcv_complex_ics_init;  desc->fn_reconfigure       = rcv_complex_ics_reconfig;  desc->fn_process_data      = rcv_complex_ics_pdata;  desc->fn_finalize          = rcv_complex_ics_finalize;  desc->fn_configure_outputs = rcv_complex_ics_configure_outputs;  // And register the module in the SPM  rcv_complex_ics_id = swr_cdb_register_spc( &desc, "synch_complex_ics_rcv" );  if ( rcv_complex_ics_id == SWR_SPM_INVALID_ID ) {    swr_spc_free_desc( desc );    PR_DBG( 0, "Couldn't register the module!\n" );    return 1;  }  PR_DBG( 4, "Ready to synch\n" );  return 0;}/* * This is called upon rmmod */void rcv_complex_ics_module_exit( void ) {  PR_DBG( 4, "Freeing id: %i\n", rcv_complex_ics_id );  if ( swr_cdb_unregister_spc( rcv_complex_ics_id ) < 0 ) {    PR_DBG( 0, "Still in use somewhere\n" );  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -