📄 rrc_send.c
字号:
/*************************************************************************** rrc.c - SRadio module for a root-raised cosine ------------------- begin : 2002 authors : Linus Gasser emails : linus.gasser@epfl.ch ***************************************************************************//*************************************************************************** Changes ------- date - name - description 02-10-16 - ineiti - begin 04/03/06 - ineiti - adjusted description Take Care --------- if ever you should have the idea to change this rrc, take care about the fact that the peak of the RRC is in the middle! **************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************//** * short makes the root-raised-cosine with roll-off 0.22 * * Is more or less a copy-paste from the ancient software-radio. * Highly-optimized convolution and upsampling of 4 in one. */#include "spc.h"#include "antenna.h"#define DBG_LVL 0#define TX_FILTER_LENGTH_CHIPS 12short int data_rrc[] = { 111, -270, -168, -141, -396, 312, -153, 669, 753, -141, 882, -1551, -1137, -435, -2286, 2979, 1473, 1935, 5322, -5937, -1710, -7320,-18573, 27894, 31506,-27894,-18573, 7320, -1710, 5937, 5322, -1935, 1473, -2979, -2286, 435, -1137, 1551, 882, 141, 753, -669, -153, -312, -396, 141, -168, 270 };typedef struct {}config_t;typedef struct {}stats_t;typedef struct { mmx_t tx_filter_def[TX_FILTER_LENGTH_CHIPS] __attribute__ ((aligned(8))); mmx_t *buffer_in; int size_in;}private_t;/** * The initialisation part that is only called the first time this module * is instantiated. */int send_init( swr_sdb_t *context ) { config_t *config; stats_t *stats; int i; MOD_INC_USE_COUNT; 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 ); for(i=0;i<12;i++) { private->tx_filter_def[i].w[0] = data_rrc[4*i]; private->tx_filter_def[i].w[1] = data_rrc[4*i+1]; private->tx_filter_def[i].w[2] = data_rrc[4*i+2]; private->tx_filter_def[i].w[3] = data_rrc[4*i+3]; } private->buffer_in = 0; private->size_in = 0; swr_sdb_free_config_struct( context->id, (void**)&config ); swr_sdb_free_stats_struct( context->id, (void**)&stats ); return 0;}/** * To configure the inputs */int send_configure_inputs( swr_sdb_t *context ) { config_t *config; swr_sdb_get_config_struct( context->id, (void**)&config ); size_in(0) = size_out(0) / DAQ_SAMPLES_PER_CHIP; // Allocate some private buffer for the complex2mmx operation // But only if the size changed if ( size_in(0) != private->size_in ) { if ( private->buffer_in ) { swr_free( private->buffer_in ); } private->buffer_in = swr_malloc( size_in(0) * sizeof( SYMBOL_MMX ) ); private->size_in = size_in(0); } swr_sdb_free_config_struct( context->id, (void**)&config ); return 0;}/** * To configure the outputs */int send_configure_outputs( swr_sdb_t *context ) { config_t *config; swr_sdb_get_config_struct( context->id, (void**)&config ); size_out(0) = size_in(0) * DAQ_SAMPLES_PER_CHIP; // Allocate some private buffer for the complex2mmx operation // But only if the size changed if ( size_in(0) != private->size_in ) { if ( private->buffer_in ) { swr_free( private->buffer_in ); } private->buffer_in = swr_malloc( size_in(0) * sizeof( SYMBOL_MMX ) ); private->size_in = size_in(0); } swr_sdb_free_config_struct( context->id, (void**)&config ); return 0;}/** * Every time somebody from the outside changes a configuration value, * this function is called just before the working-function */int send_reconfig( swr_sdb_t *context ) { config_t *config; int ret = 0; swr_sdb_get_config_struct( context->id, (void**)&config ); swr_sdb_free_config_struct( context->id, (void**)&config ); return ret;}/** * The actual working function */int send_pdata( swr_sdb_t *context ) { stats_t *stats; SYMBOL_COMPLEX *in_cplx; SYMBOL_MMX *in; SAMPLE_S12 *out; mmx_t ZERO_TWO_LSBs = {0xfffcfffcfffcfffcULL}, SEND = {0x0002000200020002ULL}; int i, j; mmx_t *filter = private->tx_filter_def; PR_DBG( 4, "Entered pdata\n" ); // Convert from complex to complex_mmx in_cplx = port_in(0).data; in = private->buffer_in; for ( i=0; i < size_in(0); i++ ) { in[i].w[0] = in[i].w[2] = in_cplx[i].real; in[i].w[1] = in[i].w[3] = in_cplx[i].imag; } out = buffer_out( 0 ); PR_DBG( 4, "Got buffer: %p / %p\n", in, out ); PR_DBG( 4, "Got config\n" ); // Convolution for the first couple of samples, we admit // size_in(0) > 24 // Try to switch the sending on a bit earlier...#define BEFORE 50 out -= 4*BEFORE + 24; for ( i=-BEFORE; i<0; i++ ) { movq_m2r( SEND, mm0 ); movq_r2m( mm0, *out ); out += 4; } for ( i=0; i < 12; i++ ) { movq_m2r( filter[ 0 ], mm2 ); pxor_r2r( mm0, mm0 ); movq_m2r( in[ i ], mm3 ); for ( j=1; j<=i; j++ ) { pmulhw_r2r( mm2, mm3 ); movq_m2r( filter[ j ], mm2 ); paddsw_r2r( mm3, mm0 ); movq_m2r( in[ i - j ], mm3 ); } pmulhw_r2r( mm2, mm3 ); paddsw_r2r( mm3, mm0 ); pand_m2r( ZERO_TWO_LSBs, mm0 ); por_m2r( SEND, mm0 ); movq_r2m( mm0, *out ); out += 4; } // The actual convolution is done here for ( i=12; i<size_in(0); i++ ) { movq_m2r( filter[ 0 ], mm2 ); pxor_r2r( mm0, mm0 ); movq_m2r( in[ i ], mm3 ); // This will be unrolled anyway by the compiler... for ( j=1; j < 10; j += 2 ) { movq_m2r( filter[ j ], mm4 ); pmulhw_r2r( mm2, mm3 ); movq_m2r( in[ i - j ], mm5 ); paddsw_r2r( mm3, mm0 ); movq_m2r( filter[ j + 1 ], mm2 ); pmulhw_r2r( mm4, mm5 ); movq_m2r( in[ i - j - 1 ], mm3 ); paddsw_r2r( mm5, mm0 ); } movq_m2r( filter[ 11 ], mm4 ); pmulhw_r2r( mm2, mm3 ); movq_m2r( in[ i - 11 ], mm5 ); paddsw_r2r( mm3, mm0 ); pmulhw_r2r( mm4, mm5 ); paddsw_r2r( mm5, mm0 ); pand_m2r( ZERO_TWO_LSBs, mm0 ); por_m2r( SEND, mm0 ); movq_r2m( mm0, *out ); out += 4; } // Convolution for the tail for ( i=size_in(0); i < size_in(0) + 12; i++ ) { movq_m2r( filter[ i - size_in(0) + 1 ], mm2 ); pxor_r2r( mm0, mm0 ); movq_m2r( in[ size_in(0) - 1 ], mm3 ); for ( j=2; j < size_in(0) + 12 - i; j++ ) { pmulhw_r2r( mm2, mm3 ); movq_m2r( filter[ i - size_in(0) + j ], mm2 ); paddsw_r2r( mm3, mm0 ); movq_m2r( in[ size_in(0) - j ], mm3 ); } pmulhw_r2r( mm2, mm3 ); paddsw_r2r( mm3, mm0 ); pand_m2r( ZERO_TWO_LSBs, mm0 ); por_m2r( SEND, mm0 ); movq_r2m( mm0, *out ); out += 4; } emms(); PR_DBG( 4, "Did convolution\n" ); // Update the stats swr_sdb_get_stats_struct( context->id, (void**)&stats ); swr_sdb_free_stats_struct( context->id, (void**)&stats ); PR_DBG( 4, "About to quit\n" ); return 0;}int send_finalize( swr_sdb_t *context ) { swr_free( private ); MOD_DEC_USE_COUNT; return 0;}swr_spc_id_t send_id;/** * This function is called upon "insmod" and is used to register the * different parts of the module to the SPM. */int send_module_init(void) { swr_spc_desc_t *desc; // Get a description-part from SPM // Nbr_input_ports, Nbr_output_ports, Nbr_config_values, Nbr_stats_values desc = swr_spc_get_new_desc( 1, 1, 0, 0 ); if ( !desc ) { PR_DBG( 0, "Can't initialise the module. This is bad!\n" ); return -1; } // Define the different parts of config, stats and io-ports // Initialise the callback-functions. NULL for not-used functions desc->fn_init = send_init; desc->fn_reconfigure = send_reconfig; desc->fn_process_data = send_pdata; desc->fn_custom_msg = NULL; desc->fn_finalize = send_finalize; desc->fn_configure_inputs = send_configure_inputs; desc->fn_configure_outputs = send_configure_outputs; UM_INPUT( SIG_SYMBOL_COMPLEX, 0 ); UM_OUTPUT( SIG_SAMPLE_S12, 0 ); // And register the module in the SPM send_id = swr_cdb_register_spc( &desc, "rrc" ); if ( send_id == SWR_SPM_INVALID_ID ) { swr_spc_free_desc( desc ); PR_DBG( 0, "Couldn't register the module!\n" ); return 1; } return 0;}void send_module_exit( void ) { PR_DBG( 2, "RRC is going\n" ); 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 + -