📄 radio_bs.c
字号:
/*************************************************************************** radio_bs.c - SRadio MoreMS ------------------- begin : 02/10/30 authors : Linus Gasser emails : linus.gasser@epfl.ch ***************************************************************************//*************************************************************************** Changes ------- date - name - description 02/10/30 - ineiti - begin 02/11/04 - ineiti - no msgqs... 03/01/16 - ineiti - added a real multi-user environment 04/03/02 - ineiti - adjusted the gains so that it works... 04/04/20 - ineiti - cleaned up exiting stuff **************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************//** * Make a basestation where multiple mobiles may connect to * * Function: * - emit sync and Sch * - listen to RACh * - allocate MS a position via the Sch * - if MS got lost, clear it's position */#define DBG_LVL 1#include "system.h"#include "sdb.h"#include "stfa.h"#include "antenna.h"#include "std.h"#include "debugging.h"#include "chain.h"#include "../sradio.h"#include "../common.h"#define ANTENNA 0#define STR_LEN 256swr_sdb_idstfa,sch,energy,rndstr[MAX_SLOTS],midamble[MAX_SLOTS],mod[MAX_SLOTS],mafi[MAX_SLOTS],cch[MAX_SLOTS];struct chain_t *ch_sch, *ch_rach, *ch_dch, *uplink[MAX_TR_SLOTS], *downlink[MAX_TR_SLOTS];struct rach_data rach_data;char *slot_str[MAX_SLOTS];struct ms_data mobile[ MAX_MS ];int slots_per_frame, looping, ms_count, frames;void mobile_attach( int index ) { int d1, d2, u1; // The mobile is new, so fill up it's config swr_sdb_set_config_int_array( sch, "id0", index, rach_data.id ); // One uplink and two downlinks d1 = mobile[index].downlink[0] = index * 4 + 3; u1 = mobile[index].uplink[0] = index * 4 + 4; d2 = mobile[index].downlink[1] = index * 4 + 5; swr_sdb_set_config_int_array ( sch, "downlinks0", index, ( 1 << d1 ) + ( 1 << d2 ) ); swr_sdb_set_config_int_array( sch, "uplinks0", index, ( 1 << u1 ) ); downlink[ d1 ] = setup_send( d1, cch, mod, stfa, slot_str ); uplink[ u1 ] = setup_rcv( u1, stfa, mafi, cch, slot_str ); downlink[ d2 ] = setup_send( d2, cch, mod, stfa, slot_str ); swr_sdb_set_config_int_array( sch, "mafi0", index, mafi[ u1 ] ); ms_count++;}void mobile_detach( int index ) { int i, up, down; // Sanity-check if ( !ms_count ) { PR_DBG( 0, "No mobile to detach!\n" ); return; } swr_sdb_set_config_int_array( sch, "id0", index, -1 ); up = swr_sdb_get_config_int_array( sch, "uplinks0", index ); down = swr_sdb_get_config_int_array( sch, "downlinks0", index ); swr_sdb_set_config_int_array( sch, "mafi0", index, -1 ); // Delete all chains for ( i=0; i<MAX_SLOTS; i++ ) { if ( up & ( 1 << i ) ) { swr_chain_destroy( uplink[ i ] ); swr_stfa_notice_sdb( stfa, i, -1 ); swr_free( slot_str[ i ] ); } if ( down & ( 1 << i ) ) { swr_chain_destroy( downlink[ i ] ); swr_stfa_notice_sdb( stfa, i, -1 ); swr_free( slot_str[ i ] ); } } PR_DBG( 1, "Detached 1 mobile.\n" ); ms_count--;}void check_exit( void ) { int i, rec; for ( i=0; i<MAX_MS; i++ ) { if ( swr_sdb_get_config_int_array( sch, "id0", i ) >= 0 ) { rec = swr_sdb_get_stats_int( cch[ mobile[i].uplink[ 0 ] ], "received" ); if ( rec < 1 ) { PR_DBG( 2, "Receiving mobile %i: %i\n", i, rec ); } else { PR_DBG( 4, "Receiving mobile %i: %i\n", i, rec ); }#ifdef USER_SPACE if ( rec < -10 ) { // This mobile hasn't sent anything for the last 10 // frames. mobile_detach( i ); }#else if ( rec < -100 ) { // This mobile hasn't sent anything for the last 100 // frames. mobile_detach( i ); }#endif } }}void check_for_mobile( void ) { int i, index = MAX_MS; // Yipie, there is a new MS. PR_DBG( 1, "MS %i asked for access\n", rach_data.id ); for ( i=0; i<MAX_MS; i++ ) { if ( swr_sdb_get_config_int_array( sch, "id0", i ) == rach_data.id ) { PR_DBG( 0, "MS is still asking for access... strange\n" ); return; } if ( swr_sdb_get_config_int_array( sch, "id0", i ) < 0 ) { index = i; } } if ( index < MAX_MS ) { PR_DBG( 1, "MS got index %i\n", index ); } else { PR_DBG( 0, "MS rejected, list full!\n" ); return; } mobile_attach( index );}/** * this is called once a frame */int dispatcher( int msg, void *data, swr_sdb_id ret_id ) { // Check for 'old' mobiles check_exit(); // Check for RACh if ( swr_sdb_get_stats_int( cch[ SLOT_RACH ], "received" ) == 1 ) { check_for_mobile(); } return 0;}/** * Here everything is prepared */void *start_it( void *arg ) { int i, j; looping = 1; frames = 0; stfa = swr_sdb_instantiate_name( "stfa" ); for ( i=0; i<MAX_MS; i++ ) { for ( j=0; j<MAX_SLOTS; j++ ) { mobile[i].uplink[j] = mobile[i].downlink[j] = -1; } } ms_count = 0; rach_data.id = -2; PR( "Setting up Sch on slot %i\n", SLOT_SCH ); ch_sch = swr_chain_create( NEW_SPC_VAR( "sch_send", sch ), NEW_SPC_VAR( "mapper", mod[SLOT_SCH] ), NEW_SPC( "spread" ), NEW_SPC( "midamble" ), NEW_SPC( "synch_send" ), NEW_SPC( "rrc" ), OLD_SPC_IN( stfa, SLOT_SCH ), CHAIN_END ); swr_stfa_notice_sdb( stfa, SLOT_SCH, sch ); swr_sdb_set_config_double( sch, "target_snr0", 20 ); swr_sdb_set_config_double( sch, "target_snr1", 20 ); PR( "Setting up RACh slot %i\n", SLOT_RACH ); ch_rach = swr_chain_create( OLD_SPC_OUT( stfa, SLOT_RACH ), NEW_SPC_VAR( "energy", energy ), NEW_SPC_VAR( "matched_filter", mafi[SLOT_RACH] ), NEW_SPC( "despread" ), NEW_SPC( "slicer" ), NEW_SPC_VAR( "cch_rcv", cch[SLOT_RACH] ), CHAIN_END ); swr_sdb_set_config_pointer( cch[SLOT_RACH], "data", &rach_data ); swr_sdb_set_config_int( cch[SLOT_RACH], "length", sizeof( rach_data ) ); swr_stfa_notice_func( stfa, 10, dispatcher ); swr_stfa_go( stfa ); swr_sdb_set_config_int( stfa, "attn_rx", 5 ); while( looping ) { usleep( 1000000 ); } swr_stfa_stop( stfa ); PR_DBG( 0, "Stopping STFA\n" ); return 0;}struct thread start;/** * This function is called upon "insmod" and is used to register the * different parts of the module to the SPM. */int um_module_init(void) { int i; looping = 0; ch_sch = NULL; ch_rach = NULL; ch_dch = NULL; for ( i=0; i<MAX_TR_SLOTS; i++ ) { uplink[i] = downlink[i] = NULL; } if ( swr_thread_init( &start, start_it, NULL ) ) { goto rrc_no_thread; } return 0;rrc_no_thread: PR_DBG( 0, "Couldn't init thread\n" ); return -1;}void um_module_exit( void ) { int i; looping = 0; swr_thread_free( &start, NULL ); PR_DBG( 0, "deleting everything\n" ); swr_chain_destroy( ch_sch ); swr_chain_destroy( ch_rach ); swr_chain_destroy( ch_dch ); for ( i=0; i<MAX_TR_SLOTS; i++ ) { swr_chain_destroy( uplink[i] ); swr_chain_destroy( downlink[i] ); } swr_sdb_destroy( stfa );}module_init( um_module_init );module_exit( um_module_exit );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -