mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-13 08:13:22 +00:00
Change the fsk filter used in CID and TDD decode to an integer based implementation
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@78227 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -31,30 +31,39 @@
|
|||||||
|
|
||||||
#define NCOLA 0x4000
|
#define NCOLA 0x4000
|
||||||
|
|
||||||
|
/* new filter structure */
|
||||||
|
struct filter_struct {
|
||||||
|
|
||||||
|
int icoefs[8];
|
||||||
|
int ip;
|
||||||
|
int ixv[8];
|
||||||
|
int iyv[8];
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float spb; /*!< Samples / Bit */
|
|
||||||
int nbit; /*!< Number of Data Bits (5,7,8) */
|
int nbit; /*!< Number of Data Bits (5,7,8) */
|
||||||
float nstop; /*!< Number of Stop Bits 1,1.5,2 */
|
|
||||||
int parity; /*!< Parity 0=none 1=even 2=odd */
|
int parity; /*!< Parity 0=none 1=even 2=odd */
|
||||||
|
int instop; /*!< Number of Stop Bits */
|
||||||
int hdlc; /*!< Modo Packet */
|
int hdlc; /*!< Modo Packet */
|
||||||
float x0;
|
int xi0;
|
||||||
float x1;
|
int xi1;
|
||||||
float x2;
|
int xi2;
|
||||||
float cont;
|
|
||||||
int bw; /*!< Bandwidth */
|
int ispb;
|
||||||
double fmxv[8],fmyv[8]; /*!< filter stuff for M filter */
|
int icont;
|
||||||
int fmp; /*!< pointer for M filter */
|
int bw; /*!< Band Selector*/
|
||||||
double fsxv[8],fsyv[8]; /*!< filter stuff for S filter */
|
int f_mark_idx; /*!< Mark Frequency Index (f_M-500)/5 */
|
||||||
int fsp; /*!< pointer for S filter */
|
int f_space_idx; /*!< Space Frequency Index (f_S-500)/5 */
|
||||||
double flxv[8],flyv[8]; /*!< filter stuff for L filter */
|
|
||||||
int flp; /*!< pointer for L filter */
|
|
||||||
int f_mark_idx; /*!< Mark frequency index (f_M-500)/5 */
|
|
||||||
int f_space_idx; /*!< Space frequency index (f_S-500)/5 */
|
|
||||||
int state;
|
int state;
|
||||||
int pcola; /*!< Pointer to data queues */
|
|
||||||
float cola_in[NCOLA]; /*!< Queue of input samples */
|
int pllispb; /*!<Pll autosense */
|
||||||
float cola_filter[NCOLA]; /*!< Queue of samples after filters */
|
int pllids;
|
||||||
float cola_demod[NCOLA]; /*!< Queue of demodulated samples */
|
int pllispb2;
|
||||||
|
|
||||||
|
struct filter_struct mark_filter;
|
||||||
|
struct filter_struct space_filter;
|
||||||
|
struct filter_struct demod_filter;
|
||||||
|
|
||||||
} fsk_data;
|
} fsk_data;
|
||||||
|
|
||||||
/* \brief Retrieve a serial byte into outbyte.
|
/* \brief Retrieve a serial byte into outbyte.
|
||||||
@@ -65,7 +74,8 @@ typedef struct {
|
|||||||
\arg 0: Still looking for something...
|
\arg 0: Still looking for something...
|
||||||
\arg 1: An output byte was received and stored in outbyte
|
\arg 1: An output byte was received and stored in outbyte
|
||||||
\arg -1: An error occured in the transmission
|
\arg -1: An error occured in the transmission
|
||||||
He must be called with at least 80 bytes of buffer. */
|
This must be called with at least 80 bytes of buffer. */
|
||||||
int fsk_serial(fsk_data *fskd, short *buffer, int *len, int *outbyte);
|
int fsk_serial(fsk_data *fskd, short *buffer, int *len, int *outbyte);
|
||||||
|
int fskmodem_init(fsk_data *fskd);
|
||||||
|
|
||||||
#endif /* _ASTERISK_FSKMODEM_H */
|
#endif /* _ASTERISK_FSKMODEM_H */
|
||||||
|
@@ -134,17 +134,23 @@ struct callerid_state *callerid_new(int cid_signalling)
|
|||||||
struct callerid_state *cid;
|
struct callerid_state *cid;
|
||||||
|
|
||||||
if ((cid = ast_calloc(1, sizeof(*cid)))) {
|
if ((cid = ast_calloc(1, sizeof(*cid)))) {
|
||||||
cid->fskd.spb = 7.0; /* 1200 baud */
|
cid->fskd.ispb = 7; /* 1200 baud */
|
||||||
|
/* Set up for 1200 / 8000 freq *32 to allow ints */
|
||||||
|
cid->fskd.pllispb = (int)(8000 * 32 / 1200);
|
||||||
|
cid->fskd.pllids = cid->fskd.pllispb/32;
|
||||||
|
cid->fskd.pllispb2 = cid->fskd.pllispb/2;
|
||||||
|
|
||||||
|
cid->fskd.icont = 0; /* PLL REset */
|
||||||
/* cid->fskd.hdlc = 0; */ /* Async */
|
/* cid->fskd.hdlc = 0; */ /* Async */
|
||||||
cid->fskd.nbit = 8; /* 8 bits */
|
cid->fskd.nbit = 8; /* 8 bits */
|
||||||
cid->fskd.nstop = 1.0; /* 1 stop bit */
|
cid->fskd.instop = 1; /* 1 stop bit */
|
||||||
/* cid->fskd.paridad = 0; */ /* No parity */
|
/* cid->fskd.paridad = 0; */ /* No parity */
|
||||||
cid->fskd.bw = 1; /* Filter 800 Hz */
|
cid->fskd.bw = 1; /* Filter 800 Hz */
|
||||||
if (cid_signalling == 2) { /* v23 signalling */
|
if (cid_signalling == 2) { /* v23 signalling */
|
||||||
cid->fskd.f_mark_idx = 4; /* 1300 Hz */
|
cid->fskd.f_mark_idx = 4; /* 1300 Hz */
|
||||||
cid->fskd.f_space_idx = 5; /* 2100 Hz */
|
cid->fskd.f_space_idx = 5; /* 2100 Hz */
|
||||||
} else { /* Bell 202 signalling as default */
|
} else { /* Bell 202 signalling as default */
|
||||||
cid->fskd.f_mark_idx = 2; /* 1200 Hz */
|
cid->fskd.f_mark_idx = 2; /* 1200 Hz */
|
||||||
cid->fskd.f_space_idx = 3; /* 2200 Hz */
|
cid->fskd.f_space_idx = 3; /* 2200 Hz */
|
||||||
}
|
}
|
||||||
/* cid->fskd.pcola = 0; */ /* No clue */
|
/* cid->fskd.pcola = 0; */ /* No clue */
|
||||||
@@ -153,6 +159,8 @@ struct callerid_state *callerid_new(int cid_signalling)
|
|||||||
/* cid->fskd.state = 0; */
|
/* cid->fskd.state = 0; */
|
||||||
cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
|
cid->flags = CID_UNKNOWN_NAME | CID_UNKNOWN_NUMBER;
|
||||||
/* cid->pos = 0; */
|
/* cid->pos = 0; */
|
||||||
|
|
||||||
|
fskmodem_init(&cid->fskd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cid;
|
return cid;
|
||||||
|
324
main/fskmodem.c
324
main/fskmodem.c
@@ -46,17 +46,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
#define STATE_SEARCH_STARTBIT3 2
|
#define STATE_SEARCH_STARTBIT3 2
|
||||||
#define STATE_GET_BYTE 3
|
#define STATE_GET_BYTE 3
|
||||||
|
|
||||||
static inline float get_sample(short **buffer, int *len)
|
static inline int iget_sample(short **buffer, int *len)
|
||||||
{
|
{
|
||||||
float retval;
|
int retval;
|
||||||
retval = (float) **buffer / 256;
|
retval = (int) **buffer;
|
||||||
(*buffer)++;
|
(*buffer)++;
|
||||||
(*len)--;
|
(*len)--;
|
||||||
return retval;
|
return retval;
|
||||||
};
|
}
|
||||||
|
|
||||||
#define GET_SAMPLE get_sample(&buffer, len)
|
|
||||||
|
|
||||||
|
#define IGET_SAMPLE iget_sample(&buffer, len)
|
||||||
/*! \brief Coefficients for input filters
|
/*! \brief Coefficients for input filters
|
||||||
* Coefficients table, generated by program "mkfilter"
|
* Coefficients table, generated by program "mkfilter"
|
||||||
* mkfilter is part of the zapatatelephony.org distribution
|
* mkfilter is part of the zapatatelephony.org distribution
|
||||||
@@ -64,31 +63,20 @@ static inline float get_sample(short **buffer, int *len)
|
|||||||
* IDX_COEF = 0 => 1/GAIN
|
* IDX_COEF = 0 => 1/GAIN
|
||||||
* IDX_COEF = 1-6 => Coefficientes y[n]
|
* IDX_COEF = 1-6 => Coefficientes y[n]
|
||||||
*/
|
*/
|
||||||
static double coef_in[NF][NBW][8] = {
|
static double coef_in[NF][NBW][8]={
|
||||||
{
|
{ { 1.8229206611e-04,-7.8997325866e-01,2.2401819940e+00,-4.6751353581e+00,5.5080745712e+00,-5.0571565772e+00,2.6215820004e+00,0.0000000000e+00,
|
||||||
{ 1.8229206611e-04,-7.8997325866e-01,2.2401819940e+00,-4.6751353581e+00,5.5080745712e+00,-5.0571565772e+00,2.6215820004e+00,0.0000000000e+00, },
|
}, { 9.8532175289e-02,-5.6297236492e-02,3.3146713415e-01,-9.2239200436e-01,1.4844365184e+00,-2.0183258642e+00,2.0074154497e+00,0.0000000000e+00,
|
||||||
{ 9.8532175289e-02,-5.6297236492e-02,3.3146713415e-01,-9.2239200436e-01,1.4844365184e+00,-2.0183258642e+00,2.0074154497e+00,0.0000000000e+00, },
|
}, }, { { 1.8229206610e-04,-7.8997325866e-01,7.7191410839e-01,-2.8075643964e+00,1.6948618347e+00,-3.0367273700e+00,9.0333559408e-01,0.0000000000e+00,
|
||||||
},
|
}, { 9.8531161839e-02,-5.6297236492e-02,1.1421579050e-01,-4.8122536483e-01,4.0121072432e-01,-7.4834487567e-01,6.9170822332e-01,0.0000000000e+00,
|
||||||
{
|
}, }, { { 1.8229206611e-04,-7.8997325866e-01,2.9003821430e+00,-6.1082779024e+00,7.7169345751e+00,-6.6075999680e+00,3.3941838836e+00,0.0000000000e+00,
|
||||||
{ 1.8229206610e-04,-7.8997325866e-01,7.7191410839e-01,-2.8075643964e+00,1.6948618347e+00,-3.0367273700e+00,9.0333559408e-01,0.0000000000e+00, } ,
|
}, { 9.8539686961e-02,-5.6297236492e-02,4.2915323820e-01,-1.2609358633e+00,2.2399213250e+00,-2.9928879142e+00,2.5990173742e+00,0.0000000000e+00,
|
||||||
{ 9.8531161839e-02,-5.6297236492e-02,1.1421579050e-01,-4.8122536483e-01,4.0121072432e-01,-7.4834487567e-01,6.9170822332e-01,0.0000000000e+00, },
|
}, }, { { 1.8229206610e-04,-7.8997325866e-01,-7.7191410839e-01,-2.8075643964e+00,-1.6948618347e+00,-3.0367273700e+00,-9.0333559408e-01,0.0000000000e+00,
|
||||||
},
|
}, { 9.8531161839e-02,-5.6297236492e-02,-1.1421579050e-01,-4.8122536483e-01,-4.0121072432e-01,-7.4834487567e-01,-6.9170822332e-01,0.0000000000e+00,
|
||||||
{
|
}, }, { { 1.8229206611e-04,-7.8997325866e-01,2.5782298908e+00,-5.3629717478e+00,6.5890882172e+00,-5.8012914776e+00,3.0171839130e+00,0.0000000000e+00,
|
||||||
{ 1.8229206611e-04,-7.8997325866e-01,2.9003821430e+00,-6.1082779024e+00,7.7169345751e+00,-6.6075999680e+00,3.3941838836e+00,0.0000000000e+00, },
|
}, { 9.8534230718e-02,-5.6297236492e-02,3.8148618075e-01,-1.0848760410e+00,1.8441165168e+00,-2.4860666655e+00,2.3103384142e+00,0.0000000000e+00,
|
||||||
{ 9.8539686961e-02,-5.6297236492e-02,4.2915323820e-01,-1.2609358633e+00,2.2399213250e+00,-2.9928879142e+00,2.5990173742e+00,0.0000000000e+00, },
|
}, }, { { 1.8229206610e-04,-7.8997325866e-01,-3.8715051001e-01,-2.6192408538e+00,-8.3977994034e-01,-2.8329897913e+00,-4.5306444352e-01,0.0000000000e+00,
|
||||||
},
|
}, { 9.8531160936e-02,-5.6297236492e-02,-5.7284484199e-02,-4.3673866734e-01,-1.9564766257e-01,-6.2028156584e-01,-3.4692356122e-01,0.0000000000e+00,
|
||||||
{
|
}, },
|
||||||
{ 1.8229206610e-04,-7.8997325866e-01,-7.7191410839e-01,-2.8075643964e+00,-1.6948618347e+00,-3.0367273700e+00,-9.0333559408e-01,0.0000000000e+00, },
|
|
||||||
{ 9.8531161839e-02,-5.6297236492e-02,-1.1421579050e-01,-4.8122536483e-01,-4.0121072432e-01,-7.4834487567e-01,-6.9170822332e-01,0.0000000000e+00, },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{ 1.8229206611e-04,-7.8997325866e-01,2.5782298908e+00,-5.3629717478e+00,6.5890882172e+00,-5.8012914776e+00,3.0171839130e+00,0.0000000000e+00, },
|
|
||||||
{ 9.8534230718e-02,-5.6297236492e-02,3.8148618075e-01,-1.0848760410e+00,1.8441165168e+00,-2.4860666655e+00,2.3103384142e+00,0.0000000000e+00, },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{ 1.8229206610e-04,-7.8997325866e-01,-3.8715051001e-01,-2.6192408538e+00,-8.3977994034e-01,-2.8329897913e+00,-4.5306444352e-01,0.0000000000e+00, },
|
|
||||||
{ 9.8531160936e-02,-5.6297236492e-02,-5.7284484199e-02,-4.3673866734e-01,-1.9564766257e-01,-6.2028156584e-01,-3.4692356122e-01,0.0000000000e+00, },
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief Coefficients for output filter
|
/*! \brief Coefficients for output filter
|
||||||
@@ -96,134 +84,144 @@ static double coef_in[NF][NBW][8] = {
|
|||||||
* Format: coef[IDX_BW][IDX_COEF]
|
* Format: coef[IDX_BW][IDX_COEF]
|
||||||
* IDX_COEF = 0 => 1/GAIN
|
* IDX_COEF = 0 => 1/GAIN
|
||||||
* IDX_COEF = 1-6 => Coefficientes y[n]
|
* IDX_COEF = 1-6 => Coefficientes y[n]
|
||||||
*/
|
*/
|
||||||
static double coef_out[NBW][8] = {
|
static double coef_out[NBW][8]={
|
||||||
{ 1.3868644653e-08,-6.3283665042e-01,4.0895057217e+00,-1.1020074592e+01,1.5850766191e+01,-1.2835109292e+01,5.5477477340e+00,0.0000000000e+00, },
|
{ 1.3868644653e-08,-6.3283665042e-01,4.0895057217e+00,-1.1020074592e+01,1.5850766191e+01,-1.2835109292e+01,5.5477477340e+00,0.0000000000e+00,
|
||||||
{ 3.1262119724e-03,-7.8390522307e-03,8.5209627801e-02,-4.0804129163e-01,1.1157139955e+00,-1.8767603680e+00,1.8916395224e+00,0.0000000000e+00, },
|
}, { 3.1262119724e-03,-7.8390522307e-03,8.5209627801e-02,-4.0804129163e-01,1.1157139955e+00,-1.8767603680e+00,1.8916395224e+00,0.0000000000e+00
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! Integer Pass Band demodulator filter */
|
||||||
/*! Band-pass filter for MARK frequency */
|
static inline int ibpdfilter(struct filter_struct * fs, int in)
|
||||||
static inline float filterM(fsk_data *fskd,float in)
|
|
||||||
{
|
{
|
||||||
int i, j;
|
int i,j;
|
||||||
double s;
|
int s;
|
||||||
double *pc;
|
int64_t s_interim;
|
||||||
|
|
||||||
pc = &coef_in[fskd->f_mark_idx][fskd->bw][0];
|
/* integer filter */
|
||||||
fskd->fmxv[(fskd->fmp+6)&7] = in*(*pc++);
|
s = in * fs->icoefs[0];
|
||||||
|
fs->ixv[(fs->ip+6)&7] = s;
|
||||||
|
|
||||||
s = (fskd->fmxv[(fskd->fmp + 6) & 7] - fskd->fmxv[fskd->fmp]) + 3 * (fskd->fmxv[(fskd->fmp + 2) & 7] - fskd->fmxv[(fskd->fmp + 4) & 7]);
|
s= (fs->ixv[fs->ip] + fs->ixv[(fs->ip+6)&7]) +
|
||||||
for (i = 0, j = fskd->fmp; i < 6; i++, j++)
|
6 * (fs->ixv[(fs->ip+1)&7] + fs->ixv[(fs->ip+5)&7]) +
|
||||||
s += fskd->fmyv[j&7]*(*pc++);
|
15 * (fs->ixv[(fs->ip+2)&7] + fs->ixv[(fs->ip+4)&7]) +
|
||||||
fskd->fmyv[j&7] = s;
|
20 * fs->ixv[(fs->ip+3)&7];
|
||||||
fskd->fmp++;
|
|
||||||
fskd->fmp &= 7;
|
for (i=1,j=fs->ip; i < 7; i++,j++) {
|
||||||
|
/* Promote operation to 64 bit to prevent overflow that occurred in 32 bit) */
|
||||||
|
s_interim = (int64_t)(fs->iyv[j & 7]) *
|
||||||
|
(int64_t)(fs->icoefs[i]) /
|
||||||
|
(int64_t)(1024);
|
||||||
|
s += (int)s_interim;
|
||||||
|
}
|
||||||
|
fs->iyv[ j & 7] = s;
|
||||||
|
fs->ip++;
|
||||||
|
fs->ip &= 7;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Band-pass filter for SPACE frequency */
|
/*! Integer Band Pass filter */
|
||||||
static inline float filterS(fsk_data *fskd,float in)
|
static inline int ibpfilter(struct filter_struct * fs, int in)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i,j;
|
||||||
double s;
|
int s;
|
||||||
double *pc;
|
int64_t s_interim;
|
||||||
|
|
||||||
pc = &coef_in[fskd->f_space_idx][fskd->bw][0];
|
/* integer filter */
|
||||||
fskd->fsxv[(fskd->fsp+6)&7] = in*(*pc++);
|
s = in * fs->icoefs[0] / 256;
|
||||||
|
fs->ixv[(fs->ip+6) & 7] = s;
|
||||||
|
|
||||||
s = (fskd->fsxv[(fskd->fsp + 6) & 7] - fskd->fsxv[fskd->fsp]) + 3 * (fskd->fsxv[(fskd->fsp + 2) & 7] - fskd->fsxv[(fskd->fsp + 4) & 7]);
|
s = (fs->ixv[(fs->ip+6) & 7] - fs->ixv[fs->ip])
|
||||||
for (i = 0, j = fskd->fsp; i < 6; i++, j++)
|
+ 3 * (fs->ixv[(fs->ip+2) & 7] - fs->ixv[(fs->ip+4) & 7]);
|
||||||
s += fskd->fsyv[j&7]*(*pc++);
|
|
||||||
fskd->fsyv[j&7] = s;
|
for (i=1,j=fs->ip; i < 7; i++,j++) {
|
||||||
fskd->fsp++;
|
s_interim = (int64_t)(fs->iyv[j&7]) *
|
||||||
fskd->fsp &= 7;
|
(int64_t)(fs->icoefs[i]) /
|
||||||
|
(int64_t)(256);
|
||||||
|
s+= (int)s_interim;
|
||||||
|
}
|
||||||
|
fs->iyv[j&7]=s;
|
||||||
|
fs->ip++; fs->ip &= 7;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Low-pass filter for demodulated data */
|
static inline int idemodulator(fsk_data *fskd, int *retval, int x)
|
||||||
static inline float filterL(fsk_data *fskd,float in)
|
|
||||||
{
|
{
|
||||||
int i, j;
|
int is, im, id;
|
||||||
double s;
|
int ilin2;
|
||||||
double *pc;
|
|
||||||
|
is = ibpfilter(&fskd->space_filter, x);
|
||||||
|
im = ibpfilter(&fskd->mark_filter, x);
|
||||||
|
|
||||||
pc = &coef_out[fskd->bw][0];
|
ilin2 = ((im * im) - (is * is))/(256 * 256);
|
||||||
fskd->flxv[(fskd->flp + 6) & 7] = in * (*pc++);
|
|
||||||
|
|
||||||
s = (fskd->flxv[fskd->flp] + fskd->flxv[(fskd->flp+6)&7]) +
|
id = ibpdfilter(&fskd->demod_filter, ilin2);
|
||||||
6 * (fskd->flxv[(fskd->flp+1)&7] + fskd->flxv[(fskd->flp+5)&7]) +
|
|
||||||
15 * (fskd->flxv[(fskd->flp+2)&7] + fskd->flxv[(fskd->flp+4)&7]) +
|
|
||||||
20 * fskd->flxv[(fskd->flp+3)&7];
|
|
||||||
|
|
||||||
for (i = 0,j = fskd->flp;i<6;i++,j++)
|
*retval = id;
|
||||||
s += fskd->flyv[j&7]*(*pc++);
|
|
||||||
fskd->flyv[j&7] = s;
|
|
||||||
fskd->flp++;
|
|
||||||
fskd->flp &= 7;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int demodulator(fsk_data *fskd, float *retval, float x)
|
|
||||||
{
|
|
||||||
float xS,xM;
|
|
||||||
|
|
||||||
fskd->cola_in[fskd->pcola] = x;
|
|
||||||
|
|
||||||
xS = filterS(fskd,x);
|
|
||||||
xM = filterM(fskd,x);
|
|
||||||
|
|
||||||
fskd->cola_filter[fskd->pcola] = xM-xS;
|
|
||||||
|
|
||||||
x = filterL(fskd,xM*xM - xS*xS);
|
|
||||||
|
|
||||||
fskd->cola_demod[fskd->pcola++] = x;
|
|
||||||
fskd->pcola &= (NCOLA-1);
|
|
||||||
|
|
||||||
*retval = x;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_bit_raw(fsk_data *fskd, short *buffer, int *len)
|
static int get_bit_raw(fsk_data *fskd, short *buffer, int *len)
|
||||||
{
|
{
|
||||||
/* This function implements a DPLL to synchronize with the bits */
|
/* This function implements a DPLL to synchronize with the bits */
|
||||||
float x,spb,spb2,ds;
|
|
||||||
int f;
|
int f;
|
||||||
|
|
||||||
spb = fskd->spb;
|
int ix;
|
||||||
if (fskd->spb == 7)
|
/* PLL coeffs are set up in callerid_new */
|
||||||
spb = 8000.0 / 1200.0;
|
for (f = 0;;){
|
||||||
ds = spb/32.;
|
if (idemodulator(fskd, &ix, IGET_SAMPLE)) return(-1);
|
||||||
spb2 = spb/2.;
|
if ((ix * fskd->xi0)<0) { /* Transicion */
|
||||||
|
|
||||||
for (f = 0;;) {
|
|
||||||
if (demodulator(fskd, &x, GET_SAMPLE))
|
|
||||||
return -1;
|
|
||||||
if ((x * fskd->x0) < 0) { /* Transition */
|
|
||||||
if (!f) {
|
if (!f) {
|
||||||
if (fskd->cont<(spb2))
|
if (fskd->icont<(fskd->pllispb2))
|
||||||
fskd->cont += ds;
|
fskd->icont+=fskd->pllids;
|
||||||
else
|
else
|
||||||
fskd->cont -= ds;
|
fskd->icont-=fskd->pllids;
|
||||||
f = 1;
|
f=1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fskd->x0 = x;
|
fskd->xi0=ix;
|
||||||
fskd->cont += 1.;
|
fskd->icont+=32;
|
||||||
if (fskd->cont > spb) {
|
if (fskd->icont>fskd->pllispb) {
|
||||||
fskd->cont -= spb;
|
fskd->icont-=fskd->pllispb;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f = (x > 0) ? 0x80 : 0;
|
f=(ix>0)?0x80:0;
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fskmodem_init(fsk_data *fskd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fskd->space_filter.ip = 0;
|
||||||
|
fskd->mark_filter.ip = 0;
|
||||||
|
fskd->demod_filter.ip = 0;
|
||||||
|
|
||||||
|
for ( i = 0 ; i < 7 ; i++ ) {
|
||||||
|
fskd->space_filter.icoefs[i] =
|
||||||
|
coef_in[fskd->f_space_idx][fskd->bw][i] * 256;
|
||||||
|
fskd->space_filter.ixv[i] = 0;;
|
||||||
|
fskd->space_filter.iyv[i] = 0;;
|
||||||
|
|
||||||
|
fskd->mark_filter.icoefs[i] =
|
||||||
|
coef_in[fskd->f_mark_idx][fskd->bw][i] * 256;
|
||||||
|
fskd->mark_filter.ixv[i] = 0;;
|
||||||
|
fskd->mark_filter.iyv[i] = 0;;
|
||||||
|
|
||||||
|
fskd->demod_filter.icoefs[i] =
|
||||||
|
coef_out[fskd->bw][i] * 1024;
|
||||||
|
fskd->demod_filter.ixv[i] = 0;;
|
||||||
|
fskd->demod_filter.iyv[i] = 0;;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int fsk_serial(fsk_data *fskd, short *buffer, int *len, int *outbyte)
|
int fsk_serial(fsk_data *fskd, short *buffer, int *len, int *outbyte)
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
int i,j,n1,r;
|
int i,j,n1,r;
|
||||||
int samples = 0;
|
int samples=0;
|
||||||
int olen;
|
int olen;
|
||||||
int beginlen=*len;
|
int beginlen=*len;
|
||||||
int beginlenx;
|
int beginlenx;
|
||||||
@@ -243,56 +241,58 @@ int fsk_serial(fsk_data *fskd, short *buffer, int *len, int *outbyte)
|
|||||||
to look for the beginning of the start bit. Unfortunately, since TTY/TDD's
|
to look for the beginning of the start bit. Unfortunately, since TTY/TDD's
|
||||||
just start sending a start bit with nothing preceding it at the beginning
|
just start sending a start bit with nothing preceding it at the beginning
|
||||||
of a transmission (what a LOSING design), we cant do it this elegantly */
|
of a transmission (what a LOSING design), we cant do it this elegantly */
|
||||||
/*
|
/* NOT USED
|
||||||
if (demodulator(zap,&x1)) return(-1);
|
if (demodulator(zap,&x1))
|
||||||
for (;;) {
|
return -1;
|
||||||
if (demodulator(zap,&x2)) return(-1);
|
for(;;) {
|
||||||
if (x1>0 && x2<0) break;
|
if (demodulator(zap,&x2))
|
||||||
x1 = x2;
|
return -1;
|
||||||
}
|
if (x1>0 && x2<0) break;
|
||||||
|
x1=x2;
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
/* this is now the imprecise, losing, but functional code to detect the
|
/* this is now the imprecise, losing, but functional code to detect the
|
||||||
beginning of a start bit in the TDD sceanario. It just looks for sufficient
|
beginning of a start bit in the TDD sceanario. It just looks for sufficient
|
||||||
level to maybe, perhaps, guess, maybe that its maybe the beginning of
|
level to maybe, perhaps, guess, maybe that its maybe the beginning of
|
||||||
a start bit, perhaps. This whole thing stinks! */
|
a start bit, perhaps. This whole thing stinks! */
|
||||||
beginlenx=beginlen; /* just to avoid unused war warnings */
|
beginlenx=beginlen; /* just to avoid unused war warnings */
|
||||||
if (demodulator(fskd, &fskd->x1, GET_SAMPLE))
|
if (idemodulator(fskd, &fskd->xi1, IGET_SAMPLE))
|
||||||
return -1;
|
return -1;
|
||||||
samples++;
|
samples++;
|
||||||
for (;;) {
|
for(;;) {
|
||||||
search_startbit2:
|
search_startbit2:
|
||||||
if (*len <= 0) {
|
if (*len <= 0) {
|
||||||
fskd->state = STATE_SEARCH_STARTBIT2;
|
fskd->state = STATE_SEARCH_STARTBIT2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
samples++;
|
samples++;
|
||||||
if (demodulator(fskd, &fskd->x2, GET_SAMPLE))
|
if (idemodulator(fskd,&fskd->xi2,IGET_SAMPLE))
|
||||||
return(-1);
|
return -1;
|
||||||
#if 0
|
#if 0
|
||||||
printf("x2 = %5.5f ", fskd->x2);
|
printf("xi2 = %d ", fskd->xi2);
|
||||||
#endif
|
#endif
|
||||||
if (fskd->x2 < -0.5)
|
if (fskd->xi2 < 512)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
search_startbit3:
|
search_startbit3:
|
||||||
/* We await for 0.5 bits before using DPLL */
|
/* We await for 0.5 bits before using DPLL */
|
||||||
i = fskd->spb/2;
|
i=fskd->ispb/2;
|
||||||
if (*len < i) {
|
if (*len < i) {
|
||||||
fskd->state = STATE_SEARCH_STARTBIT3;
|
fskd->state = STATE_SEARCH_STARTBIT3;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (; i>0; i--) {
|
for (; i>0; i--) {
|
||||||
if (demodulator(fskd, &fskd->x1, GET_SAMPLE))
|
if (idemodulator(fskd, &fskd->xi1, IGET_SAMPLE))
|
||||||
return(-1);
|
return(-1);
|
||||||
#if 0
|
#if 0
|
||||||
printf("x1 = %5.5f ", fskd->x1);
|
printf("xi1 = %d ", fskd->xi1);
|
||||||
#endif
|
#endif
|
||||||
samples++;
|
samples++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* x1 must be negative (start bit confirmation) */
|
/* x1 must be negative (start bit confirmation) */
|
||||||
|
|
||||||
} while (fskd->x1 > 0);
|
} while (fskd->xi1>0);
|
||||||
fskd->state = STATE_GET_BYTE;
|
fskd->state = STATE_GET_BYTE;
|
||||||
|
|
||||||
getbyte:
|
getbyte:
|
||||||
@@ -306,18 +306,19 @@ getbyte:
|
|||||||
if (*len < 80)
|
if (*len < 80)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we read the data bits */
|
/* Now we read the data bits */
|
||||||
j = fskd->nbit;
|
j = fskd->nbit;
|
||||||
for (a = n1 = 0; j; j--) {
|
for (a = n1 = 0; j; j--) {
|
||||||
olen = *len;
|
olen = *len;
|
||||||
i = get_bit_raw(fskd, buffer, len);
|
i = get_bit_raw(fskd, buffer, len);
|
||||||
buffer += (olen - *len);
|
buffer += (olen - *len);
|
||||||
if (i == -1)
|
if (i == -1)
|
||||||
return(-1);
|
return -1;
|
||||||
if (i)
|
if (i)
|
||||||
n1++;
|
n1++;
|
||||||
a >>= 1;
|
a >>= 1;
|
||||||
a |= i;
|
a |= i;
|
||||||
}
|
}
|
||||||
j = 8-fskd->nbit;
|
j = 8-fskd->nbit;
|
||||||
a >>= j;
|
a >>= j;
|
||||||
@@ -327,33 +328,34 @@ getbyte:
|
|||||||
olen = *len;
|
olen = *len;
|
||||||
i = get_bit_raw(fskd, buffer, len);
|
i = get_bit_raw(fskd, buffer, len);
|
||||||
buffer += (olen - *len);
|
buffer += (olen - *len);
|
||||||
if (i == -1)
|
if (i == -1)
|
||||||
return(-1);
|
return -1;
|
||||||
if (i)
|
if (i)
|
||||||
n1++;
|
n1++;
|
||||||
if (fskd->parity == 1) { /* parity=1 (even) */
|
if (fskd->parity == 1) { /* parity=1 (even) */
|
||||||
if (n1&1)
|
if (n1&1)
|
||||||
a |= 0x100; /* error */
|
a |= 0x100; /* error */
|
||||||
} else { /* parity=2 (odd) */
|
} else { /* parity=2 (odd) */
|
||||||
if (!(n1&1))
|
if (!(n1&1))
|
||||||
a |= 0x100; /* error */
|
a |= 0x100; /* error */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We read STOP bits. All of them must be 1 */
|
/* We read STOP bits. All of them must be 1 */
|
||||||
|
|
||||||
for (j = fskd->nstop;j;j--) {
|
for (j=fskd->instop; j; j--) {
|
||||||
r = get_bit_raw(fskd, buffer, len);
|
r = get_bit_raw(fskd, buffer, len);
|
||||||
if (r == -1)
|
if (r == -1)
|
||||||
return(-1);
|
return -1;
|
||||||
if (!r)
|
if (!r)
|
||||||
a |= 0x200;
|
a |= 0x200;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And finally we return */
|
/* And finally we return
|
||||||
/* Bit 8 : Parity error */
|
* Bit 8 : Parity error
|
||||||
/* Bit 9 : Framming error*/
|
* Bit 9 : Framming error
|
||||||
|
*/
|
||||||
|
|
||||||
*outbyte = a;
|
*outbyte = a;
|
||||||
fskd->state = STATE_SEARCH_STARTBIT;
|
fskd->state = STATE_SEARCH_STARTBIT;
|
||||||
return 1;
|
return 1;
|
||||||
|
13
main/tdd.c
13
main/tdd.c
@@ -103,20 +103,23 @@ struct tdd_state *tdd_new(void)
|
|||||||
struct tdd_state *tdd;
|
struct tdd_state *tdd;
|
||||||
tdd = calloc(1, sizeof(*tdd));
|
tdd = calloc(1, sizeof(*tdd));
|
||||||
if (tdd) {
|
if (tdd) {
|
||||||
tdd->fskd.spb = 176; /* 45.5 baud */
|
tdd->fskd.ispb = 176; /* 45.5 baud */
|
||||||
|
/* Set up for 45.5 / 8000 freq *32 to allow ints */
|
||||||
|
tdd->fskd.pllispb = (int)((8000 * 32 * 2) / 90);
|
||||||
|
tdd->fskd.pllids = tdd->fskd.pllispb/32;
|
||||||
|
tdd->fskd.pllispb2 = tdd->fskd.pllispb/2;
|
||||||
tdd->fskd.hdlc = 0; /* Async */
|
tdd->fskd.hdlc = 0; /* Async */
|
||||||
tdd->fskd.nbit = 5; /* 5 bits */
|
tdd->fskd.nbit = 5; /* 5 bits */
|
||||||
tdd->fskd.nstop = 1.5; /* 1.5 stop bits */
|
tdd->fskd.instop = 1; /* integer rep of 1.5 stop bits */
|
||||||
tdd->fskd.parity = 0; /* No parity */
|
tdd->fskd.parity = 0; /* No parity */
|
||||||
tdd->fskd.bw=0; /* Filter 75 Hz */
|
tdd->fskd.bw=0; /* Filter 75 Hz */
|
||||||
tdd->fskd.f_mark_idx = 0; /* 1400 Hz */
|
tdd->fskd.f_mark_idx = 0; /* 1400 Hz */
|
||||||
tdd->fskd.f_space_idx = 1; /* 1800 Hz */
|
tdd->fskd.f_space_idx = 1; /* 1800 Hz */
|
||||||
tdd->fskd.pcola = 0; /* No clue */
|
tdd->fskd.xi0 = 0;
|
||||||
tdd->fskd.cont = 0; /* Digital PLL reset */
|
|
||||||
tdd->fskd.x0 = 0.0;
|
|
||||||
tdd->fskd.state = 0;
|
tdd->fskd.state = 0;
|
||||||
tdd->pos = 0;
|
tdd->pos = 0;
|
||||||
tdd->mode = 2;
|
tdd->mode = 2;
|
||||||
|
fskmodem_init(&tdd->fskd);
|
||||||
} else
|
} else
|
||||||
ast_log(LOG_WARNING, "Out of memory\n");
|
ast_log(LOG_WARNING, "Out of memory\n");
|
||||||
return tdd;
|
return tdd;
|
||||||
|
Reference in New Issue
Block a user