/*********************************************************************************
* EMG Sensor Shirt SeniorProjectMain.c
*
* 04/05/2015  Dylan Kleist and Josh Goertz
* Last Edited on 06/07/2015
*********************************************************************************/
#include "includes.h"

/*******************************************************************************
* Allocate task control blocks
*******************************************************************************/
static OS_TCB TaskStartTCB;
static OS_TCB UITaskTCB;
static OS_TCB PITTaskTCB;

/*******************************************************************************
* Allocate task stack space.
*******************************************************************************/
static CPU_STK TaskStartStk[APP_CFG_TASK_START_STK_SIZE];
static CPU_STK UITaskStk[APP_CFG_UITASK_STK_SIZE];
static CPU_STK  PITTaskStk[APP_CFG_TASK_PIT_STK_SIZE];

/*******************************************************************************
* Task Function Prototypes. 
*   - Private if in the same module as startup task. Otherwise public.
*******************************************************************************/
static void  StartTask(void *p_arg);
static void  UITask(void *p_arg);
void LcdDispResults(void);
static void PITTask(void *p_arg);
void PIT0_Handler(void);
void PIT1_Handler(void);
INT32U LPF_Averaging(INT32U lpfchannel);


/*******************************************************************************
* DEFINES
*******************************************************************************/
#define STAR        0x31
#define POUND       0x33
#define UP          0x32
#define DOWN        0x35
#define LEFT        0x34
#define RIGHT       0x36
#define ESC         0x11
#define ENT         0x12

#define MUSC_MASK    0x01
#define MUSC_ZERO   0
#define MUSC_ONE    1
#define MUSC_TWO    2
#define MUSC_THREE  3
#define MUSC_FOUR   4
#define MUSC_FIVE   5
#define MUSC_SIX    6
#define MUSC_SEVEN  7

#define RIGHT_TRI_CHANNEL     0x01
#define LEFT_TRI_CHANNEL      0x03
#define RIGHT_BI_CHANNEL      0x02
#define LEFT_BI_CHANNEL       0x04
#define RIGHT_CHEST_CHANNEL   0x05
#define LEFT_CHEST_CHANNEL    0x06
#define RIGHT_LAT_CHANNEL     0x07
#define LEFT_LAT_CHANNEL      0x08
/*******************************************************************************
* Enumerated Types
*******************************************************************************/
typedef enum {MAIN_MENU,REAL_MENU,CALIBRATION_MENU,BLUETOOTH_MENU,START_UP,
              BT_SETTINGS,CALI_SETTINGS,RTR_RUNNING}MENU;
typedef enum {FIRST,WAIT,PAIRED,DISPLAY,SEM}BT;
typedef enum {START,DO_IT}CALIBRATING;
typedef enum {BEGIN,REG,LCD,EXOSKELETON}RTR;
typedef enum {ONE_GROUP,SECOND_GROUP,THIRD_GROUP,RELAX_RUN,
	         RELAX_MUSCLE_PROMPT,FLEX_MUSCLE_PROMPT,FLEX_RUN,
	         RELAX_ANSWER,FLEX_ANSWER,STORE_VAL}CALVALUES;

/*******************************************************************************
* Variables
*******************************************************************************/
INT8U PIT_Flags[NUMFLAGS];
INT8U PIT_Sub_Flags[NUMFLAGS][NUMSUBFLAGS];
INT32U RequiredSamples;
INT32U SampleOrder[16];
INT32U Calibration_RefValue[16] =
   {CALIBRATION_BASEVALUE, CALIBRATION_BASEVALUE,
	CALIBRATION_BASEVALUE, CALIBRATION_BASEVALUE,
	CALIBRATION_BASEVALUE, CALIBRATION_BASEVALUE,
	CALIBRATION_BASEVALUE, CALIBRATION_BASEVALUE,
	CALIBRATION_BASEVALUE, CALIBRATION_BASEVALUE,
	CALIBRATION_BASEVALUE, CALIBRATION_BASEVALUE,
	CALIBRATION_BASEVALUE, CALIBRATION_BASEVALUE,
	CALIBRATION_BASEVALUE, CALIBRATION_BASEVALUE}; //Set to starting base values
INT32U Calibration_LowValue[16] =
   {CALIBRATION_LOWVALUE, CALIBRATION_LOWVALUE,
	CALIBRATION_LOWVALUE, CALIBRATION_LOWVALUE,
	CALIBRATION_LOWVALUE, CALIBRATION_LOWVALUE,
	CALIBRATION_LOWVALUE, CALIBRATION_LOWVALUE,
	CALIBRATION_LOWVALUE, CALIBRATION_LOWVALUE,
	CALIBRATION_LOWVALUE, CALIBRATION_LOWVALUE,
	CALIBRATION_LOWVALUE, CALIBRATION_LOWVALUE,
	CALIBRATION_LOWVALUE, CALIBRATION_LOWVALUE}; //Set to starting base values
INT32U ADCSamples[2048];
INT32U High_Samples;
INT32U Low_Samples;
INT32U Working_Channel;
INT32U Working_Pot_Setting;
INT32U Checked_Pot_Setting;
INT32U Pot_SignalSettings[4][4] = { //Signals 1-16, refer to 0-15, do not confuse with channels
	{128, 128, 128, 128},
	{128, 128, 128, 128},
	{128, 128, 128, 128},
	{128, 128, 128, 128} };
INT32U CalibrationRequestChannel; //Used to get potentiometer settings
INT32U CalibrationRawChannel; //Used to get the actual ADC Channel
INT32U ReturnDataAvg[16]; //Used to compare to Calibration_RefValue and Calibration_Lowvalue
INT32U ReturnData;
INT32U ComparisonData;
INT32U ResultsCounter;
INT8U  ResultData;
/*******************************************************************************
* Constants
*******************************************************************************/
const INT8U Bluetooth [] = "Bluetooth Settings";
const INT8U MenuLabel [] = "Menu";
const INT8U Main [] = "Main Menu";
const INT8U Start [] = "EMG Sensor Shirt";
const INT8U Engineers [] = "By: Josh and Dylan";
const INT8U CalibrateMen [] = "Calibration Menu";
const INT8U CaliQuest [] = "Calibration Process?";
const INT8U ReCaliQuest [] = "Calibrate next?";
const INT8U RealTime [] = "Real Time Results";
const INT8U CheckPaired [] = "Do you want to pair";
const INT8U CheckPairedTwo [] = "EXO_BT and EMG_SHIRT";
const INT8U Paired [] = "Yes it is Paired";
const INT8U Waiting [] = "Please Wait...";
const INT8U Already [] = "Device Paired";
const INT8U ShowDevice [] = "Display the device?";
const INT8U Device [] = "Paired Device Name:";
const INT8U Exo [] = "EXO_BT";
const INT8U ExoMac [] = "000666A0B8F1";
const INT8U Calibrate [] = "Which muscle do you";
const INT8U Prompt [] = "want to calibrate?";
//these are the const for the calibration menu with the button presses next to
//them either Left/Right pertaining to the button and the muscle as well as # or
//* for the other button they can press to choose that muscle
const INT8U RightTri [] = "Right Tricep";   //channel 0
const INT8U LeftTri [] = "Left Tricep";     //channel 2
const INT8U RightBi [] = "Right Bicep";     //channel 1
const INT8U LeftBi [] = "Left Bicep";       //channel 3
const INT8U RightChest [] = "# Right Chest";//channel 4
const INT8U LeftChest [] = "* Left Chest";  //channel 5
const INT8U RightLat [] = "Right Lat";      //channel 6
const INT8U LeftLat [] = "Left Lat";        //channel 7
//these are the const for the real time results with just the name of the muscle
const INT8U RightChestMuscle [] = "Right Chest";
const INT8U LeftChestMuscle [] = "Left Chest";
const INT8U Run [] = "Run Muscle Baseline";
const INT8U Correct [] = "Press ENT if YES";
const INT8U Incorrect [] = "Press ESC if NO";
const INT8U PleaseRelax [] = "Please Relax Muscle";
const INT8U RelaxQuest [] = "Is muscle relaxed?";
const INT8U FlexQuest [] = "Is muscle flexed?";
const INT8U PleaseFlex [] = "Flex Chosen Muscle..";
const INT8U Stored [] = "STORED VALUE";

const INT8U ResultsLcdDispZero [] = "LCD Results Shows";
const INT8U ResultsLcdDispOne [] = "the state that your";
const INT8U ResultsLcdDispTwo [] = "specific muscles are";
const INT8U ResultsLcdDispThree [] = "in, CONTRACTED/NOT.";
const INT8U Yes [] = "CONTRACT";
const INT8U No [] = "NOT";
const INT8U ExoResult [] = "Exoskeleton Ready";
const INT8U Processing [] = "Processing";
/*******************************************************************************
* Structure Instances
*******************************************************************************/
MENU Menu;
BT BTooth;
CALIBRATING Cali;
CALVALUES CalcValues;
RTR Real;
INT8U SemFlag = TRUE;
/*******************************************************************************
* main()
*******************************************************************************/
int main(void) {
    OS_ERR  err;

    CPU_Init();

    CPU_IntDis();       /* Disable all interrupts, OS will enable them */

    OSInit(&err);       /* Initialise uC/OS-III  */
    OS_ERR  os_err;

    BSP_Init();                           /* BSP, CPU, OS Tick initialization */
//
    OSInit(&os_err);            /* Initialize uC/OS-III                       */

    OSTaskCreate((OS_TCB     *)&TaskStartTCB,    /* Create the start task  */
                 (CPU_CHAR   *)"Start Task ",
                 (OS_TASK_PTR ) StartTask,
                 (void       *) 0,
                 (OS_PRIO     ) APP_CFG_TASK_START_PRIO,
                 (CPU_STK    *)&TaskStartStk[0],
                 (CPU_STK     )(APP_CFG_TASK_START_STK_SIZE / 10u),
                 (CPU_STK_SIZE) APP_CFG_TASK_START_STK_SIZE,
                 (OS_MSG_QTY  ) 0,
                 (OS_TICK     ) 0,
                 (void       *) 0,
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                 (OS_ERR     *)&os_err);

    while(os_err != OS_ERR_NONE){           /* Error Trap                     */
    }

    OSStart(&os_err);       /*Start multitasking(i.e. give control to uC/OS)  */

    while(DEF_ON){}         /* Should Never Get Here    */
    
}

