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

📄 v34.c

📁 Linmodem is soft modem source code for embedded system
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * Implementation of the V34 modulation/demodulation *  * 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. *  * This implementation is totally clean room. It was written by * reading the V34 specification and by using basic signal processing * knowledge.   */#include "lm.h"#include "v34priv.h"#define DEBUGvoid print_bits(int val, int n){    int i;    for(i=n-1;i>=0;i--) {        putchar('0' + ((val >> i) & 1));    }}void print_bit_vector(char *str, u8 *tab, int n){  int i;  printf("%s[%d]= ", str, n);  for(i=n-1;i>=0;i--) putchar(tab[i] + '0');  printf("\n");}static void agc_init(V34DSPState *s);static void baseband_decode(V34DSPState *s, int si, int sq);static void put_sym(V34DSPState *s, int si, int sq);/* divide the bit sequence by poly */#define SCRAMBLER_DEG 23#define V34_GPC       (1 | (1 << (23-18)))#define V34_GPA       (1 | (1 << (23-5)))int scramble_bit(V34DSPState *s, int b, int poly){  int b1, reg;   reg = s->scrambler_reg;  b1 = (reg >> (SCRAMBLER_DEG-1)) ^ b;  reg = (reg << 1) & ((1 << SCRAMBLER_DEG) - 1);  if (b1)    reg ^= poly;    s->scrambler_reg = reg;  return b1;}int unscramble_bit(V34DSPState *s, int b, int poly){  int b1, reg;   reg = s->scrambler_reg;  b1 = (reg >> (SCRAMBLER_DEG-1)) ^ b;  reg = (reg << 1) & ((1 << SCRAMBLER_DEG) - 1);  if (b)    reg ^= poly;    s->scrambler_reg = reg;  return b1;}/* build the constellation (no need to store it completely, we are lazy!) */static int constellation_cmp(const void *a_ptr, const void *b_ptr){  int x1,y1,x2,y2,d;  x1= ((s8 *)a_ptr)[0];  y1= ((s8 *)a_ptr)[1];  x2= ((s8 *)b_ptr)[0];  y2= ((s8 *)b_ptr)[1];    d = (x1 * x1 + y1 * y1) - (x2 * x2 + y2 * y2) ;  if (d != 0)     return d;  else    return y2 - y1;}#define rotate_clockwise(x, y, x1, y1, z)\{\      switch(z) {\      case 0:\        x = x1;\        y = y1;\        break;\      case 1:\        x = -y1;\        y = x1;\        break;\      case 2:\        x = -x1;\        y = -y1;\        break;\      default:\        x = y1;\        y = -x1;\        break;\      }\}static void build_constellation(V34DSPState *s){  int x,y,i,j,k;  k = 0;  for(y=C_MIN; y<= C_MAX; y++) {      for(x=C_MIN; x<= C_MAX; x++) {          s->constellation[k][0] = 4*x+1;          s->constellation[k][1] = 4*y+1;          k++;      }  }  /* now sort the constellation */  qsort(s->constellation, C_MAX_SIZE, 2, constellation_cmp);#if 0  for(i=0;i<L_MAX/4;i++) printf("%d: x=%d y=%d\n",                            i, s->constellation[i][0], s->constellation[i][1]);#endif  /* build the table for the decoder (not the best table, the corners     are not ok) */    memset(s->constellation_to_code, 0, sizeof(s->constellation_to_code));  for(j=0;j<4;j++) {    for(i=0;i<L_MAX/4;i++) {      int x1,y1;      x1 = s->constellation[i][0];      y1 = s->constellation[i][1];      rotate_clockwise(x, y, x1, y1, j);      x = (x + C_RADIUS) >> 1;      y = (y + C_RADIUS) >> 1;            s->constellation_to_code[x][y] = i | (j << 14);    }  }}/* index to ring utilities */static inline int g2(V34DSPState *st, int p, int m){  if (p >= 0 && p <= 2*(m-1))    return m - abs(p-(m-1));  else {    return 0;  }}static inline int g4(V34DSPState *st, int p, int m){  int s,i;    s = 0;  if (p >= 0 && p <= 4*(m-1)) {    for(i=0;i<=p;i++) s += st->g2_tab[i] * st->g2_tab[p-i];  }  return s;}static inline int g8(V34DSPState *st, int p, int m){  int s,i;  s = 0;  if (p >= 0 && p <= 8*(m-1)) {    for(i=0;i<=p;i++) s += st->g4_tab[i] * st->g4_tab[p-i];  }  return s;}static void index_to_rings(V34DSPState *s, int ring[4][2], int r0){  int a,b,c,d,e,f,g,h,r1,r2,r3,r4,r5,tmp,m;    m = s->M;  a = -1;  r1 = 0;  for(;;) {    tmp = r0 - s->z8_tab[a+1];    if (tmp < 0) break;    r1 = tmp;    a++;  }    b = 0;  for(;;) {    tmp = r1 - s->g4_tab[b] * s->g4_tab[a-b];    if (tmp < 0) break;    r1 = tmp;    b++;  }    tmp = s->g4_tab[b];  r2 = r1 % tmp;  r3 = (r1 - r2) / tmp;  c = 0;  r4 = r2;  for(;;) {    tmp = r4 - s->g2_tab[c] * s->g2_tab[b-c];    if (tmp < 0) break;    r4 = tmp;    c++;  }  d = 0;  r5 = r3;  for(;;) {    tmp = r5 - s->g2_tab[d] * s->g2_tab[a-b-d];    if (tmp < 0) break;    r5 = tmp;    d++;  }  tmp = s->g2_tab[c];  e = r4 % tmp;  f = (r4 - e) / tmp;    tmp = s->g2_tab[d];  g = r5 % tmp;  h = (r5 - g) / tmp;    if (c < m) {    ring[0][0] = e;    ring[0][1] = c - ring[0][0];  } else {    ring[0][1] = m - 1 - e;    ring[0][0] = c - ring[0][1];  }      if ((b-c) < m) {    ring[1][0] = f;    ring[1][1] = b - c - ring[1][0];  } else {    ring[1][1] = m - 1 - f;    ring[1][0] = b - c - ring[1][1];  }    if (d < m) {    ring[2][0] = g;    ring[2][1] = d - ring[2][0];  } else {    ring[2][1] = m - 1 - g;    ring[2][0] = d - ring[2][1];  }  if ((a-b-d) < m) {    ring[3][0] = h;    ring[3][1] = a - b - d - ring[3][0];  } else {    ring[3][1] = m - 1 - h;    ring[3][0] = a - b - d - ring[3][1];  }}/* return the K bit index corresponding to the rings */static int rings_to_index(V34DSPState *s, int ring[4][2]){  int a,b,c,d,e,f,g,h,r0,r1,r2,r3,r4,r5,m,i;  m = s->M;  /* find back the parameters */  c = ring[0][0] + ring[0][1];  if (c < m) e = ring[0][0]; else e = m - 1 - ring[0][1];    b = ring[1][0] + ring[1][1];  if (b < m) f = ring[1][0]; else f = m - 1 - ring[1][1];  b += c;    d = ring[2][0] + ring[2][1];  if (d < m) g = ring[2][0]; else g = m - 1 - ring[2][1];    a = ring[3][0] + ring[3][1];  if (a < m) h = ring[3][0]; else h = m - 1 - ring[3][1];  a += b + d;  r5 = h * s->g2_tab[d] + g;  r4 = f * s->g2_tab[c] + e;    r3 = r5;  for(i=0;i<d;i++) r3 += s->g2_tab[i] * s->g2_tab[a-b-i];    r2 = r4;  for(i=0;i<c;i++) r2 += s->g2_tab[i] * s->g2_tab[b-i];  r1 = r3 * s->g4_tab[b] + r2;    for(i=0;i<b;i++) r1 += s->g4_tab[i] * s->g4_tab[a-i];  r0 = r1 + s->z8_tab[a];  return r0;}/* initialize the g2, g4, g8 & z8 tables */static void build_rings(V34DSPState *s){  int n,i,m;  m = s->M;  n = 8*(m - 1) + 1;  for(i=0;i<n;i++) s->g2_tab[i] = g2(s,i,m);  for(i=0;i<n;i++) s->g4_tab[i] = g4(s,i,m);  for(i=0;i<n;i++) s->g8_tab[i] = g8(s,i,m);    s->z8_tab[0] = 0;  for(i=1;i<n;i++) {    s->z8_tab[i] = s->z8_tab[i-1] + s->g8_tab[i-1];  }#if 0  {    int i;    for(i=0;i<=(1 << s->K);i++) {      int m[4][2],j, r1,r0;      r0 = random() % (1 << s->K);      index_to_rings(s, m, r0);      r1 = rings_to_index(s, m);      printf("%d:", r0);      for(j=0;j<4;j++) printf(" %d %d",m[j][0], m[j][1]);      printf("\n");      if (r0 != r1) {        printf("error r0=%d r1=%d\n" , r0, r1);        exit(1);      }    }  }#endif}/* parameters for each symbol rate */static u8 S_tab[6][8] = {  /* a, c, d1, e1, d2, e2, J, P */    { 1, 1, 2, 3, 3, 4, 7, 12, }, /* S=2400 */    { 8, 7, 3, 5, 2, 3, 8, 12, }, /* S=2743 */    { 7, 6, 3, 5, 2, 3, 7, 14, }, /* S=2800 */    { 5, 4, 3, 5, 2, 3, 7, 15, }, /* S=3000 */    { 4, 3, 4, 7, 3, 5, 7, 16, }, /* S=3200 */    {10, 7, 4, 7, 4, 7, 8, 15, }, /* S=3429 */};/* this table depends on the sample rate. We have S=a1/c1 * V34_SAMPLE_RATE */static u8 baud_tab[6][2] = {    /* a1, c1 */    { 3, 10 },    { 12, 35 },    { 7, 20 },    { 3, 8 },    { 2, 5 },    { 3, 7 },};static s16 *rc_filter[6] = {    v34_rc_10_filter,    v34_rc_35_filter,    v34_rc_20_filter,    v34_rc_8_filter,    v34_rc_5_filter,    v34_rc_7_filter,};    static void build_tx_filter(V34DSPState *s){    /* sampled at every symbol */        s->tx_filter = rc_filter[s->S];    s->baud_incr = s->symbol_rate * (float)0x10000 / (float)V34_SAMPLE_RATE;    s->baud_phase = 4;    s->carrier_phase = 0;    s->carrier_incr = s->carrier_freq * (float)0x10000 / (float)V34_SAMPLE_RATE;    /* init TX fifo */    s->tx_filter_wsize = RC_FILTER_SIZE;    s->tx_buf_ptr = 0;    s->tx_outbuf_ptr = s->tx_filter_wsize;    s->tx_buf_size = 0;}float hilbert[156] = {/* alpha=0.000000 beta=0.000000 */

⌨️ 快捷键说明

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