aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-14 15:42:42 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-14 15:42:42 +0000
commit4b7add369a1a77105a5f2738eb4e8c68be8b7c46 (patch)
treeadad85f05da59260b14f303c965bb79c12176d8b /channels
parenteb84605afa03401d6cd92501b72e9b1112fd3247 (diff)
Remove chan_usbradio from the main 1.4 branch. It can't live here because we
have a strict policy to not include new features in release branches. However, I'm going to merge it into trunk, and I also have a special 1.4 based branch that includes this module. svn co http://svn.digium.com/svn/asterisk/team/jdixon/chan_usbradio-1.4 git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@82382 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/Makefile6
-rw-r--r--channels/chan_usbradio.c2812
-rwxr-xr-xchannels/xpmr/LICENSE341
-rwxr-xr-xchannels/xpmr/sinetabx.h300
-rwxr-xr-xchannels/xpmr/xpmr.c2266
-rwxr-xr-xchannels/xpmr/xpmr.h553
-rwxr-xr-xchannels/xpmr/xpmr_coef.h963
7 files changed, 0 insertions, 7241 deletions
diff --git a/channels/Makefile b/channels/Makefile
index 7aea7d857..beba0d1ff 100644
--- a/channels/Makefile
+++ b/channels/Makefile
@@ -116,9 +116,3 @@ misdn/isdn_lib.o: ASTCFLAGS+=-Wno-strict-aliasing
$(if $(filter chan_misdn,$(EMBEDDED_MODS)),modules.link,chan_misdn.so): chan_misdn.o misdn_config.o misdn/isdn_lib.o misdn/isdn_msg_parser.o
chan_vpb.oo: ASTCFLAGS:=$(filter-out -Wdeclaration-after-statement,$(ASTCFLAGS))
-
-chan_usbradio.o: chan_usbradio.c xpmr/xpmr.c xpmr/xpmr.h xpmr/xpmr_coef.h xpmr/sinetabx.h busy.h ringtone.h
-
-chan_usbradio.so: LIBS+=-lusb -lasound
-
-
diff --git a/channels/chan_usbradio.c b/channels/chan_usbradio.c
deleted file mode 100644
index 570f5b569..000000000
--- a/channels/chan_usbradio.c
+++ /dev/null
@@ -1,2812 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- * Copyright (C) 2007, Jim Dixon
- *
- * Jim Dixon, WB6NIL <jim@lambdatel.com>
- * Steve Henke, W9SH <w9sh@arrl.net>
- * Based upon work by Mark Spencer <markster@digium.com> and Luigi Rizzo
- *
- * 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, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Channel driver for CM108 USB Cards with Radio Interface
- *
- * \author Jim Dixon <jim@lambdatel.com>
- * \author Steve Henke <w9sh@arrl.net>
- *
- * \par See also
- * \arg \ref Config_usbradio
- *
- * \ingroup channel_drivers
- */
-
-/*** MODULEINFO
- <depend>ossaudio</depend>
- <defaultenabled>no</defaultenabled>
- ***/
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdio.h>
-#include <ctype.h>
-#include <math.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <usb.h>
-#include <alsa/asoundlib.h>
-
-#define CHAN_USBRADIO 1
-
-#define DEBUG_USBRADIO 0
-#define DEBUG_CAPTURES 1
-
-#define DEBUG_CAP_RX_OUT 0
-#define DEBUG_CAP_TX_OUT 0
-
-#define DEBUG_FILETEST 0
-
-#define RX_CAP_RAW_FILE "/tmp/rx_cap_in.pcm"
-#define RX_CAP_TRACE_FILE "/tmp/rx_trace.pcm"
-#define RX_CAP_OUT_FILE "/tmp/rx_cap_out.pcm"
-
-#define TX_CAP_RAW_FILE "/tmp/tx_cap_in.pcm"
-#define TX_CAP_TRACE_FILE "/tmp/tx_trace.pcm"
-#define TX_CAP_OUT_FILE "/tmp/tx_cap_out.pcm"
-
-#define MIXER_PARAM_MIC_PLAYBACK_SW "Mic Playback Switch"
-#define MIXER_PARAM_MIC_PLAYBACK_VOL "Mic Playback Volume"
-#define MIXER_PARAM_MIC_CAPTURE_SW "Mic Capture Switch"
-#define MIXER_PARAM_MIC_CAPTURE_VOL "Mic Capture Volume"
-#define MIXER_PARAM_MIC_BOOST "Auto Gain Control"
-#define MIXER_PARAM_SPKR_PLAYBACK_SW "Speaker Playback Switch"
-#define MIXER_PARAM_SPKR_PLAYBACK_VOL "Speaker Playback Volume"
-
-#include "./xpmr/xpmr.h"
-
-#if 0
-#define traceusb1(a) {printf a;}
-#else
-#define traceusb1(a)
-#endif
-
-#if 0
-#define traceusb2(a) {printf a;}
-#else
-#define traceusb2(a)
-#endif
-
-#ifdef __linux
-#include <linux/soundcard.h>
-#elif defined(__FreeBSD__)
-#include <sys/soundcard.h>
-#else
-#include <soundcard.h>
-#endif
-
-#include "asterisk/lock.h"
-#include "asterisk/frame.h"
-#include "asterisk/logger.h"
-#include "asterisk/callerid.h"
-#include "asterisk/channel.h"
-#include "asterisk/module.h"
-#include "asterisk/options.h"
-#include "asterisk/pbx.h"
-#include "asterisk/config.h"
-#include "asterisk/cli.h"
-#include "asterisk/utils.h"
-#include "asterisk/causes.h"
-#include "asterisk/endian.h"
-#include "asterisk/stringfields.h"
-#include "asterisk/abstract_jb.h"
-#include "asterisk/musiconhold.h"
-#include "asterisk/dsp.h"
-
-/* ringtones we use */
-#include "busy.h"
-#include "ringtone.h"
-#include "ring10.h"
-#include "answer.h"
-
-#define C108_VENDOR_ID 0x0d8c
-#define C108_PRODUCT_ID 0x000c
-#define C108_HID_INTERFACE 3
-
-#define HID_REPORT_GET 0x01
-#define HID_REPORT_SET 0x09
-
-#define HID_RT_INPUT 0x01
-#define HID_RT_OUTPUT 0x02
-
-/*! Global jitterbuffer configuration - by default, jb is disabled */
-static struct ast_jb_conf default_jbconf =
-{
- .flags = 0,
- .max_size = -1,
- .resync_threshold = -1,
- .impl = "",
-};
-static struct ast_jb_conf global_jbconf;
-
-/*
- * usbradio.conf parameters are
-START_CONFIG
-
-[general]
- ; General config options, with default values shown.
- ; You should use one section per device, with [general] being used
- ; for the device.
- ;
- ;
- ; debug = 0x0 ; misc debug flags, default is 0
-
- ; Set the device to use for I/O
- ; devicenum = 0
- ; Set hardware type here
- ; hdwtype=0 ; 0=limey, 1=sph
-
- ; rxboostset=0 ; no rx gain boost
- ; rxctcssrelax=1 ; reduce talkoff from radios w/o CTCSS Tx HPF
- ; rxctcssfreq=100.0 ; rx ctcss freq in floating point. must be in table
- ; txctcssfreq=100.0 ; tx ctcss freq, any frequency permitted
-
- ; carrierfrom=dsp ;no,usb,usbinvert,dsp,vox
- ; ctcssfrom=dsp ;no,usb,dsp
-
- ; rxdemod=flat ; input type from radio: no,speaker,flat
- ; txprelim=yes ; output is pre-emphasised and limited
- ; txtoctype=no ; no,phase,notone
-
- ; txmixa=composite ;no,voice,tone,composite,auxvoice
- ; txmixb=no ;no,voice,tone,composite,auxvoice
-
- ; invertptt=0
-
- ;------------------------------ JITTER BUFFER CONFIGURATION --------------------------
- ; jbenable = yes ; Enables the use of a jitterbuffer on the receiving side of an
- ; USBRADIO channel. Defaults to "no". An enabled jitterbuffer will
- ; be used only if the sending side can create and the receiving
- ; side can not accept jitter. The USBRADIO channel can't accept jitter,
- ; thus an enabled jitterbuffer on the receive USBRADIO side will always
- ; be used if the sending side can create jitter.
-
- ; jbmaxsize = 200 ; Max length of the jitterbuffer in milliseconds.
-
- ; jbresyncthreshold = 1000 ; Jump in the frame timestamps over which the jitterbuffer is
- ; resynchronized. Useful to improve the quality of the voice, with
- ; big jumps in/broken timestamps, usualy sent from exotic devices
- ; and programs. Defaults to 1000.
-
- ; jbimpl = fixed ; Jitterbuffer implementation, used on the receiving side of an USBRADIO
- ; channel. Two implementations are currenlty available - "fixed"
- ; (with size always equals to jbmax-size) and "adaptive" (with
- ; variable size, actually the new jb of IAX2). Defaults to fixed.
-
- ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no".
- ;-----------------------------------------------------------------------------------
-
-
-END_CONFIG
-
- */
-
-/*
- * Helper macros to parse config arguments. They will go in a common
- * header file if their usage is globally accepted. In the meantime,
- * we define them here. Typical usage is as below.
- * Remember to open a block right before M_START (as it declares
- * some variables) and use the M_* macros WITHOUT A SEMICOLON:
- *
- * {
- * M_START(v->name, v->value)
- *
- * M_BOOL("dothis", x->flag1)
- * M_STR("name", x->somestring)
- * M_F("bar", some_c_code)
- * M_END(some_final_statement)
- * ... other code in the block
- * }
- *
- * XXX NOTE these macros should NOT be replicated in other parts of asterisk.
- * Likely we will come up with a better way of doing config file parsing.
- */
-#define M_START(var, val) \
- char *__s = var; char *__val = val;
-#define M_END(x) x;
-#define M_F(tag, f) if (!strcasecmp((__s), tag)) { f; } else
-#define M_BOOL(tag, dst) M_F(tag, (dst) = ast_true(__val) )
-#define M_UINT(tag, dst) M_F(tag, (dst) = strtoul(__val, NULL, 0) )
-#define M_STR(tag, dst) M_F(tag, ast_copy_string(dst, __val, sizeof(dst)))
-
-/*
- * The following parameters are used in the driver:
- *
- * FRAME_SIZE the size of an audio frame, in samples.
- * 160 is used almost universally, so you should not change it.
- *
- * FRAGS the argument for the SETFRAGMENT ioctl.
- * Overridden by the 'frags' parameter in usbradio.conf
- *
- * Bits 0-7 are the base-2 log of the device's block size,
- * bits 16-31 are the number of blocks in the driver's queue.
- * There are a lot of differences in the way this parameter
- * is supported by different drivers, so you may need to
- * experiment a bit with the value.
- * A good default for linux is 30 blocks of 64 bytes, which
- * results in 6 frames of 320 bytes (160 samples).
- * FreeBSD works decently with blocks of 256 or 512 bytes,
- * leaving the number unspecified.
- * Note that this only refers to the device buffer size,
- * this module will then try to keep the lenght of audio
- * buffered within small constraints.
- *
- * QUEUE_SIZE The max number of blocks actually allowed in the device
- * driver's buffer, irrespective of the available number.
- * Overridden by the 'queuesize' parameter in usbradio.conf
- *
- * Should be >=2, and at most as large as the hw queue above
- * (otherwise it will never be full).
- */
-
-#define FRAME_SIZE 160
-#define QUEUE_SIZE 20
-
-#if defined(__FreeBSD__)
-#define FRAGS 0x8
-#else
-#define FRAGS ( ( (6 * 5) << 16 ) | 0xc )
-#endif
-
-/*
- * XXX text message sizes are probably 256 chars, but i am
- * not sure if there is a suitable definition anywhere.
- */
-#define TEXT_SIZE 256
-
-#if 0
-#define TRYOPEN 1 /* try to open on startup */
-#endif
-#define O_CLOSE 0x444 /* special 'close' mode for device */
-/* Which device to use */
-#if defined( __OpenBSD__ ) || defined( __NetBSD__ )
-#define DEV_DSP "/dev/audio"
-#else
-#define DEV_DSP "/dev/dsp"
-#endif
-
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-static char *config = "usbradio.conf"; /* default config file */
-static char *config1 = "usbradio_tune.conf"; /* tune config file */
-
-static FILE *frxcapraw = NULL, *frxcaptrace = NULL, *frxoutraw = NULL;
-static FILE *ftxcapraw = NULL, *ftxcaptrace = NULL, *ftxoutraw = NULL;
-
-static int usbradio_debug;
-#if 0 //maw asdf sph
-static int usbradio_debug_level = 0;
-#endif
-
-enum {RX_AUDIO_NONE,RX_AUDIO_SPEAKER,RX_AUDIO_FLAT};
-enum {CD_IGNORE,CD_XPMR_NOISE,CD_XPMR_VOX,CD_HID,CD_HID_INVERT};
-enum {SD_IGNORE,SD_HID,SD_HID_INVERT,SD_XPMR}; // no,external,externalinvert,software
-enum {RX_KEY_CARRIER,RX_KEY_CARRIER_CODE};
-enum {TX_OUT_OFF,TX_OUT_VOICE,TX_OUT_LSD,TX_OUT_COMPOSITE,TX_OUT_AUX};
-enum {TOC_NONE,TOC_PHASE,TOC_NOTONE};
-
-/* DECLARE STRUCTURES */
-
-/*
- * Each sound is made of 'datalen' samples of sound, repeated as needed to
- * generate 'samplen' samples of data, then followed by 'silencelen' samples
- * of silence. The loop is repeated if 'repeat' is set.
- */
-struct sound {
- int ind;
- char *desc;
- short *data;
- int datalen;
- int samplen;
- int silencelen;
- int repeat;
-};
-
-static struct sound sounds[] = {
- { AST_CONTROL_RINGING, "RINGING", ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
- { AST_CONTROL_BUSY, "BUSY", busy, sizeof(busy)/2, 4000, 4000, 1 },
- { AST_CONTROL_CONGESTION, "CONGESTION", busy, sizeof(busy)/2, 2000, 2000, 1 },
- { AST_CONTROL_RING, "RING10", ring10, sizeof(ring10)/2, 16000, 32000, 1 },
- { AST_CONTROL_ANSWER, "ANSWER", answer, sizeof(answer)/2, 2200, 0, 0 },
- { -1, NULL, 0, 0, 0, 0 }, /* end marker */
-};
-
-
-/*
- * descriptor for one of our channels.
- * There is one used for 'default' values (from the [general] entry in
- * the configuration file), and then one instance for each device
- * (the default is cloned from [general], others are only created
- * if the relevant section exists).
- */
-struct chan_usbradio_pvt {
- struct chan_usbradio_pvt *next;
-
- char *name;
- /*
- * cursound indicates which in struct sound we play. -1 means nothing,
- * any other value is a valid sound, in which case sampsent indicates
- * the next sample to send in [0..samplen + silencelen]
- * nosound is set to disable the audio data from the channel
- * (so we can play the tones etc.).
- */
- int sndcmd[2]; /* Sound command pipe */
- int cursound; /* index of sound to send */
- int sampsent; /* # of sound samples sent */
- int nosound; /* set to block audio from the PBX */
-
- int total_blocks; /* total blocks in the output device */
- int sounddev;
- enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;
- i16 cdMethod;
- int autoanswer;
- int autohangup;
- int hookstate;
- unsigned int queuesize; /* max fragments in queue */
- unsigned int frags; /* parameter for SETFRAGMENT */
-
- int warned; /* various flags used for warnings */
-#define WARN_used_blocks 1
-#define WARN_speed 2
-#define WARN_frag 4
- int w_errors; /* overfull in the write path */
- struct timeval lastopen;
-
- int overridecontext;
- int mute;
-
- /* boost support. BOOST_SCALE * 10 ^(BOOST_MAX/20) must
- * be representable in 16 bits to avoid overflows.
- */
-#define BOOST_SCALE (1<<9)
-#define BOOST_MAX 40 /* slightly less than 7 bits */
- int boost; /* input boost, scaled by BOOST_SCALE */
- char devicenum;
- int spkrmax;
- int micmax;
-
- pthread_t sthread;
- pthread_t hidthread;
-
- int stophid;
- struct ast_channel *owner;
- char ext[AST_MAX_EXTENSION];
- char ctx[AST_MAX_CONTEXT];
- char language[MAX_LANGUAGE];
- char cid_name[256]; /*XXX */
- char cid_num[256]; /*XXX */
- char mohinterpret[MAX_MUSICCLASS];
-
- /* buffers used in usbradio_write, 2 per int by 2 channels by 6 times oversampling (48KS/s) */
- char usbradio_write_buf[FRAME_SIZE * 2 * 2 * 6];
- char usbradio_write_buf_1[FRAME_SIZE * 2 * 2* 6];
-
- int usbradio_write_dst;
- /* buffers used in usbradio_read - AST_FRIENDLY_OFFSET space for headers
- * plus enough room for a full frame
- */
- char usbradio_read_buf[FRAME_SIZE * (2 * 12) + AST_FRIENDLY_OFFSET];
- char usbradio_read_buf_8k[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
- int readpos; /* read position above */
- struct ast_frame read_f; /* returned by usbradio_read */
-
-
- char debuglevel;
- char radioduplex; //
-
- char lastrx;
- char rxhidsq;
- char rxcarrierdetect; // status from pmr channel
- char rxctcssdecode; // status from pmr channel
-
- char rxkeytype;
- char rxkeyed; // indicates rx signal present
-
- char lasttx;
- char txkeyed; // tx key request from upper layers
- char txchankey;
- char txtestkey;
-
- time_t lasthidtime;
- struct ast_dsp *dsp;
-
- t_pmr_chan *pmrChan;
-
- char rxcpusaver;
- char txcpusaver;
-
- char rxdemod;
- float rxgain;
- char rxcdtype;
- char rxsdtype;
- int rxsquelchadj; /* this copy needs to be here for initialization */
- char txtoctype;
-
- char txprelim;
- float txctcssgain;
- char txmixa;
- char txmixb;
-
- char invertptt;
-
- char rxctcssrelax;
- float rxctcssgain;
- float rxctcssfreq;
- float txctcssfreq;
-
- int rxmixerset;
- int rxboostset;
- float rxvoiceadj;
- float rxctcssadj;
- int txmixaset;
- int txmixbset;
- int txctcssadj;
-
- int hdwtype;
- int hid_gpio_ctl;
- int hid_gpio_ctl_loc;
- int hid_io_cor;
- int hid_io_cor_loc;
- int hid_io_ctcss;
- int hid_io_ctcss_loc;
- int hid_io_ptt;
- int hid_gpio_loc;
-
- struct {
- unsigned rxcapraw:1;
- unsigned txcapraw:1;
- unsigned txcap2:1;
- unsigned rxcap2:1;
- }b;
-};
-
-// maw add additional defaults !!!
-static struct chan_usbradio_pvt usbradio_default = {
- .cursound = -1,
- .sounddev = -1,
- .duplex = M_UNSET, /* XXX check this */
- .autoanswer = 1,
- .autohangup = 1,
- .queuesize = QUEUE_SIZE,
- .frags = FRAGS,
- .ext = "s",
- .ctx = "default",
- .readpos = AST_FRIENDLY_OFFSET, /* start here on reads */
- .lastopen = { 0, 0 },
- .boost = BOOST_SCALE,
-};
-
-/* DECLARE FUNCTION PROTOTYPES */
-
-static void store_txtoctype(struct chan_usbradio_pvt *o, char *s);
-static int hidhdwconfig(struct chan_usbradio_pvt *o);
-static int set_txctcss_level(struct chan_usbradio_pvt *o);
-static void pmrdump(struct chan_usbradio_pvt *o);
-static void mult_set(struct chan_usbradio_pvt *o);
-static int mult_calc(int value);
-static void mixer_write(struct chan_usbradio_pvt *o);
-static void tune_rxinput(struct chan_usbradio_pvt *o);
-static void tune_rxvoice(struct chan_usbradio_pvt *o);
-static void tune_rxctcss(struct chan_usbradio_pvt *o);
-static void tune_txoutput(struct chan_usbradio_pvt *o, int value);
-static void tune_write(struct chan_usbradio_pvt *o);
-
-static char *usbradio_active; /* the active device */
-
-static int setformat(struct chan_usbradio_pvt *o, int mode);
-
-static struct ast_channel *usbradio_request(const char *type, int format, void *data
-, int *cause);
-static int usbradio_digit_begin(struct ast_channel *c, char digit);
-static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration);
-static int usbradio_text(struct ast_channel *c, const char *text);
-static int usbradio_hangup(struct ast_channel *c);
-static int usbradio_answer(struct ast_channel *c);
-static struct ast_frame *usbradio_read(struct ast_channel *chan);
-static int usbradio_call(struct ast_channel *c, char *dest, int timeout);
-static int usbradio_write(struct ast_channel *chan, struct ast_frame *f);
-static int usbradio_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);
-static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
-
-#if DEBUG_FILETEST == 1
-static int RxTestIt(struct chan_usbradio_pvt *o);
-#endif
-
-static char tdesc[] = "USB (CM108) Radio Channel Driver";
-
-static const struct ast_channel_tech usbradio_tech = {
- .type = "Radio",
- .description = tdesc,
- .capabilities = AST_FORMAT_SLINEAR,
- .requester = usbradio_request,
- .send_digit_begin = usbradio_digit_begin,
- .send_digit_end = usbradio_digit_end,
- .send_text = usbradio_text,
- .hangup = usbradio_hangup,
- .answer = usbradio_answer,
- .read = usbradio_read,
- .call = usbradio_call,
- .write = usbradio_write,
- .indicate = usbradio_indicate,
- .fixup = usbradio_fixup,
-};
-
-/* Call with: devnum: alsa major device number, param: ascii Formal
-Parameter Name, val1, first or only value, val2 second value, or 0
-if only 1 value. Values: 0-99 (percent) or 0-1 for baboon.
-
-Note: must add -lasound to end of linkage */
-
-static int amixer_max(int devnum,char *param)
-{
-int rv,type;
-char str[100];
-snd_hctl_t *hctl;
-snd_ctl_elem_id_t *id;
-snd_hctl_elem_t *elem;
-snd_ctl_elem_info_t *info;
-
- sprintf(str,"hw:%d",devnum);
- if (snd_hctl_open(&hctl, str, 0)) return(-1);
- snd_hctl_load(hctl);
- snd_ctl_elem_id_alloca(&id);
- snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
- snd_ctl_elem_id_set_name(id, param);
- elem = snd_hctl_find_elem(hctl, id);
- if (!elem)
- {
- snd_hctl_close(hctl);
- return(-1);
- }
- snd_ctl_elem_info_alloca(&info);
- snd_hctl_elem_info(elem,info);
- type = snd_ctl_elem_info_get_type(info);
- rv = 0;
- switch(type)
- {
- case SND_CTL_ELEM_TYPE_INTEGER:
- rv = snd_ctl_elem_info_get_max(info);
- break;
- case SND_CTL_ELEM_TYPE_BOOLEAN:
- rv = 1;
- break;
- }
- snd_hctl_close(hctl);
- return(rv);
-}
-
-/* Call with: devnum: alsa major device number, param: ascii Formal
-Parameter Name, val1, first or only value, val2 second value, or 0
-if only 1 value. Values: 0-99 (percent) or 0-1 for baboon.
-
-Note: must add -lasound to end of linkage */
-
-static int setamixer(int devnum,char *param, int v1, int v2)
-{
-int type;
-char str[100];
-snd_hctl_t *hctl;
-snd_ctl_elem_id_t *id;
-snd_ctl_elem_value_t *control;
-snd_hctl_elem_t *elem;
-snd_ctl_elem_info_t *info;
-
- sprintf(str,"hw:%d",devnum);
- if (snd_hctl_open(&hctl, str, 0)) return(-1);
- snd_hctl_load(hctl);
- snd_ctl_elem_id_alloca(&id);
- snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
- snd_ctl_elem_id_set_name(id, param);
- elem = snd_hctl_find_elem(hctl, id);
- if (!elem)
- {
- snd_hctl_close(hctl);
- return(-1);
- }
- snd_ctl_elem_info_alloca(&info);
- snd_hctl_elem_info(elem,info);
- type = snd_ctl_elem_info_get_type(info);
- snd_ctl_elem_value_alloca(&control);
- snd_ctl_elem_value_set_id(control, id);
- switch(type)
- {
- case SND_CTL_ELEM_TYPE_INTEGER:
- snd_ctl_elem_value_set_integer(control, 0, v1);
- if (v2 > 0) snd_ctl_elem_value_set_integer(control, 1, v2);
- break;
- case SND_CTL_ELEM_TYPE_BOOLEAN:
- snd_ctl_elem_value_set_integer(control, 0, (v1 != 0));
- break;
- }
- if (snd_hctl_elem_write(elem, control))
- {
- snd_hctl_close(hctl);
- return(-1);
- }
- snd_hctl_close(hctl);
- return(0);
-}
-
-static void hid_set_outputs(struct usb_dev_handle *handle,
- unsigned char *outputs)
-{
- usb_control_msg(handle,
- USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
- HID_REPORT_SET,
- 0 + (HID_RT_OUTPUT << 8),
- C108_HID_INTERFACE,
- (char*)outputs, 4, 5000);
-}
-
-static void hid_get_inputs(struct usb_dev_handle *handle,
- unsigned char *inputs)
-{
- usb_control_msg(handle,
- USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
- HID_REPORT_GET,
- 0 + (HID_RT_INPUT << 8),
- C108_HID_INTERFACE,
- (char*)inputs, 4, 5000);
-}
-
-static struct usb_device *hid_device_init(void)
-{
- struct usb_bus *usb_bus;
- struct usb_device *dev;
- usb_init();
- usb_find_busses();
- usb_find_devices();
- for (usb_bus = usb_busses;
- usb_bus;
- usb_bus = usb_bus->next) {
- for (dev = usb_bus->devices;
- dev;
- dev = dev->next) {
- if ((dev->descriptor.idVendor
- == C108_VENDOR_ID) &&
- (dev->descriptor.idProduct
- == C108_PRODUCT_ID))
- return dev;
- }
- }
- return NULL;
-}
-
-static int hidhdwconfig(struct chan_usbradio_pvt *o)
-{
- if(o->hdwtype==1) //sphusb
- {
- o->hid_gpio_ctl = 0x08; /* set GPIO4 to output mode */
- o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
- o->hid_io_cor = 4; /* GPIO3 is COR */
- o->hid_io_cor_loc = 1; /* GPIO3 is COR */
- o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
- o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
- o->hid_io_ptt = 8; /* GPIO 4 is PTT */
- o->hid_gpio_loc = 1; /* For ALL GPIO */
- }
- else if(o->hdwtype==0) //dudeusb
- {
- o->hid_gpio_ctl = 0x0c; /* set GPIO 3 & 4 to output mode */
- o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
- o->hid_io_cor = 2; /* VOLD DN is COR */
- o->hid_io_cor_loc = 0; /* VOL DN COR */
- o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
- o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
- o->hid_io_ptt = 4; /* GPIO 3 is PTT */
- o->hid_gpio_loc = 1; /* For ALL GPIO */
- }
- else if(o->hdwtype==3) // custom version
- {
- o->hid_gpio_ctl = 0x0c; /* set GPIO 3 & 4 to output mode */
- o->hid_gpio_ctl_loc = 2; /* For CTL of GPIO */
- o->hid_io_cor = 2; /* VOLD DN is COR */
- o->hid_io_cor_loc = 0; /* VOL DN COR */
- o->hid_io_ctcss = 2; /* GPIO 2 is External CTCSS */
- o->hid_io_ctcss_loc = 1; /* is GPIO 2 */
- o->hid_io_ptt = 4; /* GPIO 3 is PTT */
- o->hid_gpio_loc = 1; /* For ALL GPIO */
- }
-
- return 0;
-}
-
-
-static void *hidthread(void *arg)
-{
- unsigned char buf[4],keyed;
- char lastrx, txtmp;
- struct usb_device *usb_dev;
- struct usb_dev_handle *usb_handle;
- struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
-
- usb_dev = hid_device_init();
- if (usb_dev == NULL) {
- ast_log(LOG_ERROR,"USB HID device not found\n");
- pthread_exit(NULL);
- }
- usb_handle = usb_open(usb_dev);
- if (usb_handle == NULL) {
- ast_log(LOG_ERROR,"Not able to open USB device\n");
- pthread_exit(NULL);
- }
- if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0)
- {
- if (usb_detach_kernel_driver_np(usb_handle,C108_HID_INTERFACE) < 0) {
- ast_log(LOG_ERROR,"Not able to detach the USB device\n");
- pthread_exit(NULL);
- }
- if (usb_claim_interface(usb_handle,C108_HID_INTERFACE) < 0) {
- ast_log(LOG_ERROR,"Not able to claim the USB device\n");
- pthread_exit(NULL);
- }
- }
- memset(buf,0,sizeof(buf));
- buf[2] = o->hid_gpio_ctl;
- buf[1] = 0;
- hid_set_outputs(usb_handle,buf);
- traceusb1(("hidthread: Starting normally!!\n"));
- lastrx = 0;
- while(!o->stophid)
- {
- buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
- hid_get_inputs(usb_handle,buf);
- keyed = !(buf[o->hid_io_cor_loc] & o->hid_io_cor);
- if (keyed != o->rxhidsq)
- {
- if(o->debuglevel)printf("chan_usbradio() hidthread: update rxhidsq = %d\n",keyed);
- o->rxhidsq=keyed;
- }
-
- /* if change in tx stuff */
- txtmp=0;
- if(o->txkeyed || o->txchankey || o->txtestkey || o->pmrChan->txPttOut) txtmp=1;
-
- if (o->lasttx != txtmp)
- {
- o->lasttx = txtmp;
- if(o->debuglevel)printf("hidthread: tx set to %d\n",txtmp);
- buf[o->hid_gpio_loc] = 0;
- if (txtmp) buf[o->hid_gpio_loc] = o->hid_io_ptt;
- buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
- hid_set_outputs(usb_handle,buf);
- }
-
- time(&o->lasthidtime);
- usleep(50000);
- }
- buf[o->hid_gpio_loc] = 0;
- if (o->invertptt) buf[o->hid_gpio_loc] = o->hid_io_ptt;
- buf[o->hid_gpio_ctl_loc] = o->hid_gpio_ctl;
- hid_set_outputs(usb_handle,buf);
- pthread_exit(0);
-}
-
-/*
- * returns a pointer to the descriptor with the given name
- */
-static struct chan_usbradio_pvt *find_desc(char *dev)
-{
- struct chan_usbradio_pvt *o = NULL;
-
- if (!dev)
- ast_log(LOG_WARNING, "null dev\n");
-
- for (o = usbradio_default.next; o && o->name && dev && strcmp(o->name, dev) != 0; o = o->next);
-
- if (!o)
- ast_log(LOG_WARNING, "could not find <%s>\n", dev ? dev : "--no-device--");
-
- return o;
-}
-
-/*
- * split a string in extension-context, returns pointers to malloc'ed
- * strings.
- * If we do not have 'overridecontext' then the last @ is considered as
- * a context separator, and the context is overridden.
- * This is usually not very necessary as you can play with the dialplan,
- * and it is nice not to need it because you have '@' in SIP addresses.
- * Return value is the buffer address.
- */
-#if 0
-static char *ast_ext_ctx(const char *src, char **ext, char **ctx)
-{
- struct chan_usbradio_pvt *o = find_desc(usbradio_active);
-
- if (ext == NULL || ctx == NULL)
- return NULL; /* error */
-
- *ext = *ctx = NULL;
-
- if (src && *src != '\0')
- *ext = ast_strdup(src);
-
- if (*ext == NULL)
- return NULL;
-
- if (!o->overridecontext) {
- /* parse from the right */
- *ctx = strrchr(*ext, '@');
- if (*ctx)
- *(*ctx)++ = '\0';
- }
-
- return *ext;
-}
-#endif
-
-/*
- * Returns the number of blocks used in the audio output channel
- */
-static int used_blocks(struct chan_usbradio_pvt *o)
-{
- struct audio_buf_info info;
-
- if (ioctl(o->sounddev, SNDCTL_DSP_GETOSPACE, &info)) {
- if (!(o->warned & WARN_used_blocks)) {
- ast_log(LOG_WARNING, "Error reading output space\n");
- o->warned |= WARN_used_blocks;
- }
- return 1;
- }
-
- if (o->total_blocks == 0) {
- if (0) /* debugging */
- ast_log(LOG_WARNING, "fragtotal %d size %d avail %d\n", info.fragstotal, info.fragsize, info.fragments);
- o->total_blocks = info.fragments;
- }
-
- return o->total_blocks - info.fragments;
-}
-
-/* Write an exactly FRAME_SIZE sized frame */
-static int soundcard_writeframe(struct chan_usbradio_pvt *o, short *data)
-{
- int res;
-
- if (o->sounddev < 0)
- setformat(o, O_RDWR);
- if (o->sounddev < 0)
- return 0; /* not fatal */
- /*
- * Nothing complex to manage the audio device queue.
- * If the buffer is full just drop the extra, otherwise write.
- * XXX in some cases it might be useful to write anyways after
- * a number of failures, to restart the output chain.
- */
- res = used_blocks(o);
- if (res > o->queuesize) { /* no room to write a block */
- if (o->w_errors++ == 0 && (usbradio_debug & 0x4))
- ast_log(LOG_WARNING, "write: used %d blocks (%d)\n", res, o->w_errors);
- return 0;
- }
- o->w_errors = 0;
-
- return write(o->sounddev, ((void *) data), FRAME_SIZE * 2 * 12);
-}
-
-/*
- * Handler for 'sound writable' events from the sound thread.
- * Builds a frame from the high level description of the sounds,
- * and passes it to the audio device.
- * The actual sound is made of 1 or more sequences of sound samples
- * (s->datalen, repeated to make s->samplen samples) followed by
- * s->silencelen samples of silence. The position in the sequence is stored
- * in o->sampsent, which goes between 0 .. s->samplen+s->silencelen.
- * In case we fail to write a frame, don't update o->sampsent.
- */
-static void send_sound(struct chan_usbradio_pvt *o)
-{
- short myframe[FRAME_SIZE];
- int ofs, l, start;
- int l_sampsent = o->sampsent;
- struct sound *s;
-
- if (o->cursound < 0) /* no sound to send */
- return;
-
- s = &sounds[o->cursound];
-
- for (ofs = 0; ofs < FRAME_SIZE; ofs += l) {
- l = s->samplen - l_sampsent; /* # of available samples */
- if (l > 0) {
- start = l_sampsent % s->datalen; /* source offset */
- if (l > FRAME_SIZE - ofs) /* don't overflow the frame */
- l = FRAME_SIZE - ofs;
- if (l > s->datalen - start) /* don't overflow the source */
- l = s->datalen - start;
- bcopy(s->data + start, myframe + ofs, l * 2);
- if (0)
- ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n", l_sampsent, l, s->samplen, ofs);
- l_sampsent += l;
- } else { /* end of samples, maybe some silence */
- static const short silence[FRAME_SIZE] = { 0, };
-
- l += s->silencelen;
- if (l > 0) {
- if (l > FRAME_SIZE - ofs)
- l = FRAME_SIZE - ofs;
- bcopy(silence, myframe + ofs, l * 2);
- l_sampsent += l;
- } else { /* silence is over, restart sound if loop */
- if (s->repeat == 0) { /* last block */
- o->cursound = -1;
- o->nosound = 0; /* allow audio data */
- if (ofs < FRAME_SIZE) /* pad with silence */
- bcopy(silence, myframe + ofs, (FRAME_SIZE - ofs) * 2);
- }
- l_sampsent = 0;
- }
- }
- }
- l = soundcard_writeframe(o, myframe);
- if (l > 0)
- o->sampsent = l_sampsent; /* update status */
-}
-
-static void *sound_thread(void *arg)
-{
- char ign[4096];
- struct chan_usbradio_pvt *o = (struct chan_usbradio_pvt *) arg;
-
- /*
- * Just in case, kick the driver by trying to read from it.
- * Ignore errors - this read is almost guaranteed to fail.
- */
- read(o->sounddev, ign, sizeof(ign));
- for (;;) {
- fd_set rfds, wfds;
- int maxfd, res;
-
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_SET(o->sndcmd[0], &rfds);
- maxfd = o->sndcmd[0]; /* pipe from the main process */
- if (o->cursound > -1 && o->sounddev < 0)
- setformat(o, O_RDWR); /* need the channel, try to reopen */
- else if (o->cursound == -1 && o->owner == NULL)
- {
- setformat(o, O_CLOSE); /* can close */
- }
- if (o->sounddev > -1) {
- if (!o->owner) { /* no one owns the audio, so we must drain it */
- FD_SET(o->sounddev, &rfds);
- maxfd = MAX(o->sounddev, maxfd);
- }
- if (o->cursound > -1) {
- FD_SET(o->sounddev, &wfds);
- maxfd = MAX(o->sounddev, maxfd);
- }
- }
- /* ast_select emulates linux behaviour in terms of timeout handling */
- res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL);
- if (res < 1) {
- ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
- sleep(1);
- continue;
- }
- if (FD_ISSET(o->sndcmd[0], &rfds)) {
- /* read which sound to play from the pipe */
- int i, what = -1;
-
- read(o->sndcmd[0], &what, sizeof(what));
- for (i = 0; sounds[i].ind != -1; i++) {
- if (sounds[i].ind == what) {
- o->cursound = i;
- o->sampsent = 0;
- o->nosound = 1; /* block audio from pbx */
- break;
- }
- }
- if (sounds[i].ind == -1)
- ast_log(LOG_WARNING, "invalid sound index: %d\n", what);
- }
- if (o->sounddev > -1) {
- if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */
- read(o->sounddev, ign, sizeof(ign));
- if (FD_ISSET(o->sounddev, &wfds))
- send_sound(o);
- }
- }
- return NULL; /* Never reached */
-}
-
-/*
- * reset and close the device if opened,
- * then open and initialize it in the desired mode,
- * trigger reads and writes so we can start using it.
- */
-static int setformat(struct chan_usbradio_pvt *o, int mode)
-{
- int fmt, desired, res, fd;
- char device[100];
-
- if (o->sounddev >= 0) {
- ioctl(o->sounddev, SNDCTL_DSP_RESET, 0);
- close(o->sounddev);
- o->duplex = M_UNSET;
- o->sounddev = -1;
- }
- if (mode == O_CLOSE) /* we are done */
- return 0;
- if (ast_tvdiff_ms(ast_tvnow(), o->lastopen) < 1000)
- return -1; /* don't open too often */
- o->lastopen = ast_tvnow();
- strcpy(device,"/dev/dsp");
- if (o->devicenum)
- sprintf(device,"/dev/dsp%d",o->devicenum);
- fd = o->sounddev = open(device, mode | O_NONBLOCK);
- if (fd < 0) {
- ast_log(LOG_WARNING, "Unable to re-open DSP device %d: %s\n", o->devicenum, strerror(errno));
- return -1;
- }
- if (o->owner)
- o->owner->fds[0] = fd;
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- fmt = AFMT_S16_LE;
-#else
- fmt = AFMT_S16_BE;
-#endif
- res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
- if (res < 0) {
- ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
- return -1;
- }
- switch (mode) {
- case O_RDWR:
- res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
- /* Check to see if duplex set (FreeBSD Bug) */
- res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
- if (res == 0 && (fmt & DSP_CAP_DUPLEX)) {
- if (option_verbose > 1)
- ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n");
- o->duplex = M_FULL;
- };
- break;
- case O_WRONLY:
- o->duplex = M_WRITE;
- break;
- case O_RDONLY:
- o->duplex = M_READ;
- break;
- }
-
- fmt = 1;
- res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
- if (res < 0) {
- ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
- return -1;
- }
- fmt = desired = 48000; /* 8000 Hz desired */
- res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
-
- if (res < 0) {
- ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
- return -1;
- }
- if (fmt != desired) {
- if (!(o->warned & WARN_speed)) {
- ast_log(LOG_WARNING,
- "Requested %d Hz, got %d Hz -- sound may be choppy\n",
- desired, fmt);
- o->warned |= WARN_speed;
- }
- }
- /*
- * on Freebsd, SETFRAGMENT does not work very well on some cards.
- * Default to use 256 bytes, let the user override
- */
- if (o->frags) {
- fmt = o->frags;
- res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
- if (res < 0) {
- if (!(o->warned & WARN_frag)) {
- ast_log(LOG_WARNING,
- "Unable to set fragment size -- sound may be choppy\n");
- o->warned |= WARN_frag;
- }
- }
- }
- /* on some cards, we need SNDCTL_DSP_SETTRIGGER to start outputting */
- res = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
- res = ioctl(fd, SNDCTL_DSP_SETTRIGGER, &res);
- /* it may fail if we are in half duplex, never mind */
- return 0;
-}
-
-/*
- * some of the standard methods supported by channels.
- */
-static int usbradio_digit_begin(struct ast_channel *c, char digit)
-{
- return 0;
-}
-
-static int usbradio_digit_end(struct ast_channel *c, char digit, unsigned int duration)
-{
- /* no better use for received digits than print them */
- ast_verbose(" << Console Received digit %c of duration %u ms >> \n",
- digit, duration);
- return 0;
-}
-
-static int usbradio_text(struct ast_channel *c, const char *text)
-{
- /* print received messages */
- ast_verbose(" << Console Received text %s >> \n", text);
- return 0;
-}
-
-/* Play ringtone 'x' on device 'o' */
-static void ring(struct chan_usbradio_pvt *o, int x)
-{
- write(o->sndcmd[1], &x, sizeof(x));
-}
-
-/*
- * handler for incoming calls. Either autoanswer, or start ringing
- */
-static int usbradio_call(struct ast_channel *c, char *dest, int timeout)
-{
- struct chan_usbradio_pvt *o = c->tech_pvt;
-
- time(&o->lasthidtime);
- ast_pthread_create_background(&o->hidthread, NULL, hidthread, o);
- ast_setstate(c, AST_STATE_UP);
- return 0;
-}
-
-/*
- * remote side answered the phone
- */
-static int usbradio_answer(struct ast_channel *c)
-{
- struct chan_usbradio_pvt *o = c->tech_pvt;
-
- ast_setstate(c, AST_STATE_UP);
- o->cursound = -1;
- o->nosound = 0;
- return 0;
-}
-
-static int usbradio_hangup(struct ast_channel *c)
-{
- struct chan_usbradio_pvt *o = c->tech_pvt;
-
- o->cursound = -1;
- o->nosound = 0;
- c->tech_pvt = NULL;
- o->owner = NULL;
- ast_module_unref(ast_module_info->self);
- if (o->hookstate) {
- if (o->autoanswer || o->autohangup) {
- /* Assume auto-hangup too */
- o->hookstate = 0;
- setformat(o, O_CLOSE);
- } else {
- /* Make congestion noise */
- ring(o, AST_CONTROL_CONGESTION);
- }
- }
- o->stophid = 1;
- pthread_join(o->hidthread,NULL);
- return 0;
-}
-
-
-/* used for data coming from the network */
-static int usbradio_write(struct ast_channel *c, struct ast_frame *f)
-{
- int src,datalen;
- struct chan_usbradio_pvt *o = c->tech_pvt;
-
- traceusb2(("usbradio_write() o->nosound= %i\n",o->nosound)); //sph maw asdf
-
- /* Immediately return if no sound is enabled */
- if (o->nosound)
- return 0;
- /* Stop any currently playing sound */
- o->cursound = -1;
- /*
- * we could receive a block which is not a multiple of our
- * FRAME_SIZE, so buffer it locally and write to the device
- * in FRAME_SIZE chunks.
- * Keep the residue stored for future use.
- */
-
- if(o->txkeyed||o->txtestkey)o->pmrChan->txPttIn=1;
- else o->pmrChan->txPttIn=0;
-
- #if DEBUG_CAPTURES == 1 // to write input data to a file datalen=320
- if (ftxcapraw && o->b.txcapraw)
- {
- i16 i, tbuff[f->datalen];
- for(i=0;i<f->datalen;i+=2)
- {
- tbuff[i]= ((i16*)(f->data))[i/2];
- tbuff[i+1]= o->txkeyed*M_Q13;
- }
- fwrite(tbuff,2,f->datalen,ftxcapraw);
- //fwrite(f->data,1,f->datalen,ftxcapraw);
- }
- #endif
-
- PmrTx(o->pmrChan,(i16*)f->data,(i16*)o->usbradio_write_buf_1);
-
- #if 0 // to write 48KS/s stereo data to a file
- if (!ftxoutraw) ftxoutraw = fopen(TX_CAP_OUT_FILE,"w");
- if (ftxoutraw) fwrite(o->usbradio_write_buf_1,1,f->datalen * 2 * 6,ftxoutraw);
- #endif
-
- #if DEBUG_CAPTURES == 1
- if (o->b.txcap2 && ftxcaptrace) fwrite((o->pmrChan->ptxDebug),1,FRAME_SIZE * 2 * 16,ftxcaptrace);
- #endif
-
- src = 0; /* read position into f->data */
- datalen = f->datalen * 12;
- while (src < datalen) {
- /* Compute spare room in the buffer */
- int l = sizeof(o->usbradio_write_buf) - o->usbradio_write_dst;
-
- if (datalen - src >= l) { /* enough to fill a frame */
- memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
- soundcard_writeframe(o, (short *) o->usbradio_write_buf);
- src += l;
- o->usbradio_write_dst = 0;
- } else { /* copy residue */
- l = datalen - src;
- memcpy(o->usbradio_write_buf + o->usbradio_write_dst, o->usbradio_write_buf_1 + src, l);
- src += l; /* but really, we are done */
- o->usbradio_write_dst += l;
- }
- }
- return 0;
-}
-
-static struct ast_frame *usbradio_read(struct ast_channel *c)
-{
- int res;
- struct chan_usbradio_pvt *o = c->tech_pvt;
- struct ast_frame *f = &o->read_f,*f1;
- struct ast_frame wf = { AST_FRAME_CONTROL };
- time_t now;
-
- traceusb2(("usbradio_read()\n")); //sph maw asdf
-
- if (o->lasthidtime)
- {
- time(&now);
- if ((now - o->lasthidtime) > 3)
- {
- ast_log(LOG_ERROR,"HID process has died or something!!\n");
- return NULL;
- }
- }
- if (o->lastrx && (!o->rxkeyed))
- {
- o->lastrx = 0;
- wf.subclass = AST_CONTROL_RADIO_UNKEY;
- ast_queue_frame(o->owner, &wf);
- } else if ((!o->lastrx) && (o->rxkeyed))
- {
- o->lastrx = 1;
- wf.subclass = AST_CONTROL_RADIO_KEY;
- ast_queue_frame(o->owner, &wf);
- }
- /* XXX can be simplified returning &ast_null_frame */
- /* prepare a NULL frame in case we don't have enough data to return */
- bzero(f, sizeof(struct ast_frame));
- f->frametype = AST_FRAME_NULL;
- f->src = usbradio_tech.type;
-
- res = read(o->sounddev, o->usbradio_read_buf + o->readpos,
- sizeof(o->usbradio_read_buf) - o->readpos);
- if (res < 0) /* audio data not ready, return a NULL frame */
- return f;
-
- o->readpos += res;
- if (o->readpos < sizeof(o->usbradio_read_buf)) /* not enough samples */
- return f;
-
- if (o->mute)
- return f;
-
- #if DEBUG_CAPTURES == 1
- if (o->b.rxcapraw && frxcapraw) fwrite((o->usbradio_read_buf + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2 * 2 * 6,frxcapraw);
- #endif
-
- #if 1
- PmrRx( o->pmrChan,
- (i16 *)(o->usbradio_read_buf + AST_FRIENDLY_OFFSET),
- (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
-
- #else
- static FILE *hInput;
- i16 iBuff[FRAME_SIZE*2*6];
-
- o->pmrChan->b.rxCapture=1;
-
- if(!hInput)
- {
- hInput = fopen("/usr/src/xpmr/testdata/rx_in.pcm","r");
- if(!hInput)
- {
- printf(" Input Data File Not Found.\n");
- return 0;
- }
- }
-
- if(0==fread((void *)iBuff,2,FRAME_SIZE*2*6,hInput))exit;
-
- PmrRx( o->pmrChan,
- (i16 *)iBuff,
- (i16 *)(o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET));
-
- #endif
-
- #if 0
- if (!frxoutraw) frxoutraw = fopen(RX_CAP_OUT_FILE,"w");
- if (frxoutraw) fwrite((o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET),1,FRAME_SIZE * 2,frxoutraw);
- #endif
-
- #if DEBUG_CAPTURES == 1
- if (frxcaptrace && o->b.rxcap2) fwrite((o->pmrChan->prxDebug),1,FRAME_SIZE * 2 * 16,frxcaptrace);
- #endif
-
- if(o->rxcdtype==CD_HID && (o->pmrChan->rxExtCarrierDetect!=o->rxhidsq))
- o->pmrChan->rxExtCarrierDetect=o->rxhidsq;
- if(o->rxcdtype==CD_HID_INVERT && (o->pmrChan->rxExtCarrierDetect==o->rxhidsq))
- o->pmrChan->rxExtCarrierDetect=!o->rxhidsq;
-
- if( (o->rxcdtype==CD_HID && o->rxhidsq) ||
- (o->rxcdtype==CD_HID_INVERT && !o->rxhidsq) ||
- (o->rxcdtype==CD_XPMR_NOISE && o->pmrChan->rxCarrierDetect) ||
- (o->rxcdtype==CD_XPMR_VOX && o->pmrChan->rxCarrierDetect)
- )
- {
- res=1;
- }
- else res=0;
-
- if(res!=o->rxcarrierdetect)
- {
- o->rxcarrierdetect=res;
- if(o->debuglevel)printf("rxcarrierdetect = %i\n",res);
- }
-
- if(o->pmrChan->rxCtcss->decode!=o->rxctcssdecode)
- {
- if(o->debuglevel)printf("rxctcssdecode = %i\n",o->pmrChan->rxCtcss->decode);
- o->rxctcssdecode=o->pmrChan->rxCtcss->decode;
- }
-
- if (
- ( o->rxctcssfreq && (o->rxctcssdecode == o->pmrChan->rxCtcssIndex)) ||
- ( !o->rxctcssfreq && o->rxcarrierdetect)
- )
- {
- o->rxkeyed = 1;
- }
- else o->rxkeyed = 0;
-
-
- o->readpos = AST_FRIENDLY_OFFSET; /* reset read pointer for next frame */
- if (c->_state != AST_STATE_UP) /* drop data if frame is not up */
- return f;
- /* ok we can build and deliver the frame to the caller */
- f->frametype = AST_FRAME_VOICE;
- f->subclass = AST_FORMAT_SLINEAR;
- f->samples = FRAME_SIZE;
- f->datalen = FRAME_SIZE * 2;
- f->data = o->usbradio_read_buf_8k + AST_FRIENDLY_OFFSET;
- if (o->boost != BOOST_SCALE) { /* scale and clip values */
- int i, x;
- int16_t *p = (int16_t *) f->data;
- for (i = 0; i < f->samples; i++) {
- x = (p[i] * o->boost) / BOOST_SCALE;
- if (x > 32767)
- x = 32767;
- else if (x < -32768)
- x = -32768;
- p[i] = x;
- }
- }
-
- f->offset = AST_FRIENDLY_OFFSET;
- if (o->dsp)
- {
- f1 = ast_dsp_process(c,o->dsp,f);
- if ((f1->frametype == AST_FRAME_DTMF_END) ||
- (f1->frametype == AST_FRAME_DTMF_BEGIN))
- {
- if ((f1->subclass == 'm') || (f1->subclass == 'u'))
- f1->frametype = AST_FRAME_DTMF_BEGIN;
- if (f1->frametype == AST_FRAME_DTMF_END)
- ast_log(LOG_NOTICE,"Got DTMF char %c\n",f1->subclass);
- return(f1);
- }
- }
- return f;
-}
-
-static int usbradio_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
-{
- struct chan_usbradio_pvt *o = newchan->tech_pvt;
- ast_log(LOG_WARNING,"usbradio_fixup()\n");
- o->owner = newchan;
- return 0;
-}
-
-static int usbradio_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen)
-{
- struct chan_usbradio_pvt *o = c->tech_pvt;
- int res = -1;
-
- switch (cond) {
- case AST_CONTROL_BUSY:
- case AST_CONTROL_CONGESTION:
- case AST_CONTROL_RINGING:
- res = cond;
- break;
-
- case -1:
- o->cursound = -1;
- o->nosound = 0; /* when cursound is -1 nosound must be 0 */
- return 0;
-
- case AST_CONTROL_VIDUPDATE:
- res = -1;
- break;
- case AST_CONTROL_HOLD:
- ast_verbose(" << Console Has Been Placed on Hold >> \n");
- ast_moh_start(c, data, o->mohinterpret);
- break;
- case AST_CONTROL_UNHOLD:
- ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
- ast_moh_stop(c);
- break;
- case AST_CONTROL_PROCEEDING:
- ast_verbose(" << Call Proceeding... >> \n");
- ast_moh_stop(c);
- break;
- case AST_CONTROL_PROGRESS:
- ast_verbose(" << Call Progress... >> \n");
- ast_moh_stop(c);
- break;
- case AST_CONTROL_RADIO_KEY:
- o->txkeyed = 1;
- if(o->debuglevel)ast_verbose(" << Radio Transmit On. >> \n");
- break;
- case AST_CONTROL_RADIO_UNKEY:
- o->txkeyed = 0;
- if(o->debuglevel)ast_verbose(" << Radio Transmit Off. >> \n");
- break;
- default:
- ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, c->name);
- return -1;
- }
-
- if (res > -1)
- ring(o, res);
-
- return 0;
-}
-
-/*
- * allocate a new channel.
- */
-static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext, char *ctx, int state)
-{
- struct ast_channel *c;
- char device[100];
-
- strcpy(device,"dsp");
- if (o->devicenum) sprintf(device,"dsp%d",o->devicenum);
- c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, 0, "usbRadio/%s", device);
- if (c == NULL)
- return NULL;
- c->tech = &usbradio_tech;
- if (o->sounddev < 0)
- setformat(o, O_RDWR);
- c->fds[0] = o->sounddev; /* -1 if device closed, override later */
- c->nativeformats = AST_FORMAT_SLINEAR;
- c->readformat = AST_FORMAT_SLINEAR;
- c->writeformat = AST_FORMAT_SLINEAR;
- c->tech_pvt = o;
-
- if (!ast_strlen_zero(o->language))
- ast_string_field_set(c, language, o->language);
- /* Don't use ast_set_callerid() here because it will
- * generate a needless NewCallerID event */
- c->cid.cid_num = ast_strdup(o->cid_num);
- c->cid.cid_ani = ast_strdup(o->cid_num);
- c->cid.cid_name = ast_strdup(o->cid_name);
- if (!ast_strlen_zero(ext))
- c->cid.cid_dnid = ast_strdup(ext);
-
- o->owner = c;
- ast_module_ref(ast_module_info->self);
- ast_jb_configure(c, &global_jbconf);
- if (state != AST_STATE_DOWN) {
- if (ast_pbx_start(c)) {
- ast_log(LOG_WARNING, "Unable to start PBX on %s\n", c->name);
- ast_hangup(c);
- o->owner = c = NULL;
- /* XXX what about the channel itself ? */
- /* XXX what about usecnt ? */
- }
- }
-
- return c;
-}
-
-static struct ast_channel *usbradio_request(const char *type, int format, void *data, int *cause)
-{
- struct ast_channel *c;
- struct chan_usbradio_pvt *o = find_desc(data);
-
- if (0)
- {
- ast_log(LOG_WARNING, "usbradio_request ty <%s> data 0x%p <%s>\n", type, data, (char *) data);
- }
- if (o == NULL) {
- ast_log(LOG_NOTICE, "Device %s not found\n", (char *) data);
- /* XXX we could default to 'dsp' perhaps ? */
- return NULL;
- }
- if ((format & AST_FORMAT_SLINEAR) == 0) {
- ast_log(LOG_NOTICE, "Format 0x%x unsupported\n", format);
- return NULL;
- }
- if (o->owner) {
- ast_log(LOG_NOTICE, "Already have a call (chan %p) on the usb channel\n", o->owner);
- *cause = AST_CAUSE_BUSY;
- return NULL;
- }
- c = usbradio_new(o, NULL, NULL, AST_STATE_DOWN);
- if (c == NULL) {
- ast_log(LOG_WARNING, "Unable to create new usb channel\n");
- return NULL;
- }
- return c;
-}
-
-static int console_key(int fd, int argc, char *argv[])
-{
- struct chan_usbradio_pvt *o = find_desc(usbradio_active);
-
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- o->txtestkey = 1;
- return RESULT_SUCCESS;
-}
-
-static int console_unkey(int fd, int argc, char *argv[])
-{
- struct chan_usbradio_pvt *o = find_desc(usbradio_active);
-
- if (argc != 2)
- return RESULT_SHOWUSAGE;
- o->txtestkey = 0;
-
- return RESULT_SUCCESS;
-}
-
-static int radio_tune(int fd, int argc, char *argv[])
-{
- struct chan_usbradio_pvt *o = find_desc(usbradio_active);
- int i=0;
-
- if ((argc < 2) || (argc > 4))
- return RESULT_SHOWUSAGE;
-
- if (argc == 2) /* just show stuff */
- {
- ast_cli(fd,"Output A is currently set to ");
- if(o->txmixa==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
- else if (o->txmixa==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
- else if (o->txmixa==TX_OUT_LSD)ast_cli(fd,"tone.\n");
- else if (o->txmixa==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n");
- else ast_cli(fd,"off.\n");
-
- ast_cli(fd,"Output B is currently set to ");
- if(o->txmixb==TX_OUT_COMPOSITE)ast_cli(fd,"composite.\n");
- else if (o->txmixb==TX_OUT_VOICE)ast_cli(fd,"voice.\n");
- else if (o->txmixb==TX_OUT_LSD)ast_cli(fd,"tone.\n");
- else if (o->txmixb==TX_OUT_AUX)ast_cli(fd,"auxvoice.\n");
- else ast_cli(fd,"off.\n");
-
- ast_cli(fd,"Tx Voice Level currently set to %d\n",o->txmixaset);
- ast_cli(fd,"Tx Tone Level currently set to %d\n",o->txctcssadj);
- ast_cli(fd,"Rx Squelch currently set to %d\n",o->rxsquelchadj);
- return RESULT_SHOWUSAGE;
- }
-
- if (!strcasecmp(argv[2],"rxnoise")) tune_rxinput(o);
- else if (!strcasecmp(argv[2],"rxvoice")) tune_rxvoice(o);
- else if (!strcasecmp(argv[2],"rxtone")) tune_rxctcss(o);
- else if (!strcasecmp(argv[2],"rxsquelch"))
- {
- if (argc == 3)
- {
- ast_cli(fd,"Current Signal Strength is %d\n",((32767-o->pmrChan->rxRssi)*1000/32767));
- ast_cli(fd,"Current Squelch setting is %d\n",o->rxsquelchadj);
- //ast_cli(fd,"Current Raw RSSI is %d\n",o->pmrChan->rxRssi);
- //ast_cli(fd,"Current (real) Squelch setting is %d\n",*(o->pmrChan->prxSquelchAdjust));
- } else {
- i = atoi(argv[3]);
- if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
- ast_cli(fd,"Changed Squelch setting to %d\n",i);
- o->rxsquelchadj = i;
- *(o->pmrChan->prxSquelchAdjust)= ((999 - i) * 32767) / 1000;
- }
- }
- else if (!strcasecmp(argv[2],"txvoice")) {
- i = 0;
-
- if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
- (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
- )
- {
- ast_log(LOG_ERROR,"No txvoice output configured.\n");
- }
- else if (argc == 3)
- {
- if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
- ast_cli(fd,"Current txvoice setting on Channel A is %d\n",o->txmixaset);
- else
- ast_cli(fd,"Current txvoice setting on Channel B is %d\n",o->txmixbset);
- }
- else
- {
- i = atoi(argv[3]);
- if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
-
- if((o->txmixa==TX_OUT_VOICE)||(o->txmixa==TX_OUT_COMPOSITE))
- {
- o->txmixaset=i;
- ast_cli(fd,"Changed txvoice setting on Channel A to %d\n",o->txmixaset);
- }
- else
- {
- o->txmixbset=i;
- ast_cli(fd,"Changed txvoice setting on Channel B to %d\n",o->txmixbset);
- }
- mixer_write(o);
- mult_set(o);
- ast_cli(fd,"Changed Tx Voice Output setting to %d\n",i);
- }
- tune_txoutput(o,i);
- }
- else if (!strcasecmp(argv[2],"auxvoice")) {
- i = 0;
- if( (o->txmixa!=TX_OUT_AUX) && (o->txmixb!=TX_OUT_AUX))
- {
- ast_log(LOG_WARNING,"No auxvoice output configured.\n");
- }
- else if (argc == 3)
- {
- if(o->txmixa==TX_OUT_AUX)
- ast_cli(fd,"Current auxvoice setting on Channel A is %d\n",o->txmixaset);
- else
- ast_cli(fd,"Current auxvoice setting on Channel B is %d\n",o->txmixbset);
- }
- else
- {
- i = atoi(argv[3]);
- if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
- if(o->txmixa==TX_OUT_AUX)
- {
- o->txmixbset=i;
- ast_cli(fd,"Changed auxvoice setting on Channel A to %d\n",o->txmixaset);
- }
- else
- {
- o->txmixbset=i;
- ast_cli(fd,"Changed auxvoice setting on Channel B to %d\n",o->txmixbset);
- }
- mixer_write(o);
- mult_set(o);
- }
- //tune_auxoutput(o,i);
- }
- else if (!strcasecmp(argv[2],"txtone"))
- {
- if (argc == 3)
- ast_cli(fd,"Current Tx CTCSS modulation setting = %d\n",o->txctcssadj);
- else
- {
- i = atoi(argv[3]);
- if ((i < 0) || (i > 999)) return RESULT_SHOWUSAGE;
- o->txctcssadj = i;
- set_txctcss_level(o);
- ast_cli(fd,"Changed Tx CTCSS modulation setting to %i\n",i);
- }
- o->txtestkey=1;
- usleep(5000000);
- o->txtestkey=0;
- }
- else if (!strcasecmp(argv[2],"dump")) pmrdump(o);
- else if (!strcasecmp(argv[2],"nocap"))
- {
- ast_cli(fd,"File capture (trace) was rx=%d tx=%d and now off.\n",o->b.rxcap2,o->b.txcap2);
- ast_cli(fd,"File capture (raw) was rx=%d tx=%d and now off.\n",o->b.rxcapraw,o->b.txcapraw);
- o->b.rxcapraw=o->b.txcapraw=o->b.rxcap2=o->b.txcap2=o->pmrChan->b.rxCapture=o->pmrChan->b.txCapture=0;
- if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; }
- if (frxcaptrace) { fclose(frxcaptrace); frxcaptrace = NULL; }
- if (frxoutraw) { fclose(frxoutraw); frxoutraw = NULL; }
- if (ftxcapraw) { fclose(ftxcapraw); ftxcapraw = NULL; }
- if (ftxcaptrace) { fclose(ftxcaptrace); ftxcaptrace = NULL; }
- if (ftxoutraw) { fclose(ftxoutraw); ftxoutraw = NULL; }
- }
- else if (!strcasecmp(argv[2],"rxtracecap"))
- {
- if (!frxcaptrace) frxcaptrace= fopen(RX_CAP_TRACE_FILE,"w");
- ast_cli(fd,"Trace rx on.\n");
- o->b.rxcap2=o->pmrChan->b.rxCapture=1;
- }
- else if (!strcasecmp(argv[2],"txtracecap"))
- {
- if (!ftxcaptrace) ftxcaptrace= fopen(TX_CAP_TRACE_FILE,"w");
- ast_cli(fd,"Trace tx on.\n");
- o->b.txcap2=o->pmrChan->b.txCapture=1;
- }
- else if (!strcasecmp(argv[2],"rxcap"))
- {
- if (!frxcapraw) frxcapraw = fopen(RX_CAP_RAW_FILE,"w");
- ast_cli(fd,"cap rx raw on.\n");
- o->b.rxcapraw=1;
- }
- else if (!strcasecmp(argv[2],"txcap"))
- {
- if (!ftxcapraw) ftxcapraw = fopen(TX_CAP_RAW_FILE,"w");
- ast_cli(fd,"cap tx raw on.\n");
- o->b.txcapraw=1;
- }
- else if (!strcasecmp(argv[2],"save"))
- {
- tune_write(o);
- ast_cli(fd,"Saved radio tuning settings to usbradio_tune.conf\n");
- }
- else return RESULT_SHOWUSAGE;
- return RESULT_SUCCESS;
-}
-
-/*
- set transmit ctcss modulation level
- adjust mixer output or internal gain depending on output type
- setting range is 0.0 to 0.9
-*/
-static int set_txctcss_level(struct chan_usbradio_pvt *o)
-{
- if (o->txmixa == TX_OUT_LSD)
- {
- o->txmixaset=(151*o->txctcssadj) / 1000;
- mixer_write(o);
- mult_set(o);
- }
- else if (o->txmixb == TX_OUT_LSD)
- {
- o->txmixbset=(151*o->txctcssadj) / 1000;
- mixer_write(o);
- mult_set(o);
- }
- else
- {
- *o->pmrChan->ptxCtcssAdjust=(o->txctcssadj * M_Q8) / 1000;
- }
- return 0;
-}
-/*
- CLI debugging on and off
-*/
-static int radio_set_debug(int fd, int argc, char *argv[])
-{
- struct chan_usbradio_pvt *o = find_desc(usbradio_active);
-
- o->debuglevel=1;
- ast_cli(fd,"usbradio debug on.\n");
-
- return RESULT_SUCCESS;
-}
-
-static int radio_set_debug_off(int fd, int argc, char *argv[])
-{
- struct chan_usbradio_pvt *o = find_desc(usbradio_active);
-
- o->debuglevel=0;
- ast_cli(fd,"usbradio debug off.\n");
- return RESULT_SUCCESS;
-}
-
-static char key_usage[] =
- "Usage: radio key\n"
- " Simulates COR active.\n";
-
-static char unkey_usage[] =
- "Usage: radio unkey\n"
- " Simulates COR un-active.\n";
-
-/*
-radio tune 6 3000 measured tx value
-*/
-static char radio_tune_usage[] =
- "Usage: radio tune <function>\n"
- " rxnoise\n"
- " rxvoice\n"
- " rxtone\n"
- " rxsquelch [newsetting]\n"
- " txvoice [newsetting]\n"
- " txtone [newsetting]\n"
- " auxvoice [newsetting]\n"
- " save (settings to tuning file)\n"
- "\n All [newsetting]'s are values 0-999\n\n";
-
-static struct ast_cli_entry cli_usbradio[] = {
- { { "radio", "key", NULL },
- console_key, "Simulate Rx Signal Present",
- key_usage, NULL, NULL},
-
- { { "radio", "unkey", NULL },
- console_unkey, "Simulate Rx Signal Lusb",
- unkey_usage, NULL, NULL },
-
- { { "radio", "tune", NULL },
- radio_tune, "Radio Tune",
- radio_tune_usage, NULL, NULL },
-
- { { "radio", "set", "debug", NULL },
- radio_set_debug, "Radio Debug",
- radio_tune_usage, NULL, NULL },
-
- { { "radio", "set", "debug", "off", NULL },
- radio_set_debug_off, "Radio Debug",
- radio_tune_usage, NULL, NULL },
-};
-
-/*
- * store the callerid components
- */
-#if 0
-static void store_callerid(struct chan_usbradio_pvt *o, char *s)
-{
- ast_callerid_split(s, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num));
-}
-#endif
-
-static void store_rxdemod(struct chan_usbradio_pvt *o, char *s)
-{
- if (!strcasecmp(s,"no")){
- o->rxdemod = RX_AUDIO_NONE;
- }
- else if (!strcasecmp(s,"speaker")){
- o->rxdemod = RX_AUDIO_SPEAKER;
- }
- else if (!strcasecmp(s,"flat")){
- o->rxdemod = RX_AUDIO_FLAT;
- }
- else {
- ast_log(LOG_WARNING,"Unrecognized rxdemod parameter: %s\n",s);
- }
-
- //ast_log(LOG_WARNING, "set rxdemod = %s\n", s);
-}
-
-
-static void store_txmixa(struct chan_usbradio_pvt *o, char *s)
-{
- if (!strcasecmp(s,"no")){
- o->txmixa = TX_OUT_OFF;
- }
- else if (!strcasecmp(s,"voice")){
- o->txmixa = TX_OUT_VOICE;
- }
- else if (!strcasecmp(s,"tone")){
- o->txmixa = TX_OUT_LSD;
- }
- else if (!strcasecmp(s,"composite")){
- o->txmixa = TX_OUT_COMPOSITE;
- }
- else if (!strcasecmp(s,"auxvoice")){
- o->txmixb = TX_OUT_AUX;
- }
- else {
- ast_log(LOG_WARNING,"Unrecognized txmixa parameter: %s\n",s);
- }
-
- //ast_log(LOG_WARNING, "set txmixa = %s\n", s);
-}
-
-static void store_txmixb(struct chan_usbradio_pvt *o, char *s)
-{
- if (!strcasecmp(s,"no")){
- o->txmixb = TX_OUT_OFF;
- }
- else if (!strcasecmp(s,"voice")){
- o->txmixb = TX_OUT_VOICE;
- }
- else if (!strcasecmp(s,"tone")){
- o->txmixb = TX_OUT_LSD;
- }
- else if (!strcasecmp(s,"composite")){
- o->txmixb = TX_OUT_COMPOSITE;
- }
- else if (!strcasecmp(s,"auxvoice")){
- o->txmixb = TX_OUT_AUX;
- }
- else {
- ast_log(LOG_WARNING,"Unrecognized txmixb parameter: %s\n",s);
- }
-
- //ast_log(LOG_WARNING, "set txmixb = %s\n", s);
-}
-/*
-*/
-static void store_rxcdtype(struct chan_usbradio_pvt *o, char *s)
-{
- if (!strcasecmp(s,"no")){
- o->rxcdtype = CD_IGNORE;
- }
- else if (!strcasecmp(s,"usb")){
- o->rxcdtype = CD_HID;
- }
- else if (!strcasecmp(s,"dsp")){
- o->rxcdtype = CD_XPMR_NOISE;
- }
- else if (!strcasecmp(s,"vox")){
- o->rxcdtype = CD_XPMR_VOX;
- }
- else if (!strcasecmp(s,"usbinvert")){
- o->rxcdtype = CD_HID_INVERT;
- }
- else {
- ast_log(LOG_WARNING,"Unrecognized rxcdtype parameter: %s\n",s);
- }
-
- //ast_log(LOG_WARNING, "set rxcdtype = %s\n", s);
-}
-/*
-*/
-static void store_rxsdtype(struct chan_usbradio_pvt *o, char *s)
-{
- if (!strcasecmp(s,"no") || !strcasecmp(s,"SD_IGNORE")){
- o->rxsdtype = SD_IGNORE;
- }
- else if (!strcasecmp(s,"usb") || !strcasecmp(s,"SD_HID")){
- o->rxsdtype = SD_HID;
- }
- else if (!strcasecmp(s,"usbinvert") || !strcasecmp(s,"SD_HID_INVERT")){
- o->rxsdtype = SD_HID_INVERT;
- }
- else if (!strcasecmp(s,"software") || !strcasecmp(s,"SD_XPMR")){
- o->rxsdtype = SD_XPMR;
- }
- else {
- ast_log(LOG_WARNING,"Unrecognized rxsdtype parameter: %s\n",s);
- }
-
- //ast_log(LOG_WARNING, "set rxsdtype = %s\n", s);
-}
-/*
-*/
-static void store_rxgain(struct chan_usbradio_pvt *o, char *s)
-{
- float f;
- sscanf(s,"%f",&f);
- o->rxgain = f;
- //ast_log(LOG_WARNING, "set rxgain = %f\n", f);
-}
-/*
-*/
-static void store_rxvoiceadj(struct chan_usbradio_pvt *o, char *s)
-{
- float f;
- sscanf(s,"%f",&f);
- o->rxvoiceadj = f;
- //ast_log(LOG_WARNING, "set rxvoiceadj = %f\n", f);
-}
-/*
-*/
-static void store_rxctcssadj(struct chan_usbradio_pvt *o, char *s)
-{
- float f;
- sscanf(s,"%f",&f);
- o->rxctcssadj = f;
- //ast_log(LOG_WARNING, "set rxctcssadj = %f\n", f);
-}
-/*
-*/
-static void store_txtoctype(struct chan_usbradio_pvt *o, char *s)
-{
- if (!strcasecmp(s,"no") || !strcasecmp(s,"TOC_NONE")){
- o->txtoctype = TOC_NONE;
- }
- else if (!strcasecmp(s,"phase") || !strcasecmp(s,"TOC_PHASE")){
- o->txtoctype = TOC_PHASE;
- }
- else if (!strcasecmp(s,"notone") || !strcasecmp(s,"TOC_NOTONE")){
- o->txtoctype = TOC_NOTONE;
- }
- else {
- ast_log(LOG_WARNING,"Unrecognized txtoctype parameter: %s\n",s);
- }
-
- //ast_log(LOG_WARNING, "set txtoctype = %s\n", s);
-}
-/*
-*/
-static void store_rxctcssfreq(struct chan_usbradio_pvt *o, char *s)
-{
- float f;
- sscanf(s,"%f",&f);
- o->rxctcssfreq = f;
- //ast_log(LOG_WARNING, "set rxctcss = %f\n", f);
-}
-/*
-*/
-static void store_txctcssfreq(struct chan_usbradio_pvt *o, char *s)
-{
- float f;
- sscanf(s,"%f",&f);
- o->txctcssfreq = f;
- //ast_log(LOG_WARNING, "set txctcss = %f\n", f);
-}
-/*
-*/
-static void tune_txoutput(struct chan_usbradio_pvt *o, int value)
-{
- o->txtestkey=1;
- o->pmrChan->txPttIn=1;
-
- // generate 1KHz tone at 7200 peak
- //o->pmrChan->spsSigGen1->freq=10000;
- //o->pmrChan->spsSigGen1->outputGain=(float)(0.22*M_Q8);
- //o->pmrChan->b.startSpecialTone=1;
-
- TxTestTone(o->pmrChan, 1);
-
- usleep(5000000);
- //o->pmrChan->b.stopSpecialTone=1;
- usleep(100000);
-
- TxTestTone(o->pmrChan, 0);
-
- o->pmrChan->txPttIn=0;
- o->txtestkey=0;
-}
-/*
-*/
-static void tune_rxinput(struct chan_usbradio_pvt *o)
-{
- const int target=23000;
- const int tolerance=2000;
- const int settingmin=1;
- const int settingstart=2;
- const int maxtries=12;
-
- float settingmax;
-
- int setting=0, tries=0, tmpdiscfactor, meas;
- int tunetype=0;
-
- settingmax = o->micmax;
-
- if(o->pmrChan->rxDemod)tunetype=1;
-
- setting = settingstart;
-
- while(tries<maxtries)
- {
- setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,setting,0);
- setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0);
- usleep(100000);
- if(o->rxcdtype==CD_XPMR_VOX || o->rxdemod==RX_AUDIO_SPEAKER)
- {
- // printf("Measure Direct Input\n");
- o->pmrChan->spsMeasure->source = o->pmrChan->spsRx->source;
- o->pmrChan->spsMeasure->discfactor=1000;
- o->pmrChan->spsMeasure->enabled=1;
- o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
- usleep(400000);
- meas=o->pmrChan->spsMeasure->apeak;
- o->pmrChan->spsMeasure->enabled=0;
- }
- else
- {
- // printf("Measure HF Noise\n");
- tmpdiscfactor=o->pmrChan->spsRx->discfactor;
- o->pmrChan->spsRx->discfactor=(i16)1000;
- o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0;
- o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0;
- usleep(200000);
- meas=o->pmrChan->rxRssi;
- o->pmrChan->spsRx->discfactor=tmpdiscfactor;
- o->pmrChan->spsRx->discounteru=o->pmrChan->spsRx->discounterl=0;
- o->pmrChan->spsRx->amax=o->pmrChan->spsRx->amin=0;
- }
- if(!meas)meas++;
- printf("tries=%d, setting=%d, meas=%i\n",tries,setting,meas);
-
- if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
- setting=setting*target/meas;
- }
- else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
- {
- break;
- }
-
- if(setting<settingmin)setting=settingmin;
- else if(setting>settingmax)setting=settingmax;
-
- tries++;
- }
- printf("DONE tries=%d, setting=%d, meas=%i\n",tries,
- (setting * 1000) / o->micmax,meas);
- if( meas<(target-tolerance) || meas>(target+tolerance) ){
- printf("ERROR: RX INPUT ADJUST FAILED.\n");
- }else{
- printf("INFO: RX INPUT ADJUST SUCCESS.\n");
- o->rxmixerset=(setting * 1000) / o->micmax;
- }
-}
-/*
-*/
-static void tune_rxvoice(struct chan_usbradio_pvt *o)
-{
- const int target=7200; // peak
- const int tolerance=360; // peak to peak
- const float settingmin=0.1;
- const float settingmax=4;
- const float settingstart=1;
- const int maxtries=12;
-
- float setting;
-
- int tries=0, meas;
-
- printf("INFO: RX VOICE ADJUST START.\n");
- printf("target=%i tolerance=%i \n",target,tolerance);
-
- if(!o->pmrChan->spsMeasure)
- printf("ERROR: NO MEASURE BLOCK.\n");
-
- if(!o->pmrChan->spsMeasure->source || !o->pmrChan->prxVoiceAdjust )
- printf("ERROR: NO SOURCE OR MEASURE SETTING.\n");
-
- o->pmrChan->spsMeasure->source=o->pmrChan->spsRxOut->sink;
- o->pmrChan->spsMeasure->enabled=1;
- o->pmrChan->spsMeasure->discfactor=1000;
-
- setting=settingstart;
-
- // printf("ERROR: NO MEASURE BLOCK.\n");
-
- while(tries<maxtries)
- {
- *(o->pmrChan->prxVoiceAdjust)=setting*M_Q8;
- usleep(10000);
- o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
- usleep(1000000);
- meas = o->pmrChan->spsMeasure->apeak;
- printf("tries=%d, setting=%f, meas=%i\n",tries,setting,meas);
-
- if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
- setting=setting*target/meas;
- }
- else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
- {
- break;
- }
- if(setting<settingmin)setting=settingmin;
- else if(setting>settingmax)setting=settingmax;
-
- tries++;
- }
-
- o->pmrChan->spsMeasure->enabled=0;
-
- printf("DONE tries=%d, setting=%f, meas=%f\n",tries,setting,(float)meas);
- if( meas<(target-tolerance) || meas>(target+tolerance) ){
- printf("ERROR: RX VOICE GAIN ADJUST FAILED.\n");
- }else{
- printf("INFO: RX VOICE GAIN ADJUST SUCCESS.\n");
- o->rxvoiceadj=setting;
- }
-}
-/*
-*/
-static void tune_rxctcss(struct chan_usbradio_pvt *o)
-{
- const int target=4096;
- const int tolerance=100;
- const float settingmin=0.1;
- const float settingmax=4;
- const float settingstart=1;
- const int maxtries=12;
-
- float setting;
- int tries=0, meas;
-
- printf("INFO: RX CTCSS ADJUST START.\n");
- printf("target=%i tolerance=%i \n",target,tolerance);
-
- o->pmrChan->spsMeasure->source=o->pmrChan->prxCtcssMeasure;
- o->pmrChan->spsMeasure->discfactor=400;
- o->pmrChan->spsMeasure->enabled=1;
-
- setting=settingstart;
-
- while(tries<maxtries)
- {
- *(o->pmrChan->prxCtcssAdjust)=setting*M_Q8;
- usleep(10000);
- o->pmrChan->spsMeasure->amax = o->pmrChan->spsMeasure->amin = 0;
- usleep(500000);
- meas = o->pmrChan->spsMeasure->apeak;
- printf("tries=%d, setting=%f, meas=%i\n",tries,setting,meas);
-
- if( meas<(target-tolerance) || meas>(target+tolerance) || tries<3){
- setting=setting*target/meas;
- }
- else if(tries>4 && meas>(target-tolerance) && meas<(target+tolerance) )
- {
- break;
- }
- if(setting<settingmin)setting=settingmin;
- else if(setting>settingmax)setting=settingmax;
-
- tries++;
- }
- o->pmrChan->spsMeasure->enabled=0;
- printf("DONE tries=%d, setting=%f, meas=%f\n",tries,setting,(float)meas);
- if( meas<(target-tolerance) || meas>(target+tolerance) ){
- printf("ERROR: RX CTCSS GAIN ADJUST FAILED.\n");
- }else{
- printf("INFO: RX CTCSS GAIN ADJUST SUCCESS.\n");
- o->rxctcssadj=setting;
- }
-}
-/*
- this file then is included in chan_usbradio.conf
- #include /etc/asterisk/usbradio_tune.conf
-*/
-static void tune_write(struct chan_usbradio_pvt *o)
-{
- FILE *fp;
-
- fp=fopen("/etc/asterisk/usbradio_tune.conf","w");
-
- if (!strcmp(o->name,"dsp"))
- fprintf(fp,"[general]\n");
- else
- fprintf(fp,"[%s]\n",o->name);
-
- fprintf(fp,"; name=%s\n",o->name);
- fprintf(fp,"; devicenum=%i\n",o->devicenum);
-
- fprintf(fp,"rxmixerset=%i\n",o->rxmixerset);
- fprintf(fp,"rxboostset=%i\n",o->rxboostset);
- fprintf(fp,"txmixaset=%i\n",o->txmixaset);
- fprintf(fp,"txmixbset=%i\n",o->txmixbset);
-
- fprintf(fp,"rxvoiceadj=%f\n",o->rxvoiceadj);
- fprintf(fp,"rxctcssadj=%f\n",o->rxctcssadj);
- fprintf(fp,"txctcssadj=%i\n",o->txctcssadj);
-
- fprintf(fp,"rxsquelchadj=%i\n",o->rxsquelchadj);
- fclose(fp);
-}
-//
-static void mixer_write(struct chan_usbradio_pvt *o)
-{
- setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_SW,0,0);
- setamixer(o->devicenum,MIXER_PARAM_MIC_PLAYBACK_VOL,0,0);
- setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_SW,1,0);
- setamixer(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL,
- o->txmixaset * o->spkrmax / 1000,
- o->txmixbset * o->spkrmax / 1000);
- setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL,
- o->rxmixerset * o->micmax / 1000,0);
- setamixer(o->devicenum,MIXER_PARAM_MIC_BOOST,o->rxboostset,0);
- setamixer(o->devicenum,MIXER_PARAM_MIC_CAPTURE_SW,1,0);
-}
-/*
- adjust dsp multiplier to add resolution to tx level adjustment
-*/
-static void mult_set(struct chan_usbradio_pvt *o)
-{
-
- if(o->pmrChan->spsTxOutA) {
- o->pmrChan->spsTxOutA->outputGain =
- mult_calc((o->txmixaset * 152) / 1000);
- }
- if(o->pmrChan->spsTxOutB){
- o->pmrChan->spsTxOutB->outputGain =
- mult_calc((o->txmixbset * 152) / 1000);
- }
-}
-//
-// input 0 - 151 outputs are pot and multiplier
-//
-static int mult_calc(int value)
-{
- const int multx=M_Q8;
- int pot,mult;
-
- pot=((int)(value/4)*4)+2;
- mult = multx-( ( multx * (3-(value%4)) ) / (pot+2) );
- return(mult);
-}
-
-#define pd(x) {printf(#x" = %d\n",x);}
-#define pp(x) {printf(#x" = %p\n",x);}
-#define ps(x) {printf(#x" = %s\n",x);}
-#define pf(x) {printf(#x" = %f\n",x);}
-/*
-*/
-static void pmrdump(struct chan_usbradio_pvt *o)
-{
- t_pmr_chan *p;
-
- p=o->pmrChan;
-
- printf("\nodump()\n");
-
- pd(o->devicenum);
-
- pd(o->rxdemod);
- pd(o->rxcdtype);
- pd(o->rxsdtype);
- pd(o->txtoctype);
-
- pd(o->rxmixerset);
- pf(o->rxvoiceadj);
- pf(o->rxctcssadj);
- pd(o->rxsquelchadj);
-
- pd(o->txprelim);
- pd(o->txmixa);
- pd(o->txmixb);
-
- pd(o->txmixaset);
- pd(o->txmixbset);
-
- printf("\npmrdump()\n");
-
- printf("prxSquelchAdjust=%i\n",*(o->pmrChan->prxSquelchAdjust));
-
- pd(p->rxCarrierPoint);
- pd(p->rxCarrierHyst);
-
- pd(p->rxCtcss->relax);
- pf(p->rxCtcssFreq);
- pd(p->rxCtcssIndex);
- pf(p->txCtcssFreq);
-
- pd(p->txMixA);
- pd(p->txMixB);
-
- pd(p->rxDeEmpEnable);
- pd(p->rxCenterSlicerEnable);
- pd(p->rxCtcssDecodeEnable);
- pd(p->rxDcsDecodeEnable);
-
- pd(p->txHpfEnable);
- pd(p->txLimiterEnable);
- pd(p->txPreEmpEnable);
- pd(p->txLpfEnable);
-
- if(p->spsTxOutA)pd(p->spsTxOutA->outputGain);
- if(p->spsTxOutB)pd(p->spsTxOutB->outputGain);
-
- return;
-}
-
-
-/*
- * grab fields from the config file, init the descriptor and open the device.
- */
-static struct chan_usbradio_pvt *store_config(struct ast_config *cfg, char *ctg)
-{
- struct ast_variable *v;
- struct chan_usbradio_pvt *o;
- struct ast_config *cfg1;
-
- if (ctg == NULL) {
- traceusb1((" store_config() ctg == NULL\n"));
- o = &usbradio_default;
- ctg = "general";
- } else {
- if (!(o = ast_calloc(1, sizeof(*o)))){
- return NULL;
- }
- *o = usbradio_default;
- /* "general" is also the default thing */
- if (strcmp(ctg, "general") == 0) {
- o->name = ast_strdup("dsp");
- usbradio_active = o->name;
- }
- else o->name = ast_strdup(ctg);
- }
-
- strcpy(o->mohinterpret, "default");
- o->micmax = amixer_max(o->devicenum,MIXER_PARAM_MIC_CAPTURE_VOL);
- o->spkrmax = amixer_max(o->devicenum,MIXER_PARAM_SPKR_PLAYBACK_VOL);
- /* fill other fields from configuration */
- for (v = ast_variable_browse(cfg, ctg); v; v = v->next) {
- M_START(v->name, v->value);
-
- /* handle jb conf */
- if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
- continue;
-
-#if 0
- M_BOOL("autoanswer", o->autoanswer)
- M_BOOL("autohangup", o->autohangup)
- M_BOOL("overridecontext", o->overridecontext)
- M_STR("context", o->ctx)
- M_STR("language", o->language)
- M_STR("mohinterpret", o->mohinterpret)
- M_STR("extension", o->ext)
- M_F("callerid", store_callerid(o, v->value))
-#endif
- M_UINT("frags", o->frags)
- M_UINT("queuesize", o->queuesize)
- M_UINT("devicenum", o->devicenum)
- M_UINT("debug", usbradio_debug)
- M_BOOL("rxcpusaver",o->rxcpusaver)
- M_BOOL("txcpusaver",o->txcpusaver)
- M_BOOL("invertptt",o->invertptt)
- M_F("rxdemod",store_rxdemod(o,v->value))
- M_BOOL("txprelim",o->txprelim);
- M_F("txmixa",store_txmixa(o,v->value))
- M_F("txmixb",store_txmixb(o,v->value))
- M_F("carrierfrom",store_rxcdtype(o,v->value))
- M_F("rxsdtype",store_rxsdtype(o,v->value))
- M_F("rxctcssfreq",store_rxctcssfreq(o,v->value))
- M_F("txctcssfreq",store_txctcssfreq(o,v->value))
- M_F("rxgain",store_rxgain(o,v->value))
- M_BOOL("rxboostset", o->rxboostset)
- M_UINT("rxctcssrelax", o->rxctcssrelax)
- M_F("txtoctype",store_txtoctype(o,v->value))
- M_UINT("hdwtype", o->hdwtype)
- M_UINT("duplex", o->radioduplex)
- M_END(;
- );
- }
-
- cfg1 = ast_config_load(config1);
- if (!cfg1)
- {
- o->rxmixerset = 500;
- o->txmixaset = 500;
- o->txmixbset = 500;
- o->rxvoiceadj = 0.5;
- o->rxctcssadj = 0.5;
- o->txctcssadj = 200;
- o->rxsquelchadj = 500;
- ast_log(LOG_WARNING,"File %s not found, using default parameters.\n",config1);
- } else {
- for (v = ast_variable_browse(cfg1, ctg); v; v = v->next) {
-
- M_START(v->name, v->value);
- M_UINT("rxmixerset", o->rxmixerset)
- M_UINT("txmixaset", o->txmixaset)
- M_UINT("txmixbset", o->txmixbset)
- M_F("rxvoiceadj",store_rxvoiceadj(o,v->value))
- M_F("rxctcssadj",store_rxctcssadj(o,v->value))
- M_UINT("txctcssadj",o->txctcssadj);
- M_UINT("rxsquelchadj", o->rxsquelchadj)
- M_END(;
- );
- }
- ast_config_destroy(cfg1);
- }
-
- o->debuglevel=0;
-
- if (o == &usbradio_default) /* we are done with the default */
- return NULL;
-
- o->lastopen = ast_tvnow(); /* don't leave it 0 or tvdiff may wrap */
- o->dsp = ast_dsp_new();
- if (o->dsp)
- {
- ast_dsp_set_features(o->dsp,DSP_FEATURE_DTMF_DETECT);
- ast_dsp_digitmode(o->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
- }
-
- if(o->rxctcssfreq!=0 && o->rxdemod==RX_AUDIO_SPEAKER)
- {
- ast_log(LOG_ERROR, "Incompatable Options o->rxctcssfreq=%f and o->rxdemod=speaker\n", o->rxctcssfreq);
- }
-
- if(o->pmrChan==NULL)
- {
- t_pmr_chan tChan;
-
- memset(&tChan,0,sizeof(t_pmr_chan));
-
- tChan.rxDemod=o->rxdemod;
- tChan.rxCdType=o->rxcdtype;
-
- tChan.txMod=o->txprelim;
-
- tChan.txMixA = o->txmixa;
- tChan.txMixB = o->txmixb;
-
- tChan.rxCpuSaver=o->rxcpusaver;
- tChan.txCpuSaver=o->txcpusaver;
-
- tChan.rxCtcssFreq=o->rxctcssfreq;
- tChan.txCtcssFreq=o->txctcssfreq;
-
- o->pmrChan=createPmrChannel(&tChan,FRAME_SIZE);
-
- o->pmrChan->radioDuplex=o->radioduplex;
-
- o->pmrChan->rxCpuSaver=o->rxcpusaver;
- o->pmrChan->txCpuSaver=o->txcpusaver;
-
- *(o->pmrChan->prxSquelchAdjust) =
- ((999 - o->rxsquelchadj) * 32767) / 1000;
-
- o->pmrChan->spsRx->outputGain = o->rxvoiceadj*M_Q8;
-
- o->pmrChan->txTocType = o->txtoctype;
-
- if ((o->txmixa == TX_OUT_LSD) ||
- (o->txmixa == TX_OUT_COMPOSITE) ||
- (o->txmixb == TX_OUT_LSD) ||
- (o->txmixb == TX_OUT_COMPOSITE))
- {
- *(o->pmrChan->prxCtcssAdjust)=o->rxctcssadj*M_Q8;
- set_txctcss_level(o);
- }
-
- o->pmrChan->rxCtcss->relax=o->rxctcssrelax;
-
- }
-
- if( (o->txmixa!=TX_OUT_VOICE) && (o->txmixb!=TX_OUT_VOICE) &&
- (o->txmixa!=TX_OUT_COMPOSITE) && (o->txmixb!=TX_OUT_COMPOSITE)
- )
- {
- ast_log(LOG_ERROR,"No txvoice output configured.\n");
- }
-
- if( o->txctcssfreq &&
- o->txmixa!=TX_OUT_LSD && o->txmixa!=TX_OUT_COMPOSITE &&
- o->txmixb!=TX_OUT_LSD && o->txmixb!=TX_OUT_COMPOSITE
- )
- {
- ast_log(LOG_ERROR,"No txtone output configured.\n");
- }
-
- if( o->rxctcssfreq && o->pmrChan->rxCtcssIndex<0 )
- {
- ast_log(LOG_ERROR,"Invalid CTCSS Frequency.\n");
- }
-
- // RxTestIt(o);
-
- mixer_write(o);
- mult_set(o);
- hidhdwconfig(o);
-
- // pmrdump(o);
-
- if (pipe(o->sndcmd) != 0) {
- ast_log(LOG_ERROR, "Unable to create pipe\n");
- goto error;
- }
-
- printf("creating sound thread\n");
- ast_pthread_create_background(&o->sthread, NULL, sound_thread, o);
-
- /* link into list of devices */
- if (o != &usbradio_default) {
- o->next = usbradio_default.next;
- usbradio_default.next = o;
- }
- return o;
-
- error:
- if (o != &usbradio_default)
- free(o);
- return NULL;
-}
-
-#if DEBUG_FILETEST == 1
-/*
- Test It on a File
-*/
-int RxTestIt(struct chan_usbradio_pvt *o)
-{
- const int numSamples = SAMPLES_PER_BLOCK;
- const int numChannels = 16;
-
- i16 sample,i,ii;
-
- i32 txHangTime;
-
- i16 txEnable;
-
- t_pmr_chan tChan;
- t_pmr_chan *pChan;
-
- FILE *hInput=NULL, *hOutput=NULL, *hOutputTx=NULL;
-
- i16 iBuff[numSamples*2*6], oBuff[numSamples];
-
- printf("RxTestIt()\n");
-
- pChan=o->pmrChan;
- pChan->b.txCapture=1;
- pChan->b.rxCapture=1;
-
- txEnable = 0;
-
- hInput = fopen("/usr/src/xpmr/testdata/rx_in.pcm","r");
- if(!hInput){
- printf(" RxTestIt() File Not Found.\n");
- return 0;
- }
- hOutput = fopen("/usr/src/xpmr/testdata/rx_debug.pcm","w");
-
- printf(" RxTestIt() Working...\n");
-
- while(!feof(hInput))
- {
- fread((void *)iBuff,2,numSamples*2*6,hInput);
-
- if(txHangTime)txHangTime-=numSamples;
- if(txHangTime<0)txHangTime=0;
-
- if(pChan->rxCtcss->decode)txHangTime=(8000/1000*2000);
-
- if(pChan->rxCtcss->decode && !txEnable)
- {
- txEnable=1;
- //pChan->inputBlanking=(8000/1000*200);
- }
- else if(!pChan->rxCtcss->decode && txEnable)
- {
- txEnable=0;
- }
-
- PmrRx(pChan,iBuff,oBuff);
-
- fwrite((void *)pChan->prxDebug,2,numSamples*numChannels,hOutput);
- }
- pChan->b.txCapture=0;
- pChan->b.rxCapture=0;
-
- if(hInput)fclose(hInput);
- if(hOutput)fclose(hOutput);
-
- printf(" RxTestIt() Complete.\n");
-
- return 0;
-}
-#endif
-
-#include "./xpmr/xpmr.c"
-/*
-*/
-static int load_module(void)
-{
- struct ast_config *cfg = NULL;
- char *ctg = NULL;
-
- /* Copy the default jb config over global_jbconf */
- memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
-
- /* load config file */
- if (!(cfg = ast_config_load(config))) {
- ast_log(LOG_NOTICE, "Unable to load config %s\n", config);
- return AST_MODULE_LOAD_DECLINE;
- }
-
- do {
- store_config(cfg, ctg);
- } while ( (ctg = ast_category_browse(cfg, ctg)) != NULL);
-
- ast_config_destroy(cfg);
-
- if (find_desc(usbradio_active) == NULL) {
- ast_log(LOG_NOTICE, "Device %s not found\n", usbradio_active);
- /* XXX we could default to 'dsp' perhaps ? */
- /* XXX should cleanup allocated memory etc. */
- return AST_MODULE_LOAD_FAILURE;
- }
-
- if (ast_channel_register(&usbradio_tech)) {
- ast_log(LOG_ERROR, "Unable to register channel type 'usb'\n");
- return AST_MODULE_LOAD_FAILURE;
- }
-
- ast_cli_register_multiple(cli_usbradio, sizeof(cli_usbradio) / sizeof(struct ast_cli_entry));
-
- return AST_MODULE_LOAD_SUCCESS;
-}
-/*
-*/
-static int unload_module(void)
-{
- struct chan_usbradio_pvt *o;
-
- ast_log(LOG_WARNING, "unload_module() called\n");
-
- ast_channel_unregister(&usbradio_tech);
- ast_cli_unregister_multiple(cli_usbradio, sizeof(cli_usbradio) / sizeof(struct ast_cli_entry));
-
- for (o = usbradio_default.next; o; o = o->next) {
-
- ast_log(LOG_WARNING, "destroyPmrChannel() called\n");
- if(o->pmrChan)destroyPmrChannel(o->pmrChan);
-
- #if DEBUG_CAPTURES == 1
- if (frxcapraw) { fclose(frxcapraw); frxcapraw = NULL; }
- if (frxcaptrace) { fclose(frxcaptrace); frxcaptrace = NULL; }
- if (frxoutraw) { fclose(frxoutraw); frxoutraw = NULL; }
- if (ftxcapraw) { fclose(ftxcapraw); ftxcapraw = NULL; }
- if (ftxcaptrace) { fclose(ftxcaptrace); ftxcaptrace = NULL; }
- if (ftxoutraw) { fclose(ftxoutraw); ftxoutraw = NULL; }
- #endif
-
- close(o->sounddev);
- if (o->sndcmd[0] > 0) {
- close(o->sndcmd[0]);
- close(o->sndcmd[1]);
- }
- if (o->dsp) ast_dsp_free(o->dsp);
- if (o->owner)
- ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD);
- if (o->owner) /* XXX how ??? */
- return -1;
- /* XXX what about the thread ? */
- /* XXX what about the memory allocated ? */
- }
- return 0;
-}
-
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "usb Console Channel Driver");
-
-/* end of file */
-
-
diff --git a/channels/xpmr/LICENSE b/channels/xpmr/LICENSE
deleted file mode 100755
index a52b16e40..000000000
--- a/channels/xpmr/LICENSE
+++ /dev/null
@@ -1,341 +0,0 @@
-
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) 19yy <name of author>
-
- 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
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) 19yy name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/channels/xpmr/sinetabx.h b/channels/xpmr/sinetabx.h
deleted file mode 100755
index 1ceb659e7..000000000
--- a/channels/xpmr/sinetabx.h
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * sinetabx.h - for Xelatec Private Mobile Radio Processes
- *
- * 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.
- *
- */
-
-/*! \file
- *
- * \brief Private Land Mobile Radio Channel Voice and Signaling Processor
- *
- * \author Steven Henke, W9SH <sph@xelatec.com> Xelatec, LLC
- */
-
-#ifndef XPMR_SINETABX_H
-#define XPMR_SINETABX_H 1
-
-#define SAMPLES_PER_SINE 256
-
-const i16 sinetablex[]={
-0, // 0
-804, // 1
-1608, // 2
-2410, // 3
-3212, // 4
-4011, // 5
-4808, // 6
-5602, // 7
-6393, // 8
-7179, // 9
-7962, // 10
-8739, // 11
-9512, // 12
-10278, // 13
-11039, // 14
-11793, // 15
-12539, // 16
-13279, // 17
-14010, // 18
-14732, // 19
-15446, // 20
-16151, // 21
-16846, // 22
-17530, // 23
-18204, // 24
-18868, // 25
-19519, // 26
-20159, // 27
-20787, // 28
-21403, // 29
-22005, // 30
-22594, // 31
-23170, // 32
-23731, // 33
-24279, // 34
-24811, // 35
-25329, // 36
-25832, // 37
-26319, // 38
-26790, // 39
-27245, // 40
-27683, // 41
-28105, // 42
-28510, // 43
-28898, // 44
-29268, // 45
-29621, // 46
-29956, // 47
-30273, // 48
-30571, // 49
-30852, // 50
-31113, // 51
-31356, // 52
-31580, // 53
-31785, // 54
-31971, // 55
-32137, // 56
-32285, // 57
-32412, // 58
-32521, // 59
-32609, // 60
-32678, // 61
-32728, // 62
-32757, // 63
-32767, // 64
-32757, // 65
-32728, // 66
-32678, // 67
-32609, // 68
-32521, // 69
-32412, // 70
-32285, // 71
-32137, // 72
-31971, // 73
-31785, // 74
-31580, // 75
-31356, // 76
-31113, // 77
-30852, // 78
-30571, // 79
-30273, // 80
-29956, // 81
-29621, // 82
-29268, // 83
-28898, // 84
-28510, // 85
-28105, // 86
-27683, // 87
-27245, // 88
-26790, // 89
-26319, // 90
-25832, // 91
-25329, // 92
-24811, // 93
-24279, // 94
-23731, // 95
-23170, // 96
-22594, // 97
-22005, // 98
-21403, // 99
-20787, // 100
-20159, // 101
-19519, // 102
-18868, // 103
-18204, // 104
-17530, // 105
-16846, // 106
-16151, // 107
-15446, // 108
-14732, // 109
-14010, // 110
-13279, // 111
-12539, // 112
-11793, // 113
-11039, // 114
-10278, // 115
-9512, // 116
-8739, // 117
-7962, // 118
-7179, // 119
-6393, // 120
-5602, // 121
-4808, // 122
-4011, // 123
-3212, // 124
-2410, // 125
-1608, // 126
-804, // 127
-0, // 128
--804, // 129
--1608, // 130
--2410, // 131
--3212, // 132
--4011, // 133
--4808, // 134
--5602, // 135
--6393, // 136
--7179, // 137
--7962, // 138
--8739, // 139
--9512, // 140
--10278, // 141
--11039, // 142
--11793, // 143
--12539, // 144
--13279, // 145
--14010, // 146
--14732, // 147
--15446, // 148
--16151, // 149
--16846, // 150
--17530, // 151
--18204, // 152
--18868, // 153
--19519, // 154
--20159, // 155
--20787, // 156
--21403, // 157
--22005, // 158
--22594, // 159
--23170, // 160
--23731, // 161
--24279, // 162
--24811, // 163
--25329, // 164
--25832, // 165
--26319, // 166
--26790, // 167
--27245, // 168
--27683, // 169
--28105, // 170
--28510, // 171
--28898, // 172
--29268, // 173
--29621, // 174
--29956, // 175
--30273, // 176
--30571, // 177
--30852, // 178
--31113, // 179
--31356, // 180
--31580, // 181
--31785, // 182
--31971, // 183
--32137, // 184
--32285, // 185
--32412, // 186
--32521, // 187
--32609, // 188
--32678, // 189
--32728, // 190
--32757, // 191
--32767, // 192
--32757, // 193
--32728, // 194
--32678, // 195
--32609, // 196
--32521, // 197
--32412, // 198
--32285, // 199
--32137, // 200
--31971, // 201
--31785, // 202
--31580, // 203
--31356, // 204
--31113, // 205
--30852, // 206
--30571, // 207
--30273, // 208
--29956, // 209
--29621, // 210
--29268, // 211
--28898, // 212
--28510, // 213
--28105, // 214
--27683, // 215
--27245, // 216
--26790, // 217
--26319, // 218
--25832, // 219
--25329, // 220
--24811, // 221
--24279, // 222
--23731, // 223
--23170, // 224
--22594, // 225
--22005, // 226
--21403, // 227
--20787, // 228
--20159, // 229
--19519, // 230
--18868, // 231
--18204, // 232
--17530, // 233
--16846, // 234
--16151, // 235
--15446, // 236
--14732, // 237
--14010, // 238
--13279, // 239
--12539, // 240
--11793, // 241
--11039, // 242
--10278, // 243
--9512, // 244
--8739, // 245
--7962, // 246
--7179, // 247
--6393, // 248
--5602, // 249
--4808, // 250
--4011, // 251
--3212, // 252
--2410, // 253
--1608, // 254
--804, // 255
-};
-
-#endif /* !XPMR_SINETABX_H */
diff --git a/channels/xpmr/xpmr.c b/channels/xpmr/xpmr.c
deleted file mode 100755
index c67e40841..000000000
--- a/channels/xpmr/xpmr.c
+++ /dev/null
@@ -1,2266 +0,0 @@
-/*
- * xpmr.c - Xelatec Private Mobile Radio Processes
- *
- * 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.
- *
- */
-
-/*! \file
- *
- * \brief Private Land Mobile Radio Channel Voice and Signaling Processor
- *
- * \author Steven Henke, W9SH <sph@xelatec.com> Xelatec, LLC
- */
-/*
- FYI = For Your Information
- PMR = Private Mobile Radio
- RX = Receive
- TX = Transmit
- CTCSS = Continuous Tone Coded Squelch System
- TONE = Same as above.
- LSD = Low Speed Data, subaudible signaling. May be tones or codes.
- VOX = Voice Operated Transmit
- DSP = Digital Signal Processing
- LPF = Low Pass Filter
- FIR = Finite Impulse Response (Filter)
- IIR = Infinite Impulse Response (Filter)
-*/
-#include <stdio.h>
-#include <ctype.h>
-#include <math.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "xpmr.h"
-#include "xpmr_coef.h"
-#include "sinetabx.h"
-
-static i16 pmrChanIndex=0; // count of created pmr instances
-
-/*
- Convert a Frequency in Hz to a zero based CTCSS Table index
-*/
-i16 CtcssFreqIndex(float freq)
-{
- i16 i,hit=-1;
-
- for(i=0;i<CTCSS_NUM_CODES;i++){
- if(freq==freq_ctcss[i])hit=i;
- }
- return hit;
-}
-/*
- pmr_rx_frontend
- Takes a block of data and low pass filters it.
- Determines the amplitude of high frequency noise for carrier detect.
- Decimates input data to change the rate.
-*/
-i16 pmr_rx_frontend(t_pmr_sps *mySps)
-{
- #define DCgainBpfNoise 65536
-
- i16 samples,iOutput, *input, *output, *noutput;
- i16 *x, *coef, *coef2;
- i32 i, naccum, outputGain, calcAdjust;
- i64 y;
- i16 nx, hyst, setpt, compOut;
- i16 amax, amin, apeak, discounteru, discounterl, discfactor;
- i16 decimator, decimate, doNoise;
-
- TRACEX(("pmr_rx_frontend()\n"));
-
- if(!mySps->enabled)return(1);
-
- decimator = mySps->decimator;
- decimate = mySps->decimate;
-
- input = mySps->source;
- output = mySps->sink;
- noutput = mySps->parentChan->pRxNoise;
-
- nx = mySps->nx;
- coef = mySps->coef;
- coef2 = mySps->coef2;
-
- calcAdjust = mySps->calcAdjust;
- outputGain = mySps->outputGain;
-
- amax=mySps->amax;
- amin=mySps->amin;
- apeak=mySps->apeak;
- discounteru=mySps->discounteru;
- discounterl=mySps->discounterl;
- discfactor=mySps->discfactor;
- setpt=mySps->setpt;
- hyst=mySps->hyst;
- compOut=mySps->compOut;
-
- samples=mySps->nSamples*decimate;
- x=mySps->x;
- iOutput=0;
-
- if(mySps->parentChan->rxCdType!=CD_XPMR_VOX)doNoise=1;
- else doNoise=0;
-
- for(i=0;i<samples;i++)
- {
- i16 n;
-
- //shift the old samples
- for(n=nx-1; n>0; n--)
- x[n] = x[n-1];
-
- x[0] = input[i*2];
-
- --decimator;
-
- if(decimator<=0)
- {
- decimator=decimate;
-
- y=0;
- for(n=0; n<nx; n++)
- y += coef[n] * x[n];
-
- y=((y/calcAdjust)*outputGain)/M_Q8;
-
- if(y>32767)y=32767;
- else if(y<-32767)y=-32767;
-
- output[iOutput]=y; // Rx Baseband decimated
- noutput[iOutput++] = apeak; // Rx Noise
- }
-
- if(doNoise)
- {
- // calculate noise output
- naccum=0;
- for(n=0; n<nx; n++)
- naccum += coef_fir_bpf_noise_1[n] * x[n];
-
- naccum /= DCgainBpfNoise;
-
- if(naccum>amax)
- {
- amax=naccum;
- discounteru=discfactor;
- }
- else if(--discounteru<=0)
- {
- discounteru=discfactor;
- amax=(i32)((amax*32700)/32768);
- }
-
- if(naccum<amin)
- {
- amin=naccum;
- discounterl=discfactor;
- }
- else if(--discounterl<=0)
- {
- 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->apeak=apeak;
- mySps->discounteru=discounteru;
- mySps->discounterl=discounterl;
- }
-
- return 0;
-}
-/*
- pmr general purpose fir
- works on a block of samples
-*/
-i16 pmr_gp_fir(t_pmr_sps *mySps)
-{
- i32 nsamples,inputGain,outputGain,calcAdjust;
- i16 *input, *output;
- i16 *x, *coef;
- i32 i, ii;
- i16 nx, hyst, setpt, compOut;
- i16 amax, amin, apeak=0, discounteru=0, discounterl=0, discfactor;
- i16 decimator, decimate, interpolate;
- i16 numChanOut, selChanOut, mixOut, monoOut;
-
- TRACEX(("pmr_gp_fir() %i\n",mySps->enabled));
-
- if(!mySps->enabled)return(1);
-
- inputGain = mySps->inputGain;
- calcAdjust = mySps->calcAdjust;
- outputGain = mySps->outputGain;
-
- input = mySps->source;
- output = mySps->sink;
- x = mySps->x;
- nx = mySps->nx;
- coef = mySps->coef;
-
- decimator = mySps->decimator;
- decimate = mySps->decimate;
- interpolate = mySps->interpolate;
-
- setpt = mySps->setpt;
- compOut = mySps->compOut;
-
- inputGain = mySps->inputGain;
- outputGain = mySps->outputGain;
- numChanOut = mySps->numChanOut;
- selChanOut = mySps->selChanOut;
- mixOut = mySps->mixOut;
- monoOut = mySps->monoOut;
-
- amax=mySps->amax;
- amin=mySps->amin;
-
- discfactor=mySps->discfactor;
- hyst=mySps->hyst;
- setpt=mySps->setpt;
- nsamples=mySps->nSamples;
-
- if(mySps->option==3)
- {
- mySps->option=0;
- mySps->enabled=0;
- for(i=0;i<nsamples;i++)
- {
- if(monoOut)
- output[(i*2)]=output[(i*2)+1]=0;
- else
- output[(i*numChanOut)+selChanOut]=0;
- }
- return 0;
- }
-
- ii=0;
- for(i=0;i<nsamples;i++)
- {
- int ix;
-
- int64_t y=0;
-
- if(decimate<0)
- {
- decimator=decimate;
- }
-
- for(ix=0;ix<interpolate;ix++)
- {
- i16 n;
- y=0;
-
- for(n=nx-1; n>0; n--)
- x[n] = x[n-1];
- x[0] = (input[i]*inputGain)/M_Q8;
-
- #if 0
- --decimator;
- if(decimator<=0)
- {
- decimator=decimate;
- for(n=0; n<nx; n++)
- y += coef[n] * x[n];
- y /= (outputGain*3);
- output[ii++]=y;
- }
- #else
- for(n=0; n<nx; n++)
- y += coef[n] * x[n];
-
- y=((y/calcAdjust)*outputGain)/M_Q8;
-
- if(mixOut){
- if(monoOut){
- output[(ii*2)]=output[(ii*2)+1]+=y;
- }
- else{
- output[(ii*numChanOut)+selChanOut]+=y;
- }
- }
- else{
- if(monoOut){
- output[(ii*2)]=output[(ii*2)+1]=y;
- }
- else{
- output[(ii*numChanOut)+selChanOut]=y;
- }
- }
- ii++;
- #endif
- }
-
- // amplitude detector
- if(setpt)
- {
- i16 accum=y;
-
- if(accum>amax)
- {
- amax=accum;
- discounteru=discfactor;
- }
- else if(--discounteru<=0)
- {
- discounteru=discfactor;
- amax=(i32)((amax*32700)/32768);
- }
-
- if(accum<amin)
- {
- amin=accum;
- discounterl=discfactor;
- }
- else if(--discounterl<=0)
- {
- discounterl=discfactor;
- amin=(i32)((amin*32700)/32768);
- }
-
- apeak = (i32)(amax-amin)/2;
-
- if(apeak>setpt)compOut=1;
- else if(compOut&&(apeak<(setpt-hyst)))compOut=0;
- }
- }
-
- mySps->decimator = decimator;
-
- mySps->amax=amax;
- mySps->amin=amin;
- mySps->apeak=apeak;
- mySps->discounteru=discounteru;
- mySps->discounterl=discounterl;
-
- mySps->compOut=compOut;
-
- return 0;
-}
-/*
- general purpose integrator lpf
-*/
-i16 gp_inte_00(t_pmr_sps *mySps)
-{
- i16 npoints;
- i16 *input, *output;
-
- i32 inputGain, outputGain,calcAdjust;
- i32 i;
- i32 accum;
-
- i32 state00;
- i16 coeff00, coeff01;
-
- TRACEX(("gp_inte_00() %i\n",mySps->enabled));
- if(!mySps->enabled)return(1);
-
- input = mySps->source;
- output = mySps->sink;
-
- npoints=mySps->nSamples;
-
- inputGain=mySps->inputGain;
- outputGain=mySps->outputGain;
- calcAdjust=mySps->calcAdjust;
-
- coeff00=((i16*)mySps->coef)[0];
- coeff01=((i16*)mySps->coef)[1];
- state00=((i32*)mySps->x)[0];
-
- // note fixed gain of 2 to compensate for attenuation
- // in passband
-
- for(i=0;i<npoints;i++)
- {
- accum=input[i];
- state00 = accum + (state00*coeff01)/M_Q15;
- accum = (state00*coeff00)/(M_Q15/4);
- output[i]=(accum*outputGain)/M_Q8;
- }
-
- ((i32*)(mySps->x))[0]=state00;
-
- return 0;
-}
-/*
- general purpose differentiator hpf
-*/
-i16 gp_diff(t_pmr_sps *mySps)
-{
- i16 *input, *output;
- i16 npoints;
- i32 inputGain, outputGain, calcAdjust;
- i32 i;
- i32 temp0,temp1;
- i16 x0;
- i32 y0;
- i16 a0,a1;
- i16 b0;
- i16 *coef;
- i16 *x;
-
- input = mySps->source;
- output = mySps->sink;
-
- npoints=mySps->nSamples;
-
- inputGain=mySps->inputGain;
- outputGain=mySps->outputGain;
- calcAdjust=mySps->calcAdjust;
-
- coef=(i16*)(mySps->coef);
- x=(i16*)(mySps->x);
- a0=coef[0];
- a1=coef[1];
- b0=coef[2];
-
- x0=x[0];
-
- TRACEX(("gp_diff()\n"));
-
- for (i=0;i<npoints;i++)
- {
- temp0 = x0 * a1;
- x0 = input[i];
- temp1 = input[i] * a0;
- y0 = (temp0 + temp1)/calcAdjust;
- output[i]=(y0*outputGain)/M_Q8;
- }
-
- x[0]=x0;
-
- return 0;
-}
-/* ----------------------------------------------------------------------
- CenterSlicer
-*/
-i16 CenterSlicer(t_pmr_sps *mySps)
-{
- i16 npoints,lhit,uhit;
- i16 *input, *output, *buff;
-
- i32 inputGain, outputGain, inputGainB;
- i32 i;
- i32 accum;
-
- i32 amax; // buffer amplitude maximum
- i32 amin; // buffer amplitude minimum
- i32 apeak; // buffer amplitude peak
- i32 center;
- i32 setpt; // amplitude set point for peak tracking
-
- i32 discounteru; // amplitude detector integrator discharge counter upper
- i32 discounterl; // amplitude detector integrator discharge counter lower
- i32 discfactor; // amplitude detector integrator discharge factor
-
- TRACEX(("CenterSlicer() %i\n",mySps->enabled));
-
- input = mySps->source;
- output = mySps->sink;
- buff = mySps->buff;
-
- npoints=mySps->nSamples;
-
- inputGain=mySps->inputGain;
- outputGain=mySps->outputGain;
- inputGainB=mySps->inputGainB;
-
- amax=mySps->amax;
- amin=mySps->amin;
- setpt=mySps->setpt;
- apeak=mySps->apeak;
- discounteru=mySps->discounteru;
- discounterl=mySps->discounterl;
-
- discfactor=mySps->discfactor;
- npoints=mySps->nSamples;
-
- for(i=0;i<npoints;i++)
- {
- accum=input[i];
-
- lhit=uhit=0;
-
- if(accum>amax)
- {
- amax=accum;
- uhit=1;
- if(amin<(amax-setpt))
- {
- amin=(amax-setpt);
- lhit=1;
- }
- }
- else if(accum<amin)
- {
- amin=accum;
- lhit=1;
- if(amax>(amin+setpt))
- {
- amax=(amin+setpt);
- uhit=1;
- }
- }
-
- if(--discounteru<=0 && amax>0)
- {
- amax--;
- uhit=1;
- }
-
- if(--discounterl<=0 && amin<0)
- {
- amin++;
- lhit=1;
- }
-
- if(uhit)discounteru=discfactor;
- if(lhit)discounterl=discfactor;
-
- apeak = (amax-amin)/2;
- center = (amax+amin)/2;
- accum = accum - center;
- output[i]=accum;
-
- // 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;
- #endif
- #if 0
- if(mySps->parentChan->frameCountRx&0x01) mySps->parentChan->prxDebug1[i]=amax;
- else mySps->parentChan->prxDebug1[i]=amin;
- #endif
- #endif
- }
-
- mySps->amax=amax;
- mySps->amin=amin;
- mySps->apeak=apeak;
- mySps->discounteru=discounteru;
- mySps->discounterl=discounterl;
-
- return 0;
-}
-/* ----------------------------------------------------------------------
- MeasureBlock
- determine peak amplitude
-*/
-i16 MeasureBlock(t_pmr_sps *mySps)
-{
- i16 npoints;
- i16 *input, *output;
-
- i32 inputGain, outputGain;
- i32 i;
- i32 accum;
-
- i16 amax; // buffer amplitude maximum
- i16 amin; // buffer amplitude minimum
- i16 apeak=0; // buffer amplitude peak (peak to peak)/2
- i16 setpt; // amplitude set point for amplitude comparator
-
- i32 discounteru; // amplitude detector integrator discharge counter upper
- i32 discounterl; // amplitude detector integrator discharge counter lower
- i32 discfactor; // amplitude detector integrator discharge factor
-
- TRACEX(("MeasureBlock() %i\n",mySps->enabled));
-
- if(!mySps->enabled)return 1;
-
- if(mySps->option==3)
- {
- mySps->amax = mySps->amin = mySps->apeak = \
- mySps->discounteru = mySps->discounterl = \
- mySps->enabled = 0;
- return 1;
- }
-
- input = mySps->source;
- output = mySps->sink;
-
- npoints=mySps->nSamples;
-
- inputGain=mySps->inputGain;
- outputGain=mySps->outputGain;
-
- amax=mySps->amax;
- amin=mySps->amin;
- setpt=mySps->setpt;
- discounteru=mySps->discounteru;
- discounterl=mySps->discounterl;
-
- discfactor=mySps->discfactor;
- npoints=mySps->nSamples;
-
- for(i=0;i<npoints;i++)
- {
- accum=input[i];
-
- if(accum>amax)
- {
- amax=accum;
- discounteru=discfactor;
- }
- else if(--discounteru<=0)
- {
- discounteru=discfactor;
- amax=(i32)((amax*32700)/32768);
- }
-
- if(accum<amin)
- {
- amin=accum;
- discounterl=discfactor;
- }
- else if(--discounterl<=0)
- {
- discounterl=discfactor;
- amin=(i32)((amin*32700)/32768);
- }
-
- apeak = (i32)(amax-amin)/2;
- if(output)output[i]=apeak;
- }
-
- mySps->amax=amax;
- mySps->amin=amin;
- mySps->apeak=apeak;
- mySps->discounteru=discounteru;
- mySps->discounterl=discounterl;
- if(apeak>=setpt) mySps->compOut=1;
- else mySps->compOut=0;
-
- //TRACEX((" -MeasureBlock()=%i\n",mySps->apeak));
- return 0;
-}
-/*
- SoftLimiter
-*/
-i16 SoftLimiter(t_pmr_sps *mySps)
-{
- i16 npoints;
- //i16 samples, lhit,uhit;
- i16 *input, *output;
-
- i32 inputGain, outputGain;
- i32 i;
- i32 accum;
- i32 tmp;
-
- i32 amax; // buffer amplitude maximum
- i32 amin; // buffer amplitude minimum
- //i32 apeak; // buffer amplitude peak
- i32 setpt; // amplitude set point for amplitude comparator
- i16 compOut; // amplitude comparator output
-
- input = mySps->source;
- output = mySps->sink;
-
- inputGain=mySps->inputGain;
- outputGain=mySps->outputGain;
-
- npoints=mySps->nSamples;
-
- setpt=mySps->setpt;
- amax=(setpt*124)/128;
- amin=-amax;
-
- TRACEX(("SoftLimiter() %i %i %i) \n",amin, amax,setpt));
-
- for(i=0;i<npoints;i++)
- {
- accum=input[i];
- //accum=input[i]*mySps->inputGain/256;
-
- if(accum>setpt)
- {
- tmp=((accum-setpt)*4)/128;
- accum=setpt+tmp;
- if(accum>amax)accum=amax;
- compOut=1;
- accum=setpt;
- }
- else if(accum<-setpt)
- {
- tmp=((accum+setpt)*4)/128;
- accum=(-setpt)-tmp;
- if(accum<amin)accum=amin;
- compOut=1;
- accum=-setpt;
- }
-
- output[i]=(accum*outputGain)/M_Q8;
- }
-
- return 0;
-}
-/*
- SigGen() - sine, square function generator
- sps overloaded values
- discfactor = phase factor
- discfactoru = phase index
- if source is not NULL then mix it in!
-
- sign table and output gain are in Q15 format (32767=.999)
-*/
-i16 SigGen(t_pmr_sps *mySps)
-{
- #define PH_FRACT_FACT 128
-
- i32 ph;
- i16 i,outputgain,waveform,numChanOut,selChanOut;
- i32 accum;
-
- TRACEX(("SigGen(%i) \n",mySps->option));
-
- if(!mySps->freq ||!mySps->enabled)return 0;
-
- outputgain=mySps->outputGain;
- waveform=0;
- numChanOut=mySps->numChanOut;
- selChanOut=mySps->selChanOut;
-
- if(mySps->option==1)
- {
- mySps->option=0;
- mySps->state=1;
- mySps->discfactor=
- (SAMPLES_PER_SINE*mySps->freq*PH_FRACT_FACT)/mySps->sampleRate/10;
-
- TRACEX((" SigGen() discfactor = %i\n",mySps->discfactor));
- if(mySps->discounterl)mySps->state=2;
- }
- else if(mySps->option==2)
- {
- i16 shiftfactor=CTCSS_TURN_OFF_SHIFT;
- // phase shift request
- mySps->option=0;
- mySps->state=2;
- 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);
- //printf("shiftfactor = %i\n",shiftfactor);
- //shiftfactor+=10;
- }
- else if(mySps->option==3)
- {
- // stop it and clear the output buffer
- mySps->option=0;
- mySps->state=0;
- mySps->enabled=0;
- for(i=0;i<mySps->nSamples;i++)
- mySps->sink[(i*numChanOut)+selChanOut]=0;
- return(0);
- }
- else if(mySps->state==2)
- {
- // doing turn off
- mySps->discounterl-=MS_PER_FRAME;
- if(mySps->discounterl<=0)
- {
- mySps->option=3;
- mySps->state=2;
- }
- }
- else if(mySps->state==0)
- {
- return(0);
- }
-
- ph=mySps->discounteru;
-
- for(i=0;i<mySps->nSamples;i++)
- {
- if(!waveform)
- {
- // sine
- //tmp=(sinetablex[ph/PH_FRACT_FACT]*amplitude)/M_Q16;
- accum=sinetablex[ph/PH_FRACT_FACT];
- accum=(accum*outputgain)/M_Q8;
- }
- else
- {
- // square
- if(ph>SAMPLES_PER_SINE/2)
- accum=outputgain/M_Q8;
- else
- accum=-outputgain/M_Q8;
- }
-
- if(mySps->source)accum+=mySps->source[i];
-
- mySps->sink[(i*numChanOut)+selChanOut]=accum;
-
- ph=(ph+mySps->discfactor)%(SAMPLES_PER_SINE*PH_FRACT_FACT);
- }
-
- mySps->discounteru=ph;
-
- return 0;
-}
-/*
- adder/mixer
- takes existing buffer and adds source buffer to destination buffer
- sink buffer = (sink buffer * gain) + source buffer
-*/
-i16 pmrMixer(t_pmr_sps *mySps)
-{
- i32 accum;
- i16 i, *input, *inputB, *output;
- i16 inputGain, inputGainB; // apply to input data in Q7.8 format
- i16 outputGain; // apply to output data in Q7.8 format
- i16 discounteru,discounterl,amax,amin,setpt,discfactor;
- i16 npoints,uhit,lhit,apeak,measPeak;
-
- TRACEX(("pmrMixer()\n"));
-
- input = mySps->source;
- inputB = mySps->sourceB;
- output = mySps->sink;
-
- inputGain=mySps->inputGain;
- inputGainB=mySps->inputGainB;
- outputGain=mySps->outputGain;
-
- amax=mySps->amax;
- amin=mySps->amin;
- setpt=mySps->setpt;
- discounteru=mySps->discounteru;
- discounterl=mySps->discounteru;
-
- discfactor=mySps->discfactor;
- npoints=mySps->nSamples;
- measPeak=mySps->measPeak;
-
- for(i=0;i<npoints;i++)
- {
- accum = ((input[i]*inputGain)/M_Q8) +
- ((inputB[i]*inputGainB)/M_Q8);
-
- accum=(accum*outputGain)/M_Q8;
- output[i]=accum;
-
- if(measPeak){
- lhit=uhit=0;
-
- if(accum>amax){
- amax=accum;
- uhit=1;
- if(amin<(amax-setpt)){
- amin=(amax-setpt);
- lhit=1;
- }
- }
- else if(accum<amin){
- amin=accum;
- lhit=1;
- if(amax>(amin+setpt)){
- amax=(amin+setpt);
- uhit=1;
- }
- }
-
- if(--discounteru<=0 && amax>0){
- amax--;
- uhit=1;
- }
-
- if(--discounterl<=0 && amin<0){
- amin++;
- lhit=1;
- }
-
- if(uhit)discounteru=discfactor;
- if(lhit)discounterl=discfactor;
- }
- }
-
- if(measPeak){
- apeak = (amax-amin)/2;
- mySps->apeak=apeak;
- mySps->amax=amax;
- mySps->amin=amin;
- mySps->discounteru=discounteru;
- mySps->discounterl=discounterl;
- }
-
- return 0;
-}
-/*
- DelayLine
-*/
-i16 DelayLine(t_pmr_sps *mySps)
-{
- i16 *input, *output, *buff;
- i16 i, npoints,buffsize,inindex,outindex;
-
- TRACEX((" DelayLine() %i\n",mySps->enabled));
-
- input = mySps->source;
- output = mySps->sink;
- buff = (i16*)(mySps->buff);
- buffsize = mySps->buffSize;
- npoints = mySps->nSamples;
-
- outindex = mySps->buffOutIndex;
- inindex = outindex + mySps->buffLead;
-
- for(i=0;i<npoints;i++)
- {
- inindex %= buffsize;
- outindex %= buffsize;
-
- buff[inindex]=input[i];
- output[i]=buff[outindex];
- inindex++;
- outindex++;
- }
- mySps->buffOutIndex=outindex;
-
- return 0;
-}
-/*
- Continuous Tone Coded Squelch (CTCSS) Detector
-*/
-i16 ctcss_detect(t_pmr_chan *pmrChan)
-{
- i16 i,points2do, points=0, *pInput, hit, thit,relax;
- i16 tnum, tmp, indexWas=0, indexNow, gain, peakwas=0, diffpeak;
- i16 difftrig;
- i16 lasttv0=0, lasttv1=0, lasttv2=0, tv0, tv1, tv2, indexDebug;
-
- TRACEX(("ctcss_detect(%p) %i %i %i %i\n",pmrChan,
- pmrChan->rxCtcss->enabled,
- pmrChan->rxCtcssIndex,
- pmrChan->rxCtcss->testIndex,
- pmrChan->rxCtcss->decode));
-
- if(!pmrChan->rxCtcss->enabled)return(1);
-
- 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);
-
- thit=hit=-1;
-
- //TRACEX((" ctcss_detect() %i %i %i %i\n", CTCSS_NUM_CODES,0,0,0));
-
- for(tnum=0;tnum<CTCSS_NUM_CODES;tnum++)
- {
- i32 accum, peak;
- t_tdet *ptdet;
- i16 fudgeFactor;
- i16 binFactor;
-
- //TRACEX((" ctcss_detect() tnum=%i %i\n",tnum,pmrChan->rxCtcssMap[tnum]));
-
- if( (pmrChan->rxCtcssMap[tnum] < 0) ||
- (pmrChan->rxCtcss->decode>=0 && (tnum!= pmrChan->rxCtcss->decode)) ||
- (!pmrChan->rxCtcss->multiFreq && (tnum!= pmrChan->rxCtcssIndex))
- )
- continue;
-
- //TRACEX((" ctcss_detect() tnum=%i\n",tnum));
-
- ptdet=&(pmrChan->rxCtcss->tdet[tnum]);
- indexDebug=0;
- points=points2do=pmrChan->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!
-
- peakwas=ptdet->peak;
-
- ptdet->z[ptdet->zIndex]+=
- (((accum - ptdet->z[ptdet->zIndex])*binFactor)/M_Q15);
-
- peak = abs(ptdet->z[0]-ptdet->z[2]) + abs(ptdet->z[1]-ptdet->z[3]);
-
- if (ptdet->peak < peak)
- ptdet->peak += ( ((peak-ptdet->peak)*binFactor)/M_Q15);
- else
- ptdet->peak=peak;
-
- {
- static const i16 a0=13723;
- static const i16 a1=-13723;
- i32 temp0,temp1;
- i16 x0;
-
- //differentiate
- x0=ptdet->zd;
- temp0 = x0 * a1;
- ptdet->zd = ptdet->peak;
- temp1 = ptdet->peak * a0;
- diffpeak = (temp0 + temp1)/1024;
- }
-
- if(diffpeak<(-0.03*M_Q15))ptdet->dvd-=4;
- else if(ptdet->dvd<0)ptdet->dvd++;
-
- if((ptdet->dvd < -12) && diffpeak > (-0.02*M_Q15))ptdet->dvu+=2;
- else if(ptdet->dvu)ptdet->dvu--;
-
- tmp=ptdet->setpt;
- if(pmrChan->rxCtcss->decode==tnum)
- {
- if(relax)tmp=(tmp*55)/100;
- else tmp=(tmp*80)/100;
- }
-
- if(ptdet->peak > tmp)
- {
- if(ptdet->decode<(fudgeFactor*32))ptdet->decode++;
- }
- else if(pmrChan->rxCtcss->decode==tnum)
- {
- if(ptdet->peak > ptdet->hyst)ptdet->decode--;
- 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)))
- {
- ptdet->decode=0;
- ptdet->z[0]=ptdet->z[1]=ptdet->z[2]=ptdet->z[3]=ptdet->dvu=0;
- //printf("ctcss_detect() turnoff code!\n");
- }
-
- if(ptdet->decode<0 || !pmrChan->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(indexDebug<indexNow)
- {
- if(indexDebug==0)lasttv0=ptdet->pDebug0[points-1];
- if(ptdet->pDebug0)ptdet->pDebug0[indexDebug]=lasttv0;
-
- if(indexDebug==0)lasttv1=ptdet->pDebug1[points-1];
- if(ptdet->pDebug1)ptdet->pDebug1[indexDebug]=lasttv1;
-
- if(indexDebug==0)lasttv2=ptdet->pDebug2[points-1];
- if(ptdet->pDebug2)ptdet->pDebug2[indexDebug]=lasttv2;
-
- indexDebug++;
- }
- lasttv0=tv0;
- lasttv1=tv1;
- lasttv2=tv2*100;
- #endif
- indexWas=indexNow;
- ptdet->zIndex=(++ptdet->zIndex)%4;
- }
- ptdet->counter-=(points2do*CTCSS_SCOUNT_MUL);
-
- #if XPMR_DEBUG0 == 1
- for(i=indexWas;i<points;i++)
- {
- if(ptdet->pDebug0)ptdet->pDebug0[i]=lasttv0;
- if(ptdet->pDebug1)ptdet->pDebug1[i]=lasttv1;
- if(ptdet->pDebug2)ptdet->pDebug2[i]=lasttv2;
- }
- #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(thit>=0 && pmrChan->rxCtcss->decode<0 && !pmrChan->rxCtcss->BlankingTimer)
- {
- pmrChan->rxCtcss->decode=thit;
- }
- else if(thit<0 && pmrChan->rxCtcss->decode>=0)
- {
- pmrChan->rxCtcss->BlankingTimer=SAMPLE_RATE_NETWORK/5;
- pmrChan->rxCtcss->decode=-1;
-
- for(tnum=0;tnum<CTCSS_NUM_CODES;tnum++)
- {
- t_tdet *ptdet=NULL;
- ptdet=&(pmrChan->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));
- return(0);
-}
-/*
- TxTestTone
-*/
-static i16 TxTestTone(t_pmr_chan *pChan, i16 function)
-{
- if(function==1)
- {
- pChan->spsSigGen1->enabled=1;
- pChan->spsSigGen1->option=1;
- pChan->spsTx->source=pChan->spsSigGen1->sink;
- }
- else
- {
- pChan->spsSigGen1->option=3;
- }
- return 0;
-}
-/*
- assumes:
- sampling rate is 48KS/s
- samples are all 16 bits
- samples are filtered and decimated by 1/6th
-*/
-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));
-
- 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;
-
- pChan->index=pmrChanIndex++;
-
- for(i=0;i<CTCSS_NUM_CODES;i++)
- {
- pChan->rxCtcssMap[i]=-1;
- }
-
- pChan->rxCtcssIndex=-1;
-
- if(tChan==NULL)
- {
- pChan->rxNoiseSquelchEnable=0;
- pChan->rxHpfEnable=0;
- pChan->rxDeEmpEnable=0;
- pChan->rxCenterSlicerEnable=0;
- pChan->rxCtcssDecodeEnable=0;
- pChan->rxDcsDecodeEnable=0;
-
- 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;
- }
- else
- {
- pChan->rxDemod=tChan->rxDemod;
- pChan->rxCdType=tChan->rxCdType;
- pChan->rxSquelchPoint = tChan->rxSquelchPoint;
- pChan->rxCarrierHyst = 3000;
- pChan->rxCtcssFreq=tChan->rxCtcssFreq;
-
- for(i=0;i<CTCSS_NUM_CODES;i++)
- pChan->rxCtcssMap[i]=tChan->rxCtcssMap[i];
-
- pChan->txMod=tChan->txMod;
- pChan->txHpfEnable=1;
- pChan->txLpfEnable=1;
- pChan->txCtcssFreq=tChan->txCtcssFreq;
- pChan->txMixA=tChan->txMixA;
- pChan->txMixB=tChan->txMixB;
- pChan->radioDuplex=tChan->radioDuplex;
- }
-
- TRACEX(("misc settings \n"));
-
- if(pChan->rxCdType==CD_XPMR_NOISE){
- pChan->rxNoiseSquelchEnable=1;
- }
-
- if(pChan->rxDemod==RX_AUDIO_FLAT){
- pChan->rxHpfEnable=1;
- pChan->rxDeEmpEnable=1;
- }
-
- pChan->rxCarrierPoint=(pChan->rxSquelchPoint*32767)/100;
- pChan->rxCarrierHyst = 3000; //pChan->rxCarrierPoint/15;
-
- pChan->rxDcsDecodeEnable=0;
-
- if(pChan->rxCtcssFreq!=0){
- 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->pRxDemod = calloc(numSamples,2);
- pChan->pRxNoise = calloc(numSamples,2);
- pChan->pRxBase = calloc(numSamples,2);
- pChan->pRxHpf = calloc(numSamples,2);
- pChan->pRxLsd = calloc(numSamples,2);
- pChan->pRxSpeaker = calloc(numSamples,2);
- pChan->pRxCtcss = calloc(numSamples,2);
- pChan->pRxDcTrack = calloc(numSamples,2);
- pChan->pRxLsdLimit = calloc(numSamples,2);
-
-
- pChan->pTxBase = calloc(numSamples,2);
- pChan->pTxHpf = calloc(numSamples,2);
- pChan->pTxPreEmp = calloc(numSamples,2);
- pChan->pTxLimiter = calloc(numSamples,2);
- pChan->pTxLsd = calloc(numSamples,2);
- pChan->pTxLsdLpf = calloc(numSamples,2);
- pChan->pTxComposite = calloc(numSamples,2);
- pChan->pSigGen0 = calloc(numSamples,2);
- pChan->pSigGen1 = calloc(numSamples,2);
-
- pChan->pTxCode = calloc(numSamples,2);
- pChan->pTxOut = calloc(numSamples,2*2*6); // output buffer
-
- #if XPMR_DEBUG0 == 1
- pChan->pTxPttIn = calloc(numSamples,2);
- pChan->pTxPttOut = calloc(numSamples,2);
- pChan->prxDebug0 = calloc(numSamples,2);
- pChan->prxDebug1 = calloc(numSamples,2);
- pChan->prxDebug2 = calloc(numSamples,2);
- pChan->prxDebug3 = calloc(numSamples,2);
- pChan->ptxDebug0 = calloc(numSamples,2);
- pChan->ptxDebug1 = calloc(numSamples,2);
- pChan->ptxDebug2 = calloc(numSamples,2);
- pChan->ptxDebug3 = calloc(numSamples,2);
- pChan->pNull = calloc(numSamples,2);
- for(i=0;i<numSamples;i++)pChan->pNull[i]=((i%(numSamples/2))*8000)-4000;
- #endif
-
- TRACEX(("create ctcss\n"));
-
- 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;
-
- for(i=0;i<CTCSS_NUM_CODES;i++)
- {
- ptdet=&(pChan->rxCtcss->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;
- }
-
- // General Purpose Function Generator
- pSps=pChan->spsSigGen1=createPmrSps();
- pSps->parentChan=pChan;
- pSps->sink=pChan->pSigGen1;
- pSps->numChanOut=1;
- pSps->selChanOut=0;
- pSps->sigProc=SigGen;
- pSps->nSamples=pChan->nSamplesTx;
- pSps->sampleRate=SAMPLE_RATE_NETWORK;
- pSps->freq=10000; // in increments of 0.1 Hz
- pSps->outputGain=(.25*M_Q8);
- pSps->option=0;
- pSps->interpolate=1;
- pSps->decimate=1;
- pSps->enabled=0;
-
-
- // CTCSS ENCODER
- pSps = pChan->spsSigGen0 = createPmrSps();
- pSps->parentChan=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->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->source=pChan->pTxLsd;
- pSps->sink=pChan->pTxLsdLpf;
- pSps->sigProc=pmr_gp_fir;
- pSps->enabled=0;
- pSps->numChanOut=1;
- pSps->selChanOut=0;
- pSps->nSamples=pChan->nSamplesTx;
- pSps->decimator=pSps->decimate=1;
- 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;
- }
-
- pSps->inputGain=(1*M_Q8);
- pSps->outputGain=(1*M_Q8);
-
- if(pSps==NULL)printf("Error: calloc(), createPmrChannel()\n");
-
-
- // RX Process
- TRACEX(("create rx\n"));
- pSps = NULL;
-
- // allocate space for first sps and set pointers
- pSps=pChan->spsRx=createPmrSps();
- pSps->parentChan=pChan;
- pSps->source=NULL; //set when called
- pSps->sink=pChan->pRxBase;
- pSps->sigProc=pmr_rx_frontend;
- pSps->enabled=1;
- pSps->decimator=pSps->decimate=6;
- pSps->interpolate=pSps->interpolate=1;
- pSps->nSamples=pChan->nSamplesRx;
- pSps->ncoef=taps_fir_bpf_noise_1;
- pSps->size_coef=2;
- pSps->coef=(void*)coef_fir_lpf_3K_1;
- pSps->coef2=(void*)coef_fir_bpf_noise_1;
- pSps->nx=taps_fir_bpf_noise_1;
- pSps->size_x=2;
- 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->hyst=pChan->rxCarrierHyst;
- pSps->setpt=pChan->rxCarrierPoint;
- pChan->prxSquelchAdjust=&pSps->setpt;
- #if XPMR_DEBUG0 == 1
- pSps->debugBuff0=pChan->pRxDemod;
- pSps->debugBuff1=pChan->pRxNoise;
- 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->source=pChan->pRxBase;
- pSps->sink=pChan->pRxLsd;
- pSps->sigProc=pmr_gp_fir;
- pSps->enabled=1;
- pSps->numChanOut=1;
- pSps->selChanOut=0;
- pSps->nSamples=pChan->nSamplesRx;
- 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;
- }
-
- pSps->inputGain=(1*M_Q8);
- pSps->outputGain=(1*M_Q8);
- pChan->prxCtcssMeasure=pSps->sink;
- pChan->prxCtcssAdjust=&(pSps->outputGain);
-
-
- // 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;
- pChan->spsRxHpf=pSps;
- pSps->source=pChan->pRxBase;
- pSps->sink=pChan->pRxHpf;
- pSps->sigProc=pmr_gp_fir;
- pSps->enabled=1;
- pSps->numChanOut=1;
- pSps->selChanOut=0;
- pSps->nSamples=pChan->nSamplesRx;
- pSps->decimator=pSps->decimate=1;
- pSps->interpolate=1;
- pSps->ncoef=taps_fir_hpf_300_9_66;
- pSps->size_coef=2;
- pSps->coef=(void*)coef_fir_hpf_300_9_66;
- 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");
- pSps->calcAdjust=gain_fir_hpf_300_9_66;
- pSps->inputGain=(1*M_Q8);
- pSps->outputGain=(1*M_Q8);
- pChan->spsRxOut=pSps;
-
- // allocate space for next sps and set pointers
- // Rx DeEmp
- if(pChan->rxDeEmpEnable){
- pSps=pSps->nextSps=createPmrSps();
- pSps->parentChan=pChan;
- pChan->spsRxDeEmp=pSps;
- pSps->source=pChan->pRxHpf;
- pSps->sink=pChan->pRxSpeaker;
- pChan->spsRxOut=pSps; // OUTPUT STRUCTURE! maw
- 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");
- 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);
- }
-
- if(pChan->rxDelayLineEnable)
- {
- TRACEX(("create delayline\n"));
- pSps=pChan->spsDelayLine=pSps->nextSps=createPmrSps();
- pSps->sigProc=DelayLine;
- pSps->source=pChan->pRxSpeaker;
- pSps->sink=pChan->pRxSpeaker;
- pSps->enabled=0;
- pSps->inputGain=1*M_Q8;
- pSps->outputGain=1*M_Q8;
- pSps->nSamples=pChan->nSamplesRx;
- pSps->buffSize=4096;
- pSps->buff=calloc(4096,2); // one second maximum
- pSps->buffLead = (SAMPLE_RATE_NETWORK*0.100);
- pSps->buffOutIndex=0;
- }
-
- if(pChan->rxCdType==CD_XPMR_VOX)
- {
- TRACEX(("create vox measureblock\n"));
- pSps=pChan->spsRxVox=pSps->nextSps=createPmrSps();
- pSps->sigProc=MeasureBlock;
- pSps->parentChan=pChan;
- pSps->source=pChan->pRxBase;
- pSps->sink=pChan->prxDebug1;
- pSps->inputGain=1*M_Q8;
- pSps->outputGain=1*M_Q8;
- pSps->nSamples=pChan->nSamplesRx;
- pSps->discfactor=3;
- pSps->setpt=(0.01*M_Q15);
- 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->sigProc=MeasureBlock;
- pSps->enabled=0;
- pSps->nSamples=pChan->nSamplesRx;
- pSps->discfactor=10;
-
- pSps->nextSps=NULL; // last sps in chain RX
-
-
- // CREATE TRANSMIT CHAIN
- TRACEX((" create tx\n"));
- inputTmp=NULL;
- pSps = NULL;
-
- // allocate space for first sps and set pointers
-
- // Tx HPF SubAudible
- if(pChan->txHpfEnable)
- {
- pSps=createPmrSps();
- pChan->spsTx=pSps;
- pSps->source=pChan->pTxBase;
- pSps->sink=pChan->pTxHpf;
- pSps->sigProc=pmr_gp_fir;
- pSps->enabled=1;
- pSps->numChanOut=1;
- pSps->selChanOut=0;
- pSps->nSamples=pChan->nSamplesTx;
- pSps->decimator=pSps->decimate=1;
- pSps->interpolate=1;
- pSps->ncoef=taps_fir_hpf_300_9_66;
- pSps->size_coef=2;
- pSps->coef=(void*)coef_fir_hpf_300_9_66;
- 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");
- pSps->calcAdjust=gain_fir_hpf_300_9_66;
- pSps->inputGain=(1*M_Q8);
- pSps->outputGain=(1*M_Q8);
- inputTmp=pChan->pTxHpf;
- }
-
- // Tx PreEmphasis
- if(pChan->txPreEmpEnable)
- {
- if(pSps==NULL) pSps=pChan->spsTx=createPmrSps();
- else pSps=pSps->nextSps=createPmrSps();
-
- pSps->parentChan=pChan;
- pSps->source=inputTmp;
- 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);
- inputTmp=pSps->sink;
- }
-
- // Tx Limiter
- if(pChan->txLimiterEnable)
- {
- if(pSps==NULL) pSps=pChan->spsTx=createPmrSps();
- else pSps=pSps->nextSps=createPmrSps();
- pSps->source=inputTmp;
- pSps->sink=pChan->pTxLimiter;
- pSps->sigProc=SoftLimiter;
- pSps->enabled=1;
- pSps->nSamples=pChan->nSamplesTx;
- pSps->inputGain=(1*M_Q8);
- pSps->outputGain=(1*M_Q8);
- pSps->setpt=12000;
- inputTmp=pSps->sink;
- }
-
- // Composite Mix of Voice and LSD
- if((pChan->txMixA==TX_OUT_COMPOSITE)||(pChan->txMixB==TX_OUT_COMPOSITE))
- {
- if(pSps==NULL)
- pSps=pChan->spsTx=createPmrSps();
- else
- pSps=pSps->nextSps=createPmrSps();
- 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->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();
-
- pChan->spsTxOutA=pSps;
- if(!pChan->spsTx)pChan->spsTx=pSps;
- pSps->parentChan=pChan;
-
- if(pChan->txMixA==TX_OUT_COMPOSITE)
- {
- pSps->source=pChan->pTxComposite;
- }
- else if(pChan->txMixA==TX_OUT_LSD)
- {
- pSps->source=pChan->pTxLsdLpf;
- }
- else if(pChan->txMixA==TX_OUT_VOICE)
- {
- pSps->source=pChan->pTxHpf;
- }
- else if (pChan->txMixA==TX_OUT_AUX)
- {
- pSps->source=inputTmp;
- }
- else
- {
- pSps->source=NULL;
- }
-
- pSps->sink=pChan->pTxOut;
- pSps->sigProc=pmr_gp_fir;
- pSps->enabled=1;
- pSps->numChanOut=2;
- pSps->selChanOut=0;
- pSps->nSamples=pChan->nSamplesTx;
- pSps->interpolate=6;
- pSps->ncoef=taps_fir_lpf_3K_1;
- pSps->size_coef=2;
- pSps->coef=(void*)coef_fir_lpf_3K_1;
- 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");
- pSps->calcAdjust=gain_fir_lpf_3K_1;
- pSps->inputGain=(1*M_Q8);
- pSps->outputGain=(1*M_Q8);
- if(pChan->txMixA==pChan->txMixB)pSps->monoOut=1;
- else pSps->monoOut=0;
-
-
- // 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();
-
- pChan->spsTxOutB=pSps;
- pSps->parentChan=pChan;
- if(pChan->txMixB==TX_OUT_COMPOSITE)
- {
- pSps->source=pChan->pTxComposite;
- }
- else if(pChan->txMixB==TX_OUT_LSD)
- {
- pSps->source=pChan->pTxLsdLpf;
- // pChan->ptxCtcssAdjust=&pSps->inputGain;
- }
- else if(pChan->txMixB==TX_OUT_VOICE)
- {
- pSps->source=inputTmp;
- }
- else if(pChan->txMixB==TX_OUT_AUX)
- {
- pSps->source=pChan->pTxHpf;
- }
- else
- {
- pSps->source=NULL;
- }
-
- pSps->sink=pChan->pTxOut;
- pSps->sigProc=pmr_gp_fir;
- pSps->enabled=1;
- pSps->numChanOut=2;
- pSps->selChanOut=1;
- pSps->mixOut=0;
- pSps->nSamples=pChan->nSamplesTx;
- pSps->interpolate=6;
- pSps->ncoef=taps_fir_lpf_3K_1;
- pSps->size_coef=2;
- pSps->coef=(void*)coef_fir_lpf_3K_1;
- 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");
- pSps->calcAdjust=(gain_fir_lpf_3K_1);
- pSps->inputGain=(1*M_Q8);
- pSps->outputGain=(1*M_Q8);
-
- }
-
- pSps->nextSps=NULL;
-
- #if XPMR_DEBUG0 == 1
- {
- TRACEX((" configure tracing\n"));
- t_tdet *ptdet;
-
- pChan->rxCtcss->pDebug0=calloc(numSamples,2);
- pChan->rxCtcss->pDebug1=calloc(numSamples,2);
- pChan->rxCtcss->pDebug2=calloc(numSamples,2);
-
- for(i=0;i<CTCSS_NUM_CODES;i++){
- ptdet=&(pChan->rxCtcss->tdet[i]);
- ptdet->pDebug0=calloc(numSamples,2);
- ptdet->pDebug1=calloc(numSamples,2);
- ptdet->pDebug2=calloc(numSamples,2);
- }
-
- // buffer, 2 bytes per sample, and 16 channels
- pChan->prxDebug=calloc(numSamples*16,2);
- pChan->ptxDebug=calloc(numSamples*16,2);
- }
- #endif
-
- TRACEX((" createPmrChannel() end\n"));
-
- return pChan;
-}
-/*
-*/
-i16 destroyPmrChannel(t_pmr_chan *pChan)
-{
- t_pmr_sps *pmr_sps, *tmp_sps;
-
- TRACEX(("destroyPmrChannel()\n"));
-
- free(pChan->pRxDemod);
- free(pChan->pRxNoise);
- free(pChan->pRxBase);
- free(pChan->pRxHpf);
- free(pChan->pRxLsd);
- free(pChan->pRxSpeaker);
- free(pChan->pRxDcTrack);
- if(pChan->pRxLsdLimit)free(pChan->pRxLsdLimit);
- free(pChan->pTxBase);
- free(pChan->pTxHpf);
- free(pChan->pTxPreEmp);
- free(pChan->pTxLimiter);
- free(pChan->pTxLsd);
- free(pChan->pTxLsdLpf);
- if(pChan->pTxComposite)free(pChan->pTxComposite);
- free(pChan->pTxCode);
- free(pChan->pTxOut);
-
- 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->ptxDebug)free(pChan->ptxDebug);
- free(pChan->rxCtcss->pDebug0);
- free(pChan->rxCtcss->pDebug1);
-
- free(pChan->prxDebug0);
- free(pChan->prxDebug1);
- free(pChan->prxDebug2);
- free(pChan->prxDebug3);
-
- free(pChan->ptxDebug0);
- free(pChan->ptxDebug1);
- free(pChan->ptxDebug2);
- free(pChan->ptxDebug3);
-
- i16 i;
- for(i=0;i<CTCSS_NUM_CODES;i++)
- {
- free(pChan->rxCtcss->tdet[i].pDebug0);
- free(pChan->rxCtcss->tdet[i].pDebug1);
- free(pChan->rxCtcss->tdet[i].pDebug2);
- }
- #endif
-
- free(pChan->pRxCtcss);
-
- pmr_sps=pChan->spsRx;
-
- while(pmr_sps)
- {
- tmp_sps = pmr_sps;
- pmr_sps = tmp_sps->nextSps;
- destroyPmrSps(tmp_sps);
- }
-
- free(pChan);
-
- return 0;
-}
-/*
-*/
-t_pmr_sps *createPmrSps(void)
-{
- t_pmr_sps *pSps;
-
- TRACEX(("createPmrSps()\n"));
-
- pSps = (t_pmr_sps *)calloc(sizeof(t_pmr_sps),1);
-
- if(!pSps)printf("Error: createPmrSps()\n");
-
- // pSps->x=calloc(pSps->nx,pSps->size_x);
-
- return pSps;
-}
-/*
-*/
-i16 destroyPmrSps(t_pmr_sps *pSps)
-{
- TRACEX(("destroyPmrSps(%i)\n",pSps->index));
-
- if(pSps->x!=NULL)free(pSps->x);
- free(pSps);
- return 0;
-}
-/*
- PmrRx does the whole buffer
-*/
-i16 PmrRx(t_pmr_chan *pChan, i16 *input, i16 *output)
-{
- int i,ii;
- t_pmr_sps *pmr_sps;
-
- TRACEX(("PmrRx() %i\n",pChan->frameCountRx));
-
- if(pChan==NULL){
- printf("PmrRx() pChan == NULL\n");
- return 1;
- }
-
- pChan->frameCountRx++;
-
- pmr_sps=pChan->spsRx; // first sps
- pmr_sps->source=input;
-
- if(output!=NULL)pChan->spsRxOut->sink=output; //last sps
-
- #if 0
- if(pChan->inputBlanking>0)
- {
- pChan->inputBlanking-=pChan->nSamplesRx;
- if(pChan->inputBlanking<0)pChan->inputBlanking=0;
- for(i=0;i<pChan->nSamplesRx*6;i++)
- input[i]=0;
- }
- #endif
-
- // || (pChan->radioDuplex && (pChan->pttIn || pChan->pttOut)))
- if(pChan->rxCpuSaver && !pChan->rxCarrierDetect)
- {
- if(pChan->spsRxHpf)pChan->spsRxHpf->enabled=0;
- if(pChan->spsRxDeEmp)pChan->spsRxDeEmp->enabled=0;
- }
- else
- {
- if(pChan->spsRxHpf)pChan->spsRxHpf->enabled=1;
- if(pChan->spsRxDeEmp)pChan->spsRxDeEmp->enabled=1;
- }
-
- i=0;
- while(pmr_sps!=NULL && pmr_sps!=0)
- {
- TRACEX(("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)
- {
- pChan->rxVoxTimer=XPMR_VOX_HANGTIME; //VOX HangTime in ms
- }
- if(pChan->rxVoxTimer>0)
- {
- pChan->rxVoxTimer-=MS_PER_FRAME;
- pChan->rxCarrierDetect=1;
- }
- else
- {
- pChan->rxVoxTimer=0;
- pChan->rxCarrierDetect=0;
- }
- }
- else
- {
- pChan->rxCarrierDetect=!pChan->spsRx->compOut;
- }
-
- if( !pChan->rxCpuSaver || pChan->rxCarrierDetect
- || pChan->rxCtcss->decode!=-1) ctcss_detect(pChan);
-
- #if XPMR_DEBUG0 == 1
- // TRACEX(("Write file.\n"));
- ii=0;
- if(pChan->b.rxCapture)
- {
- for(i=0;i<pChan->nSamplesRx;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
- }
- }
- #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));
-
- if(pChan==NULL){
- printf("PmrTx() pChan == NULL\n");
- 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=output;
- pChan->spsSigGen1->sigProc(pChan->spsSigGen1);
- for(i=0;i<(pChan->nSamplesTx*2*6);i+=2)output[i+1]=output[i];
- return 0;
- }
-
- // handle transmitter ptt input
- hit=0;
- if( pChan->txPttIn && pChan->txState==0)
- {
- pChan->txState = 2;
- pChan->txPttOut=1;
- pChan->spsSigGen0->freq=pChan->txCtcssFreq*10;
- pChan->spsSigGen0->option=1;
- pChan->spsSigGen0->enabled=1;
- if(pChan->spsTxOutA)pChan->spsTxOutA->enabled=1;
- if(pChan->spsTxOutB)pChan->spsTxOutB->enabled=1;
- if(pChan->spsTxLsdLpf)pChan->spsTxLsdLpf->enabled=1;
- TRACEX((" TxOn\n"));
- }
- else if(!pChan->txPttIn && pChan->txState==2)
- {
- if( pChan->txTocType==TOC_NONE || !pChan->txCtcssFreq )
- {
- hit=1;
- TRACEX((" Tx Off Immediate.\n"));
- }
- else if(pChan->txCtcssFreq && pChan->txTocType==TOC_NOTONE)
- {
- pChan->txState=3;
- pChan->txHangTime=TOC_NOTONE_TIME/MS_PER_FRAME;
- pChan->spsSigGen0->option=3;
- TRACEX((" Tx Turn Off No Tone Start.\n"));
- }
- else
- {
- pChan->txState=3;
- pChan->txHangTime=0;
- pChan->spsSigGen0->option=2;
- TRACEX((" Tx Turn Off Phase Shift Start.\n"));
- }
- }
- else if(pChan->txState==3)
- {
- if(pChan->txHangTime)
- {
- if(--pChan->txHangTime==0)hit=1;
-
- }
- 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;
- }
- }
- }
-
- if( pChan->txCpuSaver && !hit && !pChan->txPttIn && !pChan->txPttOut && pChan->txState==0 ) return (1);
-
- if(hit)
- {
- pChan->txPttOut=0;
- pChan->txState=0;
- 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->spsSigGen0)
- {
- pChan->spsSigGen0->sigProc(pChan->spsSigGen0);
- pmr_sps=pChan->spsSigGen0->nextSps;
- i=0;
- while(pmr_sps!=NULL && pmr_sps!=0)
- {
- 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);
- }
- }
-
- if(pChan->spsSigGen1 && pChan->spsSigGen1->enabled)
- {
- pChan->spsSigGen1->sigProc(pChan->spsSigGen1);
- }
-
- // Do Voice
- pmr_sps=pChan->spsTx;
- if(!pChan->spsSigGen1->enabled)pmr_sps->source=input;
- else input=pmr_sps->source;
-
- if(output!=NULL)
- {
- if(pChan->spsTxOutA)pChan->spsTxOutA->sink=output;
- if(pChan->spsTxOutB)pChan->spsTxOutB->sink=output;
- }
-
- i=0;
- while(pmr_sps!=NULL && pmr_sps!=0)
- {
- TRACEX((" PmrTx() sps %i\n",i++));
- pmr_sps->sigProc(pmr_sps);
- pmr_sps = (t_pmr_sps *)(pmr_sps->nextSps);
- }
-
-
- if(pChan->txMixA==TX_OUT_OFF || !pChan->txPttOut){
- for(i=0;i<pChan->nSamplesTx*2*6;i+=2)output[i]=0;
- }
-
- if(pChan->txMixB==TX_OUT_OFF || !pChan->txPttOut ){
- for(i=0;i<pChan->nSamplesTx*2*6;i+=2)output[i+1]=0;
- }
-
- #if XPMR_DEBUG0 == 1
- if(pChan->b.txCapture)
- {
- i16 ii=0;
- for(i=0;i<pChan->nSamplesTx;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
- }
- }
- #endif
-
- return 0;
-}
-/* end of file */
diff --git a/channels/xpmr/xpmr.h b/channels/xpmr/xpmr.h
deleted file mode 100755
index d51aa6dca..000000000
--- a/channels/xpmr/xpmr.h
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * xpmr.h - for Xelatec Private Mobile Radio Processes
- *
- * 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.
- *
- */
-
-/*! \file
- *
- * \brief Private Land Mobile Radio Channel Voice and Signaling Processor
- *
- * \author Steven Henke, W9SH <sph@xelatec.com> Xelatec, LLC
- */
-
-#ifndef XPMR_H
-#define XPMR_H 1
-
-#ifdef CHAN_USBRADIO
-#define XPMR_DEBUG0 1
-#define XPMR_TRACE 0
-#else
-#define XPMR_DEBUG0 1
-#define XPMR_TRACE 1
-#endif
-
-#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; }
-#else
-#define TRACEX(a)
-#define TRACEXL(a)
-#define TRACEXT(a)
-#endif
-
-#define i8 int8_t
-#define u8 u_int8_t
-#define i16 int16_t
-#define u16 u_int16_t
-#define i32 int32_t
-#define u32 u_int32_t
-#define i64 int64_t
-#define u64 u_int64_t
-
-#define M_Q24 0x01000000 //
-#define M_Q23 0x00800000 //
-#define M_Q22 0x00400000 //
-#define M_Q21 0x00200000 //
-#define M_Q20 0x00100000 // 1048576
-#define M_Q19 0x00080000 // 524288
-#define M_Q18 0x00040000 // 262144
-#define M_Q17 0x00020000 // 131072
-#define M_Q16 0x00010000 // 65536
-#define M_Q15 0x00008000 // 32768
-#define M_Q14 0x00004000 // 16384
-#define M_Q13 0x00002000 // 8182
-#define M_Q12 0x00001000 // 4096
-#define M_Q11 0x00000800 // 2048
-#define M_Q10 0x00000400 // 1024
-#define M_Q9 0x00000200 // 512
-#define M_Q8 0x00000100 // 256
-#define M_Q7 0x00000080 // 128
-#define M_Q6 0x00000040 // 64
-#define M_Q5 0x00000020 // 32
-#define M_Q4 0x00000010 // 16
-#define M_Q3 0x00000008 // 16
-#define M_Q2 0x00000004 // 16
-#define M_Q1 0x00000002 // 16
-#define M_Q0 0x00000001 // 16
-
-#define RADIANS_PER_CYCLE (2*M_PI)
-
-#define SAMPLE_RATE_INPUT 48000
-#define SAMPLE_RATE_NETWORK 8000
-
-#define SAMPLES_PER_BLOCK 160
-#define MS_PER_FRAME 20
-
-#define CTCSS_NUM_CODES 38
-#define CTCSS_SCOUNT_MUL 100
-#define CTCSS_INTEGRATE 3932 // 32767*.120 // 120/1000 // 0.120
-#define CTCSS_INPUT_LIMIT 1000
-#define CTCSS_DETECT_POINT 1989
-#define CTCSS_HYSTERSIS 200
-
-#define CTCSS_TURN_OFF_TIME 160 // ms
-#define CTCSS_TURN_OFF_SHIFT 240 // degrees
-#define TOC_NOTONE_TIME 600 // ms
-
-#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};
-enum {CD_IGNORE,CD_XPMR_NOISE,CD_XPMR_VOX,CD_HID,CD_HID_INVERT};
-enum {SD_IGNORE,SD_HID,SD_HID_INVERT,SD_XPMR}; // no,external,externalinvert,software
-enum {RX_KEY_CARRIER,RX_KEY_CARRIER_CODE};
-enum {TX_OUT_OFF,TX_OUT_VOICE,TX_OUT_LSD,TX_OUT_COMPOSITE,TX_OUT_AUX};
-enum {TOC_NONE,TOC_PHASE,TOC_NOTONE};
-#endif
-
-/*
- one structure for each ctcss tone to decode
-*/
-typedef struct
-{
- i16 counter; // counter to next sample
- i16 counterFactor; // full divisor used to increment counter
- i16 binFactor;
- i16 fudgeFactor;
- i16 peak; // peak amplitude now maw sph now
- i16 enabled;
- i16 state; // dead, running, error
- i16 zIndex; // z bucket index
- i16 z[4]; // maw sph today
- i16 zi;
- i16 dvu;
- i16 dvd;
- i16 zd;
- i16 setpt;
- i16 hyst;
- i16 decode;
- i16 diffpeak;
- i16 debug; // value held from last pass
- i16 *pDebug0; // pointer to debug output
- i16 *pDebug1; // pointer to debug output
- i16 *pDebug2; // pointer to debug output
-
-} t_tdet;
-
-typedef struct
-{
- i16 enabled; // if 0 none, 0xFFFF all tones, or single tone
- i16 *input;
- 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 *pDebug0;
- i16 *pDebug1;
- i16 *pDebug2;
- i16 testIndex;
- i16 multiFreq;
- i8 relax;
-
-} t_dec_ctcss;
-
-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;
-
-/*
- Low Speed Data decoding both polarities
-*/
-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;
-
-typedef struct t_pmr_sps
-{
- i16 index; // unique to each instance
-
- i16 enabled; // enabled/disabled
-
- struct t_pmr_chan *parentChan;
-
- i16 *source; // source buffer
- i16 *sourceB; // source buffer B
- i16 *sink; // sink buffer
-
- i16 numChanOut; // allows output direct to interleaved buffer
- i16 selChanOut;
-
- u32 ticks;
-
- void *buff; // this structure's internal buffer
-
- i16 *debugBuff0; // debug buffer
- i16 *debugBuff1; // debug buffer
- i16 *debugBuff2; // debug buffer
- i16 *debugBuff3; // debug buffer
-
- i16 nSamples; // number of samples in the buffer
-
- u32 buffSize; // buffer maximum index
- u32 buffInIndex; // index to current input point
- u32 buffOutIndex; // index to current output point
- u32 buffLead; // lead of input over output through cb
-
- i16 decimate; // decimation or interpolation factor (could be put in coef's)
- i16 interpolate;
- i16 decimator; // like the state this must be saved between calls (could be put in x's)
-
- u32 sampleRate; // in Hz for elements in this structure
- u32 freq; // in 0.1 Hz
-
- i16 measPeak; // do measure Peak
- i16 amax; // buffer amplitude maximum
- i16 amin; // buffer amplitude minimum
- i16 apeak; // buffer amplitude peak value (peak to peak)/2
- i16 setpt; // amplitude set point for amplitude comparator
- i16 hyst; // hysterysis for amplitude comparator
- i16 compOut; // amplitude comparator output
-
- i32 discounteru; // amplitude detector integrator discharge counter upper
- i32 discounterl; // amplitude detector integrator discharge counter lower
- i32 discfactor; // amplitude detector integrator discharge factor
-
- i16 err; // error condition
- i16 option; // option / request zero
- i16 state; // stopped, start, stopped assumes zero'd
-
- i16 cleared; // output buffer cleared
-
- i16 delay;
- i16 decode;
-
- i32 inputGain; // apply to input data ? in Q7.8 format
- i32 inputGainB; // apply to input data ? in Q7.8 format
- i32 outputGain; // apply to output data ? in Q7.8 format
- i16 mixOut;
- i16 monoOut;
-
- i16 filterType; // iir, fir, 1, 2, 3, 4 ...
-
- i16 (*sigProc)(struct t_pmr_sps *sps); // function to call
-
- i32 calcAdjust; // final adjustment
- i16 nx; // number of x history elements
- i16 ncoef; // number of coefficients
- i16 size_x; // size of each x history element
- i16 size_coef; // size of each coefficient
- void *x; // history registers
- void *x2; // history registers, 2nd bank
- void *coef; // coefficients
- void *coef2; // coefficients 2
-
- void *nextSps; // next Sps function
-
-} t_pmr_sps;
-
-/*
- pmr channel
-*/
-typedef struct t_pmr_chan
-{
- i16 index; // which one
- i16 enabled; // enabled/disabled
- i16 status; // ok, error, busy, idle, initializing
-
- i16 nSamplesRx; // max frame size
- i16 nSamplesTx;
-
- i32 inputSampleRate; // in S/s 48000
- i32 baseSampleRate; // in S/s 8000
-
- i16 inputGain;
- i16 inputOffset;
-
- u32 frameCountRx; // number processed
- u32 frameCountTx;
-
- i32 txHangTime;
- i32 txTurnOff;
-
- i16 rxDC; // average DC value of input
- i16 rxSqSet; // carrier squelch threshold
- i16 rxSqHyst; // carrier squelch hysterysis
- i16 rxRssi; // current Rssi level
- i16 rxQuality; // signal quality metric
- i16 rxCarrierDetect; // carrier detect
- i16 rxCdType;
- i16 rxExtCarrierDetect;
- i32 inputBlanking; // Tx pulse eliminator
-
- i16 rxDemod; // see enum
- i16 txMod; //
-
- i16 rxNoiseSquelchEnable;
- i16 rxHpfEnable;
- i16 rxDeEmpEnable;
- i16 rxCenterSlicerEnable;
- i16 rxCtcssDecodeEnable;
- i16 rxDcsDecodeEnable;
- i16 rxDelayLineEnable;
-
- i16 txHpfEnable;
- i16 txLimiterEnable;
- i16 txPreEmpEnable;
- i16 txLpfEnable;
-
- 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;
-
- i16 dummy;
-
- i32 txScramFreq;
- i32 rxScramFreq;
-
- i16 gainVoice;
- i16 gainSubAudible;
-
- i16 txMixA; // Off, Ctcss, Voice, Composite
- i16 txMixB; // Off, Ctcss, Voice, Composite
-
- i16 rxMuting;
-
- i16 rxCpuSaver;
- i16 txCpuSaver;
-
- i8 rxSqMode; // 0 open, 1 carrier, 2 coded
-
- i8 cdMethod;
-
- i16 rxSquelchPoint;
-
- i16 rxCarrierPoint;
- i16 rxCarrierHyst;
-
- i16 rxCtcssMap[CTCSS_NUM_CODES];
-
- i16 txCtcssTocShift;
- i16 txCtcssTocTime;
- i8 txTocType;
-
- float txCtcssFreq;
- float rxCtcssFreq;
- float rxInputGain;
-
- i16 rxCtcssIndex;
-
- i16 txPttIn; // from external request
- i16 txPttOut; // to radio hardware
-
- i16 bandwidth; // wide/narrow
- i16 txCompand; // type
- i16 rxCompand; //
-
- i16 txEqRight; // muted, flat, pre-emp limited filtered
- i16 txEqLeft;
-
- i16 txPotRight; //
- i16 txPotLeft; //
-
- i16 rxPotRight; //
- i16 rxPotLeft; //
-
- i16 function;
-
- i16 txState; // off,settling,on,hangtime,turnoff
-
- t_pmr_sps *spsMeasure; // measurement block
-
- t_pmr_sps *spsRx; // 1st signal processing struct
- t_pmr_sps *spsRxLsd;
- t_pmr_sps *spsRxDeEmp;
- t_pmr_sps *spsRxHpf;
- t_pmr_sps *spsRxVox;
- t_pmr_sps *spsDelayLine; // Last signal processing struct
- 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
-
- // tune tweaks
-
- i32 rxVoxTimer; // Vox Hang Timer
-
- i16 *prxSquelchAdjust;
-
- // i16 *prxNoiseMeasure; // for autotune
- // i32 *prxNoiseAdjust;
-
- i16 *prxVoiceMeasure;
- i32 *prxVoiceAdjust;
-
- i16 *prxCtcssMeasure;
- i32 *prxCtcssAdjust;
-
- i16 *ptxVoiceAdjust; // from calling application
- i32 *ptxCtcssAdjust; // from calling application
-
- i32 *ptxLimiterAdjust; // from calling application
-
- i16 *pRxDemod; // buffers
- i16 *pRxBase; // decimated lpf input
- i16 *pRxNoise;
- i16 *pRxLsd; // subaudible only
- i16 *pRxHpf; // subaudible removed
- i16 *pRxDeEmp; // EIA Audio
- i16 *pRxSpeaker; // EIA Audio
- i16 *pRxDcTrack; // DC Restored LSD
- i16 *pRxLsdLimit; // LSD Limited
- i16 *pRxCtcss; //
- i16 *pRxSquelch;
-
- i16 *pTxBase; // input data
- i16 *pTxHpf;
- i16 *pTxPreEmp;
- i16 *pTxLimiter;
- i16 *pTxLsd;
- i16 *pTxLsdLpf;
- i16 *pTxComposite;
- i16 *pTxMod; // upsampled, low pass filtered
-
- i16 *pTxOut; //
-
- i16 *pTxPttIn;
- i16 *pTxPttOut;
- i16 *pTxHang;
- i16 *pTxCode;
-
- i16 *pSigGen0;
- i16 *pSigGen1;
-
- i16 *pAlt0;
- i16 *pAlt1;
-
- i16 *pNull;
-
- i16 *prxDebug; // consolidated debug buffer
- i16 *ptxDebug; // consolidated debug buffer
-
- i16 *prxDebug0;
- i16 *prxDebug1;
- i16 *prxDebug2;
- i16 *prxDebug3;
-
- i16 *ptxDebug0;
- i16 *ptxDebug1;
- i16 *ptxDebug2;
- i16 *ptxDebug3;
-
- t_dec_ctcss *rxCtcss;
-
- i16 clamplitudeDcs;
- i16 centerDcs;
- u32 dcsBlankingTimer;
- i16 dcsDecode; // current dcs decode value
-
- i16 clamplitudeLsd;
- i16 centerLsd;
- t_decLsd decLsd[2]; // for both polarities
-
-} t_pmr_chan;
-
-static i16 TxTestTone(t_pmr_chan *pChan, i16 function);
-
-t_pmr_chan *createPmrChannel(t_pmr_chan *tChan, i16 numSamples);
-t_pmr_sps *createPmrSps(void);
-i16 destroyPmrChannel(t_pmr_chan *pChan);
-i16 destroyPmrSps(t_pmr_sps *pSps);
-i16 pmr_rx_frontend(t_pmr_sps *mySps);
-i16 pmr_gp_fir(t_pmr_sps *mySps);
-i16 pmr_gp_iir(t_pmr_sps *mySps);
-i16 gp_inte_00(t_pmr_sps *mySps);
-i16 gp_diff(t_pmr_sps *mySps);
-i16 CenterSlicer(t_pmr_sps *mySps);
-i16 ctcss_detect(t_pmr_chan *pmrChan);
-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 CtcssFreqIndex(float freq);
-i16 MeasureBlock(t_pmr_sps *mySps);
-#endif /* ! XPMR_H */
-
-/* end of file */
-
-
-
diff --git a/channels/xpmr/xpmr_coef.h b/channels/xpmr/xpmr_coef.h
deleted file mode 100755
index 4b7274e5a..000000000
--- a/channels/xpmr/xpmr_coef.h
+++ /dev/null
@@ -1,963 +0,0 @@
-/*
- * xpmr_coef.h - for Xelatec Private Mobile Radio Processes
- *
- * 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.
- *
- * Some filter coeficients via 'WinFilter' http://www.winfilter.20m.com.
- *
- */
-
-/*! \file
- *
- * \brief Private Land Mobile Radio Channel Voice and Signaling Processor
- *
- * \author Steven Henke, W9SH <sph@xelatec.com> Xelatec, LLC
- */
-
-#ifndef XPMR_COEF_H
-#define XMPR_COEF_H 1
-
-// frequencies in 0.1 Hz
-const u32 dtmf_row[] =
-{
- 6970, 7700, 8520, 9410
-};
-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]=
-{
- // freq, divisor, integrator, filter
- {770,TDIV(770),CTCSS_COEF_INT,0,0},
- {1000,TDIV(1000),CTCSS_COEF_INT,0,0},
- {1035,TDIV(1035),CTCSS_COEF_INT,0,0},
- {0,0,0,0}
-};
-
-
-i16 coef_ctcss_div[]=
-{
-2985, // 00 067.0
-2782, // 01 071.9
-2688, // 02 074.4
-2597, // 03 077.0
-2509, // 04 079.7
-2424, // 05 082.5
-2342, // 06 085.4
-2260, // 07 088.5
-2186, // 08 091.5
-2110, // 09 094.8
-2053, // 10 097.4
-2000, // 11 100.0
-1932, // 12 103.5
-1866, // 13 107.2
-1803, // 14 110.9
-1742, // 15 114.8
-1684, // 16 118.8
-1626, // 17 123.0
-1571, // 18 127.3
-1517, // 19 131.8
-1465, // 20 136.5
-1415, // 21 141.3
-1368, // 22 146.2
-1321, // 23 151.4
-1276, // 24 156.7
-1233, // 25 162.2
-1191, // 26 167.9
-1151, // 27 173.8
-1112, // 28 179.9
-1074, // 29 186.2
-1037, // 30 192.8
-983, // 31 203.5
-949, // 32 210.7
-917, // 33 218.1
-886, // 34 225.7
-856, // 35 233.6
-827, // 36 241.8
-799 // 37 250.3
-};
-
-float freq_ctcss[]=
-{
-067.0, // 00
-071.9, // 01
-074.4, // 02
-077.0, // 03
-079.7, // 04
-082.5, // 05
-085.4, // 06
-088.5, // 07
-091.5, // 08
-094.8, // 09
-097.4, // 10
-100.0, // 11
-103.5, // 12
-107.2, // 13
-110.9, // 14
-114.8, // 15
-118.8, // 16
-123.0, // 17
-127.3, // 18
-131.8, // 19
-136.5, // 20
-141.3, // 21
-146.2, // 22
-151.4, // 23
-156.7, // 24
-162.2, // 25
-167.9, // 26
-173.8, // 27
-179.9, // 28
-186.2, // 29
-192.8, // 30
-203.5, // 31
-210.7 , // 32
-218.1 , // 33
-225.7 , // 34
-233.6 , // 35
-241.8 , // 36
-250.3 // 37
-};
-
-/*
- noise squelch carrier detect filter
-*/
-static const int16_t taps_fir_bpf_noise_1 = 66;
-static const int32_t gain_fir_bpf_noise_1 = 65536;
-static const int16_t coef_fir_bpf_noise_1[] = {
- 139,
- -182,
- -269,
- -66,
- 56,
- 59,
- 250,
- 395,
- -80,
- -775,
- -557,
- 437,
- 779,
- 210,
- -17,
- 123,
- -692,
- -1664,
- -256,
- 2495,
- 2237,
- -1018,
- -2133,
- -478,
- -1134,
- -2711,
- 2642,
- 10453,
- 4010,
- -14385,
- -16488,
- 6954,
- 23030,
- 6954,
- -16488,
- -14385,
- 4010,
- 10453,
- 2642,
- -2711,
- -1134,
- -478,
- -2133,
- -1018,
- 2237,
- 2495,
- -256,
- -1664,
- -692,
- 123,
- -17,
- 210,
- 779,
- 437,
- -557,
- -775,
- -80,
- 395,
- 250,
- 59,
- 56,
- -66,
- -269,
- -182,
- 139,
- 257
-};
-/*
- tbd
-*/
-static const int16_t taps_fir_lpf_3K_1 = 66;
-static const int32_t gain_fir_lpf_3K_1 = 131072;
-static const int16_t coef_fir_lpf_3K_1[] = {
- 259,
- 58,
- -185,
- -437,
- -654,
- -793,
- -815,
- -696,
- -434,
- -48,
- 414,
- 886,
- 1284,
- 1523,
- 1529,
- 1254,
- 691,
- -117,
- -1078,
- -2049,
- -2854,
- -3303,
- -3220,
- -2472,
- -995,
- 1187,
- 3952,
- 7086,
- 10300,
- 13270,
- 15672,
- 17236,
- 17778,
- 17236,
- 15672,
- 13270,
- 10300,
- 7086,
- 3952,
- 1187,
- -995,
- -2472,
- -3220,
- -3303,
- -2854,
- -2049,
- -1078,
- -117,
- 691,
- 1254,
- 1529,
- 1523,
- 1284,
- 886,
- 414,
- -48,
- -434,
- -696,
- -815,
- -793,
- -654,
- -437,
- -185,
- 58,
- 259,
- 393
-};
-
-/**************************************************************
-Filter type: Low Pass
-Filter model: Butterworth
-Filter order: 9
-Sampling Frequency: 8 KHz
-Cut Frequency: 0.250000 KHz
-Coefficents Quantization: 16-bit
-***************************************************************/
-static const int16_t taps_fir_lpf_250_11_64 = 64;
-static const int32_t gain_fir_lpf_250_11_64 = 262144;
-static const int16_t coef_fir_lpf_250_11_64[] =
-{
- 366,
- -3,
- -418,
- -865,
- -1328,
- -1788,
- -2223,
- -2609,
- -2922,
- -3138,
- -3232,
- -3181,
- -2967,
- -2573,
- -1988,
- -1206,
- -228,
- 937,
- 2277,
- 3767,
- 5379,
- 7077,
- 8821,
- 10564,
- 12259,
- 13855,
- 15305,
- 16563,
- 17588,
- 18346,
- 18812,
- 18968,
- 18812,
- 18346,
- 17588,
- 16563,
- 15305,
- 13855,
- 12259,
- 10564,
- 8821,
- 7077,
- 5379,
- 3767,
- 2277,
- 937,
- -228,
- -1206,
- -1988,
- -2573,
- -2967,
- -3181,
- -3232,
- -3138,
- -2922,
- -2609,
- -2223,
- -1788,
- -1328,
- -865,
- -418,
- -3,
- 366,
- 680
-};
-
-// de-emphasis integrator 300 Hz with 8KS/s
-// a0, b1
-static const int16_t taps_int_lpf_300_1_2 = 2;
-static const int32_t gain_int_lpf_300_1_2 = 8182;
-static const int16_t coef_int_lpf_300_1_2[]={
-6878,
-25889
-};
-
-// 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 int16_t coef_int_hpf_4000_1_2[]={
-17610,
--17610,
-2454
-};
-
-
-/*
- 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
-};
-
-
-/*
- ctcss decode filter
-*/
-/**************************************************************
-Filter type: Low Pass
-Filter model: Butterworth
-Filter order: 9
-Sampling Frequency: 8 KHz
-Cut Frequency: 0.250000 KHz
-Coefficents Quantization: 16-bit
-***************************************************************/
-static const int16_t taps_fir_lpf_250_9_66 = 66;
-static const int32_t gain_fir_lpf_250_9_66 = 262144;
-static const int16_t coef_fir_lpf_250_9_66[] =
-{
- 676,
- 364,
- -3,
- -415,
- -860,
--1320,
--1777,
--2209,
--2593,
--2904,
--3119,
--3212,
--3162,
--2949,
--2557,
--1975,
--1198,
- -226,
- 932,
- 2263,
- 3744,
- 5346,
- 7034,
- 8767,
-10499,
-12184,
-13770,
-15211,
-16462,
-17480,
-18234,
-18696,
-18852,
-18696,
-18234,
-17480,
-16462,
-15211,
-13770,
-12184,
-10499,
- 8767,
- 7034,
- 5346,
- 3744,
- 2263,
- 932,
- -226,
--1198,
--1975,
--2557,
--2949,
--3162,
--3212,
--3119,
--2904,
--2593,
--2209,
--1777,
--1320,
- -860,
- -415,
- -3,
- 364,
- 676,
- 927
-};
-/* *************************************************************
-Filter type: Low Pass
-Filter model: Butterworth
-Filter order: 9
-Sampling Frequency: 8 KHz
-Cut Frequency: 0.215 KHz
-Coefficents Quantization: 16-bit
-***************************************************************/
-static const int16_t taps_fir_lpf_215_9_88 = 88;
-static const int32_t gain_fir_lpf_215_9_88 = 524288;
-static const int16_t coef_fir_lpf_215_9_88[] = {
- 2038,
- 2049,
- 1991,
- 1859,
- 1650,
- 1363,
- 999,
- 562,
- 58,
- -502,
--1106,
--1739,
--2382,
--3014,
--3612,
--4153,
--4610,
--4959,
--5172,
--5226,
--5098,
--4769,
--4222,
--3444,
--2430,
--1176,
- 310,
- 2021,
- 3937,
- 6035,
- 8284,
-10648,
-13086,
-15550,
-17993,
-20363,
-22608,
-24677,
-26522,
-28099,
-29369,
-30299,
-30867,
-31058,
-30867,
-30299,
-29369,
-28099,
-26522,
-24677,
-22608,
-20363,
-17993,
-15550,
-13086,
-10648,
- 8284,
- 6035,
- 3937,
- 2021,
- 310,
--1176,
--2430,
--3444,
--4222,
--4769,
--5098,
--5226,
--5172,
--4959,
--4610,
--4153,
--3612,
--3014,
--2382,
--1739,
--1106,
- -502,
- 58,
- 562,
- 999,
- 1363,
- 1650,
- 1859,
- 1991,
- 2049,
- 2038,
- 1966
-};
-// end coef fir_lpf_215_9_88
-//
-/**************************************************************
-Filter type: High Pass
-Filter model: Butterworth
-Filter order: 9
-Sampling Frequency: 8 KHz
-Cut Frequency: 0.300000 KHz
-Coefficents Quantization: 16-bit
-***************************************************************/
-static const int16_t taps_fir_hpf_300_9_66 = 66;
-static const int32_t gain_fir_hpf_300_9_66 = 32768;
-static const int16_t coef_fir_hpf_300_9_66[] =
-{
- -141,
- -114,
- -77,
- -30,
- 23,
- 83,
- 147,
- 210,
- 271,
- 324,
- 367,
- 396,
- 407,
- 396,
- 362,
- 302,
- 216,
- 102,
- -36,
- -199,
- -383,
- -585,
- -798,
--1017,
--1237,
--1452,
--1653,
--1836,
--1995,
--2124,
--2219,
--2278,
-30463,
--2278,
--2219,
--2124,
--1995,
--1836,
--1653,
--1452,
--1237,
--1017,
- -798,
- -585,
- -383,
- -199,
- -36,
- 102,
- 216,
- 302,
- 362,
- 396,
- 407,
- 396,
- 367,
- 324,
- 271,
- 210,
- 147,
- 83,
- 23,
- -30,
- -77,
- -114,
- -141,
- -158
- };
-#endif /* !XPMR_COEF_H */
-/* end of file */
-
-
-
-