/*********************************  timers.h  *********************************
 * $Source: /home/cvs/ESP/gen2/software/msp430/include/timers.h,v $
 *  Copyright (C) 2003 MBARI
 *
 *  MBARI Proprietary Information. All rights reserved.
 * $Id: timers.h,v 1.8 2004/04/01 00:35:13 brent Exp $
 *
 * Simple interval timers for the MSP430
 *
 * Each timer consists of a countdown, a period and an action
 * function to call when the countdown decriments from one to zero.
 * The period is a divisor on the fundamental timer frequency.
 * Each time the countdown reaches zero, it is reloaded with the
 * period.  If the period is zero, the timer functions as
 * a one shot -- i.e. when its countdown reaches zero, it is reloaded
 * with zero and remains inactive.
 *
 * The action function assocated with each timer must always be
 * a valid timerAction.  It must never be NULL!  Use one of the
 * stock timerAction functions when no action is desired.
 *
 * To prevent reentry to a hypothetical "nonReentrantTimerAction" function:
 *   void nonReentrantTimerAction (array, index, timer) {
 *    timer->action = dummyTimerAction;  //ignore any attempts to reenter
 *      .... non-reentrant stuff ....
 *    timer->action = nonReentrantTimerAction;
 *   }
 *
 * By default, the maximum number of timers supported is 16.
 * timerServiceMask may be #defined to uint32 before this is #included to 
 * support up to 32 timers.
 *
 * A skeleton for using timers in an application:
 *
 *  Declare:
 *    struct timer myTimers[NTIMERS];
 *
 *  At reset:
 *    initTimers (myTimers, NTIMERS);
 *    (set up myTimers for desired repeated services)
 *    (configure MSP430 clocks, timers & interrupts)
 *  
 *  In timer Interrupt Service Routine:
 *    timerServiceMask service = advanceTimers (myTimers, NTIMERS);
 *    enable_interrupts();
 *    if (service) serviceTimers (myTimers, service);
 *    ...
 * 
 *****************************************************************************/

#ifndef TIMERS_H
#define TIMERS_H

#include <in430.h>
#include "types.h"

#ifndef timerServiceMaskType
#define timerServiceMaskType  uint16
#endif

struct timer;  //introduce incomplete type

typedef void 
  timerAction (struct timer *array, unsigned index, struct timer *timer);

struct timer {
  unsigned countdown;   //decriments toward zero
  unsigned period;      //value to load into countdown when it reaches zero
  timerAction *action;  //function to call when countdown reaches zero
};

extern
  void initTimers (struct timer *array, unsigned timers);
/*
  (re-)initialize a timer array of timers elements
*/


static inline
  timerServiceMaskType advanceTimers (struct timer *array, unsigned timers)
/*
  advance one timer tick on each of a specified array of timers.
  assumes timers != 0 on entry.
  timer interrupt should be MASKED.
  returns bitset of those timers requireing service
*/
{
  struct timer *timer = array;
  struct timer *end = array + timers;
  timerServiceMaskType service = 0;  //mask of timers that just reached zero
  timerServiceMaskType thisTimer = 1;
  do {
    if (timer->countdown && !--timer->countdown) {
      timer->countdown = timer->period;
      service |= thisTimer;
    }
    thisTimer <<= 1;
  } while (++timer < end);
  return service;
}


static inline 
  void serviceTimers (struct timer *array, timerServiceMaskType service)
/*
  service the timers that just counted down to zero
  timer interrupt should be UNMASKED
*/
{
  struct timer *timer = array;
  unsigned index = 0;
  do {
    if (service & 1) timer->action (array, index, timer);
    index++; timer++;
  } while (service>>=1);
}


/* some stock timerAction functions */

extern void 
 dummyTimerAction (struct timer *array, unsigned index, struct timer *timer);
/*
  do nothing -- ignore countdown
*/


#endif
