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

📄 wordy_bak.txt

📁 Fax and soft modem source code. - Slow modem You can use this code to build a soft modem function
💻 TXT
字号:
/*********************************************************
**********************************************************
	wordy_bak.txt
**********************************************************
**********************************************************/
/* Modem for MIPS   AJF	  January 1995
   Fax routines (T.30) */

#include <stdio.h>

#include <myaudio.h>

#include "modem.h"
#include "fcf.h"

#define MAXFRAME	252
#define MAXMESSAGE	(MAXFRAME+4)	/* frame plus address, control, checksum */
#define HDLC_TIMEOUT	(-3)

#define NO_STATE	0		/* state not set yet	 */
#define RX_CTL_STATE	1		/* receive control info	 */
#define TX_CTL_STATE	2		/* transmit control info */
#define RX_DOC_STATE	3		/* receive document	 */
#define TX_DOC_STATE	4		/* transmit document	 */

#define MYNAME	"+44 1904 432738"       /* sent in TSI/CSI frame */

static uchar shuffle[256] =
  { 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
    8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
    4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
    12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
    2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
    10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
    6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
    14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
    1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
    9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
    5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
    13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
    3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
    11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
    7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
    15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255,
  };

static uchar dcstranstab[16] =
  { /* decodes DIS bits 21-23 into DCS equivalent */
    0, 1, 2, 2, 4, 1, 0, 7,	/* low density	*/
    0, 1, 2, 4, 4, 0, 2, 7,	/* high density */
  };

static short scanbitstab[8] =
  { /* decodes DCS scan time bits into num. of bits at 7200 bit/s */
    144, 288, 72, -1, 36, -1, -1, 0,
  };

static uchar mpsframe[] = { MPS };
static uchar eopframe[] = { EOP };
static uchar dcnframe[] = { DCN };
static uchar fttframe[] = { FTT };
static uchar cfrframe[] = { CFR };
static uchar mcfframe[] = { MCF };

static uchar disframe[] = { DIS, 0x00, 0xe2, 0x0e };	/* V.29 only; no 2d coding; set "fine" bit; no scan-line padding */

static int pagecount, state, rxval, framelen, msgendtime, scanbits;
static bool isfinal;
static uchar frame[MAXFRAME];
static uchar identframe[21], dcsframe[4];

static void senddoc(), makedcs(uchar*), sendtraining();
static void receivedoc(), getdcs(bool), checkdcs(uchar*);
static bool gettraining();
static void makeident(uchar);
static void getmessage(), printident(), getmsg(), nextval();
static void msgerror(char*, word = 0, word = 0, word = 0);
static void sendframe(uchar*, int, bool), printframe(char*, uchar*, int);
static char *frametype(uchar);
static bool csumok(uchar*, int);
static ushort computecsum(uchar*, int);
static void setstate(int);


global void becomefax()
  { pagecount = 0; state = NO_STATE;
    if (options & opt_org) senddoc(); else receivedoc();
  }

static void senddoc()
  { makeident(TSI);
    int ntries = 0;
    do
      { getmessage();	/* try for DIS */
	ntries++;
      }
    until ((frame[0] == DIS && framelen >= 4) || ntries >= 6);
    unless (frame[0] == DIS && framelen >= 4) giveup("Failed to get a valid DIS frame");
    makedcs(frame);				    /* construct DCS from DIS */
    sendtraining();
    while (pagecount < numpages)
      { setstate(TX_DOC_STATE);
	sendpage(pagecount+1, scanbits);
	ntries = 0;
	do
	  { sendframe((pagecount+1 < numpages) ? mpsframe : eopframe, 1, true);	    /* send MPS or EOP */
	    getmessage();	/* shd be MCF, RTP, RTN */
	    ntries++;
	  }
	until (frame[0] == MCF || frame[0] == RTP || frame[0] == RTN || ntries >= 3);
	unless (frame[0] == MCF || frame[0] == RTP || frame[0] == RTN) break;
	if (frame[0] == MCF || frame[0] == RTP) pagecount++;
	if (frame[0] == RTP || frame[0] == RTN) sendtraining();
      }
    sendframe(dcnframe, 1, true);   /* send DCN */
    if (pagecount < numpages) giveup("Document transmission failed");
    infomsg("Success - delivered %d pages", pagecount);
  }

