From 76707a409c8cce29ae8a001e3b3c1e6b43b078d0 Mon Sep 17 00:00:00 2001 From: Jim Dixon Date: Fri, 16 May 2008 00:51:14 +0000 Subject: Bring all app_rpt and chan_usbradio stuff up to date git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@116731 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/xpmr/sinetabx.h | 30 +- channels/xpmr/xpmr.c | 2256 +++++++++++++++++++++++++++++++++------------ channels/xpmr/xpmr.h | 620 ++++++++++--- channels/xpmr/xpmr_coef.h | 344 +------ 4 files changed, 2230 insertions(+), 1020 deletions(-) (limited to 'channels/xpmr') diff --git a/channels/xpmr/sinetabx.h b/channels/xpmr/sinetabx.h index 4c4574850..14d8f9f4c 100755 --- a/channels/xpmr/sinetabx.h +++ b/channels/xpmr/sinetabx.h @@ -4,16 +4,26 @@ * All Rights Reserved. Copyright (C)2007, Xelatec, LLC * * 20070808 1235 Steven Henke, W9SH, sph@xelatec.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This version may be optionally licenced under the GNU LGPL licence. * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. + * A license has been granted to Digium (via disclaimer) for the use of + * this code. * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. */ /*! \file @@ -24,11 +34,11 @@ */ #ifndef XPMR_SINETABX_H -#define XPMR_SINETABX_H 1 +#define XPMR_SINETABX_H 1 #define SAMPLES_PER_SINE 256 -const i16 sinetablex[]={ +static const i16 sinetablex[]={ 0, // 0 804, // 1 1608, // 2 diff --git a/channels/xpmr/xpmr.c b/channels/xpmr/xpmr.c index a799ca9d3..5e1b0f59d 100755 --- a/channels/xpmr/xpmr.c +++ b/channels/xpmr/xpmr.c @@ -1,19 +1,30 @@ /* * xpmr.c - Xelatec Private Mobile Radio Processes - * + * * All Rights Reserved. Copyright (C)2007, Xelatec, LLC - * + * * 20070808 1235 Steven Henke, W9SH, sph@xelatec.com * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. + * This version may be optionally licenced under the GNU LGPL licence. + * + * A license has been granted to Digium (via disclaimer) for the use of + * this code. + * + * 20080118 0800 sph@xelatec.com major fixes and features */ /*! \file @@ -36,29 +47,419 @@ FIR = Finite Impulse Response (Filter) IIR = Infinite Impulse Response (Filter) */ + +// XPMR_FILE_VERSION(__FILE__, "$Revision$") + #include #include #include #include #include #include +#include #include #include #include #include - + #include "xpmr.h" #include "xpmr_coef.h" #include "sinetabx.h" static i16 pmrChanIndex=0; // count of created pmr instances +//static i16 pmrSpsIndex=0; + +#if (DTX_PROG == 1) || XPMR_PPTP == 1 +static int ppdrvdev=0; +#endif + +/* + Trace Routines +*/ +void strace(i16 point, t_sdbg *sdbg, i16 index, i16 value) +{ + // make dbg_trace buffer in structure + if(!sdbg->mode || sdbg->point[point]<0){ + return; + } else { + sdbg->buffer[(index*XPMR_DEBUG_CHANS) + sdbg->point[point]] = value; + } +} +/* + +*/ +void strace2(t_sdbg *sdbg) +{ + int i; + for(i=0;isource[i]) + { + int ii; + for(ii=0;iibuffer[ii*XPMR_DEBUG_CHANS + i] = sdbg->source[i][ii]; + } + } + } +} +#if XPMR_PPTP == 1 +/* + Hardware Trace Signals via the PC Parallel Port +*/ +void pptp_init (void) +{ + if (ppdrvdev == 0) + ppdrvdev = open("/dev/ppdrv_device", 0); + + if (ppdrvdev < 0) + { + ast_log(LOG_ERROR, "open /dev/ppdrv_ppdrvdev returned %i\n",ppdrvdev); + exit(0); + } + ioctl(ppdrvdev, PPDRV_IOC_PINMODE_OUT, DTX_CLK | DTX_DATA | DTX_ENABLE | DTX_TXPWR | DTX_TX | DTX_TP1 | DTX_TP2); + ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_CLK | DTX_DATA | DTX_ENABLE | DTX_TXPWR | DTX_TX | DTX_TP1 | DTX_TP2); +} +/* +*/ +void pptp_write(i16 bit, i16 state) +{ + if(bit==0) + { + if(state)ioctl(ppdrvdev,PPDRV_IOC_PINSET,DTX_TP1); + else ioctl(ppdrvdev,PPDRV_IOC_PINCLEAR,DTX_TP1); + } + else + { + if(state)ioctl(ppdrvdev,PPDRV_IOC_PINSET,DTX_TP2); + else ioctl(ppdrvdev,PPDRV_IOC_PINCLEAR,DTX_TP2); + } +} +#endif +/* + take source string allocate and copy + copy is modified, delimiters are replaced with zeros to mark + end of string + count set pointers + string_parse( char *src, char *dest, char **sub) +*/ +i16 string_parse(char *src, char **dest, char ***ptrs) +{ + char *p,*pd; + char *ptstr[1000]; + i16 i, slen, numsub; + + TRACEJ(2,("string_parse(%s)\n",src)); + + slen=strlen(src); + TRACEJ(2,(" source len = %i\n",slen)); + + pd=*dest; + if(pd) free(pd); + pd=calloc(slen+1,1); + memcpy(pd,src,slen); + *dest=pd; + + p=0; + numsub=0; + for(i=0;ipRxCodeSrc %s \n",pChan->pRxCodeSrc)); + TRACEF(1,("pChan->pTxCodeSrc %s \n",pChan->pTxCodeSrc)); + TRACEF(1,("pChan->pTxCodeDefault %s \n",pChan->pTxCodeDefault)); + + //printf("code_string_parse() %s / %s / %s / %s \n",pChan->name, pChan->pTxCodeDefault,pChan->pTxCodeSrc,pChan->pRxCodeSrc); + + maxctcssindex=CTCSS_NULL; + maxctcsstxfreq=CTCSS_NULL; + pChan->txctcssdefault_index=CTCSS_NULL; + pChan->txctcssdefault_value=CTCSS_NULL; + + pChan->b.ctcssRxEnable=pChan->b.ctcssTxEnable=0; + pChan->b.dcsRxEnable=pChan->b.dcsTxEnable=0; + pChan->b.lmrRxEnable=pChan->b.lmrTxEnable=0; + pChan->b.mdcRxEnable=pChan->b.mdcTxEnable=0; + pChan->b.dstRxEnable=pChan->b.dstTxEnable=0; + pChan->b.p25RxEnable=pChan->b.p25TxEnable=0; + + if(pChan->spsLsdGen){ + pChan->spsLsdGen->enabled=0; + pChan->spsLsdGen->state=0; + } + + TRACEF(1,("code_string_parse(%i) 05\n",0)); + + pChan->numrxcodes = string_parse( pChan->pRxCodeSrc, &(pChan->pRxCodeStr), &(pChan->pRxCode)); + pChan->numtxcodes = string_parse( pChan->pTxCodeSrc, &(pChan->pTxCodeStr), &(pChan->pTxCode)); + + if(pChan->numrxcodes!=pChan->numtxcodes)printf("ERROR: numrxcodes != numtxcodes \n"); + + pChan->rxCtcss->enabled=0; + pChan->rxCtcss->gain=1*M_Q8; + pChan->rxCtcss->limit=8192; + pChan->rxCtcss->input=pChan->pRxLsdLimit; + pChan->rxCtcss->decode=CTCSS_NULL; + + pChan->rxCtcss->testIndex=0; + if(!pChan->rxCtcss->testIndex)pChan->rxCtcss->testIndex=3; + + pChan->rxctcssfreq[0]=0; // decode now CTCSS_RXONLY + + for(i=0;irxctcss[i]=0; + pChan->txctcss[i]=0; + pChan->rxCtcssMap[i]=CTCSS_NULL; + } + + TRACEF(1,("code_string_parse(%i) 10\n",0)); + + #ifdef XPMRX_H + xpmrx(pChan,XXO_LSDCODEPARSE); + #endif + + // Do Receive Codes String + for(i=0;inumrxcodes;i++) + { + i16 ii,ri,ti; + float f; + + p=pChan->pStr=pChan->pRxCode[i]; + + #ifdef HAVE_XPMRX + if(!xpmrx(pChan,XXO_LSDCODEPARSE_1)) + #endif + { + sscanf(p,"%f",&f); + ri=CtcssFreqIndex(f); + if(ri>maxctcssindex)maxctcssindex=ri; + + sscanf(pChan->pTxCode[i],"%f",&f); + ti=CtcssFreqIndex(f); + if(f>maxctcsstxfreq)maxctcsstxfreq=f; + + if(ri>CTCSS_NULL && ti>CTCSS_NULL) + { + pChan->b.ctcssRxEnable=pChan->b.ctcssTxEnable=1; + pChan->rxCtcssMap[ri]=ti; + pChan->numrxctcssfreqs++; + TRACEF(1,("pChan->rxctcss[%i]=%s pChan->rxCtcssMap[%i]=%i\n",i,pChan->rxctcss[i],ri,ti)); + } + else if(ri>CTCSS_NULL && f==0) + { + pChan->b.ctcssRxEnable=1; + pChan->rxCtcssMap[ri]=CTCSS_RXONLY; + pChan->numrxctcssfreqs++; + TRACEF(1,("pChan->rxctcss[%i]=%s pChan->rxCtcssMap[%i]=%i RXONLY\n",i,pChan->rxctcss[i],ri,ti)); + } + else + { + pChan->numrxctcssfreqs=0; + for(ii=0;iirxCtcssMap[ii]=CTCSS_NULL; + TRACEF(1,("WARNING: Invalid Channel code detected and ignored. %i %s %s \n",i,pChan->pRxCode[i],pChan->pTxCode[i])); + } + } + } + + TRACEF(1,("code_string_parse() CTCSS Init Struct %i %i\n",pChan->b.ctcssRxEnable,pChan->b.ctcssTxEnable)); + if(pChan->b.ctcssRxEnable) + { + pChan->rxHpfEnable=1; + pChan->spsRxLsdNrz->enabled=pChan->rxCenterSlicerEnable=1; + pChan->rxCtcssDecodeEnable=1; + pChan->rxCtcss->enabled=1; + } + else + { + pChan->rxHpfEnable=1; + pChan->spsRxLsdNrz->enabled=pChan->rxCenterSlicerEnable=0; + pChan->rxCtcssDecodeEnable=0; + pChan->rxCtcss->enabled=0; + } + + TRACEF(1,("code_string_parse() CTCSS Init Decoders \n")); + for(i=0;irxCtcss->tdet[i]); + ptdet->counterFactor=coef_ctcss_div[i]; + ptdet->state=1; + ptdet->setpt=(M_Q15*0.041); // 0.069 + ptdet->hyst =(M_Q15*0.0130); + ptdet->binFactor=(M_Q15*0.135); // was 0.140 + ptdet->fudgeFactor=8; + } + + + // DEFAULT TX CODE + TRACEF(1,("code_string_parse() Default Tx Code %s \n",pChan->pTxCodeDefault)); + pChan->txcodedefaultsmode=SMODE_NULL; + p=pChan->pStr=pChan->pTxCodeDefault; + + #ifdef HAVE_XPMRX + if(!lsd_code_parse(pChan,3)) + #endif + { + sscanf(p,"%f",&f); + ti=CtcssFreqIndex(f); + if(f>maxctcsstxfreq)maxctcsstxfreq=f; + + if(ti>CTCSS_NULL) + { + pChan->b.ctcssTxEnable=1; + pChan->txctcssdefault_index=ti; + pChan->txctcssdefault_value=f; + pChan->spsSigGen0->freq=f*10; + pChan->txcodedefaultsmode=SMODE_CTCSS; + TRACEF(1,("code_string_parse() Tx Default CTCSS = %s %i %f\n",p,ti,f)); + } + } + + + // set x for maximum length and just change pointers + TRACEF(1,("code_string_parse() Filter Config \n")); + pSps=pChan->spsTxLsdLpf; + if(pSps->x)free(pSps->x); + if(maxctcsstxfreq>203.5) + { + pSps->ncoef=taps_fir_lpf_250_9_66; + pSps->size_coef=2; + pSps->coef=(void*)coef_fir_lpf_250_9_66; + pSps->nx=taps_fir_lpf_250_9_66; + pSps->size_x=2; + pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); + pSps->calcAdjust=gain_fir_lpf_250_9_66; + TRACEF(1,("code_string_parse() Tx Filter Freq High\n")); + } + else + { + pSps->ncoef=taps_fir_lpf_215_9_88; + pSps->size_coef=2; + pSps->coef=(void*)coef_fir_lpf_215_9_88; + pSps->nx=taps_fir_lpf_215_9_88; + pSps->size_x=2; + pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); + pSps->calcAdjust=gain_fir_lpf_215_9_88; + TRACEF(1,("code_string_parse() Tx Filter Freq Low\n")); + } + + // CTCSS Rx Decoder Low Pass Filter + hit=0; + ii= CtcssFreqIndex(203.5); + for(i=ii;irxCtcssMap[i]>CTCSS_NULL)hit=1; + } + + pSps=pChan->spsRxLsd; + if(pSps->x)free(pSps->x); + if(hit) + { + pSps->ncoef=taps_fir_lpf_250_9_66; + pSps->size_coef=2; + pSps->coef=(void*)coef_fir_lpf_250_9_66; + pSps->nx=taps_fir_lpf_250_9_66; + pSps->size_x=2; + pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); + pSps->calcAdjust=gain_fir_lpf_250_9_66; + TRACEF(1,("code_string_parse() Rx Filter Freq High\n")); + } + else + { + pSps->ncoef=taps_fir_lpf_215_9_88; + pSps->size_coef=2; + pSps->coef=(void*)coef_fir_lpf_215_9_88; + pSps->nx=taps_fir_lpf_215_9_88; + pSps->size_x=2; + pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); + pSps->calcAdjust=gain_fir_lpf_215_9_88; + TRACEF(1,("code_string_parse() Rx Filter Freq Low\n")); + } + + if(pChan->b.ctcssRxEnable || pChan->b.dcsRxEnable || pChan->b.lmrRxEnable) + { + pChan->rxCenterSlicerEnable=1; + pSps->enabled=1; + } + else + { + pChan->rxCenterSlicerEnable=0; + pSps->enabled=0; + } + + #if XPMR_DEBUG0 == 1 + TRACEF(2,("code_string_parse() ctcssRxEnable = %i \n",pChan->b.ctcssRxEnable)); + TRACEF(2,(" ctcssTxEnable = %i \n",pChan->b.ctcssTxEnable)); + TRACEF(2,(" dcsRxEnable = %i \n",pChan->b.dcsRxEnable)); + TRACEF(2,(" lmrRxEnable = %i \n",pChan->b.lmrRxEnable)); + TRACEF(2,(" txcodedefaultsmode = %i \n",pChan->txcodedefaultsmode)); + for(i=0;irxCtcssMap[i])); + } + #endif + + #ifdef HAVE_XPMRX + lsd_code_parse(pChan,5); + #endif + TRACEF(1,("code_string_parse(%i) end\n",0)); + + return 0; +} /* Convert a Frequency in Hz to a zero based CTCSS Table index */ i16 CtcssFreqIndex(float freq) { - i16 i,hit=-1; + i16 i,hit=CTCSS_NULL; for(i=0;ienabled)return(1); @@ -112,12 +513,12 @@ i16 pmr_rx_frontend(t_pmr_sps *mySps) compOut=mySps->compOut; samples=mySps->nSamples*decimate; - x=mySps->x; + x=mySps->x; iOutput=0; if(mySps->parentChan->rxCdType!=CD_XPMR_VOX)doNoise=1; else doNoise=0; - + for(i=0;iamax) { amax=naccum; @@ -177,33 +578,33 @@ i16 pmr_rx_frontend(t_pmr_sps *mySps) discounterl=discfactor; amin=(i32)((amin*32700)/32768); } - + apeak=(amax-amin)/2; - + } // if doNoise } if(doNoise) { ((t_pmr_chan *)(mySps->parentChan))->rxRssi=apeak; - + if(apeak>setpt || (compOut&&(apeak>(setpt-hyst)))) compOut=1; else compOut=0; mySps->compOut=compOut; mySps->amax=amax; - mySps->amin=amin; + mySps->amin=amin; mySps->apeak=apeak; mySps->discounteru=discounteru; - mySps->discounterl=discounterl; + mySps->discounterl=discounterl; } return 0; } -/* +/* pmr general purpose fir works on a block of samples */ -i16 pmr_gp_fir(t_pmr_sps *mySps) +i16 pmr_gp_fir(t_pmr_sps *mySps) { i32 nsamples,inputGain,outputGain,calcAdjust; i16 *input, *output; @@ -214,7 +615,7 @@ i16 pmr_gp_fir(t_pmr_sps *mySps) i16 decimator, decimate, interpolate; i16 numChanOut, selChanOut, mixOut, monoOut; - TRACEX(("pmr_gp_fir() %i\n",mySps->enabled)); + TRACEJ(5,("pmr_gp_fir() %i %i\n",mySps->index, mySps->enabled)); if(!mySps->enabled)return(1); @@ -227,7 +628,7 @@ i16 pmr_gp_fir(t_pmr_sps *mySps) x = mySps->x; nx = mySps->nx; coef = mySps->coef; - + decimator = mySps->decimator; decimate = mySps->decimate; interpolate = mySps->interpolate; @@ -243,11 +644,11 @@ i16 pmr_gp_fir(t_pmr_sps *mySps) monoOut = mySps->monoOut; amax=mySps->amax; - amin=mySps->amin; + amin=mySps->amin; discfactor=mySps->discfactor; - hyst=mySps->hyst; - setpt=mySps->setpt; + hyst=mySps->hyst; + setpt=mySps->setpt; nsamples=mySps->nSamples; if(mySps->option==3) @@ -270,21 +671,21 @@ i16 pmr_gp_fir(t_pmr_sps *mySps) int ix; int64_t y=0; - + if(decimate<0) { - decimator=decimate; + decimator=decimate; } for(ix=0;ix0; n--) x[n] = x[n-1]; x[0] = (input[i]*inputGain)/M_Q8; - + #if 0 --decimator; if(decimator<=0) @@ -292,7 +693,7 @@ i16 pmr_gp_fir(t_pmr_sps *mySps) decimator=decimate; for(n=0; nsetpt)compOut=1; else if(compOut&&(apeak<(setpt-hyst)))compOut=0; } @@ -358,13 +759,13 @@ i16 pmr_gp_fir(t_pmr_sps *mySps) mySps->decimator = decimator; mySps->amax=amax; - mySps->amin=amin; - mySps->apeak=apeak; + mySps->amin=amin; + mySps->apeak=apeak; mySps->discounteru=discounteru; - mySps->discounterl=discounterl; - + mySps->discounterl=discounterl; + mySps->compOut=compOut; - + return 0; } /* @@ -382,7 +783,7 @@ i16 gp_inte_00(t_pmr_sps *mySps) i32 state00; i16 coeff00, coeff01; - TRACEX(("gp_inte_00() %i\n",mySps->enabled)); + TRACEJ(5,("gp_inte_00() %i\n",mySps->enabled)); if(!mySps->enabled)return(1); input = mySps->source; @@ -447,7 +848,7 @@ i16 gp_diff(t_pmr_sps *mySps) x0=x[0]; - TRACEX(("gp_diff()\n")); + TRACEJ(5,("gp_diff()\n")); for (i=0;i32766)y0=32766; + else if(y0<-32766)y0=-32766; + output[i]=y0; } x[0]=x0; @@ -484,10 +889,11 @@ i16 CenterSlicer(t_pmr_sps *mySps) i32 discounterl; // amplitude detector integrator discharge counter lower i32 discfactor; // amplitude detector integrator discharge factor - TRACEX(("CenterSlicer() %i\n",mySps->enabled)); + TRACEJ(5,("CenterSlicer() %i\n",mySps->enabled)); + if(!mySps->enabled)return(1); input = mySps->source; - output = mySps->sink; + output = mySps->sink; // limited output buff = mySps->buff; npoints=mySps->nSamples; @@ -532,35 +938,48 @@ i16 CenterSlicer(t_pmr_sps *mySps) uhit=1; } } - - if(--discounteru<=0 && amax>0) + #if 0 + if((discounteru-=1)<=0 && amax>amin) { - amax--; + if((amax-=10)amax)amin=amax; lhit=1; } - - if(uhit)discounteru=discfactor; - if(lhit)discounterl=discfactor; - + if(uhit)discounteru=discfactor; + if(lhit)discounterl=discfactor; + + #else + + if((amax-=discfactor)amax)amin=amax; + + #endif + apeak = (amax-amin)/2; center = (amax+amin)/2; accum = accum - center; - output[i]=accum; - - // do limiter function + + output[i]=accum; // sink output unlimited/centered. + + // do limiter function if(accum>inputGainB)accum=inputGainB; else if(accum<-inputGainB)accum=-inputGainB; buff[i]=accum; #if XPMR_DEBUG0 == 1 #if 0 - mySps->debugBuff0[i]=center; + mySps->parentChan->pRxLsdCen[i]=center; // trace center ref + #else + static i32 tfx=0; + if((tfx++/8)&1) // trace min/max levels + mySps->parentChan->pRxLsdCen[i]=amax; + else + mySps->parentChan->pRxLsdCen[i]=amin; #endif #if 0 if(mySps->parentChan->frameCountRx&0x01) mySps->parentChan->prxDebug1[i]=amax; @@ -599,7 +1018,7 @@ i16 MeasureBlock(t_pmr_sps *mySps) i32 discounterl; // amplitude detector integrator discharge counter lower i32 discfactor; // amplitude detector integrator discharge factor - TRACEX(("MeasureBlock() %i\n",mySps->enabled)); + TRACEJ(5,("MeasureBlock() %i\n",mySps->enabled)); if(!mySps->enabled)return 1; @@ -657,7 +1076,7 @@ i16 MeasureBlock(t_pmr_sps *mySps) apeak = (i32)(amax-amin)/2; if(output)output[i]=apeak; } - + mySps->amax=amax; mySps->amin=amin; mySps->apeak=apeak; @@ -665,7 +1084,7 @@ i16 MeasureBlock(t_pmr_sps *mySps) mySps->discounterl=discounterl; if(apeak>=setpt) mySps->compOut=1; else mySps->compOut=0; - + //TRACEX((" -MeasureBlock()=%i\n",mySps->apeak)); return 0; } @@ -701,7 +1120,7 @@ i16 SoftLimiter(t_pmr_sps *mySps) amax=(setpt*124)/128; amin=-amax; - TRACEX(("SoftLimiter() %i %i %i) \n",amin, amax,setpt)); + TRACEJ(5,("SoftLimiter() %i %i %i) \n",amin, amax,setpt)); for(i=0;ioption)); + i32 accum; + + t_pmr_chan *pChan; + pChan=mySps->parentChan; + TRACEC(5,("SigGen(%i %i %i)\n",mySps->option,mySps->enabled,mySps->state)); if(!mySps->freq ||!mySps->enabled)return 0; outputgain=mySps->outputGain; waveform=0; - numChanOut=mySps->numChanOut; + numChanOut=mySps->numChanOut; selChanOut=mySps->selChanOut; if(mySps->option==1) @@ -762,8 +1183,8 @@ i16 SigGen(t_pmr_sps *mySps) mySps->state=1; mySps->discfactor= (SAMPLES_PER_SINE*mySps->freq*PH_FRACT_FACT)/mySps->sampleRate/10; - - TRACEX((" SigGen() discfactor = %i\n",mySps->discfactor)); + + TRACEF(5,(" SigGen() discfactor = %i\n",mySps->discfactor)); if(mySps->discounterl)mySps->state=2; } else if(mySps->option==2) @@ -772,7 +1193,7 @@ i16 SigGen(t_pmr_sps *mySps) // phase shift request mySps->option=0; mySps->state=2; - mySps->discounterl=CTCSS_TURN_OFF_TIME-(2*MS_PER_FRAME); // + mySps->discounterl=CTCSS_TURN_OFF_TIME-(2*MS_PER_FRAME); // mySps->discounteru = \ (mySps->discounteru + (((SAMPLES_PER_SINE*shiftfactor)/360)*PH_FRACT_FACT)) % (SAMPLES_PER_SINE*PH_FRACT_FACT); @@ -838,7 +1259,7 @@ i16 SigGen(t_pmr_sps *mySps) /* adder/mixer takes existing buffer and adds source buffer to destination buffer - sink buffer = (sink buffer * gain) + source buffer + sink buffer = (sink buffer * gain) + source buffer */ i16 pmrMixer(t_pmr_sps *mySps) { @@ -849,7 +1270,9 @@ i16 pmrMixer(t_pmr_sps *mySps) i16 discounteru,discounterl,amax,amin,setpt,discfactor; i16 npoints,uhit,lhit,apeak,measPeak; - TRACEX(("pmrMixer()\n")); + t_pmr_chan *pChan; + pChan=mySps->parentChan; + TRACEF(5,("pmrMixer()\n")); input = mySps->source; inputB = mySps->sourceB; @@ -858,7 +1281,7 @@ i16 pmrMixer(t_pmr_sps *mySps) inputGain=mySps->inputGain; inputGainB=mySps->inputGainB; outputGain=mySps->outputGain; - + amax=mySps->amax; amin=mySps->amin; setpt=mySps->setpt; @@ -871,7 +1294,7 @@ i16 pmrMixer(t_pmr_sps *mySps) for(i=0;iamax){ amax=accum; uhit=1; @@ -896,20 +1319,20 @@ i16 pmrMixer(t_pmr_sps *mySps) uhit=1; } } - + if(--discounteru<=0 && amax>0){ amax--; uhit=1; } - + if(--discounterl<=0 && amin<0){ amin++; lhit=1; } - - if(uhit)discounteru=discfactor; + + if(uhit)discounteru=discfactor; if(lhit)discounterl=discfactor; - } + } } if(measPeak){ @@ -920,19 +1343,21 @@ i16 pmrMixer(t_pmr_sps *mySps) mySps->discounteru=discounteru; mySps->discounterl=discounterl; } - + return 0; } /* - DelayLine + DelayLine */ i16 DelayLine(t_pmr_sps *mySps) { i16 *input, *output, *buff; i16 i, npoints,buffsize,inindex,outindex; - TRACEX((" DelayLine() %i\n",mySps->enabled)); - + t_pmr_chan *pChan; + pChan=mySps->parentChan; + TRACEF(5,(" DelayLine() %i\n",mySps->enabled)); + input = mySps->source; output = mySps->sink; buff = (i16*)(mySps->buff); @@ -946,7 +1371,7 @@ i16 DelayLine(t_pmr_sps *mySps) { inindex %= buffsize; outindex %= buffsize; - + buff[inindex]=input[i]; output[i]=buff[outindex]; inindex++; @@ -959,25 +1384,27 @@ i16 DelayLine(t_pmr_sps *mySps) /* Continuous Tone Coded Squelch (CTCSS) Detector */ -i16 ctcss_detect(t_pmr_chan *pmrChan) +i16 ctcss_detect(t_pmr_chan *pChan) { - i16 i,points2do, points=0, *pInput, hit, thit,relax; - i16 tnum, tmp, indexWas=0, indexNow, gain, peakwas=0, diffpeak; + i16 i,points2do,*pInput,hit,thit,relax; + i16 tnum, tmp,indexNow,gain,diffpeak; i16 difftrig; - i16 lasttv0=0, lasttv1=0, lasttv2=0, tv0, tv1, tv2, indexDebug; + i16 tv0,tv1,tv2,tv3,indexDebug; + i16 points=0; + i16 indexWas=0; - TRACEX(("ctcss_detect(%p) %i %i %i %i\n",pmrChan, - pmrChan->rxCtcss->enabled, - pmrChan->rxCtcssIndex, - pmrChan->rxCtcss->testIndex, - pmrChan->rxCtcss->decode)); + TRACEF(5,("ctcss_detect(%p) %i %i %i %i\n",pChan, + pChan->rxCtcss->enabled, + 0, + pChan->rxCtcss->testIndex, + pChan->rxCtcss->decode)); - if(!pmrChan->rxCtcss->enabled)return(1); + if(!pChan->rxCtcss->enabled)return(1); + + relax = pChan->rxCtcss->relax; + pInput = pChan->rxCtcss->input; + gain = pChan->rxCtcss->gain; - relax = pmrChan->rxCtcss->relax; - pInput = pmrChan->rxCtcss->input; - gain = pmrChan->rxCtcss->gain; - if(relax) difftrig=(-0.1*M_Q15); else difftrig=(-0.05*M_Q15); @@ -992,35 +1419,32 @@ i16 ctcss_detect(t_pmr_chan *pmrChan) i16 fudgeFactor; i16 binFactor; - //TRACEX((" ctcss_detect() tnum=%i %i\n",tnum,pmrChan->rxCtcssMap[tnum])); + TRACEF(6,(" ctcss_detect() tnum=%i %i\n",tnum,pChan->rxCtcssMap[tnum])); + //if(tnum==14)printf("ctcss_detect() %i %i %i\n",tnum,pChan->rxCtcssMap[tnum], pChan->rxCtcss->decode ); - if( (pmrChan->rxCtcssMap[tnum] < 0) || - (pmrChan->rxCtcss->decode>=0 && (tnum!= pmrChan->rxCtcss->decode)) || - (!pmrChan->rxCtcss->multiFreq && (tnum!= pmrChan->rxCtcssIndex)) + if( (pChan->rxCtcssMap[tnum]==CTCSS_NULL) || + (pChan->rxCtcss->decode>CTCSS_NULL && (tnum!= pChan->rxCtcss->decode)) ) continue; - //TRACEX((" ctcss_detect() tnum=%i\n",tnum)); + TRACEF(6,(" ctcss_detect() tnum=%i\n",tnum)); - ptdet=&(pmrChan->rxCtcss->tdet[tnum]); + ptdet=&(pChan->rxCtcss->tdet[tnum]); indexDebug=0; - points=points2do=pmrChan->nSamplesRx; + points=points2do=pChan->nSamplesRx; fudgeFactor=ptdet->fudgeFactor; binFactor=ptdet->binFactor; while(ptdet->counter < (points2do*CTCSS_SCOUNT_MUL)) { - //TRACEX((" ctcss_detect() - inner loop\n")); tmp=(ptdet->counter/CTCSS_SCOUNT_MUL)+1; ptdet->counter-=(tmp*CTCSS_SCOUNT_MUL); points2do-=tmp; indexNow=points-points2do; - - ptdet->counter += ptdet->counterFactor; - accum = pInput[indexNow-1]; // dude's major bug fix! + ptdet->counter += ptdet->counterFactor; - peakwas=ptdet->peak; + accum = pInput[indexNow-1]; // duuuude's major bug fix! ptdet->z[ptdet->zIndex]+= (((accum - ptdet->z[ptdet->zIndex])*binFactor)/M_Q15); @@ -1037,7 +1461,7 @@ i16 ctcss_detect(t_pmr_chan *pmrChan) static const i16 a1=-13723; i32 temp0,temp1; i16 x0; - + //differentiate x0=ptdet->zd; temp0 = x0 * a1; @@ -1053,7 +1477,7 @@ i16 ctcss_detect(t_pmr_chan *pmrChan) else if(ptdet->dvu)ptdet->dvu--; tmp=ptdet->setpt; - if(pmrChan->rxCtcss->decode==tnum) + if(pChan->rxCtcss->decode==tnum) { if(relax)tmp=(tmp*55)/100; else tmp=(tmp*80)/100; @@ -1063,54 +1487,67 @@ i16 ctcss_detect(t_pmr_chan *pmrChan) { if(ptdet->decode<(fudgeFactor*32))ptdet->decode++; } - else if(pmrChan->rxCtcss->decode==tnum) + else if(pChan->rxCtcss->decode==tnum) { if(ptdet->peak > ptdet->hyst)ptdet->decode--; - else if(relax) ptdet->decode--; - else ptdet->decode-=4; + else if(relax) ptdet->decode--; + else ptdet->decode-=4; } else { ptdet->decode=0; } - if((pmrChan->rxCtcss->decode==tnum) && !relax && (ptdet->dvu > (0.00075*M_Q15))) + if((pChan->rxCtcss->decode==tnum) && !relax && (ptdet->dvu > (0.00075*M_Q15))) { ptdet->decode=0; ptdet->z[0]=ptdet->z[1]=ptdet->z[2]=ptdet->z[3]=ptdet->dvu=0; - //printf("ctcss_detect() turnoff code!\n"); + TRACEF(4,("ctcss_detect() turnoff detected by dvdt for tnum = %i.\n",tnum)); } - if(ptdet->decode<0 || !pmrChan->rxCarrierDetect)ptdet->decode=0; + if(ptdet->decode<0 || !pChan->rxCarrierDetect)ptdet->decode=0; - if(ptdet->decode>=fudgeFactor)thit=tnum; - - #if XPMR_DEBUG0 == 1 - //if(thit>=0 && thit==tnum) - // printf(" ctcss_detect() %i %i %i %i \n",tnum,ptdet->peak,ptdet->setpt,ptdet->hyst); - - // tv0=accum; - tv0=ptdet->peak; - tv1=diffpeak; - tv2=ptdet->dvu; - - //tv1=ptdet->zi*100; - while(indexDebugdecode>=fudgeFactor) { - if(indexDebug==0)lasttv0=ptdet->pDebug0[points-1]; - if(ptdet->pDebug0)ptdet->pDebug0[indexDebug]=lasttv0; + thit=tnum; + if(pChan->rxCtcss->decode!=tnum) + { + ptdet->zd=ptdet->dvu=ptdet->dvd=0; + } + } - if(indexDebug==0)lasttv1=ptdet->pDebug1[points-1]; - if(ptdet->pDebug1)ptdet->pDebug1[indexDebug]=lasttv1; + #if XPMR_DEBUG0 == 1 + if(thit>=0 && thit==tnum) + TRACEF(6,(" ctcss_detect() %i %i %i %i \n",tnum,ptdet->peak,ptdet->setpt,ptdet->hyst)); - if(indexDebug==0)lasttv2=ptdet->pDebug2[points-1]; - if(ptdet->pDebug2)ptdet->pDebug2[indexDebug]=lasttv2; + if(ptdet->pDebug0) + { + tv0=ptdet->peak; + tv1=ptdet->decode; + tv2=tmp; + tv3=ptdet->dvu*32; + + if(indexDebug==0) + { + ptdet->lasttv0=ptdet->pDebug0[points-1]; + ptdet->lasttv1=ptdet->pDebug1[points-1]; + ptdet->lasttv2=ptdet->pDebug2[points-1]; + ptdet->lasttv3=ptdet->pDebug3[points-1]; + } - indexDebug++; + while(indexDebugpDebug0[indexDebug]=ptdet->lasttv0; + ptdet->pDebug1[indexDebug]=ptdet->lasttv1; + ptdet->pDebug2[indexDebug]=ptdet->lasttv2; + ptdet->pDebug3[indexDebug]=ptdet->lasttv3; + indexDebug++; + } + ptdet->lasttv0=tv0; + ptdet->lasttv1=tv1; + ptdet->lasttv2=tv2; + ptdet->lasttv3=tv3; } - lasttv0=tv0; - lasttv1=tv1; - lasttv2=tv2*100; #endif indexWas=indexNow; ptdet->zIndex=(++ptdet->zIndex)%4; @@ -1120,36 +1557,40 @@ i16 ctcss_detect(t_pmr_chan *pmrChan) #if XPMR_DEBUG0 == 1 for(i=indexWas;ipDebug0)ptdet->pDebug0[i]=lasttv0; - if(ptdet->pDebug1)ptdet->pDebug1[i]=lasttv1; - if(ptdet->pDebug2)ptdet->pDebug2[i]=lasttv2; + ptdet->pDebug0[i]=ptdet->lasttv0; + ptdet->pDebug1[i]=ptdet->lasttv1; + ptdet->pDebug2[i]=ptdet->lasttv2; + ptdet->pDebug3[i]=ptdet->lasttv3; } #endif } //TRACEX((" ctcss_detect() thit %i\n",thit)); - if(pmrChan->rxCtcss->BlankingTimer>0)pmrChan->rxCtcss->BlankingTimer-=points; - if(pmrChan->rxCtcss->BlankingTimer<0)pmrChan->rxCtcss->BlankingTimer=0; + if(pChan->rxCtcss->BlankingTimer>0)pChan->rxCtcss->BlankingTimer-=points; + if(pChan->rxCtcss->BlankingTimer<0)pChan->rxCtcss->BlankingTimer=0; - if(thit>=0 && pmrChan->rxCtcss->decode<0 && !pmrChan->rxCtcss->BlankingTimer) + if(thit>CTCSS_NULL && pChan->rxCtcss->decode<=CTCSS_NULL && !pChan->rxCtcss->BlankingTimer) { - pmrChan->rxCtcss->decode=thit; + pChan->rxCtcss->decode=thit; + sprintf(pChan->rxctcssfreq,"%.1f",freq_ctcss[thit]); + TRACEC(1,("ctcss decode %i %.1f\n",thit,freq_ctcss[thit])); } - else if(thit<0 && pmrChan->rxCtcss->decode>=0) + else if(thit<=CTCSS_NULL && pChan->rxCtcss->decode>CTCSS_NULL) { - pmrChan->rxCtcss->BlankingTimer=SAMPLE_RATE_NETWORK/5; - pmrChan->rxCtcss->decode=-1; - + pChan->rxCtcss->BlankingTimer=SAMPLE_RATE_NETWORK/5; + pChan->rxCtcss->decode=CTCSS_NULL; + strcpy(pChan->rxctcssfreq,"0"); + TRACEC(1,("ctcss decode NULL\n")); for(tnum=0;tnumrxCtcss->tdet[tnum]); + ptdet=&(pChan->rxCtcss->tdet[tnum]); ptdet->decode=0; ptdet->z[0]=ptdet->z[1]=ptdet->z[2]=ptdet->z[3]=0; } } - //TRACEX((" ctcss_detect() thit %i %i\n",thit,pmrChan->rxCtcss->decode)); + //TRACEX((" ctcss_detect() thit %i %i\n",thit,pChan->rxCtcss->decode)); return(0); } /* @@ -1161,6 +1602,7 @@ static i16 TxTestTone(t_pmr_chan *pChan, i16 function) { pChan->spsSigGen1->enabled=1; pChan->spsSigGen1->option=1; + pChan->spsSigGen1->outputGain=(.23125*M_Q8); // to match *99 level pChan->spsTx->source=pChan->spsSigGen1->sink; } else @@ -1169,7 +1611,7 @@ static i16 TxTestTone(t_pmr_chan *pChan, i16 function) } return 0; } -/* +/* assumes: sampling rate is 48KS/s samples are all 16 bits @@ -1178,36 +1620,37 @@ static i16 TxTestTone(t_pmr_chan *pChan, i16 function) t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) { i16 i, *inputTmp; - t_pmr_chan *pChan; t_pmr_sps *pSps; t_dec_ctcss *pDecCtcss; - t_tdet *ptdet; - TRACEX(("createPmrChannel(%p,%i)\n",tChan,numSamples)); + TRACEJ(1,("createPmrChannel(%p,%i)\n",tChan,numSamples)); pChan = (t_pmr_chan *)calloc(sizeof(t_pmr_chan),1); - if(pChan==NULL) { printf("createPmrChannel() failed\n"); return(NULL); } - - pChan->nSamplesRx=numSamples; - pChan->nSamplesTx=numSamples; + + #if XPMR_PPTP == 1 + pptp_init(); + #endif pChan->index=pmrChanIndex++; + pChan->nSamplesTx=pChan->nSamplesRx=numSamples; - for(i=0;irxCtcssMap[i]=-1; - } + pDecCtcss = (t_dec_ctcss *)calloc(sizeof(t_dec_ctcss),1); + pChan->rxCtcss=pDecCtcss; + pChan->rxctcssfreq[0]=0; - pChan->rxCtcssIndex=-1; + #ifdef HAVE_XPMRX + if(tChan->rptnum>=LSD_CHAN_MAX)tChan->rptnum=0; + #endif if(tChan==NULL) { + printf("createPmrChannel() WARNING: NULL tChan!\n"); pChan->rxNoiseSquelchEnable=0; pChan->rxHpfEnable=0; pChan->rxDeEmpEnable=0; @@ -1218,13 +1661,10 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pChan->rxCarrierPoint = 17000; pChan->rxCarrierHyst = 2500; - pChan->rxCtcssFreq=103.5; - pChan->txHpfEnable=0; pChan->txLimiterEnable=0; pChan->txPreEmpEnable=0; pChan->txLpfEnable=1; - pChan->txCtcssFreq=103.5; pChan->txMixA=TX_OUT_VOICE; pChan->txMixB=TX_OUT_LSD; } @@ -1234,49 +1674,66 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pChan->rxCdType=tChan->rxCdType; pChan->rxSquelchPoint = tChan->rxSquelchPoint; pChan->rxCarrierHyst = 3000; - pChan->rxCtcssFreq=tChan->rxCtcssFreq; + pChan->rxSqVoxAdj=tChan->rxSqVoxAdj; - for(i=0;irxCtcssMap[i]=tChan->rxCtcssMap[i]; - pChan->txMod=tChan->txMod; - pChan->txHpfEnable=1; + pChan->txHpfEnable=1; pChan->txLpfEnable=1; - pChan->txCtcssFreq=tChan->txCtcssFreq; + + pChan->pTxCodeDefault=tChan->pTxCodeDefault; + pChan->pRxCodeSrc=tChan->pRxCodeSrc; + pChan->pTxCodeSrc=tChan->pTxCodeSrc; + pChan->txMixA=tChan->txMixA; pChan->txMixB=tChan->txMixB; pChan->radioDuplex=tChan->radioDuplex; + pChan->area=tChan->area; + pChan->rptnum=tChan->rptnum; + pChan->idleinterval=tChan->idleinterval; + pChan->turnoffs=tChan->turnoffs; + pChan->b.rxpolarity=tChan->b.rxpolarity; + pChan->b.txpolarity=tChan->b.txpolarity; + pChan->b.dcsrxpolarity=tChan->b.dcsrxpolarity; + pChan->b.dcstxpolarity=tChan->b.dcstxpolarity; + pChan->b.lsdrxpolarity=tChan->b.lsdrxpolarity; + pChan->b.lsdtxpolarity=tChan->b.lsdtxpolarity; + + pChan->txsettletime=tChan->txsettletime; + pChan->tracelevel=tChan->tracelevel; + pChan->tracetype=tChan->tracetype; + pChan->ukey=tChan->ukey; + pChan->name=tChan->name; } - TRACEX(("misc settings \n")); - if(pChan->rxCdType==CD_XPMR_NOISE){ - pChan->rxNoiseSquelchEnable=1; - } + pChan->txHpfEnable=1; + pChan->txLpfEnable=1; - if(pChan->rxDemod==RX_AUDIO_FLAT){ - pChan->rxHpfEnable=1; - pChan->rxDeEmpEnable=1; - } + if(pChan->rxCdType==CD_XPMR_NOISE) pChan->rxNoiseSquelchEnable=1; + + if(pChan->rxDemod==RX_AUDIO_FLAT) pChan->rxDeEmpEnable=1; pChan->rxCarrierPoint=(pChan->rxSquelchPoint*32767)/100; pChan->rxCarrierHyst = 3000; //pChan->rxCarrierPoint/15; - + pChan->rxDcsDecodeEnable=0; - if(pChan->rxCtcssFreq!=0){ + if(pChan->b.ctcssRxEnable || pChan->b.dcsRxEnable || pChan->b.lmrRxEnable) + { pChan->rxHpfEnable=1; pChan->rxCenterSlicerEnable=1; pChan->rxCtcssDecodeEnable=1; - pChan->rxCtcssIndex=CtcssFreqIndex(pChan->rxCtcssFreq); } if(pChan->txMod){ pChan->txPreEmpEnable=1; pChan->txLimiterEnable=1; } - - TRACEX(("calloc buffers \n")); + + pChan->dd.option=9; + dedrift(pChan); + + TRACEF(1,("calloc buffers \n")); pChan->pRxDemod = calloc(numSamples,2); pChan->pRxNoise = calloc(numSamples,2); @@ -1287,8 +1744,8 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pChan->pRxCtcss = calloc(numSamples,2); pChan->pRxDcTrack = calloc(numSamples,2); pChan->pRxLsdLimit = calloc(numSamples,2); - - + + pChan->pTxInput = calloc(numSamples,2); pChan->pTxBase = calloc(numSamples,2); pChan->pTxHpf = calloc(numSamples,2); pChan->pTxPreEmp = calloc(numSamples,2); @@ -1298,13 +1755,20 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pChan->pTxComposite = calloc(numSamples,2); pChan->pSigGen0 = calloc(numSamples,2); pChan->pSigGen1 = calloc(numSamples,2); + + pChan->prxMeasure = calloc(numSamples,2); - pChan->pTxCode = calloc(numSamples,2); pChan->pTxOut = calloc(numSamples,2*2*6); // output buffer - + +#ifdef HAVE_XPMRX + pChan->pLsdEnc = calloc(sizeof(t_encLsd),1); +#endif + #if XPMR_DEBUG0 == 1 - pChan->pTxPttIn = calloc(numSamples,2); - pChan->pTxPttOut = calloc(numSamples,2); + TRACEF(1,("configure tracing\n")); + + pChan->pTstTxOut = calloc(numSamples,2); + pChan->pRxLsdCen = calloc(numSamples,2); pChan->prxDebug0 = calloc(numSamples,2); pChan->prxDebug1 = calloc(numSamples,2); pChan->prxDebug2 = calloc(numSamples,2); @@ -1314,41 +1778,175 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pChan->ptxDebug2 = calloc(numSamples,2); pChan->ptxDebug3 = calloc(numSamples,2); pChan->pNull = calloc(numSamples,2); - for(i=0;ipNull[i]=((i%(numSamples/2))*8000)-4000; - #endif - TRACEX(("create ctcss\n")); + for(i=0;ipNull[i]=((i%(numSamples/2))*8000)-4000; - pDecCtcss = (t_dec_ctcss *)calloc(sizeof(t_dec_ctcss),1); - - pChan->rxCtcss=pDecCtcss; - pDecCtcss->enabled=1; - pDecCtcss->gain=1*M_Q8; - pDecCtcss->limit=8192; - pDecCtcss->input=pChan->pRxLsdLimit; - pDecCtcss->testIndex=pChan->rxCtcssIndex; - if(!pDecCtcss->testIndex)pDecCtcss->testIndex=1; - pChan->rxCtcssMap[pChan->rxCtcssIndex]=pChan->rxCtcssIndex; - pDecCtcss->decode=-1; + pChan->rxCtcss->pDebug0=calloc(numSamples,2); + pChan->rxCtcss->pDebug1=calloc(numSamples,2); + pChan->rxCtcss->pDebug2=calloc(numSamples,2); + pChan->rxCtcss->pDebug3=calloc(numSamples,2); for(i=0;irxCtcss->tdet[i]); - ptdet->state=1; - ptdet->setpt=(M_Q15*0.067); // 0.069 - ptdet->hyst =(M_Q15*0.020); - ptdet->counterFactor=coef_ctcss_div[i]; - ptdet->binFactor=(M_Q15*0.135); // was 0.140 - ptdet->fudgeFactor=8; - } + pChan->rxCtcss->tdet[i].pDebug0=calloc(numSamples,2); + pChan->rxCtcss->tdet[i].pDebug1=calloc(numSamples,2); + pChan->rxCtcss->tdet[i].pDebug2=calloc(numSamples,2); + pChan->rxCtcss->tdet[i].pDebug3=calloc(numSamples,2); + } + + // buffer, 2 bytes per sample, and 16 channels + pChan->prxDebug=calloc(numSamples*16,2); + pChan->ptxDebug=calloc(numSamples*16,2); + + // TSCOPE CONFIGURATION SETSCOPE configure debug traces and sources for each channel of the output + pChan->sdbg = (t_sdbg *)calloc(sizeof(t_sdbg),1); + + for(i=0;isdbg->trace[i]=-1; + + TRACEF(1,("pChan->tracetype = %i\n",pChan->tracetype)); + + if(pChan->tracetype==1) // CTCSS DECODE + { + pChan->sdbg->source [0]=pChan->pRxDemod; + pChan->sdbg->source [1]=pChan->pRxBase; + pChan->sdbg->source [2]=pChan->pRxNoise; + pChan->sdbg->trace [3]=RX_NOISE_TRIG; + pChan->sdbg->source [4]=pChan->pRxLsd; + pChan->sdbg->source [5]=pChan->pRxLsdCen; + pChan->sdbg->source [6]=pChan->pRxLsdLimit; + pChan->sdbg->source [7]=pChan->rxCtcss->tdet[3].pDebug0; + pChan->sdbg->trace [8]=RX_CTCSS_DECODE; + pChan->sdbg->trace [9]=RX_SMODE; + } + if(pChan->tracetype==2) // CTCSS DECODE + { + pChan->sdbg->source [0]=pChan->pRxDemod; + pChan->sdbg->source [1]=pChan->pRxBase; + pChan->sdbg->trace [2]=RX_NOISE_TRIG; + pChan->sdbg->source [3]=pChan->pRxLsd; + pChan->sdbg->source [4]=pChan->pRxLsdCen; + pChan->sdbg->source [5]=pChan->pRxDcTrack; + pChan->sdbg->source [6]=pChan->pRxLsdLimit; + pChan->sdbg->source [7]=pChan->rxCtcss->tdet[3].pDebug0; + pChan->sdbg->source [8]=pChan->rxCtcss->tdet[3].pDebug1; + pChan->sdbg->source [9]=pChan->rxCtcss->tdet[3].pDebug2; + pChan->sdbg->source [10]=pChan->rxCtcss->tdet[3].pDebug3; + pChan->sdbg->trace [11]=RX_CTCSS_DECODE; + pChan->sdbg->trace [12]=RX_SMODE; + pChan->sdbg->trace [13]=TX_PTT_IN; + pChan->sdbg->trace [14]=TX_PTT_OUT; + pChan->sdbg->source [15]=pChan->pTxLsdLpf; + } + else if(pChan->tracetype==3) // DCS DECODE + { + pChan->sdbg->source [0]=pChan->pRxDemod; + pChan->sdbg->source [1]=pChan->pRxBase; + pChan->sdbg->trace [2]=RX_NOISE_TRIG; + pChan->sdbg->source [3]=pChan->pRxLsd; + pChan->sdbg->source [4]=pChan->pRxLsdCen; + pChan->sdbg->source [5]=pChan->pRxDcTrack; + pChan->sdbg->trace [6]=RX_DCS_CLK; + pChan->sdbg->trace [7]=RX_DCS_DIN; + pChan->sdbg->trace [8]=RX_DCS_DEC; + pChan->sdbg->trace [9]=RX_SMODE; + pChan->sdbg->trace [10]=TX_PTT_IN; + pChan->sdbg->trace [11]=TX_PTT_OUT; + pChan->sdbg->trace [12]=TX_LSD_CLK; + pChan->sdbg->trace [13]=TX_LSD_DAT; + pChan->sdbg->trace [14]=TX_LSD_GEN; + pChan->sdbg->source [14]=pChan->pTxLsd; + pChan->sdbg->source [15]=pChan->pTxLsdLpf; + } + else if(pChan->tracetype==4) // LSD DECODE + { + pChan->sdbg->source [0]=pChan->pRxDemod; + pChan->sdbg->source [1]=pChan->pRxBase; + pChan->sdbg->trace [2]=RX_NOISE_TRIG; + pChan->sdbg->source [3]=pChan->pRxLsd; + pChan->sdbg->source [4]=pChan->pRxLsdCen; + pChan->sdbg->source [5]=pChan->pRxDcTrack; + pChan->sdbg->trace [6]=RX_LSD_CLK; + pChan->sdbg->trace [7]=RX_LSD_DAT; + pChan->sdbg->trace [8]=RX_LSD_ERR; + pChan->sdbg->trace [9]=RX_LSD_SYNC; + pChan->sdbg->trace [10]=RX_SMODE; + pChan->sdbg->trace [11]=TX_PTT_IN; + pChan->sdbg->trace [12]=TX_PTT_OUT; + pChan->sdbg->trace [13]=TX_LSD_CLK; + pChan->sdbg->trace [14]=TX_LSD_DAT; + //pChan->sdbg->trace [14]=TX_LSD_GEN; + //pChan->sdbg->source [14]=pChan->pTxLsd; + pChan->sdbg->source [15]=pChan->pTxLsdLpf; + } + else if(pChan->tracetype==5) // LSD LOGIC + { + pChan->sdbg->source [0]=pChan->pRxBase; + pChan->sdbg->trace [1]=RX_NOISE_TRIG; + pChan->sdbg->source [2]=pChan->pRxDcTrack; + pChan->sdbg->trace [3]=RX_LSD_SYNC; + pChan->sdbg->trace [4]=RX_SMODE; + pChan->sdbg->trace [5]=TX_PTT_IN; + pChan->sdbg->trace [6]=TX_PTT_OUT; + pChan->sdbg->source [7]=pChan->pTxLsdLpf; + } + else if(pChan->tracetype==6) + { + // tx clock skew and jitter buffer + pChan->sdbg->source [0]=pChan->pRxDemod; + pChan->sdbg->source [5]=pChan->pTxBase; + pChan->sdbg->trace [6]=TX_DEDRIFT_LEAD; + pChan->sdbg->trace [7]=TX_DEDRIFT_ERR; + pChan->sdbg->trace [8]=TX_DEDRIFT_FACTOR; + pChan->sdbg->trace [9]=TX_DEDRIFT_DRIFT; + } + else if(pChan->tracetype==7) + { + // tx path + pChan->sdbg->source [0]=pChan->pRxBase; + pChan->sdbg->trace [1]=RX_NOISE_TRIG; + pChan->sdbg->source [2]=pChan->pRxLsd; + pChan->sdbg->trace [3]=RX_CTCSS_DECODE; + pChan->sdbg->source [4]=pChan->pRxHpf; + + pChan->sdbg->trace [5]=TX_PTT_IN; + pChan->sdbg->trace [6]=TX_PTT_OUT; + + pChan->sdbg->source [7]=pChan->pTxBase; + pChan->sdbg->source [8]=pChan->pTxHpf; + pChan->sdbg->source [9]=pChan->pTxPreEmp; + pChan->sdbg->source [10]=pChan->pTxLimiter; + pChan->sdbg->source [11]=pChan->pTxComposite; + pChan->sdbg->source [12]=pChan->pTxLsdLpf; + } + + for(i=0;isdbg->trace[i]>=0)pChan->sdbg->point[pChan->sdbg->trace[i]]=i; + } + pChan->sdbg->mode=1; + #endif + + #ifdef XPMRX_H + // LSD GENERATOR + pSps=pChan->spsLsdGen=createPmrSps(pChan); + pSps->source=NULL; + pSps->sink=pChan->pTxLsd; + pSps->numChanOut=1; + pSps->selChanOut=0; + pSps->sigProc=LsdGen; + pSps->nSamples=pChan->nSamplesTx; + pSps->outputGain=(.25*M_Q8); + pSps->option=0; + pSps->interpolate=1; + pSps->decimate=1; + pSps->enabled=0; + #endif // General Purpose Function Generator - pSps=pChan->spsSigGen1=createPmrSps(); - pSps->parentChan=pChan; - pSps->sink=pChan->pSigGen1; + pSps=pChan->spsSigGen1=createPmrSps(pChan); + pSps->sink=pChan->pSigGen1; pSps->numChanOut=1; pSps->selChanOut=0; - pSps->sigProc=SigGen; + pSps->sigProc=SigGen; pSps->nSamples=pChan->nSamplesTx; pSps->sampleRate=SAMPLE_RATE_NETWORK; pSps->freq=10000; // in increments of 0.1 Hz @@ -1360,26 +1958,24 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) // CTCSS ENCODER - pSps = pChan->spsSigGen0 = createPmrSps(); - pSps->parentChan=pChan; - pSps->sink=pChan->pTxLsd; - pSps->sigProc=SigGen; + pSps = pChan->spsSigGen0 = createPmrSps(pChan); + pSps->sink=pChan->pTxLsd; + pSps->sigProc=SigGen; pSps->numChanOut=1; pSps->selChanOut=0; pSps->nSamples=pChan->nSamplesTx; pSps->sampleRate=SAMPLE_RATE_NETWORK; - pSps->freq=pChan->txCtcssFreq*10; // in increments of 0.1 Hz + pSps->freq=1000; // in 0.1 Hz steps pSps->outputGain=(0.5*M_Q8); pSps->option=0; pSps->interpolate=1; pSps->decimate=1; pSps->enabled=0; - // Tx LSD Low Pass Filter - pSps=pChan->spsTxLsdLpf=pSps->nextSps=createPmrSps(); + pSps=pChan->spsTxLsdLpf=createPmrSps(pChan); pSps->source=pChan->pTxLsd; - pSps->sink=pChan->pTxLsdLpf; + pSps->sink=pChan->pTxLsdLpf; pSps->sigProc=pmr_gp_fir; pSps->enabled=0; pSps->numChanOut=1; @@ -1389,41 +1985,30 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pSps->interpolate=1; pSps->inputGain=(1*M_Q8); pSps->outputGain=(1*M_Q8); - - if(pChan->txCtcssFreq>203.0) - { - pSps->ncoef=taps_fir_lpf_250_9_66; - pSps->size_coef=2; - pSps->coef=(void*)coef_fir_lpf_250_9_66; - pSps->nx=taps_fir_lpf_250_9_66; - pSps->size_x=2; - pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); - pSps->calcAdjust=gain_fir_lpf_250_9_66; - } - else - { - pSps->ncoef=taps_fir_lpf_215_9_88; - pSps->size_coef=2; - pSps->coef=(void*)coef_fir_lpf_215_9_88; - pSps->nx=taps_fir_lpf_215_9_88; - pSps->size_x=2; - pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); - pSps->calcAdjust=gain_fir_lpf_215_9_88; - } + + // configure the longer, lower cutoff filter by default + pSps->ncoef=taps_fir_lpf_215_9_88; + pSps->size_coef=2; + pSps->coef=(void*)coef_fir_lpf_215_9_88; + pSps->nx=taps_fir_lpf_215_9_88; + pSps->size_x=2; + pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); + pSps->calcAdjust=gain_fir_lpf_215_9_88; pSps->inputGain=(1*M_Q8); pSps->outputGain=(1*M_Q8); - - if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); - + TRACEF(1,("spsTxLsdLpf = sps \n")); + + if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); + + // RX Process - TRACEX(("create rx\n")); + TRACEF(1,("create rx\n")); pSps = NULL; // allocate space for first sps and set pointers - pSps=pChan->spsRx=createPmrSps(); - pSps->parentChan=pChan; + pSps=pChan->spsRx=createPmrSps(pChan); pSps->source=NULL; //set when called pSps->sink=pChan->pRxBase; pSps->sigProc=pmr_rx_frontend; @@ -1440,7 +2025,7 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pSps->x=(void*)(calloc(pSps->nx,pSps->size_coef)); pSps->calcAdjust=(gain_fir_lpf_3K_1*256)/0x0100; pSps->outputGain=(1.0*M_Q8); - pSps->discfactor=2; + pSps->discfactor=2; pSps->hyst=pChan->rxCarrierHyst; pSps->setpt=pChan->rxCarrierPoint; pChan->prxSquelchAdjust=&pSps->setpt; @@ -1450,11 +2035,10 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pSps->debugBuff2=pChan->prxDebug0; #endif - + // allocate space for next sps and set pointers // Rx SubAudible Decoder Low Pass Filter - pSps=pSps->nextSps=createPmrSps(); - pSps->parentChan=pChan; + pSps=pChan->spsRxLsd=pSps->nextSps=createPmrSps(pChan); pSps->source=pChan->pRxBase; pSps->sink=pChan->pRxLsd; pSps->sigProc=pmr_gp_fir; @@ -1465,59 +2049,40 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pSps->decimator=pSps->decimate=1; pSps->interpolate=1; - if(pChan->rxCtcssFreq>203.5) - { - pSps->ncoef=taps_fir_lpf_250_9_66; - pSps->size_coef=2; - pSps->coef=(void*)coef_fir_lpf_250_9_66; - pSps->nx=taps_fir_lpf_250_9_66; - pSps->size_x=2; - pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); - pSps->calcAdjust=gain_fir_lpf_250_9_66; - } - else - { - pSps->ncoef=taps_fir_lpf_215_9_88; - pSps->size_coef=2; - pSps->coef=(void*)coef_fir_lpf_215_9_88; - pSps->nx=taps_fir_lpf_215_9_88; - pSps->size_x=2; - pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); - pSps->calcAdjust=gain_fir_lpf_215_9_88; - } + // configure the the larger, lower cutoff filter by default + pSps->ncoef=taps_fir_lpf_215_9_88; + pSps->size_coef=2; + pSps->coef=(void*)coef_fir_lpf_215_9_88; + pSps->nx=taps_fir_lpf_215_9_88; + pSps->size_x=2; + pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); + pSps->calcAdjust=gain_fir_lpf_215_9_88; pSps->inputGain=(1*M_Q8); pSps->outputGain=(1*M_Q8); pChan->prxCtcssMeasure=pSps->sink; - pChan->prxCtcssAdjust=&(pSps->outputGain); - + pChan->prxCtcssAdjust=&(pSps->outputGain); + + // CTCSS CenterSlicer + pSps=pChan->spsRxLsdNrz=pSps->nextSps=createPmrSps(pChan); + pSps->source=pChan->pRxLsd; + pSps->sink=pChan->pRxDcTrack; + pSps->buff=pChan->pRxLsdLimit; + pSps->sigProc=CenterSlicer; + pSps->nSamples=pChan->nSamplesRx; + pSps->discfactor=LSD_DFS; // centering time constant + pSps->inputGain=(1*M_Q8); + pSps->outputGain=(1*M_Q8); + pSps->setpt=4900; // ptp clamp for DC centering + pSps->inputGainB=625; // peak output limiter clip point + pSps->enabled=0; - // allocate space for next sps and set pointers - // CenterSlicer - if(pChan->rxCenterSlicerEnable) - { - pSps=pSps->nextSps=createPmrSps(); - pSps->parentChan=pChan; - pSps->source=pChan->pRxLsd; - pSps->sink=pChan->pRxDcTrack; - pSps->buff=pChan->pRxLsdLimit; - pSps->sigProc=CenterSlicer; - pSps->enabled=1; - pSps->nSamples=pChan->nSamplesRx; - pSps->discfactor=800; - pSps->inputGain=(1*M_Q8); - pSps->outputGain=(1*M_Q8); - pSps->setpt=3000; - pSps->inputGainB=1000; // limiter set point - } - // allocate space for next sps and set pointers // Rx HPF - pSps=pSps->nextSps=createPmrSps(); - pSps->parentChan=pChan; + pSps=pSps->nextSps=createPmrSps(pChan); pChan->spsRxHpf=pSps; pSps->source=pChan->pRxBase; - pSps->sink=pChan->pRxHpf; + pSps->sink=pChan->pRxHpf; pSps->sigProc=pmr_gp_fir; pSps->enabled=1; pSps->numChanOut=1; @@ -1531,49 +2096,49 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pSps->nx=taps_fir_hpf_300_9_66; pSps->size_x=2; pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); - if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); + if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); pSps->calcAdjust=gain_fir_hpf_300_9_66; pSps->inputGain=(1*M_Q8); pSps->outputGain=(1*M_Q8); + pChan->prxVoiceAdjust=&(pSps->outputGain); pChan->spsRxOut=pSps; // allocate space for next sps and set pointers // Rx DeEmp if(pChan->rxDeEmpEnable){ - pSps=pSps->nextSps=createPmrSps(); - pSps->parentChan=pChan; + pSps=pSps->nextSps=createPmrSps(pChan); pChan->spsRxDeEmp=pSps; pSps->source=pChan->pRxHpf; - pSps->sink=pChan->pRxSpeaker; - pChan->spsRxOut=pSps; // OUTPUT STRUCTURE! maw + pSps->sink=pChan->pRxSpeaker; + pChan->spsRxOut=pSps; // OUTPUT STRUCTURE! pSps->sigProc=gp_inte_00; pSps->enabled=1; pSps->nSamples=pChan->nSamplesRx; - + pSps->ncoef=taps_int_lpf_300_1_2; pSps->size_coef=2; pSps->coef=(void*)coef_int_lpf_300_1_2; - + pSps->nx=taps_int_lpf_300_1_2; pSps->size_x=4; pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); - if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); + if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); pSps->calcAdjust=gain_int_lpf_300_1_2/2; pSps->inputGain=(1.0*M_Q8); pSps->outputGain=(1.0*M_Q8); pChan->prxVoiceMeasure=pSps->sink; - pChan->prxVoiceAdjust=&(pSps->outputGain); + pChan->prxVoiceAdjust=&(pSps->outputGain); } if(pChan->rxDelayLineEnable) { - TRACEX(("create delayline\n")); - pSps=pChan->spsDelayLine=pSps->nextSps=createPmrSps(); + TRACEF(1,("create delayline\n")); + pSps=pChan->spsDelayLine=pSps->nextSps=createPmrSps(pChan); pSps->sigProc=DelayLine; - pSps->source=pChan->pRxSpeaker; + pSps->source=pChan->pRxSpeaker; pSps->sink=pChan->pRxSpeaker; pSps->enabled=0; - pSps->inputGain=1*M_Q8; + pSps->inputGain=1*M_Q8; pSps->outputGain=1*M_Q8; pSps->nSamples=pChan->nSamplesRx; pSps->buffSize=4096; @@ -1584,36 +2149,40 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) if(pChan->rxCdType==CD_XPMR_VOX) { - TRACEX(("create vox measureblock\n")); - pSps=pChan->spsRxVox=pSps->nextSps=createPmrSps(); + TRACEF(1,("create vox measureblock\n")); + pChan->prxVoxMeas=calloc(pChan->nSamplesRx,2); + + pSps=pChan->spsRxVox=pSps->nextSps=createPmrSps(pChan); pSps->sigProc=MeasureBlock; pSps->parentChan=pChan; pSps->source=pChan->pRxBase; - pSps->sink=pChan->prxDebug1; - pSps->inputGain=1*M_Q8; + pSps->sink=pChan->prxVoxMeas; + pSps->inputGain=1*M_Q8; pSps->outputGain=1*M_Q8; pSps->nSamples=pChan->nSamplesRx; pSps->discfactor=3; - pSps->setpt=(0.01*M_Q15); + if(pChan->rxSqVoxAdj==0) + pSps->setpt=(0.011*M_Q15); + else + pSps->setpt=(pChan->rxSqVoxAdj); pSps->hyst=(pSps->setpt/10); pSps->enabled=1; } // tuning measure block - pSps=pChan->spsMeasure=pSps->nextSps=createPmrSps(); - pSps->parentChan=pChan; - pSps->source=pChan->spsRx->sink; - pSps->sink=pChan->prxDebug2; + pSps=pChan->spsMeasure=pSps->nextSps=createPmrSps(pChan); + pSps->source=pChan->spsRx->sink; + pSps->sink=pChan->prxMeasure; pSps->sigProc=MeasureBlock; pSps->enabled=0; pSps->nSamples=pChan->nSamplesRx; - pSps->discfactor=10; + pSps->discfactor=10; pSps->nextSps=NULL; // last sps in chain RX // CREATE TRANSMIT CHAIN - TRACEX((" create tx\n")); + TRACEF(1,("create tx\n")); inputTmp=NULL; pSps = NULL; @@ -1622,10 +2191,10 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) // Tx HPF SubAudible if(pChan->txHpfEnable) { - pSps=createPmrSps(); + pSps=createPmrSps(pChan); pChan->spsTx=pSps; pSps->source=pChan->pTxBase; - pSps->sink=pChan->pTxHpf; + pSps->sink=pChan->pTxHpf; pSps->sigProc=pmr_gp_fir; pSps->enabled=1; pSps->numChanOut=1; @@ -1639,7 +2208,7 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pSps->nx=taps_fir_hpf_300_9_66; pSps->size_x=2; pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); - if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); + if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); pSps->calcAdjust=gain_fir_hpf_300_9_66; pSps->inputGain=(1*M_Q8); pSps->outputGain=(1*M_Q8); @@ -1649,37 +2218,36 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) // Tx PreEmphasis if(pChan->txPreEmpEnable) { - if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(); - else pSps=pSps->nextSps=createPmrSps(); - - pSps->parentChan=pChan; + if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(pChan); + else pSps=pSps->nextSps=createPmrSps(pChan); + pSps->source=inputTmp; - pSps->sink=pChan->pTxPreEmp; - + pSps->sink=pChan->pTxPreEmp; + pSps->sigProc=gp_diff; pSps->enabled=1; pSps->nSamples=pChan->nSamplesTx; - + pSps->ncoef=taps_int_hpf_4000_1_2; pSps->size_coef=2; pSps->coef=(void*)coef_int_hpf_4000_1_2; - + pSps->nx=taps_int_hpf_4000_1_2; pSps->size_x=2; pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); - pSps->outputGain=(1*M_Q8); + pSps->calcAdjust=gain_int_hpf_4000_1_2; pSps->inputGain=(1*M_Q8); - pSps->outputGain=(1*M_Q8); + pSps->outputGain=(1*M_Q8); // to match flat at 1KHz inputTmp=pSps->sink; } // Tx Limiter if(pChan->txLimiterEnable) { - if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(); - else pSps=pSps->nextSps=createPmrSps(); + if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(pChan); + else pSps=pSps->nextSps=createPmrSps(pChan); pSps->source=inputTmp; pSps->sink=pChan->pTxLimiter; pSps->sigProc=SoftLimiter; @@ -1695,38 +2263,37 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) if((pChan->txMixA==TX_OUT_COMPOSITE)||(pChan->txMixB==TX_OUT_COMPOSITE)) { if(pSps==NULL) - pSps=pChan->spsTx=createPmrSps(); + pSps=pChan->spsTx=createPmrSps(pChan); else - pSps=pSps->nextSps=createPmrSps(); + pSps=pSps->nextSps=createPmrSps(pChan); pSps->source=inputTmp; pSps->sourceB=pChan->pTxLsdLpf; //asdf ??? !!! maw pTxLsdLpf pSps->sink=pChan->pTxComposite; pSps->sigProc=pmrMixer; pSps->enabled=1; pSps->nSamples=pChan->nSamplesTx; - pSps->inputGain=2*M_Q8; - pSps->inputGainB=1*M_Q8/8; + pSps->inputGain=2*M_Q8; + pSps->inputGainB=1*M_Q8/8; pSps->outputGain=1*M_Q8; pSps->setpt=0; inputTmp=pSps->sink; pChan->ptxCtcssAdjust=&pSps->inputGainB; } - // Chan A Upsampler and Filter - if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(); - else pSps=pSps->nextSps=createPmrSps(); + // Chan A Upsampler and Filter + if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(pChan); + else pSps=pSps->nextSps=createPmrSps(pChan); pChan->spsTxOutA=pSps; if(!pChan->spsTx)pChan->spsTx=pSps; - pSps->parentChan=pChan; if(pChan->txMixA==TX_OUT_COMPOSITE) { - pSps->source=pChan->pTxComposite; + pSps->source=pChan->pTxComposite; } else if(pChan->txMixA==TX_OUT_LSD) { - pSps->source=pChan->pTxLsdLpf; + pSps->source=pChan->pTxLsdLpf; } else if(pChan->txMixA==TX_OUT_VOICE) { @@ -1734,14 +2301,15 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) } else if (pChan->txMixA==TX_OUT_AUX) { - pSps->source=inputTmp; + pSps->source=inputTmp; } else { - pSps->source=NULL; + pSps->source=NULL; // maw sph asdf !!! no blow up + pSps->source=inputTmp; } - - pSps->sink=pChan->pTxOut; + + pSps->sink=pChan->pTxOut; pSps->sigProc=pmr_gp_fir; pSps->enabled=1; pSps->numChanOut=2; @@ -1754,7 +2322,7 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pSps->nx=taps_fir_lpf_3K_1; pSps->size_x=2; pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); - if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); + if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n"); pSps->calcAdjust=gain_fir_lpf_3K_1; pSps->inputGain=(1*M_Q8); pSps->outputGain=(1*M_Q8); @@ -1762,17 +2330,16 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) else pSps->monoOut=0; - // Chan B Upsampler and Filter + // Chan B Upsampler and Filter if((pChan->txMixA!=pChan->txMixB)&&(pChan->txMixB!=TX_OUT_OFF)) { - if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(); - else pSps=pSps->nextSps=createPmrSps(); + if(pSps==NULL) pSps=pChan->spsTx=createPmrSps(pChan); + else pSps=pSps->nextSps=createPmrSps(pChan); pChan->spsTxOutB=pSps; - pSps->parentChan=pChan; if(pChan->txMixB==TX_OUT_COMPOSITE) { - pSps->source=pChan->pTxComposite; + pSps->source=pChan->pTxComposite; } else if(pChan->txMixB==TX_OUT_LSD) { @@ -1789,10 +2356,10 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) } else { - pSps->source=NULL; + pSps->source=NULL; } - pSps->sink=pChan->pTxOut; + pSps->sink=pChan->pTxOut; pSps->sigProc=pmr_gp_fir; pSps->enabled=1; pSps->numChanOut=2; @@ -1810,46 +2377,33 @@ t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples) pSps->calcAdjust=(gain_fir_lpf_3K_1); pSps->inputGain=(1*M_Q8); pSps->outputGain=(1*M_Q8); - } pSps->nextSps=NULL; - #if XPMR_DEBUG0 == 1 - { - t_tdet *ptdet; - TRACEX((" configure tracing\n")); - - pChan->rxCtcss->pDebug0=calloc(numSamples,2); - pChan->rxCtcss->pDebug1=calloc(numSamples,2); - pChan->rxCtcss->pDebug2=calloc(numSamples,2); - - for(i=0;irxCtcss->tdet[i]); - ptdet->pDebug0=calloc(numSamples,2); - ptdet->pDebug1=calloc(numSamples,2); - ptdet->pDebug2=calloc(numSamples,2); - } + // Configure Coded Signaling + code_string_parse(pChan); - // buffer, 2 bytes per sample, and 16 channels - pChan->prxDebug=calloc(numSamples*16,2); - pChan->ptxDebug=calloc(numSamples*16,2); - } - #endif + pChan->smode=SMODE_NULL; + pChan->smodewas=SMODE_NULL; + pChan->smodetime=2500; + pChan->smodetimer=0; + pChan->b.smodeturnoff=0; + + pChan->txsettletimer=0; - TRACEX((" createPmrChannel() end\n")); + TRACEF(1,("createPmrChannel() end\n")); return pChan; } -/* +/* */ i16 destroyPmrChannel(t_pmr_chan *pChan) { t_pmr_sps *pmr_sps, *tmp_sps; - i16 i; - - TRACEX(("destroyPmrChannel()\n")); + TRACEF(1,("destroyPmrChannel()\n")); + free(pChan->pRxDemod); free(pChan->pRxNoise); free(pChan->pRxBase); @@ -1865,20 +2419,16 @@ i16 destroyPmrChannel(t_pmr_chan *pChan) free(pChan->pTxLsd); free(pChan->pTxLsdLpf); if(pChan->pTxComposite)free(pChan->pTxComposite); - free(pChan->pTxCode); free(pChan->pTxOut); + if(pChan->prxMeasure)free(pChan->prxMeasure); if(pChan->pSigGen0)free(pChan->pSigGen0); if(pChan->pSigGen1)free(pChan->pSigGen1); + #if XPMR_DEBUG0 == 1 - free(pChan->pTxPttIn); - free(pChan->pTxPttOut); - if(pChan->prxDebug)free(pChan->prxDebug); + //if(pChan->prxDebug)free(pChan->prxDebug); if(pChan->ptxDebug)free(pChan->ptxDebug); - free(pChan->rxCtcss->pDebug0); - free(pChan->rxCtcss->pDebug1); - free(pChan->prxDebug0); free(pChan->prxDebug1); free(pChan->prxDebug2); @@ -1889,18 +2439,28 @@ i16 destroyPmrChannel(t_pmr_chan *pChan) free(pChan->ptxDebug2); free(pChan->ptxDebug3); + free(pChan->rxCtcss->pDebug0); + free(pChan->rxCtcss->pDebug1); + + i16 i; for(i=0;irxCtcss->tdet[i].pDebug0); free(pChan->rxCtcss->tdet[i].pDebug1); free(pChan->rxCtcss->tdet[i].pDebug2); + free(pChan->rxCtcss->tdet[i].pDebug3); } #endif + pChan->dd.option=8; + dedrift(pChan); + free(pChan->pRxCtcss); pmr_sps=pChan->spsRx; - + + if(pChan->sdbg)free(pChan->sdbg); + while(pmr_sps) { tmp_sps = pmr_sps; @@ -1914,16 +2474,19 @@ i16 destroyPmrChannel(t_pmr_chan *pChan) } /* */ -t_pmr_sps *createPmrSps(void) +t_pmr_sps *createPmrSps(t_pmr_chan *pChan) { t_pmr_sps *pSps; - TRACEX(("createPmrSps()\n")); + TRACEF(1,("createPmrSps()\n")); pSps = (t_pmr_sps *)calloc(sizeof(t_pmr_sps),1); if(!pSps)printf("Error: createPmrSps()\n"); + pSps->parentChan=pChan; + pSps->index=pChan->spsIndex++; + // pSps->x=calloc(pSps->nx,pSps->size_x); return pSps; @@ -1932,21 +2495,63 @@ t_pmr_sps *createPmrSps(void) */ i16 destroyPmrSps(t_pmr_sps *pSps) { - TRACEX(("destroyPmrSps(%i)\n",pSps->index)); + TRACEJ(1,("destroyPmrSps(%i)\n",pSps->index)); if(pSps->x!=NULL)free(pSps->x); free(pSps); return 0; } -/* - PmrRx does the whole buffer +/* + PmrTx - takes data from network and holds it for PmrRx */ -i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *output) +i16 PmrTx(t_pmr_chan *pChan, i16 *input) { - int i,ii; + pChan->frameCountTx++; + + TRACEF(5,("PmrTx() start %i\n",pChan->frameCountTx)); + + #if XPMR_PPTP == 99 + pptp_p2^=1; + if(pptp_p2)ioctl(ppdrvdev,PPDRV_IOC_PINSET,LP_PIN02); + else ioctl(ppdrvdev,PPDRV_IOC_PINCLEAR,LP_PIN02); + #endif + + if(pChan==NULL){ + printf("PmrTx() pChan == NULL\n"); + return 1; + } + + #if XPMR_DEBUG0 == 1 + if(pChan->b.rxCapture && pChan->tracetype==5) + { + memcpy(pChan->pTxInput,input,pChan->nSamplesRx*2); + } + #endif + + //if(pChan->b.radioactive)pChan->dd.debug=1; + //else pChan->dd.debug=0; + + dedrift_write(pChan,input); + + return 0; +} +/* + PmrRx handles a block of data from the usb audio device +*/ +i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *outputrx, i16 *outputtx) +{ + int i,hit; + float f=0; t_pmr_sps *pmr_sps; - TRACEX(("PmrRx() %i\n",pChan->frameCountRx)); + TRACEC(5,("PmrRx(%p %p %p %p)\n",pChan, input, outputrx, outputtx)); + + #if XPMR_PPTP == 1 + if(pChan->b.radioactive) + { + pptp_write(1,pChan->frameCountRx&0x00000001); + } + #endif if(pChan==NULL){ printf("PmrRx() pChan == NULL\n"); @@ -1955,10 +2560,23 @@ i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *output) pChan->frameCountRx++; + #if XPMR_DEBUG0 == 1 + if(pChan->b.rxCapture) + { + //if(pChan->prxDebug)memset((void *)pChan->prxDebug,0,pChan->nSamplesRx*XPMR_DEBUG_CHANS*2); + if(pChan->ptxDebug)memset((void *)pChan->ptxDebug,0,pChan->nSamplesRx*XPMR_DEBUG_CHANS*2); + if(pChan->sdbg->buffer) + { + memset((void *)pChan->sdbg->buffer,0,pChan->nSamplesRx*XPMR_DEBUG_CHANS*2); + pChan->prxDebug=pChan->sdbg->buffer; + } + } + #endif + pmr_sps=pChan->spsRx; // first sps pmr_sps->source=input; - if(output!=NULL)pChan->spsRxOut->sink=output; //last sps + if(outputrx!=NULL)pChan->spsRxOut->sink=outputrx; //last sps #if 0 if(pChan->inputBlanking>0) @@ -1969,30 +2587,38 @@ i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *output) input[i]=0; } #endif - - // || (pChan->radioDuplex && (pChan->pttIn || pChan->pttOut))) - if(pChan->rxCpuSaver && !pChan->rxCarrierDetect) + + if( pChan->rxCpuSaver && !pChan->rxCarrierDetect && + pChan->smode==SMODE_NULL && + !pChan->txPttIn && !pChan->txPttOut) { - if(pChan->spsRxHpf)pChan->spsRxHpf->enabled=0; - if(pChan->spsRxDeEmp)pChan->spsRxDeEmp->enabled=0; + if(!pChan->b.rxhalted) + { + if(pChan->spsRxHpf)pChan->spsRxHpf->enabled=0; + if(pChan->spsRxDeEmp)pChan->spsRxDeEmp->enabled=0; + pChan->b.rxhalted=1; + TRACEC(1,("PmrRx() rx sps halted\n")); + } } - else + else if(pChan->b.rxhalted) { if(pChan->spsRxHpf)pChan->spsRxHpf->enabled=1; if(pChan->spsRxDeEmp)pChan->spsRxDeEmp->enabled=1; + pChan->b.rxhalted=0; + TRACEC(1,("PmrRx() rx sps un-halted\n")); } i=0; while(pmr_sps!=NULL && pmr_sps!=0) { - TRACEX(("PmrRx() sps %i\n",i++)); + TRACEC(5,("PmrRx() sps %i\n",i++)); pmr_sps->sigProc(pmr_sps); pmr_sps = (t_pmr_sps *)(pmr_sps->nextSps); //pmr_sps=NULL; // sph maw } #define XPMR_VOX_HANGTIME 2000 - + if(pChan->rxCdType==CD_XPMR_VOX) { if(pChan->spsRxVox->compOut) @@ -2015,242 +2641,692 @@ i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *output) pChan->rxCarrierDetect=!pChan->spsRx->compOut; } - if( !pChan->rxCpuSaver || pChan->rxCarrierDetect - || pChan->rxCtcss->decode!=-1) ctcss_detect(pChan); + // stop and start these engines instead to eliminate falsing + if( pChan->b.ctcssRxEnable && + ( (!pChan->b.rxhalted || + pChan->rxCtcss->decode!=CTCSS_NULL || pChan->smode==SMODE_CTCSS) && + (pChan->smode!=SMODE_DCS&&pChan->smode!=SMODE_LSD) ) + ) + { + ctcss_detect(pChan); + } - #if XPMR_DEBUG0 == 1 - // TRACEX(("Write file.\n")); - ii=0; - if(pChan->b.rxCapture) + #if 1 + if(pChan->txPttIn!=pChan->b.pttwas) { - for(i=0;inSamplesRx;i++) - { - pChan->prxDebug[ii++]=input[i*2*6]; // input data - pChan->prxDebug[ii++]=output[i]; // output data - pChan->prxDebug[ii++]=pChan->rxCarrierDetect*M_Q14; // carrier detect - if(pChan->rxCtcss) - pChan->prxDebug[ii++]=pChan->rxCtcss->decode*M_Q15/CTCSS_NUM_CODES; // decoded ctcss - else - pChan->prxDebug[ii++]=0; - - pChan->prxDebug[ii++]=pChan->pRxNoise[i]; // rssi - pChan->prxDebug[ii++]=pChan->pRxBase[i]; // decimated, low pass filtered - pChan->prxDebug[ii++]=pChan->pRxHpf[i]; // output to network - pChan->prxDebug[ii++]=pChan->pRxSpeaker[i]; - - pChan->prxDebug[ii++]=pChan->pRxLsd[i]; // CTCSS Filtered - pChan->prxDebug[ii++]=pChan->pRxDcTrack[i]; // DC Restoration - pChan->prxDebug[ii++]=pChan->pRxLsdLimit[i]; // Amplitude Limited - - //pChan->prxDebug[ii++]=pChan->rxCtcss->tdet[pChan->rxCtcss->testIndex+1].pDebug0[i]; // Upper Adjacent CTCSS Code - pChan->prxDebug[ii++]=pChan->rxCtcss->tdet[pChan->rxCtcss->testIndex].pDebug0[i]; // Primary CTCSS Code - pChan->prxDebug[ii++]=pChan->rxCtcss->tdet[pChan->rxCtcss->testIndex].pDebug1[i]; // dv/dt of decoder output - pChan->prxDebug[ii++]=pChan->rxCtcss->tdet[pChan->rxCtcss->testIndex].pDebug2[i]; - - //pChan->prxDebug[ii++]=pChan->rxCtcss->tdet[pChan->rxCtcss->testIndex-1].pDebug0[i]; // Lower Adjacent CTCSS Code - - pChan->prxDebug[ii++]=pChan->prxDebug1[i]; // Measure Output for VOX - pChan->prxDebug[ii++]=pChan->prxDebug2[i]; // Measure Output for Tuning - } + pChan->b.pttwas=pChan->txPttIn; + TRACEC(1,("PmrRx() txPttIn=%i\n",pChan->b.pttwas)); } #endif - return 0; -} -/* - PmrTx does the whole buffer -*/ -i16 PmrTx(t_pmr_chan *pChan, i16 *input, i16 *output) -{ - int i, hit=0; - t_pmr_sps *pmr_sps; - - pChan->frameCountTx++; - - TRACEX(("PmrTx() %i\n",pChan->frameCountTx)); + #ifdef XPMRX_H + xpmrx(pChan,XXO_RXDECODE); + #endif - if(pChan==NULL){ - printf("PmrTx() pChan == NULL\n"); - return 1; + if(pChan->smodetimer>0 && !pChan->txPttIn) + { + pChan->smodetimer-=MS_PER_FRAME; + + if(pChan->smodetimer<=0) + { + pChan->smodetimer=0; + pChan->smodewas=pChan->smode; + pChan->smode=SMODE_NULL; + pChan->b.smodeturnoff=1; + TRACEC(1,("smode timeout. smode was=%i\n",pChan->smodewas)); + } } - if(pChan->b.startSpecialTone) - { - pChan->b.startSpecialTone=0; - pChan->spsSigGen1->option=1; - pChan->spsSigGen1->enabled=1; - pChan->b.doingSpecialTone=1; - } else if(pChan->b.stopSpecialTone) - { - pChan->b.stopSpecialTone=0; - pChan->spsSigGen1->option=0; - pChan->b.doingSpecialTone=0; - pChan->spsSigGen1->enabled=0; - } else if(pChan->b.doingSpecialTone) + if(pChan->rxCtcss->decode > CTCSS_NULL && + (pChan->smode==SMODE_NULL||pChan->smode==SMODE_CTCSS) ) { - pChan->spsSigGen1->sink=output; - pChan->spsSigGen1->sigProc(pChan->spsSigGen1); - for(i=0;i<(pChan->nSamplesTx*2*6);i+=2)output[i+1]=output[i]; - return 0; + if(pChan->smode!=SMODE_CTCSS) + { + TRACEC(1,("smode set=%i code=%i\n",pChan->smode,pChan->rxCtcss->decode)); + pChan->smode=pChan->smodewas=SMODE_CTCSS; + } + pChan->smodetimer=pChan->smodetime; } - // handle transmitter ptt input + #ifdef HAVE_XPMRX + xpmrx(pChan,XXO_LSDCTL); + #endif + + //TRACEX(("PmrRx() tx portion.\n")); + + // handle radio transmitter ptt input hit=0; - if( pChan->txPttIn && pChan->txState==0) + if( !(pChan->smode==SMODE_DCS||pChan->smode==SMODE_LSD) ) { - pChan->txState = 2; + + if( pChan->txPttIn && pChan->txState==CHAN_TXSTATE_IDLE ) + { + TRACEC(1,("txPttIn==1 from CHAN_TXSTATE_IDLE && !SMODE_LSD. codeindex=%i %i \n",pChan->rxCtcss->decode, pChan->rxCtcssMap[pChan->rxCtcss->decode] )); + pChan->dd.b.doitnow=1; + + if(pChan->smode==SMODE_CTCSS && !pChan->b.txCtcssInhibit) + { + if(pChan->rxCtcss->decode>CTCSS_NULL) + { + if(pChan->rxCtcssMap[pChan->rxCtcss->decode]!=CTCSS_RXONLY) + { + f=freq_ctcss[pChan->rxCtcssMap[pChan->rxCtcss->decode]]; + } + } + else + { + f=pChan->txctcssdefault_value; + } + TRACEC(1,("txPttIn - Start CTCSSGen %f \n",f)); + if(f) + { + t_pmr_sps *pSps; + + pChan->spsSigGen0->freq=f*10; + pSps=pChan->spsTxLsdLpf; + pSps->enabled=1; + + #if 0 + if(f>203.0) + { + pSps->ncoef=taps_fir_lpf_250_9_66; + pSps->size_coef=2; + pSps->coef=(void*)coef_fir_lpf_250_9_66; + pSps->nx=taps_fir_lpf_250_9_66; + pSps->size_x=2; + pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); + pSps->calcAdjust=gain_fir_lpf_250_9_66; + } + else + { + pSps->ncoef=taps_fir_lpf_215_9_88; + pSps->size_coef=2; + pSps->coef=(void*)coef_fir_lpf_215_9_88; + pSps->nx=taps_fir_lpf_215_9_88; + pSps->size_x=2; + pSps->x=(void*)(calloc(pSps->nx,pSps->size_x)); + pSps->calcAdjust=gain_fir_lpf_215_9_88; + } + #endif + + pChan->spsSigGen0->option=1; + pChan->spsSigGen0->enabled=1; + pChan->spsSigGen0->discounterl=0; + } + } + else if(pChan->smode==SMODE_NULL && pChan->txcodedefaultsmode==SMODE_CTCSS && !pChan->b.txCtcssInhibit) + { + TRACEC(1,("txPtt Encode txcodedefaultsmode==SMODE_CTCSS %f\n",pChan->txctcssdefault_value)); + pChan->spsSigGen0->freq=pChan->txctcssdefault_value*10; + pChan->spsSigGen0->option=1; + pChan->spsSigGen0->enabled=1; + pChan->spsSigGen0->discounterl=0; + pChan->smode=SMODE_CTCSS; + pChan->smodetimer=pChan->smodetime; + } + else if(pChan->txcodedefaultsmode==SMODE_NULL||pChan->b.txCtcssInhibit) + { + TRACEC(1,("txPtt Encode txcodedefaultsmode==SMODE_NULL\n")); + } + else + { + printf ("ERROR: txPttIn=%i NOT HANDLED PROPERLY.\n",pChan->txPttIn); + TRACEC(1,("ERROR: txPttIn=%i NOT HANDLED PROPERLY.\n",pChan->txPttIn)); + } + + pChan->txState = CHAN_TXSTATE_ACTIVE; pChan->txPttOut=1; - pChan->spsSigGen0->freq=pChan->txCtcssFreq*10; - pChan->spsSigGen0->option=1; - pChan->spsSigGen0->enabled=1; + + pChan->txsettletimer=pChan->txsettletime; + if(pChan->spsTxOutA)pChan->spsTxOutA->enabled=1; if(pChan->spsTxOutB)pChan->spsTxOutB->enabled=1; if(pChan->spsTxLsdLpf)pChan->spsTxLsdLpf->enabled=1; - TRACEX((" TxOn\n")); + if(pChan->txfreq)pChan->b.reprog=1; + TRACEC(1,("PmrRx() TxOn\n")); + } + else if(pChan->txPttIn && pChan->txState==CHAN_TXSTATE_ACTIVE) + { + // pChan->smode=SMODE_CTCSS; + pChan->smodetimer=pChan->smodetime; } - else if(!pChan->txPttIn && pChan->txState==2) + else if(!pChan->txPttIn && pChan->txState==CHAN_TXSTATE_ACTIVE) { - if( pChan->txTocType==TOC_NONE || !pChan->txCtcssFreq ) + TRACEC(1,("txPttIn==0 from CHAN_TXSTATE_ACTIVE\n")); + if(pChan->smode==SMODE_CTCSS && !pChan->b.txCtcssInhibit) { - hit=1; - TRACEX((" Tx Off Immediate.\n")); - } - else if(pChan->txCtcssFreq && pChan->txTocType==TOC_NOTONE) + if( pChan->txTocType==TOC_NONE || !pChan->b.ctcssTxEnable ) + { + TRACEC(1,("Tx Off Immediate.\n")); + pChan->spsSigGen0->option=3; + pChan->txBufferClear=3; + pChan->txState=CHAN_TXSTATE_FINISHING; + } + else if(pChan->txTocType==TOC_NOTONE) + { + pChan->txState=CHAN_TXSTATE_TOC; + pChan->txHangTime=TOC_NOTONE_TIME/MS_PER_FRAME; + pChan->spsSigGen0->option=3; + TRACEC(1,("Tx Turn Off No Tone Start.\n")); + } + else + { + pChan->txState=CHAN_TXSTATE_TOC; + pChan->txHangTime=0; + pChan->spsSigGen0->option=2; + TRACEC(1,("Tx Turn Off Phase Shift Start.\n")); + } + } + else { - pChan->txState=3; - pChan->txHangTime=TOC_NOTONE_TIME/MS_PER_FRAME; - pChan->spsSigGen0->option=3; - TRACEX((" Tx Turn Off No Tone Start.\n")); + pChan->txBufferClear=3; + pChan->txState=CHAN_TXSTATE_FINISHING; + TRACEC(1,("Tx Off No SMODE to Finish.\n")); } - else + } + else if(pChan->txState==CHAN_TXSTATE_TOC) + { + if( pChan->txPttIn && pChan->smode==SMODE_CTCSS ) { - pChan->txState=3; - pChan->txHangTime=0; - pChan->spsSigGen0->option=2; - TRACEX((" Tx Turn Off Phase Shift Start.\n")); + TRACEC(1,("Tx Key During HangTime\n")); + pChan->txState = CHAN_TXSTATE_ACTIVE; + pChan->spsSigGen0->option=1; + pChan->spsSigGen0->enabled=1; + pChan->spsSigGen0->discounterl=0; + hit=0; } - } - else if(pChan->txState==3) - { - if(pChan->txHangTime) + else if(pChan->txHangTime) { - if(--pChan->txHangTime==0)hit=1; - + if(--pChan->txHangTime==0)pChan->txState=CHAN_TXSTATE_FINISHING; } else if(pChan->txHangTime<=0 && pChan->spsSigGen0->state==0) - { - hit=1; - TRACEX((" Tx Off TOC.\n")); - } - if(pChan->txPttIn) { - TRACEX((" Tx Key During HangTime\n")); - if((pChan->txTocType==TOC_PHASE)||(pChan->txTocType==TOC_NONE)) - { - pChan->txState = 2; - hit=0; - } + pChan->txBufferClear=3; + pChan->txState=CHAN_TXSTATE_FINISHING; + TRACEC(1,("Tx Off TOC.\n")); } } - - if( pChan->txCpuSaver && !hit && !pChan->txPttIn && !pChan->txPttOut && pChan->txState==0 ) return (1); + else if(pChan->txState==CHAN_TXSTATE_FINISHING) + { + if(--pChan->txBufferClear<=0) + pChan->txState=CHAN_TXSTATE_COMPLETE; + } + else if(pChan->txState==CHAN_TXSTATE_COMPLETE) + { + hit=1; + } + } // end of if SMODE==LSD if(hit) { pChan->txPttOut=0; - pChan->txState=0; + pChan->spsSigGen0->option=3; + pChan->txState=CHAN_TXSTATE_IDLE; if(pChan->spsTxLsdLpf)pChan->spsTxLsdLpf->option=3; if(pChan->spsTxOutA)pChan->spsTxOutA->option=3; if(pChan->spsTxOutB)pChan->spsTxOutB->option=3; - TRACEX((" Tx Off hit.\n")); + if(pChan->rxfreq||pChan->txfreq)pChan->b.reprog=1; + TRACEC(1,("Tx Off hit.\n")); + } + + if(pChan->b.reprog) + { + pChan->b.reprog=0; + progdtx(pChan); } - if(pChan->spsSigGen0) + if(pChan->txsettletimer && pChan->txPttHid ) { - pChan->spsSigGen0->sigProc(pChan->spsSigGen0); - pmr_sps=pChan->spsSigGen0->nextSps; - i=0; - while(pmr_sps!=NULL && pmr_sps!=0) + pChan->txsettletimer-=MS_PER_FRAME; + if(pChan->txsettletimer<0)pChan->txsettletimer=0; + } + + // enable this after we know everything else is working + if( pChan->txCpuSaver && + !pChan->txPttIn && !pChan->txPttOut && + pChan->txState==CHAN_TXSTATE_IDLE && + !pChan->dd.b.doitnow + ) + { + if(!pChan->b.txhalted) { - TRACEX((" PmrTx() subaudible sps %i\n",i++)); - //printf(" CTCSS ENCODE %i %i\n",pChan->spsSigGen0->freq,pChan->spsSigGen0->outputGain); - pmr_sps->sigProc(pmr_sps); - pmr_sps = (t_pmr_sps *)(pmr_sps->nextSps); + pChan->b.txhalted=1; + TRACEC(1,("PmrRx() tx sps halted\n")); } } + else if(pChan->b.txhalted) + { + pChan->dd.b.doitnow=1; + pChan->b.txhalted=0; + TRACEC(1,("PmrRx() tx sps un-halted\n")); + } + + if(pChan->b.txhalted)return(1); + + if(pChan->b.startSpecialTone) + { + pChan->b.startSpecialTone=0; + pChan->spsSigGen1->option=1; + pChan->spsSigGen1->enabled=1; + pChan->b.doingSpecialTone=1; + } + else if(pChan->b.stopSpecialTone) + { + pChan->b.stopSpecialTone=0; + pChan->spsSigGen1->option=0; + pChan->b.doingSpecialTone=0; + pChan->spsSigGen1->enabled=0; + } + else if(pChan->b.doingSpecialTone) + { + pChan->spsSigGen1->sink=outputtx; + pChan->spsSigGen1->sigProc(pChan->spsSigGen1); + for(i=0;i<(pChan->nSamplesTx*2*6);i+=2)outputtx[i+1]=outputtx[i]; + return 0; + } + + if(pChan->spsSigGen0 && pChan->spsSigGen0->enabled ) + { + pChan->spsSigGen0->sigProc(pChan->spsSigGen0); + } if(pChan->spsSigGen1 && pChan->spsSigGen1->enabled) { pChan->spsSigGen1->sigProc(pChan->spsSigGen1); } + #ifdef XPMRX_H + pChan->spsLsdGen->sigProc(pChan->spsLsdGen); // maw sph ??? + #endif + + // Do Low Speed Data Low Pass Filter + pChan->spsTxLsdLpf->sigProc(pChan->spsTxLsdLpf); + // Do Voice pmr_sps=pChan->spsTx; - if(!pChan->spsSigGen1->enabled)pmr_sps->source=input; + + // get tx data from de-drift process + pChan->dd.option=0; + pChan->dd.ptr=pChan->pTxBase; + dedrift(pChan); + + // tx process + if(!pChan->spsSigGen1->enabled) + { + pmr_sps->source=pChan->pTxBase; + } else input=pmr_sps->source; - if(output!=NULL) + if(outputtx!=NULL) { - if(pChan->spsTxOutA)pChan->spsTxOutA->sink=output; - if(pChan->spsTxOutB)pChan->spsTxOutB->sink=output; + if(pChan->spsTxOutA)pChan->spsTxOutA->sink=outputtx; + if(pChan->spsTxOutB)pChan->spsTxOutB->sink=outputtx; } i=0; while(pmr_sps!=NULL && pmr_sps!=0) { - TRACEX((" PmrTx() sps %i\n",i++)); + //TRACEF(1,("PmrTx() sps %i\n",i++)); pmr_sps->sigProc(pmr_sps); pmr_sps = (t_pmr_sps *)(pmr_sps->nextSps); } - + //TRACEF(1,("PmrTx() - outputs \n")); if(pChan->txMixA==TX_OUT_OFF || !pChan->txPttOut){ - for(i=0;inSamplesTx*2*6;i+=2)output[i]=0; + for(i=0;inSamplesTx*2*6;i+=2)outputtx[i]=0; } if(pChan->txMixB==TX_OUT_OFF || !pChan->txPttOut ){ - for(i=0;inSamplesTx*2*6;i+=2)output[i+1]=0; + for(i=0;inSamplesTx*2*6;i+=2)outputtx[i+1]=0; } - #if XPMR_DEBUG0 == 1 - if(pChan->b.txCapture) + #if XPMR_PPTP == 1 + if( pChan->b.radioactive && pChan->b.pptp_p1!=pChan->txPttOut) { - i16 ii=0; - for(i=0;inSamplesTx;i++) + pChan->b.pptp_p1=pChan->txPttOut; + pptp_write(0,pChan->b.pptp_p1); + } + #endif + + #if XPMR_DEBUG0 == 1 + // TRACEF(1,("PmrRx() - debug outputs \n")); + if(pChan->b.rxCapture){ + for(i=0;inSamplesRx;i++) { - pChan->ptxDebug[ii++]=input[i]; - pChan->ptxDebug[ii++]=output[i*2*6]; - pChan->ptxDebug[ii++]=output[(i*2*6)+1]; - pChan->ptxDebug[ii++]=pChan->txPttIn*8192; - - pChan->ptxDebug[ii++]=pChan->txPttOut*8192; - if(pChan->txHpfEnable)pChan->ptxDebug[ii++]=pChan->pTxHpf[i]; - else pChan->ptxDebug[ii++]=0; - if(pChan->txPreEmpEnable)pChan->ptxDebug[ii++]=pChan->pTxPreEmp[i]; - else pChan->ptxDebug[ii++]=0; - if(pChan->txLimiterEnable)pChan->ptxDebug[ii++]=pChan->pTxLimiter[i]; - else pChan->ptxDebug[ii++]=0; - - pChan->ptxDebug[ii++]=pChan->pTxLsd[i]; - pChan->ptxDebug[ii++]=pChan->pTxLsdLpf[i]; - pChan->ptxDebug[ii++]=pChan->pTxComposite[i]; - pChan->ptxDebug[ii++]=pChan->pSigGen1[i]; - - #if 1 - pChan->ptxDebug[ii++]=pChan->ptxDebug0[i]; - pChan->ptxDebug[ii++]=pChan->ptxDebug1[i]; - pChan->ptxDebug[ii++]=pChan->ptxDebug2[i]; - pChan->ptxDebug[ii++]=pChan->ptxDebug3[i]; - #else - pChan->ptxDebug[ii++]=0; - pChan->ptxDebug[ii++]=0; - pChan->ptxDebug[ii++]=0; - pChan->ptxDebug[ii++]=0; - #endif + pChan->pRxDemod[i]=input[i*2*6]; + pChan->pTstTxOut[i]=outputtx[i*2*6+0]; // txa + //pChan->pTstTxOut[i]=outputtx[i*2*6+1]; // txb + TSCOPE((RX_NOISE_TRIG, pChan->sdbg, i, (pChan->rxCarrierDetect*XPMR_TRACE_AMP)-XPMR_TRACE_AMP/2)); + TSCOPE((RX_CTCSS_DECODE, pChan->sdbg, i, pChan->rxCtcss->decode*(M_Q14/CTCSS_NUM_CODES))); + TSCOPE((RX_SMODE, pChan->sdbg, i, pChan->smode*(XPMR_TRACE_AMP/4))); + TSCOPE((TX_PTT_IN, pChan->sdbg, i, (pChan->txPttIn*XPMR_TRACE_AMP)-XPMR_TRACE_AMP/2)); + TSCOPE((TX_PTT_OUT, pChan->sdbg, i, (pChan->txPttOut*XPMR_TRACE_AMP)-XPMR_TRACE_AMP/2)); + TSCOPE((TX_DEDRIFT_LEAD, pChan->sdbg, i, pChan->dd.lead*8)); + TSCOPE((TX_DEDRIFT_ERR, pChan->sdbg, i, pChan->dd.err*16)); + TSCOPE((TX_DEDRIFT_FACTOR, pChan->sdbg, i, pChan->dd.factor*16)); + TSCOPE((TX_DEDRIFT_DRIFT, pChan->sdbg, i, pChan->dd.drift*16)); } - } + } #endif + strace2(pChan->sdbg); + TRACEC(5,("PmrRx() return cd=%i smode=%i txPttIn=%i txPttOut=%i \n",pChan->rxCarrierDetect,pChan->smode,pChan->txPttIn,pChan->txPttOut)); return 0; } +/* + parallel binary programming of an RF Transceiver*/ + +void ppbinout (u8 chan) +{ +#if(DTX_PROG == 1) + i32 i; + + if (ppdrvdev == 0) + ppdrvdev = open("/dev/ppdrv_device", 0); + + if (ppdrvdev < 0) + { + ast_log(LOG_ERROR, "open /dev/ppdrv_ppdrvdev returned %i\n",ppdrvdev); + return; + } + + i=0; + if(chan&0x01)i|=BIN_PROG_0; + if(chan&0x02)i|=BIN_PROG_1; + if(chan&0x04)i|=BIN_PROG_2; + if(chan&0x08)i|=BIN_PROG_3; + + ioctl(ppdrvdev, PPDRV_IOC_PINMODE_OUT, BIN_PROG_3|BIN_PROG_2|BIN_PROG_1|BIN_PROG_0); + //ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, BIN_PROG_3|BIN_PROG_2|BIN_PROG_1|BIN_PROG_0); + //ioctl(ppdrvdev, PPDRV_IOC_PINSET, i ); + ioctl(ppdrvdev, PPDRV_IOC_PINSET, BIN_PROG_3|BIN_PROG_2|BIN_PROG_1|BIN_PROG_0); + ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, i ); + + // ioctl(ppdrvdev, PPDRV_IOC_PINSET, BIN_PROG_3|BIN_PROG_2|BIN_PROG_1|BIN_PROG_0 ); + ast_log(LOG_NOTICE, "mask=%i 0x%x\n",i,i); +#endif +} +/* + SPI Programming of an RF Transceiver + need to add permissions check and mutex +*/ +/* + need to add permissions check and mutex +*/ +void ppspiout (u32 spidata) +{ +#if(DTX_PROG == 1) + static char firstrun=0; + i32 i,ii; + u32 bitselect; + + if (ppdrvdev < 0) + { + ast_log(LOG_ERROR, "no parallel port permission ppdrvdev %i\n",ppdrvdev); + exit(0); + } + + ioctl(ppdrvdev, PPDRV_IOC_PINMODE_OUT, DTX_CLK | DTX_DATA | DTX_ENABLE | DTX_TXPWR | DTX_TX ); + ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_CLK | DTX_DATA | DTX_ENABLE | DTX_TXPWR | DTX_TX ); + + if(firstrun==0) + { + firstrun=1; + for(ii=0;ii>1); + } + ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_CLK | DTX_DATA ); + ioctl(ppdrvdev, PPDRV_IOC_PINSET, DTX_ENABLE ); + for(ii=0;iirxfreq,pChan->txfreq,0)); + + if (ppdrvdev == 0) + ppdrvdev = open("/dev/ppdrv_device", 0); + + if (ppdrvdev < 0) + { + ast_log(LOG_ERROR, "open /dev/ppdrv_ppdrvdev returned %i\n",ppdrvdev); + exit(0); + } + + if(pChan->rxfreq>200000000) + { + reffreq=16012500; + stepfreq=12500; + rxiffreq=21400000; + } + else + { + reffreq=16000000; + stepfreq=5000; + rxiffreq=10700000; + } + + shiftreg=(reffreq/stepfreq)<<1; + shiftreg=shiftreg|0x00000001; + + ppspiout(shiftreg); + + if(pChan->txPttOut) + synthfreq=pChan->txfreq; + else + synthfreq=pChan->rxfreq-rxiffreq; + + shiftreg=(synthfreq/stepfreq)<<1; + tmp=(shiftreg&0xFFFFFF80)<<1; + shiftreg=tmp+(shiftreg&0x0000007F); + + ppspiout(shiftreg); + + ioctl(ppdrvdev, PPDRV_IOC_PINMODE_OUT, DTX_CLK | DTX_DATA | DTX_ENABLE | DTX_TXPWR | DTX_TX ); + ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_CLK | DTX_DATA | DTX_ENABLE ); + + if(pChan->txPttOut) + { + ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_TXPWR ); + ioctl(ppdrvdev, PPDRV_IOC_PINSET, DTX_TX ); + if(pChan->txpower && 0) ioctl(ppdrvdev, PPDRV_IOC_PINSET, DTX_TXPWR ); + } + else + { + ioctl(ppdrvdev, PPDRV_IOC_PINCLEAR, DTX_TX | DTX_TXPWR ); + } +#endif +} + +/* dedrift + reconciles clock differences between the usb adapter and + asterisk's frame rate clock + take out all accumulated drift error on these events: + before transmitter on + when ptt release from mobile units detected +*/ +void dedrift(t_pmr_chan *pChan) +{ + TRACEC(5,("dedrift()\n")); + + if(pChan->dd.option==9) + { + TRACEF(1,("dedrift(9)\n")); + pChan->dd.framesize=DDB_FRAME_SIZE; + pChan->dd.frames=DDB_FRAMES_IN_BUFF; + pChan->dd.buffersize = pChan->dd.frames * pChan->dd.framesize; + pChan->dd.buff=calloc(DDB_FRAME_SIZE*DDB_FRAMES_IN_BUFF,2); + pChan->dd.modulus=DDB_ERR_MODULUS; + pChan->dd.inputindex=0; + pChan->dd.outputindex=0; + pChan->dd.skew = pChan->dd.lead=0; + pChan->dd.z1=0; + pChan->dd.debug=0; + pChan->dd.debugcnt=0; + pChan->dd.lock=pChan->dd.b.txlock=pChan->dd.b.rxlock=0; + pChan->dd.initcnt=2; + pChan->dd.timer=10000/20; + pChan->dd.drift=0; + pChan->dd.factor=pChan->dd.x1 = pChan->dd.x0 = pChan->dd.y1 = pChan->dd.y0 = 0; + pChan->dd.txframecnt=pChan->dd.rxframecnt=0; + // clear the buffer too! + return; + } + else if(pChan->dd.option==8) + { + free(pChan->dd.buff); + pChan->dd.lock=0; + pChan->dd.b.txlock=pChan->dd.b.rxlock=0; + return; + } + else if(pChan->dd.initcnt==0) + { + void *vptr; + i16 inputindex; + i16 indextweak; + i32 accum; + + inputindex = pChan->dd.inputindex; + pChan->dd.skew = pChan->dd.txframecnt-pChan->dd.rxframecnt; + pChan->dd.rxframecnt++; + + // pull data from buffer + if( (pChan->dd.outputindex + pChan->dd.framesize) > pChan->dd.buffersize ) + { + i16 dofirst,donext; + + dofirst = pChan->dd.buffersize - pChan->dd.outputindex; + donext = pChan->dd.framesize - dofirst; + vptr = (void*)(pChan->dd.ptr); + memcpy(vptr,(void*)(pChan->dd.buff + pChan->dd.outputindex),dofirst*2); + vptr=(void*)(pChan->dd.ptr + dofirst); + memcpy(vptr,(void*)(pChan->dd.buff),donext*2); + } + else + { + memcpy(pChan->dd.ptr,(void*)(pChan->dd.buff + pChan->dd.outputindex),pChan->dd.framesize*2); + } + + // compute clock error and correction factor + if(pChan->dd.outputindex > inputindex) + { + pChan->dd.lead = (inputindex + pChan->dd.buffersize) - pChan->dd.outputindex; + } + else + { + pChan->dd.lead = inputindex - pChan->dd.outputindex; + } + pChan->dd.err = pChan->dd.lead - (pChan->dd.buffersize/2); + + // WinFilter, IIR Fs=50, Fc=0.1 + const i32 a0 = 26231; + const i32 a1 = 26231; + const i32 b0 = 32768; + const i32 b1 = -32358; + const i32 dg = 128; + pChan->dd.x1 = pChan->dd.x0; + pChan->dd.y1 = pChan->dd.y0; + pChan->dd.x0 = pChan->dd.err; + pChan->dd.y0 = a0 * pChan->dd.x0; + pChan->dd.y0 += (a1 * pChan->dd.x1 - (b1 * pChan->dd.y1)); + pChan->dd.y0 /= b0; + accum = pChan->dd.y0/dg; + + pChan->dd.factor=accum; + indextweak=0; + + #if 1 + // event sync'd correction + if(pChan->dd.b.doitnow) + { + pChan->dd.b.doitnow=0; + indextweak=pChan->dd.factor; + pChan->dd.factor = pChan->dd.x1 = pChan->dd.x0 = pChan->dd.y1 = pChan->dd.y0 = 0; + pChan->dd.timer=20000/MS_PER_FRAME; + } + // coarse lead adjustment if really far out of range + else if( pChan->dd.lead >= pChan->dd.framesize*(DDB_FRAMES_IN_BUFF-2) ) + { + pChan->dd.factor = pChan->dd.x1 = pChan->dd.x0 = pChan->dd.y1 = pChan->dd.y0 = 0; + indextweak += (pChan->dd.framesize*5/4); + } + else if(pChan->dd.lead <= pChan->dd.framesize*2 ) + { + pChan->dd.factor = pChan->dd.x1 = pChan->dd.x0 = pChan->dd.y1 = pChan->dd.y0 = 0; + indextweak -= (pChan->dd.framesize*5/4); + } + #endif + + #if 1 + if(pChan->dd.timer>0)pChan->dd.timer--; + if(pChan->dd.timer==0 && abs(pChan->dd.factor)>=16) + { + indextweak=pChan->dd.factor; + pChan->dd.factor = pChan->dd.x1 = pChan->dd.x0 = pChan->dd.y1 = pChan->dd.y0 = 0; + pChan->dd.timer=20000/MS_PER_FRAME; + } + #endif + + #if XPMR_DEBUG0 == 1 + if(indextweak!=0)TRACEF(4,("%08i indextweak %+4i %+4i %+5i %5i %5i %5i %+4i\n",pChan->dd.rxframecnt, indextweak, pChan->dd.err, accum, inputindex, pChan->dd.outputindex, pChan->dd.lead, pChan->dd.skew)); + #endif + + // set the output index based on lead and clock offset + pChan->dd.outputindex = (pChan->dd.outputindex + pChan->dd.framesize + indextweak)%pChan->dd.buffersize; + } +} +/* +*/ +void dedrift_write(t_pmr_chan *pChan, i16 *src ) +{ + void *vptr; + + TRACEF(5,("dedrift_write()\n")); + vptr = pChan->dd.buff + pChan->dd.inputindex; + memcpy(vptr, src, pChan->dd.framesize*2); + pChan->dd.inputindex = (pChan->dd.inputindex + pChan->dd.framesize) % pChan->dd.buffersize; + pChan->dd.txframecnt++; + if(pChan->dd.initcnt!=0)pChan->dd.initcnt--; + pChan->dd.accum+=pChan->dd.framesize; +} + /* end of file */ diff --git a/channels/xpmr/xpmr.h b/channels/xpmr/xpmr.h index b39ce23d6..49f5148fa 100755 --- a/channels/xpmr/xpmr.h +++ b/channels/xpmr/xpmr.h @@ -5,15 +5,25 @@ * * 20070808 1235 Steven Henke, W9SH, sph@xelatec.com * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This version may be optionally licenced under the GNU LGPL licence. + * + * A license has been granted to Digium (via disclaimer) for the use of + * this code. * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. */ /*! \file @@ -23,25 +33,73 @@ * \author Steven Henke, W9SH Xelatec, LLC */ -#ifndef XPMR_H -#define XPMR_H 1 +#ifndef XPMR_H +#define XPMR_H 1 + +#define XPMR_DEV 0 // when running in test mode + +#define XPMR_TRACE_LEVEL 0 + +#ifdef RADIO_RTX +#define DTX_PROG 1 // rf transceiver module +#define XPMR_PPTP 0 // parallel port test probe +#else +#define DTX_PROG 0 +#define XPMR_PPTP 0 +#endif + +#if (DTX_PROG == 1) || XPMR_PPTP == 1 +#include +#endif #ifdef CHAN_USBRADIO #define XPMR_DEBUG0 1 -#define XPMR_TRACE 0 +#define XPMR_TRACE 1 +#define TRACEO(level,a) { if ( o->tracelevel >= level ) {printf a;} } #else #define XPMR_DEBUG0 1 #define XPMR_TRACE 1 +#define TRACEO(level,a) #endif + +#define LSD_DFS 5 +#define LSD_DFD 1 + +#if(XPMR_DEBUG0 == 1) +#define XPMR_DEBUG_CHANS 16 +#define TSCOPE(a) {strace a;} +#else +#define XPMR_DEBUG_CHANS 0 +#define TSCOPE(a) +#endif + +#define XPMR_TRACE_AMP 8192 + +// TRACEM(3,TSYS_LSD,("pmr_lsdctl_exec() RX FRAME UNPROCESSED.\n")); #if(XPMR_TRACE == 1) #define TRACEX(a) {printf a;} #define TRACEXL(a) {printf("%s @ %u : ",__FILE__ ,__LINE__); printf a; } -#define TRACEXT(a) { struct timeval hack; gettimeofday(&hack,NULL); printf("%ld.",hack.tv_sec%100000); printf("%i : ",(int)hack.tv_usec); printf a; } +#define TRACEXT(a) {struct timeval hack; gettimeofday(&hack,NULL); printf("%ld.",hack.tv_sec%100000); printf("%i : ",(int)hack.tv_usec); printf a; } +#define TRACEXR(a) {printf a;} +#define TRACEC(level,a) {if(pChan->tracelevel>=level){printf("%08i ",pChan->frameCountRx);printf a;} } +#define TRACEF(level,a) {if(pChan->tracelevel>=level){printf a;} } +#define TRACEJ(level,a) {if(XPMR_TRACE_LEVEL>=level){printf a;} } +#define TRACES(level,a) {if(mySps->parentChan->tracelevel >= level){printf a;} } +#define TRACET(level,a) {if(pChan->tracelevel>=level){printf("%08i %02i",pChan->frameCountRx,pChan->rptnum);printf a;} } +#define TRACEXR(a) {printf a;} +#define TRACEM(level,sys,a) {if(pChan->tracelevel>=level || (pChan->tracesys[sys])){printf a;} } #else #define TRACEX(a) #define TRACEXL(a) #define TRACEXT(a) +#define TRACEC(level,a) +#define TRACEF(level,a) +#define TRACEJ(level,a) +#define TRACES(level,a) +#define TRACET(level,a) +#define TRACEXR(a) +#define TRACEM(level,sys,a) #endif #define i8 int8_t @@ -52,11 +110,18 @@ #define u32 u_int32_t #define i64 int64_t #define u64 u_int64_t - + +#define M_Q31 0x80000000 // +#define M_Q30 0x40000000 // +#define M_Q29 0x20000000 // +#define M_Q28 0x10000000 // +#define M_Q27 0x08000000 // +#define M_Q26 0x04000000 // +#define M_Q25 0x02000000 // #define M_Q24 0x01000000 // #define M_Q23 0x00800000 // #define M_Q22 0x00400000 // -#define M_Q21 0x00200000 // +#define M_Q21 0x00200000 // undsoweiter #define M_Q20 0x00100000 // 1048576 #define M_Q19 0x00080000 // 524288 #define M_Q18 0x00040000 // 262144 @@ -86,8 +151,11 @@ #define SAMPLES_PER_BLOCK 160 #define MS_PER_FRAME 20 +#define SAMPLES_PER_MS 8 -#define CTCSS_NUM_CODES 38 +#define CTCSS_NULL -1 +#define CTCSS_RXONLY -2 +#define CTCSS_NUM_CODES 38 // 0 - 37 #define CTCSS_SCOUNT_MUL 100 #define CTCSS_INTEGRATE 3932 // 32767*.120 // 120/1000 // 0.120 #define CTCSS_INPUT_LIMIT 1000 @@ -98,6 +166,61 @@ #define CTCSS_TURN_OFF_SHIFT 240 // degrees #define TOC_NOTONE_TIME 600 // ms +#define DDB_FRAME_SIZE 160 // clock de-drift defaults +#define DDB_FRAMES_IN_BUFF 8 +#define DDB_ERR_MODULUS 10000 + +#define DCS_TURN_OFF_TIME 180 + +#define NUM_TXLSD_FRAMEBUFFERS 4 + +#define CHAN_TXSTATE_IDLE 0 +#define CHAN_TXSTATE_ACTIVE 1 +#define CHAN_TXSTATE_TOC 2 +#define CHAN_TXSTATE_HANGING 3 +#define CHAN_TXSTATE_FINISHING 4 +#define CHAN_TXSTATE_COMPLETE 5 +#define CHAN_TXSTATE_USURPED 9 + +#define SMODE_NULL 0 +#define SMODE_CARRIER 1 +#define SMODE_CTCSS 2 +#define SMODE_DCS 3 +#define SMODE_LSD 4 +#define SMODE_MPT 5 +#define SMODE_DST 6 +#define SMODE_P25 7 +#define SMODE_MDC 8 + + +#define SPS_OPT_START 1 +#define SPS_OPT_STOP 2 +#define SPS_OPT_TURNOFF 3 +#define SPS_OPT_STOPNOW 4 + +#define SPS_STAT_STOPPED 0 +#define SPS_STAT_STARTING 1 +#define SPS_STAT_RUNNING 2 +#define SPS_STAT_HALTING 3 + + +#define PP_BIT_TEST 6 +#define PP_REG_LEN 32 +#define PP_BIT_TIME 100000 + +#define DTX_CLK LP_PIN02 +#define DTX_DATA LP_PIN03 +#define DTX_ENABLE LP_PIN04 +#define DTX_TX LP_PIN05 // only used on older mods +#define DTX_TXPWR LP_PIN06 // not used +#define DTX_TP1 LP_PIN07 // not used +#define DTX_TP2 LP_PIN08 // not used + +#define BIN_PROG_0 LP_PIN06 +#define BIN_PROG_1 LP_PIN07 +#define BIN_PROG_2 LP_PIN08 +#define BIN_PROG_3 LP_PIN09 + #ifndef CHAN_USBRADIO enum {RX_AUDIO_NONE,RX_AUDIO_SPEAKER,RX_AUDIO_FLAT}; enum {TX_AUDIO_NONE,TX_AUDIO_FLAT,TX_AUDIO_FILTERED,TX_AUDIO_PROC}; @@ -108,6 +231,130 @@ enum {TX_OUT_OFF,TX_OUT_VOICE,TX_OUT_LSD,TX_OUT_COMPOSITE,TX_OUT_AUX}; enum {TOC_NONE,TOC_PHASE,TOC_NOTONE}; #endif +enum dbg_pts { + +RX_INPUT, +RX_NOISE_AMP, +RX_NOISE_TRIG, + +RX_CTCSS_LPF, +RX_CTCSS_CENTER, +RX_CTCSS_NRZ, +RX_CTCSS_CLK, +RX_CTCSS_P0, +RX_CTCSS_P1, +RX_CTCSS_ACCUM, +RX_CTCSS_DVDT, +RX_CTCSS_DECODE, + +RX_DCS_CENTER, +RX_DCS_DEC, +RX_DCS_DIN, +RX_DCS_CLK, +RX_DCS_DAT, + +RX_LSD_LPF, +RX_LSD_CLK, +RX_LSD_DAT, +RX_LSD_DEC, + +RX_LSD_CENTER, +RX_LSD_SYNC, +RX_LSD_STATE, +RX_LSD_ERR, +RX_LSD_INTE, + +RX_SMODE, + +TX_PTT_IN, +TX_PTT_OUT, + +TX_DEDRIFT_LEAD, +TX_DEDRIFT_ERR, +TX_DEDRIFT_FACTOR, +TX_DEDRIFT_DRIFT, +TX_DEDRIFT_TWIDDLE, + +TX_CTCSS_GEN, + +TX_SIGGEN_0, + +TX_DCS_CLK, +TX_DCS_DAT, +TX_DCS_LPF, + +TX_LSD_CLK, +TX_LSD_DAT, +TX_LSD_GEN, +TX_LSD_LPF, + +TX_NET_INT, +TX_VOX_HPF, +TX_VOX_LIM, + +TX_VOX_LPF, + +TX_OUT_A, +TX_OUT_B, + +NUM_DEBUG_PTS +}; + +typedef struct +{ + i16 mode; + i16 point[NUM_DEBUG_PTS]; + i16 trace[16]; + i16 scale[16]; + i16 offset[16]; + i16 buffer[16 * SAMPLES_PER_BLOCK]; // allocate for rx and tx + i16 *source[16]; +} t_sdbg; + +typedef struct +{ + i16 lock; + i16 option; // 1 = data in, 0 = data out + i16 debug; + i16 debugcnt; + i32 rxframecnt; + i32 txframecnt; + + i32 skew; + + i16 frames; + i16 framesize; + i16 buffersize; + + i32 timer; + + i32 x0,x1,y0,y1; + + i16 inputindex; + i16 outputindex; + i16 lead; + i16 err; + i16 accum; + + i16 *ptr; // source or destination + i16 *buff; + + i16 inputcnt; + i16 initcnt; + + i32 factor; + i32 drift; + i32 modulus; + i32 z1; + struct { + unsigned rxlock:1; + unsigned txlock:1; + unsigned twiddle:1; + unsigned doitnow:1; + }b; +} +t_dedrift; + /* one structure for each ctcss tone to decode */ @@ -121,7 +368,7 @@ typedef struct i16 enabled; i16 state; // dead, running, error i16 zIndex; // z bucket index - i16 z[4]; // maw sph today + i16 z[4]; i16 zi; i16 dvu; i16 dvd; @@ -130,78 +377,62 @@ typedef struct i16 hyst; i16 decode; i16 diffpeak; - i16 debug; // value held from last pass + i16 debug; + + #if XPMR_DEBUG0 == 1 + i16 lasttv0; + i16 lasttv1; + i16 lasttv2; + i16 lasttv3; + i16 *pDebug0; // pointer to debug output i16 *pDebug1; // pointer to debug output i16 *pDebug2; // pointer to debug output + i16 *pDebug3; // pointer to debug output + #endif } t_tdet; typedef struct { i16 enabled; // if 0 none, 0xFFFF all tones, or single tone - i16 *input; + i16 *input; // source data i16 clamplitude; i16 center; i16 decode; // current ctcss decode index i32 BlankingTimer; u32 TurnOffTimer; - t_tdet tdet[CTCSS_NUM_CODES]; i16 gain; i16 limit; + i16 debugIndex; i16 *pDebug0; i16 *pDebug1; i16 *pDebug2; + i16 *pDebug3; i16 testIndex; i16 multiFreq; i8 relax; + t_tdet tdet[CTCSS_NUM_CODES]; -} t_dec_ctcss; + i8 numrxcodes; + i16 rxCtcssMap[CTCSS_NUM_CODES]; + char *rxctcss[CTCSS_NUM_CODES]; // pointers to each tone in string above + char *txctcss[CTCSS_NUM_CODES]; -typedef struct -{ - i16 enabled; // if 0 none, 0xFFFF all tones, or single tone - i16 clamplitude; - i16 center; - i16 decode; // current ctcss decode value - i32 BlankingTimer; - u32 TurnOffTimer; - i16 gain; - i16 limit; - i16 *pDebug0; - i16 *pDebug1; - i16 rxPolarity; -} t_dec_dcs; + i32 txctcssdefault_index; + float txctcssdefault_value; + + struct{ + unsigned valid:1; + }b; +} t_dec_ctcss; /* - Low Speed Data decoding both polarities + Low Speed Data +*/ +/* + general purpose pmr signal processing element */ -typedef struct -{ - i16 counter; // counter to next sample - i16 synced; - u32 syncCorr[2]; - u32 data[2]; - i16 state; // disabled, enabled, - i16 decode; - i16 debug; - - i16 polarity; - u32 frameNum; - - u16 area; - u16 chan; - u16 home; - u16 id; - u16 free; - - u16 crc; - i16 rssi; - -} t_decLsd; - - -/* general purpose pmr signal processing element */ struct t_pmr_chan; @@ -211,6 +442,7 @@ typedef struct t_pmr_sps i16 enabled; // enabled/disabled + struct t_pmr_chan *parentChan; i16 *source; // source buffer @@ -220,7 +452,9 @@ typedef struct t_pmr_sps i16 numChanOut; // allows output direct to interleaved buffer i16 selChanOut; - u32 ticks; + i32 ticks; + i32 timer; + i32 count; void *buff; // this structure's internal buffer @@ -258,6 +492,29 @@ typedef struct t_pmr_sps i16 err; // error condition i16 option; // option / request zero i16 state; // stopped, start, stopped assumes zero'd + + i16 pending; + + struct { + unsigned hit:1; + unsigned hitlast:1; + unsigned hita:1; + unsigned hitb:1; + unsigned bithit:1; + unsigned now:1; + unsigned next:1; + unsigned prev:1; + unsigned clock:1; + unsigned hold:1; + unsigned opt1:1; + unsigned opt2:1; + unsigned polarity:1; + unsigned dotting:1; + unsigned lastbitpending:1; + unsigned outzero:1; + unsigned settling:1; + unsigned syncing:1; + }b; i16 cleared; // output buffer cleared @@ -288,14 +545,28 @@ typedef struct t_pmr_sps } t_pmr_sps; + +struct t_dec_dcs; +struct t_lsd_control; +struct t_decLsd;; +struct t_encLsd; + /* pmr channel */ typedef struct t_pmr_chan { i16 index; // which one + i16 devicenum; // belongs to + + char *name; + i16 enabled; // enabled/disabled i16 status; // ok, error, busy, idle, initializing + + i16 tracelevel; + i16 tracetype; + u32 tracemask; i16 nSamplesRx; // max frame size i16 nSamplesTx; @@ -306,11 +577,23 @@ typedef struct t_pmr_chan i16 inputGain; i16 inputOffset; + i32 ticks; // time ticks u32 frameCountRx; // number processed u32 frameCountTx; + i8 txframelock; + i32 txHangTime; + i32 txHangTimer; i32 txTurnOff; + i16 txBufferClear; + + u32 txfreq; + u32 rxfreq; + i8 txpower; + + i32 txsettletime; // in samples + i32 txsettletimer; i16 rxDC; // average DC value of input i16 rxSqSet; // carrier squelch threshold @@ -319,6 +602,7 @@ typedef struct t_pmr_chan i16 rxQuality; // signal quality metric i16 rxCarrierDetect; // carrier detect i16 rxCdType; + i16 rxSqVoxAdj; i16 rxExtCarrierDetect; i32 inputBlanking; // Tx pulse eliminator @@ -340,20 +624,54 @@ typedef struct t_pmr_chan char radioDuplex; - struct { - unsigned pmrNoiseSquelch:1; - unsigned rxHpf:1; - unsigned txHpf:1; - unsigned txLpf:1; - unsigned rxDeEmphasis:1; - unsigned txPreEmphasis:1; - unsigned startSpecialTone:1; - unsigned stopSpecialTone:1; - unsigned doingSpecialTone:1; - unsigned extCarrierDetect:1; - unsigned txCapture:1; - unsigned rxCapture:1; - }b; + char *pStr; + + // start channel signaling codes source + char *pRxCodeSrc; // source + char *pTxCodeSrc; // source + char *pTxCodeDefault; // source + // end channel signaling codes source + + // start signaling code info derived from source + i16 numrxcodes; + i16 numtxcodes; + char *pRxCodeStr; // copied and cut up + char **pRxCode; // pointers to subs + char *pTxCodeStr; + char **pTxCode; + + char txctcssdefault[16]; // codes from higher level + + char *rxctcssfreqs; // rest are derived from this + char *txctcssfreqs; + + char numrxctcssfreqs; + char numtxctcssfreqs; + + char *rxctcss[CTCSS_NUM_CODES]; // pointers to each tone in string above + char *txctcss[CTCSS_NUM_CODES]; + + i16 rxCtcssMap[CTCSS_NUM_CODES]; + + i8 txcodedefaultsmode; + i16 txctcssdefault_index; + float txctcssdefault_value; + + char txctcssfreq[32]; // encode now + char rxctcssfreq[32]; // decode now + // end most of signaling code info derived from source + + struct t_lsd_control *pLsdCtl; + + i16 rptnum; + i16 area; + char *ukey; + u32 idleinterval; + char turnoffs; + + char pplock; + + t_dedrift dd; i16 dummy; @@ -379,21 +697,34 @@ typedef struct t_pmr_chan i16 rxCarrierPoint; i16 rxCarrierHyst; - - i16 rxCtcssMap[CTCSS_NUM_CODES]; i16 txCtcssTocShift; i16 txCtcssTocTime; i8 txTocType; - float txCtcssFreq; - float rxCtcssFreq; - float rxInputGain; - - i16 rxCtcssIndex; + i16 smode; // ctcss, dcs, lsd + i16 smodecode; + i16 smodewas; // ctcss, dcs, lsd + i32 smodetimer; // in ms + i32 smodetime; // to set in ms + + t_dec_ctcss *rxCtcss; + struct t_dec_dcs *decDcs; + struct t_decLsd *decLsd; + struct t_encLsd *pLsdEnc; + + i16 clamplitudeDcs; + i16 centerDcs; + u32 dcsBlankingTimer; + i16 dcsDecode; // current dcs decode value + + i16 clamplitudeLsd; + i16 centerLsd; + i16 txPttIn; // from external request i16 txPttOut; // to radio hardware + i16 txPttHid; i16 bandwidth; // wide/narrow i16 txCompand; // type @@ -410,12 +741,15 @@ typedef struct t_pmr_chan i16 function; - i16 txState; // off,settling,on,hangtime,turnoff + i16 txState; // off,settling,on,hangtime,turnoff + + i16 spsIndex; - t_pmr_sps *spsMeasure; // measurement block + t_pmr_sps *spsMeasure; // measurement block t_pmr_sps *spsRx; // 1st signal processing struct t_pmr_sps *spsRxLsd; + t_pmr_sps *spsRxLsdNrz; t_pmr_sps *spsRxDeEmp; t_pmr_sps *spsRxHpf; t_pmr_sps *spsRxVox; @@ -423,14 +757,14 @@ typedef struct t_pmr_chan t_pmr_sps *spsRxOut; // Last signal processing struct t_pmr_sps *spsTx; // 1st signal processing struct - - t_pmr_sps *spsTxLsdLpf; + t_pmr_sps *spsTxOutA; // Last signal processing struct - t_pmr_sps *spsTxOutB; // Last signal processing struct t_pmr_sps *spsSigGen0; // ctcss t_pmr_sps *spsSigGen1; // test and other tones + t_pmr_sps *spsLsdGen; + t_pmr_sps *spsTxLsdLpf; // tune tweaks @@ -452,6 +786,58 @@ typedef struct t_pmr_chan i32 *ptxLimiterAdjust; // from calling application + struct { + unsigned pmrNoiseSquelch:1; + unsigned rxHpf:1; + unsigned txHpf:1; + unsigned txLpf:1; + unsigned rxDeEmphasis:1; + unsigned txPreEmphasis:1; + unsigned startSpecialTone:1; + unsigned stopSpecialTone:1; + unsigned doingSpecialTone:1; + unsigned extCarrierDetect:1; + unsigned txCapture:1; + unsigned rxCapture:1; + unsigned reprog:1; + unsigned radioactive:1; + unsigned rxplmon:1; + unsigned remoted:1; + unsigned loopback:1; + unsigned rxpolarity:1; + unsigned txpolarity:1; + unsigned dcsrxpolarity:1; + unsigned dcstxpolarity:1; + unsigned lsdrxpolarity:1; + unsigned lsdtxpolarity:1; + unsigned txsettling:1; + unsigned smodeturnoff:1; + + unsigned ctcssRxEnable:1; + unsigned ctcssTxEnable:1; + unsigned dcsRxEnable:1; + unsigned dcsTxEnable:1; + unsigned lmrRxEnable:1; + unsigned lmrTxEnable:1; + unsigned mdcRxEnable:1; + unsigned mdcTxEnable:1; + unsigned dstRxEnable:1; + unsigned dstTxEnable:1; + unsigned p25RxEnable:1; + unsigned p25TxEnable:1; + unsigned ax25Enable:1; + + unsigned txCtcssInhibit:1; + + unsigned rxkeyed:1; + unsigned rxhalted:1; + unsigned txhalted:1; + unsigned pptp_p1:1; + unsigned pptp_p2:1; + unsigned tuning:1; + unsigned pttwas:1; + }b; + i16 *pRxDemod; // buffers i16 *pRxBase; // decimated lpf input i16 *pRxNoise; @@ -463,7 +849,10 @@ typedef struct t_pmr_chan i16 *pRxLsdLimit; // LSD Limited i16 *pRxCtcss; // i16 *pRxSquelch; + i16 *prxVoxMeas; + i16 *prxMeasure; + i16 *pTxInput; // input data i16 *pTxBase; // input data i16 *pTxHpf; i16 *pTxPreEmp; @@ -474,11 +863,6 @@ typedef struct t_pmr_chan i16 *pTxMod; // upsampled, low pass filtered i16 *pTxOut; // - - i16 *pTxPttIn; - i16 *pTxPttOut; - i16 *pTxHang; - i16 *pTxCode; i16 *pSigGen0; i16 *pSigGen1; @@ -488,6 +872,12 @@ typedef struct t_pmr_chan i16 *pNull; + #if XPMR_DEBUG0 == 1 + + i16 *pRxLsdCen; + + i16 *pTstTxOut; + i16 *prxDebug; // consolidated debug buffer i16 *ptxDebug; // consolidated debug buffer @@ -501,23 +891,23 @@ typedef struct t_pmr_chan i16 *ptxDebug2; i16 *ptxDebug3; - t_dec_ctcss *rxCtcss; - - i16 clamplitudeDcs; - i16 centerDcs; - u32 dcsBlankingTimer; - i16 dcsDecode; // current dcs decode value + #endif - i16 clamplitudeLsd; - i16 centerLsd; - t_decLsd decLsd[2]; // for both polarities + i16 numDebugChannels; + + t_sdbg *sdbg; } t_pmr_chan; -static i16 TxTestTone(t_pmr_chan *pChan, i16 function); +/* + function prototype declarations +*/ +void strace(i16 point, t_sdbg *sdbg, i16 index, i16 value); +void strace2(t_sdbg *sdbg); +static i16 TxTestTone(t_pmr_chan *pChan, i16 function); t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples); -t_pmr_sps *createPmrSps(void); +t_pmr_sps *createPmrSps(t_pmr_chan *pChan); i16 destroyPmrChannel(t_pmr_chan *pChan); i16 destroyPmrSps(t_pmr_sps *pSps); i16 pmr_rx_frontend(t_pmr_sps *mySps); @@ -531,10 +921,28 @@ i16 SoftLimiter(t_pmr_sps *mySps); i16 SigGen(t_pmr_sps *mySps); i16 pmrMixer(t_pmr_sps *mySps); i16 DelayLine(t_pmr_sps *mySps); -i16 PmrRx(t_pmr_chan *PmrChan, i16 *input, i16 *output); -i16 PmrTx(t_pmr_chan *PmrChan, i16 *input, i16 *output); + +i16 PmrRx(t_pmr_chan *PmrChan, i16 *input, i16 *outputrx, i16 *outputtx ); +i16 PmrTx(t_pmr_chan *PmrChan, i16 *input); + +i16 string_parse(char *src, char **dest, char ***ptrs); +i16 code_string_parse(t_pmr_chan *pChan); + i16 CtcssFreqIndex(float freq); i16 MeasureBlock(t_pmr_sps *mySps); + +void dedrift (t_pmr_chan *pChan); +void dedrift_write (t_pmr_chan *pChan, i16 *src); + +void ppspiout (u32 spidata); +void progdtx (t_pmr_chan *pChan); +void ppbinout (u8 chan); + +#if XPMR_PPTP == 1 +void pptp_init (void); +void pptp_write (i16 bit, i16 state); +#endif + #endif /* ! XPMR_H */ /* end of file */ diff --git a/channels/xpmr/xpmr_coef.h b/channels/xpmr/xpmr_coef.h index fda6762da..84254e884 100755 --- a/channels/xpmr/xpmr_coef.h +++ b/channels/xpmr/xpmr_coef.h @@ -4,16 +4,28 @@ * All Rights Reserved. Copyright (C)2007, Xelatec, LLC * * 20070808 1235 Steven Henke, W9SH, sph@xelatec.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This version may be optionally licenced under the GNU LGPL licence. + * + * A license has been granted to Digium (via disclaimer) for the use of + * this code. * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. + * Some filter coeficients via 'WinFilter' http://www.winfilter.20m.com. * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. */ /*! \file @@ -24,30 +36,25 @@ */ #ifndef XPMR_COEF_H -#define XMPR_COEF_H 1 +#define XMPR_COEF_H 1 // frequencies in 0.1 Hz -const u32 dtmf_row[] = +static const u32 dtmf_row[] = { 6970, 7700, 8520, 9410 }; -const u32 dtmf_col[] = +static const u32 dtmf_col[] = { 12090, 13360, 14770, 16330 }; -const i16 coef_dcs_rx = 1488; // dcs rx data divisor for oversampling 8000/134.4 -const i16 coef_dcs_tx = 5952; // dcs tx data divisor - -const i16 coef_lsd_div = 672; // low speed data divisor -const u32 coef_lsd_sync = 0x158; // 000101011000 -const u32 coef_lsd_sync_pattern[] = {0x0000000F, 0x0F0FF000}; #define CTCSS_COEF_INT 120 #define CTCSS_SAMPLE_RATE 8000 #define TDIV(x) ((CTCSS_SAMPLE_RATE*1000/x)+5)/10 -i32 coef_ctcss[4][5]= +#if 0 +static i32 coef_ctcss[4][5]= { // freq, divisor, integrator, filter {770,TDIV(770),CTCSS_COEF_INT,0,0}, @@ -55,9 +62,9 @@ i32 coef_ctcss[4][5]= {1035,TDIV(1035),CTCSS_COEF_INT,0,0}, {0,0,0,0} }; +#endif - -i16 coef_ctcss_div[]= +static i16 coef_ctcss_div[]= { 2985, // 00 067.0 2782, // 01 071.9 @@ -99,7 +106,7 @@ i16 coef_ctcss_div[]= 799 // 37 250.3 }; -float freq_ctcss[]= +static float freq_ctcss[]= { 067.0, // 00 071.9, // 01 @@ -378,7 +385,8 @@ static const int16_t coef_int_lpf_300_1_2[]={ // pre-emphasis differentiator 4000 Hz with 8KS/s // a0,a1,b0, static const int16_t taps_int_hpf_4000_1_2 = 2; -static const int32_t gain_int_hpf_4000_1_2 = 16384; +//static const int32_t gain_int_hpf_4000_1_2 = 16384; // per calculations +static const int32_t gain_int_hpf_4000_1_2 = 13404; // hand tweaked for unity gain at 1KHz static const int16_t coef_int_hpf_4000_1_2[]={ 17610, -17610, @@ -386,298 +394,6 @@ static const int16_t coef_int_hpf_4000_1_2[]={ }; -/* - ltr crc table - from http://www.radioreference.com/forums/showthread.php?t=24126 -*/ - -static const u8 ltr_table[]= -{ -0x38, // 00 Area 0111000 -0x1c, // 01 Channel 4 0011100 -0x0e, // 02 Channel 3 0001110 -0x46, // 03 Channel 2 1000110 -0x23, // 04 Channel 1 0100011 -0x51, // 05 Channel 0 1010001 -0x68, // 06 Home 4 1101000 -0x75, // 07 Home 3 1110101 -0x7a, // 08 Home 2 1111010 -0x3d, // 09 Home 1 0111101 -0x1f, // 10 Home 0 0011111 -0x4f, // 11 Group 7 1001111 -0x26, // 12 Group 6 0100110 -0x52, // 13 Group 5 1010010 -0x29, // 14 Group 4 0101001 -0x15, // 15 Group 3 0010101 -0x0d, // 16 Group 2 0001101 -0x45, // 17 Group 1 1000101 -0x62, // 18 Group 0 1100010 -0x31, // 19 Free 4 0110001 -0x19, // 20 Free 3 0011001 -0x0d, // 21 Free 2 0001101 -0x07, // 22 Free 1 0000111 -0x43 // 23 Free 0 1000011 -}; - -static const i16 bitWeight[]= -{ -0, // 0 -1, // 1 -1, // 2 -2, // 3 -1, // 4 -2, // 5 -2, // 6 -3, // 7 -1, // 8 -2, // 9 -2, // 10 -3, // 11 -2, // 12 -3, // 13 -3, // 14 -4, // 15 -1, // 16 -2, // 17 -2, // 18 -3, // 19 -2, // 20 -3, // 21 -3, // 22 -4, // 23 -2, // 24 -3, // 25 -3, // 26 -4, // 27 -3, // 28 -4, // 29 -4, // 30 -5, // 31 -1, // 32 -2, // 33 -2, // 34 -3, // 35 -2, // 36 -3, // 37 -3, // 38 -4, // 39 -2, // 40 -3, // 41 -3, // 42 -4, // 43 -3, // 44 -4, // 45 -4, // 46 -5, // 47 -2, // 48 -3, // 49 -3, // 50 -4, // 51 -3, // 52 -4, // 53 -4, // 54 -5, // 55 -3, // 56 -4, // 57 -4, // 58 -5, // 59 -4, // 60 -5, // 61 -5, // 62 -6, // 63 -1, // 64 -2, // 65 -2, // 66 -3, // 67 -2, // 68 -3, // 69 -3, // 70 -4, // 71 -2, // 72 -3, // 73 -3, // 74 -4, // 75 -3, // 76 -4, // 77 -4, // 78 -5, // 79 -2, // 80 -3, // 81 -3, // 82 -4, // 83 -3, // 84 -4, // 85 -4, // 86 -5, // 87 -3, // 88 -4, // 89 -4, // 90 -5, // 91 -4, // 92 -5, // 93 -5, // 94 -6, // 95 -2, // 96 -3, // 97 -3, // 98 -4, // 99 -3, // 100 -4, // 101 -4, // 102 -5, // 103 -3, // 104 -4, // 105 -4, // 106 -5, // 107 -4, // 108 -5, // 109 -5, // 110 -6, // 111 -3, // 112 -4, // 113 -4, // 114 -5, // 115 -4, // 116 -5, // 117 -5, // 118 -6, // 119 -4, // 120 -5, // 121 -5, // 122 -6, // 123 -5, // 124 -6, // 125 -6, // 126 -7, // 127 -1, // 128 -2, // 129 -2, // 130 -3, // 131 -2, // 132 -3, // 133 -3, // 134 -4, // 135 -2, // 136 -3, // 137 -3, // 138 -4, // 139 -3, // 140 -4, // 141 -4, // 142 -5, // 143 -2, // 144 -3, // 145 -3, // 146 -4, // 147 -3, // 148 -4, // 149 -4, // 150 -5, // 151 -3, // 152 -4, // 153 -4, // 154 -5, // 155 -4, // 156 -5, // 157 -5, // 158 -6, // 159 -2, // 160 -3, // 161 -3, // 162 -4, // 163 -3, // 164 -4, // 165 -4, // 166 -5, // 167 -3, // 168 -4, // 169 -4, // 170 -5, // 171 -4, // 172 -5, // 173 -5, // 174 -6, // 175 -3, // 176 -4, // 177 -4, // 178 -5, // 179 -4, // 180 -5, // 181 -5, // 182 -6, // 183 -4, // 184 -5, // 185 -5, // 186 -6, // 187 -5, // 188 -6, // 189 -6, // 190 -7, // 191 -2, // 192 -3, // 193 -3, // 194 -4, // 195 -3, // 196 -4, // 197 -4, // 198 -5, // 199 -3, // 200 -4, // 201 -4, // 202 -5, // 203 -4, // 204 -5, // 205 -5, // 206 -6, // 207 -3, // 208 -4, // 209 -4, // 210 -5, // 211 -4, // 212 -5, // 213 -5, // 214 -6, // 215 -4, // 216 -5, // 217 -5, // 218 -6, // 219 -5, // 220 -6, // 221 -6, // 222 -7, // 223 -3, // 224 -4, // 225 -4, // 226 -5, // 227 -4, // 228 -5, // 229 -5, // 230 -6, // 231 -4, // 232 -5, // 233 -5, // 234 -6, // 235 -5, // 236 -6, // 237 -6, // 238 -7, // 239 -4, // 240 -5, // 241 -5, // 242 -6, // 243 -5, // 244 -6, // 245 -6, // 246 -7, // 247 -5, // 248 -6, // 249 -6, // 250 -7, // 251 -6, // 252 -7, // 253 -7, // 254 -8 // 255 -}; /* -- cgit v1.2.3