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

📄 stfa_complex.c

📁 This a framework to test new ideas in transmission technology. Actual development is a LDPC-coder in
💻 C
📖 第 1 页 / 共 2 页
字号:
			    config->offset_samples_rcv );    swr_sdb_set_config_int( config->stfa_id, "offset_samples_send", 			    config->offset_samples_send );          swr_sdb_set_config_int( config->stfa_id, "slots_per_frame", 			    config->slots_per_frame );    swr_sdb_set_config_int( config->stfa_id, "blocks_per_slot", 			    config->blocks_per_slot );    swr_sdb_set_config_int( config->stfa_id, "guard_period_chips", 			    config->guard_period_chips );     swr_sdb_set_config_int( config->stfa_id, "gain_tx", 			    config->gain_tx );     swr_sdb_set_config_int( config->stfa_id, "gain_rx", 			    config->gain_rx );         }    if ( config->slots_per_frame && config->blocks_per_slot ) {    if ( ( config->slots_per_frame != private->slots_per_frame ) ||         ( config->blocks_per_slot != private->blocks_per_slot ) ) {      PR_DBG( 2, "spf: %i->%i, bps: %i->%i\n", 	      private->slots_per_frame, config->slots_per_frame,	      private->blocks_per_slot, config->blocks_per_slot );      if ( init_slots_frame( context, config, stats ) < 0 ) {        PR_DBG( 0, "Couldn't set new slot/frame-parameters!\n" );        return -1;      }    }  }  // Re-calculate the internal offsets  stats->offset_chips = config->offset_chips_rcv;  offset_samples = config->offset_chips_rcv * DAQ_QI_SAMPLES_PER_CHIP +                   config->offset_samples_rcv;  if ( offset_samples != stats->offset_samples ){    PR_DBG( 4, "New offset samples: %i\n", offset_samples );    stats->offset_samples = offset_samples;  }  private->sso = config->slot_send_offset;  private->offset_rcv_bytes = ( offset_samples % DAQ_DMA_BLOCK_SIZE_QI_SAMPLES ) *     DAQ_BYTES_PER_QI_SAMPLE;  private->offset_rcv_blocks = offset_samples / DAQ_DMA_BLOCK_SIZE_QI_SAMPLES;  private->offset_send_bytes = config->offset_samples_send *    DAQ_BYTES_PER_QI_SAMPLE;  swr_ant_adjust_offset( private->nbr_stfa, private->offset_rcv_blocks );  private->guard_period_bytes = config->guard_period_chips *    DAQ_QI_SAMPLES_PER_CHIP * DAQ_BYTES_PER_QI_SAMPLE;  // Fill in the slots, the guard-period is after the  // slot.  for ( slot=0; slot<private->slots_per_frame; slot++ ) {    port_in(slot).data = private->buffer_tx + BUFFER_OFFSET_TX( slot );    port_in(slot).size = ( private->slot_bytes - private->guard_period_bytes ) /      DAQ_BYTES_PER_QI_SAMPLE;    port_out(slot).data = private->buffer_rx + BUFFER_OFFSET_RX( slot );    port_out(slot).size = ( private->slot_bytes - private->guard_period_bytes ) /      DAQ_BYTES_PER_QI_SAMPLE;  }  // Update the gains only if something changed  if ( ( config->gain_tx_0 != private->gain_tx_0 ) ||       ( config->gain_tx_1 != private->gain_tx_1 ) ||       ( config->gain_tx_2 != private->gain_tx_2 ) ||       ( config->gain_rx_0 != private->gain_rx_0 ) ) {    private->gain_tx_0 = config->gain_tx_0;    private->gain_tx_1 = config->gain_tx_1;    private->gain_tx_2 = config->gain_tx_2;    private->gain_rx_0 = config->gain_rx_0;    swr_ant_rf_set_gains( private->nbr_stfa,                          private->gain_tx_0, private->gain_tx_1, private->gain_tx_2,                          private->gain_rx_0 );  }  if ( config->gain_tx != private->gain_tx ){    private->gain_tx = config->gain_tx;    swr_ant_set_gain_tx( private->nbr_stfa, private->gain_tx );  }  if (config->gain_rx != private->gain_rx ){    private->gain_rx = config->gain_rx;    swr_ant_set_gain_rx( private->nbr_stfa, private->gain_rx );  }  swr_sdb_free_stats_struct( context->id, (void**)&stats );  swr_sdb_free_config_struct( context->id, (void**)&config );  return ret;}/** * The main working function. Here is decided what to do with the * requests from the ANT-module, which module to inform aso. */void spc_slot( swr_sdb_t *context, swr_ant_notify_t *notify ) {  stats_t *stats;  int slot_send, slot_rcv, b;  // private->sso is the send-slot-offset, so how many slots  // we have to calculate in advance  slot_send = ( notify->slots + private->sso ) % private->slots_per_frame;  slot_rcv = ( notify->slots + private->slots_per_frame - 2 ) % private->slots_per_frame;  PR_DBG( 4, "STFA(%i/%2i) send/rcv: %8x:%8x\n", private->nbr_stfa,	  port_out( 1 ).sdb_id,	  BUFFER_OFFSET_RX( slot_rcv ), BUFFER_OFFSET_TX( slot_send ) );  // Arrange some wrap-arounds for the reception-part.  // Copy the end of the rx-buffer to the beginning, if necessary  b = DMA_OFFSET_RX( slot_rcv ) - private->slot_bytes / 2;  if ( b < 0 ) {    void *c = DMA_BEGIN_RX + b;    memcpy( c,            c + private->dma_bytes,            -b );  } else {    b = DMA_OFFSET_RX( slot_rcv ) + 3 * private->slot_bytes / 2 - private->dma_bytes;    // Copy the beginning of the buffer to the end if the slot starts in the     // last 3/2 slot from the end of the DMA    if ( b > 0 ){      memcpy( DMA_END_RX, DMA_BEGIN_RX, b );    }  }  // Process an evenutal tx-port  PR_DBG( 4, "Send: %i, Rcv: %i\n", slot_send, slot_rcv );  if ( private->notice_sdb[ slot_send ] >= 0 ) {    int err_prep;    PR_DBG( 4, "Sending slot-%i-notice to %i\n",            slot_send, private->notice_sdb[ slot_send ] );    err_prep = swr_sdb_send_msg( private->notice_sdb[ slot_send ], 				 SUBS_MSG_PREPARE, NULL, -1 );    if ( !err_prep ){      swr_sdb_send_msg( private->notice_sdb[ slot_send ],			SUBS_MSG_DATA, (void*)-1, context->id );    } else {      PR_DBG( 2, "Couldn't prepare for reason: %i\n",	      err_prep );    }  }  if ( port_in( slot_send ).sdb_id == -1 ){    // Switch the slot to receiving    PR_DBG( 4, "Putting slot %i to reception\n", slot_send );    memset( private->buffer_tx + BUFFER_OFFSET_TX( slot_send ),	    TX_OFF, private->slot_bytes );  }  // Process the notice function  if ( private->notice_f[ slot_send ] ) {    PR_DBG( 4, "Calling notice-function on slot %i\n", slot_send );    private->notice_f[ slot_send ]( SUBS_MSG_USER, NULL, context->id );  }  // Process an eventual rx-port  if ( port_out( slot_rcv ).sdb_id >= 0 ) {    int err_prep;    PR_DBG( 4, "Sending rcvd slot %i\n", slot_rcv );    err_prep = swr_sdb_send_msg( port_out( slot_rcv ).sdb_id, 				 SUBS_MSG_PREPARE, NULL, -1 );    if ( !err_prep ){      port_out( slot_rcv ).flags |= SWR_PORT_DATA;    } else {      PR_DBG( 2, "Couldn't prepare for reason %i\n",	      err_prep );    }  }  // Count how many frames went by  if ( !slot_send ) {    swr_sdb_get_stats_struct( context->id, (void**)&stats );    stats->frame_count++;    swr_sdb_free_stats_struct( context->id, (void**)&stats );  }}/** * When a slot is ready to send, the subsystem calls this function. */int spc_send( swr_sdb_t *context ) {  int p, nbr_ports, b;  stats_t *stats;  swr_sdb_get_stats_struct( context->id, (void**)&stats );  nbr_ports = stats->slots_per_frame;  swr_sdb_free_stats_struct( context->id, (void**)&stats );  // The only thing we need to think about is a wrap-around of the  // buffer...  // The buffer is: SLOT_BYTES + DMA_BYTES + SLOT_BYTES  // where DMA_BYTES = SLOT_BYTES * SLOTS_PER_FRAME  // and the MAX_SLOT_BYTES before and after serve as a simplification  // of the ring-buffer.  for ( p=0; p < nbr_ports; p++ ) {    if ( port_in(p).flags & SWR_PORT_DATA ) {      PR_DBG( 4, "stfa[%i], BO[%i]: %i\n", private->nbr_stfa, 	      p, BUFFER_OFFSET_TX( p ) );      PR_DBG( 4, "%i %i %i %i %i\n",	      private->offset_rcv_blocks, private->rx_tx_delay_blocks,	      private->rx_tx_delay_bytes, private->offset_rcv_bytes,	      private->offset_send_bytes );      // Make sure the wrap-around is correct:      // For the beginning of the buffer      b = DMA_OFFSET_TX( p );      if ( b < 0 ){	// The slot starts BEFORE the DMA-region, so copy it to the end	memcpy( DMA_END_TX + b, DMA_BEGIN_TX + b, -b );      } else {	b += private->slot_bytes - private->dma_bytes;	if ( b > 0 ){	  // The slot reaches AFTER the DMA-region, so copy it to the beginning	  memcpy( DMA_BEGIN_TX,		  DMA_END_TX,		  b );	}      }      port_in(p).flags &= ~SWR_PORT_DATA;    }  }  return 0;}/** * Inserts function in the table of notice queues, so that things * can roll */void add_notice_func( swr_sdb_t *context, func *f, int port ) {  if ( ( port >= private->slots_per_frame ) ||       ( port < 0 ) ) {    PR_DBG( 1, "Couldn't attach to port %i, out of range\n", port );    return;  }  private->notice_f[ port ] = f;}/** * Inserts the sdb-id in the table of notice queues, so that things * can roll */void add_notice_sdb( swr_sdb_t *context, swr_sdb_id ret, int port ) {  if ( ( port >= private->slots_per_frame ) ||       ( port < 0 ) ) {    PR_DBG( 1, "Couldn't attach to port %i, out of range\n", port );    return;  }  private->notice_sdb[ port ] = ret;}/** * Dispatch Go, Stop */int spc_custom_msg( swr_sdb_t *context, swr_usr_msg_t *data, swr_sdb_id ret ) {  if ( !data ) {    PR_DBG( 0, "Hmm, empty user-message is not cool for stfa...\n" );  } else if ( !strcmp( data->id, "ANT" ) ) {    // Message of the antenna-dispatcher that a slot is ready    if ( !private->running ) {      // If we have more than one stfa, a call to swr_stfa_go (sfta_0)      // will start all antennas. So if we're stopped and not the first      // stfa, upon reception of a "ANT" message, we go into running mode.      if ( private->nbr_stfa > 0 ){        PR_DBG( 1, "Parallel starting of STFA %i\n",			private->nbr_stfa );	private->running = 1;      } else {        PR_DBG( 0, "Got called while stopped!\n" );      }    }    if ( private->running ) {      PR_DBG( 4, "Got some dma-buffer, offset = %i\n", private->offset_rcv_blocks );      spc_slot( context, data->data );    }    swr_free( data->data );  } else if ( !strcmp( data->id, "Go" ) ) {    // Start the whole thing    PR_DBG( 2, "Starting the stfa\n" );    private->running = 1;    if ( private->stfa_id >= 0 ){      // If there is another STFA, chain it      PR_DBG( 1, "Chaining the STFA\n" );      swr_stfa_go( private->stfa_id );    } else {      // We start the antenna which starts all channels      PR_DBG( 1, "We're the last, starting the channels\n" );      swr_ant_start( private->len_frame_blocks );    }  //  PR_DBG( 4, "Finished starting the antenna\n" );  } else if ( !strcmp( data->id, "Stop" ) ) {    // Stop the whole thing    PR_DBG( 2, "Stopping the stfa\n" );    swr_ant_stop( );    private->running = 0;  } else if ( !strncmp( data->id, "Notice_func", 11 ) ) {    // Add a function    PR_DBG( 2, "Adding a notice-function for port %i\n",            (int)data->id[11] );    add_notice_func( context, data->data, (int)data->id[11] );    data->data = NULL;  } else if ( !strncmp( data->id, "Notice_sdb", 10 ) ) {    // Add a queue    PR_DBG( 2, "Adding a notice to sdb-id %i, port %i\n",            ret, (int)data->id[10] );    add_notice_sdb( context, ret, (int)data->id[10] );  }  return 0;}int spc_finalize( swr_sdb_t *context ) {  if ( private->running ){    if ( private->nbr_stfa == 0 ){      PR_DBG( 0, "Stopping the stfa in extremis!\n" );    }    swr_ant_stop( );  }  swr_ant_free( private->nbr_stfa );  PR_DBG( 2, "Freeing RX\n" );  swr_free( private->buffer_rx );  PR_DBG( 2, "Freeing TX\n" );  swr_free( private->buffer_tx );  PR_DBG( 2, "Freeing finished\n" );  swr_free( private );  nbr_stfa--;  MOD_DEC_USE_COUNT;  return 0;}swr_spc_id_t spc_id;/** * This function is called upon "insmod" and is used to register the * different parts of the module to the SPM. */int spc_module_init(void) {  swr_spc_desc_t *desc;  int i;  // Get a description-part from SPM  // Nbr_input_ports, Nbr_output_ports, Nbr_config_values, Nbr_stats_values  desc = swr_spc_get_new_desc( MAX_SLOTS, MAX_SLOTS, 14, 7 );  if ( !desc ) {    PR_DBG( 0, "Can't initialise the module. This is BAD!\n" );    return -1;  }  UM_CONFIG_INT( "slot_send_offset" );  UM_CONFIG_INT( "offset_chips_rcv" );  UM_CONFIG_INT( "offset_samples_rcv" );  UM_CONFIG_INT( "offset_samples_send" );  UM_CONFIG_INT( "blocks_per_slot" );  UM_CONFIG_INT( "slots_per_frame" );  UM_CONFIG_INT( "guard_period_chips" );  UM_CONFIG_INT( "gain_tx_0" );  UM_CONFIG_INT( "gain_tx_1" );  UM_CONFIG_INT( "gain_tx_2" );  UM_CONFIG_INT( "gain_rx_0" );  UM_CONFIG_INT( "gain_tx" );  UM_CONFIG_INT( "gain_rx" );  UM_CONFIG_INT( "stfa_id" );  UM_STATS_INT( "frame_count" );  UM_STATS_INT( "blocks_per_slot" );  UM_STATS_INT( "slots_per_frame" );  UM_STATS_BLOCK( "buffer_rx" );  UM_STATS_BLOCK( "buffer_tx" );  UM_STATS_INT( "offset_chips" );  UM_STATS_INT( "offset_samples" );  for ( i=0; i<MAX_SLOTS; i++ ) {    UM_INPUT( SIG_SYMBOL_COMPLEX, 0 );    UM_OUTPUT( SIG_SYMBOL_COMPLEX, 0 );  }  // Initialise the callback-functions. NULL for not-used functions  desc->fn_init = spc_init;  desc->fn_reconfigure = spc_reconfig;  desc->fn_custom_msg = spc_custom_msg;  desc->fn_finalize = spc_finalize;  desc->fn_process_data = spc_send;  nbr_stfa = 0;  // And register the module in the SPM  spc_id = swr_cdb_register_spc( &desc, "stfa_complex" );  if ( spc_id == SWR_SPM_INVALID_ID ) {    swr_spc_free_desc( desc );    PR_DBG( 0, "Couldn't register the module!\n" );    return 1;  }  return 0;}void spc_module_exit( void ) {  PR_DBG( 2, "STFA is going\n" );  if ( swr_cdb_unregister_spc( spc_id ) < 0 ) {    PR_DBG( 0, "Still in use somewhere\n" );  }}module_init( spc_module_init );module_exit( spc_module_exit );

⌨️ 快捷键说明

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