본문 바로가기

C언어

QPSK

//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);
}

'C언어' 카테고리의 다른 글

2의 보수를 이용한 부호 바꾸기  (0) 2014.09.26
컨볼루션 인코더 & 비터비 디코더 ver 0.5  (0) 2014.09.04
BPSK  (0) 2014.09.03
매크로(macro) #define  (0) 2014.08.21
리눅스 gcc 사용 방법(컴파일러)  (0) 2014.08.04