⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v22.c

📁 Linmodem is soft modem source code for embedded system
💻 C
字号:
/*  * V22 modulator & demodulator *  * Copyright (c) 1999,2000 Fabrice Bellard. * * This code is released under the GNU General Public License version * 2. Please read the file COPYING to know the exact terms of the * license. */#include "lm.h"/* * This code is also used by the V34 phase 2 at 600 bits/s. V22bis * 2400 bps is implemented in the modulation but not in the * demodulation.   */void V22_mod_init(V22ModState *s){    s->baud_phase = 0;    s->baud_num = 3;    s->baud_denom = 40;    s->tx_filter_wsize = V22_TX_FILTER_SIZE / s->baud_denom;    memset(s->tx_buf, 0, sizeof(s->tx_buf));    s->tx_outbuf_ptr = 0;    s->carrier_phase = 0;    s->carrier2_phase = 0;    s->Z = 0;        if (s->calling) {        /* call modem DPSK: 600 bps, carrier at 1200 Hz, 0 db */        s->carrier_incr = (PHASE_BASE * 1200.0) / V34_SAMPLE_RATE;    } else {        /* answer modem DPSK: 600 bps, carrier at 2400 Hz, -1 db,            guard tone at 1800 Hz, -7db */        s->carrier_incr = (PHASE_BASE * 2400.0) / V34_SAMPLE_RATE;        s->carrier2_incr = (PHASE_BASE * 1800.0) / V34_SAMPLE_RATE;    }}static void V22_mod_baseband(V22ModState *s, s16 *x_ptr, s16 *y_ptr){    int x, y, x1, y1, b1, b2;    /* handle each kind of modulation */    switch(s->mod_type) {    default:    case V34_MOD_600:        b1 = s->get_bit(s->opaque);        /* rotation by 0 or 180 degrees */        s->Z = s->Z ^ (b1 << 1);        x1 = 0x2000;        y1 = 0x2000;        break;    case V22_MOD_600:        b1 = s->get_bit(s->opaque);        /* rotation by 90 or 270 degrees */        s->Z = (s->Z + ((b1 << 1) | 1)) & 3;        x1 = 0x2000;        y1 = 0x2000;        break;    case V22_MOD_1200:        b1 = s->get_bit(s->opaque);        b2 = s->get_bit(s->opaque);        b2 ^= (1 - b1);        s->Z = (s->Z + ((b1 << 1) | b2)) & 3;        x1 = 0x2000;        y1 = 0x2000;        break;    case V22_MOD_2400:        /* quadrant selection */        b1 = s->get_bit(s->opaque);        b2 = s->get_bit(s->opaque);        b2 ^= (1 - b1);        s->Z = (s->Z + ((b1 << 1) | b2)) & 3;        /* 4 positions inside the quadrant */        b1 = s->get_bit(s->opaque);        b2 = s->get_bit(s->opaque);        /* XXX: normalize */        x1 = 0x1000;        if (b2)             x1 += 0x2000;        y1 = 0x1000;        if (b1)            y1 += 0x2000;        break;    }        /* rotate counter clockwise */    switch(s->Z) {    case 0:        x = x1;        y = y1;        break;    case 1:        x = -y1;        y = x1;        break;    case 2:        x = -x1;        y = -y1;        break;    default:    case 3:        x = y1;        y = -x1;        break;    }    *x_ptr = x;    *y_ptr = y;}void V22_mod(V22ModState *s, s16 *samples, unsigned int nb){    int i, j, k, val, si, sq, ph;        for(i=0;i<nb;i++) {        /* apply the spectrum shaping filter */        ph = s->baud_phase;        si = sq = 0;        for(j=0;j<s->tx_filter_wsize;j++) {            k = (s->tx_outbuf_ptr - j - 1) &                 (V22_TX_BUF_SIZE - 1);            si += s->tx_buf[k][0] * v22_tx_filter[ph];            sq += s->tx_buf[k][1] * v22_tx_filter[ph];            ph += s->baud_denom;        }        si = si >> 14;        sq = sq >> 14;        /* get next baseband symbol ? */        s->baud_phase += s->baud_num;        if (s->baud_phase >= s->baud_denom) {            s->baud_phase -= s->baud_denom;            V22_mod_baseband(s,                              &s->tx_buf[s->tx_outbuf_ptr][0],                             &s->tx_buf[s->tx_outbuf_ptr][1]);            s->tx_outbuf_ptr = (s->tx_outbuf_ptr + 1) & (V22_TX_BUF_SIZE - 1);        }                val = (si * dsp_cos(s->carrier_phase) -                sq * dsp_cos((PHASE_BASE/4) - s->carrier_phase)) >> COS_BITS;        s->carrier_phase += s->carrier_incr;        if (!s->calling) {            /* a 1800 Hz tone is added for answer modem modulation at 6 dB below it */            val += (dsp_cos(s->carrier2_phase) >> 1);            s->carrier2_phase += s->carrier2_incr;        }        samples[i] = val;    }}void V22_demod_init(V22DemodState *s){    s->baud_phase = 0;    s->baud_num = 3;    s->baud_denom = 40;    s->carrier_phase = 0;    if (!s->calling) {        /* call modem DPSK: 600 bps, carrier at 1200 Hz, 0 db */        s->carrier_incr = (PHASE_BITS * 1200) / 8000;    } else {        /* answer modem DPSK: 600 bps, carrier at 2400 Hz, -1 db,            guard tone at 1800 Hz, -7db */        s->carrier_incr = (PHASE_BITS * 2400) / 8000;    }}void V22_demod(V22DemodState *s, s16 *samples, unsigned int nb){    }/* test for FSK using V21 or V23 */#define NB_SAMPLES 40#define MAXDELAY 32static int tx_bits[MAXDELAY], tx_ptr = 0, rx_ptr = 0;static int tx_blank = 32;/* transmit random bits with a sync header (31 ones, 1 zero) */static int test_get_bit(void *opaque){    int bit;    if (tx_blank != 0) {        /* send 1 at the beginning for synchronization */        bit = (tx_blank > 1);        tx_blank--;    } else {        bit = random() % 2;        tx_bits[tx_ptr] = bit;        if (++tx_ptr == MAXDELAY)            tx_ptr = 0;    }    return bit;}static int nb_bits = 0, errors = 0, sync_count = 0, got_sync = 0;static void test_put_bit(void *opaque, int bit){    int tbit;        if (!got_sync) {                if (bit) {            sync_count++;        } else {            if (sync_count > 16)                got_sync = 1;            sync_count = 0;        }    } else {        tbit = tx_bits[rx_ptr];        if (++rx_ptr == MAXDELAY)            rx_ptr = 0;        if (bit != tbit) {            errors++;        }        nb_bits++;    }}void V22_test(void){    V22ModState tx;    V22DemodState rx;    int err, calling;    struct LineModelState *line_state;    s16 buf[NB_SAMPLES];    s16 buf1[NB_SAMPLES];    s16 buf2[NB_SAMPLES];    s16 buf3[NB_SAMPLES];    FILE *f1;        err = lm_display_init();    if (err < 0) {        fprintf(stderr, "Could not init X display\n");        exit(1);    }    line_state = line_model_init();    f1 = fopen("cal.sw", "wb");    if (f1 == NULL) {        perror("cal.sw");        exit(1);    }    calling = 0;    tx.calling = calling;    tx.opaque = NULL;    tx.get_bit = test_get_bit;    tx.mod_type = V34_MOD_600;    V22_mod_init(&tx);    rx.calling = !calling;    rx.opaque = NULL;    rx.put_bit = test_put_bit;    rx.mod_type = tx.mod_type;    V22_demod_init(&rx);    nb_bits = 0;    errors = 0;    for(;;) {        if (lm_display_poll_event())            break;                V22_mod(&tx, buf, NB_SAMPLES);        memset(buf3, 0, sizeof(buf3));        line_model(line_state, buf1, buf, buf2, buf3, NB_SAMPLES);        fwrite(buf, 1, NB_SAMPLES * 2, f1);                V22_demod(&rx, buf1, NB_SAMPLES);    }    fclose(f1);    printf("errors=%d nb_bits=%d Pe=%f\n",            errors, nb_bits, (float) errors / (float)nb_bits);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -