diff options
author | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2003-10-27 17:00:04 +0000 |
---|---|---|
committer | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2003-10-27 17:00:04 +0000 |
commit | 398f396e0f94fb6009a3b27ffbae417becee566b (patch) | |
tree | 2a6d60c717ca01981ed3555ea6e52f4cf1292ac7 /zaptel.c | |
parent | 74768740b2a7dd30d85567e258c9a8c9c75a0cae (diff) |
Create echo "Pretraining" ioctl
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@260 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'zaptel.c')
-rwxr-xr-x | zaptel.c | 87 |
1 files changed, 80 insertions, 7 deletions
@@ -52,6 +52,14 @@ #include <linux/if_ppp.h> #endif +#define __ECHO_STATE_MUTE (1 << 8) +#define ECHO_STATE_IDLE (0) +#define ECHO_STATE_PRETRAINING (1 | (__ECHO_STATE_MUTE)) +#define ECHO_STATE_STARTTRAINING (2 | (__ECHO_STATE_MUTE)) +#define ECHO_STATE_AWAITINGECHO (3 | (__ECHO_STATE_MUTE)) +#define ECHO_STATE_TRAINING (4 | (__ECHO_STATE_MUTE)) +#define ECHO_STATE_ACTIVE (5) + /* #define BUF_MUNGE */ /* Grab fasthdlc with tables */ @@ -1791,6 +1799,9 @@ static int initialize_channel(struct zt_chan *chan) ec = chan->ec; chan->ec = NULL; chan->echocancel = 0; + chan->echostate = ECHO_STATE_IDLE; + chan->echolastupdate = 0; + chan->echotimer = 0; chan->txdisable = 0; chan->rxdisable = 0; @@ -2613,6 +2624,8 @@ static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int c mychan.confna, mychan._confn, mychan.confmode, mychan.confmute); printk("ec: %08x, echocancel: %d, deflaw: %d, xlaw: %08x\n", (int) mychan.ec, mychan.echocancel, mychan.deflaw, (int) mychan.xlaw); + printk("echostate: %02x, echotimer: %d, echolastupdate: %d\n", + (int) mychan.echostate, mychan.echotimer, mychan.echolastupdate); printk("itimer: %d, otimer: %d, ringdebtimer: %d\n\n", mychan.itimer,mychan.otimer,mychan.ringdebtimer); #if 0 @@ -3551,6 +3564,9 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm tec = chan->ec; chan->ec = NULL; chan->echocancel = 0; + chan->echostate = ECHO_STATE_IDLE; + chan->echolastupdate = 0; + chan->echotimer = 0; /* Make sure there's no gain */ if (chan->gainalloc) kfree(chan->rxgain); @@ -3621,6 +3637,9 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm tec = chan->ec; chan->echocancel = j; chan->ec = ec; + chan->echostate = ECHO_STATE_IDLE; + chan->echolastupdate = 0; + chan->echotimer = 0; echo_can_disable_detector_init(&chan->txecdis); echo_can_disable_detector_init(&chan->rxecdis); spin_unlock_irqrestore(&chan->lock, flags); @@ -3631,11 +3650,26 @@ static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cm tec = chan->ec; chan->echocancel = 0; chan->ec = NULL; + chan->echostate = ECHO_STATE_IDLE; + chan->echolastupdate = 0; + chan->echotimer = 0; spin_unlock_irqrestore(&chan->lock, flags); if (tec) echo_can_free(tec); } break; + case ZT_ECHOTRAIN: + get_user(j, (int *)data); /* get pre-training time from user */ + if ((j < 0) || (j >= ZT_MAX_PRETRAINING)) + return -EINVAL; + j <<= 3; + if (chan->ec) { + /* Start pretraining stage */ + chan->echostate = ECHO_STATE_PRETRAINING; + chan->echotimer = j; + } else + return -EINVAL; + break; case ZT_SETTXBITS: if (chan->sig != ZT_SIG_CAS) return -EINVAL; @@ -4112,6 +4146,9 @@ static inline void __zt_process_getaudio_chunk(struct zt_chan *ss, unsigned char if (echo_can_disable_detector_update(&ms->txecdis, getlin[x])) { printk("zaptel Disabled echo canceller because of tone (tx) on channel %d\n", ss->channo); ms->echocancel = 0; + ms->echostate = ECHO_STATE_IDLE; + ms->echolastupdate = 0; + ms->echotimer = 0; kfree(ms->ec); ms->ec = NULL; break; @@ -4244,9 +4281,14 @@ static inline void __zt_process_getaudio_chunk(struct zt_chan *ss, unsigned char break; } } - if (ms->confmute) { + if (ms->confmute || (ms->echostate & __ECHO_STATE_MUTE)) { txb[0] = ZT_LIN2X(0, ms); memset(txb + 1, txb[0], ZT_CHUNKSIZE - 1); + if (ms->echostate == ECHO_STATE_STARTTRAINING) { + /* Transmit impulse now */ + txb[0] = ZT_LIN2X(16384, ms); + ms->echostate = ECHO_STATE_AWAITINGECHO; + } } /* save value from last chunk */ memcpy(ms->getlin_lastchunk, ms->getlin, ZT_CHUNKSIZE * sizeof(short)); @@ -4405,7 +4447,7 @@ out in the later versions, and is put back now. */ memset(txb, ZT_LIN2X(0, ms), bytes); /* Lastly we use silence on telephony channels */ bytes = 0; } - } + } } static inline void rbs_itimer_expire(struct zt_chan *chan) @@ -4705,7 +4747,7 @@ void zt_rbsbits(struct zt_chan *chan, int cursig) void zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char *txchunk) { - short rxlin; + short rxlin, txlin; int x; long flags; spin_lock_irqsave(&ss->lock, flags); @@ -4714,10 +4756,38 @@ void zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char #if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP) zt_kernel_fpu_begin(); #endif - for (x=0;x<ZT_CHUNKSIZE;x++) { - rxlin = ZT_XLAW(rxchunk[x], ss); - rxlin = echo_can_update(ss->ec, ZT_XLAW(txchunk[x], ss), rxlin); - rxchunk[x] = ZT_LIN2X((int)rxlin, ss); + if (ss->echostate & __ECHO_STATE_MUTE) { + /* Special stuff for training the echo can */ + for (x=0;x<ZT_CHUNKSIZE;x++) { + rxlin = ZT_XLAW(rxchunk[x], ss); + txlin = ZT_XLAW(txchunk[x], ss); + if (ss->echostate == ECHO_STATE_PRETRAINING) { + if (--ss->echotimer <= 0) { + ss->echotimer = 0; + ss->echostate = ECHO_STATE_STARTTRAINING; + } + } + if ((ss->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) { + ss->echolastupdate = 0; + ss->echostate = ECHO_STATE_TRAINING; + } + if (ss->echostate == ECHO_STATE_TRAINING) { + if (echo_can_traintap(ss->ec, ss->echolastupdate++, rxlin)) { +#if 0 + printk("Finished training (%d taps trained)!\n", ss->echolastupdate); +#endif + ss->echostate = ECHO_STATE_ACTIVE; + } + } + rxlin = 0; + rxchunk[x] = ZT_LIN2X((int)rxlin, ss); + } + } else { + for (x=0;x<ZT_CHUNKSIZE;x++) { + rxlin = ZT_XLAW(rxchunk[x], ss); + rxlin = echo_can_update(ss->ec, ZT_XLAW(txchunk[x], ss), rxlin); + rxchunk[x] = ZT_LIN2X((int)rxlin, ss); + } } #if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP) kernel_fpu_end(); @@ -4801,6 +4871,9 @@ static inline void __zt_process_putaudio_chunk(struct zt_chan *ss, unsigned char if (echo_can_disable_detector_update(&ms->rxecdis, putlin[x])) { printk("zaptel Disabled echo canceller because of tone (rx) on channel %d\n", ss->channo); ms->echocancel = 0; + ms->echostate = ECHO_STATE_IDLE; + ms->echolastupdate = 0; + ms->echotimer = 0; kfree(ms->ec); ms->ec = NULL; break; |