www.pudn.com > fast.zip > v32tx.C
// #include#include #include #include #include #include #include #include "modem.h" #include "cancel.h" #include "coder.h" #define TX_TRNLEN 8000 /* length of training sequence transmitted (WAS 4096) */ static float shapetab[2*SYMBLEN+1] = { /* Raised cosine pulse shaping with Beta = 0.5; square-root, with x/sinx compensation */ +1.1510798492, +0.9848450677, +0.5795790021, +0.1495226763, -0.1156411181, -0.1625782395, -0.0750914609, +0.0185567369, +0.0448950047, }; static sinegen *carrier; static coroutine *tx1_co, *tx2_co; static scrambler *gpc; static traininggen *trn; static encoder *enc; static void sendrate(ushort); static void tx2_loop(); static void sendsymbol(complex); inline void pbit(int b) { callco(tx2_co, b); } inline int gbit() { return callco(tx1_co); } global void inittx() { carrier = new sinegen(1800.0); tx1_co = currentco; tx2_co = new coroutine(tx2_loop); gpc = new scrambler(GPC); trn = new traininggen(gpc); enc = new encoder; pbit(1); /* sync to symbol boundary */ ushort r2 = rateword; infomsg(">>> R2: rates = %04x", r2); while (mstate < 5) sendrate(r2); /* send R2 */ /* now rateword == R2 & R3 */ rateword |= 0xf000; /* pick highest common bit rate, leave just one rate bit set */ if (rateword & rb_14400) rateword &= ~(rb_12000 | rb_9600 | rb_7200 | rb_4800); else if (rateword & rb_12000) rateword &= ~(rb_9600 | rb_7200 | rb_4800); else if (rateword & rb_9600) rateword &= ~(rb_7200 | rb_4800); else if (rateword & rb_7200) rateword &= ~rb_4800; else if (rateword & rb_4800) ; else giveup("can't agree on a speed!"); infomsg(">>> E2: rates = %04x", rateword); /* send E2 */ sendrate(rateword); enc -> setrate(rateword); /* tell encoder what bit rate to use */ while (mstate < 6) pbit(1); /* sync to Rx side */ for (int i = 0; i < 128; i++) pbit(1); /* followed by 128 "1" bits */ } static void sendrate(ushort wd) { for (int i=0; i < 16; i++) { pbit(wd >> 15); wd <<= 1; } } global void putasync(int n) /* asynchronous output */ { uint un = (n >= 0) ? (n << 1) | 0x200 : /* add start bit, 1 stop bit */ 0x3ff; /* send mark bits while idle */ until (un == 0) { pbit(un & 1); un >>= 1; } } static void tx2_loop() { /* round-trip-delay estimation */ while (mstate < 2) { complex z = (mstate == 0) ? ztab2[0] : ztab2[3]; /* A or C */ sendsymbol(z); sendsymbol(z); /* AA or CC */ } /* train equalizer */ while (mstate == 2) sendsymbol(0.0); /* train canceller */ carrier -> resetphase(); gpc -> reset(); /* reset scrambler before using trn */ for (int bc = SEG_1; bc < SEG_3 + TX_TRNLEN; bc++) sendsymbol(trn -> get(bc)); mstate++; /* from 3 to 4 */ /* exchange data */ enc -> reset(); for (;;) { int bits = 0; bits = (bits << 1) | gpc -> fwd(gbit()); bits = (bits << 1) | gpc -> fwd(gbit()); if (enc -> rate & rb_7200) bits = (bits << 1) | gpc -> fwd(gbit()); sendsymbol(enc -> encode(bits)); } } static void sendsymbol(complex z) { static complex a0 = 0.0, a1 = 0.0, a2 = 0.0, a3 = 0.0; for (int k = 0; k < SYMBLEN; k++) { /* baseband pulse shaping */ complex s = shapetab[SYMBLEN + k] * a0 + shapetab[k] * a1 + shapetab[SYMBLEN - k] * a2 + shapetab[2*SYMBLEN - k] * a3; /* insert baseband sample into canceller */ can -> insert(s); /* modulate onto carrier */ complex cz = carrier -> cnext(); outsample(0.2f * (s.re*cz.re + s.im*cz.im)); } a0 = a1; a1 = a2; a2 = a3; a3 = z; }