//QPSK
// 0,0 -> (-1-i)*0.707106781
// 0,1 -> (-1+i)*0.707106781
// 1,0 -> (1-i)*0.707106781
// 1,1 -> (1+i)*0.707106781
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define SIGNAL_COUNT 1000000
struct complex_1
{
double real; //실수
double img; //허수
};
double gaussian();
double uniform();
typedef struct complex_1 complex_1;
// main 함수 ----------------------------------------
int main(void)
{
int i, j; // 반복문용 변수
int error_count; // 에러체크
double ber[11]; //BER
double EbN0, noise_pow;
int* s_d_signal;
complex_1* s_a_signal;
complex_1* r_a_signal;
int* r_d_signal;
int state; // 에러확인 변수
FILE * file = fopen("output.txt", "wt");
if (file == NULL){
printf("파일 열기가 실패하였습니다.\n");
return 1;
}
for (j = 0; j< 11; j++){
EbN0 = pow(10.0, (double)j / 10.0);
noise_pow = sqrt(1.0 / (2.0*EbN0));
// seed 값을 시간 함수로 처리
srand((int)time(NULL));
// sender의 digital 신호 메모리 공간 할당
s_d_signal = (int *)calloc(SIGNAL_COUNT, sizeof(int));
// 0과 1의 디지털 신호를 랜덤으로 생성
for (i = 0; i< SIGNAL_COUNT; i++){
s_d_signal[i] = rand() % 2;
}
// sender의 analog 신호 메모리 공간 할당
s_a_signal = (complex_1 *)calloc(SIGNAL_COUNT / 2, sizeof(complex_1));
// [0,0 -> -1-i] [0,1 -> -1+i] [1,0 -> 1-i] [1,1 -> 1+i] mapping
for (i = 0; i< SIGNAL_COUNT; i = i + 2){
if ((s_d_signal[i] == 0) && (s_d_signal[i + 1] == 0)){
if (i != 0){
s_a_signal[i / 2].real = -0.707106781;
s_a_signal[i / 2].img = -0.707106781;
}
else{
s_a_signal[i].real = -0.707106781;
s_a_signal[i].img = -0.707106781;
}
}
else if ((s_d_signal[i] == 0) && (s_d_signal[i + 1] == 1)){
if (i != 0){
s_a_signal[i / 2].real = -0.707106781;
s_a_signal[i / 2].img = 0.707106781;
}
else{
s_a_signal[i].real = -0.707106781;
s_a_signal[i].img = 0.707106781;
}
}
else if ((s_d_signal[i] == 1) && (s_d_signal[i + 1] == 0)){
if (i != 0){
s_a_signal[i / 2].real = 0.707106781;
s_a_signal[i / 2].img = -0.707106781;
}
else{
s_a_signal[i].real = 0.707106781;
s_a_signal[i].img = -0.707106781;
}
}
else{
if (i != 0){
s_a_signal[i / 2].real = 0.707106781;
s_a_signal[i / 2].img = 0.707106781;
}
else{
s_a_signal[i].real = 0.707106781;
s_a_signal[i].img = 0.707106781;
}
}
}
// receiver의 analog 신호 메모리 공간 할당
r_a_signal = (complex_1 *)calloc(SIGNAL_COUNT / 2, sizeof(complex_1));
// 가우시안 통과
for (i = 0; i< SIGNAL_COUNT / 2; i++){
r_a_signal[i].real = s_a_signal[i].real + (gaussian()*noise_pow);
r_a_signal[i].img = s_a_signal[i].img + (gaussian()*noise_pow);
}
// receiver의 digital 신호 메모리 공간 할당
r_d_signal = (int *)calloc(SIGNAL_COUNT, sizeof(int));
// digital 신호 결정
for (i = 0; i< SIGNAL_COUNT / 2; i++){
if (r_a_signal[i].real > 0){
r_d_signal[i * 2] = 1;
}
else{
r_d_signal[i * 2] = 0;
}
if (r_a_signal[i].img > 0){
r_d_signal[i * 2 + 1] = 1;
}
else{
r_d_signal[i * 2 + 1] = 0;
}
}
// BER 측정
error_count = 0;
for (i = 0; i< SIGNAL_COUNT; i++){
if (s_d_signal[i] != r_d_signal[i]){
error_count++;
}
}
ber[j] = (double)error_count / SIGNAL_COUNT;
// printf("BER : %f",ber);
}
for (i = 0; i< 11; i++){
if (i != 10){
fprintf(file, "%f ", ber[i]);
}
else{
fprintf(file, "%f", ber[i]);
}
}
state = fclose(file);
if (state != 0){
printf("파일 닫기가 실패하였습니다.\n");
return 1;
}
free(s_d_signal);
free(s_a_signal);
free(r_a_signal);
free(r_d_signal);
return 0;
}
// gaussian 함수 ----------------------------------------
double gaussian()
{
static int ready = 0;
static double gstore;
double v1, v2, r, fac, gaus;
double uniform();
if (ready == 0)
{
do {
v1 = 2.*uniform();
v2 = 2.*uniform();
r = v1*v1 + v2*v2;
} while (r > 1.0);
fac = sqrt(-2.*log(r) / r);
gstore = v1*fac;
gaus = v2*fac;
ready = 1;
}
else
{
ready = 0;
gaus = gstore;
}
return(gaus);
}
// uniform 함수 ----------------------------------------
double uniform()
{
return((double)(rand() & RAND_MAX) / RAND_MAX - 0.5);
}