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

📄 stfa_complex.c

📁 This a framework to test new ideas in transmission technology. Actual development is a LDPC-coder in
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************              stfa_complex.c  -  RTLinux kernel module for a complex STFA                            -------------------    begin                :  2002    authors              :  Linus Gasser    emails               :  linus.gasser@epfl.ch ***************************************************************************//***************************************************************************                                 Changes                                 ------- date - name - description 02/09/26 - ineiti - begin 02/11/04 - ineiti - extended for notice_sdb and notice_functions 03/01/06 - ineiti - fix the offset to allow for chip-resolution 03/01/13 - ineiti - added a supplementary offset for the sending part 03/02/25 - ineiti - cleaning up the different offsets 03/03/03 - ineiti - adding sltots_per_frame and slot_size to config 03/03/13 - ineiti - finished with implementation of guard-interval 03/05/12 - ineiti - deleted the amp_* from both config and stats 03/11/13 - ineiti - added SUBS_MSG_UPDATE to make sure the chains are OK 03/11/24 - ineiti - made a complex STFA 03/12/15 - ineiti - chained the STFAs instead of array in first STFA 03/12/?? - ineiti - made it complex 04/03/08 - ineiti - adjusted description 04/03/22 - ineiti - renamed MSG_UPDATE to MSG_PREPARE 04/03/31 - ineiti - made sure that calling chain is not already active 04/04/06 - ineiti - added PREPARE_SWALLOW                                   TODO                                  ---- * Implement a real MAX_SLOTS and NUM_SLOTS... **************************************************************************//*************************************************************************** *                                                                         * *   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.                                   * *                                                                         * ***************************************************************************//** *  The STFA_complex implements a framed TDD-transmission. It is THE module  * in the software-radio. It is responsible for the interaction with the  * hardware or the simulator, and allows to define the scheduling of the  * different slots. *  This module has x inputs and x outputs which are tied to one antenna. *  It differs from STFA in that it has complex in- and outputs *   * User messages: * - "ANT": the antenna received/sent a slot * - "Go": start the STFA * - "Stop": stop the STFA * - "Notice_func": add a notice-function * - "Notice_sdb": add a notice-sdb * * The user-messages can be called using functions which are defined in stfa.h: * - add a notice-function to a slot *   void swr_stfa_notice_func( swr_sdb_id stfa, int slot, func *f ) * - add a sdb to a slot *   void swr_stfa_notice_sdb( swr_sdb_id stfa, int slot, swr_sdb_id sdb_id ); * - Start the stfa, this also starts the DMA-transfer. *   void swr_stfa_go( swr_sdb_id stfa ); * - Stop the stfa. This also stops the DMA-transfer. *   void swr_stfa_stop( swr_sdb_id stfa ); */#include "spc.h"#include "antenna.h"#include "stfa.h"#include "rf.h"#define DBG_LVL 0#define MAX_DMA_SIZE ( MAX_SLOT_BYTES * MAX_SLOTS )#define MAX_BUFFER_SIZE ( MAX_SLOT_BYTES + MAX_DMA_SIZE + MAX_SLOT_BYTES )// This is the logical pointer from the start of the DMA-region on where// to find the start of the slot#define OFFSET_RX(slot) \  ( ( ( ( (slot) * private->blocks_per_slot + private->offset_rcv_blocks + \           private->rx_tx_delay_blocks ) % \        private->len_frame_blocks ) * DAQ_DMA_BLOCK_SIZE_BYTES + \      private->rx_tx_delay_bytes + private->offset_rcv_bytes + \      private->dma_bytes ) % private->dma_bytes )// The corrected position, where the last half slot is wrapped IN FRONT// of the DMA region (memcpy has to take place)#define DMA_OFFSET_RX(slot) \  ( ( OFFSET_RX( slot ) > ( private->dma_bytes - private->slot_bytes / 2 ) ) ? \    ( OFFSET_RX( slot ) - private->dma_bytes ) : OFFSET_RX( slot ) )// The memory-buffer is one slot in front of the dma-buffer#define BUFFER_OFFSET_RX(slot) \  ( DMA_OFFSET_RX(slot) + private->slot_bytes )// *_TX is the same as *_RX#define OFFSET_TX(slot) \  ( ( ( ( (slot) * private->blocks_per_slot + private->offset_rcv_blocks ) % \        private->len_frame_blocks ) * DAQ_DMA_BLOCK_SIZE_BYTES + \      private->offset_rcv_bytes - private->offset_send_bytes + \      private->dma_bytes ) % private->dma_bytes )#define DMA_OFFSET_TX(slot) \  ( ( OFFSET_TX( slot ) > ( private->dma_bytes - private->slot_bytes / 2 ) ) ? \    ( OFFSET_TX( slot ) - private->dma_bytes ) : OFFSET_TX( slot ) )#define BUFFER_OFFSET_TX(slot) \  ( DMA_OFFSET_TX(slot) + private->slot_bytes )// some handy definitions#define DMA_BEGIN_RX ( private->buffer_rx + private->slot_bytes )#define DMA_BEGIN_TX ( private->buffer_tx + private->slot_bytes )#define DMA_END_RX ( private->buffer_rx + private->dma_bytes + private->slot_bytes )#define DMA_END_TX ( private->buffer_tx + private->dma_bytes + private->slot_bytes )int nbr_stfa;typedef struct {  // How many slots in advance a TX-chain is called  int slot_send_offset; // 2  // The general delay between the master and this radio  int offset_chips_rcv; // 0  // The more fine delay between the master and this radio  int offset_samples_rcv; // 0  // Kind of the distance between the master and this radio, as  // the samples will be sent this much earlier, in order to arrive  // in synch at the master  int offset_samples_send; // 0  // Set the size of the transmission-slots  int blocks_per_slot; // 20  // Set the number of slots per frame  int slots_per_frame; // 15  // The guard-period, which is put in before and after the slot, in chips  int guard_period_chips; // 90  // The gains for direct changes  int gain_tx_0, gain_tx_1, gain_tx_2;  int gain_rx_0;  // The more general gains (the above should disappear sometimes)  int gain_tx; // 0  int gain_rx; // 0    // Master-Slave Stfa's in MIMO  // Each STFA has the id of the next STFA or -1 to finish the chain  int stfa_id; // -1}config_t;typedef struct {  // How many frames have been done  int frame_count;  // This many blocks per slot  int blocks_per_slot;  // This many slots per frame  int slots_per_frame;  // The whole reception-dma-area, including buffer-zones  block_t rx;  // The whole transmission-dma-area, including buffer-zones  block_t tx;  // How many chips from the beginning of the buffer slot0 is  // placed  int offset_chips;  // How many samples from the beginning of the buffer slot0 is  // placed  int offset_samples;}stats_t;typedef struct {  char *buffer_rx;  char *buffer_tx;  int nbr_stfa;  int ant_index;  int sso;  // config->offset_chips_rcv * DAQ_QI_SAMPLES_PER_CHIP +  //     config->offset_samples_rcv =  //   ( private->offset_rcv_blocks * DAQ_DMA_BLOCK_SIZE_QI_SAMPLES +  //     private->offset_rcv_bytes / 2 )  // This is done because the hardware works in 'blocks', so we can tell the  // hardware to wake us up a bit later/earlier and the calculate the rest.  int offset_rcv_blocks;  // This is relative to offset_rcv_blocks  int offset_rcv_bytes;  // This equals config->offset_samples_send, and should only  // be used on the MS-end. In bytes  int offset_send_bytes;  // The delay introduced by the hardware, in blocks and bytes  int rx_tx_delay_blocks;  int rx_tx_delay_bytes;  // The actual slots per frame  int slots_per_frame;  // The actual size of the transmission-slots, in dma-blocks  int blocks_per_slot;  // The sdb's to notice at a given rcv-slot  swr_sdb_id notice_sdb[ MAX_SLOTS ];  // A function to notice at a given rcv-slot. See stfa.h for a  // definition of func  func *notice_f[ MAX_SLOTS ];  // To indicate whether the antenna is running right now  int running;  // Number of bytes in a slot  int slot_bytes;  // The length of a frame in blocks  int len_frame_blocks;  // The length of the DMA-part  int dma_bytes;  // The guard period, in bytes  int guard_period_bytes;  // The gains for direct changes  int gain_tx_0, gain_tx_1, gain_tx_2;  int gain_rx_0;  // The more general gains  int gain_tx;  int gain_rx;    int stfa_id;}private_t;/** * The initialisation part that is only called the first time this module * is instantiated. */int spc_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 );  // Tell the subsystem we don't accept resizes, but only emit them  // Furthermore, don't propagate prepare-msgs  SET_STATUS( RESIZE_NONE );  SET_STATUS( PREPARE_SWALLOW );  // First of all, initialise the static and private stuff  private->nbr_stfa = nbr_stfa++;  private->offset_rcv_blocks = 0;  private->offset_rcv_bytes = 0;  private->offset_send_bytes = 0;  private->sso = 2;  private->slots_per_frame = 0;  private->blocks_per_slot = 0;  private->running = 0;  private->stfa_id = -1;  config->stfa_id = -1;  config->slot_send_offset = 2;  config->offset_chips_rcv = 0;  config->offset_samples_rcv = 0;  config->offset_samples_send = 0;  // This is pseudo-UMTS standard  config->blocks_per_slot = 20;  config->slots_per_frame = 15;  config->guard_period_chips = 90;   // Initialise the antenna-dispatcher.  if ( ( private->ant_index = swr_ant_init( context->id ) ) < 0 ) {    PR_DBG( 0, "Can't initialise dispatcher\n" );    return -1;  }  PR_DBG( 1, "Initialised ant-dispatcher %i\n", private->ant_index );  // And put the receive and transmit-buffers in place  private->buffer_rx = swr_malloc( MAX_BUFFER_SIZE );  private->buffer_tx = swr_malloc( MAX_BUFFER_SIZE );  if ( !private->buffer_rx || !private->buffer_tx ) {    PR_DBG( 0, "Couldn't allocate all necessary memory for the DMA!\n"            "Aborting! This is SERIOUS\n" );    return -1;  }  // Setting up the antenna-parameters  i = swr_ant_get_rx_tx_delay( private->nbr_stfa );  private->rx_tx_delay_blocks = i / DAQ_DMA_BLOCK_SIZE_BYTES;  private->rx_tx_delay_bytes = i % DAQ_DMA_BLOCK_SIZE_BYTES;   //Tell the antenna that we transmitt complex data//  swr_ant_set_is_complex( private->ant_index, 1 );//  PR_DBG( 4, "antenna %i is told to transmitt complex data \n",//	  private->ant_index );  // Now we can begin initialising things depending on private->  stats->blocks_per_slot = 0;  stats->slots_per_frame = 0;  stats->frame_count = 0;  stats->rx.data = private->buffer_rx;  stats->rx.type = SIG_SYMBOL_COMPLEX;  stats->tx.data = private->buffer_tx;  stats->tx.type = SIG_SYMBOL_COMPLEX;  // Initialise the slots  for ( i=0; i < MAX_SLOTS; i++ ) {    port_in(i).data = 0;    port_in(i).size = 0;    port_in(i).flags = SWR_PORT_OWN_MALLOC;    port_out(i).data = 0;    port_out(i).size = 0;    port_out(i).flags = SWR_PORT_OWN_MALLOC;    // And initialise the notice-queues    private->notice_sdb[i] = -1;    private->notice_f[i] = NULL;  }  // This is only valid with the old RF-cards!  swr_ant_rf_get_gains( private->nbr_stfa,                        &config->gain_tx_0, &config->gain_tx_1, &config->gain_tx_2,                        &config->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;  private->gain_tx = private->gain_rx =    config->gain_tx = config->gain_rx = 0;  swr_sdb_free_stats_struct( context->id, (void**)&stats );  swr_sdb_free_config_struct( context->id, (void**)&config );  return 0;}/** * The initialisation with regard to the slots and frame is quite complex, * so it's outsourced... */int init_slots_frame( swr_sdb_t *context, config_t *config, stats_t *stats ) {  if ( private->running ) {    PR_DBG( 0, "Can't change slot/frame parameters while running!\n" );    return -1;  }  if ( config->slots_per_frame <= config->slot_send_offset ) {    PR_DBG( 0, "Can't ask to build a slot more than 1 frame in advance.\n"            "Offending assertion: slots_per_frame(%i) <= slot_send_offset(%i)\n",            config->slots_per_frame, config->slot_send_offset );    return -1;  }  if ( config->slots_per_frame * config->blocks_per_slot <=       private->rx_tx_delay_blocks ) {    PR_DBG( 0, "There are less blocks in the frame (%i) than the delay between\n"            "the reception and transmission (%i). Aborting\n",            config->slots_per_frame * config->blocks_per_slot,            private->rx_tx_delay_blocks );    return -1;  }  // Update the stats (for others) and private (for us) parameters  private->slots_per_frame = stats->slots_per_frame = config->slots_per_frame;  private->blocks_per_slot = stats->blocks_per_slot = config->blocks_per_slot;  private->slot_bytes = private->blocks_per_slot * DAQ_DMA_BLOCK_SIZE_BYTES;  private->len_frame_blocks = private->blocks_per_slot * private->slots_per_frame;  private->dma_bytes = private->slot_bytes * private->slots_per_frame;  // And tell the antenna what we're doing  swr_ant_set_slot_len( private->nbr_stfa, private->blocks_per_slot );  swr_ant_set_frame_params( private->nbr_stfa,                            private->buffer_rx + private->slot_bytes,                            private->buffer_tx + private->slot_bytes );  // Put the right length for outside viewers. We want to show the whole  // frame including the two buffer-spaces, this is the reason for the  // + 2 * private->blocks_per_slot  stats->rx.size = stats->tx.size =    ( private->dma_bytes + 2 * private->slot_bytes ) /     DAQ_BYTES_PER_QI_SAMPLE;  // Some debugging info (more to come ;-)  PR_DBG( 2, "Buffer size:%i*%i*block_size=%i tx@%p-%p and rx@%p-%p\n",          private->slots_per_frame, 	  private->blocks_per_slot,          private->len_frame_blocks * private->slot_bytes,          private->buffer_tx,          private->buffer_tx + private->slot_bytes,          private->buffer_rx,          private->buffer_rx + private->slot_bytes );  return 0;}/** * Every time somebody from the outside changes a configuration value, * this function is called just before the working-function */int spc_reconfig( swr_sdb_t *context ) {  config_t *config;  int ret = 0, slot, offset_samples;  stats_t *stats;  swr_sdb_get_config_struct( context->id, (void**)&config );  swr_sdb_get_stats_struct( context->id, (void**)&stats );  // If there is another STFA in the chain, contact it  private->stfa_id = config->stfa_id;  if( private->stfa_id >= 0 ){    PR_DBG( 4, "Putting values to %i\n", config->stfa_id );    swr_sdb_set_config_int( config->stfa_id, "slot_send_offset", 			    config->slot_send_offset );    swr_sdb_set_config_int( config->stfa_id, "offset_chips_rcv", 			    config->offset_chips_rcv );    swr_sdb_set_config_int( config->stfa_id, "offset_samples_rcv", 

⌨️ 快捷键说明

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