#include <hidef.h>      /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include "common.h"
#include "mtim.h"
#include "printf.h"
#include "tsi.h"
#include "wdog.h"
#include "adc.h"
#include "mma8451.h"
#include "pt60_tower.h"
#include "string.h"
#include "math.h"

/* TSI functions */
void KEY1_Processing( void );
void millisecond_delay (int delay);
void MMA8451_Initial(void);
void Read_MMA8451_Info(void);
void wait_for_movement (void);
void leds_show_shake (byte src);
void leds_show_tilt (byte *values);
unsigned char GetAccelerometerDemoState(void);
void PrintDemoState(unsigned char DemoState);
void ICS_FEI(void);

#define SysPotentiometer       0
#define SysAccelerometer       1

byte SystemMode;

byte CurrentDemo;                       /* Current demo, e.g. DEMO_FREEFALL */
byte NewDemo;                           /* New demo requested */

byte CurrentRange;                      /* Current range setting, e.g. FULL_SCALE_2G */
byte NewRange;                          /* New range setting requested */

byte CurrentReadMode;                   /* Current read size, e.g. READ_MODE_14BITS */
byte NewReadMode;                       /* New read size requested */

byte last_int_source_reg;               /* Last value of INT_SOURCE_REG as read by 
                                                  read_accelerometer_info() 
                                               */ 
byte last_sysmod_reg;                   /* Last value of SYSMOD_REG */
byte last_f_status_reg;                 /* Last value of F_STATUS_REG */
byte last_transient_src_reg;            /* Last value of TRANSIENT_SRC_REG */ byte last_pl_status_reg;                /* Last value of PL_STATUS_REG */
byte last_pulse_src_reg;                /* Last value of PULSE_SRC_REG */
byte last_ff_mt_src_1_reg;              /* Last value of FF_MT_SRC_1_REG */
byte last_xyz_values [6];               /* Last values of X, Y and Z */ 


/*****************************************************************************//*!
+FUNCTION----------------------------------------------------------------
* @function name: KEY1_Processing
*
* @brief handles touch pad 1 on board
*        
* @param  none 
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/

void KEY1_Processing( void )
{	
	//LED_ELECTROD_PTG0_Init();
	LED_ELECTROD_PTG0_Toggle();
	//LedElectrodOnFlag ^= 1;
	if(LedElectrodOnFlag == 0)
	{
		LedElectrodOnFlag = 1;
	}
	else
	{
		LedElectrodOnFlag = 0;
	}
}

/*****************************************************************************//*!
   +FUNCTION----------------------------------------------------------------
   * @function name: MMA8451_Initial
   *
   * @brief description: MMA8451 Initial as  Motion Detection mode.
   *        
   * @parameter:  none
   *
   * @return: none
   *
   * @ Pass/ Fail criteria: none
   *****************************************************************************/
void MMA8451_Initial(void)
{
	byte    n, int_mask;
 
    /* Disable MMA_INTx interrupts so there's no danger of a spurious interrupt
       during reconfiguration 
    */               
    KBI1_SC_KBIE = 0;               

    /* Put MMA845xQ into Standby Mode */	
	MMA8451_Standby();  
    
    /* Configure sensor for:
         Sleep Mode Poll Rate of 1.56Hz (640ms) for maximum power saving 
         System Output Data Rate (ODR) of 200Hz (5ms)
		 read mode 14-bit data
    */
    n = ASLP_RATE_640MS + DATA_RATE_5MS;          
    if (CurrentReadMode == READ_MODE_8BITS)
        n |= FREAD_MASK;
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, CTRL_REG1, n);  
  
    /* Select user-specified sensitivity, 2g/4g/8g */
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, XYZ_DATA_CFG_REG, CurrentRange);
    
    /* Configure Sleep/Wake modes 
        SMODS1:0   : 1 1    Low power mode when asleep
        SLPE       : 1      Sleep enabled
        MODS1:0    : 0 0    Normal mode when awake
    */
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, CTRL_REG2, 0x1c);          
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, ASLP_COUNT_REG, 62);      /* Sleep after 20 seconds of inactivity */         

    /* Disable the FIFO */
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, F_SETUP_REG, 0x00);

    switch (CurrentDemo) 
    {
    case DEMO_TRANSIENT:
    case DEMO_SHAKE:
    case DEMO_ORIENTATION:
        /* In all three of these demo modes we configure the accelerometer to detect
           movement:
           
                DEMO_TRANSIENT   - We configure the accelerometer to detect small movements
                                   of > 0.063g                   
                                   
                DEMO_SHAKE       - We configure the accelerometer to detect movements
                                   of > 0.5g
                                                      
                DEMO_ORIENTATION - We don't care about the movement data itself, but
                                   we use transient detection so that the accelerometer
                                   can tell us when the board isn't being used. When
                                   it transitions to Sleep mode, we can put the main
                                   processor to sleep too.
                                   
          By using the high-pass filter we can remove the constant effect of gravity,
           and only detect changes in acceleration. See Application Note AN4071.
        */

        /* ELE = 1     : Event latch enabled 
           ZTEFE = 1   : Raise event on any of Z, Y, X axes
           YTEFE = 1
           XTEFE = 1
           HBF_BYP = 0 : High-pass filter enabled
        */
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, TRANSIENT_CFG_REG, 0x1e);
        
        /* Set High-pass filter cut-off frequency for best sensitivity */
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, HP_FILTER_CUTOFF_REG, 0x03);   

        if (CurrentDemo == DEMO_SHAKE) 
        {
            /* Transient is indicated when acceleration on one of the axes
               is above threshold 8 x 0.063g = 0.5g 
             */   
        	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, TRANSIENT_THS_REG, 8);
        } 
        else 
        {
            /* Transient is indicated when acceleration on one of the axes
               is above threshold 1 x 0.063g - i.e. a small movement 
            */   
        	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, TRANSIENT_THS_REG, 1);
        }

        /* Internal debounce counter. For an ODR of 200Hz in Normal mode,
           motion is indicated after 5 x 1 = 5ms. 
        */
         MMA8451WriteRegister(MMA8451_I2C_ADDRESS, TRANSIENT_COUNT_REG, 1);

        /* Interrupt signalled on INT1 when transient detected */
        int_mask = INT_EN_TRANS_MASK;

        if (CurrentDemo == DEMO_ORIENTATION) 
        {
            /* Interrupt also signalled when new data is ready */
             int_mask |= INT_EN_DRDY_MASK;
         
            /* Set up TPMs to produce edge-aligned PWM signals */
            configure_LEDs_for_PWM ();    
        }
        break;
        
    case DEMO_TAP:
        /* Configure the accelerometer to detect single and double taps... 
           (See Application Note AN4072)
        */
 
        /* Z configured for Single Tap and Double Tap with Latch enabled */
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, PULSE_CFG_REG, 0x70);    
        
        /* Enable low-pass filter */
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, HP_FILTER_CUTOFF_REG, PULSE_LPF_EN_MASK);   

        /* Set Z Threshold to 16 x 0.063g = 1.0g 
           
           Note: In a more sophisticated application we could dynamically
           track the orientation and configure X, Y Z with changing thresholds
        */
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, PULSE_THSZ_REG, 16);  

        /* Set the Pulse Time Limit for 30 ms at 200 Hz ODR in Normal Mode with the LPF Enabled  
           30 ms/5 ms = 6 counts
        */
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, PULSE_TMLT_REG, 6);
        
        /* Set the Pulse Latency Timer to 100 ms, 200 Hz ODR Normal Mode, LPF Enabled  
           100 ms/10 ms = 10 counts
        */
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, PULSE_LTCY_REG, 10);
        
        /* Set the Pulse window to 400 ms, 200 Hz Normal Mode, LPF Enabled
           400 ms/10 ms = 50 counts
        */
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, PULSE_WIND_REG, 50);

        /* Interrupt signalled on INT1 when pulse detected */
        int_mask = INT_EN_PULSE_MASK;
        break;
        
    case DEMO_FREEFALL:
        /* Configure accelerometer for linear freefall detection... 
           [Note that the accelerometer can also detect tumbling, as
            described in Application Note AN4070]
        */
        
        /* ELE = 1   : Event latch enabled 
           OAE = 0   : Detect Freefall
           ZEFE = 1  : Raise event on any of Z, Y, X axes
           YEFE = 1
           XEFE = 1
        */
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, FF_MT_CFG_1_REG, 0xb8);   
        
        /* Freefall is indicated when acceleration on all three axes
           falls below threshold 3 x 0.063g = 0.19g 
        */   
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, FT_MT_THS_1_REG, 3);
        
        /* Internal debounce counter. For an ODR of 200Hz in Normal mode,
           freefall is indicated after 5 x 20 = 100ms of falling - a drop
           of a few centimetres - See Application Note AN4070
        */
    	MMA8451WriteRegister(MMA8451_I2C_ADDRESS, FF_MT_COUNT_1_REG, 20);

        /* Interrupt signalled on INT1 when Freefall detected */
        int_mask = INT_EN_FF_MT_1_MASK;
        break;
    }
   
    /* Configure interrupts */
    int_mask |= INT_EN_ASLP_MASK;                           /* Also generate interrupt on 
                                                               Sleep <--> Wake transition 
                                                            */
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, CTRL_REG4, int_mask);
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, CTRL_REG5, 0xfd);         /* All interrupts mapped to MMA_INT1 */
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, CTRL_REG3, 0x78);         /* Active-low interrupts, all functions 
                                                                           wake system 
                                                                        */  

    /* Throw away any stale interrupt info */
    last_int_source_reg = 0;
    
    /* Put MMA845xQ into Active Mode */
	MMA8451_Active();

    /* Enable MMA_INTx interrupts */
    KBI1_SC_KBIE  = 1;  
		 

}

/************************************************************************
*       Read_MMA8451_info - Read any state change info            *
*************************************************************************
; This routine reads the accelerometer's INT_SOURCE_REG to check whether
; any events have occured. It then reads any event-specific data in order
; to clear the interrupts.
;
; Values are returned in the following global variables:
;
;       last_int_source_reg       - INT_SOURCE_REG
;       last_sysmod_reg           - SYSMOD_REG                     
;       last_f_status_reg         - F_STATUS_REG                    
;       last_transient_src_reg    - TRANSIENT_SRC_REG               
;       last_pl_status_reg        - PL_STATUS_REG                   
;       last_pulse_src_reg        - PULSE_SRC_REG                   
;       last_ff_mt_src_1_reg      - FF_MT_SRC_1_REG                 
;       last_xyz_values           - OUT_X_MSB_REG, etc          
;
; See the comments in the routine 'accelerometer_isr' for more information 
*/
void Read_MMA8451_Info(void)
{
    /* Which source caused an interrupt, if any ? */
    last_int_source_reg = u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, INT_SOURCE_REG);

    /* Sleep <--> Wake transition detected ? */
    if (last_int_source_reg & SRC_ASLP_MASK) 
    {            
        /* Yes - Clear the event */
        last_sysmod_reg = u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, SYSMOD_REG);
    } 
    
    /* FIFO event detected ? */
    if (last_int_source_reg & SRC_FIFO_MASK) 
    {            
        /* Yes - Clear the event 
           Note that our demos don't use this event, so no further processing is required
        */
        last_f_status_reg = u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, F_STATUS_REG);
    } 
    
    /* Transient detected ? */
    if (last_int_source_reg & SRC_TRANS_MASK) 
    {            
        /* Yes - Clear the transient event */
        last_transient_src_reg = u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, TRANSIENT_SRC_REG);
    } 
    
    /* Landscape/portrait orientation change detected ? */
    if (last_int_source_reg & SRC_LNDPRT_MASK) 
    {            
        /* Yes - Clear the event 
           Note that our demos don't use this event, so no further processing is required
        */
        last_pl_status_reg = u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, PL_STATUS_REG);
    } 
    
    /* Tap/pulse event detected ? */
    if (last_int_source_reg & SRC_PULSE_MASK) 
    {
        /* Yes - Clear the pulse event */
        last_pulse_src_reg = u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, PULSE_SRC_REG);
    }
    
    /* Freefall detected ? */
    if (last_int_source_reg & SRC_FF_MT_1_MASK) 
    {            
        /* Yes - Clear the freefall event */
        last_ff_mt_src_1_reg = u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, FF_MT_SRC_1_REG);
    }             

    /* Freefall detected ? */
    if (last_int_source_reg & SRC_DRDY_MASK) 
    {            
        /* Yes - read the XYZ data to clear the event */
         if (CurrentReadMode == READ_MODE_14BITS)
         {
             /* Read 14-bit XYZ results using a 6 byte IIC access */
        	 MMA8451ReadRegister_N(MMA8451_I2C_ADDRESS, OUT_X_MSB_REG, 6, (byte *) &last_xyz_values[0]);
         }
         else
         {
             /* Read 8-bit XYZ results using a 3 byte IIC access */
        	 MMA8451ReadRegister_N(MMA8451_I2C_ADDRESS, OUT_X_MSB_REG, 3, (byte *) &last_xyz_values[0]);
         }
    }      
}
/************************************************************************
*       wait_for_movement - Wait until accelerometer indicates movement *
*************************************************************************
; This routine is called when the accelerometer indicates that no event of 
; the current type has occurred for 20 seconds. (For example if we're
; detecting 'taps', the routine is called if the user hasn't tapped the
; board for 20 seconds).
;
; We reconfigure the accelerometer to detect any movement, then put the
; CPU into a low power 'STOP 3' mode
;
; The subroutine doesn't return until the accelerometer indicates
; movement - e.g. the user has picked the board up.
*/
void wait_for_movement (void)
{
	int i;
    /* Configure accelerometer for motion detection in low power mode... */
      
    /* Disable MMA_INTx interrupts so there's no danger of a spurious interrupt
       during reconfiguration 
    */               
    DisableInterrupts;
    KBI1_SC_KBIE = 0;                  

    /* Put MMA845xQ into Standby Mode */
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, CTRL_REG1, (u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, CTRL_REG1) & ~ACTIVE_MASK));
    
    /* ELE = 1     : Event latch enabled 
       ZTEFE = 1   : Raise event on any of Z, Y, X axes
       YTEFE = 1
       XTEFE = 1
       HBF_BYP = 0 : High-pass filter enabled
    */
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, TRANSIENT_CFG_REG, 0x1e);
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, HP_FILTER_CUTOFF_REG, 0x00);   
    
    /* Transient is indicated when acceleration on one of the axes
       is above threshold 1 x 0.063g  
    */   
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, TRANSIENT_THS_REG, 1);
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, TRANSIENT_COUNT_REG, 1);

    /* Interrupt signalled on INT1 when transient detected, or on Sleep <--> Wake transition */
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, CTRL_REG4, (INT_EN_TRANS_MASK | INT_EN_ASLP_MASK));
    
    /* Since reconfiguring the accelerometer here will wake it up again,
       tell it to go back to sleep as soon as possible
    */ 
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, ASLP_COUNT_REG, 1);              

    /* Put MMA845xQ back into Active Mode */
    MMA8451WriteRegister(MMA8451_I2C_ADDRESS, CTRL_REG1, (u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, CTRL_REG1) | ACTIVE_MASK));

    /* Enable MMA_INTx interrupts */
    last_int_source_reg = 0;
    EnableInterrupts;
    KBI1_SC_KBIE = 1;               

    /* Indicate that we're in sleep mode */
    for(i=4;i>0;i--)
    {
        leds_all_on();
        millisecond_delay (500);
        leds_all_off ();
        millisecond_delay (500);
    }   

    /* Sleep until accelerometer wakes up */
    for (;;) 
    {   
        /* Wait until we have event from accelerometer or push button */
        last_int_source_reg = u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, INT_SOURCE_REG);   
        if (last_int_source_reg == 0)  
        	_Wait;
           // asm (wait);
        Read_MMA8451_Info();
        /* Accelerometer wake-up event? */
        if (last_int_source_reg & SRC_ASLP_MASK) 
        {
            if ((last_sysmod_reg & SYSMOD_MASK) != 0x02) 
            {
                /* Yes */  
                break;
            }
        }
       
        /* Did user press one of the buttons SW1 - SW3 ?
           If so, return to active mode
        */
        if (NewRange != CurrentRange || NewReadMode != CurrentReadMode || NewDemo != CurrentDemo) 
            break;
   }

    /* Indicate that we're awake again */
    for(i=6;i>0;i--)
    {
        leds_all_on();
        millisecond_delay (100);
        leds_all_off ();
        millisecond_delay (100);
    } 
}            

/************************************************************************
*       leds_show_shake - Show directional shake                        *
*************************************************************************
; This routine takes 'shake' data as returned in the accelerometer's
; Transient Source Register, and illuminates the LEDs to indicate the
; direction of the initial flick
;
; Reminder: With the board oriented so that the writing is the right way up
; and the On/Off switch is at the top, the accelerometer's X and Y
; directions are as follows:
; Note that more sophisticated directional shake detection would
; require analysis of the pattern of transients before and after
; the shake event...
;
; When the hand starts the shake, the board will experience 
; acceleration in a certain direction. A short while later the hand will
; stop the shake, causing deceleration. Usually the hand will slightly
; over-correct, so that the board 'bounces' and briefly accelerates
; in the opposite direction. Depending on the selected threshold
; programmed into TRANSIENT_THS_REG, the accelerometer may miss the
; initial shake and only detect the bounce. 
;
; See Application Note AN4071
;
*/
void leds_show_shake (byte src)
{
    byte    i;
    
    /* All LEDs off */
    configure_LEDs_for_GPIO ();

    leds_all_off ();

	/* Turn on LEDs to illustrate shake direction */
    if (src & ZTRANSE_MASK) 
    {
        /* Shake in Z axis detected */
        if (src & ZTRANSEPOL_MASK)  
        	leds_cross();
        else
        	leds_plus();
    }
    else if (src & YTRANSE_MASK) 
    {
        /* Shake in Y axis detected */
        if (src & YTRANSEPOL_MASK) 
        {
        	LED6_On();
        	LED5_On();
        	LED4_On();
        }
        else 
        {
        	LED2_On();
        	LED1_On();
        	LED8_On();
        }
   }
    else if (src & XTRANSE_MASK) 
    {
        /* Shake in X axis detected */
        if (src & XTRANSEPOL_MASK)  
        {
        	LED6_On();
        	LED7_On();
        	LED8_On();
        }
        else  
        {
        	LED2_On();
        	LED3_On();
        	LED4_On();
        }
   }
    
    /* Hold LED pattern for 1 seconds */

    millisecond_delay (800);

    leds_all_off ();
}
/************************************************************************
*       leds_show_tilt - Use LEDs to indicate how board is tilted       *
*************************************************************************
; This routine uses the X and Y values to show how the board is tilted
;
; (a) The LEDs are illuminated to indicate the direction of gravity
;     using a PWM technique to illuminate most brightly the 'spoke'
;     that's closest in direction, and dimmly illuminate the others
;
; (b) The number of LEDs illuminated along a spoke indicates how much the
;     board is tipped. (This is also affected by the 2g/4g/8g button)
;      
; We first calculate the direction in which gravity is pulling, relative to the board.
; This is then used to calculate PWM duty cycles for the LEDs, so that they illuminate 
; with different brightnesses to show which way is Down.
;
; Note that it's not necessary to go to all this effort if the software just wants to
; detect a change in orientation between Portait and Landscape mode. For this simple
; case, the accelerometer can detect the change automatically, without polling. See 
; Application Note AN4068 for details.
;
; Arguments:
;   byte        *values - Array of 3 pairs of values for X, Y and Z
;                         Each pair is in 14-bit binary form
*/

#define  PI  3.14

void leds_show_tilt (byte *values)
{
    int     x, y, pwm, spoke; 
    double  theta, angle, brightness;
   
    
    /* Get X and Y values */
    x = (values [0] << 8) | values [1];
    y = (values [2] << 8) | values [3];
           
    /* Calculate direction in which gravity is pulling. We'll use this to choose
       which spokes to illuminate, and with what duty cycles.
       
       With reference to the diagram above, 0 degrees is at 12 o'clock
       and angles increase clockwise
    */ 
    if (x == 0 && y == 0)
    {
        theta = 0.0;
    }
    else 
    {    
        theta = atan2(-x, -y);
        if (theta < 0.0)
            theta +=  2.0 * PI;
    }
      
    /* Loop to illuminate spokes */
    for (spoke = 0; spoke < 8; spoke++) 
    {
        /* Calculate angle of spoke in radians */
    	//angle = spoke * 45 * _M_PI / 180.0; 
    	angle = spoke * PI / 4; 
       
        /* Calculate desired brightness */
        angle = fabs (theta - angle);
        if (angle >= PI / 2.0 && angle <= 3 * PI / 2.0) 
        {
            /* More than 90 degress between gravity and this spoke, so always off */
            pwm = 0;
        }
        else 
        {
            /* Calculate brightness based on angle between spoke and gravity */
            brightness = cos (angle);

            /* Since the eye's response to brightness is non-linear, 
               use a logarithmic dimming curve as used by DALI lighting
            */
            brightness = pow (10.0, 3.0 * (brightness - 1.0));
        
            /* Calculate PWM value */
            pwm = (int) (MAX_PWM_VALUE * brightness);
        }
       
        switch (spoke) 
        {
        case 0: FTM2_C0V = pwm;  break;
        case 1: FTM2_C1V = pwm;  break;
        case 2: FTM2_C2V = pwm;  break;
        case 3: FTM2_C3V = pwm;  break;
        case 4: FTM2_C4V = pwm;  break;
        case 5: FTM2_C5V = pwm;  break;
        case 6: FTM1_C0V = pwm;  break;
        case 7: FTM1_C1V = pwm;  break;
        }
    }
}

/************************************************************************
*       get a demo data by changing accelerometer                       *
*************************************************************************/
unsigned char GetAccelerometerDemoState(void)
{
	unsigned short DummyAdcValue;
	
	DummyAdcValue = ADC_GetResult(0);
	if(DummyAdcValue < Potentiometer_THRESHOLD_2 )
	{
		NewDemo = DEMO_ORIENTATION;
	}
	else if(DummyAdcValue < Potentiometer_THRESHOLD_4 )
	{
		NewDemo = DEMO_SHAKE;
	}
	else if(DummyAdcValue < Potentiometer_THRESHOLD_6 )
	{
		NewDemo = DEMO_TAP;
	}	
	else
		NewDemo = DEMO_TRANSIENT;	
	
	return NewDemo;
}

/************************************************************************
*       send corresponding information to the terminal                   *
*************************************************************************/
void PrintDemoState(unsigned char AccelerometerState)
{
	switch(AccelerometerState)
	{
	case DEMO_ORIENTATION: 
		//printf("\n Demo board in SysAccelerometer mode(DEMO_ORIENTATION)now.");
		printf("\n >> LAB2: ORIENTATION Mode");
		printf("\n Tilt the board,LEDs show the orientation changing\n\n");

		break;
	case DEMO_SHAKE: 
		//printf("\n Demo board in SysAccelerometer mode(DEMO_SHAKE)now.");
		printf("\n >> LAB2: SHAKE Mode");
		printf("\n Move board from low to high LEDs show plus style");
		printf("\n Move board from high to low LEDs show cross style\n\n");
		break;
	case DEMO_TAP: 
		//printf("\n Demo board in SysAccelerometer mode(DEMO_TAP)now.");
		printf("\n >> LAB2: TAP Mode");
		printf("\n single TAP LEDs show plus style");
		printf("\n double TAP will show cross style\n\n");
		break;
	case DEMO_TRANSIENT: 
		//printf("\n Demo board in SysAccelerometer mode(DEMO_TRANSIENT)now.");
		printf("\n >> LAB2: TRANSIENT Mode");
		printf("\n The LEDs will on by any movement of the board\n\n");
		break;
	default:
		break;
	}
//	printf("\n Rotate the potentiometer to change the mode in LAB2");
//	printf("\n Touch TSI key to change into LAB1\n");
}

/************************************************************************
*       FEI defaul mode configureation                                 *
*************************************************************************/
void ICS_FEI(void)
{
	ICS_C1 = 0x04;    // Internal reference clock selected
	ICS_C2 = 0x20;    // Divides selected clock by 2 (reset default)
//	ICS_C3 = 0x80;    // internal reference clock trim value
	
	while(!ICS_S_LOCK);  // wait clock to lock 
}

/************************************************************************
*       main - Program main entry point                                 *
*************************************************************************/

void main(void) 
{
    int     count;
    byte    dummy_DemoState;
    
    DisableInterrupts;
    wdog_disable(); 
    ICS_FEI();
    Init_SCI2(BUS_CLK_HZ);   // for UART
    MTIM1_Init();            // trigger the TSI periodically
    Button_Init();           // KBI Init  
    Init_I2C();              // for accelerometer
    ADC_Init();              // for potentiometer       
    TSI_Init();              // interrupt mode 
    LedElectrodOnFlag = 0;   // flag
    SystemMode = SysAccelerometer;    // special initial, for print SysPotentiometer information for the first time  
    EnableInterrupts;
    printf("\n************************ Welcome to 9S08DC-PT60 Demo *************************\n");
    printf("\n   LAB1 : Potentiometer Demo(default demo)");
    printf("\n   LAB2 : Accelerometer Demo(ORIENTATION,SHAKE,TAP and TRANSIENT Mode)");
    printf("\n   Change two LABs by touching TSI Key");
    printf("\n   Change modes in LAB2 by rotating the potentiometer \n");
    printf("\n******************************************************************************\n\n");

    /* Loop forever to run demos */ 
    for (;;) 
    {    	
    	//TSI_Processing();    	// just used in polling mode

    	if(LedElectrodOnFlag == 0)  // demo in potentiometer mode
    	{
        	if(SystemMode == SysAccelerometer)  // if SystemMode change from SysAcceleromer to SysPotentiometer, print 
        	{
        		//printf("\n Demo board in SysPotentiometer mode now.");
        		printf("\n >> LAB 1: Potentiometer Demo ");
        		printf("\n Rotate the potentiometer, LEDs show the resistance changing\n\n");
        		//printf("\n Touch TSI key to change into LAB2\n");
        	}
    		SystemMode = SysPotentiometer;  // indicate the led is configured as GPIO
    		Potentiometer_test();     		
    	}
    	else   // demo in accelerometer mode
    	{  
    		/* get the new demo mode by reading the potentiometer */
    		dummy_DemoState = GetAccelerometerDemoState();
    		
    		if(SystemMode == SysPotentiometer)
    		{
    			SystemMode      = SysAccelerometer;
                CurrentRange    = NewRange;
                CurrentDemo     = NewDemo;
                CurrentReadMode = NewReadMode;                
    			MMA8451_Initial();  // reconfigure the accelerometer
    			PrintDemoState(dummy_DemoState);
    		}
    	if (NewRange != CurrentRange || NewReadMode != CurrentReadMode || NewDemo != CurrentDemo) 
        {
            /* Reconfigure accelerometer */ 
            CurrentRange = NewRange;
            CurrentReadMode = NewReadMode; 
            CurrentDemo = NewDemo;
            MMA8451_Initial();
            PrintDemoState(dummy_DemoState);
        }
        
        /* ---- Check for accelerometer event(s) ---- */
        Read_MMA8451_Info(); 

        /* ---- Handle any transition from accelerometer Wake -> Sleep mode ---- */
        if (last_int_source_reg & SRC_ASLP_MASK) 
        {
            if ((last_sysmod_reg & SYSMOD_MASK) == 0x02)   // current mode is sleep mode
            {
                /* Accelerometer has gone into sleep mode because no activity has been detected
                   in the last 20 seconds. We put the main CPU to sleep too, to save maximum power.
                */
                wait_for_movement ();               /*  Routine doesn't return until 
                                                        accelerometer is awake again */
                                                        
                /* Force reconfiguration now we're awake again */ 
                CurrentDemo = ~NewDemo;
                continue;
            }
        }
       
        /* ---- Update LEDs if accelerometer event occurred ---- */
        switch (CurrentDemo)
        {
        case DEMO_ORIENTATION:
            /* New XYZ tilt data ready? */
            if (last_int_source_reg & SRC_DRDY_MASK) 
            {            

                /* Temporarily disable interrupts so 'last_xyz_values' data is not overwritten */
                DisableInterrupts;
                
                /* Make a copy of the data, unpacked into 14-bit format if necessary */
                if (CurrentReadMode == READ_MODE_14BITS) 
                {
                    /* Already read 14-bit data into last_xyz_values[] */
                }
                else if (CurrentReadMode == READ_MODE_8BITS)
                {
                    /* Unpack 8-bit data into 14 bit format */
                    last_xyz_values [5] = 0;
                    last_xyz_values [4] = last_xyz_values [2];
                    last_xyz_values [3] = 0;
                    last_xyz_values [2] = last_xyz_values [1];
                    last_xyz_values [1] = 0;
                } 
                
                EnableInterrupts;   
                /* use LED to indicate the orientation of the accelerometer*/
                leds_show_tilt (&last_xyz_values[0]);
            }
            break;
            
        case DEMO_SHAKE:
            /* Shake detected ? */
            if (last_int_source_reg & SRC_TRANS_MASK) 
            {            
                /* Indicate that we detected shake */
                leds_show_shake (last_transient_src_reg);

                /* Throw away any stale shake event, typically caused in opposite
                   direction to initial shake, as hand slows the board down
                */
                //(void) u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, TRANSIENT_SRC_REG);
            }
            break;
            
        case DEMO_TAP:
            /* Tap event detected ? */
            if (last_int_source_reg & SRC_PULSE_MASK) 
            {
                /* Single or double tap detected ? */
                if (last_pulse_src_reg & PDPE_MASK)
                	leds_cross();         /* Double tap */
                else
                	leds_plus();             /* Single tap */
            }
            break;
            
        case DEMO_FREEFALL:
            /* Freefall detected ? */
            if (last_int_source_reg & SRC_FF_MT_1_MASK) 
            {            
                /* Indicate that we detected freefall by showing decreasing circle pattern on LEDs */
                for (count = 0; count < 20; count++) 
                {
                    leds_cross();
                    millisecond_delay (60);
                    leds_plus();
                }
                leds_all_off ();
                
                /* Throw away any stale freefall event, typically caused because board
                   fell some distance
                */
                (void) u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, FF_MT_SRC_1_REG);
            }
            break;
            
        case DEMO_TRANSIENT:
            /* Motion detected ? */
        	leds_all_off ();
            if (last_int_source_reg & SRC_TRANS_MASK) 
            {            
                /* Indicate that we detected motion by animating the LEDs for a few seconds */
            	//leds_cross();
            	leds_all_on ();
            	millisecond_delay (20);
            }
            break;
            
        default:
            break;
        }

        /* Wait for interrupt signalling accelerometer event or button press,
           unless another event has already occurred
        */
        last_int_source_reg = u8MMA8451ReadRegister(MMA8451_I2C_ADDRESS, INT_SOURCE_REG);   
        if (last_int_source_reg == 0 && NewRange == CurrentRange && NewReadMode == CurrentReadMode && NewDemo == CurrentDemo)  
            asm (wait); // _Wait   
     } /* Loop forever */
    }

}


/************************************************************************
*       millisecond_delay - Pause execution for specified time          *
*************************************************************************
; NB: Millisecond timings are approximate only. 
;
; Arguments:
;   int        delay        - Approximate number of milliseconds to delay
*/
void millisecond_delay (int delay)
{
    unsigned short count;
    
    /* Configure TPM1 as a free-running counter with approximately 32 microsecond tick... */  
    
    while (delay > 0) 
    {
    	
        if (delay > (0xffffUL/32)) 
        {
            /* Need to loop multiple times to achieve full delay because a value 
               of 2048 or more would overflow 16 bits in "count = (count << 5) - count" below 
            */
            count = (0xffffUL/32);
            delay -= (int) (0xffffUL/32);
        }
        else 
        {
            /* Do the whole thing in one hit */  
            count = (unsigned short) delay;
            delay = 0;
        }
        
        /* Multiply by 31, since 31 ticks = 31 x 32 microseconds = 0.992 ms,
           or approximately 1 ms. We don't care about the slight inaccuracy 
        */   
        count = (count << 5) - count;  
            
        FTM0_SC = 0;                     /* Stop the timer */  
        FTM0_SC_TOF = 0;                 /* Clear the TOF flag */  
             
        //FTM2_C0SC = 0;                   /* Configure the timer */  
        FTM0_MOD = count;           
        FTM0_CNT = 0;
        FTM0_SC = 0x0f;                  /* Restart the timer: CLKS = 01 (Use BUSCLK/2), PS=111 (Divide-by-128)
                                           Frequency = fbus / 128, so period = 128 / 4 MHz = 32 microseconds 
                                         */
        
        /* Wait for timer to expire */  
        while (!FTM0_SC_TOF);  
    }
}


interrupt VectorNumber_Vmtim1 void  Mtim1_ISR(void)
{
	if(MTIM1_SC_TOF)  // clear the flag
		MTIM1_SC_TOF = 0;		
	if(TSI_CS0_EOSF == 0)   // clear the flag
	{
		// specify the scanning channel	
		TSI_CS3_TSICH = m_ElecWorkInfo[0].Channel;
		// start scanning
		TSI_CS0 |= 0x01;
	}
}

/* 
 * enable TSIIE first in TSI_Init() last line
 */
interrupt  VectorNumber_Vtsi  void  TSIpad_D14_ISR(void)
{	
//	unsigned short uiDelta;
	if(TSI_CS0_EOSF)   // clear the flag
	{
		TSI_CS0_EOSF = 1;
	}
	    		
	TSI_Processing();	
}

interrupt  VectorNumber_Vkbi1 void  MMA8451_Int_ISR(void)
{
	KBI1_SC_KBACK = 1;
	//printf("in kbi int\n");
}

