3

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.

5
  • Can you give us the specific error you're getting? Commented Mar 31, 2012 at 17:30
  • What command do you use when compiling the files? Commented Mar 31, 2012 at 17:33
  • Maybe the linker does not find the file? do you get a linker error? What compiler do you use? Commented Mar 31, 2012 at 17:35
  • Note that c makes a distinction between "declared" (which your header does) and "defined" which happens ofdm.c. That's a clue that could have put you on the right track (and hopefully will next time). The existing answer show you how to fix the linking issue that you are having. Commented Mar 31, 2012 at 17:40
  • The error that I get is as I have written: undefined reference to '(function name)', simply function name is the name of a function. I'm using CodeBlocks for writing and running the code. Commented Mar 31, 2012 at 18:12

4 Answers 4

10

I guess you are compiling only main.c. You should also include ofdm.c.

$ gcc -Wall main.c ofdm.c -o output
Sign up to request clarification or add additional context in comments.

2 Comments

+1. Alternatively: gcc -Wall main.c -c main.o plus gcc -Wall ofdm.c -c ofdm.o plus gcc main.o ofdm.o -o output, so that only main.c needs to be recompiled if ofdm.c hasn't changed.
I agree. That's a little more efficient.
3

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.

Comments

2

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.