Added first try of a HDLC decoder.

Added logging to v21_softmodem.
This commit is contained in:
Andreas Beck 1998-12-11 00:31:53 +00:00
parent 21da018e86
commit 4ce1ba9b68
4 changed files with 231 additions and 7 deletions

View File

@ -3,7 +3,8 @@ CFLAGS=-O2 -g -Wall -pedantic -I../include
MODULES = send_to_audio.o pulsegen.o sinegen.o replicate.o \
scrambler.o modulator-V29.o fsk_demod.o fsk_mod.o \
decode_serial.o encode_serial.o debug.o rateconvert.o
decode_serial.o encode_serial.o debug.o rateconvert.o \
decode_hdlc.o
HELPERS =

148
modules/decode_hdlc.c Normal file
View File

@ -0,0 +1,148 @@
/* $Id$
******************************************************************************
Fax program for ISDN.
Decoder for hdlc data input. Expects a datastream of alternating
0/1,confidence bytes at SAMPLES_PER_SECOND.
Outputs decoded bytes that came in without any error.
Automatically locks onto the start flag and undoes bit stuffing.
Copyright (C) 1998 Andreas Beck [becka@ggi-project.org]
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************
*/
#include <time.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/times.h>
#include <ifax/ifax.h>
#define HDLC_FLAG (0x7e)
#define HDLC_STUFFMASK (0x3f)
#define HDLC_STUFF (0x3e)
typedef struct {
int baud;
int lastsamp;
int bitnum;
int sampcount;
int syncbitcnt;
int bits;
int have_stuffed;
} decode_hdlc_private;
/* Free the private data
*/
void decode_hdlc_destroy(ifax_modp self)
{
decode_hdlc_private *priv=(decode_hdlc_private *)self->private;
free(self->private);
return;
}
int decode_hdlc_command(ifax_modp self,int cmd,va_list cmds)
{
return 0; /* Not yet used. */
}
int decode_hdlc_handle(ifax_modp self, void *data, size_t length)
{
char *dat=data;
int currbit,currconf;
int x,result,handled,parity;
char hlpres;
decode_hdlc_private *priv=(decode_hdlc_private *)self->private;
handled=0;
while(length--) {
currbit =*dat++;
currconf=*dat++;
priv->sampcount++;
// printf("%d,%d\n",currbit,currconf);
if (currconf<10) continue;
if (priv->lastsamp!=currbit) {
// printf("synchronizing due to %d->%d at %d\n",priv->lastsamp,currbit,priv->sampcount);
priv->lastsamp=currbit;
priv->sampcount=-SAMPLES_PER_SECOND/2/priv->baud;
priv->bitnum=0;
} else
if ( priv->sampcount >= priv->bitnum*
SAMPLES_PER_SECOND/priv->baud)
{
// printf("Bit %d(%d) is %d\n",priv->syncbitcnt,priv->bitnum,currbit);
priv->bits<<=1;
priv->bits|=!!currbit;
priv->syncbitcnt++;
if ((priv->bits&0xff)==HDLC_FLAG)
{
printf("FLAG !\n");
priv->syncbitcnt=0;
} else if (!priv->have_stuffed &&(priv->bits&HDLC_STUFFMASK)==HDLC_STUFF)
{
printf("Stuff !\n");
priv->bits>>=1;
priv->syncbitcnt--;
priv->have_stuffed=1;
} else if ((priv->syncbitcnt&7)==0)
{
priv->have_stuffed=0;
printf("HDLC %x\n",priv->bits&0xff);
}
priv->bitnum++;
}
handled++;
}
return handled;
}
int decode_hdlc_construct(ifax_modp self,va_list args)
{
decode_hdlc_private *priv;
char *encode;
if (NULL==(priv=self->private=malloc(sizeof(decode_hdlc_private))))
return 1;
self->destroy =decode_hdlc_destroy;
self->handle_input =decode_hdlc_handle;
self->command =decode_hdlc_command;
priv->baud=va_arg(args,int);
priv->bitnum=-1; /* Init to "wait for sync" */
priv->lastsamp=2; /* Make sure we init */
priv->syncbitcnt=0;
priv->bits=0;
priv->have_stuffed=0;
return 0;
}

58
test.c
View File

@ -48,6 +48,7 @@ int rateconvert_construct(ifax_modp self, va_list args);
int fskdemod_construct(ifax_modp self, va_list args);
int fskmod_construct(ifax_modp self, va_list args);
int decode_serial_construct(ifax_modp self, va_list args);
int decode_hdlc_construct(ifax_modp self, va_list args);
int encode_serial_construct(ifax_modp self, va_list args);
int debug_construct(ifax_modp self, va_list args);
@ -66,6 +67,7 @@ ifax_module_id IFAX_FSKDEMOD;
ifax_module_id IFAX_FSKMOD;
ifax_module_id IFAX_DECODE_SERIAL;
ifax_module_id IFAX_ENCODE_SERIAL;
ifax_module_id IFAX_DECODE_HDLC;
ifax_module_id IFAX_DEBUG;
void setup_all_modules(void)
@ -78,6 +80,7 @@ void setup_all_modules(void)
IFAX_FSKMOD = ifax_register_module_class("FSK modulator",fskmod_construct);
IFAX_DECODE_SERIAL= ifax_register_module_class("Serializer",decode_serial_construct);
IFAX_ENCODE_SERIAL= ifax_register_module_class("Serial encoder",encode_serial_construct);
IFAX_DECODE_HDLC = ifax_register_module_class("HDLC decoder",decode_hdlc_construct);
IFAX_SCRAMBLER = ifax_register_module_class("Bitstream scrambler",scrambler_construct);
IFAX_MODULATORV29 = ifax_register_module_class("V.29 Modulator",modulator_V29_construct);
IFAX_RATECONVERT = ifax_register_module_class("Sample-rate converter",rateconvert_construct);
@ -192,6 +195,58 @@ void test_scrambler(void)
ifax_handle_input(scrambler,source,200);
}
/* HDLC testing code
*/
static void test_hdlc(void)
{
/* module handles for all used modules.
*/
ifax_modp fskd,totty,dehdlc;
/* helper for data in-/output
*/
unsigned char data;
#if 0
ifax_modp toaudio,debug,replicate;
/* debugger */
debug=ifax_create_module(IFAX_DEBUG,1);
/* Replicate the incoming signal. */
replicate=ifax_create_module(IFAX_REPLICATE);
// ifax_command(replicate,CMD_REPLICATE_ADD,toisdn);
#endif
/* Now for the receiver. When all is decoded, the text is sent
* to the outputhandle.
*/
totty=ifax_create_module(IFAX_TOAUDIO, write, 1/*outputhandle*/);
/* The deserializer synchronizes on the startbits and decodes
* from the 0/1 stream from the demodulator to the bytes.
* Its output is sent to the totty module. Seee above.
*/
dehdlc=ifax_create_module(IFAX_DECODE_HDLC,300);
dehdlc->sendto=totty;
/* The FSK demodulator. Takes the aLaw input stream and sends the
* decoded version to the deserializer. See above.
*/
fskd=ifax_create_module(IFAX_FSKDEMOD,1650,1850,300);
fskd->sendto=dehdlc;
/* Run until explicitly terminated.
*/
while(1) {
if (read(0,&data,1)!=1) break;
/* Send it to the demodulator.
*/
ifax_handle_input(fskd,&data,1);
}
}
void main(int argc,char **argv)
{
@ -199,5 +254,6 @@ void main(int argc,char **argv)
/* transmit_carrier(); */
/* test_modulator_V29(); */
test_scrambler();
// test_scrambler();
test_hdlc();
}

View File

@ -29,6 +29,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
@ -86,7 +87,7 @@ enum MODEM_MODE { ORIGINATE, ANSWER };
/* The actual "modem" code.
*/
static void test_v21(enum MODEM_MODE direction)
static void test_v21(enum MODEM_MODE direction,int outfd)
{
/* module handles for all used modules.
*/
@ -174,6 +175,9 @@ static void test_v21(enum MODEM_MODE direction)
/* Read data from isdn4linux.
*/
IsdnReadAudio(isdnhandle,&data,1);
/* Log data if requested.
*/
if (outfd!=-1) write(outfd,&data,1);
/* Send back a steady 0
*/
@ -223,6 +227,9 @@ static void test_v21(enum MODEM_MODE direction)
/* Read data from isdn4linux.
*/
IsdnReadAudio(isdnhandle,&data,1);
/* Log data if requested.
*/
if (outfd!=-1) write(outfd,&data,1);
/* Send it to the demodulator.
*/
@ -312,7 +319,10 @@ void answer_isdn(void)
*/
void usage(char *prgnam)
{
printf("Usage: %s [-i isdndevice] -m MSN\n",prgnam);
printf("Usage: %s [-i isdndevice]\n"
" -m MSN \n"
" [-d number|'answer']\n"
" [-l logfile]\n",prgnam);
}
/* Main program. Get the arguments and set everything up.
@ -331,6 +341,7 @@ void main(int argc,char **argv)
char *isdndevname="/dev/ttyI1";
char *numbertodial=NULL;
char *sourcemsn=NULL;
int outdata=-1;
/* Register all the modules.
*/
@ -338,7 +349,7 @@ void main(int argc,char **argv)
/* Get all options from the commandline.
*/
while(EOF!=(optchr=getopt(argc,argv,"i:m:d:")))
while(EOF!=(optchr=getopt(argc,argv,"i:m:d:l:")))
{
switch(optchr)
{
@ -358,6 +369,11 @@ void main(int argc,char **argv)
*/
numbertodial=optarg;
break;
case 'l':
/* The logfile name.
*/
outdata=open(optarg,O_WRONLY|O_CREAT|O_TRUNC,0644);
break;
}
}
@ -394,7 +410,7 @@ void main(int argc,char **argv)
answer_isdn();
/* Go to transfer mode.
*/
test_v21(ANSWER);
test_v21(ANSWER,outdata);
}
else
{
@ -403,11 +419,14 @@ void main(int argc,char **argv)
dial_isdn(numbertodial);
/* Go to transfer mode.
*/
test_v21(ORIGINATE);
test_v21(ORIGINATE,outdata);
}
/* Clean up and exit.
*/
if (outdata!=-1) {
close(outdata);
}
close(isdnhandle);
}