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

📄 sch_send.c

📁 This a framework to test new ideas in transmission technology. Actual development is a LDPC-coder in
💻 C
字号:
/****************************************************************************    sch_send.c  -  Send the System CHannel*                           -------------------*   begin                :  2003-03-19*   authors              :  ineiti*   emails               :  linus.gasser@epfl.ch***************************************************************************//****************************************************************************                                Changes*                                -------* date - name - description* 03/04/25 - ineiti - changed target_peak to target_snr* 04/03/02 - ineiti - adjusted gain_adj to reflect the difference of the*                     target and the actual gain* 04/03/05 - ineiti - adjusted description***************************************************************************//****************************************************************************                                                                         **   This program is free software; you can redistribute it and/or modify  **   it under the terms of the GNU General Public License as published by  **   the Free Software Foundation; either version 2 of the License, or     **   (at your option) any later version.                                   **                                                                         ****************************************************************************//** *  In general, it builds a big structure that is sent over the first slot * in a frame. It is also used to tell the clients about the strength of the * signal to be sent. *  If there is not enough to send the whole data_usr block through the * slot, it will be truncated and a message will appear in the logs. */#include "spc.h"#include "sch.h"#include "std.h"#include <math.h>#define DBG_LVL 0#define MAX_MID_AMP 10240typedef struct {  // the client's id  int id[ MAX_CLIENTS ]; // -1  // a bit-field of the uplinks for the clients  int uplinks[ MAX_CLIENTS ]; // 0  // a bit-field of the downlinks for the clients  int downlinks[ MAX_CLIENTS ]; // 0  // one matched-filter from an uplink that will be used for  // gain-control  int mafi[ MAX_CLIENTS ]; // -1  // the target snr that the BS tries to achieve by telling  // the MS to increase it's sending gain  double target_snr[ MAX_CLIENTS ]; // 10  // below this peak-level the client is considered to  // be missing  int minimum_peak[ MAX_CLIENTS ]; // 150  // is a pointer to a block of data that will be sent along  void *data_usr; // NULL  // is the length in bytes of the data_usr block  int len_usr; // 0}config_t;typedef struct {}stats_t;typedef struct {  struct sch_data_t data;  void *data_usr;  int len_usr;}private_t;/* * The initialisation function, or constructor,  * is called the first time this module is instantiated. */int send_init( swr_sdb_t *context ) {  // Begin system-definitions {  config_t *config;  stats_t *stats;  int i;  MOD_INC_USE_COUNT;  if ( sizeof( private_t ) > 0 )    context->private_data = swr_malloc( sizeof( private_t ) );  swr_sdb_get_config_struct( context->id, (void**)&config );  swr_sdb_get_stats_struct( context->id, (void**)&stats );  // } End of system-definitions  for ( i=0; i<MAX_CLIENTS; i++ ) {    config->id[i] = -1;    config->uplinks[i] = 0;    config->downlinks[i] = 0;    config->mafi[i] = -1;    config->target_snr[i] = 10;    config->minimum_peak[i] = 150;#ifdef USER_SPACE    private->data.client[i].gain = 0.;#else    private->data.client[i].gain = -60.;#endif  }  config->data_usr = NULL;  config->len_usr = 0;  // Begin system-definitions  swr_sdb_free_stats_struct( context->id, (void**)&stats );  swr_sdb_free_config_struct( context->id, (void**)&config );  return 0;  // End system-definitions}/* * Every time modules from the outside change the value of a configuration parameter, * this function is called. */int send_reconfig( swr_sdb_t *context ) {  // Definition of variables - don't touch  config_t *config;  int i;  swr_sdb_get_config_struct( context->id, (void**)&config );  for ( i=0; i<MAX_CLIENTS; i++ ) {    private->data.client[i].id = config->id[i];    private->data.client[i].uplinks = config->uplinks[i];    private->data.client[i].downlinks = config->downlinks[i];  }  private->data_usr = config->data_usr;  private->data.len_usr = config->len_usr;  // Definition - don't touch  swr_sdb_free_config_struct( context->id, (void**)&config );  return 0;}/* * This is the function that implements the `main method' of the class * Every class has got just ONE method/working-mode. */int send_pdata( swr_sdb_t *context ) {  // Definition of variables - don't touch  stats_t *stats;  config_t *config;  U8 *out;  double gain_adj, snr;  int i, mid_amp, peak_amp, size_data = sizeof( struct sch_data_t );  // Check for the output-size  if ( size_out(0) < size_data ) {    PR_DBG( 0, "Output-size is not sufficient to hold the data!\n" );    return -1;  }  if ( size_out(0) < size_data + private->data.len_usr ) {    private->data.len_usr = size_out(0) - size_data;    PR_DBG( 0, "Correcting len_usr to %i\n", private->data.len_usr );  }  // Look whether we have to do some power-control  swr_sdb_get_config_struct( context->id, (void**)&config );  for ( i=0; i<MAX_CLIENTS; i++ ) {    if ( config->mafi[i] >= 0 ) {      // OK, we have a matched-filter responsible for this mobile...      mid_amp = swr_sdb_get_stats_int( config->mafi[i], "mid_amp" );      peak_amp = swr_sdb_get_stats_int( config->mafi[i], "peak_amp" );      snr = swr_sdb_get_stats_double( config->mafi[i], "snr" );      PR_DBG( 4, "peak_amp: %i, snr: %g, target: %g\n",              peak_amp, snr, config->target_snr[i] );      if ( peak_amp > config->minimum_peak[i] ) {        gain_adj = abs( snr - config->target_snr[i] ) / 10;	gain_adj = max( gain_adj, .1 );        // Only do gain-control from a certain point        if ( ( snr < config->target_snr[i] ) && ( mid_amp < MAX_MID_AMP ) ) {          private->data.client[i].gain = private->data.client[i].gain + gain_adj;	  // If it's bigger than 100, we suppose nobody's there, and we start at	  // the bottom, again	  if ( private->data.client[i].gain > 200 ){	    private->data.client[i].gain = -200;	  }	  PR_DBG( 4, "Increased gain to %s%i.%i\n",                  swr_ftosii( private->data.client[i].gain ) );        } else {          private->data.client[i].gain = max( private->data.client[i].gain - gain_adj,                                              (double)-300 );          PR_DBG( 4, "Decreased gain to %s%i.%i\n",                  swr_ftosii( private->data.client[i].gain ) );        }      }    }  }  swr_sdb_free_config_struct( context->id, (void**)&config );  out = buffer_out( 0 );  // Add the system-data  *((U32*)out) = swr_crc32( &private->data, size_data );  out += sizeof( U32 );  memcpy( out, &private->data, size_data );  out += size_data;  *((U32*)out) = swr_crc32( private->data_usr,                            private->data.len_usr );  out += sizeof( U32 );  memcpy( out, private->data_usr, private->data.len_usr );  swr_sdb_get_stats_struct( context->id, (void**)&stats );  // Put your code here  // ADD HERE  swr_sdb_free_stats_struct( context->id, (void**)&stats );  return(0);}/** * User messages */int send_custom_msg( swr_sdb_t *context, swr_usr_msg_t *data, swr_msgq ret ) {  send_pdata( context );  return 0;}/* * This is the `destructor'. */int send_finalize( swr_sdb_t *context ) {  if ( sizeof( private_t ) > 0 )    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 send_id;int send_module_init(void) {  swr_spc_desc_t *desc;  int i;  char str[16];  /**   * Get a description-part from SPM   * Give the following parameters:   * Input-ports, output-ports, config-params, stat-params   */  desc = swr_spc_get_new_desc( 0, 1, MAX_CLIENTS * 6 + 2, 0 );  if ( !desc ) {    PR_DBG( 0, "Can't initialise the module. This is BAD!\n" );    return -1;  }  /**   * Define the different parts of config and stats. You have to define   * them in the same order as they appear in the structures. The names   * can be freely chosen.   *   * UM_CONFIG_{INT,DOUBLE,STRING128,POINTER}( "name" );   * UM_STATS_{INT,DOUBLE,STRING128,POINTER,BLOCK}( "name" );   */  for ( i=0; i<MAX_CLIENTS; i++ ) {    sprintf( str, "id%i", i );    UM_CONFIG_INT( str, PARAMETER_DEBUG );  }  for ( i=0; i<MAX_CLIENTS; i++ ) {    sprintf( str, "uplinks%i", i );    UM_CONFIG_INT( str, PARAMETER_DEBUG );  }  for ( i=0; i<MAX_CLIENTS; i++ ) {    sprintf( str, "downlinks%i", i );    UM_CONFIG_INT( str, PARAMETER_DEBUG );  }  for ( i=0; i<MAX_CLIENTS; i++ ) {    sprintf( str, "mafi%i", i );    UM_CONFIG_INT( str, PARAMETER_DEBUG );  }  for ( i=0; i<MAX_CLIENTS; i++ ) {    sprintf( str, "target_snr%i", i );    UM_CONFIG_DOUBLE( str );  }  for ( i=0; i<MAX_CLIENTS; i++ ) {    sprintf( str, "minimum_peak%i", i );    UM_CONFIG_INT( str, PARAMETER_DEBUG );  }  UM_CONFIG_POINTER( "data_usr", PARAMETER_DEBUG );  UM_CONFIG_INT( "len_usr", PARAMETER_DEBUG );  /**   * The in- and outputs have also to be defined in the right order. First   * port first. The additional flag is not used yet, but it will...   *   * UM_INPUT( SIG_{U8,SYMBOL_{S16,COMPLEX,MMX},SAMPLE_S12,S32}, 0 );   * UM_OUTPUT( SIG_{U8,SYMBOL_{S16,COMPLEX,MMX},SAMPLE_S12,S32}, 0 );   */  UM_OUTPUT( SIG_U8, 0 );  // Initialise the callback-functions. Delete the ones you don't use  desc->fn_init              = send_init;  desc->fn_reconfigure       = send_reconfig;  desc->fn_process_data      = send_pdata;  desc->fn_custom_msg        = send_custom_msg;  desc->fn_finalize          = send_finalize;  // And register the module in the SPM. Change the name!  send_id = swr_cdb_register_spc( &desc, "sch_send" );  if ( send_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\n" );  return 0;}/* * This is called upon rmmod */void send_module_exit( void ) {  PR_DBG( 4, "Freeing id: %i\n", send_id );  if ( swr_cdb_unregister_spc( send_id ) < 0 ) {    PR_DBG( 0, "Still in use somewhere\n" );  }}

⌨️ 快捷键说明

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