/*******************************************************************************
* STARTUP TASK
*******************************************************************************/
static void StartTask(void *p_arg) {
    OS_ERR os_err;
    (void)p_arg;                /* Avoid compiler warning for unused variable */
    LcdInit();
	KeyInit();
    UARTInit();
    PITTaskInit();
    OSStatTaskCPUUsageInit(&os_err);        /* Initialize start task          */
    while(os_err != OS_ERR_NONE){           /* Error Trap                     */
    }

	OSTaskCreate((OS_TCB     *)&UITaskTCB,
				(CPU_CHAR   *)"UITask ",
				(OS_TASK_PTR ) UITask,
				(void       *) 0,
				(OS_PRIO     ) APP_CFG_UITASK_PRIO,
				(CPU_STK    *)&UITaskStk[0],
				(CPU_STK     )(APP_CFG_UITASK_STK_SIZE / 10u),
				(CPU_STK_SIZE) APP_CFG_UITASK_STK_SIZE,
				(OS_MSG_QTY  ) 0,
				(OS_TICK     ) 0,
				(void       *) 0,
				(OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
				(OS_ERR     *)&os_err);
	while(os_err != OS_ERR_NONE){           /* Error Trap                     */
	}

	OSTaskCreate((OS_TCB     *)&PITTaskTCB,    /* Create the start task    */
				 (CPU_CHAR   *)"PIT Task ",
				 (OS_TASK_PTR ) PITTask,
				 (void       *) 0,
				 (OS_PRIO     ) APP_CFG_TASK_PIT_PRIO,
				 (CPU_STK    *)&PITTaskStk[0],
				 (CPU_STK     )(APP_CFG_TASK_PIT_STK_SIZE / 10u),
				 (CPU_STK_SIZE) APP_CFG_TASK_PIT_STK_SIZE,
				 (OS_MSG_QTY  ) 0,
				 (OS_TICK     ) 0,
				 (void       *) 0,
				 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
				 (OS_ERR     *)&os_err);

	while(os_err != OS_ERR_NONE){           /* Error Trap                     */
	}
}
/*******************************************************************************
* UITask()
* Description: Takes in the user input in order to change the state of which
*              the clock is in. So at the start it opens up in the time setting
*              state then as numbers are inserted they will show up on the
*              LCD and if A is pressed it will replace row clock time with the
*              new time set by the user. If C button is pressed then it will
*              clear the line 2 and leave the clock on top counting with no
*              change. Then to set another new time the user must re-press the
*              '#' button
* Last Updated by Dylan Kleist  02/23/2014
*******************************************************************************/
static void UITask(void *p_arg){
	OS_ERR os_err;
    (void)p_arg;
    static INT8U start_flag = TRUE;                          //initial time flag
	static INT8U init_flag = TRUE;
	Real = REG;
	INT8U key_input;
    static INT8U cnt = 0;
    if(start_flag == TRUE){
    	LcdDispClear(TITLE_LAYER);
		LcdDispString(2,3,TITLE_LAYER,Start);  //start up message for the LCD
		LcdDispString(3,2,TITLE_LAYER,Engineers);
		start_flag = FALSE;
	}else{ /*Do Nothing*/
	}
    if(init_flag == TRUE){
    	Menu = START_UP;
    	init_flag = FALSE;
	}else{ /*Do Nothing*/
	}

    while(1) {
    	if((Real != LCD)&&(BTooth != WAIT)&&(CalcValues != RELAX_RUN)/*&&(CalcValues != (FLEX_RUN || RELAX_RUN))*/){
    	key_input = KeyPend(0,&os_err);  //waiting for a key press
		while(os_err != OS_ERR_NONE){               /* Error Trap         */
		}
    	}else{}
    	switch(Menu){
    	case START_UP:
    		LcdDispClear(TITLE_LAYER);
			LcdDispString(2,8,UI_LAYER,Main);
			Menu = MAIN_MENU;
			break;
		case MAIN_MENU:
			if(key_input == DOWN){           //when in main menu must press down
				LcdDispClear(UI_LAYER);      //to enter into the actual menu
				LcdDispString(2,2,UI_LAYER,Bluetooth);  //options, first is BT
				LcdDispString(3,9,UI_LAYER,MenuLabel);
				LcdDispChar(4,9,UI_LAYER,0x18);
				Menu = BLUETOOTH_MENU;
			}else{
			}
			break;
		case BLUETOOTH_MENU:   //when the LCD displays BT Settings Menu this
			if(key_input == RIGHT){  //is where you can go from there either
				LcdDispClear(UI_LAYER);
				LcdDispString(2,3,UI_LAYER,CalibrateMen);//to Calibration menu
				Menu = CALIBRATION_MENU;
			}else if(key_input == LEFT){
				LcdDispClear(UI_LAYER);
				LcdDispString(2,2,UI_LAYER,RealTime); //to Real Time Results
				Menu = REAL_MENU;                     //menu
				Real = REG;
			}else if(key_input == DOWN){
				LcdDispClear(UI_LAYER);       //go into the menu settings
				LcdDispString(1,1,BT_LAYER,CheckPaired); //for the Bluetooth
				LcdDispString(2,1,BT_LAYER,CheckPairedTwo);
				LcdDispString(3,1,BT_LAYER,Correct);
				LcdDispString(4,1,BT_LAYER,Incorrect);
				BTooth = FIRST;
				Menu = BT_SETTINGS;
			}
			break;
		case BT_SETTINGS:
			switch(BTooth){
				case FIRST:
					if (key_input == ENT){
						LcdDispClear(BT_LAYER);
						LcdDispString(2,3,BT_LAYER,Waiting);
						BTooth = WAIT;
					}else if(key_input == ESC){
						LcdDispClear(BT_LAYER);
						LcdDispString(2,2,UI_LAYER,Bluetooth);
						LcdDispString(3,9,UI_LAYER,MenuLabel);
						BTooth = FIRST;
						Menu = BLUETOOTH_MENU;
					}else{
					}
				break;
				case WAIT:
					UARTTransmitByte('$');
					UARTTransmitByte('$');
					UARTTransmitByte('$');
					OSTimeDly(500,OS_OPT_TIME_DLY,&os_err);
					while(os_err != OS_ERR_NONE){               /* Error Trap         */
					}
					UARTTransmitByte(0x0A);
					UARTTransmitByte('C');
					UARTTransmitByte(0x0D);

					//Bluetooth Pairing Connecting Code
					OSTimeDly(15000,OS_OPT_TIME_DLY,&os_err);
					while(os_err != OS_ERR_NONE){               /* Error Trap         */
					}
					LcdDispString(1,1,BT_LAYER,Paired);
					LcdDispString(2,1,BT_LAYER,ShowDevice);
					LcdDispString(3,1,BT_LAYER,Correct);
					LcdDispString(4,1,BT_LAYER,Incorrect);
					BTooth = PAIRED;
				break;
				case PAIRED:
					if(key_input == ENT){
						LcdDispClear(BT_LAYER);
						LcdDispString(1,1,BT_LAYER,Device);
						LcdDispString(2,1,BT_LAYER,Exo);
						LcdDispString(3,1,BT_LAYER,ExoMac);
						BTooth = DISPLAY;
					}else if(key_input == ESC){
						LcdDispString(2,2,UI_LAYER,Bluetooth);
						LcdDispString(3,9,UI_LAYER,MenuLabel);
						BTooth = FIRST;
						Menu = BLUETOOTH_MENU;
						LcdDispClear(BT_LAYER);
					}else{
					}
				break;
				case DISPLAY:
					if(key_input == ENT){
						LcdDispClear(BT_LAYER);
						LcdDispString(2,2,UI_LAYER,Bluetooth);
						LcdDispString(3,9,UI_LAYER,MenuLabel);
						Menu = BLUETOOTH_MENU;
						BTooth = FIRST;
					}else{
					}
				break;
				default:
					BTooth = FIRST;
				break;
				}
			break;
		case CALIBRATION_MENU:  //when the LCD displays Calibration Menu
			if(key_input == RIGHT){  //pressing right brings you to the RTR
				LcdDispClear(1);
				LcdDispString(2,2,UI_LAYER,RealTime);
				Menu = REAL_MENU;
				Real = REG;
			}else if(key_input == LEFT){ //pressing left brings you to the BT
				LcdDispClear(1);
				LcdDispString(2,2,UI_LAYER,Bluetooth);
				LcdDispString(3,9,UI_LAYER,MenuLabel);
				Menu = BLUETOOTH_MENU;
			}else if(key_input == DOWN){         //pressing down brings you into
				LcdDispClear(UI_LAYER);          //calibration settings display
				LcdDispString(2,1,CAL_LAYER,CaliQuest);
				Menu = CALI_SETTINGS;
				Cali = START;
			}else{}
		break;
		case CALI_SETTINGS:
			switch(Cali){
			case START:
				if(key_input == ENT){
					LcdDispClear(CAL_LAYER);
					LcdDispString(1,1,CAL_LAYER,Calibrate);
					LcdDispString(2,1,CAL_LAYER,Prompt);
					LcdDispString(3,1,CAL_LAYER,RightTri);
					LcdDispString(4,1,CAL_LAYER,LeftTri);
					Cali = DO_IT;
					CalcValues = ONE_GROUP;
				}else if(key_input == ESC){
					LcdDispClear(CAL_LAYER);
					LcdDispString(2,2,UI_LAYER,CalibrateMen);
					Menu = CALIBRATION_MENU;
				}else{
				}
			break;
			case DO_IT:
				switch(CalcValues){
				case ONE_GROUP:
					if(key_input == DOWN){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,RightBi);
						LcdDispString(2,1,CAL_LAYER,LeftBi);
						LcdDispString(3,1,CAL_LAYER,RightChest);
						LcdDispString(4,1,CAL_LAYER,LeftChest);
						CalcValues = SECOND_GROUP;
					}else if(key_input == ESC){
						LcdDispClear(CAL_LAYER);
						LcdDispString(2,2,UI_LAYER,CalibrateMen);
						CalibrationRequestChannel = 0x00;
						Clear_Flag(CALIBRATION_FLAG);
						CalcValues = ONE_GROUP;
						Menu = CALIBRATION_MENU;
						Cali = START;
					}else if(key_input == RIGHT){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,Run);
						LcdDispString(2,1,CAL_LAYER,RightTri);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalibrationRequestChannel = RIGHT_TRI_CHANNEL; //channel 1
						Set_Flag(CALIBRATION_FLAG);
						OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
						while(os_err != OS_ERR_NONE){           /* Error Trap     */
						}
						OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
						while(os_err != OS_ERR_NONE){       /* Error Trap                 */
						}
						CalcValues = FLEX_MUSCLE_PROMPT;
					}else if(key_input == LEFT){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,Run);
						LcdDispString(2,1,CAL_LAYER,LeftTri);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalibrationRequestChannel = LEFT_TRI_CHANNEL; //channel 3
						Set_Flag(CALIBRATION_FLAG);
						OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
						while(os_err != OS_ERR_NONE){           /* Error Trap     */
						}
						OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
						while(os_err != OS_ERR_NONE){       /* Error Trap                 */
						}
						CalcValues = FLEX_MUSCLE_PROMPT;
					}else{
					}
					break;
				case SECOND_GROUP:
					if(key_input == DOWN){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,RightLat);
						LcdDispString(2,1,CAL_LAYER,LeftLat);
						CalcValues = THIRD_GROUP;
				    }else if(key_input == UP){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,Calibrate);
						LcdDispString(2,1,CAL_LAYER,Prompt);
						LcdDispString(3,1,CAL_LAYER,RightTri);
						LcdDispString(4,1,CAL_LAYER,LeftTri);
						CalcValues = ONE_GROUP;
					}else if(key_input == ESC){
						LcdDispClear(CAL_LAYER);
						LcdDispString(2,2,UI_LAYER,CalibrateMen);
						Clear_Flag(CALIBRATION_FLAG);
						CalcValues = ONE_GROUP;
						Menu = CALIBRATION_MENU;
						Cali = START;
					}else if(key_input == RIGHT){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,Run);
						LcdDispString(2,1,CAL_LAYER,RightBi);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalibrationRequestChannel = RIGHT_BI_CHANNEL;//channel 2
						Set_Flag(CALIBRATION_FLAG);
						OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
						while(os_err != OS_ERR_NONE){           /* Error Trap     */
						}
						OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
						while(os_err != OS_ERR_NONE){       /* Error Trap                 */
						}
						CalcValues = FLEX_MUSCLE_PROMPT;
					}else if(key_input == LEFT){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,Run);
						LcdDispString(2,1,CAL_LAYER,LeftBi);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalibrationRequestChannel = LEFT_BI_CHANNEL;//channel 4
						Set_Flag(CALIBRATION_FLAG);
						OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
						while(os_err != OS_ERR_NONE){           /* Error Trap     */
						}
						OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
						while(os_err != OS_ERR_NONE){       /* Error Trap                 */
						}
						CalcValues = FLEX_MUSCLE_PROMPT;
					}else if(key_input == POUND){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,Run);
						LcdDispString(2,1,CAL_LAYER,RightChestMuscle);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalibrationRequestChannel = RIGHT_CHEST_CHANNEL;//channel 5
						Set_Flag(CALIBRATION_FLAG);
						OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
						while(os_err != OS_ERR_NONE){           /* Error Trap     */
						}
						OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
						while(os_err != OS_ERR_NONE){       /* Error Trap                 */
						}
						CalcValues = FLEX_MUSCLE_PROMPT;
					}else if(key_input == STAR){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,Run);
						LcdDispString(2,1,CAL_LAYER,LeftChestMuscle);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalibrationRequestChannel = LEFT_CHEST_CHANNEL;//channel 6
						Set_Flag(CALIBRATION_FLAG);
						OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
						while(os_err != OS_ERR_NONE){           /* Error Trap     */
						}
						OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
						while(os_err != OS_ERR_NONE){       /* Error Trap                 */
						}
						CalcValues = FLEX_MUSCLE_PROMPT;
					}else{
					}
					break;
				case THIRD_GROUP:
					if(key_input == UP){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,RightBi);
						LcdDispString(2,1,CAL_LAYER,LeftBi);
						LcdDispString(3,1,CAL_LAYER,RightChest);
						LcdDispString(4,1,CAL_LAYER,LeftChest);
						CalcValues = SECOND_GROUP;
					}else if(key_input == ESC){
						LcdDispClear(CAL_LAYER);
						LcdDispString(2,2,UI_LAYER,CalibrateMen);
						CalibrationRequestChannel = 0x00;
						Clear_Flag(CALIBRATION_FLAG);
						CalcValues = ONE_GROUP;
						Menu = CALIBRATION_MENU;
						Cali = START;
					}else if(key_input == RIGHT){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,Run);
						LcdDispString(2,1,CAL_LAYER,RightLat);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalibrationRequestChannel = RIGHT_LAT_CHANNEL;//channel 7
						Set_Flag(CALIBRATION_FLAG);
						OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
						while(os_err != OS_ERR_NONE){           /* Error Trap     */
						}
						OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
						while(os_err != OS_ERR_NONE){       /* Error Trap                 */
						}
						CalcValues = FLEX_MUSCLE_PROMPT;
					}else if(key_input == LEFT){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,Run);
						LcdDispString(2,1,CAL_LAYER,LeftLat);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalibrationRequestChannel = LEFT_LAT_CHANNEL;//channel 8
						Set_Flag(CALIBRATION_FLAG);
						OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
						while(os_err != OS_ERR_NONE){           /* Error Trap     */
						}
						OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
						while(os_err != OS_ERR_NONE){       /* Error Trap                 */
						}
						CalcValues = FLEX_MUSCLE_PROMPT;
					}else{
					}
					break;
				case RELAX_MUSCLE_PROMPT:
					if(key_input == ENT){
						CalcValues = RELAX_RUN;
					}else if(key_input == ESC){
						LcdDispClear(CAL_LAYER);
						LcdDispString(2,2,UI_LAYER,CalibrateMen);
						Clear_Flag(CALIBRATION_FLAG);
						CalcValues = ONE_GROUP;
						Menu = CALIBRATION_MENU;
						Cali = START;
					}
					break;
				case RELAX_RUN:
						//post semaphore along with setting flag for specific muscle
						OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
						while(os_err != OS_ERR_NONE){           /* Error Trap     */
						}
						OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
						while(os_err != OS_ERR_NONE){       /* Error Trap                 */
						}
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,4,CAL_LAYER,Stored);
						LcdDispString(2,1,CAL_LAYER,ReCaliQuest);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalcValues = STORE_VAL;
					break;
				case FLEX_MUSCLE_PROMPT:
					if(key_input == ENT){
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,PleaseFlex);
						LcdDispString(2,1,CAL_LAYER,FlexQuest);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalcValues = FLEX_RUN;
					}else if(key_input == ESC){
						LcdDispClear(CAL_LAYER);
						LcdDispString(2,2,UI_LAYER,CalibrateMen);
						Clear_Flag(CALIBRATION_FLAG);
						CalcValues = ONE_GROUP;
						Menu = CALIBRATION_MENU;
						Cali = START;
					}else{
					}
					break;
				case FLEX_RUN:
					if(key_input == ENT){
						LcdDispClear(CAL_LAYER);
						LcdDispString(2,4,CAL_LAYER,Processing);
						OSTimeDly(100,OS_OPT_TIME_DLY,&os_err);
						while(os_err != OS_ERR_NONE){               /* Error Trap         */
						}
						//post semaphore along with setting flag for specific muscle
						OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
						while(os_err != OS_ERR_NONE){           /* Error Trap     */
						}
						OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
						while(os_err != OS_ERR_NONE){       /* Error Trap                 */
						}
						LcdDispClear(CAL_LAYER);
						LcdDispString(1,1,CAL_LAYER,PleaseRelax);
						LcdDispString(2,1,CAL_LAYER,RelaxQuest);
						LcdDispString(3,1,CAL_LAYER,Correct);
						LcdDispString(4,1,CAL_LAYER,Incorrect);
						CalcValues = RELAX_MUSCLE_PROMPT;
					}else if(key_input == ESC){
						LcdDispClear(CAL_LAYER);
						LcdDispString(2,2,UI_LAYER,CalibrateMen);
						Clear_Flag(CALIBRATION_FLAG);
						CalcValues = ONE_GROUP;
						Menu = CALIBRATION_MENU;
						Cali = START;
					}else{}
					break;
				case STORE_VAL:
					//store new value from data.c for specific muscles
					if(key_input == ENT){
						LcdDispClear(CAL_LAYER);
						LcdDispString(2,2,UI_LAYER,CalibrateMen);
						Clear_Flag(CALIBRATION_FLAG);
						CalcValues = ONE_GROUP;
						Menu = CALIBRATION_MENU;
						Cali = START;
					}else if(key_input == ESC){
						LcdDispClear(CAL_LAYER);
						LcdDispString(2,2,UI_LAYER,CalibrateMen);
						Clear_Flag(CALIBRATION_FLAG);
						CalcValues = ONE_GROUP;
						Menu = CALIBRATION_MENU;
						Cali = START;
					}else{}
					break;
				default:
					break;
				}
				break;
			default:
				Cali = START;
			break;
			}
			break;
		case REAL_MENU:
			switch(Real){
			case REG:
				if(key_input == LEFT){ //pressing left brings you to Calibration
					LcdDispClear(UI_LAYER);
					LcdDispString(2,3,UI_LAYER,CalibrateMen);
					Menu = CALIBRATION_MENU;
				}else if(key_input == RIGHT){//pressing right brings you to BT
					LcdDispClear(UI_LAYER);
					LcdDispString(2,2,UI_LAYER,Bluetooth);
					LcdDispString(3,9,UI_LAYER,MenuLabel);
					Menu = BLUETOOTH_MENU;
				}else if(key_input == DOWN){//pressing left puts you into RTR
					LcdDispClear(UI_LAYER);
					LcdDispString(1,1,RTR_LAYER,ResultsLcdDispZero);
					LcdDispString(2,1,RTR_LAYER,ResultsLcdDispOne);
					LcdDispString(3,1,RTR_LAYER,ResultsLcdDispTwo);
					LcdDispString(4,1,RTR_LAYER,ResultsLcdDispThree);
					Clear_Flag(CALIBRATION_FLAG);
					Clear_Flag(STOP_FLAG);
					Set_Flag(CONTINUOUS_FLAG);
					Real = LCD;
					OSTimeDly(5000,OS_OPT_TIME_DLY,&os_err);
					while(os_err != OS_ERR_NONE){               /* Error Trap         */
					}
				}else{
				}
				break;
			case LCD:
				cnt++;
				OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE,&os_err);
				while(os_err != OS_ERR_NONE){           /* Error Trap     */
				}
				OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0,&os_err);
				while(os_err != OS_ERR_NONE){       /* Error Trap                 */
				}
				UARTTransmitByte(ResultData);
				OSTimeDly(10,OS_OPT_TIME_DLY,&os_err);
				while(os_err != OS_ERR_NONE){               /* Error Trap         */
				}
				if (cnt == 20) {
					//Lcd Disp first four muscle with a Y or N for contracting
					LcdDispClear(RTR_LAYER);
					LcdDispString(1, 1, RTR_LAYER, RightTri);
					LcdDispString(2, 1, RTR_LAYER, LeftTri);
					LcdDispString(3, 1, RTR_LAYER, RightBi);
					LcdDispString(4, 1, RTR_LAYER, LeftBi);
					if (((ResultData >> MUSC_ZERO) & MUSC_MASK) == TRUE){
						LcdDispString(1, 13, RTR_LAYER, Yes);
					} else {
						LcdDispString(1, 18, RTR_LAYER, No);
					}
					if (((ResultData>>MUSC_TWO) & MUSC_MASK) == TRUE){
						LcdDispString(2, 13, RTR_LAYER, Yes);
					} else {
						LcdDispString(2, 18, RTR_LAYER, No);
					}
					if (((ResultData >>MUSC_ONE)& MUSC_MASK) == TRUE){
						LcdDispString(3, 13, RTR_LAYER, Yes);
					} else {
						LcdDispString(3, 18, RTR_LAYER, No);
					}
					if (((ResultData>>MUSC_THREE) & MUSC_MASK) == TRUE){
						LcdDispString(4, 13, RTR_LAYER, Yes);
					} else {
						LcdDispString(4, 18, RTR_LAYER, No);
					}
				} else if (cnt == 40) {
					//Lcd Disp second four muscles with Y or N for contracting
					LcdDispClear(RTR_LAYER);
					LcdDispString(1, 1, RTR_LAYER, RightChestMuscle);
					LcdDispString(2, 1, RTR_LAYER, LeftChestMuscle);
					LcdDispString(3, 1, RTR_LAYER, RightLat);
					LcdDispString(4, 1, RTR_LAYER, LeftLat);
					cnt = 0;
					if (((ResultData >>MUSC_FOUR)& MUSC_MASK) == TRUE){
						LcdDispString(1, 13, RTR_LAYER, Yes);
					} else {
						LcdDispString(1, 18, RTR_LAYER, No);
					}
					if (((ResultData >> MUSC_FIVE)& MUSC_MASK) == TRUE){
						LcdDispString(2, 13, RTR_LAYER, Yes);
					} else {
						LcdDispString(2, 18, RTR_LAYER, No);
					}
					if (((ResultData >> MUSC_SIX )& MUSC_MASK) == TRUE){
						LcdDispString(3, 13, RTR_LAYER, Yes);
					} else {
						LcdDispString(3, 18, RTR_LAYER, No);
					}
					if (((ResultData >> MUSC_SEVEN)& MUSC_MASK) == TRUE){
						LcdDispString(4, 13, RTR_LAYER, Yes);
					} else {
						LcdDispString(4, 18, RTR_LAYER, No);
					}
				}else{
				}
				break;
			default:
				Real = REG;
				break;
			}
			break;
		default:
			Menu = REAL_MENU;
			break;
		}
    }
}
/******************************************************************************
 PIT_Task() -
******************************************************************************/
static void PITTask(void *p_arg) {
    OS_ERR os_err;

    // Avoid compiler warning
    (void)p_arg;

    while(1) {

        OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,(void *)0, &os_err);
		while(os_err != OS_ERR_NONE){
		}/*Check for Error*/

        if(Read_Flag(CALIBRATION_FLAG)==SET){ //SET THE CALIBRATION_FLAG AND POST PITTask SEMAPHORE IN UITask TO RUN THIS CODE
        	if(Read_AllSubFlags(CALIBRATION_FLAG)==CLEAR){
        		/* ENTER CALIBRATION MODE, SET TIMER PERIOD, SET SWITCHES,
        		 SET SAMPLE ORDER, SET NUMBER SAMPLES, WAIT FOR USER BUTTON
        		 PRESS "FLEX MUSCLE, PRESS ENT TO START" */

        		Set_Switch(CalibrationRequestChannel);//Set Switch
        		CalibrationRawChannel = Get_Raw_Channel(CalibrationRequestChannel);//Get the raw signal channel
        		Build_Sample_Order(CalibrationRawChannel);//Setup the sample order
        		RequiredSamples = 2048;
        		Set_TimerPeriod(1, 25); //Sets timer 1 at 25uS Period, 40kHz
        		Set_SubFlag(CALIBRATION_FLAG,CALIBRATION_SUBFLAG0);
        		OSTaskSemPost(&UITaskTCB,OS_OPT_POST_NONE,&os_err); //Waiting for button press
        		while(os_err != OS_ERR_NONE){
				}/*Check for Error*/
        		// "FLEX MUSCLE", BUTTONPRESS (CHECK FOR CALIBRATION_SUBFLAG0, POST PITTask SEMAPHORE)


        	}else if(Read_SubFlag(CALIBRATION_FLAG,CALIBRATION_SUBFLAG0)==SET){
        		/* START SAMPLE TIMER(PIT1ISR), CLEAR SUBFLAG0, SET SUBFLAG1 */

        		Start_Timer(1);
        		Clear_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG0);
        		Set_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG1);

        	}else if(Read_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG1)==SET){
        		/* REENTRY AFTER SAMPLE TIMER(PIT1ISR) COMPLETE, CHECK FOR HIGH/LOW
        		 DATA VALUES, DETERMINE GAIN CHANGE, SET GAIN OR RE-RUN SAMPLES TO
        		 CHECK NEW GAIN, IF SET GAIN CLEAR SUBFLAG1 AND SET SUBFLAG2 */

        		High_Samples = Check_High_Samples(RequiredSamples);
        		Low_Samples = Check_Low_Samples(RequiredSamples);
        		Working_Pot_Setting = Get_PotSetting(CalibrationRequestChannel);
        		Checked_Pot_Setting = Check_Numbers(High_Samples, Low_Samples, Working_Pot_Setting);

        		if(Working_Pot_Setting == Checked_Pot_Setting){//gain is good, move to next phase
            		RequiredSamples = 5; //Sets a dummy wait pass so the LPF filter signals can setup
            		Set_TimerPeriod(0, 2500); //Sets switch timer 0 at 2500uS period, 400Hz
            		Set_TimerPeriod(1, 50000); //Sets timer 1 at 20Hz for setup pass
        			Clear_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG1);
        			Set_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG2);
        			Start_Timer(0); //Starts switching
        			Start_Timer(1); //Starts sampling
        		}else{ //Gain requires readjustment
        			Working_Pot_Setting = Checked_Pot_Setting;
        			Set_PotSetting(CalibrationRequestChannel, Working_Pot_Setting);
            		RequiredSamples = 2048;
            		Set_TimerPeriod(1, 25);
        			Start_Timer(1);
        		}

        	}else if(Read_SubFlag(CALIBRATION_FLAG,CALIBRATION_SUBFLAG2)==SET){
        		/* REENTRY AFTER WAIT PASS, SETUP FOR LPF CALIBRATION MEASUREMENTS
        		 * SWITCH TIMER IS ALREADY RUNNING */

        		RequiredSamples = 128;
        		Set_TimerPeriod(1, 200); //Complete required samples in 25mS.
        		Build_Sample_Order(CalibrationRequestChannel); //Build the sample order for the LPF channels
        		Clear_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG2);
        		Set_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG3);
        		Start_Timer(1);

        	}else if(Read_SubFlag(CALIBRATION_FLAG,CALIBRATION_SUBFLAG3)==SET){
        		/* REENTRY AFTER LPF PASS, AVERAGE SAMPLES, STORE AS NEW CALIBRATION HIGH VALUE */

        		Calibration_RefValue[CalibrationRequestChannel] = Average_Samples(RequiredSamples);
        		Set_TimerPeriod(1,200);
        		Clear_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG3);
        		Set_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG4);
        		OSTaskSemPost(&UITaskTCB,OS_OPT_POST_NONE,&os_err); //Waiting for button press

        		// "RELAX MUSCLE", BUTTONPRESS (CHECK FOR CALIBRATION_SUBFLAG4,POST PITTask SEMAPHORE)

        	}else if(Read_SubFlag(CALIBRATION_FLAG,CALIBRATION_SUBFLAG4)==SET){
        		/* REENTRY AFTER BUTTONPRESS, START TIMER */

        		Start_Timer(1);
        		Clear_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG4);
        		Set_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG5);

        	}else if(Read_SubFlag(CALIBRATION_FLAG,CALIBRATION_SUBFLAG5)==SET){
        		/* REENTRY AFTER LFP "RELAXED" PASS, AVERAGE SAMPLES, STORE AS NEW CALIBRATION LOW VALUE */

        		Stop_Timer(0); //Stop the switching
        		Calibration_LowValue[CalibrationRequestChannel] = Average_Samples(RequiredSamples);
        		Clear_SubFlag(CALIBRATION_FLAG, CALIBRATION_SUBFLAG5);
        		OSTaskSemPost(&UITaskTCB,OS_OPT_POST_NONE, &os_err); //Waiting for button press
        		while(os_err != OS_ERR_NONE){
				}/*Check for Error*/
        		// "CALIBRATION COMPLETE", CLEAR CALIBRATION_FLAG

        	}else{/*Do Nothing */}
        }else{/* Do Nothing */}

        if(Read_Flag(CONTINUOUS_FLAG)==SET){
        	if((Read_AllSubFlags(CONTINUOUS_FLAG))==CLEAR){
        	        		Build_Sample_Order(BUILD_ALL); //Build the sample order for the LPF channels
        	        		RequiredSamples = 1;
        	        		Set_TimerPeriod(0, 2500); //Sets switch timer 0 at 2500uS period, 400Hz
        	        		Set_TimerPeriod(1, 50000); //Sets timer 1 at 20Hz for setup pass
        	        		Set_SubFlag(CONTINUOUS_FLAG,CONTINUOUS_SUBFLAG0);
        	    			Start_Timer(0); //Starts switching
        	    			Start_Timer(1); //Starts sampling

        	        	}else if(Read_SubFlag(CONTINUOUS_FLAG, CONTINUOUS_SUBFLAG0)==SET){
        	        		RequiredSamples = 1024;
        	        		Set_TimerPeriod(1, 50); //Sets timer 1 at 20kHz for sampling
        	        		Start_Timer(1);
        	        		Clear_SubFlag(CONTINUOUS_FLAG, CONTINUOUS_SUBFLAG0);
        	        		Set_SubFlag(CONTINUOUS_FLAG, CONTINUOUS_SUBFLAG1);

        	        	}else if(Read_SubFlag(CONTINUOUS_FLAG, CONTINUOUS_SUBFLAG1)==SET){
        	        		ResultData = 0;//Clear to build new results
        	        		for(ResultsCounter = 0; ResultsCounter < MAX_CHANNELS; ResultsCounter++){
        	        			ReturnDataAvg[ResultsCounter] = LPF_Averaging(ResultsCounter); //Returns the average value of the channel for this iteration
        	        		}
        	        		for(ResultsCounter = 1; ResultsCounter <= WORKING_CHANNELS; ResultsCounter++){
        	        			ReturnData = ReturnDataAvg[ResultsCounter];
        	        			ComparisonData = Calibration_LowValue[ResultsCounter];
        	        			ComparisonData += ((Calibration_RefValue[ResultsCounter] - Calibration_LowValue[ResultsCounter])/2);
        	        			if(ReturnData >= ComparisonData){
        	        				ResultData |= (1 << (ResultsCounter-1));
        	        			}else{ /* Do Nothing */}
        	        		}
        	        		Clear_SubFlag(CONTINUOUS_FLAG, CONTINUOUS_SUBFLAG1);
        	        		Set_SubFlag(CONTINUOUS_FLAG, CONTINUOUS_SUBFLAG0);
        	        		OSTaskSemPost(&UITaskTCB,OS_OPT_POST_NONE, &os_err); //Send Data to UART/Real Time Results
        	        	}else{ /* Do Nothing */}

        }else{/* Do Nothing */}

        if(Read_Flag(STOP_FLAG)==SET){


        }else{/* Do Nothing */}


    }
}
/******************************************************************************
PIT0ISR() - ISR for the PIT0 timer. Interrupt priority 1.

SWITCH TIMER - This ISR controls the GPIO switching for the EMG shirt control
system. This is used in LPF mode.

******************************************************************************/
void PIT0_Handler(void){
	INT32U switchposition;

//    OS_ERR os_err;

    OSIntEnter();       //Tell OS that we are in an interrupt

	PIT_TFLG0 = PIT_TFLG_TIF_MASK; //Writing Clears the interrupt flag
	switchposition = (GPIOD_PDOR & ANALOGSWITCHMASK);
	switch (switchposition){//Set to next switch position
	case (SWITCHPOSONE):
		GPIOD_PDOR &= ~ANALOGSWITCHMASK;
		GPIOD_PDOR |= SWITCHPOSTWO;
		break;
	case (SWITCHPOSTWO):
		GPIOD_PDOR &= ~ANALOGSWITCHMASK;
		GPIOD_PDOR |= SWITCHPOSTHREE;
		break;
	case (SWITCHPOSTHREE):
		GPIOD_PDOR &= ~ANALOGSWITCHMASK;
		GPIOD_PDOR |= SWITCHPOSFOUR;
		break;
	case (SWITCHPOSFOUR):
		GPIOD_PDOR &= ~ANALOGSWITCHMASK;
		GPIOD_PDOR |= SWITCHPOSONE;
		break;
	default:   //Default case, will automatically start the switch routine
		GPIOD_PDOR &= ~ANALOGSWITCHMASK;
		GPIOD_PDOR |= SWITCHPOSONE;
		break;
	}

	OSIntExit();
}

/******************************************************************************
PIT1ISR() - ISR for the PIT1 timer. Interrupt priority 2.

SAMPLE TIMER - This ISR controls the ADC sampling of channels for the EMG shirt
control system.

Main functions modify the following variables:
		-static INT32U samplecount
		-SampleOrder
		-ADC

******************************************************************************/
void PIT1_Handler(void){
	static INT32U samplecount;
	INT32U workingchannel;
	INT32U samplevalue;

    OS_ERR os_err;

    OSIntEnter();       //Tell OS that we are in an interrupt
	PIT_TFLG1 = PIT_TFLG_TIF_MASK; //Writing Clears the interrupt flag

	//READ PREVIOUS SAMPLE (Only if this is not the first pass through)
	if(samplecount > 0){
		workingchannel = SampleOrder[((samplecount-1)%16)]; //Get previous sampled device
		samplevalue = ADCReadSample(workingchannel); //Read previous completed sample
		ADCSamples[(samplecount-1)] = samplevalue; //Store value
	}else{ /* Do Nothing */ }

	workingchannel = SampleOrder[samplecount%16]; //Start next sample
	samplecount++;//increment the number of samples
	//START NEXT SAMPLE
	ADCStartSample(workingchannel);//Start the next sample
    //CHECK FOR END OF SAMPLES
	if(samplecount>RequiredSamples){ //Last sample will not be completed
		samplecount = 0; //reset counter for next run
		Stop_Timer(1); //PIT timer function
		OSTaskSemPost(&PITTaskTCB,OS_OPT_POST_NONE, &os_err);
		while(os_err != OS_ERR_NONE){
		}/*Check for Error*/
	}else{ /* Do Nothing */ }

	OSIntExit();

}

/******************************************************************************
* Set_TimerPeriod() - Does not change the current timer period. Advised to
* run Stop_Timer prior to running. "INT32U timerperiod" is the desired timer
* period in microseconds.
******************************************************************************/
void Set_TimerPeriod(INT8U pitdevice, INT32U timerperiod){

	if(pitdevice == 0){
		PIT_LDVAL0 = timerperiod * BUSFREQ;
	}else if(pitdevice == 1){
		PIT_LDVAL1 = timerperiod * BUSFREQ;
	}else if(pitdevice == 2){
		PIT_LDVAL2 = timerperiod * BUSFREQ;
	}else if(pitdevice == 3){
		PIT_LDVAL3 = timerperiod * BUSFREQ;
	}else{/* do nothing */}

}
/******************************************************************************
* Start_Timer() - Starts the desired Periodic interrupt timer. Clears then
* enables the interrupt flag.
******************************************************************************/
void Start_Timer(INT8U timernum){

	if(timernum == 0){
		PIT_TFLG0 = PIT_TFLG_TIF_MASK; //Clears flag if set
		PIT_TCTRL0 = (PIT_TCTRL_TIE_MASK | PIT_TCTRL_TEN_MASK);//starts timer, enables interrupt
	}else if(timernum == 1){
		PIT_TFLG1 = PIT_TFLG_TIF_MASK; //Clears flag if set
		PIT_TCTRL1 = (PIT_TCTRL_TIE_MASK | PIT_TCTRL_TEN_MASK);//starts timer, enables interrupt
	}else if(timernum == 2){
		PIT_TFLG2 = PIT_TFLG_TIF_MASK; //Clears flag if set
		PIT_TCTRL2 = (PIT_TCTRL_TIE_MASK | PIT_TCTRL_TEN_MASK);//starts timer, enables interrupt
	}else if(timernum == 3){
		PIT_TFLG3 = PIT_TFLG_TIF_MASK; //Clears flag if set
		PIT_TCTRL3 = (PIT_TCTRL_TIE_MASK | PIT_TCTRL_TEN_MASK);//starts timer, enables interrupt
	}else{/* do nothing */}

}
/******************************************************************************
* Stop_Timer() -
******************************************************************************/
void Stop_Timer(INT8U timernumber){
	if(timernumber == 0){
		PIT_TFLG0 = PIT_TFLG_TIF_MASK; //Clears flag if set
		PIT_TCTRL0 = 0x0000;//starts timer, enables interrupt
	}else if(timernumber == 1){
		PIT_TFLG1 = PIT_TFLG_TIF_MASK; //Clears flag if set
		PIT_TCTRL1 = 0x0000;//starts timer, enables interrupt
	}else if(timernumber == 2){
		PIT_TFLG2 = PIT_TFLG_TIF_MASK; //Clears flag if set
		PIT_TCTRL2 = 0x0000;//starts timer, enables interrupt
	}else if(timernumber == 3){
		PIT_TFLG3 = PIT_TFLG_TIF_MASK; //Clears flag if set
		PIT_TCTRL3 = 0x0000;//starts timer, enables interrupt
	}else{/* do nothing */}
}
/***************DATA CHECK/POTENTIOMETER FUNCTIONS**********************************************************************************************************/
/******************************************************************************
* Build_Sample_Order() -
*
*    FOR VALUES 0-19 this will build with only the selected channel, for values
*    greater than 19, this will build a full a LPF setup channels 0-15
******************************************************************************/
void Build_Sample_Order(INT32U calibrationchannel){
    INT8U chansetupcount;


    if(calibrationchannel < 19){
    	for(chansetupcount = 0; chansetupcount < 16; chansetupcount++){
    		SampleOrder[chansetupcount] = calibrationchannel;
		}
    }else if(calibrationchannel > 19){
    	for(chansetupcount = 0; chansetupcount < 16; chansetupcount++){
    		SampleOrder[chansetupcount] = chansetupcount;
    	}
    }else{ /* DO NOTHING */}

	}
