Exemple #1
0
// create an arbitrary modem object
MODEM() MODEM(_create_arb)(unsigned int _bits_per_symbol)
{
    MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) );
    q->scheme = LIQUID_MODEM_ARB;

    MODEM(_init)(q, _bits_per_symbol);

    q->M = q->M;
    q->symbol_map = (TC*) calloc( q->M, sizeof(TC) );

    q->modulate_func   = &MODEM(_modulate_arb);
    q->demodulate_func = &MODEM(_demodulate_arb);

    return q;
}
Exemple #2
0
// create symtrack object with basic parameters
//  _ftype  : filter type (e.g. LIQUID_FIRFILT_RRC)
//  _k      : samples per symbol
//  _m      : filter delay (symbols)
//  _beta   : filter excess bandwidth
//  _ms     : modulation scheme (e.g. LIQUID_MODEM_QPSK)
SYMTRACK() SYMTRACK(_create)(int          _ftype,
                             unsigned int _k,
                             unsigned int _m,
                             float        _beta,
                             int          _ms)
{
    // validate input
    if (_k < 2) {
        fprintf(stderr,"error: symtrack_%s_create(), filter samples/symbol must be at least 2\n", EXTENSION_FULL);
        exit(1);
    } else if (_m == 0) {
        fprintf(stderr,"error: symtrack_%s_create(), filter delay must be greater than zero\n", EXTENSION_FULL);
        exit(1);
    } else if (_beta <= 0.0f || _beta > 1.0f) {
        fprintf(stderr,"error: symtrack_%s_create(), filter excess bandwidth must be in (0,1]\n", EXTENSION_FULL);
        exit(1);
    } else if (_ms == LIQUID_MODEM_UNKNOWN || _ms >= LIQUID_MODEM_NUM_SCHEMES) {
        fprintf(stderr,"error: symtrack_%s_create(), invalid modulation scheme\n", EXTENSION_FULL);
        exit(1);
    }

    // allocate memory for main object
    SYMTRACK() q = (SYMTRACK()) malloc( sizeof(struct SYMTRACK(_s)) );

    // set input parameters
    q->filter_type = _ftype;
    q->k           = _k;
    q->m           = _m;
    q->beta        = _beta;
    q->mod_scheme  = _ms == LIQUID_MODEM_UNKNOWN ? LIQUID_MODEM_BPSK : _ms;

    // create automatic gain control
    q->agc = AGC(_create)();
    
    // create symbol synchronizer (output rate: 2 samples per symbol)
    if (q->filter_type == LIQUID_FIRFILT_UNKNOWN)
        q->symsync = SYMSYNC(_create_kaiser)(q->k, q->m, 0.9f, 16);
    else
        q->symsync = SYMSYNC(_create_rnyquist)(q->filter_type, q->k, q->m, q->beta, 16);
    SYMSYNC(_set_output_rate)(q->symsync, 2);

    // create equalizer as default low-pass filter with integer symbol delay (2 samples/symbol)
    q->eq_len = 2 * 4 + 1;
    q->eq = EQLMS(_create_lowpass)(q->eq_len,0.45f);

    // nco and phase-locked loop
    q->nco = NCO(_create)(LIQUID_VCO);

    // demodulator
    q->demod = MODEM(_create)(q->mod_scheme);

    // set default bandwidth
    SYMTRACK(_set_bandwidth)(q, 0.9f);

    // reset and return main object
    SYMTRACK(_reset)(q);
    return q;
}
// create a 'square' 128-QAM modem object
MODEM() MODEM(_create_sqam128)()
{
    MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) );
    q->scheme = LIQUID_MODEM_SQAM128;

    MODEM(_init)(q, 7);

    // allocate memory for 32-point symbol map
    q->data.sqam128.map = (TC*) malloc( 32*sizeof(TC) );
#if T == float
    memmove(q->data.sqam128.map, modem_arb_sqam128, 32*sizeof(TC));
#endif

    // set modulation, demodulation functions
    q->modulate_func   = &MODEM(_modulate_sqam128);
    q->demodulate_func = &MODEM(_demodulate_sqam128);

    return q;
}
Exemple #4
0
// create arbitrary digital modem object
MODEM() MODEM(_create_arbitrary)(TC * _table,
                               unsigned int _M)
{
    // strip out bits/symbol
    unsigned int m = liquid_nextpow2(_M);
    if ( (1<<m) != _M ) {
        // TODO : eventually support non radix-2 constellation sizes
        fprintf(stderr,"error: modem_create_arbitrary(), input constellation size must be power of 2\n");
        exit(1);
    }

    // create arbitrary modem object, not initialized
    MODEM() q = MODEM(_create_arb)(m);

    // initialize object from table
    MODEM(_arb_init)(q, _table, _M);

    // return object
    return q;
}
Exemple #5
0
// create a psk (phase-shift keying) modem object
MODEM() MODEM(_create_psk)(unsigned int _bits_per_symbol)
{
    MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) );

    switch (_bits_per_symbol) {
    case 1: q->scheme = LIQUID_MODEM_PSK2;   break;
    case 2: q->scheme = LIQUID_MODEM_PSK4;   break;
    case 3: q->scheme = LIQUID_MODEM_PSK8;   break;
    case 4: q->scheme = LIQUID_MODEM_PSK16;  break;
    case 5: q->scheme = LIQUID_MODEM_PSK32;  break;
    case 6: q->scheme = LIQUID_MODEM_PSK64;  break;
    case 7: q->scheme = LIQUID_MODEM_PSK128; break;
    case 8: q->scheme = LIQUID_MODEM_PSK256; break;
    default:
        fprintf(stderr,"error: modem_create_psk(), cannot support PSK with m > 8\n");
        exit(1);
    }

    // initialize basic modem structure
    MODEM(_init)(q, _bits_per_symbol);

    // compute alpha
    q->data.psk.alpha = M_PI/(T)(q->M);

    // initialize demodulation array reference
    unsigned int k;
    for (k=0; k<(q->m); k++)
        q->ref[k] = (1<<k) * q->data.psk.alpha;

    // compute phase offset (half of phase difference between symbols)
    q->data.psk.d_phi = M_PI*(1.0f - 1.0f/(T)(q->M));

    // set modulation/demodulation functions
    q->modulate_func = &MODEM(_modulate_psk);
    q->demodulate_func = &MODEM(_demodulate_psk);

    // initialize symbol map
    q->symbol_map = (TC*)malloc(q->M*sizeof(TC));
    MODEM(_init_map)(q);
    q->modulate_using_map = 1;

    // initialize soft-demodulation look-up table
    if (q->m >= 3)
        MODEM(_demodsoft_gentab)(q, 2);

    return q;
}
Exemple #6
0
// create a qpsk (quaternary phase-shift keying) modem object
MODEM() MODEM(_create_qpsk)()
{
    MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) );
    q->scheme = LIQUID_MODEM_QPSK;

    MODEM(_init)(q, 2);

    q->modulate_func   = &MODEM(_modulate_qpsk);
    q->demodulate_func = &MODEM(_demodulate_qpsk);

    // reset and return
    MODEM(_reset)(q);
    return q;
}
Exemple #7
0
// create digital modem of a specific scheme and bits/symbol
MODEM() MODEM(_create)(modulation_scheme _scheme)
{
    switch (_scheme) {
    
    // Phase-shift keying (PSK)
    case LIQUID_MODEM_PSK2:     return MODEM(_create_psk)(1);
    case LIQUID_MODEM_PSK4:     return MODEM(_create_psk)(2);
    case LIQUID_MODEM_PSK8:     return MODEM(_create_psk)(3);
    case LIQUID_MODEM_PSK16:    return MODEM(_create_psk)(4);
    case LIQUID_MODEM_PSK32:    return MODEM(_create_psk)(5);
    case LIQUID_MODEM_PSK64:    return MODEM(_create_psk)(6);
    case LIQUID_MODEM_PSK128:   return MODEM(_create_psk)(7);
    case LIQUID_MODEM_PSK256:   return MODEM(_create_psk)(8);

    // Differential phase-shift keying (DPSK)
    case LIQUID_MODEM_DPSK2:    return MODEM(_create_dpsk)(1);
    case LIQUID_MODEM_DPSK4:    return MODEM(_create_dpsk)(2);
    case LIQUID_MODEM_DPSK8:    return MODEM(_create_dpsk)(3);
    case LIQUID_MODEM_DPSK16:   return MODEM(_create_dpsk)(4);
    case LIQUID_MODEM_DPSK32:   return MODEM(_create_dpsk)(5);
    case LIQUID_MODEM_DPSK64:   return MODEM(_create_dpsk)(6);
    case LIQUID_MODEM_DPSK128:  return MODEM(_create_dpsk)(7);
    case LIQUID_MODEM_DPSK256:  return MODEM(_create_dpsk)(8);

    // amplitude-shift keying (ASK)
    case LIQUID_MODEM_ASK2:     return MODEM(_create_ask)(1);
    case LIQUID_MODEM_ASK4:     return MODEM(_create_ask)(2);
    case LIQUID_MODEM_ASK8:     return MODEM(_create_ask)(3);
    case LIQUID_MODEM_ASK16:    return MODEM(_create_ask)(4);
    case LIQUID_MODEM_ASK32:    return MODEM(_create_ask)(5);
    case LIQUID_MODEM_ASK64:    return MODEM(_create_ask)(6);
    case LIQUID_MODEM_ASK128:   return MODEM(_create_ask)(7);
    case LIQUID_MODEM_ASK256:   return MODEM(_create_ask)(8);

    // rectangular quadrature amplitude-shift keying (QAM)
    case LIQUID_MODEM_QAM4:     return MODEM(_create_qam)(2);
    case LIQUID_MODEM_QAM8:     return MODEM(_create_qam)(3);
    case LIQUID_MODEM_QAM16:    return MODEM(_create_qam)(4);
    case LIQUID_MODEM_QAM32:    return MODEM(_create_qam)(5);
    case LIQUID_MODEM_QAM64:    return MODEM(_create_qam)(6);
    case LIQUID_MODEM_QAM128:   return MODEM(_create_qam)(7);
    case LIQUID_MODEM_QAM256:   return MODEM(_create_qam)(8);

    // amplitude phase-shift keying (APSK)
    case LIQUID_MODEM_APSK4:    return MODEM(_create_apsk)(2);
    case LIQUID_MODEM_APSK8:    return MODEM(_create_apsk)(3);
    case LIQUID_MODEM_APSK16:   return MODEM(_create_apsk)(4);
    case LIQUID_MODEM_APSK32:   return MODEM(_create_apsk)(5);
    case LIQUID_MODEM_APSK64:   return MODEM(_create_apsk)(6);
    case LIQUID_MODEM_APSK128:  return MODEM(_create_apsk)(7);
    case LIQUID_MODEM_APSK256:  return MODEM(_create_apsk)(8);

    // specific modems
    case LIQUID_MODEM_BPSK:      return MODEM(_create_bpsk)();
    case LIQUID_MODEM_QPSK:      return MODEM(_create_qpsk)();
    case LIQUID_MODEM_OOK:       return MODEM(_create_ook)();
    case LIQUID_MODEM_SQAM32:    return MODEM(_create_sqam32)();
    case LIQUID_MODEM_SQAM128:   return MODEM(_create_sqam128)();
    case LIQUID_MODEM_V29:       return MODEM(_create_V29)();
    case LIQUID_MODEM_ARB16OPT:  return MODEM(_create_arb16opt)();
    case LIQUID_MODEM_ARB32OPT:  return MODEM(_create_arb32opt)();
    case LIQUID_MODEM_ARB64OPT:  return MODEM(_create_arb64opt)();
    case LIQUID_MODEM_ARB128OPT: return MODEM(_create_arb128opt)();
    case LIQUID_MODEM_ARB256OPT: return MODEM(_create_arb256opt)();
    case LIQUID_MODEM_ARB64VT:   return MODEM(_create_arb64vt)();
    
    // arbitrary modem
    case LIQUID_MODEM_ARB:
        fprintf(stderr,"error: modem_create(), cannot create arbitrary modem (LIQUID_MODEM_ARB) without specifying constellation\n");
        exit(1);

    // unknown modulation scheme
    default:
        fprintf(stderr,"error: modem_create(), unknown/unsupported modulation scheme : %u\n", _scheme);
        exit(1);
    }

    // should never get to this point, but adding return statment
    // to keep compiler happy
    return NULL;
}
Exemple #8
0
        fprintf(stderr,"error: modem_create(), cannot create arbitrary modem (LIQUID_MODEM_ARB) without specifying constellation\n");
        exit(1);

    // unknown modulation scheme
    default:
        fprintf(stderr,"error: modem_create(), unknown/unsupported modulation scheme : %u\n", _scheme);
        exit(1);
    }

    // should never get to this point, but adding return statment
    // to keep compiler happy
    return NULL;
}

// recreate modulation scheme, re-allocating memory as necessary
MODEM() MODEM(_recreate)(MODEM() _q,
                         modulation_scheme _scheme)
{
    // TODO : regenerate modem only when truly necessary
    if (_q->scheme != _scheme) {
        // destroy and re-create modem
        MODEM(_destroy)(_q);
        _q = MODEM(_create)(_scheme);
    }

    // return object
    return _q;
}

// destroy a modem object
void MODEM(_destroy)(MODEM() _q)
    // allocate memory for 32-point symbol map
    q->data.sqam128.map = (TC*) malloc( 32*sizeof(TC) );
#if T == float
    memmove(q->data.sqam128.map, modem_arb_sqam128, 32*sizeof(TC));
#endif

    // set modulation, demodulation functions
    q->modulate_func   = &MODEM(_modulate_sqam128);
    q->demodulate_func = &MODEM(_demodulate_sqam128);

    return q;
}

// modulate symbol with 'square' 128-QAM
void MODEM(_modulate_sqam128)(MODEM()      _q,
                              unsigned int _sym_in,
                              TC *         _y)
{
    // strip off most-significant two bits (quadrant)
    unsigned int quad = (_sym_in >> 5) & 0x03;
    
    // strip off least-significant 5 bits
    unsigned int s = _sym_in & 0x1f;
    TC p = _q->data.sqam128.map[s];
    
    switch (quad) {
    case 0: *_y =  p;           return;
    case 1: *_y =  conjf(p);    return;
    case 2: *_y = -conjf(p);    return;
    case 3: *_y = -p;           return;
Exemple #10
0
// create an apsk (amplitude/phase-shift keying) modem object
MODEM() MODEM(_create_apsk)(unsigned int _bits_per_symbol)
{
    // pointer to APSK definition container
    struct liquid_apsk_s * apskdef = NULL;

    switch (_bits_per_symbol) {
    case 2: apskdef = &liquid_apsk4;    break;
    case 3: apskdef = &liquid_apsk8;    break;
    case 4: apskdef = &liquid_apsk16;   break;
    case 5: apskdef = &liquid_apsk32;   break;
    case 6: apskdef = &liquid_apsk64;   break;
    case 7: apskdef = &liquid_apsk128;  break;
    case 8: apskdef = &liquid_apsk256;  break;
    default:
        fprintf(stderr,"error: modem_create_apsk(), unsupported modulation level (%u)\n",
                _bits_per_symbol);
        exit(1);
    }

    MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) );
    q->scheme = apskdef->scheme;
    MODEM(_init)(q, _bits_per_symbol);

    // set APSK internals
    unsigned int i;
    q->data.apsk.num_levels = apskdef->num_levels;
    for (i=0; i<q->data.apsk.num_levels; i++) {
        q->data.apsk.p[i]   = apskdef->p[i];
        q->data.apsk.r[i]   = apskdef->r[i];
        q->data.apsk.phi[i] = apskdef->phi[i];
    }

    // radius slicer
    for (i=0; i<q->data.apsk.num_levels-1; i++)
        q->data.apsk.r_slicer[i] = apskdef->r_slicer[i];

    // copy symbol map
    q->data.apsk.map = (unsigned char *) malloc(q->M*sizeof(unsigned char));
    memmove(q->data.apsk.map, apskdef->map, q->M*sizeof(unsigned char));

    // set modulation/demodulation function pointers
    q->modulate_func = &MODEM(_modulate_apsk);
    q->demodulate_func = &MODEM(_demodulate_apsk);

    // initialize soft-demodulation look-up table
    switch (q->m) {
    case 2: MODEM(_demodsoft_gentab)(q, 3); break;
    case 3: MODEM(_demodsoft_gentab)(q, 3); break;
    case 4: MODEM(_demodsoft_gentab)(q, 4); break;
    case 5: MODEM(_demodsoft_gentab)(q, 4); break;
    case 6: MODEM(_demodsoft_gentab)(q, 4); break;
    case 7: MODEM(_demodsoft_gentab)(q, 5); break;
    case 8: MODEM(_demodsoft_gentab)(q, 5); break;
    default:;
    }

    // initialize symbol map
    q->symbol_map = (TC*)malloc(q->M*sizeof(TC));
    MODEM(_init_map)(q);
    q->modulate_using_map = 1;

    return q;
}
Exemple #11
0
    case 6: MODEM(_demodsoft_gentab)(q, 4); break;
    case 7: MODEM(_demodsoft_gentab)(q, 5); break;
    case 8: MODEM(_demodsoft_gentab)(q, 5); break;
    default:;
    }

    // initialize symbol map
    q->symbol_map = (TC*)malloc(q->M*sizeof(TC));
    MODEM(_init_map)(q);
    q->modulate_using_map = 1;

    return q;
}

