438 lines
12 KiB
C
438 lines
12 KiB
C
#include <string.h>
|
|
#include <math.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include "SIMULATION/TOOLS/defs.h"
|
|
#include "SIMULATION/RF/defs.h"
|
|
|
|
#include "phy/DOT11/defs.h"
|
|
#include "phy/DOT11/commonvars.h"
|
|
#include <malloc.h>
|
|
|
|
#define BW 5.0
|
|
|
|
//#include "PHY/TOOLS/twiddle64.h"
|
|
|
|
#include "UTIL/LOG/log.h"
|
|
|
|
#define FRAME_LENGTH_SAMPLES_MAX 76800
|
|
|
|
uint16_t rev64[64];
|
|
|
|
#define RX_THRES_dB 26
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
char c;
|
|
|
|
int i,aa,aarx;
|
|
double sigma2, sigma2_dB=0,SNR,snr0=10.0,snr1=10.2;
|
|
int snr1set=0;
|
|
uint32_t *txdata,*rxdata[2];
|
|
double *s_re[2],*s_im[2],*r_re[2],*r_im[2];
|
|
double iqim=0.0;
|
|
int trial, ntrials=1;
|
|
int n_rx=1;
|
|
|
|
int awgn_flag=0;
|
|
int n_frames=1;
|
|
channel_desc_t *ch;
|
|
uint32_t tx_lev,tx_lev_dB;
|
|
int interf1=-19,interf2=-19;
|
|
SCM_t channel_model=AWGN;
|
|
uint32_t sdu_length_samples;
|
|
TX_VECTOR_t tx_vector;
|
|
int errors=0,misdetected_errors=0,signal_errors=0;
|
|
int symbols=0;
|
|
int tx_offset = 0,rx_offset;
|
|
RX_VECTOR_t *rxv;
|
|
uint8_t *data_ind,*data_ind_rx;
|
|
int no_detection=1;
|
|
int missed_packets=0;
|
|
uint8_t rxp;
|
|
int off,off2;
|
|
double txg,txg_dB;
|
|
int log2_maxh;
|
|
double snr_array[100];
|
|
int errors_array[100];
|
|
int trials_array[100];
|
|
int misdetected_errors_array[100];
|
|
int signal_errors_array[100];
|
|
int missed_packets_array[100];
|
|
int cnt=0;
|
|
char fname[100],vname[100];
|
|
int stop=0;
|
|
|
|
data_ind = (uint8_t*)malloc(4095+2+1);
|
|
data_ind_rx = (uint8_t*)malloc(4095+2+1);
|
|
|
|
tx_vector.rate=1;
|
|
tx_vector.sdu_length=256;
|
|
tx_vector.service=0;
|
|
|
|
logInit();
|
|
|
|
randominit(0);
|
|
set_taus_seed(0);
|
|
|
|
// Basic initializations
|
|
init_fft(64,6,rev64);
|
|
init_interleavers();
|
|
ccodedot11_init();
|
|
ccodedot11_init_inv();
|
|
phy_generate_viterbi_tables();
|
|
|
|
init_crc32();
|
|
|
|
data_ind[0] = 0;
|
|
data_ind[1] = 0;
|
|
|
|
tx_offset = taus()%(FRAME_LENGTH_SAMPLES_MAX/2);
|
|
|
|
while ((c = getopt (argc, argv, "hag:n:s:S:z:r:p:d:")) != -1) {
|
|
switch (c) {
|
|
case 'a':
|
|
printf("Running AWGN simulation\n");
|
|
awgn_flag = 1;
|
|
ntrials=1;
|
|
break;
|
|
case 'g':
|
|
switch((char)*optarg) {
|
|
case 'A':
|
|
channel_model=SCM_A;
|
|
break;
|
|
case 'B':
|
|
channel_model=SCM_B;
|
|
break;
|
|
case 'C':
|
|
channel_model=SCM_C;
|
|
break;
|
|
case 'D':
|
|
channel_model=SCM_D;
|
|
break;
|
|
case 'E':
|
|
channel_model=EPA;
|
|
break;
|
|
case 'F':
|
|
channel_model=EVA;
|
|
break;
|
|
case 'G':
|
|
channel_model=ETU;
|
|
break;
|
|
case 'H':
|
|
channel_model=Rayleigh8;
|
|
case 'I':
|
|
channel_model=Rayleigh1;
|
|
case 'J':
|
|
channel_model=Rayleigh1_corr;
|
|
case 'K':
|
|
channel_model=Rayleigh1_anticorr;
|
|
case 'L':
|
|
channel_model=Rice8;
|
|
case 'M':
|
|
channel_model=Rice1;
|
|
break;
|
|
default:
|
|
printf("Unsupported channel model!\n");
|
|
exit(-1);
|
|
}
|
|
break;
|
|
case 'd':
|
|
tx_offset = atoi(optarg);
|
|
break;
|
|
case 'p':
|
|
tx_vector.sdu_length = atoi(optarg);
|
|
if (atoi(optarg)>4095) {
|
|
printf("Illegal sdu_length %d\n",tx_vector.sdu_length);
|
|
exit(-1);
|
|
}
|
|
break;
|
|
case 'r':
|
|
tx_vector.rate = atoi(optarg);
|
|
if (atoi(optarg)>7) {
|
|
printf("Illegal rate %d\n",tx_vector.rate);
|
|
exit(-1);
|
|
}
|
|
break;
|
|
case 'n':
|
|
n_frames = atoi(optarg);
|
|
break;
|
|
case 's':
|
|
snr0 = atof(optarg);
|
|
printf("Setting SNR0 to %f\n",snr0);
|
|
break;
|
|
case 'S':
|
|
snr1 = atof(optarg);
|
|
snr1set=1;
|
|
printf("Setting SNR1 to %f\n",snr1);
|
|
break;
|
|
case 'z':
|
|
n_rx=atoi(optarg);
|
|
if ((n_rx==0) || (n_rx>2)) {
|
|
printf("Unsupported number of rx antennas %d\n",n_rx);
|
|
exit(-1);
|
|
}
|
|
break;
|
|
default:
|
|
case 'h':
|
|
printf("%s -h(elp) -a(wgn on) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -r Ricean_FactordB -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n",argv[0]);
|
|
printf("-h This message\n");
|
|
printf("-a Use AWGN channel and not multipath\n");
|
|
printf("-n Number of frames to simulate\n");
|
|
printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB. If n_frames is 1 then just SNR is simulated\n");
|
|
printf("-S Ending SNR, runs from SNR0 to SNR1\n");
|
|
printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n");
|
|
printf("-z Number of RX antennas used\n");
|
|
printf("-F Input filename (.txt format) for RX conformance testing\n");
|
|
exit (-1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (n_frames==1)
|
|
snr1 = snr0+.2;
|
|
else
|
|
snr1 = snr0+5;
|
|
for (i=0;i<tx_vector.sdu_length;i++)
|
|
data_ind[i+2] = i;//taus(); // randomize packet
|
|
data_ind[tx_vector.sdu_length+2+4]=0; // Tail byte
|
|
|
|
// compute number of OFDM symbols in DATA period
|
|
symbols = ((4+2+1+tx_vector.sdu_length)<<1) / nibbles_per_symbol[tx_vector.rate];
|
|
if ((((4+2+1+tx_vector.sdu_length)<<1) % nibbles_per_symbol[tx_vector.rate]) > 0)
|
|
symbols++;
|
|
|
|
sdu_length_samples = (symbols + 5) * 80;
|
|
|
|
printf("Number of symbols for sdu : %d, samples %d\n",symbols,sdu_length_samples);
|
|
|
|
txdata = (uint32_t*)memalign(16,sdu_length_samples*sizeof(uint32_t));
|
|
for (i=0;i<n_rx;i++) {
|
|
rxdata[i] = (uint32_t*)memalign(16,(FRAME_LENGTH_SAMPLES_MAX+1280)*sizeof(uint32_t));
|
|
bzero(rxdata[i],(FRAME_LENGTH_SAMPLES_MAX+1280)*sizeof(uint32_t));
|
|
}
|
|
s_re[0] = (double *)malloc(sdu_length_samples*sizeof(double));
|
|
bzero(s_re[0],sdu_length_samples*sizeof(double));
|
|
s_im[0] = (double *)malloc(sdu_length_samples*sizeof(double));
|
|
bzero(s_im[0],sdu_length_samples*sizeof(double));
|
|
for (i=0;i<n_rx;i++) {
|
|
r_re[i] = (double *)malloc((sdu_length_samples+100)*sizeof(double));
|
|
bzero(r_re[i],(sdu_length_samples+100)*sizeof(double));
|
|
r_im[i] = (double *)malloc((sdu_length_samples+100)*sizeof(double));
|
|
bzero(r_im[i],(sdu_length_samples+100)*sizeof(double));
|
|
}
|
|
|
|
ch = new_channel_desc_scm(1,
|
|
n_rx,
|
|
channel_model,
|
|
BW,
|
|
0.0,
|
|
0,
|
|
0);
|
|
|
|
|
|
if (ch==NULL) {
|
|
printf("Problem generating channel model. Exiting.\n");
|
|
exit(-1);
|
|
}
|
|
|
|
|
|
phy_tx_start(&tx_vector,txdata,0,FRAME_LENGTH_SAMPLES_MAX,data_ind);
|
|
|
|
tx_lev = signal_energy((int32_t*)txdata,320);
|
|
tx_lev_dB = (unsigned int) dB_fixed(tx_lev);
|
|
|
|
write_output("txsig0.m","txs", txdata,sdu_length_samples,1,1);
|
|
|
|
// multipath channel
|
|
|
|
for (i=0;i<sdu_length_samples;i++) {
|
|
s_re[0][i] = (double)(((short *)txdata)[(i<<1)]);
|
|
s_im[0][i] = (double)(((short *)txdata)[(i<<1)+1]);
|
|
}
|
|
|
|
for (SNR=snr0;SNR<snr1;SNR+=.2) {
|
|
|
|
printf("n_frames %d SNR %f sdu_length %d rate %d\n",n_frames,SNR,tx_vector.sdu_length,tx_vector.rate);
|
|
errors=0;
|
|
misdetected_errors=0;
|
|
signal_errors=0;
|
|
missed_packets=0;
|
|
stop=0;
|
|
for (trial=0; trial<n_frames; trial++) {
|
|
// printf("Trial %d (errors %d), sdu_length_samples %d\n",trial,errors,sdu_length_samples);
|
|
sigma2_dB = 25; //10*log10((double)tx_lev) - SNR;
|
|
txg_dB = 10*log10((double)tx_lev) - (SNR + sigma2_dB);
|
|
txg = pow(10.0,-.05*txg_dB);
|
|
if (n_frames==1)
|
|
printf("sigma2_dB %f (SNR %f dB) tx_lev_dB %f, txg %f\n",sigma2_dB,SNR,10*log10((double)tx_lev)-txg_dB,txg_dB);
|
|
//AWGN
|
|
sigma2 = pow(10,sigma2_dB/10);
|
|
// printf("Sigma2 %f (sigma2_dB %f)\n",sigma2,sigma2_dB);
|
|
|
|
// sigma2 = 0;
|
|
|
|
multipath_channel(ch,s_re,s_im,r_re,r_im,
|
|
sdu_length_samples,0);
|
|
|
|
if (n_frames==1) {
|
|
printf("rx_level data symbol %f, tx_lev %f\n",
|
|
10*log10(signal_energy_fp(r_re,r_im,1,80,0)),
|
|
10*log10(tx_lev));
|
|
}
|
|
|
|
for (aa=0;aa<n_rx;aa++) {
|
|
for (i=0; i<(sdu_length_samples+100); i++) {
|
|
|
|
|
|
((short*)&rxdata[aa][tx_offset])[(i<<1)] = (short) (((txg*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
|
|
((short*)&rxdata[aa][tx_offset])[1+(i<<1)] = (short) (((txg*r_im[aa][i]) + (iqim*r_re[aa][i]*txg) + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
|
|
|
|
// if (i<128)
|
|
// printf("i%d : rxdata %d, txdata %d\n",i,((short *)rxdata[aa])[rx_offset+(i<<1)],((short *)txdata)[i<<1]);
|
|
}
|
|
|
|
for (i=0;i<tx_offset;i++) {
|
|
((short*) rxdata[aa])[(i<<1)] = (short) (sqrt(sigma2/2)*gaussdouble(0.0,1.0));
|
|
((short*) rxdata[aa])[1+(i<<1)] = (short) (sqrt(sigma2/2)*gaussdouble(0.0,1.0));
|
|
}
|
|
for (i=(tx_offset+sdu_length_samples+100);i<FRAME_LENGTH_SAMPLES_MAX;i++) {
|
|
((short*) rxdata[aa])[(i<<1)] = (short) (sqrt(sigma2/2)*gaussdouble(0.0,1.0));
|
|
((short*) rxdata[aa])[1+(i<<1)] = (short) (sqrt(sigma2/2)*gaussdouble(0.0,1.0));
|
|
}
|
|
|
|
}
|
|
if (n_frames==1) {
|
|
write_output("rxsig0.m","rxs", &rxdata[0][0],FRAME_LENGTH_SAMPLES_MAX,1,1);
|
|
}
|
|
no_detection=1;
|
|
off = 0;
|
|
while(off<FRAME_LENGTH_SAMPLES_MAX) {
|
|
|
|
rxp = dB_fixed(signal_energy(rxdata[0]+off,512));
|
|
if (n_frames==1)
|
|
printf("off %d: rxp %d (%d)\n",off,rxp,signal_energy(rxdata[0]+off,104));
|
|
|
|
if (rxp>RX_THRES_dB) {
|
|
if (off<105)
|
|
off2 = FRAME_LENGTH_SAMPLES_MAX-105;
|
|
else
|
|
off2=off;
|
|
if ((initial_sync(&rxv,&rx_offset,&log2_maxh,(uint32_t*)rxdata[0],FRAME_LENGTH_SAMPLES_MAX,off2,1) == BUSY)) {
|
|
if (n_frames==1)
|
|
printf("Channel is busy, rxv %p, offset %d\n",(void*)rxv,rx_offset);
|
|
no_detection=0;
|
|
if (rxv) {
|
|
if (n_frames==1)
|
|
printf("Rate %d, SDU_LENGTH %d\n",rxv->rate,rxv->sdu_length);
|
|
if ( (rxv->rate != tx_vector.rate)||(rxv->sdu_length != tx_vector.sdu_length)) {
|
|
signal_errors++;
|
|
if ((signal_errors > (n_frames/10)) && (trial>=100)) {
|
|
stop=1;
|
|
}
|
|
if (n_frames == 1)
|
|
printf("SIGNAL error: rx_offset %d, tx_offset %d (off2 %d)\n",rx_offset,tx_offset,off2);
|
|
break;
|
|
}
|
|
else {
|
|
memset(data_ind_rx,0,rxv->sdu_length+4+2+1);
|
|
if (data_detection(rxv,data_ind_rx,(uint32_t*)rxdata[0],FRAME_LENGTH_SAMPLES_MAX,rx_offset,log2_maxh,NULL)) {
|
|
for (i=0;i<rxv->sdu_length+6;i++) {
|
|
if (data_ind[i]!=data_ind_rx[i]) {
|
|
//printf("error position %d : %x,%x\n",i,data_ind[i],data_ind_rx[i]);
|
|
misdetected_errors++;
|
|
errors++;
|
|
}
|
|
}
|
|
if ((errors > (n_frames/10)) && (trial>100)) {
|
|
stop=1;
|
|
break;
|
|
}
|
|
} // initial_synch returns IDLE
|
|
else {
|
|
errors++;
|
|
if (n_frames == 1) {
|
|
printf("Running data_detection fails\n");
|
|
|
|
for (i=0;i<rxv->sdu_length+6;i++) {
|
|
if (data_ind[i]!=data_ind_rx[i]) {
|
|
printf("error position %d : %x,%x\n",i,data_ind[i],data_ind_rx[i]);
|
|
}
|
|
}
|
|
}
|
|
if ((errors > (n_frames/10)) && (trial>=100)) {
|
|
stop=1;
|
|
break;
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
off+=105;
|
|
}
|
|
if (no_detection==1)
|
|
missed_packets++;
|
|
if (stop==1)
|
|
break;
|
|
}
|
|
|
|
printf("\nSNR %f dB: errors %d/%d, misdetected errors %d/%d,signal_errors %d/%d, missed_packets %d/%d\n",SNR,errors,trial-signal_errors,misdetected_errors,trial-signal_errors,signal_errors,trial,missed_packets,trial);
|
|
snr_array[cnt] = SNR;
|
|
errors_array[cnt] = errors;
|
|
trials_array[cnt] = trial;
|
|
misdetected_errors_array[cnt] = misdetected_errors;
|
|
signal_errors_array[cnt] = signal_errors;
|
|
missed_packets_array[cnt] = missed_packets;
|
|
cnt++;
|
|
if (cnt>99) {
|
|
printf("too many SNR points, exiting ...\n");
|
|
break;
|
|
}
|
|
if (errors == 0)
|
|
break;
|
|
#ifdef EXECTIME
|
|
print_is_stats();
|
|
print_dd_stats();
|
|
#endif
|
|
}
|
|
|
|
|
|
sprintf(fname,"SNR_%d_%d.m",tx_vector.rate,tx_vector.sdu_length);
|
|
sprintf(vname,"SNR_%d_%d_v",tx_vector.rate,tx_vector.sdu_length);
|
|
write_output(fname,vname,snr_array,cnt,1,7);
|
|
sprintf(fname,"errors_%d_%d.m",tx_vector.rate,tx_vector.sdu_length);
|
|
sprintf(vname,"errors_%d_%d_v",tx_vector.rate,tx_vector.sdu_length);
|
|
write_output(fname,vname,errors_array,cnt,1,2);
|
|
sprintf(fname,"trials_%d_%d.m",tx_vector.rate,tx_vector.sdu_length);
|
|
sprintf(vname,"trials_%d_%d_v",tx_vector.rate,tx_vector.sdu_length);
|
|
write_output(fname,vname,trials_array,cnt,1,2);
|
|
sprintf(fname,"signal_errors_%d_%d.m",tx_vector.rate,tx_vector.sdu_length);
|
|
sprintf(vname,"signal_errors_%d_%d_v",tx_vector.rate,tx_vector.sdu_length);
|
|
write_output(fname,vname,signal_errors_array,cnt,1,2);
|
|
free(data_ind);
|
|
free(data_ind_rx);
|
|
// free_channel_desc_scm(ch);
|
|
|
|
free(txdata);
|
|
for (i=0;i<n_rx;i++) {
|
|
free(rxdata[i]);
|
|
}
|
|
|
|
free(s_re[0]);
|
|
free(s_im[0]);
|
|
|
|
for (i=0;i<n_rx;i++) {
|
|
free(r_re[i]);
|
|
free(r_im[i]);
|
|
}
|
|
|
|
return(0);
|
|
|
|
}
|