wctdm24xxp: Use interval for debouncing FXO battery.

Allows the driver the option of not calling the misc function for every
frame.  This is part of preparation for moving misc processing out of
the interrupt handler.  Also use a state machine for the various battery
states to unify the technique for debouncing the various signals in the
driver.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10169 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
Shaun Ruffell 2011-08-30 16:38:36 +00:00
parent cea4b8bda3
commit 874b76bd22
2 changed files with 148 additions and 113 deletions

View File

@ -1940,13 +1940,141 @@ static void wctdm_fxo_ring_detect(struct wctdm *wc, struct wctdm_module *mod)
}
}
#define MS_PER_CHECK_HOOK 1
static void
wctdm_check_battery_lost(struct wctdm *wc, struct wctdm_module *const mod)
{
struct fxo *const fxo = &mod->mod.fxo;
/* possible existing states:
battery lost, no debounce timer
battery lost, debounce timer (going to battery present)
battery present or unknown, no debounce timer
battery present or unknown, debounce timer (going to battery lost)
*/
switch (fxo->battery_state) {
case BATTERY_DEBOUNCING_PRESENT:
/* we were going to BATTERY_PRESENT, but
* battery was lost again. */
fxo->battery_state = BATTERY_LOST;
break;
case BATTERY_UNKNOWN:
mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK);
case BATTERY_DEBOUNCING_PRESENT_ALARM: /* intentional drop through */
case BATTERY_PRESENT:
fxo->battery_state = BATTERY_DEBOUNCING_LOST;
fxo->battdebounce_timer = wc->framecount + battdebounce;
break;
case BATTERY_DEBOUNCING_LOST:
if (time_after(wc->framecount, fxo->battdebounce_timer)) {
if (debug) {
dev_info(&wc->vb.pdev->dev,
"NO BATTERY on %d/%d!\n",
wc->aspan->span.spanno,
mod->card + 1);
}
#ifdef JAPAN
if (!wc->ohdebounce && wc->offhook) {
dahdi_hooksig(wc->aspan->chans[card],
DAHDI_RXSIG_ONHOOK);
if (debug) {
dev_info(&wc->vb.pdev->dev,
"Signalled On Hook\n");
}
#ifdef ZERO_BATT_RING
wc->onhook++;
#endif
}
#else
mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK);
#endif
/* set the alarm timer, taking into account that part
* of its time period has already passed while
* debouncing occurred */
fxo->battery_state = BATTERY_DEBOUNCING_LOST_ALARM;
fxo->battdebounce_timer = wc->framecount +
battalarm - battdebounce;
}
break;
case BATTERY_DEBOUNCING_LOST_ALARM:
if (time_after(wc->framecount, fxo->battdebounce_timer)) {
fxo->battery_state = BATTERY_LOST;
dahdi_alarm_channel(get_dahdi_chan(wc, mod),
DAHDI_ALARM_RED);
}
break;
case BATTERY_LOST:
break;
}
}
static void
wctdm_check_battery_present(struct wctdm *wc, struct wctdm_module *const mod)
{
struct fxo *const fxo = &mod->mod.fxo;
switch (fxo->battery_state) {
case BATTERY_DEBOUNCING_PRESENT:
if (time_after(jiffies, fxo->battdebounce_timer)) {
if (debug) {
dev_info(&wc->vb.pdev->dev,
"BATTERY on %d/%d (%s)!\n",
wc->aspan->span.spanno, mod->card + 1,
(fxo->line_voltage_status < 0) ?
"-" : "+");
}
#ifdef ZERO_BATT_RING
if (wc->onhook) {
wc->onhook = 0;
dahdi_hooksig(wc->aspan->chans[card],
DAHDI_RXSIG_OFFHOOK);
if (debug) {
dev_info(&wc->vb.pdev->dev,
"Signalled Off Hook\n");
}
}
#else
mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK);
#endif
/* set the alarm timer, taking into account that part
* of its time period has already passed while
* debouncing occurred */
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_ALARM;
fxo->battdebounce_timer = jiffies +
msecs_to_jiffies(battalarm - battdebounce);
}
break;
case BATTERY_DEBOUNCING_PRESENT_ALARM:
if (time_after(jiffies, fxo->battdebounce_timer)) {
fxo->battery_state = BATTERY_PRESENT;
dahdi_alarm_channel(get_dahdi_chan(wc, mod),
DAHDI_ALARM_NONE);
}
break;
case BATTERY_PRESENT:
break;
case BATTERY_DEBOUNCING_LOST:
/* we were going to BATTERY_LOST, but battery appeared again,
* so clear the debounce timer */
fxo->battery_state = BATTERY_PRESENT;
break;
case BATTERY_UNKNOWN:
mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK);
case BATTERY_LOST: /* intentional drop through */
case BATTERY_DEBOUNCING_LOST_ALARM:
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT;
fxo->battdebounce_timer = jiffies +
msecs_to_jiffies(battdebounce);
break;
}
}
static void
wctdm_voicedaa_check_hook(struct wctdm *wc, struct wctdm_module *const mod)
{
#define MS_PER_CHECK_HOOK 1
signed char b;
unsigned int abs_voltage;
u8 abs_voltage;
struct fxo *const fxo = &mod->mod.fxo;
/* Try to track issues that plague slot one FXO's */
@ -1962,15 +2090,14 @@ wctdm_voicedaa_check_hook(struct wctdm *wc, struct wctdm_module *const mod)
wctdm_fxo_ring_detect(wc, mod);
}
b = fxo->line_voltage_status;
abs_voltage = abs(b);
abs_voltage = abs(fxo->line_voltage_status);
if (fxovoltage && time_after(wc->framecount, fxo->display_fxovoltage)) {
/* Every 100 ms */
fxo->display_fxovoltage = wc->framecount + 100;
dev_info(&wc->vb.pdev->dev,
"Port %d: Voltage: %d Debounce %d\n",
mod->card + 1, b, fxo->battdebounce);
"Port %d: Voltage: %d\n",
mod->card + 1, fxo->line_voltage_status);
}
if (unlikely(DAHDI_RXSIG_INITIAL == get_dahdi_chan(wc, mod)->rxhooksig)) {
@ -1985,125 +2112,31 @@ wctdm_voicedaa_check_hook(struct wctdm *wc, struct wctdm_module *const mod)
* to force us to report it again via dahdi_hooksig.
*
*/
fxo->battery = BATTERY_UNKNOWN;
fxo->battery_state = BATTERY_UNKNOWN;
}
if (abs_voltage < battthresh) {
/* possible existing states:
battery lost, no debounce timer
battery lost, debounce timer (going to battery present)
battery present or unknown, no debounce timer
battery present or unknown, debounce timer (going to battery lost)
*/
fxo->lastpol = fxo->polarity;
fxo->polaritydebounce = 0;
if (fxo->battery == BATTERY_LOST) {
if (fxo->battdebounce) {
/* we were going to BATTERY_PRESENT, but battery was lost again,
so clear the debounce timer */
fxo->battdebounce = 0;
}
wctdm_check_battery_lost(wc, mod);
} else {
if (fxo->battdebounce) {
/* going to BATTERY_LOST, see if we are there yet */
if (--fxo->battdebounce == 0) {
fxo->battery = BATTERY_LOST;
if (debug)
dev_info(&wc->vb.pdev->dev, "NO BATTERY on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
#ifdef JAPAN
if (!wc->ohdebounce && wc->offhook) {
dahdi_hooksig(wc->aspan->chans[card], DAHDI_RXSIG_ONHOOK);
if (debug)
dev_info(&wc->vb.pdev->dev, "Signalled On Hook\n");
#ifdef ZERO_BATT_RING
wc->onhook++;
#endif
}
#else
mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK);
/* set the alarm timer, taking into account that part of its time
period has already passed while debouncing occurred */
fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK;
#endif
}
} else {
/* start the debounce timer to verify that battery has been lost */
fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK;
}
}
} else {
/* possible existing states:
battery lost or unknown, no debounce timer
battery lost or unknown, debounce timer (going to battery present)
battery present, no debounce timer
battery present, debounce timer (going to battery lost)
*/
if (fxo->battery == BATTERY_PRESENT) {
if (fxo->battdebounce) {
/* we were going to BATTERY_LOST, but battery appeared again,
so clear the debounce timer */
fxo->battdebounce = 0;
}
} else {
if (fxo->battdebounce) {
/* going to BATTERY_PRESENT, see if we are there yet */
if (--fxo->battdebounce == 0) {
fxo->battery = BATTERY_PRESENT;
if (debug) {
dev_info(&wc->vb.pdev->dev,
"BATTERY on %d/%d (%s)!\n",
wc->aspan->span.spanno,
mod->card + 1,
(b < 0) ? "-" : "+");
}
#ifdef ZERO_BATT_RING
if (wc->onhook) {
wc->onhook = 0;
mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK);
if (debug)
dev_info(&wc->vb.pdev->dev, "Signalled Off Hook\n");
}
#else
mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK);
#endif
/* set the alarm timer, taking into account that part of its time
period has already passed while debouncing occurred */
fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK;
}
} else {
/* start the debounce timer to verify that battery has appeared */
fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK;
}
}
wctdm_check_battery_present(wc, mod);
if (fxo->lastpol >= 0) {
if (b < 0) {
if (fxo->line_voltage_status < 0) {
fxo->lastpol = -1;
fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK;
}
}
if (fxo->lastpol <= 0) {
if (b > 0) {
if (fxo->line_voltage_status > 0) {
fxo->lastpol = 1;
fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK;
}
}
}
if (fxo->battalarm) {
if (--fxo->battalarm == 0) {
/* the alarm timer has expired, so update the battery alarm state
for this channel */
dahdi_alarm_channel(get_dahdi_chan(wc, mod),
(fxo->battery == BATTERY_LOST) ?
DAHDI_ALARM_RED :
DAHDI_ALARM_NONE);
}
}
if (fxo->polaritydebounce) {
fxo->polaritydebounce--;
if (fxo->polaritydebounce < 1) {
@ -2124,12 +2157,12 @@ wctdm_voicedaa_check_hook(struct wctdm *wc, struct wctdm_module *const mod)
* where the voltage is over the neon limit but
* does not vary greatly from the last reading
*/
if (fxo->battery == 1 &&
if (fxo->battery_state == BATTERY_PRESENT &&
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;
(fxo->line_voltage_status >= fxo->neonmwi_last_voltage - neonmwi_envelope &&
fxo->line_voltage_status <= fxo->neonmwi_last_voltage + neonmwi_envelope))) {
fxo->neonmwi_last_voltage = fxo->line_voltage_status;
if (NEONMWI_ON_DEBOUNCE == fxo->neonmwi_debounce) {
fxo->neonmwi_offcounter = neonmwi_offlimit_cycles;
if (0 == fxo->neonmwi_state) {

View File

@ -105,7 +105,11 @@ struct calregs {
enum battery_state {
BATTERY_UNKNOWN = 0,
BATTERY_DEBOUNCING_PRESENT,
BATTERY_DEBOUNCING_PRESENT_ALARM,
BATTERY_PRESENT,
BATTERY_DEBOUNCING_LOST,
BATTERY_DEBOUNCING_LOST_ALARM,
BATTERY_LOST,
};
@ -159,9 +163,6 @@ struct fxo {
u8 hook_ring_shadow;
s8 line_voltage_status;
int offhook;
int battdebounce;
int battalarm;
enum battery_state battery;
int lastpol;
int polarity;
int polaritydebounce;
@ -171,6 +172,7 @@ struct fxo {
unsigned int neonmwi_offcounter;
unsigned long display_fxovoltage;
unsigned long ringdebounce_timer;
unsigned long battdebounce_timer;
};
struct fxs {