📄 v34.c
字号:
/* * 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 + -