File: qpacketmodem_example.c

package info (click to toggle)
liquid-dsp 1.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,216 kB
  • sloc: ansic: 115,859; sh: 3,513; makefile: 1,350; python: 274; asm: 11
file content (139 lines) | stat: -rw-r--r-- 4,619 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//
// qpacketmodem_example.c
//
// This example demonstrates the basic packet modem encoder/decoder
// operation. A packet of data is encoded and modulated into symbols,
// channel noise is added, and the resulting packet is demodulated
// and decoded.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <getopt.h>
#include <assert.h>

#include "liquid.h"

void usage()
{
    printf("ofdmflexframesync_example [options]\n");
    printf("  h     : print usage\n");
    printf("  n     : payload length [bytes], default: 400\n");
    printf("  m     : modulation scheme (qpsk default)\n");
    liquid_print_modulation_schemes();
    printf("  v     : data integrity check: crc32 default\n");
    liquid_print_crc_schemes();
    printf("  c     : coding scheme (inner): g2412 default\n");
    printf("  k     : coding scheme (outer): none default\n");
    liquid_print_fec_schemes();
    printf("  s     : signal-to-noise ratio [dB], default: 6\n");
}

int main(int argc, char *argv[])
{
    //srand( time(NULL) );

    // options
    modulation_scheme ms     = LIQUID_MODEM_QPSK;        // mod. scheme
    crc_scheme   check       = LIQUID_CRC_32;            // data validity check
    fec_scheme   fec0        = LIQUID_FEC_GOLAY2412;     // fec (inner)
    fec_scheme   fec1        = LIQUID_FEC_NONE;          // fec (outer)
    unsigned int payload_len = 400;                      // payload length
    float        SNRdB       = 6.0f;                     // SNR [dB]
    const char   filename[]  = "qpacketmodem_example.m"; // output filename

    // get options
    int dopt;
    while((dopt = getopt(argc,argv,"hn:m:v:c:k:s:")) != EOF){
        switch (dopt) {
        case 'h': usage();                                     return 0;
        case 'n': payload_len = atol(optarg);                  break;
        case 'm': ms          = liquid_getopt_str2mod(optarg); break;
        case 'v': check       = liquid_getopt_str2crc(optarg); break;
        case 'c': fec0        = liquid_getopt_str2fec(optarg); break;
        case 'k': fec1        = liquid_getopt_str2fec(optarg); break;
        case 's': SNRdB       = atof(optarg);                  break;
        default:
            exit(-1);
        }
    }
    unsigned int i;

    // derived values
    float nstd = powf(10.0f, -SNRdB/20.0f);

    // create and configure packet encoder/decoder object
    qpacketmodem q = qpacketmodem_create();
    qpacketmodem_configure(q, payload_len, check, fec0, fec1, ms);
    qpacketmodem_print(q);

    // initialize payload
    unsigned char payload_tx[payload_len];
    unsigned char payload_rx[payload_len];

    // initialize payload
    for (i=0; i<payload_len; i++) {
        payload_tx[i] = rand() & 0xff;
        payload_rx[i] = 0x00;
    }

    // get frame length
    unsigned int frame_len = qpacketmodem_get_frame_len(q);

    // allocate memory for frame samples
    float complex frame_tx[frame_len];
    float complex frame_rx[frame_len];

    // encode frame
    qpacketmodem_encode(q, payload_tx, frame_tx);

    // add noise
    for (i=0; i<frame_len; i++)
        frame_rx[i] = frame_tx[i] + nstd*(randnf() + _Complex_I*randnf())*M_SQRT1_2;

    // decode frame
    int crc_pass = qpacketmodem_decode(q, frame_rx, payload_rx);

    // count errors
    unsigned int num_bit_errors = count_bit_errors_array(payload_tx, payload_rx, payload_len);

    // print results
    printf("payload pass ? %s, errors: %u / %u\n",
            crc_pass ? "pass" : "FAIL",
            num_bit_errors,
            8*payload_len);

    // destroy allocated objects
    qpacketmodem_destroy(q);

    // write symbols to output file for plotting
    FILE * fid = fopen(filename,"w");
    if (!fid) {
        fprintf(stderr,"error: could not open '%s' for writing\n", filename);
        return -1;
    }
    fprintf(fid,"%% %s : auto-generated file\n", filename);
    fprintf(fid,"clear all;\n");
    fprintf(fid,"close all;\n");
    fprintf(fid,"frame_len = %u;\n", frame_len);
    fprintf(fid,"y = zeros(1,frame_len);\n");
    for (i=0; i<frame_len; i++)
        fprintf(fid,"y(%6u) = %12.4e + 1i*%12.4e;\n", i+1, crealf(frame_rx[i]), cimagf(frame_rx[i]));
    fprintf(fid,"figure('Color','white');\n");
    fprintf(fid,"plot(real(y),imag(y),'x','MarkerSize',3);\n");
    fprintf(fid,"axis([-1 1 -1 1]*1.5);\n");
    fprintf(fid,"axis square;\n");
    fprintf(fid,"grid on;\n");
    fprintf(fid,"xlabel('real');\n");
    fprintf(fid,"ylabel('imag');\n");

    fclose(fid);
    printf("results written to '%s'\n", filename);

    printf("done.\n");
    return 0;
}