/******************************************************************************
* Get_Raw_Channel() -
*
*    FOR VALUES 0-19 this will build with only the selected channel, for values
*    greater than 19, this will build a full a LPF setup channels 0-15
******************************************************************************/
INT32U Get_Raw_Channel(INT32U cal_signal){
    INT32U channeloffset;
    INT32U raw_cal_signal;

    channeloffset = cal_signal/4;
    raw_cal_signal = 16 + channeloffset;

    return(raw_cal_signal);
	}

/******************************************************************************
* Check_High_Samples() -
******************************************************************************/
INT32U Check_High_Samples(INT32U numsamplesh){
	INT32U highcounter;
	INT32U hh;
	INT32U highsamples;
	highsamples = 0;
	highcounter = 0;
	while(highcounter < numsamplesh){
		hh = ADCSamples[highcounter];
		highcounter++;
		if(hh>ADCLIMITHIGH){
			highsamples++;
		}else{ /* Do Nothing */}
	}

	return(highsamples);
}
/******************************************************************************
* Check_Low_Samples() -
******************************************************************************/
INT32U Check_Low_Samples(INT32U numsamplesl){
	INT32U lowcounter;
	INT32U ll;
	INT32U lowsamples;
	lowsamples = 0;
	lowcounter = 0;
	while(lowcounter < numsamplesl){
		ll = ADCSamples[lowcounter];
		lowcounter++;
		if(ll MINALLOWED)||(lownumber > MINALLOWED)){ //exceeds minimums
		if((highnumber < MAXALLOWED)&&(lownumber < MAXALLOWED)){ //does not exceed maximums
			//potvalue = potvalue; //value is good, no change to gain
		}else{
			if(potvaluePOTSETTINGMIN){
			potvalue++;  //Increase gain
		}else{/*Do Nothing*/}
	}
	return(potvalue);

}

/******************************************************************************
* Set_Switch() - sets the analog switchs to the appropriate position for
* channel calibration
******************************************************************************/
void Set_Switch(INT32U setup_channel){
    INT32U switch_offset;

    switch_offset = setup_channel%4; //Find the appropriate switch for the channel
    GPIOD_PDOR &= ~ANALOGSWITCHMASK; //Clear the current switch
    GPIOD_PDOR |= ((0x01)<<(switch_offset+ANALOGSWITCHSHIFT)); //Write new switch setting

}

/******************************************************************************
* Get_PotSetting() -
******************************************************************************/
INT32U Get_PotSetting(INT32U cali_channel){
    INT32U returngain;
    INT32U xoffset;
    INT32U yoffset;

    yoffset = cali_channel/4;
    xoffset = cali_channel%4;
    returngain = Pot_SignalSettings[yoffset][xoffset];
	return(returngain);
}
/******************************************************************************
* Set_PotSetting() - stores the value for the potentiometer settings in a
* local array and in the potentiometer. Sets up potentiometer writing to the
* MCP4351 Digital Potentiometer 16-Bit mode
******************************************************************************/
void Set_PotSetting(INT32U cal_channel, INT32U pot_setting){
    INT32U offsetx;
    INT32U offsety;

    offsety = cal_channel/4; //Also the value for the SPI CS pin
    offsetx = cal_channel%4; //Also the value for the Internal POT number

    Pot_SignalSettings[offsety][offsetx] = pot_setting;

    //pot_setting |= ((0x01)<<(offsetx+DIGIPOT_DEVICE_BASE_SHIFT)); //set the internal device
    pot_setting |= ((0x01)<<(offsety+DIGIPOT_CS_BASE_SHIFT )); //set the chip select for appropriate device

    switch(offsetx){
    case 0:
    	pot_setting |= DIGIPOT_WIPER0_MASK;
    	break;
    case 1:
    	pot_setting |= DIGIPOT_WIPER1_MASK;
    	break;
    case 2:
    	pot_setting |= DIGIPOT_WIPER2_MASK;
    	break;
    case 3:
    	pot_setting |= DIGIPOT_WIPER3_MASK;
    	break;
    default:
    	pot_setting |= DIGIPOT_READ_MASK;//Invalid value, don't change any Potentiometer setting
        break;
    }

    SPI_Write(0, pot_setting); //write the new value to the appropriate device

}
/***************************DATA PROCESSING************************************/
/******************************************************************************
* LPF_Averaging() - must be used with ADCSamples[1024]
******************************************************************************/
INT32U LPF_Averaging(INT32U lpfchannel){
	INT32U lpfavg;
	INT32U avg_counter;

	for(avg_counter = 0; avg_counter < 64; avg_counter++){
			lpfavg += ADCSamples[(lpfchannel+(avg_counter*16))];
	}

	lpfavg = lpfavg/64;

	return(lpfavg);
}

/***************FLAG FUNCTIONS*************************************************/
/*******************************************************************************
* Set_Flag() -
*******************************************************************************/
void Set_Flag(INT8U setflag){
	PIT_Flags[setflag]=SET;
}

/******************************************************************************
* Read_Flag() -
******************************************************************************/
INT8U Read_Flag(INT8U readflag){
	INT8U flagstatus;
	flagstatus = PIT_Flags[readflag];
    return(flagstatus);
}

/******************************************************************************
* Clear_Flag() -
******************************************************************************/
void Clear_Flag(INT8U clearflag){
	PIT_Flags[clearflag] = CLEAR;
}

/******************************************************************************
* Set_SubFlag() -
******************************************************************************/
void Set_SubFlag(INT8U setflag, INT8U setsubflag){
    PIT_Sub_Flags[setflag][setsubflag] = SET;
}

/******************************************************************************
* Read_SubFlag() -
******************************************************************************/
INT8U Read_SubFlag(INT8U readflag, INT8U readsubflag){
	INT8U subflagstatus;
    subflagstatus = PIT_Sub_Flags[readflag][readsubflag];
    return(subflagstatus);
}
/******************************************************************************
* Clear_SubFlag() - clears a specific subflag
******************************************************************************/
void Clear_SubFlag(INT8U clearflag, INT8U clearsubflag){
    PIT_Sub_Flags[clearflag][clearsubflag] = CLEAR;
}
/******************************************************************************
* Read_AllSubFlags() - produces and OR response from all sub-flags
******************************************************************************/
INT8U Read_AllSubFlags(INT8U readflag){
	INT8U subflagstatus = CLEAR;
	INT8U readcount;
	for(readcount = 0; readcount < NUMSUBFLAGS; readcount++){
    subflagstatus |= PIT_Sub_Flags[readflag][readcount];
	}
    return(subflagstatus);
}
/******************************************************************************
* Clear_AllFlags() - clears all flags and subflags
******************************************************************************/
void Clear_AllFlags(void){
	INT8U flagclearcount;
	INT8U subflagclearcount;
	for(flagclearcount=0; flagclearcount < NUMFLAGS; flagclearcount++){
		PIT_Flags[flagclearcount] = CLEAR;
		for(subflagclearcount=0; subflagclearcount < NUMSUBFLAGS; subflagclearcount++){
		PIT_Sub_Flags[flagclearcount][subflagclearcount] = CLEAR;
		}
	}
}
/*******************************************************************************
 * PIT Initializations
 ******************************************************************************/
void PITTaskInit(void) {

    SPI_Init(0);
	ADCInit(0);
	ADCInit(1);
	ADCInit(3);

	//Clock Routing
	SIM_SCGC6 |= SIM_SCGC6_PIT_MASK;  //enable clock for PIT

	//Enable GPIO(s) (For analog switches)
	PORTD_PCR12 |= PORT_PCR_MUX(0x1);  //GPIO
	PORTD_PCR13 |= PORT_PCR_MUX(0x1);  //GPIO
	PORTD_PCR14 |= PORT_PCR_MUX(0x1);  //GPIO
	PORTD_PCR15 |= PORT_PCR_MUX(0x1);  //GPIO
	GPIOD_PDDR   |= 0xF000; //Set bits 15-12 as GPIO output

	//PIT Initilization
	PIT_MCR |= PIT_MCR_FRZ_MASK;//Stops clocks during Debug
	PIT_MCR &= ~PIT_MCR_MDIS_MASK;//Enables the PIT module

	NVIC_EnableIRQ(PIT0_IRQn);
	NVIC_EnableIRQ(PIT1_IRQn);
	NVIC_SetPriority(PIT0_IRQn,0x01);
	NVIC_SetPriority(PIT1_IRQn,0x02);

}


Previous Page