/*******************************  interrupts.h  *******************************
 * $Source: /home/cvs/ESP/gen2/software/msp430/include/interrupts.h,v $
 *  Copyright (C) 2003 MBARI
 *
 *  MBARI Proprietary Information. All rights reserved.
 * $Id: interrupts.h,v 1.3 2004/04/15 05:50:38 brent Exp $
 *
 * Support for nested interrupts
 *    This is application dependent, so it is
 *    defined in the application directory.
 *
 * Theory of operation:
 *
 *  The SCG0 flag in the MSP430 status register is the only one not cleared
 *  when it enters an ISR.  It has no function in the power save modes used
 *  by this application.  Therefore, we can use it to detect if an event
 *  was signaled inside any nested ISR.
 *
 *  The ISR that may set GIE must first (or simultaneously) set SCG0.
 *  Before that interrupt returns, however, if an event was signaled,
 *  it must modify the stacked SR to insure that sleep mode is exited.
 *
 *****************************************************************************/

#ifndef interrupts_h
#define interrutps_h

#include "msp430x16x.h" //register and I/O definitions

//Timing constants
#define ACLKRATE  4096    //ACLK 4096hz (assuming 32768hz watch crystal)
#define TIMERHZ   64      //# of interval timer interrupts per second

#define MASK_TIMER_INTERRUPTS()   (IE1 &= ~WDTIE)
#define UNMASK_TIMER_INTERRUPTS() (IE1 |= WDTIE)

/*
  block in non-ISR context until some Interrupt Service Routine signals
  an event with SIGNALEV()  
  Must be entered with interrupts disabled, exits with interrupts enabled
*/
#define AWAITEV() _BIS_SR(LPM1_bits | GIE)   //wait for event from ISR
#define firstEINTinISR() _BIS_SR(GIE | SCG0) //use SCG0 to detect SIGNALEV()
#define allowINTinISR()  _BIS_SR(SCG0)       //use SCG0 to detect SIGNALEV()
#define signalEV() _BIC_SR(SCG0)             //cause event to be propagated

// The following may be used only in a top-level interrupt function
#define SIGNALEV() LPM4_EXIT  //from ISR to awaken mainline (also clears SCG0)

//isr is just any unique identifier to let us generate a local label
#macro DINTandPropagateEV(isr)  //invoke at end of ISRs that invoke EINTinISR()
{ /$
      dint
      nop
$/ }
      propagateEV(isr)
#endm

#macro propagateEV(isr) //shorter form used when interrupts are already disabled
{ /$
	bit	\#SCG0,sr     ;if SCG0_bit was cleared during this ISR
	jne	SKIP_SIGNALEVin##isr
$/
  SIGNALEV();         //propagate SIGNALEV() up the stack...
/$
SKIP_SIGNALEVin##isr:
$/ }
#endm

#endif
