📄 synch.c
字号:
/*************************************************************************** * synch.c - Macro for synchronisation with BS * ------------------- * begin : 03/03/05 * authors : ineiti * emails : linus.gasser@epfl.ch ***************************************************************************//*************************************************************************** * Changes * ------- * date - name - description * 03/03/05 - ineiti - begin * 04/03/06 - 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 order to have a simple synchronisation going, this macro has been * written. You can call it and then wait for the synchronisation to be * complete, before going on with the rest of the radio. * * Usage * ----- * * This macro can be used either in 'polling'- or in 'callback'-mode. For * both modes, after you instantiated the macro with swr_sdb_instantiate_name, * you have to set the 'stfa_id'. * For the polling-mode, you can directly set the 'synch' parameter to 1, * start the stfa and wait in regular intervals whether the 'status' is 1, * which indicates that a synchronisation has been found. * In callback-mode, you have to give a pointer to a 'func' (as defined in * stfa.h) in 'call_synched'. After setting the 'synch' parameter to 1, you * can wait for 'func' to be called. * In either mode, once the synchronisation is achieved, you must set the * 'synch' parameter to 0 before trying to add other modules to the stfa. * * For an example, see Radio/Simple/MS/radio_ms.c */#include "spc.h"#include "stfa.h"#include "antenna.h"#define DBG_LVL 0typedef struct { // the id of the stfa where the synch has to attach itself int stfa_id; // -1 // The needed energy to consider synchronisation int min_energy; // 2^14 // If a change from 0 to 1 is detected, the module attaches // all necessary chains to the stfa. On a change from 1 to 0, // all attached chains to the stfa are deleted, except the first one. int synch; // 0 // A pointer to a 'func' (defined in stfa.h) that // is called if a synchronisation has succesfully been detected. func *call_synched; // NULL}config_t;typedef struct { // 0 means not synched, 1 tells it's synched int status; // The offset of the synchronisation-signal int offset; // the synchronisation-module where the matched-filter can be // attached to in order to decode the synch-channel swr_sdb_id synch_rcv;}stats_t;typedef struct { swr_sdb_id synch_rcv[MAX_SLOTS]; int synching; int slots; int guard; int rx_gain; int offset;}private_t;/* * The initialisation function, or constructor, * is called the first time this module is instantiated. */int spc_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 config->min_energy = 1 * ( 1 << 14 ); config->synch = private->synching = 0; config->call_synched = 0; stats->status = 0; stats->synch_rcv = -1; for ( i=0; i<MAX_SLOTS; i++ ) { private->synch_rcv[i] = -1; } // 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 spc_reconfig( swr_sdb_t *context ) { // Definition of variables - don't touch config_t *config; stats_t *stats; swr_sdb_id stfa; int i, synch; swr_sdb_get_config_struct( context->id, (void**)&config ); synch = config->synch; stfa = config->stfa_id; swr_sdb_free_config_struct( context->id, (void**)&config ); if ( synch == 1 ) { if ( !private->synching && ( stfa >= 0 ) ) { // Set up all the synch_rcv-modules private->slots = swr_sdb_get_stats_int( stfa, "slots_per_frame" ); private->guard = swr_sdb_get_config_int( stfa, "guard_period_chips" ); // If we have a guard-period, we can be sure to miss the synchronisation // signal... swr_sdb_set_config_int( stfa, "guard_period_chips", 0 ); PR_DBG( 2, "Setting up %i slots for synchronising\n", private->slots ); for ( i=0; i<private->slots; i++ ) { swr_chain_create( 2, OLD_SPC_OUT( stfa, i ), NEW_SPC_VAR( "synch_rcv", private->synch_rcv[i] ) ); } private->synching = 1; private->rx_gain = 0; swr_stfa_notice_sdb( stfa, private->slots - 1, context->id ); } } else if ( synch == 0 ) { if ( private->synching && ( stfa >= 0 ) ) { // Destroy all unnecessary synch-modules PR_DBG( 2, "Freeing %i slots of synchronising\n", private->slots ); for ( i=1; i<private->slots; i++ ) { swr_sdb_destroy( private->synch_rcv[i] ); private->synch_rcv[i] = -1; } private->synching = 0; // Write the synchronisation-offset to the STFA swr_sdb_set_config_int( stfa, "guard_period_chips", private->guard ); swr_sdb_set_config_int( stfa, "offset_chips_rcv", private->offset ); swr_sdb_set_config_int( private->synch_rcv[0], "stfa_id", stfa ); swr_sdb_get_stats_struct( context->id, (void**)&stats ); stats->synch_rcv = private->synch_rcv[0]; swr_sdb_free_stats_struct( context->id, (void**)&stats ); swr_stfa_notice_sdb( stfa, private->slots - 1, -1 ); } } return 0;}int spc_send( swr_sdb_t *context ) { config_t *config; stats_t *stats; int max_slot, max_en, max_pos, i, en; func *call = NULL; swr_sdb_get_config_struct( context->id, (void**)&config ); swr_sdb_get_stats_struct( context->id, (void**)&stats ); if ( private->synching ) { PR_DBG( 4, "Searching for synchronisation\n" ); max_slot = -1; max_en = 0; max_pos = 0; for ( i=0; i<private->slots; i++ ) { en = swr_sdb_get_stats_int( private->synch_rcv[i], "synch_amp" ); if ( en > max_en ) { max_slot = i; max_en = en; max_pos = swr_sdb_get_stats_int( private->synch_rcv[i], "synch_pos" ); } } // Check that we have enough energy from the basestation if ( max_en < config->min_energy ) { private->rx_gain += 1; PR_DBG( 3, "Max_en: %i, Increasing rx-gain to: %i\n", max_en, private->rx_gain ); if ( private->rx_gain > 1024 ) { PR_DBG( 0, "Rx-gain too high, restarting...\n" ); private->rx_gain = 0; } //swr_sdb_set_config_int( config->stfa_id, "amp_rx_if", private->rx_gain ); swr_ant_set_gains( 0, (double)private->rx_gain, 0 ); } else { // Save the offset, and set the status to 'synched' private->offset = max_slot * swr_sdb_get_stats_int( config->stfa_id, "blocks_per_slot" ) * DAQ_DMA_BLOCK_SIZE_SAMPLES / DAQ_SAMPLES_PER_CHIP + max_pos; PR_DBG( 2, "Top pos: %i at slot %i with energy %i -> offset %i\n", max_pos, max_slot, max_en, private->offset ); stats->status = 1; stats->offset = private->offset; call = config->call_synched; config->synch = 0; } } else { PR_DBG( 0, "There should be no msg while not synching!\n" ); } swr_sdb_free_stats_struct( context->id, (void**)&stats ); swr_sdb_free_config_struct( context->id, (void**)&config ); // If we have a call-back function, let's call it... if ( call ) { spc_reconfig( context ); call( SUBS_MSG_OK, NULL, context->id ); } return 0;}/* * This is the `destructor'. */int spc_finalize( swr_sdb_t *context ) { int i; PR_DBG( 2, "Deleting synch\n" ); // Delete all remaining synchs for ( i=0; i<MAX_SLOTS; i++ ) { if ( private->synch_rcv[i] >= 0 ) { swr_sdb_destroy( private->synch_rcv[i] ); } } if ( sizeof( private_t ) > 0 ) swr_free( private ); MOD_DEC_USE_COUNT; PR_DBG( 2, "Finished deleting synch\n" ); 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 cdb_id;int spc_module_init(void) { swr_spc_desc_t *desc; /** * 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, 0, 4, 3 ); 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" ); */ UM_CONFIG_INT( "stfa_id" ); UM_CONFIG_INT( "min_energy" ); UM_CONFIG_INT( "synch" ); UM_CONFIG_POINTER( "call_synched" ); UM_STATS_INT( "status" ); UM_STATS_INT( "offset" ); UM_STATS_INT( "synch_rcv" ); // Initialise the callback-functions. Delete the ones you don't use desc->fn_init = spc_init; desc->fn_reconfigure = spc_reconfig; desc->fn_process_data = spc_send; desc->fn_finalize = spc_finalize; // And register the module in the SPM. Change the name! cdb_id = swr_cdb_register_spc( &desc, "macro_synch" ); if ( cdb_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 spc_module_exit( void ) { PR_DBG( 2, "Freeing id: %i\n", cdb_id ); if ( swr_cdb_unregister_spc( cdb_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 + -