Added first try of a HDLC decoder.
Added logging to v21_softmodem.
This commit is contained in:
parent
21da018e86
commit
4ce1ba9b68
|
@ -3,7 +3,8 @@ CFLAGS=-O2 -g -Wall -pedantic -I../include
|
||||||
|
|
||||||
MODULES = send_to_audio.o pulsegen.o sinegen.o replicate.o \
|
MODULES = send_to_audio.o pulsegen.o sinegen.o replicate.o \
|
||||||
scrambler.o modulator-V29.o fsk_demod.o fsk_mod.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 =
|
HELPERS =
|
||||||
|
|
||||||
|
|
|
@ -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
58
test.c
|
@ -48,6 +48,7 @@ int rateconvert_construct(ifax_modp self, va_list args);
|
||||||
int fskdemod_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 fskmod_construct(ifax_modp self, va_list args);
|
||||||
int decode_serial_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 encode_serial_construct(ifax_modp self, va_list args);
|
||||||
int debug_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_FSKMOD;
|
||||||
ifax_module_id IFAX_DECODE_SERIAL;
|
ifax_module_id IFAX_DECODE_SERIAL;
|
||||||
ifax_module_id IFAX_ENCODE_SERIAL;
|
ifax_module_id IFAX_ENCODE_SERIAL;
|
||||||
|
ifax_module_id IFAX_DECODE_HDLC;
|
||||||
ifax_module_id IFAX_DEBUG;
|
ifax_module_id IFAX_DEBUG;
|
||||||
|
|
||||||
void setup_all_modules(void)
|
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_FSKMOD = ifax_register_module_class("FSK modulator",fskmod_construct);
|
||||||
IFAX_DECODE_SERIAL= ifax_register_module_class("Serializer",decode_serial_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_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_SCRAMBLER = ifax_register_module_class("Bitstream scrambler",scrambler_construct);
|
||||||
IFAX_MODULATORV29 = ifax_register_module_class("V.29 Modulator",modulator_V29_construct);
|
IFAX_MODULATORV29 = ifax_register_module_class("V.29 Modulator",modulator_V29_construct);
|
||||||
IFAX_RATECONVERT = ifax_register_module_class("Sample-rate converter",rateconvert_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);
|
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)
|
void main(int argc,char **argv)
|
||||||
{
|
{
|
||||||
|
@ -199,5 +254,6 @@ void main(int argc,char **argv)
|
||||||
|
|
||||||
/* transmit_carrier(); */
|
/* transmit_carrier(); */
|
||||||
/* test_modulator_V29(); */
|
/* test_modulator_V29(); */
|
||||||
test_scrambler();
|
// test_scrambler();
|
||||||
|
test_hdlc();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
@ -86,7 +87,7 @@ enum MODEM_MODE { ORIGINATE, ANSWER };
|
||||||
|
|
||||||
/* The actual "modem" code.
|
/* 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.
|
/* module handles for all used modules.
|
||||||
*/
|
*/
|
||||||
|
@ -174,6 +175,9 @@ static void test_v21(enum MODEM_MODE direction)
|
||||||
/* Read data from isdn4linux.
|
/* Read data from isdn4linux.
|
||||||
*/
|
*/
|
||||||
IsdnReadAudio(isdnhandle,&data,1);
|
IsdnReadAudio(isdnhandle,&data,1);
|
||||||
|
/* Log data if requested.
|
||||||
|
*/
|
||||||
|
if (outfd!=-1) write(outfd,&data,1);
|
||||||
|
|
||||||
/* Send back a steady 0
|
/* Send back a steady 0
|
||||||
*/
|
*/
|
||||||
|
@ -223,6 +227,9 @@ static void test_v21(enum MODEM_MODE direction)
|
||||||
/* Read data from isdn4linux.
|
/* Read data from isdn4linux.
|
||||||
*/
|
*/
|
||||||
IsdnReadAudio(isdnhandle,&data,1);
|
IsdnReadAudio(isdnhandle,&data,1);
|
||||||
|
/* Log data if requested.
|
||||||
|
*/
|
||||||
|
if (outfd!=-1) write(outfd,&data,1);
|
||||||
|
|
||||||
/* Send it to the demodulator.
|
/* Send it to the demodulator.
|
||||||
*/
|
*/
|
||||||
|
@ -312,7 +319,10 @@ void answer_isdn(void)
|
||||||
*/
|
*/
|
||||||
void usage(char *prgnam)
|
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.
|
/* Main program. Get the arguments and set everything up.
|
||||||
|
@ -331,6 +341,7 @@ void main(int argc,char **argv)
|
||||||
char *isdndevname="/dev/ttyI1";
|
char *isdndevname="/dev/ttyI1";
|
||||||
char *numbertodial=NULL;
|
char *numbertodial=NULL;
|
||||||
char *sourcemsn=NULL;
|
char *sourcemsn=NULL;
|
||||||
|
int outdata=-1;
|
||||||
|
|
||||||
/* Register all the modules.
|
/* Register all the modules.
|
||||||
*/
|
*/
|
||||||
|
@ -338,7 +349,7 @@ void main(int argc,char **argv)
|
||||||
|
|
||||||
/* Get all options from the commandline.
|
/* 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)
|
switch(optchr)
|
||||||
{
|
{
|
||||||
|
@ -358,6 +369,11 @@ void main(int argc,char **argv)
|
||||||
*/
|
*/
|
||||||
numbertodial=optarg;
|
numbertodial=optarg;
|
||||||
break;
|
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();
|
answer_isdn();
|
||||||
/* Go to transfer mode.
|
/* Go to transfer mode.
|
||||||
*/
|
*/
|
||||||
test_v21(ANSWER);
|
test_v21(ANSWER,outdata);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -403,11 +419,14 @@ void main(int argc,char **argv)
|
||||||
dial_isdn(numbertodial);
|
dial_isdn(numbertodial);
|
||||||
/* Go to transfer mode.
|
/* Go to transfer mode.
|
||||||
*/
|
*/
|
||||||
test_v21(ORIGINATE);
|
test_v21(ORIGINATE,outdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Clean up and exit.
|
/* Clean up and exit.
|
||||||
*/
|
*/
|
||||||
|
if (outdata!=-1) {
|
||||||
|
close(outdata);
|
||||||
|
}
|
||||||
close(isdnhandle);
|
close(isdnhandle);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue