#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <dos.h>
#include <stdlib.h>
#include <math.h>
int pork(int l);
void set8250 ();
void set8253();
void shob();
void frame_sync(char gin);
/* This copy of MDTWIDR is modified to use Com1 thru COM4. */
/* Only Com1, Com2 and Com3 are tested and working. */
/* Com4 has not been tested, but should work just the same. */
/* Output of intercepted data is now supported using the same */
/* Com port as the incoming data slicer bitstream. */
/* */
/* Much of this code has been lifted directly from the Trunker */
/* source code that is floating around the net. Why reinvent the */
/* wheel? Many thanks to the authors of Trunker for all the code */
/* I ripped off. */
/* */
/* */
/* This program supports command line switches as follows: */
/* */
/* /OUT - enables output of intercepts on the Com port */
/* /COM:1 - selects Com1 for input from data slicer (default) */
/* /COM:2 - selects Com2 for input from data slicer */
/* /COM:3 - selects Com3 for input from data slicer */
/* /COM:4 - selects Com4 for input from data slicer */
/* /RE - reverses input polarity */
/* /WS - selects wide-screen (Non-Hex) output to screen */
/* (default is Hex-Narrow output) */
/* /WF - selects wide-file (Non-Hex) output to data file */
/* (default is Hex-Narrow output) */
/* /H - display help screen */
/* /? - display help screen */
/* */
/* - Bonzo - */
/* */
/* */
/* Purpose of program: receive messages using the Motorola MDC4800 */
/* protocol and show them on the screen */
/* */
/* WARNING TO ALL : This program is free. Please distribute and modify*/
/* this program. I only request that you always include the source */
/* code so that others may also learn and add improvements. The */
/* status of this program at the time of the original release is : */
/* it doesn't have much in the way of a user interface or options but */
/* it should work if you follow the procedure in the text file. Don't */
/* expect any sort of support (you get what you pay for - nothing in */
/* this case). Finally, here's a special message to all of you who */
/* might have the urge to try to make money with this information: */
/* I know where you live. I will shave your pets and pour rubbing */
/* alcohol all over them (unless said pet happens to be a Rottweiler).*/
/* I will have sex with your wife while you off at work; on the rare */
/* occasions when you have sex with your wife she will in the throes */
/* of passion cry not your name but mine. I will sell drugs to the */
/* demented spawn you refer to as your children. And if that's not */
/* enough for you let a thousand lawyers from motorola descend on you */
/* and pound your fat rear end so far into the ground that it finally */
/* sees daylight again somewhere in Australia. */
/* */
/* */
/* General tidbits (a few of those "Why were things done this way */
/* questions). */
/* 1. Why is captured data kept in an array and only written to a */
/* disk file at the very end? Because disk access seems unreliable */
/* when so much time is taken up by the background interrupt service */
/* routine. */
/* 2. Why is the array storing this so small? Because yours truly was */
/* too damn lazy to use a pointer and allocate a huge chunk of memory.*/
/* (Hint for those of you who would like to improve this. */
/*--------------------------------------------------------------------*/
/* global variables */
static double baudrate=9600.0;/* baud rate of data link output */
static int lassie=0; /* bring help indicator */
int nuline=1;
int lc=0;
char fob[30000];/* output buffer for captured data to be sent to disk */
int foblen=29900;
int fobp=0; /* pointer to current position in array fob */
char ob[1000]; /* output buffer for packet before being sent to screen */
int obp=0; /* pointer to current position in array ob */
static unsigned int buflen= 15000; /* length of data buffer */
static volatile unsigned int cpstn = 0; /* current position in buffer */
static unsigned int fdata[15001] ; /* frequency data array */
void interrupt (*oldfuncc) (); /* vector to old com port interrupt */
static char temp[100];
static int sport;
static int irqv = 0x0c;
static int wscreen = 0;
static int wfile = 0;
static int comout = 0;
static int comport;
static int comport8;
static int comport9;
static int comporta;
static int comportb;
static int comportc;
static int comportd;
static int comporte;
/**********************************************************************/
/* this is serial com port interrupt */
/* we assume here that it only gets called when one of the status */
/* lines on the serial port changes (that's all you have hooked up). */
/* All this handler does is read the system timer (which increments */
/* every 840 nanoseconds) and stores it in the fdata array. The MSB */
/* is set to indicate whether the status line is zero. In this way */
/* the fdata array is continuously updated with the appropriate the */
/* length and polarity of each data pulse for further processing by */
/* the main program. */
void interrupt comint()
{
static unsigned int d1,d2,ltick,tick,dtick;
/* the system timer is a 16 bit counter whose value counts down */
/* from 65535 to zero and repeats ad nauseum. For those who really */
/* care, every time the count reaches zero the system timer */
/* interrupt is called (remember that thing that gets called every */
/* 55 milliseconds and does housekeeping such as checking the */
/* keyboard. */
outportb (0x43, 0x00); /* latch counter until we read it */
d1 = inportb (0x40); /* get low count */
d2 = inportb (0x40); /* get high count */
/* get difference between current, last counter reading */
tick = (d2 << 8) + d1;
dtick = ltick - tick;
ltick = tick;
/* Corrected per arron5@geocities.com 02/08/97 */
if ((inportb(comporte) & 0xF0) > 0) dtick = dtick | 0x8000;
else dtick = dtick & 0x3fff;
fdata[cpstn] = dtick; /* put freq in fdata array */
cpstn ++; /* increment data buffer pointer */
if (cpstn>buflen) cpstn=0; /* make sure cpstn doesnt leave array */
d1 = inportb (comporta); /* clear IIR */
d1 = inportb (comportd); /* clear LSR */
d1 = inportb (comporte); /* clear MSR */
d1 = inportb (comport8); /* clear RX */
outportb (0x20, 0x20); /* this is the END OF INTERRUPT SIGNAL */
/* "... that's all folks!!!!" */
}
void set8250 (double bps) /* sets up the 8250 UART */
{
static unsigned int t,dv,tp;
dv = (int) 1843200.0/(16.0*bps);
/* how to configure your serial port setup: */
/* do you want two stop bits? then make sure you set bit 2 in tp */
/* do you want a parity bit generated? then set bit bit 3 in tp */
/* do you want even parity? then set bit 4 in tp */
/* do you want an 8 bit word length? set bits 0 and 1 in tp */
/* do you want an 7 bit word length? set bit 1 in tp */
tp = 0x80 + 0x02 + 0x01;
outportb (comport+3, tp); /* set line control register */
outport (comport , dv); /* output brg divisor latch */
tp = tp & 0x7f; /* switch out brg divisor reg */
outportb (comport+3, tp);
outportb (comport9, 0x08); /* enable MODEM STATUS INTERRUPT */
outportb (comportc, 0x0a); /* push up RTS, DOWN DTR */
t = inportb(comportd); /* clear LSR */
t = inportb(comport8); /* clear RX */
t = inportb(comporte); /* clear MSR */
t = inportb(comporta); /* clear IID */
t = inportb(comporta); /* clear IID - again to make sure */
}
void set8253() /* set up the 8253 timer chip */
{ /* NOTE: ctr zero, the one we are using*/
/* is incremented every 840nSec, is */
/* main system time keeper for dos */
outportb (0x43, 0x34); /* set ctr 0 to mode 2, binary */
outportb (0x40, 0x00); /* this gives us the max count */
outportb (0x40, 0x00);
}
/************************************************************************/
/* send_char */
/* */
/* This routine sends a character out on the serial port TxD line. */
/* It makes sure the previous character has been completely sent and */
/* then sends puts the current character into the transmit register. */
/************************************************************************/
void send_char(int c)
{
/* wait for transmit reg to empty */
while ( (inportb(comport+0x05) & 0x20) == 0x00);
/* send character */
outportb(comport,c);
}
int pork(int l)
{
static int s=0,sl=0x0000,t1,asp=0,ll,k,v,b,tap,synd=0,nsy;
static char line[200]; /* array used to format 112 bit data chunks */
static int lc=0; /* pointer to position in array line */
if (l == -1)
{
/**********************************************************************/
/* Wide Screen Output? */
/**********************************************************************/
if (wscreen == 0)
{
/* printf (" %2i\n",asp); */
}
sl = 0x0000;
s = 0;
synd = 0;
if ((asp <12) && (lc > 50))
{
ll = 12 - asp;
for (ll=0; ll<6; ll++)
{
v = 0;
for (k=7; k>=0; k--)
{
b = line[ (ll<<3) +k ];
v = v << 1;
if ( b == 49) v++;
}
ob[obp] = (char) v;
if (obp < 999) obp++;
}
}
lc = 0;
tap = asp;
asp = 0;
return(tap);
}
else
{
s++;
if (s==1)
{
line[lc] = (char) l;
lc++;
}
/* update sliding buffer */
sl = sl << 1;
sl = sl & 0x7fff;
if (l == 49) sl++;
if (s >1)
{
s = 0;
if ((sl & 0x2000) > 0) t1 = 1; else t1 = 0;
if ((sl & 0x0800) > 0) t1^=1;
if ((sl & 0x0020) > 0) t1^=1;
if ((sl & 0x0002) > 0) t1^=1;
if ((sl & 0x0001) > 0) t1^=1;
/* attempt to identify, correct certain erroneous bits */
synd = synd << 1;
if (t1 == 0)
{
asp++;
synd++;
}
nsy = 0;
/* Corrected per arron5@geocities.com 02/08/97 */
if ( (synd & 0x0001) > 0) nsy++;
if ( (synd & 0x0002) > 0) nsy++;
if ( (synd & 0x0010) > 0) nsy++;
if ( (synd & 0x0040) > 0) nsy++;
/* assume bit is correctable */
if ( nsy >= 3)
{
printf ("*");
nuline=1;
synd = synd ^ 0x53;
line[lc - 7] ^= 0x01;
}
}
}
return(0);
}
void shob()
{
int i1,i2,j1,j2,k1;
if (nuline==1)
{
printf("\n");
nuline=0;
}
/* update file output buffer */
i1 = obp / 18;
if ( (obp-(i1*18)) > 0) i1++;
fob[fobp] = (char) (i1 & 0xff);
if (fobp < 29999) fobp++;
for (i2 = obp; i2<=(obp+20); i2++) ob[i2] = 0;
for (j1 = 0; j1 < i1; j1++)
{
for (j2 = 0; j2 < 18; j2++)
{
k1 = j2 + (j1*18);
/**********************************************************************/
/* Wide Screen Output? */
/**********************************************************************/
if (wscreen == 0)
{
printf("%02X ", ob[k1] & 0xff);
}
fob[fobp] = (char) (ob[k1] & 0xff);
if (fobp < 29999) fobp++;
}
/**********************************************************************/
/* Wide Screen Output? */
/**********************************************************************/
if (wscreen == 0)
{
printf (" ");
}
for (j2 = 0; j2 < 18; j2++)
{
k1 = j2 + (j1*18);
if (ob[k1] >=32) printf("%c",ob[k1]); else printf(".");
/**********************************************************************/
/* Copy each byte to the comport if requested */
/* but only if its decimal ascii equivalent is within the following */
/* printable ranges: */
/* */
/* 010 - 010 */
/* 013 - 013 */
/* 032 - 122 */
/* */
/* Otherwise, send a period. */
/* */
/**********************************************************************/
if (comout == 1)
{
if (ob[k1] == 10)
{
send_char(ob[k1]);
}
else
{
if (ob[k1] == 13)
{
send_char(ob[k1]);
}
else
{
if ((ob[k1] >= 32) && (ob[k1] <= 122)) send_char(ob[k1]);else send_char( (char) 46 );
}
}
}
}
/**********************************************************************/
/* Wide Screen Output? */
/**********************************************************************/
if (wscreen == 0)
{
printf("\n");
}
}
obp=0;
printf("\n");
printf("BUFFER: %3i percent full\n",(int)(fobp/299.0));
/**********************************************************************/
/* After sending data for this burst, send a carriage return/linefeed */
/* and then reset the com port for receiving the next data burst. */
/**********************************************************************/
if (comout == 1)
{
send_char( (char) 10 );
send_char( (char) 13 );
set8250(baudrate);
}
}
/**********************************************************************/
/* frame_sync */
/**********************************************************************/
/* this routine recieves the raw bit stream and tries to decode it */
/* the first step is frame synchronization - a particular 40 bit */
/* long sequence indicates the start of each data frame. Data frames */
/* are always 112 bits long. After each 112 bit chunk this routine */
/* tries to see if the message is finished (assumption - it's finished*/
/* if the 40 bit frame sync sequence is detected right after the end */
/* of the 112 bit data chunk). This routine also goes back to hunting */
/* for the frame sync when the routine processing the 112 bit data */
/* chunk decides there are too many errors (transmitter stopped or */
/* bit detection routine skipped or gained an extra bit). */
/* */
/* inputs are fed to this routine one bit at a time */
/* input : 48 - bit is a zero */
/* 49 - bit is a 1 */
void frame_sync(char gin)
{
static unsigned int s1=0,s2=0,s3=0,nm,j,t1,t2,t3,ns=0,st=0,n,m,l,chu=0,eef=0;
static char ta[200];
if (st == 1)
{
ta[ns] = gin;
ns++;
if (ns >= 112) /* process 112 bit chunk */
{
chu++;
ns = 0;
for (n= 0; n<16; n++)
{
for (m=0; m<7; m++)
{
l = n + (m<<4);
pork(ta[l]);
}
}
if (pork(-1) > 20) eef++; else eef=0;
if (eef > 1) /* if two consecutive excess error chunks - bye */
{
st = 0;
shob();
eef = 0;
}
/* else eef = 0; */
}
}
/* s1,s2,s3 represent a 40 bit long buffer */
s1 = (s1 << 1) & 0xff;
if ((s2 & 0x8000) > 0) s1++;
s2 = (s2 << 1);
if ((s3 & 0x8000) > 0) s2++;
s3 = (s3 << 1);
if (gin == 49) s3++;
/* xor with 40 bit long sync word */
t1 = s1 ^ 0x0007;
t2 = s2 ^ 0x092A;
t3 = s3 ^ 0x446F;
/* find how many bits match up */
/* currently : the frame sync indicates system id / idling / whatever */
/* inverted frame sync indicates message follows */
nm = 0;
for (j=0; j<16; j++)
{
if (t1 & 1) nm++;
if (t2 & 1) nm++;
if (t3 & 1) nm++;
t1 = t1 >> 1;
t2 = t2 >> 1;
t3 = t3 >> 1;
}
if (nm < 5)
{
st = 1;
ns = 0;
}
else if (nm > 35)
{
if (st==1)
{
shob();
}
st = 0;
ns = 0;
}
}
/************************************************************************/
/* DISPLAY HELP SCREEN
*/
/************************************************************************/
void help()
{
printf("\n MDTW1234 Revision B MDC4800 monitoring program\n");
printf(" Command line argument summary\n\n");
printf(" /COM:y - set y = 1,2,3,4 to set com port you want to use.\n");
printf(" /RE - reverse input polarity of incoming data.\n");
printf(" /WS - remove hex display from screen output and use\n");
printf(" the additional room for more character output.\n");
printf(" /WF - remove hex display and newline characters from the output\n");
printf(" file making it more suitable for keyword searches.\n");
printf(" /H - produces this help screen.\n");
printf(" /? - ditto.\n");
printf("\nExample: MDTW1234 /COM:2 /WS /RE\n");
printf(" will use reversed input from COM2 and produce wide screen output.\n");
printf("\n Interface requirements: Hamcomm type data slicer circuit.\n");
printf("\n See README file for further details...\n\n");
printf(" press any key to continue...\n");
getch();
}
void main (int argc, char **argv)
{
unsigned int n,i=0,j,k,l,cw1=49,cw0=48;
FILE *out;
char s=48;
double pl,dt,exc=0.0,clk=0.0,xct;
for (n=1; n<argc; n++)
{
strcpy(temp,argv[n]);
strupr(temp);
j+=sscanf(temp,"/COM:%i",&sport);
if (temp[1] == 'O' && temp[2] == 'U' && temp[3] == 'T')
{
printf ("Intercept Output Enabled.\n");
comout = 1;
}
if (temp[1] == 'W' && temp[2] == 'S')
{
printf ("Wide Screen Output Selected.\n");
wscreen = 1;
}
if (temp[1] == 'W' && temp[2] == 'F')
{
printf ("Wide File Output Selected.\n");
wfile = 1;
}
if (temp[1] == 'R' && temp[2] == 'E')
{
printf ("Reverse Polarity.\n");
cw1 = 48;
cw0 = 49;
}
if (temp[1] == 'H') lassie=1;
if (temp[1] == '?') lassie=1;
}
if ( lassie == 1) help();
if (sport > 4) { sport = 4; }
if (sport < 1) { sport = 1; }
printf("Checking for data coming in on COM%i... \n",sport);
/* dt is the number of expected clock ticks per bit */
dt = 1.0/(4800.0*838.8e-9);
/* set up items related to serial port */
n = inportb (0x21);
if ( (sport == 1) | (sport == 3))
{
irqv = 0x0c;
oldfuncc = getvect(irqv); /* save COM Vector */
setvect (irqv, comint); /* Capture COM vector */
outportb(0x21, n & 0xef);
if (sport == 1) comport = 0x3f8; else comport = 0x3e8;
}
else
{
irqv = 0x0b;
oldfuncc = getvect(irqv); /* save COM Vector */
setvect (irqv, comint); /* Capture COM vector */
outportb(0x21, n & 0xf7);
if (sport == 2) comport = 0x2f8; else comport = 0x2e8;
}
/* set up comport offsets for other code */
comport8 = comport + 0x00;
comport9 = comport + 0x01;
comporta = comport + 0x02;
comportb = comport + 0x03;
comportc = comport + 0x04;
comportd = comport + 0x05;
comporte = comport + 0x06;
set8253(); /* set up 8253 timer chip */
set8250(baudrate); /* set up 8250 UART */
while ((kbhit() == 0) && (fobp<29900))
{
if (i != cpstn)
{
if ( ( fdata[i] & 0x8000) != 0) s = cw1; else s = cw0;
/* add in new number of cycles to clock */
clk += (fdata[i] & 0x7fff);
xct = exc + 0.5 * dt; /* exc is current boundary */
while ( clk >= xct )
{
frame_sync(s);
clk = clk - dt;
}
/* clk now holds new boundary position. update exc slowly... */
/* 0.005 sucks; 0.02 better; 0.06 mayber even better; 0.05 seems pretty good */
exc = exc + 0.020*(clk - exc);
i++;
if( i >buflen) i = 0;
}
}
outportb (0x21, n); /* disable IRQ interrupt */
setvect (irqv, oldfuncc); /* restore old COM Vector */
/* save captured data to disk file */
i = 0;
out = fopen("data.dat","wt");
if (out == NULL)
{
printf ("couldn't open output file.\n");
exit(1);
}
i = 0;
while ( (i < fobp) && (i < 29800))
{
j = ((int)fob[i] & 0xff);
i++;
for (k=0; k<j; k++)
{
/************************************************************************/
/* This produces Narrow File Output */
/************************************************************************/
if (wfile == 0)
{
for (l=0; l<18; l++)
{
fprintf(out,"%02X ",((int) fob[i + l]&0xff));
}
fprintf(out," ");
for (l=0; l<18; l++)
{
n = ((int)fob[i]&0xff);
i++;
if (n >=32) fprintf(out,"%c",n); else fprintf(out,".");
}
fprintf(out,"\n");
}
/************************************************************************/
/* This produces Wide File Output */
/************************************************************************/
if (wfile == 1)
{
for (l=0; l<18; l++)
{
n = ((int)fob[i]&0xff);
i++;
if (n >=32) fprintf(out,"%c",n); else fprintf(out,".");
}
}
}
/************************************************************************/
/* Extra linefeed here for narrow file output */
/************************************************************************/
if (wfile == 0)
{
fprintf(out,"\n");
}
}
fclose(out);
}
syntax highlighted by Code2HTML, v. 0.9.1