📄 stfa_ics.c
字号:
/*************************************************************************** stfa_ics.c - RTLinux kernel module for a ics-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 04/01/20 - ineiti - made a STFA_ics to interface the ics-cards 04/03/08 - ineiti - adjusted descriptions 04/03/19 - ineiti - fixed the number of bytes we write for TX_OFF 04/03/22 - ineiti - renamed MSG_UPDATE to MSG_PREPARE 04/03/31 - ineiti - takes care about chains that are still active 04/04/06 - ineiti - added PREPARE_SWALLOW 04/05/07 - ineiti - cleaned up buffer_rx for even and odd STFAs 04/05/14 - ineiti - enabled tx/rx switching again, but this time TX_OFF is 0, so we shouldn't introduce noise. But it is necessary for the channel-simulation 04/05/25 - ineiti - swr_sdb_set_config_int adjusted to not do the tree- spanning thingie **************************************************************************//*************************************************************************** * * * 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_ics 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 in- and outputs suited for the * ICS-cards. * * 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 )// Converts TX-bytes to RX-bytes#define TX2RX(x) ((x)*2*2)// 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) \ TX2RX( ( ( ( (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 ) > \ TX2RX( private->dma_bytes - private->slot_bytes / 2 ) ) ? \ ( OFFSET_RX( slot ) - TX2RX( 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) + TX2RX( 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 + TX2RX( private->slot_bytes ) )#define DMA_BEGIN_TX ( private->buffer_tx + private->slot_bytes )#define DMA_END_RX ( private->buffer_rx + \ TX2RX( 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 at the end of the slot, in chips int guard_period_chips; // 90 // The more general gains (the above should disappear sometimes) int attn_tx; // 0 int attn_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 // To pass the buffer_rx pointer in case when there's more than // one stfa void *buffer_rx; // NULL // Whether to send or receive int tx; // 0 (rcv) // The frequency in MHz int freq; // 2'380 // The frequency difference from the ICS-cards int freq_diff; // 0 // Injection: // (0) automatic // (1) Low-side // (2) high-side int side; // 0}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 more general gains int attn_tx; int attn_rx; int tx; int freq; int freq_diff; int side; 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 ); SET_STATUS( MULTI_IN ); // 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; config->buffer_rx = NULL; config->tx = 0; config->freq = 2380; config->freq_diff = 0; config->side = 0; private->tx = -1; private->freq = 0; private->freq_diff = 0; private->side = -1; // 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 // We receive 32-bit samples, but transmit 16-bit samples // And one stfa holds the rx of two... go ask ICS if ( !( private->nbr_stfa % 2 ) ){ private->buffer_rx = swr_malloc( MAX_BUFFER_SIZE * 2 * 2 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -