Multiple timers


#1

How to run multiple timers at the same time ?
I need to use 3 timers.

Mark


#2

Hi Mark,

I don’t see a problem here… Why not just call adl_tmrSubscribe() three times?

Best Regards,
Jan


#3

Yes, limitation is around 30 timers at the same time… no problem with 3 timers !!


#4

…and if you do need >30 (or whatever) timers, just use the standard approach of having one “real” ADL timer to generate your timebase “tick”, and maintain a number of counters clocked by that “tick” to implement your other timed requirements…


#5

Another good reason is the need of retriggerable timers.
My app is “presetting” the counter to its initial val - unfortunately the ADL timers do not provide this funcionality.

Heinz


#6

Absolutely!

It is a very major omission that Open-AT does not provide retrigerable timers!! :open_mouth: :angry:

The retrigerable timer is such a fundamental requirement for any comms protocol work (ie, timeouts), that it is quite incredible that Open-AT doesn’t provide them!! :open_mouth: :open_mouth: :angry:

So there’s a new functionality request: wavecom.com/modules/movie/sc … php?p=4902


#7

Since it is quite simple, but lot of work to write I’m going to share 8)

/****************************************************************************
 *
 *	File:	timer.h
 *
 *  Object:	header file for timer system
 *
 ****************************************************************************
 *
 * ----------+--------+----------------+-------------------------------------
 *  06/11/05 | HLI    | 1.0            | Initial revision.                  
 * ----------+--------+----------------+-------------------------------------
 *
 ***************************************************************************/

#ifndef __TIMER_H__
#define __TIMER_H__

#include "adl_global.h"

#define MAX_TIMERS		40

typedef enum TimerStatus_e
{
	TIMER_FREE = 0,
	TIMER_RUNNING,
	TIMER_EXPIRED,
	TIMER_STOPPED
} TimerStatus_e;

typedef enum TimerType_e
{
	TIMER_NONE = 0,
	TIMER_ONESHOT,
	TIMER_CYCLIC
} TimerType_e;

typedef struct //sw_timers_t
{
	s8				timer;
	TimerStatus_e	state;
	TimerType_e		type;
	u32				reload;
	void			(*callback)( s8 timer );
	u32				count;
} sw_timers_t;

void	timer_init ( void );
void	timer_remove ( void );

// sw realized timer system
void	SwTmr_Init			( void );
s8		SwTmr_StartTimer	( s8 timer, TimerType_e type, u32 timeout, void (*callback)( s8 timer ) );
void	SwTmr_SetStatus		( s8 timer, TimerStatus_e status );
void	SwTmr_StopTimer		( s8 timer );
void	SwTmr_ContinueTimer ( s8 timer );
void	SwTmr_KillTimer		( s8 timer );
void	SwTmr_RetriggerTimer( s8 timer );
void	SwTmr_SetInterval ( s8 timer, u16 new_interval );
#endif

and

/****************************************************************************
 *
 *	File:	timer.c
 *
 *  Object:	functions related to the timer subsystem
 *
 ****************************************************************************
 *
 * ----------+--------+----------------+-------------------------------------
 *  06/11/05 | HLI    | 1.0            | Initial revision.                  
 * ----------+--------+----------------+-------------------------------------
 *
 ***************************************************************************/

#include "adl_global.h"
#include "timer.h"
#include "tcp_all.h"
#include "dtl_all.h"
#include "grl_all.h"

/*===========================================================================
 * some global var's for timing issues 
 *=========================================================================*/
adl_tmr_t * myHWTimer;						// wavecom system timer 100ms
sw_timers_t	TIMERS[ MAX_TIMERS ];			// SW timer system


/*===========================================================================
 *	Function:	Tmr_FindTimer 
 *  Descr.:     find the correct timer in array list
 *=========================================================================*/
s8 SwTmr_FindTimer( s8 timer ) 
{
	u8	i;
	for( i = 0; i < MAX_TIMERS; i++ )
	{
		if ( TIMERS[ i ].timer == timer )
		{
			return ( i );
		}
	}
	return ( -1 );
}


/*===========================================================================
 *	Function:	SwTmr_KillTimer 
 *  Descr.:     cancel a running timer
 *=========================================================================*/
void SwTmr_KillTimer( s8 timer )
{
	s8	i = SwTmr_FindTimer( timer );
	if ( i != -1 )
	{
		TIMERS[ i ].timer		= -1;
		TIMERS[ i ].reload		= 0L;
		TIMERS[ i ].state		= TIMER_FREE;
		TIMERS[ i ].callback	= 0;
		TIMERS[ i ].count		= 0L;
	}
}


/*===========================================================================
 *	Function:	SwTmr_StopTimer 
 *  Descr.:     suspend a running sw timer
 *=========================================================================*/
void SwTmr_StopTimer( s8 timer )
{
	s8	i = SwTmr_FindTimer( timer );
	if ( i != -1 )
	{
		TIMERS[ i ].state	= TIMER_STOPPED;
	}
}


/*===========================================================================
 *	Function:	SwTmr_ContinueTimer 
 *  Descr.:     continue a previous suspended timer
 *=========================================================================*/
void SwTmr_ContinueTimer( s8 timer )
{
	s8	i = SwTmr_FindTimer( timer );
	if ( i != -1 )
	{
		TIMERS[ i ].state	= TIMER_RUNNING;
	}
}


/*===========================================================================
 *	Function:	SwTmr_RetriggerTimer 
 *  Descr.:     refresh the time of a running timer
 *=========================================================================*/
void SwTmr_RetriggerTimer( s8 timer )
{
	s8	i = SwTmr_FindTimer( timer );
	if ( i != -1 )
	{
		TIMERS[ i ].count = TIMERS[ i ].reload;
	}
}


/*===========================================================================
 *	Function:	SwTmr_Init 
 *  Descr.:     initialize the software timer system
 *=========================================================================*/
void SwTmr_Init( void )
{
	u8 i;
	for( i = 0; i < MAX_TIMERS; i++ )
	{
		TIMERS[ i ].timer		= -1;
		TIMERS[ i ].count		= 0L;
		TIMERS[ i ].state		= TIMER_FREE;
		TIMERS[ i ].type		= TIMER_NONE;
		TIMERS[ i ].callback	= NULL;
		TIMERS[ i ].reload		= 0L;
	}
}


/*===========================================================================
 *	Function:	SwTmr_SetStatus 
 *  Descr.:     set the status of an existing timer
 *=========================================================================*/
void SwTmr_SetStatus( s8 timer, TimerStatus_e status )
{
	s8	i = SwTmr_FindTimer( timer );
	if ( i != -1 )
	{
		TIMERS[ i ].state	= status;
		return;
	}
}

/*===========================================================================
 *	Function:	SwTmr_Control 
 *  Descr.:     function which is called by OS timing system to provide
 *              retriggerable sw timer system
 *=========================================================================*/
void SwTmr_Control( u8 hwtmr )
{
	// ignore hwtmr cause there is only one
	u8	i;
	if ( hwtmr == myHWTimer->TimerId )
	{
		for( i = 0; i < MAX_TIMERS; i++ )
		{
			if ( TIMERS[ i ].state == TIMER_RUNNING )
			{
				if ( TIMERS[ i ].count-- == 0 )
				{
					TIMERS[ i ].state = TIMER_EXPIRED;
					TIMERS[ i ].callback ( TIMERS[ i ].timer );
					if ( TIMERS[ i ].type == TIMER_CYCLIC )
					{
						TIMERS[ i ].count	= TIMERS[ i ].reload;
						TIMERS[ i ].state = TIMER_RUNNING;
						break;
					}
					else
					{
						SwTmr_KillTimer ( i );				
					}
				}
			}
		}
	}
}


/*===========================================================================
 *	Function:	SwTmr_Status 
 *  Descr.:     read the status of a sw defined timer
 *=========================================================================*/
TimerStatus_e SwTmr_Status( u8 timer )
{
	s8	i = SwTmr_FindTimer( timer );
	if ( i != -1 )
	{
		return ( TIMERS[ timer ].state );
	}
	return ( TIMER_FREE );
}

/*===========================================================================
 *	Function:	SwTmr_StartTimer 
 *  Descr.:     start a sw defined n*1s timer
 *=========================================================================*/
s8 SwTmr_StartTimer( s8 timer, TimerType_e type, u32 timeout, void (*callback)( s8 timer ) )
{
	s8	i = SwTmr_FindTimer( timer );
	if ( i == -1 )
	{
		i = SwTmr_FindTimer( -1 );
		if ( i == -1 )
		{
			TRACE ((1, "##### PANIC: No more sw timers! #####" ));
			return ( -1 );
		}
	}
	TIMERS[ i ].timer		= timer;
	TIMERS[ i ].type		= type;
	TIMERS[ i ].count		= timeout;
	TIMERS[ i ].callback	= callback;
	TIMERS[ i ].reload		= TIMERS[ i ].count = timeout;
	TIMERS[ i ].state		= TIMER_RUNNING;
	return ( i );
}


/*===========================================================================
 *	Function:	SwTmr_SetInterval 
 *  Descr.:     set a new timer interval
 *=========================================================================*/
void SwTmr_SetInterval ( s8 timer, u16 new_interval )
{
	s8	i = SwTmr_FindTimer( timer );
	if ( i != -1 )
	{
		TIMERS[ i ].reload	= new_interval;
		return;
	}
}


/*===========================================================================
 *	Function:	timer_init 
 *  Descr.:     initialize timer handling
 *=========================================================================*/
void timer_init ( void )
{
	SwTmr_Init();
	
	// subscribe a OS timer every 10*100ms for the SW defined timing funcs
	myHWTimer = adl_tmrSubscribe ( TRUE, (u32)10, ADL_TMR_TYPE_100MS, (void*) SwTmr_Control  );
}


/*===========================================================================
 *	Function:	timer_remove 
 *  Descr.:     remove the OS driven timing feature, therefore also
 *              the driven timing system stops!
 *=========================================================================*/
void timer_remove ( void )
{
	adl_tmrUnSubscribe ( myHWTimer, (void*) SwTmr_Control, ADL_TMR_TYPE_100MS  );
}

I’m using typically 1sec intervals, but it simply can be changed by changing the values in timer_init.

Regards,
Heinz