static void makedcs(uchar *disfr)
  { /* make DCS frame from received DIS; establish capabilities */
    dcsframe[0] = DCS;
    dcsframe[1] = 0x00;
    unless (disfr[2] & 0x40) giveup("Remote fax can't do Group 3 (T.4)");
    uchar spd = (disfr[2] >> 2) & 0xf;
    dcsframe[2] = 0x70;			/* set to V.29 7200 bit/s; no 2d coding; clear "fine" bit */
    uchar n = (disfr[3] >> 1) & 7;	/* DIS bits 21-23 */
    if (options & opt_H)
      { unless (disfr[2] & 0x02) giveup("Remote fax can't do 200 dpi; try -l");
	dcsframe[2] |= 0x02;		/* ask for high density */
	n += 8;
      }
    n = dcstranstab[n];			/* translate to DCS equivalent */
    dcsframe[3] = n << 1;		/* set A4 1728 dots per scan line; set scantime bits; clear extend bit */
    scanbits = scanbitstab[n];		/* min. scan time, in bits */
    infomsg("resolution=%c; speeds=%02x; scanbits=%d", (options & opt_H) ? 'H' : 'L', spd, scanbits);
    unless (spd & 0x8) giveup("Remote fax can't do V.29");
  }

static void sendtraining()
  { int ntries = 0;
    do
      { sendframe(identframe, 21, false);	    /* send TSI */
	sendframe(dcsframe, 4, true);		    /* send DCS */
	if (options & opt_v) fprintf(stderr, ">>> TCF\n");
	setstate(TX_DOC_STATE);
	for (int j = 0; j < 10800; j++) putbit(0);  /* TCF, 1.5 sec @ 7200 bps */
	getmessage();
	ntries++;
      }
    until (frame[0] == CFR || ntries >= 3);
    unless (frame[0] == CFR) giveup("Remote fax training failed");
  }

static void receivedoc()
  { makeident(CSI);
    getdcs(true);
    bool ok = gettraining();
    int ntries = 0;
    until (ok || ntries >= 3)
      { getdcs(false);
	ok = gettraining();
	ntries++;
      }
    unless (ok) giveup("Local fax training failed");
    sendframe(cfrframe, 1, true);
    bool more;
    do
      { setstate(RX_DOC_STATE);
	receivepage(pagecount+1);
	ntries = 0;
	do
	  { getmessage();
	    ntries++;
	  }
	until (frame[0] == EOP || frame[0] == MPS || ntries >= 3);
	unless (frame[0] == EOP || frame[0] == MPS) giveup("Remote fax has given up");
	more = (frame[0] == MPS);
	sendframe(mcfframe, 1, true);
	pagecount++;
      }
    while (more);
    getmessage();	/* should be DCN */	// ???
    infomsg("Success - received %d pages", pagecount);
  }

static void getdcs(bool first)
  { int ntries = 0;
    do
      { if (first)
	  { sendframe(identframe, 21, false);	/* send CSI */
	    sendframe(disframe, 4, true);	/* send DIS */
	  }
	else sendframe(fttframe, 1, true);	/* send FTT */
	getmessage();	/* try for DCS */
	ntries++;
      }
    until ((frame[0] == DCS && framelen >= 4) || frame[0] == DCN || ntries >= 6);
    unless (frame[0] == DCS && framelen >= 4) giveup("Failed to get a valid DCS frame");
    checkdcs(frame);
  }

static void checkdcs(uchar *dcsfr)
  { /* check DCS frame from remote sender */
    uchar spd = (dcsfr[2] >> 2) & 0xf;
    if (dcsfr[2] & 0x02) options |= opt_H;
    infomsg("resolution=%c; speeds=%02x; scanbits=%d", (options & opt_H) ? 'H' : 'L', spd, scanbits);
    unless (dcsfr[2] & 0x40) giveup("Remote fax can't do Group 3 (T.4)");
    unless (spd & 0x8) giveup("Remote fax can't do V.29");
  }

static bool gettraining()
  { setstate(RX_DOC_STATE);
    int totnz = 0, tot = 0;
    for (int j = 0; j < 13; j++)	/* spec says length +- 10%, so look for 13*720 not 15*720 */
      { int nz = 0;
	for (int k = 0; k < 720; k++) if (!getbit()) nz++;
	if (options & opt_v) fprintf(stderr, "%d ", nz);
	totnz += nz; tot += 720;
      }
    bool ok = (tot-totnz < 10);		/* tolerate 0.1% error */
    if (options & opt_v)
      { fprintf(stderr, "= %d out of %d\n", totnz, tot);
	fprintf(stderr, "<<< TCF %s\n", ok ? "ok" : "fail");
      }
    return ok;
  }

static void makeident(uchar cmd)
  { int len = strlen(MYNAME);
    int p = 0;
    identframe[p++] = cmd;  /* TSI or CSI */
    while (len > 0) identframe[p++] = shuffle[MYNAME[--len]];
    while (p < 21) identframe[p++] = 0x04; /* pad with spaces */
  }

static void getmessage()
  { setstate(RX_CTL_STATE);
    isfinal = true;
    msgendtime = samplecount + 4*SAMPLERATE;	/* reset timeout counter (4 secs in future) */
    nextval();					/* read 1st byte of preamble */
    do
      { getmsg();
	if (frame[0] == CSI || frame[0] == TSI) printident();
      }
    until (isfinal || frame[0] == TMO);
  }

static void printident()
  { char buf[21];
    int p = framelen, k = 0;
    while (p > 1 && frame[p-1] == 0x04) p--; /* delete spaces */
    while (p > 1 && k < 20) buf[k++] = shuffle[frame[--p]];
    buf[k++] = '\0';
    infomsg("Remote fax identifies as: %s", buf);
  }

static void getmsg()
  { uchar message[MAXMESSAGE];
    int msglen;
    bool ok = false;
    until (ok || rxval == HDLC_TIMEOUT)
      { until (rxval == HDLC_FLAG || rxval == HDLC_TIMEOUT) nextval();
	int nflags = 0;
	while (rxval == HDLC_FLAG) { nflags++; nextval(); }
	unless (isfinal && nflags < 10) /* preamble too short? */
	  { msglen = 0;
	    until (rxval == HDLC_FLAG || rxval == HDLC_TIMEOUT || msglen >= MAXMESSAGE)
	      { unless (rxval == HDLC_ABORT) message[msglen++] = rxval;
		nextval();
	      }
	    unless (rxval == HDLC_TIMEOUT)
	      { if (rxval != HDLC_FLAG)
		  msgerror("Message too long: %02x %02x %02x...", message[0], message[1], message[2]);
		else if (msglen < 5) /* ensure frame length .ge. 1 */
		  msgerror("Message too short");
		else unless (csumok(message, msglen))
		  msgerror("Checksum error");
		else unless (message[0] == 0xff)
		  msgerror("Got %02x after frame, exp ff", message[0]);
		else unless (message[1] == 0xc0 || message[1] == 0xc8)
		  msgerror("Got %02x after addr, exp c0 or c8", message[1]);
		else ok = true;
	      }
	  }
      }
    if (ok)
      { framelen = msglen-4;	/* length excludes addr, control, checksum */
	memcpy(frame, &message[2], framelen);
	isfinal = message[1] & 8;   /* final frame? */
      }
    else
      { frame[0] = TMO;		/* fake "timeout" frame */
	framelen = 1;
	isfinal = true;
      }
    printframe("<<<", frame, framelen);
  }