// modulate APSK
void MODEM(_modulate_apsk)(MODEM()      _q,
                           unsigned int _sym_in,
                           TC *         _y)
{
    if (_sym_in >= _q->M) {
        fprintf(stderr,"error: modem_modulate_apsk(), input symbol exceeds maximum\n");
        return;
    }

    // map input symbol to constellation symbol
    unsigned int i;
    unsigned int s = _q->data.apsk.map[_sym_in];

    // determine in which level the symbol is located
    unsigned int p=0;   // level
    unsigned int t=0;   // accumulated number of points per level
Exemple #12
0
    MODEM() q = (MODEM()) malloc( sizeof(struct MODEM(_s)) );
    q->scheme = LIQUID_MODEM_ARB;

    MODEM(_init)(q, _bits_per_symbol);

    q->M = q->M;
    q->symbol_map = (TC*) calloc( q->M, sizeof(TC) );

    q->modulate_func   = &MODEM(_modulate_arb);
    q->demodulate_func = &MODEM(_demodulate_arb);

    return q;
}

// modulate arbitrary modem type
void MODEM(_modulate_arb)(MODEM()      _q,
                          unsigned int _sym_in,
                          TC *         _y)
{
    if (_sym_in >= _q->M) {
        fprintf(stderr,"error: modulate_arb(), input symbol exceeds maximum\n");
        exit(1);
    }

    // map sample directly to output
    *_y = _q->symbol_map[_sym_in]; 
}

// demodulate arbitrary modem type
void MODEM(_demodulate_arb)(MODEM()        _q,
                            TC             _x,