I tried to implement C code for Wavelet transform in FPGA (Zynq ZC 702) but the code get stuck and this is because of memory problem so I should optimize my code but I don't know how.
Can anyone please give me some ideas how to do that ?
This is the main of the code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "wavemin.h"
#include "waveaux.h"
#include "waveaux.c"
#include "wavemin.c"
int main() {
printf("Hello World1 \n\r");
wave_object obj;
wt_object wt;
float *inp, *out;
int N, i, J,k;
float temp[1280] = {};
char *name = "db4";
obj = wave_init(name);
printf("Hello World2 \n\r");
N = 1280;
inp = (float*)malloc(sizeof(float) * N);
out = (float*)malloc(sizeof(float) * N);
//wmean = mean(temp, N);
for (i = 0; i < N; ++i) {
inp[i] = temp[i];
printf("Hello World3 \n\r");
//printf("%g \n", inp[i]);
}
J = 4; //Decomposition Levels
wt = wt_init(obj, "dwt", N, J); // Initialize the wavelet transform object
printf("Hello World4 \n\r");
setDWTExtension(wt, "sym"); // Options are "per" and "sym". Symmetric is the default option
printf("Hello World5 \n\r");
setWTConv(wt, "direct");
printf("Hello World6 \n\r");
dwt(wt, inp); // Perform DWT
printf("Hello World7 \n\r");
//getDWTAppx(wt, out, wt->length[0]);
// printf("Approximation Coefficients Level 1 \n");
// for (i = 0; i < wt->length[0]; ++i) {
// printf("%g ", out[i]);
// }
// printf("\n\n");
for (k = 1; k <= J; ++k) {
getDWTDetail(wt, out, wt->length[k], k);
printf("Detail Coefficients Level %d Length %d \n",
k, wt - length[k]);
for (i = 0; i < wt->length[k]; ++i) {
printf("%g ", out[i]);
}
printf("\n\n");
}
wt_summary(wt);// Prints the full summary.
printf("Hello World8 \n\r");
wave_free(obj);
wt_free(wt);
free(inp);
free(out);
return 0;
}
The other part of the code where there is the function used in the main function:
#include "wavemin.h"
wave_object wave_init(char *wname) {
wave_object obj = NULL;
int retval;
retval = 0;
if (wname != NULL) {
retval = filtlength(wname);
}
obj = (wave_object)malloc(sizeof(struct wave_set) + sizeof(float) * 4 *
retval);
obj->filtlength = retval;
obj->lpd_len = obj->hpd_len = obj->lpr_len = obj->hpr_len = obj->filtlength;
strcpy(obj->wname, wname);
if (wname != NULL) {
filtcoef(wname, obj->params, obj->params + retval, obj->params + 2 *
retval, obj->params + 3 * retval);
}
obj->lpd = &obj->params[0];
obj->hpd = &obj->params[retval];
obj->lpr = &obj->params[2 * retval];
obj->hpr = &obj->params[3 * retval];
return obj;
}
wt_object wt_init(wave_object wave, char *method, int siglength, int J) {
int size, i, MaxIter;
wt_object obj = NULL;
size = wave->filtlength;
MaxIter = wmaxiter(siglength, size);
if (!strcmp(method, "dwt") || !strcmp(method, "DWT")) {
obj = (wt_object)malloc(sizeof(struct wt_set) + sizeof(float) *
(siglength + 2 * J * (size + 1)));
obj->outlength = siglength + 2 * J * (size + 1); // Default
strcpy(obj->ext, "sym"); // Default
}
obj->wave = wave;
obj->siglength = siglength;
obj->J = J;
obj->MaxIter = MaxIter;
strcpy(obj->method, method);
if (siglength % 2 == 0) {
obj->even = 1;
}
else {
obj->even = 0;
}
strcpy(obj->cmethod, "direct"); // Default
obj->cfftset = 0;
obj->lenlength = J + 2;
obj->output = &obj->params[0];
if (!strcmp(method, "dwt") || !strcmp(method, "DWT")) {
for (i = 0; i < siglength + 2 * J * (size + 1); ++i) {
obj->params[i] = 0.0;
}
}
//wave_summary(obj->wave);
return obj;
}
static void dwt_sym(wt_object wt, float *inp, int N, float *cA, int len_cA,
float *cD, int len_cD) {
int i, l, t, len_avg;
len_avg = wt->wave->lpd_len;
for (i = 0; i < len_cA; ++i) {
t = 2 * i + 1;
cA[i] = 0.0;
cD[i] = 0.0;
for (l = 0; l < len_avg; ++l) {
if ((t - l) >= 0 && (t - l) < N) {
cA[i] += wt->wave->lpd[l] * inp[t - l];
cD[i] += wt->wave->hpd[l] * inp[t - l];
printf("world1 \n\r");
}
else if ((t - l) < 0) {
cA[i] += wt->wave->lpd[l] * inp[-t + l - 1];
cD[i] += wt->wave->hpd[l] * inp[-t + l - 1];
printf("world2 \n\r");
}
else if ((t - l) >= N) {
cA[i] += wt->wave->lpd[l] * inp[2 * N - t + l - 1];
cD[i] += wt->wave->hpd[l] * inp[2 * N - t + l - 1];
printf("world3 \n\r");
}
}
}
}
void dwt(wt_object wt, float *inp) {
int i, J, temp_len, iter, N, lp;
int len_cA;
float *orig, *orig2;
temp_len = wt->siglength;
J = wt->J;
wt->length[J + 1] = temp_len;
wt->outlength = 0;
wt->zpad = 0;
orig = (float*)malloc(sizeof(float) * temp_len);
orig2 = (float*)malloc(sizeof(float) * temp_len);
for (i = 0; i < wt->siglength; ++i) {
orig[i] = inp[i];
printf("Hello1 \n\r");
}
if (wt->zpad == 1) {
orig[temp_len - 1] = orig[temp_len - 2];
printf("Hello2 \n\r");
}
N = temp_len;
lp = wt->wave->lpd_len;
if (!strcmp(wt->ext, "sym")) {
//printf("\n YES %s \n", wt->ext);
i = J;
while (i > 0) {
N = N + lp - 2;
N = (int)ceil((float)N / 2.0);
wt->length[i] = N;
wt->outlength += wt->length[i];
i--;
}
wt->length[0] = wt->length[1];
wt->outlength += wt->length[0];
N = wt->outlength;
printf("Hello3 \n\r");
for (iter = 0; iter < J; ++iter) {
len_cA = wt->length[J - iter];
N -= len_cA;
dwt_sym(wt, orig, temp_len, orig2, len_cA, wt->params + N, len_cA);
temp_len = wt->length[J - iter];
printf("Hello4 \n\r");
if (iter == J - 1) {
for (i = 0; i < len_cA; ++i) {
wt->params[i] = orig2[i];
printf("Hello5 \n\r");
}
} else {
for (i = 0; i < len_cA; ++i) {
orig[i] = orig2[i];
printf("Hello6 \n\r");
}
}
}
} else {
printf("Signal extension can be either per or sym");
exit(-1);
}
free(orig);
free(orig2);
}
void setDWTExtension(wt_object wt, char *extension) {
if (!strcmp(extension, "sym")) {
strcpy(wt->ext, "sym");
} else {
printf("Signal extension can be either per or sym");
exit(-1);
}
}
void setWTConv(wt_object wt, char *cmethod) {
if (!strcmp(cmethod, "direct")) {
strcpy(wt->cmethod, "direct");
}
}
void getDWTDetail(wt_object wt, float *detail, int N, int level) {
/*
returns Detail coefficents at the jth level where j = 1,2,.., J
and Wavelet decomposition is stored as
[A(J) D(J) D(J-1) ..... D(1)] in wt->output vector
Use getDWTAppx() to get A(J)
Level 1 : Length of D(J), ie N, is stored in wt->length[1]
Level 2 :Length of D(J-1), ie N, is stored in wt->length[2]
....
Level J : Length of D(1), ie N, is stored in wt->length[J]
*/
int i, iter, J;
J = wt->J;
if (level > J) {
printf("The decomposition only has %d levels", J);
}
iter = wt->length[0];
for (i = 1; i < level; ++i) {
iter += wt->length[i];
}
for (i = 0; i < N; ++i) {
detail[i] = wt->output[i + iter];
}
}
void getDWTAppx(wt_object wt, float *appx, int N) {
/*
Wavelet decomposition is stored as
[A(J) D(J) D(J-1) ..... D(1)] in wt->output vector
Length of A(J) , N = wt->length[0]
*/
int i;
for (i = 0; i < N; ++i) {
appx[i] = wt->output[i];
}
}
void wt_summary(wt_object wt) {
int i;
int J, t;
J = wt->J;
printf("Wavelet Coefficients are contained in vector : %s \n", "output");
printf("\n");
printf("Approximation Coefficients \n");
printf("Level %d Access : output[%d] Length : %d \n",
1, 0, wt->length[0]);
printf("\n");
printf("Detail Coefficients \n");
t = wt->length[0];
for (i = 0; i < J; ++i) {
printf("Level %d Access : output[%d] Length : %d \n",
i + 1, t, wt->length[i + 1]);
t += wt->length[i + 1];
}
printf("\n");
}
void wave_free(wave_object object) {
free(object);
}
void wt_free(wt_object object) {
free(object);
}
enter image description here
In your code
Always check if malloc has returned non NULL value
Check your stack and heap settings in the linker file as you declare massive local variables and do a lots of mallocs - I suspect the (nomen omen)stack overflow, or failed mallocs.
Is it a bare metal program or you run it under some kind of OS?
Just for a matter of style and concision, I would rewrite this:
if (siglength % 2 == 0) {
obj->even = 1;
}
else {
obj->even = 0;
}
Into the following code:
obj->even = !(siglength % 2);
Or, alternatively:
obj->even = (siglength % 2) ? 0 : 1;
Also, I think there is room for optimization in this function:
static void dwt_sym(wt_object wt, float *inp, int N, float *cA, int len_cA,
float *cD, int len_cD) {
int i, l, t, len_avg;
len_avg = wt->wave->lpd_len;
for (i = 0; i < len_cA; ++i) {
t = 2 * i + 1;
cA[i] = 0.0;
cD[i] = 0.0;
for (l = 0; l < len_avg; ++l) {
if ((t - l) >= 0 && (t - l) < N) {
cA[i] += wt->wave->lpd[l] * inp[t - l];
cD[i] += wt->wave->hpd[l] * inp[t - l];
printf("world1 \n\r");
}
else if ((t - l) < 0) {
cA[i] += wt->wave->lpd[l] * inp[-t + l - 1];
cD[i] += wt->wave->hpd[l] * inp[-t + l - 1];
printf("world2 \n\r");
}
else if ((t - l) >= N) {
cA[i] += wt->wave->lpd[l] * inp[2 * N - t + l - 1];
cD[i] += wt->wave->hpd[l] * inp[2 * N - t + l - 1];
printf("world3 \n\r");
}
}
}
}
First, you are always referring to t - 1 and never t itself, so why not have:
t = 2 * i;
And, I can guess that a lot of computation can be placed outside of the inner loop... If you want to optimize, there are many good candidate here.
One last word about optimization!
You should first profile your software and see where you spend the most time before thinking about optimization. You cannot optimize "in the air" without knowing where your software does really struggle. Consider using gprof.
PS: You should never ever use the letter l (ell) as a variable... it is way to close from the number 1 (one). Consider changing this is also, it can improve the reading.
I created a header file called ofdm.h which includes all the function prototypes. Then I created a source file called ofdm.c, which includes the source code of all the functions declared in ofdm.h . After that I started coding in main.c, but when I run it I get the error: undefined reference to '(function name)'. I get this error for all my functions.
Below you can find the source code of all my three files.
ofdm.h
#ifndef OFDM_H_INCLUDED
#define OFDM_H_INCLUDED
typedef struct {
double real, img;
} Complex;
char** split(char *s, const char *delim);
void parseComplex(Complex *c, char *line);
void rbits(short* buf, int nbits);
void printbinary(short* buf, int len);
void printcomplex(Complex* buf, int len);
long bin2dec(short *bin, int len);
void dec2bin(long dec, short *bin, int len);
void binaryadd(short *bin1, short *bin2, short *erg, int len);
void leftshift(short *bin,short *erg,int shifts, int len);
void binarymult(short *bin1, short *bin2, short *erg, int len);
void binarypower(short *bin,short *erg,int power, int len);
void scrambler(short *seed, short *input, short *output, int len, int seedlen);
void encoder(short *input, short *output, int inputlen);
void interleaver(short *input, short *output, int N_CBPS,int N_BPSC);
void deinterleaver(short *input, short *output, int N_CBPS,int N_BPSC);
void fixed_point(short* input, int nbits);
void fixed_point_complex(Complex* input, int nbits);
void defixed_point(short* input, int nbits);
void BPSKmapping(short* input, short* output, int nbits);
void BPSKdemapping(short* input, short* output, int nbits);
void QPSKmapping(short* input, Complex* output, int nbits);
void QPSKdemapping(Complex* input, short* output, int nbits);
void IFFT_BPSK(short* input, Complex* output, Complex* twidder);
void IFFT_QPSK(Complex* input, Complex* output, Complex* twidder);
double uniform(double a, double b);
double gauss(double mean, int SNRdb);
void ChannelModel(Complex R[], Complex S[], int SNRdb);
#endif
ofdm.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "ofdm.h"
char** split(char* string, const char* delim)
{
char* p;
int i = 0;
char** array = malloc(strlen(string) * sizeof(char*));
p = strtok(string, delim);
while(p != NULL)
{
array[i] = malloc(sizeof(char));
array[i++] = p;
p = strtok(NULL, delim);
}
return array;
}
void parseComplex(Complex *cmplx, char *number)
{
char *copy = number;
if(strchr(copy, ' ') != NULL)
{
char **result = split(copy, " ");
cmplx->real = atof(*result++);
char *sign = *result++;
cmplx->img = atof(*result++);
if(sign[0] == '-')
cmplx->img = -(cmplx->img);
}
else if(strchr(copy, 'j') != NULL)
{
cmplx->real = 0;
cmplx->img = atof(copy);
}
else
{
cmplx->real = atof(copy);
cmplx->img = 0;
}
}
void rbits(short* buf, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
buf[i] = (rand() % 2);
}
void printbinary(short* buf, int len)
{
int i;
for(i = 0; i < len; i++)
{
printf("%d\t", buf[i]);
}
printf("\n\n\n");
}
void printcomplex(Complex* buf, int len)
{
int i;
for(i = 0; i < len; i++)
{
printf("%.0lf %.0lf\t", buf[i].real, buf[i].img);
}
printf("\n\n");
}
long bin2dec(short *bin, int len)
{
long dec = 0;
int i;
for(i = 0;i < len;i++)
{
dec += bin[i]*pow(2.0,(double) (len - i -1));
}
return dec;
}
void dec2bin(long dec, short *bin, int len)
{
long temp = dec;
int i;
for(i = 0;i<len;i++)
{
bin[len - 1 - i] = temp % 2;
temp = temp/2;
}
}
void binaryadd(short *bin1, short *bin2, short *erg, int len)
{
int i;
short carry = 0;
short oldcarry = 0;
for(i = len - 1; i >= 0; i--)
{
if((bin1[i] + bin2[i] + oldcarry) > 1)
{
carry = 1;
}
else
{
carry = 0;
}
erg[i] = (bin1[i] + bin2[i] + oldcarry) % 2;
oldcarry = carry;
}
}
void leftshift(short *bin,short *erg,int shifts, int len)
{
int i;
for(i = 0;i < len - shifts;i++)
{
erg[i] = bin[i + shifts];
}
for(i = len - shifts;i < len;i++)
{
erg[i] = 0;
}
}
void binarymult(short *bin1, short *bin2, short *erg, int len)
{
int i;
short temp[len - 1];
for(i = 0;i < len;i++)
{
erg[i] = 0;
}
for(i = 0;i < len;i++)
{
if(bin2[i] == 1)
{
leftshift(bin1,temp,len - 1 - i,len);
binaryadd(temp,erg,erg,len);
}
}
}
void binarypower(short *bin,short *erg,int power, int len)
{
int i;
short temp[len - 1];
for(i = 0;i < len;i++)
{
temp[i] = 0;
}
temp[len - 1] = 1;
if(power > 1)
binarypower(bin,temp,power - 1,len);
binarymult(temp,bin,erg,len);
}
void scrambler(short *seed, short *input, short *output, int len, int seedlen)
{
int i;
short carry;
short sequence[len - 1];
for(i = 0; i < len; i++)
{
sequence[i] = (seed[0] + seed[3]) % 2;
carry = (seed[0] + seed[3]) % 2;
leftshift(seed,seed,1,seedlen);
seed[seedlen - 1] = carry;
output[i] = (sequence[i] + input[i]) % 2;
}
}
void encoder(short *input, short *output, int inputlen)
{
int i;
short SR[7] = {0,0,0,0,0,0,0};
short A;
short B;
for(i = 0; i < inputlen;i++)
{
leftshift(SR,SR,1,7);
SR[6] = input[i];
A = (SR[6] + SR[4] + SR[3] + SR[1] + SR[0]) % 2;
B = (SR[6] + SR[5] + SR[4] + SR[3] + SR[0]) % 2;
output[2*i] = A;
output[2*i + 1] = B;
}
}
/*
void decoder(short *input, short *output, int inputlen)
{
int i;
short SR[7] = {0}
short A;
short B;
short C1;
short C2;
for(i = 0; i < intputlen; i++)
{
leftshift(SR, SR, 1, 7)
SR[6] = input[i];
C1 = (SR[6] + SR[4] + SR[3] + SR[1] + SR[0]) / 2;
C2 = (SR[6] + SR[5] + SR[4] + SR[3] + SR[0]) / 2;
A = (SR[6] + SR[4] + SR[3] + SR[1] + SR[0]) - (2 * C1);
B = (SR[6] + SR[5] + SR[4] + SR[3] + SR[0]) - (2 * C2);
output[2*i] = A; // output[i/2] = A;
output[2*i + 1] = B; // output[i/2 + 1] = B;
}
}
*/
void interleaver(short *input, short *output, int N_CBPS,int N_BPSC)
{
int i;
int t;
int k;
int s;
short first_permutuation[N_CBPS - 1];
for (k = 0; k < N_CBPS; k++)
{
i = (N_CBPS/16)*(k % 16) + (k/16);
first_permutuation[i] = input[k];
}
s = fmax(N_BPSC/2,1);
for(i = 0; i < N_CBPS;i++)
{
t = s*(i/s) + (i + N_CBPS - ((16*i)/N_CBPS)) % s;
output[t] = first_permutuation[i];
}
}
void fixed_point(short* input, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
{
if(input[i] < 0)
input[i] *= 32768;
else input[i] *= 32767;
}
}
void fixed_point_complex(Complex* input, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
{
if(input[i].real == -1 || input[i].img == -1)
input[i] *= 32768;
else input[i] *= 32767;
}
}
void defixed_point(short* input, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
{
if(input[i] < 0)
input[i] /= 32768;
else input[i] /= 32767;
}
}
void IFFT_BPSK(short* input, Complex* output, Complex* twidder)
{
int i, k;
for(i = 0; i < 64; i++)
{
for(k = 0; k < 64; k++)
{
output[i].real += (twidder[i][k].real * input[i]) / 64;
output[i].img += (twidder[i][k].img * input[i]) / 64;
}
}
}
void IFFT_QPSK(Complex* input, Complex* output, Complex* twidder)
{
int i, k;
for(i = 0; i < 64; i++)
{
for(k = 0; k < 64; k++)
{
output[i].real += (twidder[i][k].real * input[i].real) / 64;
output[i].img += (twidder[i][k].img * input[i].img) / 64;
}
}
}
void IFFT_QPSK2(Complex* input, Complex* output, Complex* twidder, int nbits)
{
int a, b, c, d, e, f, g, h, blocks;
int count1 = 7, count2 = 20, count3 = 28, count4 = 41;
int next = 0;
Complex ifft_qpsk_output[64];
blocks = nbits / 48;
for(a = 1; a <= blocks; a++)
{
// pilots
output[7].real = 32767;
output[21].real = 32767;
output[42].real = 32767;
output[56].real = -32768;
// some data
output[40].real = input[26 + (next * 48)].real;
output[40].img = input[26 + (next * 48)].img;
output[41].real = input[27 + (next * 48)].real;
output[41].img = input[27 + (next * 48)].img;
// zeroes
for(b = 28; b <= 39; b++)
output[b].real = 0;
// other data
for(c = 0; c <= 6; c++)
{
output[c].real = input[c + (next * 48)].real;
output[c].img = input[c + (next * 48)].img;
}
for(d = 8; d <= 20; d++)
{
output[d].real = input[count1++ + (next * 48)].real;
output[d].img = input[count1++ + (next * 48)].img;
}
for(e = 22; e <= 27; e++)
{
output[e].real = input[count2++ + (next * 48)].real;
output[e].img = input[count2++ + (next * 48)].img;
}
for(f = 43; f <= 55; f++)
{
output[f].real = input[count3++ + (next * 48)].real;
output[f].img = input[count3++ + (next * 48)].img;
}
for(h = 57; h <= 63; h++)
{
output[h].real = input[count4++ + (next * 48)].real;
output[h].img = input[count4++ + (next * 48)].img;
}
// IFFT function goes here
IFFT_QPSK(output, ifft_qpsk_output, twidder);
printcomplex(ifft_qpsk_output, 64);
next++;
}
}
void IFFT_BPSK2(short* input, short* output, Complex* twidder, int nbits)
{
int a, b, c, d, e, f, g, h, blocks;
int count1 = 7, count2 = 20, count3 = 28, count4 = 41;
int next = 0;
Complex ifft_bpsk_output[64];
blocks = nbits / 48;
for(a = 1; a <= blocks; a++)
{
// pilots
output[7] = 32767;
output[21] = 32767;
output[42] = 32767;
output[56] = -32768;
// some data
output[40] = input[26 + (next * 48)];
output[41] = input[27 + (next * 48)];
// zeroes
for(b = 28; b <= 39; b++)
output[b] = 0;
// other data
for(c = 0; c <= 6; c++)
output[c] = input[c + (next * 48)];
for(d = 8; d <= 20; d++)
output[d] = input[count1++ + (next * 48)];
for(e = 22; e <= 27; e++)
output[e] = input[count2++ + (next * 48)];
for(f = 43; f <= 55; f++)
output[f] = input[count3++ + (next * 48)];
for(h = 57; h <= 63; h++)
output[h] = input[count4++ + (next * 48)];
// IFFT function goes here
IFFT_BPSK(output, ifft_bpsk_output, twidder);
printcomplex(ifft_bpsk_output, 64);
next++;
}
}
void BPSKmapping(short* input, short* output, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
{
if(input[i] == 0)
output[i] = -1;
else output[i] = 1;
}
}
void BPSKdemapping(short* input, short* output, int nbits)
{
int i;
for(i = 0; i < nbits; i++)
{
if(input[i] == -1)
output[i] == 0;
else output[i] == 1;
}
}
void QPSKmapping(short* input, Complex* output, int nbits)
{
int i;
for(i = 0; i < nbits; i += 2)
{
if(input[i] == 0 && input[i+1] == 0)
{
output[i].real = -1;
output[i+1].img = -1;
}
else if(input[i] == 0 && input[i+1] == 1)
{
output[i].real = -1;
output[i+1].img = 1;
}
else if(input[i] == 1 && input[i+1] == 0)
{
output[i].real = 1;
output[i+1].img = -1;
}
else
{
output[i].real = 1;
output[i+1].img = 1;
}
}
}
void QPSKdemapping(Complex* input, short* output, int nbits)
{
int i;
for(i = 0; i < nbits; i += 2)
{
if(input[i].real == -1 && input[i+1].img == -1)
{
output[i] = 0;
output[i+1] = 0;
}
else if(input[i].real == -1 && input[i+1].img == 1)
{
output[i] = 0;
output[i+1] = 1;
}
else if(input[i].real == 1 && input[i+1].img == -1)
{
output[i] = 1;
output[i+1] = 0;
}
else
{
output[i] = 1;
output[i+1] = 1;
}
}
}
//Channel Begin
double uniform(double a, double b)
{
double c;
double d;
static int firstcall = 1;
c = b - a;
if(firstcall == 1)
{
srand((unsigned int)time(NULL));
firstcall = 0;
}
d = a + (double)rand() / RAND_MAX * c;
return d;
}
double gauss(double mean, int SNRdb)
{
double dGaussNum;
double x = 0;
int i;
double sigma;
sigma = 1 / pow(10, (double)SNRdb / 10);
for(i = 0;i < 12; i ++)
{
x = x + uniform(0,1);
}
x = x - 6;
dGaussNum = mean + sqrt(sigma) * x;
return dGaussNum;
}
void ChannelModel(Complex R[], Complex S[], int SNRdb)
{
int i;
for (i=0;i<N+L;i++)
{
R[i].real = S[i].real + gauss(0, SNRdb);
R[i].img = S[i].img + gauss(0, SNRdb);
}
}
//Channel End
void deinterleaver(short *input, short *output, int N_CBPS,int N_BPSC)
{
int i;
int t;
int k;
int s;
short first_permutuation[N_CBPS - 1];
s = fmax(N_BPSC/2,1);
for (t = 0; t < N_CBPS; t++)
{
i = s*(t/s) + (t + ((16*t)/N_CBPS)) % s;
first_permutuation[i] = input[t];
}
for(i = 0; i < N_CBPS;i++)
{
k = 16*i - (N_CBPS - 1)*((16*i)/N_CBPS);
output[k] = first_permutuation[i];
}
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ofdm.h"
int main(int argc, char *argv[])
{
short seed[8];
int bits, i, j, k;
char mode[5], line[1024];
/* Complex twidder[64][64];
FILE *file = fopen("twidder_factor.txt", "r");
i = 0;
while(fgets(line, sizeof(line), file ) != NULL)
{
k = j = 0;
char **result = split(line, "\t");
while(result[k] != NULL)
{
parseComplex(&twidder[i][j], result[k++]);
j++;
}
i++;
}
*/
printf("How many bits do you want to transmit?: ");
scanf("%d", &bits);
short* start_input;
short* scrambler_output;
short* encoder_output;
short* interleaver_output;
short* bpsk_mapper_output;
short* ifft_bpsk_input[64];
Complex* qpsk_mapper_output;
Complex ifft_qpsk_input[64];
start_input = malloc(sizeof(short) * bits);
scrambler_output = malloc(sizeof(short) * bits);
encoder_output = malloc(sizeof(short) * (bits * 2));
interleaver_output = malloc(sizeof(short) * (bits * 2));
bpsk_mapper_output = malloc(sizeof(short) * (bits * 2));
qpsk_mapper_output = malloc(sizeof(Complex) * (bits * 2));
if(qpsk_mapper_output == NULL)
{
fprintf(stderr, "Couldn't allocate that much memory!\n");
return 1;
}
srand(time(NULL));
rbits(seed, 8);
rbits(start_input, bits);
printf("Which modulation type to you want to use? (type BPSK or QPSK): ");
scanf("%s", mode);
if((strcmp(mode, "BPSK") == 0) || (strcmp(mode, "bpsk") == 0))
{
printf("\nSelected modulation type: BPSK\n\n\n");
printf("SCRAMBLER OUTPUT:\n\n");
scrambler(seed, start_input, scrambler_output, bits, 8);
printbinary(scrambler_output, bits);
printf("ENCODER OUTPUT:\n\n");
encoder(scrambler_output, encoder_output, bits);
printbinary(encoder_output, bits*2);
printf("INTERLEAVER OUTPUT:\n\n");
interleaver(encoder_output, interleaver_output, bits, 1);
printbinary(interleaver_output, bits*2);
printf("MAPPER OUTPUT:\n\n");
BPSKmapping(interleaver_output, bpsk_mapper_output, bits*2);
printbinary(bpsk_mapper_output, bits*2);
printf("FIXED-POINT OUTPUT:\n\n");
fixed_point(bpsk_mapper_output, bits*2);
printbinary(bpsk_mapper_output, bits*2);
/*
printf("IFFT OUTPUT:\n\n");
IFFT_BPSK(bpsk_mapper_output, ifft_bpsk_input, twidder, bits*2)
defixed_point(bpsk_mapper_output, bits*2);
printbinary(bpsk_mapper_output, bits*2);
*/ }
else if((strcmp(mode, "QPSK") == 0) || (strcmp(mode, "qpsk") == 0))
{
printf("\nSelected modulation type: QPSK\n\n\n");
printf("SCRAMBLER OUTPUT:\n\n");
scrambler(seed, start_input, scrambler_output, bits, 8);
printbinary(scrambler_output, bits);
printf("ENCODER OUTPUT:\n\n");
encoder(scrambler_output, encoder_output, bits);
printbinary(encoder_output, bits*2);
printf("INTERLEAVER OUTPUT:\n\n");
interleaver(encoder_output, interleaver_output, bits, 2);
printbinary(interleaver_output, bits*2);
printf("MAPPER OUTPUT:\n\n");
QPSKmapping(interleaver_output, qpsk_mapper_output, bits*2);
printcomplex(qpsk_mapper_output, bits*2);
/*
printf("FIXED-POINT OUTPUT:\n\n");
fixed_point_complex(qpsk_mapper_output, bits*2);
printcomplex(qpsk_mapper_output, bits*2);
printf("IFFT OUTPUT:\n\n");
IFFT_QPSK(qpsk_mapper_output, ifft_qpsk_input, twidder, bits*2)
defixed_point(qpsk_mapper_output, bits*2);
printbinary(qpsk_mapper_output, bits*2);
*/ }
else
{
printf("That's an invalid modulation type!\n");
free(start_input);
free(scrambler_output);
free(encoder_output);
free(interleaver_output);
free(bpsk_mapper_output);
free(qpsk_mapper_output);
return 0;
}
free(start_input);
free(scrambler_output);
free(encoder_output);
free(interleaver_output);
free(bpsk_mapper_output);
free(qpsk_mapper_output);
system("PAUSE");
return 0;
}
If you could help me to solve this problem I would be glad. I think there is some kind of linking problem between my library and the main source file.
Thanks in advance.
I guess you are compiling only main.c. You should also include ofdm.c.
$ gcc -Wall main.c ofdm.c -o output
Since you get this error for all your functions, it can't be a typo. My best guess is that you are not linking the two files.
If using gcc, this is done in the following way:
gcc -o main.o -c main.c
gcc -o ofdm.o -c ofdm.c
gcc -o program main.o ofdm.o
Note that -c means it should compile, but not try to create an executable. This means that linking is not done.
Once both files are compiled, you would then link them together.
When you're learning new things, it helps to learn one new thing at a time. Put your source code into version control, then simplify it to get a clean compile.
main.c
#include "ofdm.h"
int main(int argc, char *argv[])
{
return 0;
}
ofdm.c
#include "ofdm.h"
void leftshift(short *bin,short *erg,int shifts, int len)
{
int i;
for(i = 0;i < len - shifts;i++)
{
erg[i] = bin[i + shifts];
}
for(i = len - shifts;i < len;i++)
{
erg[i] = 0;
}
}
ofdm.h
#ifndef OFDM_H_INCLUDED
#define OFDM_H_INCLUDED
void leftshift(short *bin,short *erg,int shifts, int len);
#endif
Then, to compile with gcc . . .
$ gcc -Wall -c ofdm.c
$ gcc -Wall -c main.c
$ gcc -Wall *.o
That should give you a program that does nothing, successfully. Now you can start to build it up again from your version-controlled source.
Add one function at a time.
Edit it to get a clean compile.
Edit it to pass sane tests.
I came here with the same issue while using ESP-IDF as a beginner. What solved this for me was that I just forgot to add all the necessary sources in the idf_component_register function call.