static void nextval()
  { rxval = (after(samplecount, msgendtime)) ? HDLC_TIMEOUT : getsync();
  }

static void msgerror(char *msg, word p1, word p2, word p3)
  { if (options & opt_v)
      { fprintf(stderr, "*** "); fprintf(stderr, msg, p1, p2, p3); putc('\n', stderr);
      }
  }

static void sendframe(uchar *fr, int frlen, bool final)
  { setstate(TX_CTL_STATE);
    printframe(">>>", fr, frlen);
    uchar message[MAXMESSAGE];
    message[0] = 0xff; message[1] = final ? 0xc8 : 0xc0;
    memcpy(&message[2], fr, frlen);
    ushort csum = computecsum(message, frlen+2);
    message[frlen+2] = (csum >> 8) ^ 0xff; message[frlen+3] = (csum & 0xff) ^ 0xff;
    unless (csumok(message, frlen+4)) giveup("Bug! Tx checksum");
    putsync(HDLC_FLAG); putsync(HDLC_FLAG);
    for (int i=0; i < frlen+4; i++) putsync(message[i]);
    putsync(HDLC_FLAG);
  }

static void printframe(char *io, uchar *fr, int frlen)
  { if (options & opt_v)
      { fprintf(stderr, "%s %s:", io, frametype(fr[0]));
	for (int i=0; i < frlen; i++) fprintf(stderr, " %02x", fr[i]);
	putc('\n', stderr);
      }
  }

static char *frametype(uchar x)
  { switch (x)
      { default:    return "???";
	case DIS:   return "DIS";
	case CSI:   return "CSI";
	case NSF:   return "NSF";
	case CFR:   return "CFR";
	case FTT:   return "FTT";
	case MCF:   return "MCF";
	case RTN:   return "RTN";
	case RTP:   return "RTP";
	case DCS:   return "DCS";
	case TSI:   return "TSI";
	case DCN:   return "DCN";
	case XCN:   return "XCN";
	case MPS:   return "MPS";
	case EOP:   return "EOP";
	case TMO:   return "TMO";
      }
  }

static bool csumok(uchar *msg, int len)
  { ushort csum = computecsum(msg, len);
    return (csum == 0x1d0f);
  }

static ushort computecsum(uchar *msg, int len)
  { /* CCITT V.41 crc (sort of) */
    ushort reg = 0xffff;
    while (len-- > 0)
      { uchar x = *(msg++);
	for (int j=0; j < 8; j++)
	  { uchar bit = (reg >> 15) ^ (x >> 7);
	    reg <<= 1; x <<= 1;
	    if (bit) reg ^= 0x1021;
	  }
      }
    return reg;
  }

static void setstate(int st)
  { unless (st == state)
      { switch (st)
	  { case RX_CTL_STATE:
		flushoutput(); discardinput();			/* flush Tx before switching to Rx */
		initrx_fsk(V21o);
		break;

	    case TX_CTL_STATE:
		if (state == TX_DOC_STATE) sendpause(0.075);	/* pause before switching from TX_DOC to TX_CTL */
		inittx_fsk(V21a);
		for (int i=0; i < 40; i++) putsync(HDLC_FLAG);	/* send HDLC preamble */
		break;

	    case RX_DOC_STATE:
		/* old state is tx_ctl or rx_ctl */
		if (state == TX_CTL_STATE) { flushoutput(); discardinput(); }
		initrx_v29();
		break;

	    case TX_DOC_STATE:
		sendpause(0.075);	/* pause before switching from anything to TX_DOC */
		inittx_v29();
		break;
	  }
	state = st;
      }
  }



⌨️ 快捷键说明

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