📄 channel_est.c
字号:
//channel_est.c
//
// Project Red 2002: High Performance OFDM Modem
// Against Channel Imperfections
// Auther: Linus Falk
#include "complex_math.h"
#include <mathf.h>
#include "sync.h"
#include "ofdm.h"
#pragma DATA_SECTION (mod_training_bits, ".sysmem");
static float mod_training_bits[32];
const char position[16] = {3,11,19,27,35,43,51,59,67,75,83,91,99,107,115,123};
#pragma DATA_SECTION (received_training_symbols, ".sysmem");
float received_training_symbols[32];
#pragma DATA_SECTION (H, ".sysmem");
float H[254];
#pragma DATA_SECTION (H_abs_sqr, ".sysmem");
float H_abs_sqr[127];
#pragma DATA_SECTION (H_mean, ".sysmem");
float H_mean[254];
#pragma DATA_SECTION (H_mean_abs_sqr, ".sysmem");
float H_mean_abs_sqr[127];
#pragma DATA_SECTION (cosV, ".sysmem");
static float cosV[256];
#pragma DATA_SECTION (sinV, ".sysmem");
static float sinV[256];
short first_time = 1;
#pragma DATA_SECTION (noise_var_V, ".sysmem");
float noise_var_V[16]={0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
#pragma DATA_SECTION (noise_var, ".sysmem");
float noise_var = 0;
#pragma DATA_SECTION (snr, ".sysmem");
float snr;
#pragma DATA_SECTION (snr_int, ".sysmem");
int snr_int;
void scale(float *complex_frame);
void init_channel_est(void);
void interpolateFilter(float filter[254]);
void create_mean(void);
void calc_noise_var(void);
void calculate_snr(float *complex_frame);
void calculate_channel_abs_sqr(void);
void calc_noise(void);
//#pragma CODE_SECTION(channel_est,"SBSRAM_PROG_MEM");
void channel_est(float *complex_frame){
int j=0;
int index=0;
static int do_what = 1;
#pragma MUST_ITERATE(16,16);
for(j=0; j<16; j++){
index = position[j]*2;
H[index] = complex_frame[index];
H[index+1] = complex_frame[index+1];
received_training_symbols[j*2] = complex_frame[index];
received_training_symbols[j*2+1] = complex_frame[index+1];
complex_division(H +index, mod_training_bits +j*2);
}
create_mean();
interpolateFilter(H);
scale(complex_frame);
interpolateFilter(H_mean);
calc_noise_var();
switch(do_what){ //do not need to do everything every time
case 1:
calculate_channel_abs_sqr();
break;
case 2:
calculate_snr(complex_frame);
break;
default :
do_what = 0;
break;
}
do_what++;
}
#pragma CODE_SECTION(init_channel_est,"SBSRAM_PROG_MEM");
void init_channel_est(void){
const unsigned char training[] = {1,0,3,1,2,2,3,2,0,1,1,1,1,3,1,3};
int i;
float tal;
tal = 9.0;
#pragma MUST_ITERATE(254,254);
for(i=0; i<254; i++){
H[i] = 0;
H_mean[i] = 0;
}
#pragma MUST_ITERATE(16,16);
for(i=0; i<16; i++){
switch ((int)training[i]){
case 0:
mod_training_bits[i*2] = -tal;
mod_training_bits[i*2+1] = -tal;
break;
case 1:
mod_training_bits[i*2] = tal;
mod_training_bits[i*2+1] = -tal;
break;
case 2:
mod_training_bits[i*2] = -tal;
mod_training_bits[i*2+1] = tal;
break;
case 3:
mod_training_bits[i*2] = tal;
mod_training_bits[i*2+1] = tal;
break;
default:
break;
}
}
#pragma MUST_ITERATE(256,256);
for(i=0; i<256; i++){
cosV[i] = cosf(2*PI*i*0.00390625);
sinV[i] = sinf(2*PI*i*0.00390625);
}
}
//#pragma CODE_SECTION(interpolateFilter,"SBSRAM_PROG_MEM");
void interpolateFilter(float filter[254]){
int i,j;
float Re_step;
float Im_step;
filter[0] = filter[6];
filter[1] = filter[7];
filter[2] = filter[6];
filter[3] = filter[7];
filter[4] = filter[6];
filter[5] = filter[7];
#pragma MUST_ITERATE(15,15);
for(i=0; i<15; i++){
Re_step = (filter[position[i+1]*2] - filter[position[i]*2])*0.125;
Im_step = (filter[position[i+1]*2+1] - filter[position[i]*2+1])*0.125;
#pragma MUST_ITERATE(7,7);
for(j=1; j<8; j++){
filter[(position[i]+j)*2] = filter[position[i]*2] + j*Re_step;
filter[(position[i]+j)*2+1] = filter[position[i]*2+1] + j*Im_step;
}
}
filter[248] = filter[246];
filter[249] = filter[247];
filter[250] = filter[246];
filter[251] = filter[247];
filter[252] = filter[246];
filter[253] = filter[247];
}
//#pragma CODE_SECTION(scale,"SBSRAM_PROG_MEM");
void scale(float *complex_frame){
int i;
#pragma MUST_ITERATE(127,127);
for(i=0; i<127; i++){ //complex division
complex_division(complex_frame +2*i, H +2*i);
}
}
//#pragma CODE_SECTION(create_mean,"SBSRAM_PROG_MEM");
void create_mean(void){
int j=0;
int index=0;
float phase_coef[2];
int arg;
if(first_time == 1){ //first time
first_time = 0;
#pragma MUST_ITERATE(16,16);
for(j=0; j<16; j++){
index = position[j]*2; //position in H_mean an H
H_mean[index] = H[index]; //copy
H_mean[index+1] = H[index+1];
calculate_channel_abs_sqr();
}
}else{ //not first time
#pragma MUST_ITERATE(16,16);
for(j=0; j<16; j++){
index = position[j]*2; //position in H_mean an H
arg = (sync_diff*(position[j]+1))%256; //cos and sin arg
if(arg < 0){
arg = 256 + arg;
}
phase_coef[0] = cosV[arg]; //calculate phase coef
phase_coef[1] = sinV[arg];
//phase_coef[0] = cosf(2*PI*sync_diff*(position[j]+1)*0.00390625);
//phase_coef[1] = sinf(2*PI*sync_diff*(position[j]+1)*0.00390625);
complex_multiplication(H_mean+index, phase_coef); //shift phase
H_mean[index] = H_mean[index]*0.9 + H[index]*0.1; //calculate mean
H_mean[index+1] = H_mean[index+1]*0.9 + H[index+1]*0.1;
}
}
}
#pragma CODE_SECTION(calc_noise_var,"SBSRAM_PROG_MEM");
void calc_noise_var(void){
int i;
float symbol_est[2];
float diff[2];
float abs_sqr;
#pragma MUST_ITERATE(16,16);
for(i=0; i<16; i++){
symbol_est[0] = mod_training_bits[i*2];
symbol_est[1] = mod_training_bits[i*2+1];
complex_multiplication(symbol_est, H_mean + position[i]*2);
diff[0] = received_training_symbols[i*2] - symbol_est[0];
diff[1] = received_training_symbols[i*2+1] - symbol_est[1];
complex_abs_sqr(diff,&abs_sqr);
noise_var_V[i] = abs_sqr;
}
calc_noise();
}
//#pragma CODE_SECTION(calc_noise,"SBSRAM_PROG_MEM");
void calc_noise(void){
int i;
float new_noise = 0;
for(i=0; i<16; i++){
new_noise += noise_var_V[i];
}
new_noise *= 0.065; //mean
if(noise_var == 0){
noise_var = new_noise;
}else{
noise_var = noise_var*0.9+new_noise*0.1;
}
}
//#pragma CODE_SECTION(calculate_snr,"SBSRAM_PROG_MEM");
void calculate_snr(float *complex_frame){
int i;
snr = 0;
#pragma MUST_ITERATE(127,127);
for(i=0; i<127; i++){
snr += (complex_frame[i*2]*complex_frame[i*2] + complex_frame[i*2+1]*complex_frame[i*2+1])*0.007874;
}
snr *= _rcpsp(noise_var);
snr_int = (int)(snr*1000);
}
//#pragma CODE_SECTION(calculate_channel_abs_sqr,"SBSRAM_PROG_MEM");
void calculate_channel_abs_sqr(void){
int i;
#pragma MUST_ITERATE(127,127);
for(i=0; i<127; i++){
H_abs_sqr[i] = H[i*2]*H[i*2] + H[i*2+1]*H[i*2+1];
H_mean_abs_sqr[i] = H_mean[i*2]*H_mean[i*2] + H_mean[i*2+1]*H_mean[i*2+1];
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -