blob: c39778f437a391375f52bd885c6fd13ace279da3 [file] [log] [blame]
/******************************************************************************
Copyright (c) 2014-2015 Lantiq Deutschland GmbH
Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
Copyright 2016, Intel Corporation.
For licensing information, see the file 'LICENSE' in the root folder of
this software module.
******************************************************************************/
/**
\file dxs_hsm.c
*/
/* ========================================================================== */
/* Includes */
/* ========================================================================== */
#include "dxs_config.h"
#include "dxs_lib.h"
#include "dxs.h"
#include "dxs_error.h"
#include "dxs_timer.h"
#include "dxs_event.h"
/* ============================= */
/* Configuration */
/* ============================= */
/* Scatter the times used for timeout over the given period with the given
increment between each timer start. This can help to distribute the load
in systems with multiple devices when hook events happen on all lines in
parallel. The increment must be smaller than half the maximum time.
To use this option set DXS_DIAL_SCATTER_MAX to a positive time in ms and
DXS_DIAL_SCATTER_INC to a positive time in ms of maximum half the max time.
Using this option degrades the precision of the timeouts for the on-hook,
off-hook, flash-holdoff and interdigit. The precision of the times for
flash and pulse detection will stay unaffected. */
#define DXS_DIAL_SCATTER_MAX 0 /* ms */
#define DXS_DIAL_SCATTER_INC 0 /* ms */
#if (DXS_DIAL_SCATTER_MAX / 2) < DXS_DIAL_SCATTER_INC
#error Configuration of DIAL_SCATTER incorrect
#endif
/* ========================================================================== */
/* Macro definitions */
/* ========================================================================== */
#if (DXS_DIAL_SCATTER_MAX > 0)
#define DXS_DIAL_SCATTER_INCREASE \
do { \
nScatter += DXS_DIAL_SCATTER_INC; \
if (nScatter > DXS_DIAL_SCATTER_MAX) \
nScatter = 0; \
} while (0)
#else
#define DXS_DIAL_SCATTER_INCREASE
#endif
#if 0
//origin code
#define DXS_MIN_FLASH 80
#define DXS_MAX_FLASH 400
#define DXS_MIN_FLASH_MAKE 200
#define DXS_MIN_DIGIT_LOW 30
#define DXS_MAX_DIGIT_LOW 80
#define DXS_MIN_DIGIT_HIGH 30
#define DXS_MAX_DIGIT_HIGH 80
#define DXS_MIN_OFF_HOOK 40
#define DXS_MIN_ON_HOOK 400
#define DXS_MIN_INTERDIGIT 300
#else
#define DXS_MIN_FLASH 150
#define DXS_MAX_FLASH 700
#define DXS_MIN_FLASH_MAKE 400
#define DXS_MIN_DIGIT_LOW 30
#define DXS_MAX_DIGIT_LOW 80
#define DXS_MIN_DIGIT_HIGH 30
#define DXS_MAX_DIGIT_HIGH 80
#define DXS_MIN_OFF_HOOK 40
#define DXS_MIN_ON_HOOK 710
#define DXS_MIN_INTERDIGIT 300
#endif
/* ========================================================================== */
/* Type definitions */
/* ========================================================================== */
/* ========================================================================== */
/* Global variables */
/* ========================================================================== */
/* ========================================================================== */
/* Function prototypes */
/* ========================================================================== */
/* ========================================================================== */
/* Function implementation */
/* ========================================================================== */
#ifdef DXS_FEAT_HSM
/**
Process an action in the state machines.
In this function the hook, digit and flash state machines are all handled
one after the other. The hook state machine needs to be the first because it
directly changes the on-hook/off-hook states of the other state machines.
This reduces the complexity of code of the other state machines.
\param pChannel Pointer to DXS channel structure.
\param nAction Action to be executed.
\param nTime If action is make or break this parameter holds the
duration since the last hook event in milliseconds.
If the action is timeout this parameter is unused.
*/
static void dxs_dial_Action(DXS_CHANNEL_t * pChannel,
enum ACTION nAction,
uint16_t nTime)
{
DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
DXS_DEVICE_t *pDev = pChannel->pParent;
DXS_Event_t dxs_event;
int32_t bSendPulseEvent;
static uint32_t nScatter = 0; /* library global */
#if 0 /* hook state machine tracing */
printf(" ACTION: %d (hook %d, digit %d, flash %d) time %d\n", nAction,
pDXS_DialData->nHookState,
pDXS_DialData->nDigitState,
pDXS_DialData->nFlashState,
nTime);
#endif
/* Handle the hook-state detection finite state machine. */
switch (pDXS_DialData->nHookState)
{
case HOOK_STATE_ONHOOK:
if (nAction == ACTION_MAKE)
{
pDXS_DialData->nHookState = HOOK_STATE_VALIDATE_OFFHOOK;
DXS_TimerSet(pDXS_DialData->HookTimerID,
pDXS_DialData->nTimeOffhook + nScatter, 0, 1);
DXS_DIAL_SCATTER_INCREASE;
}
break;
case HOOK_STATE_OFFHOOK:
if (nAction == ACTION_BREAK)
{
pDXS_DialData->nHookState = HOOK_STATE_VALIDATE_ONHOOK;
DXS_TimerSet(pDXS_DialData->HookTimerID,
pDXS_DialData->nTimeOnhook + nScatter, 0, 1);
DXS_DIAL_SCATTER_INCREASE;
}
break;
case HOOK_STATE_VALIDATE_OFFHOOK:
if (nAction == ACTION_BREAK)
{
pDXS_DialData->nHookState = HOOK_STATE_ONHOOK;
DXS_TimerStop(pDXS_DialData->HookTimerID);
}
else
if (nAction == ACTION_TIMEOUT_HOOK)
{
pDXS_DialData->nHookState = HOOK_STATE_OFFHOOK;
/* Attention: change of the digit and flash state machine data! */
pDXS_DialData->nDigitState = DIGIT_STATE_OFFHOOK;
pDXS_DialData->nFlashState = FLASH_STATE_OFFHOOK;
pDXS_DialData->nPulseDigit = 0;
pDXS_DialData->bPulseStartSent = 0;
/* DXS event: off-hook */
dxs_event.dev = pDev->nDevNum;
dxs_event.ch = pChannel->nCh;
dxs_event.id = DXS_EVENT_FXS_OFFHOOK;
DXS_EventDispatch(pDev, &dxs_event);
}
break;
case HOOK_STATE_VALIDATE_ONHOOK:
if (nAction == ACTION_MAKE)
{
pDXS_DialData->nHookState = HOOK_STATE_OFFHOOK;
DXS_TimerStop(pDXS_DialData->HookTimerID);
}
else
if (nAction == ACTION_TIMEOUT_HOOK)
{
pDXS_DialData->nHookState = HOOK_STATE_ONHOOK;
/* Attention: change of the digit and flash state machine data! */
pDXS_DialData->nDigitState = DIGIT_STATE_ONHOOK;
pDXS_DialData->nFlashState = FLASH_STATE_ONHOOK;
/* TAPI event: on-hook */
dxs_event.dev = pDev->nDevNum;
dxs_event.ch = pChannel->nCh;
dxs_event.id = DXS_EVENT_FXS_ONHOOK;
DXS_EventDispatch(pDev, &dxs_event);
}
break;
}
/* Handle the pulse dialing detection finite state machine. */
/* Attention: the hook state machine above will do the transitions into and
out of the off-hook state. */
switch (pDXS_DialData->nDigitState)
{
case DIGIT_STATE_ONHOOK:
/* ignore all */
break;
case DIGIT_STATE_OFFHOOK:
if (nAction == ACTION_BREAK)
pDXS_DialData->nDigitState = DIGIT_STATE_VALIDATE_DIGIT_BREAK;
break;
case DIGIT_STATE_VALIDATE_DIGIT_BREAK:
if (nAction == ACTION_MAKE)
{
if ((nTime >= pDXS_DialData->nTimeDigitBreakMin) &&
(nTime <= pDXS_DialData->nTimeDigitBreakMax))
{
pDXS_DialData->nDigitState = DIGIT_STATE_VALIDATE_DIGIT_MAKE;
pDXS_DialData->nPulseDigit += 1;
DXS_TimerSet(pDXS_DialData->InterdigitTimerID,
pDXS_DialData->nTimeInterdigit + nScatter, 0, 1);
DXS_DIAL_SCATTER_INCREASE;
if ((pDXS_DialData->nPulseDigit == 1) &&
(pDXS_DialData->bPulseStartSent == 0))
{
/* report the first validated pulse dial break */
/* Use this to stop a dial tone right after the first pulse. */
dxs_event.dev = pDev->nDevNum;
dxs_event.ch = pChannel->nCh;
dxs_event.id = DXS_EVENT_PULSE_START;
DXS_EventDispatch(pDev, &dxs_event);
/* Do this only for the first pulse after off-hook or flash. */
pDXS_DialData->bPulseStartSent = 1;
}
}
else
{
pDXS_DialData->nDigitState = DIGIT_STATE_OFFHOOK;
pDXS_DialData->nPulseDigit = 0;
}
}
break;
case DIGIT_STATE_VALIDATE_DIGIT_MAKE:
bSendPulseEvent = 0;
if (nAction == ACTION_BREAK)
{
pDXS_DialData->nDigitState = DIGIT_STATE_VALIDATE_DIGIT_BREAK;
DXS_TimerStop(pDXS_DialData->InterdigitTimerID);
if (nTime >= pDXS_DialData->nTimeInterdigit)
{
/* Accept also the time from the hook event for the inter-digit
timeout condition. */
bSendPulseEvent = 1;
}
else
if ((nTime < pDXS_DialData->nTimeDigitMakeMin) ||
(nTime > pDXS_DialData->nTimeDigitMakeMax))
{
pDXS_DialData->nPulseDigit = 0;
}
}
else
if (nAction == ACTION_TIMEOUT_INTERDIGIT)
{
pDXS_DialData->nDigitState = DIGIT_STATE_OFFHOOK;
bSendPulseEvent = 1;
}
/* _no_ else here */
if (bSendPulseEvent)
{
if (pDXS_DialData->nPulseDigit <= 10)
{
/* TAPI event: digit */
dxs_event.dev = pDev->nDevNum;
dxs_event.ch = pChannel->nCh;
dxs_event.id = DXS_EVENT_PULSE_DIGIT;
dxs_event.data.pulse.digit = pDXS_DialData->nPulseDigit;
/* 10 pulses represent digit 0 which has TAPI code 0xB */
if (dxs_event.data.pulse.digit == 10)
dxs_event.data.pulse.digit = 0x0B;
DXS_EventDispatch(pDev, &dxs_event);
}
pDXS_DialData->nPulseDigit = 0;
}
break;
}
/* Handle the flash hook detection finite state machine. */
/* Attention: the hook state machine above will do the transitions into and
out of the off-hook state. */
switch (pDXS_DialData->nFlashState)
{
case FLASH_STATE_ONHOOK:
/* ignore all */
break;
case FLASH_STATE_OFFHOOK:
if (nAction == ACTION_BREAK)
pDXS_DialData->nFlashState = FLASH_STATE_VALIDATE_FLASH_BREAK;
break;
case FLASH_STATE_VALIDATE_FLASH_BREAK:
if (nAction == ACTION_MAKE)
{
if ((nTime >= pDXS_DialData->nTimeFlashBreakMin) &&
(nTime <= pDXS_DialData->nTimeFlashBreakMax))
{
pDXS_DialData->nFlashState = FLASH_STATE_VALIDATE_FLASH_HOLDOFF;
DXS_TimerSet(pDXS_DialData->FlashHoldoffTimerID,
pDXS_DialData->nTimeFlashHoldoff + nScatter, 0, 1);
DXS_DIAL_SCATTER_INCREASE;
}
else
{
pDXS_DialData->nFlashState = FLASH_STATE_OFFHOOK;
}
}
break;
case FLASH_STATE_VALIDATE_FLASH_HOLDOFF:
if (nAction == ACTION_BREAK)
{
pDXS_DialData->nFlashState = FLASH_STATE_VALIDATE_FLASH_BREAK;
DXS_TimerStop(pDXS_DialData->FlashHoldoffTimerID);
}
else
if (nAction == ACTION_TIMEOUT_FLASHHOLDOFF)
{
pDXS_DialData->nFlashState = FLASH_STATE_OFFHOOK;
pDXS_DialData->bPulseStartSent = 0;
/* TAPI event: flash */
dxs_event.dev = pDev->nDevNum;
dxs_event.ch = pChannel->nCh;
dxs_event.id = DXS_EVENT_FXS_FLASH;
DXS_EventDispatch(pDev, &dxs_event);
}
break;
}
#if 0 /* hook state machine tracing */
printf(" (hook %d, digit %d, flash %d) digit %d\n",
pDXS_DialData->nHookState,
pDXS_DialData->nDigitState,
pDXS_DialData->nFlashState,
pDXS_DialData->nPulseDigit);
#endif
}
/**
Hook state machine timer callback function.
\param nArg Argument of timer. This argument is a pointer to the
DXS_CHANNEL_t structure.
*/
void dxs_dial_OnHookTimer(Timer_ID tm, void *arg)
{
DXS_CHANNEL_t *pChannel = (DXS_CHANNEL_t *)arg;
dxs_dial_Action(pChannel, ACTION_TIMEOUT_HOOK, /*dummy*/0);
return;
}
/**
Inter-digit timer callback function.
\param nArg Argument of timer. This argument is a pointer to the
DXS_CHANNEL_t structure.
*/
void dxs_dial_OnInterdigitTimer(Timer_ID tm, void *arg)
{
DXS_CHANNEL_t *pChannel = (DXS_CHANNEL_t *)arg;
dxs_dial_Action(pChannel, ACTION_TIMEOUT_INTERDIGIT, /*dummy*/0);
return;
}
/**
Flash holdoff timer callback function.
\param nArg Argument of timer. This argument is a pointer to the
DXS_CHANNEL_t structure.
*/
void dxs_dial_OnFlashHoldoffTimer(Timer_ID tm, void *arg)
{
DXS_CHANNEL_t *pChannel = (DXS_CHANNEL_t *)arg;
dxs_dial_Action(pChannel, ACTION_TIMEOUT_FLASHHOLDOFF, /*dummy*/0);
return;
}
/**
Flash holdoff timer callback function.
\param nArg Argument of timer. This argument is a pointer to the
DXS_CHANNEL_t structure.
*/
void dxs_dial_OnHookWindowTimer(Timer_ID tm, void *arg)
{
DXS_CHANNEL_t *pChannel = (DXS_CHANNEL_t *)arg;
DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
pDXS_DialData->bHookWindow = 0;
return;
}
/**
Initialize the analog line state machines on the given channel.
Initialize the data structures and resources needed for the
hook state machine.
\param pChannel Pointer to DXS_CHANNEL_t structure.
\return
DXS_statusOk - if successful
DXS_statusTimerCreateError - timer creation failed
\remarks This function is not protected.
*/
int32_t DXS_Dial_Initialise_Unprot (DXS_CHANNEL_t *pChannel)
{
DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
DXS_status_t ret = DXS_statusError;
if (pChannel->flags & DXS_CH_DIAL_DATA_INITIALIZED)
return DXS_statusOk;
/* set default values for the validation times */
pDXS_DialData->nTimeOnhook = DXS_MIN_ON_HOOK;
pDXS_DialData->nTimeOffhook = DXS_MIN_OFF_HOOK;
pDXS_DialData->nTimeInterdigit = DXS_MIN_INTERDIGIT;
pDXS_DialData->nTimeFlashHoldoff = DXS_MIN_FLASH_MAKE;
pDXS_DialData->nTimeDigitMakeMin = DXS_MIN_DIGIT_HIGH;
pDXS_DialData->nTimeDigitMakeMax = DXS_MAX_DIGIT_HIGH;
pDXS_DialData->nTimeDigitBreakMin = DXS_MIN_DIGIT_LOW;
pDXS_DialData->nTimeDigitBreakMax = DXS_MAX_DIGIT_LOW;
pDXS_DialData->nTimeFlashBreakMin = DXS_MIN_FLASH;
pDXS_DialData->nTimeFlashBreakMax = DXS_MAX_FLASH;
/* start all three HSMs in on-hook state */
pDXS_DialData->nHookState = HOOK_STATE_ONHOOK;
pDXS_DialData->nDigitState = DIGIT_STATE_ONHOOK;
pDXS_DialData->nFlashState = FLASH_STATE_ONHOOK;
pDXS_DialData->nPulseDigit = 0;
pDXS_DialData->bPulseStartSent = 0;
/* create hook-state-machine validation timer */
pDXS_DialData->HookTimerID =
DXS_TimerCreate(dxs_dial_OnHookTimer, (void *)pChannel);
if (NULL == pDXS_DialData->HookTimerID)
{
perror("ERROR: Creation of hook-state-machine validation timer failed");
DXS_RETURN(ret);
}
/* create inter-digit timer */
pDXS_DialData->InterdigitTimerID =
DXS_TimerCreate(dxs_dial_OnInterdigitTimer, (void *)pChannel);
if (NULL == pDXS_DialData->InterdigitTimerID)
{
perror("ERROR: Creation of inter-digit timer failed");
DXS_Dial_Cleanup(pChannel);
DXS_RETURN(ret);
}
/* create flash holdoff timer */
pDXS_DialData->FlashHoldoffTimerID =
DXS_TimerCreate(dxs_dial_OnFlashHoldoffTimer, (void *)pChannel);
if (NULL == pDXS_DialData->FlashHoldoffTimerID)
{
perror("ERROR: Creation of flash holdoff timer failed");
DXS_Dial_Cleanup(pChannel);
DXS_RETURN(ret);
}
/* create hook event timestamp wraparound timer */
pDXS_DialData->HookWindowTimerId =
DXS_TimerCreate(dxs_dial_OnHookWindowTimer, (void *)pChannel);
if (NULL == pDXS_DialData->HookWindowTimerId)
{
perror("ERROR: Creation of hook event timestamp wraparound timer failed");
DXS_Dial_Cleanup(pChannel);
DXS_RETURN(ret);
}
pDXS_DialData->bHookWindow = 0;
pDXS_DialData->nLastHookEvtTimestamp = 0;
pDXS_DialData->nTimeOffhookBackup = 0;
pChannel->flags |= DXS_CH_DIAL_DATA_INITIALIZED;
return DXS_statusOk;
}
/**
Cleanup the analog line state machines on the given channel.
Free the resources needed for the hook state machine and
the ground-key state machine.
\param pChannel Pointer to DXS_CHANNEL_t structure.
*/
void DXS_Dial_Cleanup(DXS_CHANNEL_t *pChannel)
{
DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
if (!(pChannel->flags & DXS_CH_DIAL_DATA_INITIALIZED))
return;
/* unconditionally delete all timers */
DXS_TimerDestroy(pDXS_DialData->HookTimerID);
DXS_TimerDestroy(pDXS_DialData->InterdigitTimerID);
DXS_TimerDestroy(pDXS_DialData->FlashHoldoffTimerID);
DXS_TimerDestroy(pDXS_DialData->HookWindowTimerId);
pChannel->flags &= ~DXS_CH_DIAL_DATA_INITIALIZED;
}
/**
Process hook events in the state machines.
\param pChannel Pointer to DXS_CHANNEL_t structure.
\param bHookState - 1: make (off-hook),
- 0: break (on-hook)
\param nTime Duration since the last hook event in ms.
*/
void DXS_Dial_HookEvent (DXS_CHANNEL_t* pChannel,
uint32_t bHookState,
uint16_t nTime)
{
/* make sure dial is initialised on this channel */
if (!(pChannel->flags & DXS_CH_DIAL_DATA_INITIALIZED))
{
/* silently ignore event - this case can happen during startup or
shutdown when an interrupt occurs but DXS_DialData is not initialized.
*/
return;
}
nTime = DXS_Dial_ElapsedTimeSinceLastHook(pChannel, nTime);
/* Note: The hook events actually report a change between the make and break
status of the line. The action reports the new line status. This implies
that before this event the opposite line status was present and that the
time that is reported is the duration that this status was present.
Here make and break is used to make it clear that this is not the hook
status of the phone but the line state which will also change from
pulse dialing and flash hook. */
dxs_dial_Action(pChannel, bHookState ? ACTION_MAKE : ACTION_BREAK, nTime);
return;
}
/**
Set the given hook state unconditionally.
This is used after certain CID sequences which use hook for signaling
purposes. There the hook is not given to this state machine and so the
state needs to be corrected in case of an abort.
\param pChannel Pointer to DXS_CHANNEL_t structure.
\param bHookState - 1: make (off-hook),
- 0: break (on-hook)
*/
void DXS_Dial_HookSet (DXS_CHANNEL_t *pChannel, int32_t bHookState)
{
DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
/* make sure dial is initialised on this channel */
if (!(pChannel->flags & DXS_CH_DIAL_DATA_INITIALIZED))
{
/* silently ignore */
return;
}
/* Handle the hook-state detection finite state machine. */
switch(pDXS_DialData->nHookState)
{
case HOOK_STATE_OFFHOOK:
if (bHookState == 0)
{
pDXS_DialData->nHookState = HOOK_STATE_ONHOOK;
pDXS_DialData->nDigitState = DIGIT_STATE_ONHOOK;
pDXS_DialData->nFlashState = FLASH_STATE_ONHOOK;
/* Do not send a TAPI event here. */
}
break;
case HOOK_STATE_ONHOOK:
if (bHookState == 1)
{
pDXS_DialData->nHookState = HOOK_STATE_OFFHOOK;
pDXS_DialData->nDigitState = DIGIT_STATE_OFFHOOK;
pDXS_DialData->nFlashState = FLASH_STATE_OFFHOOK;
pDXS_DialData->nPulseDigit = 0;
pDXS_DialData->bPulseStartSent = 0;
/* Do not send a TAPI event here. */
}
break;
default:
/* Do nothing in the validation states. */
break;
}
return;
}
/**
Overrides the user configured off-hook time.
This is used by the phone detection to set an off-hook time to suppress
transient hook events that can occur in the off-hook detection state.
\param pChannel Pointer to DXS_CHANNEL_t structure.
\param nTime DXS_DIAL_TIME_NORMAL for normal user configured
value. All other values are used as off-hook time
in milliseconds.
\remarks
The value 0 is invalid for the off-hook time. Here it is used as a marker.
*/
void DXS_Dial_OffhookTime_Override(DXS_CHANNEL_t *pChannel,
uint32_t const nTime)
{
DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
/* make sure that dial is initialised on this channel */
if (pChannel->flags & DXS_CH_DIAL_DATA_INITIALIZED)
{
if (nTime == DXS_DIAL_TIME_NORMAL)
{
if (pDXS_DialData->nTimeOffhookBackup != 0)
{
/* Restore the backed up time value. */
pDXS_DialData->nTimeOffhook = pDXS_DialData->nTimeOffhookBackup;
pDXS_DialData->nTimeOffhookBackup = 0;
}
}
else
{
/* Switch to override - backup time value and set from parameter. */
if (pDXS_DialData->nTimeOffhookBackup == 0)
{
pDXS_DialData->nTimeOffhookBackup = pDXS_DialData->nTimeOffhook;
}
pDXS_DialData->nTimeOffhook = nTime;
}
}
}
/**
Calculate the elapsed time since the last hook event.
This function is to be called with each hook event. It calculates the
elapsed time since the last hook event.
The DxS provides a timestamp with each FW event. However, this timestamp
has a wraparound after ~66 seconds. So an addtional timer is used to prevent
calculation after a wraparound. This function wraps the calculation and
also restarts the timer.
\param pCh Pointer to DxS channel structure.
\param nCurrentTimestamp Current timestamp value from the FW event.
\return
Elapsed time since the last hook event in 1 ms steps.
If the last event happened too long ago or dial is not initialised 0xFFFF is
returned.
*/
uint16_t DXS_Dial_ElapsedTimeSinceLastHook(DXS_CHANNEL_t *pChannel,
uint16_t nCurrentTimestamp)
{
DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
uint16_t elapsedTime;
if (pDXS_DialData->bHookWindow)
{
/* Calculate elapsed time since the saved timestamp. In case the 16-bit
counter had a wraparound since the saved timestamp the calculation
will still be correct because the calculation is done with 16-bit
unsigned data type. This will always result in the positive distance
between the two timestamps. */
elapsedTime = nCurrentTimestamp - pDXS_DialData->nLastHookEvtTimestamp;
}
else
{
elapsedTime = 0xFFFF;
}
/* Start timer, length of timer nominal 65000 ms. A random component is
added to distribute the expiration of the timers in systems with multiple
devices using polling where a lot of timers might be started in parallel.
This time needs to be below the wraparound of the HW timestamp. */
pDXS_DialData->bHookWindow = 1;
DXS_TimerSet(pDXS_DialData->HookWindowTimerId,
65000 + (nCurrentTimestamp & 0x00FF), 0, 1);
/* store the timestamp from this event */
pDXS_DialData->nLastHookEvtTimestamp = nCurrentTimestamp;
return elapsedTime;
}
/**
Sets the validation times for hook, pulse digit and flashhook.
\param pChannel - pointer to DXS channel structure
\param pTime - type of validation setting, min and max time in
milliseconds.
\return
- DXS_status_t
*/
int32_t DXS_Dial_HookValTimeSet(DXS_CHANNEL_t *pChannel,
DXS_HookValTime_t *pTime)
{
DXS_DIAL_DATA_t *pDXS_DialData = &pChannel->DXS_DialData;
/* zero timer value is not allowed -- except for the flash holdoff time */
if ((pTime->nMinTime == 0) &&
(pTime->nType != DXS_HOOK_VT_FLASH_HOLDOFF_TIME))
{
DXS_RETURN(DXS_statusDialZeroParam);
}
/* For the times hook-off, hook-on, interdigit and flash holdoff just
the minimum time is relevant. So do not check the maximum time. */
if ((pTime->nType != DXS_HOOK_VT_HOOKOFF_TIME) &&
(pTime->nType != DXS_HOOK_VT_HOOKON_TIME) &&
(pTime->nType != DXS_HOOK_VT_INTERDIGIT_TIME) &&
(pTime->nType != DXS_HOOK_VT_FLASH_HOLDOFF_TIME))
{
/* check whether min timer value > max timer value */
if (pTime->nMinTime > pTime->nMaxTime)
{
DXS_RETURN(DXS_statusDialMaxMinParam);
}
/* Note: the max timer value cannot be 0 because min > 0 and
min <= max entails that max > 0. */
}
/* set the validation times */
switch (pTime->nType)
{
case DXS_HOOK_VT_HOOKOFF_TIME:
if (pDXS_DialData->nTimeOffhookBackup == 0)
pDXS_DialData->nTimeOffhook = pTime->nMinTime;
else
pDXS_DialData->nTimeOffhookBackup= pTime->nMinTime;
break;
case DXS_HOOK_VT_HOOKON_TIME:
pDXS_DialData->nTimeOnhook = pTime->nMinTime;
break;
case DXS_HOOK_VT_HOOKFLASH_TIME:
pDXS_DialData->nTimeFlashBreakMin = pTime->nMinTime;
pDXS_DialData->nTimeFlashBreakMax = pTime->nMaxTime;
break;
case DXS_HOOK_VT_DIGITLOW_TIME:
pDXS_DialData->nTimeDigitBreakMin = pTime->nMinTime;
pDXS_DialData->nTimeDigitBreakMax = pTime->nMaxTime;
break;
case DXS_HOOK_VT_DIGITHIGH_TIME:
pDXS_DialData->nTimeDigitMakeMin = pTime->nMinTime;
pDXS_DialData->nTimeDigitMakeMax = pTime->nMaxTime;
break;
case DXS_HOOK_VT_INTERDIGIT_TIME:
pDXS_DialData->nTimeInterdigit = pTime->nMinTime;
break;
case DXS_HOOK_VT_FLASH_HOLDOFF_TIME:
pDXS_DialData->nTimeFlashHoldoff = pTime->nMinTime;
break;
}
return DXS_statusOk;
}
/**
Sets the nHookState to HOOK_STATE_ONHOOK.
\param pChannel - pointer to DXS channel structure
*/
extern void DXS_Dial_HookStateSetOnhook(DXS_CHANNEL_t *pChannel)
{
DXS_DIAL_DATA_t *pDXS_DialData;
if (pChannel != NULL)
{
pDXS_DialData = &pChannel->DXS_DialData;
pDXS_DialData->nHookState = HOOK_STATE_ONHOOK;
}
}
#endif /* DXS_FEAT_HSM */