[zaptel-commits] dbailey: branch 1.4 r4479 - /branches/1.4/kernel/wctdm24xxp/

SVN commits to the Zaptel project zaptel-commits at lists.digium.com
Wed Aug 13 14:06:05 CDT 2008


Author: dbailey
Date: Wed Aug 13 14:06:04 2008
New Revision: 4479

URL: http://svn.digium.com/view/zaptel?view=rev&rev=4479
Log:
Port in the NEON MWI detection from the AA50 into the wctdm24xxp driver

Modified:
    branches/1.4/kernel/wctdm24xxp/base.c
    branches/1.4/kernel/wctdm24xxp/wctdm24xxp.h

Modified: branches/1.4/kernel/wctdm24xxp/base.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/kernel/wctdm24xxp/base.c?view=diff&rev=4479&r1=4478&r2=4479
==============================================================================
--- branches/1.4/kernel/wctdm24xxp/base.c (original)
+++ branches/1.4/kernel/wctdm24xxp/base.c Wed Aug 13 14:06:04 2008
@@ -193,6 +193,17 @@
 static int ringdebounce = DEFAULT_RING_DEBOUNCE;
 static int fwringdetect = 0;
 static int latency = VOICEBUS_DEFAULT_LATENCY;
+
+#define NEONMWI_ON_DEBOUNCE	(3)
+#define MS_PER_HOOKCHECK	(1)
+
+static int neonmwi_monitor = 0; 	/* Note: this causes use of full wave ring detect */
+static int neonmwi_level = 75;		/* neon mwi trip voltage */
+static int neonmwi_envelope = 10;
+static int neonmwi_offlimit = 16000;  /* Time in milliseconds the monitor is checked before saying no message is waiting */
+
+static int neonmwi_offlimit_cycles;  /* Time in milliseconds the monitor is checked before saying no message is waiting */
+
 #ifdef VPM_SUPPORT
 static int vpmsupport = 1;
 static int vpmdtmfsupport = 0;
@@ -1130,6 +1141,7 @@
 	unsigned char res;
 	signed char b;
 	struct fxo *fxo = &wc->mods[card].fxo;
+	unsigned int abs_voltage;
 
 	/* Try to track issues that plague slot one FXO's */
 	b = wc->cmdq[card].isrshadow[0];	/* Hook/Ring state */
@@ -1142,29 +1154,52 @@
 			wctdm_setreg_intr(wc, card, 5, 0x8);
 	}
 	if (!fxo->offhook) {
-		if (fwringdetect) {
+		if(fwringdetect || neonmwi_monitor) {
+			/* Look for ring status bits (Ring Detect Signal Negative and
+			 * Ring Detect Signal Positive) to transition back and forth
+			 * some number of times to indicate that a ring is occurring.
+			 * Provide some number of samples to allow for the transitions
+			 * to occur before ginving up.
+			 * NOTE: neon mwi voltages will trigger one of these bits to go active
+			 * but not to have transitions between the two bits (i.e. no negative
+			 * to positive or positive to negative transversals )
+			 */ 
 			res =  wc->cmdq[card].isrshadow[0] & 0x60;
-			if (fxo->ringdebounce--) {
-				if (res && (res != fxo->lastrdtx) && (fxo->battery == 1)) {
-					if (!fxo->wasringing) {
+			if (0 == wc->mods[card].fxo.wasringing) {
+				if (res) {
+					/* Look for positive/negative crossings in ring status reg */
+					fxo->wasringing = 2; 
+					fxo->ringdebounce = ringdebounce /16;
+					fxo->lastrdtx = res;
+					fxo->lastrdtx_count = 0;
+				}
+			} else if (2 == fxo->wasringing) {
+				/* If ring detect signal has transversed */
+				if (res && res != fxo->lastrdtx) {
+					/* if there are at least 3 ring polarity transversals */
+					if(++fxo->lastrdtx_count >= 2) {
 						fxo->wasringing = 1;
 						if (debug)
-							printk("RING on %d/%d!\n", wc->span.spanno, card + 1);
+							printk("FW RING on %d/%d!\n", wc->span.spanno, card + 1);
 						zt_hooksig(&wc->chans[card], ZT_RXSIG_RING);
+						fxo->ringdebounce = ringdebounce / 16;
+					} else {
+						fxo->lastrdtx = res;
+						fxo->ringdebounce = ringdebounce / 16;
 					}
-					fxo->lastrdtx = res;
-					fxo->ringdebounce = 10;
-				} else if (!res) {
-					if ((fxo->ringdebounce == 0) && fxo->wasringing) {
-						fxo->wasringing = 0;
-						if (debug)
-							printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1);
-						zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
-					}
+				/* ring indicator (positve or negative) has not transitioned, check debounce count */
+				} else if (--fxo->ringdebounce == 0) {
+					fxo->wasringing = 0;
 				}
-			} else if (res && (fxo->battery == BATTERY_PRESENT)) {
-				fxo->lastrdtx = res;
-				fxo->ringdebounce = 10;
+			} else {  /* I am in ring state */
+				if (res) { /* If any ringdetect bits are still active */
+					fxo->ringdebounce = ringdebounce / 16;
+				} else if (--fxo->ringdebounce == 0) {
+					fxo->wasringing = 0;
+					if (debug)
+						printk("FW NO RING on %d/%d!\n", wc->span.spanno, card + 1);
+					zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
+				}
 			}
 		} else {
 			res =  wc->cmdq[card].isrshadow[0];
@@ -1196,6 +1231,7 @@
 	}
 
 	b = wc->cmdq[card].isrshadow[1]; /* Voltage */
+	abs_voltage = abs(b);
 
 	if (fxovoltage) {
 		if (!(wc->intcount % 100)) {
@@ -1204,7 +1240,7 @@
 		}
 	}
 
-	if (abs(b) < battthresh) {
+	if (abs_voltage < battthresh) {
 		/* possible existing states:
 		   battery lost, no debounce timer
 		   battery lost, debounce timer (going to battery present)
@@ -1322,6 +1358,48 @@
 				zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY);
 			fxo->polarity = fxo->lastpol;
 		    }
+		}
+	}
+
+	/* Look for neon mwi pulse */
+	if (neonmwi_monitor && !wc->mods[card].fxo.offhook) {
+		/* Look for 4 consecutive voltage readings
+		 * where the voltage is over the neon limit but
+		 * does not vary greatly from the last reading
+		 */
+		if (fxo->battery == 1 &&
+			abs_voltage > neonmwi_level &&
+				(0 == fxo->neonmwi_last_voltage ||
+					(b >= fxo->neonmwi_last_voltage - neonmwi_envelope &&
+					 b <= fxo->neonmwi_last_voltage + neonmwi_envelope ))) {
+			fxo->neonmwi_last_voltage = b;
+			if (NEONMWI_ON_DEBOUNCE == fxo->neonmwi_debounce) {
+				fxo->neonmwi_offcounter = neonmwi_offlimit_cycles;
+				if(0 == fxo->neonmwi_state) {
+					zt_qevent_lock(&wc->chans[card], ZT_EVENT_NEONMWI_ACTIVE);
+					fxo->neonmwi_state = 1;
+					if (debug)
+						printk("NEON MWI active for card %d\n", card+1);
+				}
+				fxo->neonmwi_debounce++;  /* terminate the processing */
+			} else if (NEONMWI_ON_DEBOUNCE > fxo->neonmwi_debounce) {
+				fxo->neonmwi_debounce++;
+			} else { /* Insure the count gets reset */
+				fxo->neonmwi_offcounter = neonmwi_offlimit_cycles;
+			}
+		} else {
+			fxo->neonmwi_debounce = 0;
+			fxo->neonmwi_last_voltage = 0;
+		}
+		/* If no neon mwi pulse for given period of time, indicte no neon mwi state */
+		if (fxo->neonmwi_state && 0 < fxo->neonmwi_offcounter ) {
+			fxo->neonmwi_offcounter--;
+			if (0 == fxo->neonmwi_offcounter) {
+				zt_qevent_lock(&wc->chans[card], ZT_EVENT_NEONMWI_INACTIVE);
+				fxo->neonmwi_state = 0;
+				if (debug)
+					printk("NEON MWI cleared for card %d\n", card+1);
+			}
 		}
 	}
 #undef MS_PER_CHECK_HOOK
@@ -1876,7 +1954,7 @@
 	reg16 |= (fxo_modes[_opermode].rt);
 	wctdm_setreg(wc, card, 16, reg16);
 
-	if(fwringdetect) {
+	if(fwringdetect || neonmwi_monitor) {
 		/* Enable ring detector full-wave rectifier mode */
 		wctdm_setreg(wc, card, 18, 2);
 		wctdm_setreg(wc, card, 24, 0);
@@ -2599,6 +2677,9 @@
 static int wctdm_open(struct zt_chan *chan)
 {
 	struct wctdm *wc = chan->pvt;
+	int channo = chan->chanpos - 1;
+	unsigned long flags;
+
 	if (!(wc->cardflag & (1 << (chan->chanpos - 1))))
 		return -ENODEV;
 	if (wc->dead)
@@ -2608,7 +2689,14 @@
 	MOD_INC_USE_COUNT;
 #else
 	try_module_get(THIS_MODULE);
-#endif	
+#endif
+	/* Reset the mwi indicators */
+	spin_lock_irqsave(&wc->reglock, flags);
+	wc->mods[channo].fxo.neonmwi_debounce = 0;
+	wc->mods[channo].fxo.neonmwi_offcounter = 0;
+	wc->mods[channo].fxo.neonmwi_state = 0;
+	spin_unlock_irqrestore(&wc->reglock, flags);
+	
 	return 0;
 }
 
@@ -3762,6 +3850,8 @@
 	int y;
 	int ret;
 
+	neonmwi_offlimit_cycles = neonmwi_offlimit /MS_PER_HOOKCHECK;
+
 retry:
 	wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL);
 	if (!wc) {
@@ -4012,6 +4102,10 @@
 module_param(ringdebounce, int, 0600);
 module_param(fwringdetect, int, 0600);
 module_param(latency, int, 0600);
+module_param(neonmwi_monitor, int, 0600);
+module_param(neonmwi_level, int, 0600);
+module_param(neonmwi_envelope, int, 0600);
+module_param(neonmwi_offlimit, int, 0600);
 #ifdef VPM_SUPPORT
 module_param(vpmsupport, int, 0600);
 module_param(vpmdtmfsupport, int, 0600);
@@ -4041,6 +4135,10 @@
 MODULE_PARM(fxsrxgain, "i");
 MODULE_PARM(ringdebounce, "i");
 MODULE_PARM(fwringdetect, "i");
+MODULE_PARM(neonmwi_monitor, "i");
+MODULE_PARM(neonmwi_level, "i");
+MODULE_PARM(neonmwi_envelope, "i");
+MODULE_PARM(neonmwi_offlimit, "i");
 #ifdef VPM_SUPPORT
 MODULE_PARM(vpmsupport, "i");
 MODULE_PARM(vpmdtmfsupport, "i");

Modified: branches/1.4/kernel/wctdm24xxp/wctdm24xxp.h
URL: http://svn.digium.com/view/zaptel/branches/1.4/kernel/wctdm24xxp/wctdm24xxp.h?view=diff&rev=4479&r1=4478&r2=4479
==============================================================================
--- branches/1.4/kernel/wctdm24xxp/wctdm24xxp.h (original)
+++ branches/1.4/kernel/wctdm24xxp/wctdm24xxp.h Wed Aug 13 14:06:04 2008
@@ -220,6 +220,7 @@
 		struct fxo {
 			int wasringing;
 			int lastrdtx;
+			int lastrdtx_count;
 			int ringdebounce;
 			int offhook;
 			int battdebounce;
@@ -228,6 +229,11 @@
 			int lastpol;
 			int polarity;
 			int polaritydebounce;
+			int neonmwi_state;
+			int neonmwi_last_voltage;
+			unsigned int neonmwi_debounce;
+			unsigned int neonmwi_offcounter;
+
 		} fxo;
 		struct fxs {
 			int oldrxhook;




More information about the zaptel-commits mailing list