예제 #1
0
char canstdio_getcharacter(bool blocking)
{
	while (blocking && nodo_attivo && !input_buffer_nonempty)
		simulator_relax();

	if (input_buffer_nonempty == false)
		return 0;

	int current_cpu_ipl;
	SET_AND_SAVE_CPU_IPL(current_cpu_ipl, 7); // disattiva interrupt
	char res;

	if (input_buffer_count == 0)
	{
		res = 0;
	}
	else
	{
		res = input_buffer[0];
		memmove(input_buffer, input_buffer + 1, --input_buffer_count);
	}

	input_buffer_nonempty = (input_buffer_count != 0);
	RESTORE_CPU_IPL(current_cpu_ipl); // riattiva interrupt

	return res;
}
예제 #2
0
//************************************************************
// Registers callback in "OffsetMS" milliseconds
//************************************************************
void	TMRCallBackAfter(	ulong 		OffsetMS, 
							TMRCallBack callBack)
	{
	//======================================================
	char saved_ipl;                       
	SET_AND_SAVE_CPU_IPL(saved_ipl,_TMRIL);
	//--------------------------------------------------
	// Reset/Enable CTMU (callback) interrupt
	//--------------------------------------------------
	_RTCIF 	= 0; 		// Clear RTCC interrupt flag
	_RTCIE 	= 1; 		// Enable RTCC interrupt
	//--------------------------------------------------
	// Set callback request
	//--------------------------------------------------
	_TMR_CallBack				= callBack;
	//======================================================
	// Important NOTE: Timer counter updated every 125 usec!
	//------------------------------------------------------
	// Time offset need to be converted to timer units
	//------------------------------------------------------
	_TMR_CallBack_TriggerTime 	= _TMR_RT_ElapsedTime 
								+ (OffsetMS << 3);
	//--------------------------------------------------
	RESTORE_CPU_IPL(saved_ipl);
	//---------------------------------------------------
	return;
	}
예제 #3
0
파일: ecan_lib.c 프로젝트: MCL88/psr
static void invoke_update_handler(t_object * obj)
{
    t_object_buffer *src_buffer;
    unsigned int data_length;
    uint8_t buffer[8];

    int current_cpu_ipl;
    SET_AND_SAVE_CPU_IPL(current_cpu_ipl, 7); // disattiva interrupt

    if ((obj->flags & ECAN_RX_FLAG_FIFO))
    {
        src_buffer = &fifo_buffer[fifo_head++];
        if (fifo_head == ECAN_FIFO_SIZE)
            fifo_head = 0;
        if (--fifo_count != 0)
            obj->new_data_arrived = true;
        else
            obj->new_data_arrived = false;
    }
    else
    {
        src_buffer = &obj->buff;
        obj->new_data_arrived = false;
    }

    data_length = src_buffer->data_length;
    memcpy(buffer, src_buffer->data, data_length);

    RESTORE_CPU_IPL(current_cpu_ipl); // ripristina interrupt

    obj->update(buffer, data_length, obj->user_ptr);
}
예제 #4
0
파일: main.c 프로젝트: dakhouya/Chinook3
void fct_can_cmd(unsigned long ID, T_TYPE_ID type_ID, const void * data_rx, char nbr_data)
{
	char UART_can_receive[50]={0x00};
	int old_ipl, ii, jj;
	// Block interruptions
	SET_AND_SAVE_CPU_IPL(old_ipl, 7);

 	datReceive_can_cmd.datReceive = (char *)data_rx;
 	datReceive_can_cmd.nb_data = (unsigned int)nbr_data;

	RESTORE_CPU_IPL(old_ipl);
}
예제 #5
0
파일: main.c 프로젝트: dakhouya/Chinook3
void fct_can_pitch(unsigned long ID, T_TYPE_ID type_ID, T_CAN_DATA* recopie, char nbr_data)
{
        const char ubReceiveData[5] = {(recopie->data3 & 0x00FF),(recopie->data3 & 0xFF00)>>8,(recopie->data4 & 0x00FF),(recopie->data4 & 0xFF00)>>8,(recopie->data5 & 0x00FF)};
	int old_ipl;

	// Block interruptions
	SET_AND_SAVE_CPU_IPL(old_ipl, 7);
	off = 0;
	chinookpack_unpack_next(&unpacker,ubReceiveData,5,&off);
	off = 0;
	RESTORE_CPU_IPL(old_ipl);
        fCanPitchPercent = unpacker.data.via.dec;
}
예제 #6
0
파일: main.c 프로젝트: dakhouya/Chinook3
void fct_can_gear(unsigned long ID, T_TYPE_ID type_ID, T_CAN_DATA* recopie, char nbr_data)
{
        const char ubReceiveData[2] = {(recopie->data3 & 0x00FF),(recopie->data3 & 0xFF00)>>8};
	int old_ipl;

	// Block interruptions
	SET_AND_SAVE_CPU_IPL(old_ipl, 7);
	off = 0;
	chinookpack_unpack_next(&unpacker,ubReceiveData,5,&off);
	off = 0;
	RESTORE_CPU_IPL(old_ipl);
        ubGearCanReceive = (unsigned char)unpacker.data.via.u64;
}
예제 #7
0
//********************************************************************
// SR04Read function - returns calculated Altitude and Speed if there
// is at least one captured sample since last call to the function.
//--------------------------------------------------------------------
// Return value indicates whether initialization condition was met and,
// if so, how many samples were available for calculation of resulting
// values.
//--------------------------------------------------
// NOTE: Output data structure updated ONLY if a new
//       sample is available!
//====================================================================
uint	SR04Read(SR04Data*	SR04Sample)
	{
	if (0 == _SR04Init)
		return -1;		// Component not initialized
	if (0 == _SR04Ready)
		return 0;		// New Sample is not ready yet!
						// SR04Sample structure left "as-is"
	//----------------------------------------------------------------
	byte 		saved_ipl;     
	//-----------------------
	uint		SR04ReadyCount;
	ulong		SR04TimeSum;
	//-----------------------
	ulong		SR04RecentTS;
                  
	//================================================================
	// Enter Critical Section: SR04 (Input Capture) interrupt is blocked
	//================================================================
	SET_AND_SAVE_CPU_IPL(saved_ipl,_SR04IL);
	//================================================================
	// Consume current sample
	//----------------------------------------------------------------
	SR04ReadyCount	= _SR04Ready;
	SR04TimeSum		= _SR04Sum;
	//------------------------------
	SR04RecentTS	= _SR04RecentTS;
	//----------------------------------------------------------------
	_SR04Ready		= 0;		// Sample is consumed...
	_SR04Sum		= 0;
	_SR04RecentTS	= 0;
	//================================================================
	// Leave Critical Section
	//================================================================
	RESTORE_CPU_IPL(saved_ipl);
	//================================================================

	//================================================================
	// Calculate Altitude
	//----------------------------------------------------------------
	SR04Sample->Altitude	= ((float)SR04TimeSum) * _SR04CF;
	if (SR04ReadyCount > 1)
		// Several samples were aggregated, let's get average
		SR04Sample->Altitude /= (float)SR04ReadyCount;
	//----------------------------------------------------------------
	// Update output data structure
	//----------------------------------------------------------------
	SR04Sample->Altitude	-= _SR04Offset;
	SR04Sample->TS			 = SR04RecentTS;
	//================================================================
	return SR04ReadyCount;		// SR04Sample updated with new sample 
	}
예제 #8
0
파일: main.c 프로젝트: dakhouya/Chinook3
void fct_can_pitch_eeprom(unsigned long ID, T_TYPE_ID type_ID, T_CAN_DATA* recopie, char nbr_data)
{
        //LED_STAT1 = 1;
        const char ubReceiveData[2] = {(recopie->data3 & 0x00FF),(recopie->data3 & 0xFF00)>>8};
        int old_ipl;

        // Block interruptions
        SET_AND_SAVE_CPU_IPL(old_ipl, 7);
        off = 0;
        chinookpack_unpack_next(&unpacker,ubReceiveData,2,&off);
        off = 0;
        RESTORE_CPU_IPL(old_ipl);
        ubPitchEepromAnswerReceive = (unsigned char)unpacker.data.via.u64;
}
예제 #9
0
파일: Main.c 프로젝트: dakhouya/Chinook3
void fct_can_conf(unsigned long ID, T_TYPE_ID type_ID, T_CAN_DATA* recopie, char nbr_data)
{
        const char ubReceiveData[1] = {(recopie->data3 & 0x00FF)};
	int old_ipl;
	// Block interruptions
	SET_AND_SAVE_CPU_IPL(old_ipl, 7);

	off = 0;
	chinookpack_unpack_next(&unpacker,ubReceiveData,2,&off);
	off = 0;

	RESTORE_CPU_IPL(old_ipl);

        datReceive_can_conf = (int)unpacker.data.via.i64;
}
예제 #10
0
//************************************************************
void	UARTRXGetStat(pUARTRXStat RXStat)
	{
	uint current_cpu_ipl;
	//---------------------------------
	// Enter UART_RX CRITICAL SECTION
	//---------------------------------
  	SET_AND_SAVE_CPU_IPL(current_cpu_ipl, _UART_IL_RX);  /* disable UART_RX interrupts */
	//--------------------------------------------------------
	RXStat->RecordCount			= _UART_RX_RecCnt;
	RXStat->FrameOverrunCount	= _UART_RX_OvrCnt;
	RXStat->InvalidFrameCount	= _UART_RX_InvCnt;
	RXStat->ErrorCount			= _UART_RX_ErrCnt;	
	//---------------------------------
	// Leave UART_RX CRITICAL SECTION
	//---------------------------------
  	RESTORE_CPU_IPL(current_cpu_ipl);
	//--------------------------
	}
예제 #11
0
//*************************************************************
uint    _MPLAsyncRead(MPLData* pSample)
    {
    //----------------------------------------------
    int         current_cpu_ipl;
    //----------------------------------------------
    uint        Ready_Cnt;
    ulong       RawTS;
    long        RawData;
    //==============================================
    // Enter MPL/I2C CRITICAL SECTION
    //----------------------------------------------
    SET_AND_SAVE_CPU_IPL(current_cpu_ipl, _MPL_IL);  /* disable interrupts */
    //-----------------------------------------------
    Ready_Cnt    = _MPL_Ready;
    RawTS        = _MPL_DataTS;
    RawData      = _MPL_Data;
    //-----------------------------------------------
    _MPL_Ready   = 0;        // Sample consumed...
    _MPL_Data    = 0;        // Data cleared
    //----------------------------------------------
    RESTORE_CPU_IPL(current_cpu_ipl);
    //----------------------------------------------
    // Leave MPL/I2C CRITICAL SECTION
    //==============================================

    //==============================================
    // Timestamp and Altitude
    //-----------------------------------------------
    pSample->TS     = RawTS;
    pSample->Alt    = ((float)RawData)*0.0625;
    //==============================================
    if (Ready_Cnt > 1)
        // Find average of samples if multiple
        // samples summed together
        pSample->Alt /= (float)Ready_Cnt;
    //==============================================
    // Adjust normalized (averaged) Altitude to
    // account for Ground level
    //-----------------------------------------------
    pSample->Alt = pSample->Alt - _MPL_BaseAlt;
    //-----------------------------------------------
    return MPL_OK;             // The return code was OK    
    }
예제 #12
0
파일: Main.c 프로젝트: dakhouya/Chinook3
void fct_can_cmd(unsigned long ID, T_TYPE_ID type_ID, T_CAN_DATA* recopie, char nbr_data)
{
        const char ubReceiveData[2] = {(recopie->data3 & 0x00FF),(recopie->data3 & 0xFF00)>>8};
	int old_ipl, tempo=0;
	// Block interruptions
	SET_AND_SAVE_CPU_IPL(old_ipl, 7);

	off = 0;
	chinookpack_unpack_next(&unpacker,ubReceiveData,2,&off);
	off = 0;

	RESTORE_CPU_IPL(old_ipl);

        tempo = (int)unpacker.data.via.i64;
        datReceive_can_cmd[0] = tempo & 0b0001;
        datReceive_can_cmd[1] = (tempo & 0b0010)>>1;
        datReceive_can_cmd[2] = (tempo & 0b0100)>>2;
        datReceive_can_cmd[3] = (tempo & 0b1000)>>3;
}
예제 #13
0
//************************************************************
void	TMRCallBackDiscard()
	{
	char saved_ipl;                       
	SET_AND_SAVE_CPU_IPL(saved_ipl,_TMRIL);
	//--------------------------------------------------
	// Disable/Reset CTMU (callback) interrupt
	//--------------------------------------------------
	_RTCIE 	= 0; 		// Disable RTCC interrupt
	_RTCIF 	= 0; 		// Clear RTCC interrupt flag
	//--------------------------------------------------
	// Reset callback request
	//--------------------------------------------------
	_TMR_CallBack_TriggerTime 	= -1;	// Infinite...
	_TMR_CallBack				=  0;	// Reset callback address
	//--------------------------------------------------
	RESTORE_CPU_IPL(saved_ipl);
	//---------------------------------------------------
	return;
	}
예제 #14
0
파일: Main.c 프로젝트: dakhouya/Chinook3
void fct_can_EEPROM_CONFIG_ANSWER(unsigned long ID, T_TYPE_ID type_ID, T_CAN_DATA* recopie, char nbr_data)
{
        const char ubReceiveData[5] = {(recopie->data3 & 0x00FF),(recopie->data3 & 0xFF00)>>8,(recopie->data4 & 0x00FF),(recopie->data4 & 0xFF00)>>8,(recopie->data5 & 0x00FF)};
        const char ubReceiveData2[2] = {(recopie->data5 & 0xFF00)>>8,(recopie->data6 & 0x00FF)};
        int old_ipl;

	// Block interruptions
	SET_AND_SAVE_CPU_IPL(old_ipl, 7);

	off = 0;
        chinookpack_unpack_next(&unpacker,ubReceiveData2,2,&off);
        off=0;
	chinookpack_unpack_next(&unpacker,ubReceiveData,5,&off);
	off = 0;

	RESTORE_CPU_IPL(old_ipl);

        datReceive_can_EEPROM_CONFIG_ANSWER_gear = (char)unpacker.data.via.u64;
        datReceive_can_EEPROM_CONFIG_ANSWER_mat = unpacker.data.via.dec;

}
예제 #15
0
/* main ***********************************************************************/
int main (void){
    CO_NMT_reset_cmd_t reset = CO_RESET_NOT;

    /* Initialize two CAN led diodes */
    TRISAbits.TRISA0 = 0; LATAbits.LATA0 = 0;
    TRISAbits.TRISA1 = 0; LATAbits.LATA1 = 1;
    #define CAN_RUN_LED        LATAbits.LATA0
    #define CAN_ERROR_LED      LATAbits.LATA1

    /* Initialize other LED diodes for RPDO */
    TRISAbits.TRISA2 = 0; LATAbits.LATA2 = 0;
    TRISAbits.TRISA3 = 0; LATAbits.LATA3 = 0;
    TRISAbits.TRISA4 = 0; LATAbits.LATA4 = 0;
    TRISAbits.TRISA5 = 0; LATAbits.LATA5 = 0;
    TRISAbits.TRISA6 = 0; LATAbits.LATA6 = 0;
    TRISAbits.TRISA7 = 0; LATAbits.LATA7 = 0;


    /* Configure Oscillator */
    /* Fosc = Fin*M/(N1*N2), Fcy=Fosc/2 */
    /* Fosc = 8M*24(2*2) = 48MHz -> Fcy = 24MHz */
    PLLFBD=22;              /*  M=24 */
    CLKDIVbits.PLLPOST=0;   /*  N1=2 */
    CLKDIVbits.PLLPRE=0;    /*  N2=2 */
    OSCTUN=0;               /*  Tune FRC oscillator, if FRC is used */
    while(OSCCONbits.LOCK!=1) ClrWdt(); /* wait for PLL to lock */


    /* Verify, if OD structures have proper alignment of initial values */
    if(CO_OD_RAM.FirstWord != CO_OD_RAM.LastWord) while(1) ClrWdt();
    if(CO_OD_EEPROM.FirstWord != CO_OD_EEPROM.LastWord) while(1) ClrWdt();
    if(CO_OD_ROM.FirstWord != CO_OD_ROM.LastWord) while(1) ClrWdt();


    /* initialize EEPROM */
        /* (not implemented) */

    /* increase variable each startup. Variable is stored in eeprom. */
    OD_powerOnCounter++;

    while(reset != CO_RESET_APP){
/* CANopen communication reset - initialize CANopen objects *******************/
        static uint16_t timer1msPrevious;
        CO_ReturnError_t err;

        /* disable timer and CAN interrupts, turn on red LED */
        CO_TMR_ISR_ENABLE = 0;
        CO_CAN_ISR_ENABLE = 0;
        CAN_RUN_LED = 0;
        CAN_ERROR_LED = 1;

        /* Initialize digital outputs */
        TRISAbits.TRISA2 = 0; LATAbits.LATA2 = 0;
        TRISAbits.TRISA3 = 0; LATAbits.LATA3 = 0;
        TRISAbits.TRISA4 = 0; LATAbits.LATA4 = 0;
        TRISAbits.TRISA5 = 0; LATAbits.LATA5 = 0;
        TRISAbits.TRISA6 = 0; LATAbits.LATA6 = 0;
        TRISAbits.TRISA7 = 0; LATAbits.LATA7 = 0;
        OD_writeOutput8Bit[0] = 0;
        OD_writeOutput8Bit[1] = 0;


        /* initialize CANopen */
        err = CO_init();
        if(err != CO_ERROR_NO){
            while(1) ClrWdt();
            /* CO_errorReport(CO->em, CO_EM_MEMORY_ALLOCATION_ERROR, CO_EMC_SOFTWARE_INTERNAL, err); */
        }

        /* start CAN */
        CO_CANsetNormalMode(ADDR_CAN1);


        /* Configure Timer interrupt function for execution every 1 millisecond */
        CO_TMR_CON = 0;
        CO_TMR_TMR = 0;
        CO_TMR_PR = CO_FCY - 1;    /* Period register */
        CO_TMR_CON = 0x8000;       /* start timer (TON=1) */
        CO_timer1ms = 0;
        CO_TMR_ISR_FLAG = 0;       /* clear interrupt flag */
        CO_TMR_ISR_PRIORITY = 3;   /* interrupt - set lower priority than CAN */
        CO_TMR_ISR_ENABLE = 1;     /* enable interrupt */
        /* Configure CAN1 Interrupt (Combined) */
        CO_CAN_ISR_FLAG = 0;       /* CAN1 Interrupt - Clear flag */
        CO_CAN_ISR_PRIORITY = 5;   /* CAN1 Interrupt - Set higher priority than timer */
        CO_CAN_ISR_ENABLE = 1;     /* CAN1 Interrupt - Enable interrupt */

        reset = CO_RESET_NOT;
        timer1msPrevious = CO_timer1ms;

        while(reset == CO_RESET_NOT){
/* loop for normal program execution ******************************************/
            uint16_t timer1msCopy, timer1msDiff;
            static uint16_t TMR_TMR_PREV = 0;

            timer1msCopy = CO_timer1ms;
            timer1msDiff = timer1msCopy - timer1msPrevious;
            timer1msPrevious = timer1msCopy;

            ClrWdt();

            /* calculate cycle time for performance measurement */
            uint16_t t0 = CO_TMR_TMR;
            uint16_t t = t0;
            if(t >= TMR_TMR_PREV){
                t = t - TMR_TMR_PREV;
                t = (timer1msDiff * 100) + (t / (CO_FCY / 100));
            }
            else if(timer1msDiff){
                t = TMR_TMR_PREV - t;
                t = (timer1msDiff * 100) - (t / (CO_FCY / 100));
            }
            else t = 0;
            OD_performance[ODA_performance_mainCycleTime] = t;
            if(t > OD_performance[ODA_performance_mainCycleMaxTime])
                OD_performance[ODA_performance_mainCycleMaxTime] = t;
            TMR_TMR_PREV = t0;

            /* CANopen process */
            reset = CO_process(CO, timer1msDiff);

            CAN_RUN_LED = LED_GREEN_RUN(CO->NMT);
            CAN_ERROR_LED = LED_RED_ERROR(CO->NMT);

            ClrWdt();

            /* (not implemented) eeprom_process(&eeprom); */
        }
    }
/* program exit ***************************************************************/
    /* save variables to eeprom */
    RESTORE_CPU_IPL(7);           /* disable interrupts */
    CAN_RUN_LED = 0;
    /* CAN_ERROR_LED = 0; */
    /* (not implemented) eeprom_saveAll(&eeprom); */
    CAN_ERROR_LED = 1;

    /* delete CANopen object from memory */
    CO_delete();

    /* reset */
    return 0;
}
예제 #16
0
//*************************************************************
uint    _MPUAsyncRead(MPU_CB* pCB, MPUData* pSample)
    {
    //----------------------------------------------
    uint        Ready_Cnt;
    _MPURawData RawData;
    //----------------------------------------------
    int         current_cpu_ipl;
    //----------------------------------------------

    //==============================================
    // Enter MPU/I2C CRITICAL SECTION
    //----------------------------------------------
    SET_AND_SAVE_CPU_IPL(current_cpu_ipl, _MPU_IL);  /* disable interrupts */
    //---------------------------------
    RawData.Temp    = pCB->_MPU_Sample.Temp;
    //---------------------------------
    RawData.AX      = pCB->_MPU_Sample.AX;
    RawData.AY      = pCB->_MPU_Sample.AY;
    RawData.AZ      = pCB->_MPU_Sample.AZ;
    //---------------------------------
    RawData.GX      = pCB->_MPU_Sample.GX;
    RawData.GY      = pCB->_MPU_Sample.GY;
    RawData.GZ      = pCB->_MPU_Sample.GZ;
    //-----------------------------------------------
    Ready_Cnt       = pCB->_MPU_Ready;
    //-----------------------------------------------
    pCB->_MPU_Ready = 0;        // Sample consumed...
    //----------------------------------------------
    // Leave MPU/I2C CRITICAL SECTION
    //==============================================
    RESTORE_CPU_IPL(current_cpu_ipl);

    //==============================================
    // Set sample timestamp
    //----------------------------------------------
    pSample->TS    = TMRGetTS();
    //==============================================
    // Adjust Sample Weight to account for multiple samples
    //----------------------------------------------
    float     Weight;
    if (Ready_Cnt > 1)
        Weight = 1.0/(float)Ready_Cnt;
    else
        Weight = 1.0;
    //----------------------------------------------
    // Process collected sample
    //----------------------------------------------
    // Temperature (C) 
    //-----------------------------------------------
    pSample->Temp = (Weight * RawData.Temp - pCB->_MPU_Temp_OffsetTo0)
                    * pCB->_MPU_Temp_Sensitivity;
    //-----------------------------------------------
    // Acceleration (G)
    //-----------------------------------------------
    VectorSet   (
                Weight * RawData.AX * pCB->_MPU_Accl_Sensitivity,
                Weight * RawData.AY * pCB->_MPU_Accl_Sensitivity,
                Weight * RawData.AZ * pCB->_MPU_Accl_Sensitivity,
                //---------
                &pSample->A
                );
    //-----------------------------------------------
    // Gyroscopes (Rad/sec)
    //-----------------------------------------------
    VectorSet   (
                Weight * RawData.GX * pCB->_MPU_Gyro_Sensitivity,
                Weight * RawData.GY * pCB->_MPU_Gyro_Sensitivity,
                Weight * RawData.GZ * pCB->_MPU_Gyro_Sensitivity,
                //---------
                &pSample->G
                );
    //-----------------------------------------------
    // Applying calibration and tuning parameters
    //-----------------------------------------------
    _MPU_ApplyCalibration(pCB, pSample);
    //-----------------------------------------------
    return MPU_OK;             // The return code was OK    
    }
예제 #17
0
//************************************************************
// Synchronous READ - I2C API (visible externally) component
//************************************************************
uint	I2CSyncRead(	uint	I2Cx,
						byte 	DevAddr, 
						byte	Register,
						byte* 	Buffer,
						uint  	BufLen )
	{
	if (!_I2C_Init)		return I2CRC_NRDY;
	//=========================================================
	// Obtain references to proper Control Blocks and registers
	//---------------------------------------------------------
	_I2C_CB*		pCB;
	if ( NULL == (pCB = I2CpCB(I2Cx)) )		return I2CRC_NOTA;
	//---------------------------------------------------------
	I2C_CONBITS*	pCON	= I2CpCON(pCB);
	I2C_STATBITS*	pSTAT	= I2CpSTAT(pCB);
	//=========================================================
	// Validate run-time conditions
	//---------------------------------------------------------
	uint	RC;
	BYTE	CPU_IPL;
	uint	RetryCount	= 0;

	//---------------------------------------------------------
	// Enter I2C (and related modules) CRITICAL SECTION
	//---------------------------------------------------------
Retry:
	RC	= I2CRC_OK;
	//------------------------------------
	SET_AND_SAVE_CPU_IPL(CPU_IPL, _I2C_IL);
		{
		if (I2CRC_OK == (RC=I2CGetStatus(pCB, pCON, pSTAT)))
			//---------------------------------------------------------
			// Set Flag indicating Synchronous operation is in progress
			//---------------------------------------------------------
			pCB->_I2C_SBSY	= 1;	// Should be cleared at exit
		}  
	//---------------------------------------------------------
	// Leave I2C CRITICAL SECTION
	//---------------------------------------------------------
  	RESTORE_CPU_IPL(CPU_IPL);
	//=========================================================
	switch (RC)	
		{
		case	I2CRC_OK:
			break;		// Run-time conditions are OK
		//-------------------------------------------
		case	I2CRC_ABSY:
		case	I2CRC_SBSY:
		case	I2CRC_BUSY:
			// Situation could be helped by delay/retry
			if (RetryCount < I2C_BUSYRetry)
				{
				TMRDelayTicks(1);	// Small delay ~125 usec
				RetryCount++;
				goto Retry;					// Attempt retry
				}
			else;		// Fall through to "default"
		//-------------------------------------------
		default:
			return RC;	// Run-time conditions are not met
		}
	//=========================================================

	//---------------------------------------------------------
	// Event sequence to accomplish simple READ from the target
	// slave device in the MASTER mode:
	//	1. Assert a Start condition on SDAx and SCLx.
	//	2. Send the I2C device address byte to the slave with a
	//	   read indication ("1" in the LSB of address)
	//	3. Wait for and verify an Acknowledge from the slave.
	//	4. Assert receiving state (RCEN = 1).
	//	5. Receive byte and send ACK to the slave.
	//	6. Repeat steps 4 and 5 for every byte in a message, 
	//	   except the last - after receiving last byte send NACK.
	//	7. Generate a Stop condition on SDAx and SCLx.
	//---------------------------------------------------------
	// Prepare READ and WRITE forms of device address
	byte	i2cAddrW	= DevAddr & 0xFE;	// Set WRITE cond.
	byte	i2cAddrR	= DevAddr | 0x01;	// Set READ cond.
	//---------------------------------------------------------
	RC			= I2CRC_OK;
	//---------------------------------------------------------
	I2CStart(pCB);		// Signal START on SDA and SCL pins
	//---------------------------------------------------------
	// Send Device WRITE address
	//---------------------------------------------------------
	RC = I2CMasterWriteByte(pCB, i2cAddrW);
	if (RC != I2CRC_OK)	goto Finally;
	//---------------------------------------------------------
	// Send Register address (as data))
	//---------------------------------------------------------
	RC = I2CMasterWriteByte(pCB, Register);
	if (RC != I2CRC_OK)	goto Finally;
	//---------------------------------------------------------
	I2CReStart(pCB);	// Signal Repeated-START on SDA and SCL pins
	//---------------------------------------------------------
	// Send Device READ address
	//---------------------------------------------------------
	RC = I2CMasterWriteByte(pCB, i2cAddrR);
	if (RC != I2CRC_OK)	goto Finally;
	//---------------------------------------------------------
	// Receive data
	//---------------------------------------------------------
	pSTAT->I2COV = 0;	// Clear receive OVERFLOW bit, if any
	//---------------------------------------------------------
	uint	BufPos;
	uint	BufCnt	= BufLen;
	//---------------------------------------------------------
	for (BufPos = 0; BufPos < BufLen; BufPos++)
		{
		BufCnt--;	// Used as a FLAG (BufCnt=0) to indicate last byte
		//---------------------------------------------------------
		RC = I2CMasterReadByte(pCB, Buffer, BufCnt);
		if (RC != I2CRC_OK)
			break;			// Error...
		Buffer++;
		}
	//---------------------------------------------------------
Finally:
	I2CStop(pCB);			// Signal STOP on SDA and SCL pins
	//---------------------------------------------------------
	pCB->_I2C_SBSY	= 0;	// Clear SYNC flag
	return RC;				// Return last Error Code...
	}
int main(){
  uint8_t start_r, old_IPL;
  uint8_t hz50_scaler, hz5_scaler, hz1_scaler, sec;
  uint32_t tick = 0;

  hz50_scaler = hz5_scaler = hz1_scaler = sec = 0;

  touch_init();

  __delay_ms(200);
  lcd_initialize();             // Initialize the LCD 

  motor_init();

  lcd_clear();
  lcd_locate(0,0);
  lcd_printf("-- Ball position: --");

  timers_initialize();          // Initialize timers

  while (1) {
    start_r = 0;
    while(!start_r) {      
      // disable all maskable interrupts
      SET_AND_SAVE_CPU_IPL(old_IPL, 7);
      start_r = start;

      // enable all maskable interrupts
      RESTORE_CPU_IPL(old_IPL);
    }

    // Periodic real-time task code starts here = CENTER_X + RADIUS * cos(tick * SPEED);
//      Ypos_set = CENT!!!
    double pidX, pidY;
    uint16_t duty_us_x, duty_us_y;

    // 50Hz control task
    if(hz50_scaler == 0) {
      calcQEI(Xpos_set, Xpos, Ypos_set, Ypos);
//      Xpos_set = CENTER_X;
//      Xpos_set = CENTER_Y;
      Xpos_set = CENTER_X + RADIUS * cos(tick * SPEED);
      Ypos_set = CENTER_Y + RADIUS * sin(tick * SPEED);
      tick++;


      pidX = pidX_controller(Xpos);
      pidY = pidY_controller(Ypos);

      // TODO: Convert PID to motor duty cycle (900-2100 us)

      // setMotorDuty is a wrapper function that calls your motor_set_duty
      // implementation in flexmotor.c. The 2nd parameter expects a value
      // between 900-2100 us
//      duty_us_x = cap((pidX*1000.0), 2100, 900);
//      duty_us_y = cap((pidY*1000.0), 2100, 900);

      duty_us_x = cap((pidX + 1500), 2100, 900);
      duty_us_y = cap((pidY + 1500), 2100, 900);
      motor_set_duty(1, duty_us_x);
      motor_set_duty(2, duty_us_y+100);
//      setMotorDuty(MOTOR_X_CHAN, duty_us_x);
//      setMotorDuty(MOTOR_Y_CHAN, duty_us_y);
    }

    // 5Hz display task
    if(hz5_scaler == 0) {
//      lcd_locate(0,1);
//      lcd_printf("Xp=%.1f,Yp=%.1f", Xpos, Ypos);
//      lcd_locate(0,2);
//      lcd_printf("X*=%.1f, Y*=%.1f", Xpos_set, Ypos_set);
//      lcd_locate(0,3);
//      lcd_printf("pX=%.1f,pY=%.1f", pidX, pidY);
//      lcd_locate(0,4);
//      lcd_printf("dx=%u, dY=%u", duty_us_x, duty_us_y);
//
      if(deadline_miss >= 1) {
        lcd_locate(0,6);
        lcd_printf("%4d d_misses!!!", deadline_miss);
      }
    }

    // 1Hz seconds display task
    if(hz1_scaler == 0) {
      lcd_locate(0,7);
      lcd_printf("QEI: %5u", getQEI());
      sec++;
    }
    
    hz50_scaler = (hz50_scaler + 1) % 2;
    hz5_scaler = (hz5_scaler + 1) % 20;
    hz1_scaler = (hz1_scaler + 1) % 100;

    start = 0;
  }

  return 0;
}
예제 #19
0
//============================================================
// Asynchronous I2C API (visible externally) component
//============================================================
// <editor-fold defaultstate="collapsed" desc="uint	I2CAsyncStart(uint SubscrID)">
uint	I2CAsyncStart(uint I2Cx, I2CAsyncRqst* Rqst)
	{
	if (!_I2C_Init)		return I2CRC_NRDY;
	//=========================================================
	// Obtain references to proper Control Blocks and registers
	//---------------------------------------------------------
	_I2C_CB*		pCB;
	if ( NULL == (pCB = I2CpCB(I2Cx)) )		return I2CRC_NOTA;
	//---------------------------------------------------------
	I2C_CONBITS*	pCON	= I2CpCON(pCB);
	I2C_STATBITS*	pSTAT	= I2CpSTAT(pCB);
	//=========================================================
	// Validate run-time conditions
	//---------------------------------------------------------
	int		i;
	//---------------------------------------------------------
	uint	RC		= I2CRC_OK;
	BYTE	CPU_IPL;
	//---------------------------------------------------------
	// Enter I2C (and related modules) CRITICAL SECTION
	//---------------------------------------------------------
	SET_AND_SAVE_CPU_IPL(CPU_IPL, _I2C_IL);
		{
		//-----------------------------------------------------------
		// New request...
		//-----------------------------------------------------------
		if (pCB->_I2C_CallBack)
			// There is an active request being processed -
			// several checks need to be implemented...
			{
			//------------------------------------------------------------
			// First, check whether this request already active
			//---------------------------------------------------------
			if (	pCB->_I2C_CallBack		== Rqst->CallBack
				&&	pCB->_I2C_CallBackArg	== Rqst->CallBackArg )
				{
				// Duplicate request...
				RC = I2CRC_RQSTA;
				goto Finally;
				}
			//-------------------------------------------------------
			// Second, check whether this request already queued
			//-------------------------------------------------------
			for (i = 0; i < I2CMaxAsyncRqst; i++)
				{
				if (	pCB->_I2CRqstQueue[i].CallBack		== Rqst->CallBack
					 &&
						pCB->_I2CRqstQueue[i].CallBackArg	== Rqst->CallBackArg )
					{
					// Request is already in the queue...
					RC = I2CRC_OK;
					goto Finally;
					}
				}
			//-------------------------------------------------------
			// Third, try to add this request to the queue
			//-------------------------------------------------------
			for (i = 0; i < I2CMaxAsyncRqst; i++)
				{
				if (	NULL == pCB->_I2CRqstQueue[i].CallBack )
					{
					// Free slot found! Add request to the queue
					pCB->_I2CRqstQueue[i].CallBack		= Rqst->CallBack;
					pCB->_I2CRqstQueue[i].CallBackArg	= Rqst->CallBackArg;
					//-------------------------------------------
					RC = I2CRC_OK;
					goto Finally;
					}
				}
			// No free slots available in the queue...
			RC = I2CRC_QFULL;
			goto Finally;
			}
		else
			// No Active Asynchronous requests now - let's try
			// to innitiate a new Asynchronous request
			{
			// Frist, let's check bus condition
			if (0 == pSTAT->P)
				{
				// Bus is not idle as the last status is not "Stop"
				RC = I2CRC_BUSY;	// // Bus is busy...
				goto Finally;
				}
			//--------------------------------------------
			// Bus condition validated, proceed with activating
			// Async operation
			//---------------------------------------------------------
			// Store in the I2C Library control block address of the
			// callback function of the current bus owner and
			// respective callback parameter.
			//---------------------------------------------------------
			pCB->_I2C_CallBack		= Rqst->CallBack;
			// NOTE: non-NULL value of pCB->_I2C_CallBack field
			//		 also serves as a FLAG indicating that bus is
			//		 busy and tested for in I2CGetStatus(...) routine
			pCB->_I2C_CallBackArg	= Rqst->CallBackArg;
			//--------------------------------------------------------
			I2CSetIF(I2Cx, 0); 	// Clear  I2C Master interrupt flag
			I2CSetIE(I2Cx, 1);	// Enable I2C Master interrupt
			//--------------------------------------------------------
			// Initiate Start on I2C bus
			pCON->SEN = 1;
			// NOTE: because I2C bus is being allocated to the client,
			//		 from now until the asynchronous operation completes
			//		 I2C interrupts will be routed to client's callback
			//		 routine.
			RC = I2CRC_OK;
			goto Finally;
			}
		}
Finally:
	//---------------------------------------------------------
	// Leave I2C CRITICAL SECTION
	//---------------------------------------------------------
  	RESTORE_CPU_IPL(CPU_IPL);
	//=========================================================
	return RC;		
	}
예제 #20
0
//*************************************************************
uint	_MPUAsyncRead(MPUData* pSample)
	{
	//----------------------------------------------
	uint		Ready_Cnt;
	_MPURawData RawData;
	//----------------------------------------------
	int 		current_cpu_ipl;
	//----------------------------------------------

	//==============================================
	// Enter MPU/I2C CRITICAL SECTION
	//----------------------------------------------
  	SET_AND_SAVE_CPU_IPL(current_cpu_ipl, _MPU_IL);  /* disable interrupts */
	//-----------------------------------------------
	pSample->Count	= _MPU_Count;
	//---------------------------------
	RawData.Temp 	= _MPU_Sample.Temp;
	//---------------------------------
	RawData.AX		= _MPU_Sample.AX;
	RawData.AY		= _MPU_Sample.AY;
	RawData.AZ		= _MPU_Sample.AZ;
	//---------------------------------
	RawData.GX		= _MPU_Sample.GX;
	RawData.GY		= _MPU_Sample.GY;
	RawData.GZ		= _MPU_Sample.GZ;
	//-----------------------------------------------
	Ready_Cnt		= _MPU_Ready;
	//-----------------------------------------------
	_MPU_Ready 		= 0;		// Sample consumed...
	//----------------------------------------------
	// Leave MPU/I2C CRITICAL SECTION
	//==============================================
  	RESTORE_CPU_IPL(current_cpu_ipl);

	//==============================================
	// Set sample timestamp
	//----------------------------------------------
	pSample->TS	= TMRGetTS();
	//==============================================
	float	TDev;
	//----------------------------------------------
	// Adjust Sample Weight to account for multiple samples
	//----------------------------------------------
	float 	Weight;
	if (Ready_Cnt > 1)
		Weight = 1.0/(float)Ready_Cnt;
	else
		Weight = 1.0;
	//----------------------------------------------
	// Process collected sample
	//----------------------------------------------
	// Temperature (C) (will be used in subsequent
	// temperature compensation calculation)
	//-----------------------------------------------
	pSample->Temp = (Weight * RawData.Temp - _MPU_Temp_OffsetTo0) * _MPU_Temp_Sensitivity;
	//-----------------------------------------------
	// Acceleration (G)
	//-----------------------------------------------
	TDev	= pSample->Temp - _MPU_Accl_BaseTemp;
	//-----------------------------------------------
	VectorSet	(
				(Weight * RawData.AX - (_MPU_Accl_XOffset + _MPU_Accl_XSlope*TDev)) * _MPU_Accl_Sensitivity,
				(Weight * RawData.AY - (_MPU_Accl_YOffset + _MPU_Accl_YSlope*TDev)) * _MPU_Accl_Sensitivity,
				(Weight * RawData.AZ - (_MPU_Accl_ZOffset + _MPU_Accl_ZSlope*TDev)) * _MPU_Accl_Sensitivity,
				&pSample->A
				);
	//-----------------------------------------------
	// Gyroscopes (Rad/sec)
	//-----------------------------------------------
	TDev	= pSample->Temp - _MPU_Gyro_BaseTemp;
	//-----------------------------------------------
	VectorSet	(
				(Weight * RawData.GX - (_MPU_Gyro_XOffset + _MPU_Gyro_XSlope*TDev)) * _MPU_Gyro_Sensitivity,
				(Weight * RawData.GY - (_MPU_Gyro_YOffset + _MPU_Gyro_YSlope*TDev)) * _MPU_Gyro_Sensitivity,
				(Weight * RawData.GZ - (_MPU_Gyro_ZOffset + _MPU_Gyro_ZSlope*TDev)) * _MPU_Gyro_Sensitivity,
				&pSample->G
				);
	//-----------------------------------------------
	return MPU_OK; 			// The return code was OK	
	}
예제 #21
0
//=============================================================
uint	_MPUCalibrateAsync()
	{
	if (!_MPU_Init)
		return MPU_NOTINIT;		// Not initialized...
	//-----------------------
	if (0 == _MPU_Async)
		return MPU_NACT;		// Asynchronous read not active...

	//=========================================================
	// Local Variables
	//---------------------------------------------------------
	ulong Alarm	= TMRSetAlarm(2000);	// Set Alarm time 2 sec
										// into the future.
	//---------------------------------------------------------
	uint		Ready_Cnt;
	_MPURawData RawData;
	//----------------------------------------------
	int 		current_cpu_ipl;
	//=========================================================

	//=========================================================
	// Reset  Gyro offsets...
	//---------------------------------------------------------
	_MPU_Gyro_XOffset		= 0;
	_MPU_Gyro_YOffset		= 0;
	_MPU_Gyro_ZOffset		= 0;
	//---------------------------------------------------------
	// To collect averages we would like to "watch" MPU for at
	// least 2 seconds; number of samples will be variable
	// depending on the value of RateDiv
	//---------------------------------------------------------
	TMRWaitAlarm(Alarm);
	//---------------------------------------------------------

	//=========================================================
	// Enter MPU/I2C CRITICAL SECTION
	//---------------------------------------------------------
  	SET_AND_SAVE_CPU_IPL(current_cpu_ipl, _MPU_IL);  /* disable interrupts */
	//---------------------------------------------------------
	RawData.Temp 	= _MPU_Sample.Temp;
	//---------------------------------
	RawData.AX		= _MPU_Sample.AX;
	RawData.AY		= _MPU_Sample.AY;
	RawData.AZ		= _MPU_Sample.AZ;
	//---------------------------------
	RawData.GX		= _MPU_Sample.GX;
	RawData.GY		= _MPU_Sample.GY;
	RawData.GZ		= _MPU_Sample.GZ;
	//---------------------------------------------------------
	Ready_Cnt		= _MPU_Ready;
	//---------------------------------------------------------
	_MPU_Ready 		= 0;		// Sample consumed...
	//---------------------------------------------------------
	// Leave MPU/I2C CRITICAL SECTION
	//=========================================================
  	RESTORE_CPU_IPL(current_cpu_ipl);
	//=========================================================

	//=========================================================
	// Adjust Sample Weight to account for multiple samples
	//---------------------------------------------------------
	float 	Weight;
	if (Ready_Cnt > 1)
		Weight = 1.0/(float)Ready_Cnt;
	else
		Weight = 1.0;
	//=========================================================

	//=========================================================
	// Process collected sample
	//---------------------------------------------------------
	// Gyro offset is calculated in LSB units
	//---------------------------------------
	_MPU_Gyro_XOffset	= (float)RawData.GX * Weight;
	_MPU_Gyro_YOffset	= (float)RawData.GY * Weight;
	_MPU_Gyro_ZOffset	= (float)RawData.GZ * Weight;
	//---------------------------------------
	// Base temperature converted to degrees C
	//---------------------------------------
	_MPU_Gyro_BaseTemp	= ((float)RawData.Temp * Weight - _MPU_Temp_OffsetTo0)
						  * _MPU_Temp_Sensitivity;
	//*********************************************************
	return MPU_OK;
	}
예제 #22
0
//*************************************************************
uint	MPUAsyncAdjustAccZBase(float Incl)
	{
	if (0 == _MPU_Async)
		return MPU_NACT;	// Asynchronous read not active...
	//--------------------------------------------------
	TMRDelay(2000); 		// Wait 2,000 msec (2 second) to
							// accumulate in the buffer enough
							// samples for for solid averaging
	//----------------------------------------------
	uint		Ready_Cnt;
	_MPURawData RawData;
	//----------------------------------------------
	int 		current_cpu_ipl;
	//----------------------------------------------

	//==============================================
	// Enter MPU/I2C CRITICAL SECTION
	//----------------------------------------------
  	SET_AND_SAVE_CPU_IPL(current_cpu_ipl, _MPU_IL);  /* disable interrupts */
	//-----------------------------------------------
	RawData.Temp 	= _MPU_Sample.Temp;
	//---------------------------------
	RawData.AX		= _MPU_Sample.AX;
	RawData.AY		= _MPU_Sample.AY;
	RawData.AZ		= _MPU_Sample.AZ;
	//---------------------------------
	RawData.GX		= _MPU_Sample.GX;
	RawData.GY		= _MPU_Sample.GY;
	RawData.GZ		= _MPU_Sample.GZ;
	//-----------------------------------------------
	Ready_Cnt		= _MPU_Ready;
	//-----------------------------------------------
	_MPU_Ready 		= 0;		// Sample consumed...
	//----------------------------------------------
	// Leave MPU/I2C CRITICAL SECTION
	//==============================================
  	RESTORE_CPU_IPL(current_cpu_ipl);

	//==============================================
	// Adjust Sample Weight to account for multiple samples
	//----------------------------------------------
	float 	Weight;
	if (Ready_Cnt > 1)
		Weight = 1.0/(float)Ready_Cnt;
	else
		Weight = 1.0;
	//----------------------------------------------
	// Process collected sample
	//----------------------------------------------
	// Temperature (C) (will be used in subsequent
	// temperature compensation calculation)
	//-----------------------------------------------
	float	Temp = (Weight * RawData.Temp - _MPU_Temp_OffsetTo0) * _MPU_Temp_Sensitivity;
	//-----------------------------------------------
	// Acceleration (G)
	//-----------------------------------------------
	float	TDev	= Temp - _MPU_Accl_BaseTemp;
	//-----------------------------------------------
//	AccZBase = (Weight * RawData.AZ - _MPU_Accl_ZOffset - _MPU_Accl_ZSlope*TDev) * _MPU_Accl_Sensitivity;

	// NOTE: Incl is the cosine of the angle between Earth gravity 
	// ( -1G given given Z-axis orientation to be "down"), thus
	// Expected AccZ => -Incl; AccZ should appear on the right side
	// with the "-" sign and as two "-" becomes "+" we can use Incl
	// directly in the formula below
	_MPU_Accl_ZOffset  = Incl/_MPU_Accl_Sensitivity + Weight * RawData.AZ - _MPU_Accl_ZSlope*TDev;

	//-----------------------------------------------
	return MPU_OK; 			// The return code was OK	
	}
예제 #23
0
void ReadCTMU( void )
{
    int                     current_ipl;
    int                     i;
    int                     j;
    volatile unsigned int   tempADch;


    tempADch            = AD1CHS0;      //store the current A/D mux channel selected

    AD1CON1             = 0x0000;       // Unsigned integer format
    AD1CSSL             = 0x0000;
    AD1CON3             = 0x0002;
    AD1CON2             = 0x0000;
    AD1CON1bits.ADON    = 1;            // Start A/D in continuous mode

    for(i = 0; i < NUM_TOUCHPADS; i++)
    {
        // Get the raw sensor reading.
        AD1CHS0                 = STARTING_ADC_CHANNEL + buttonIndex; //select A/D channel

        // Make sure touch circuit is completely discharged
        IFS0bits.AD1IF          = 0;
        AD1CON1bits.DONE        = 0;
        AD1CON1bits.SAMP        = 1;        // Manually start the conversion
        // Wait for the A/D converter to begin sampling
        Nop();    Nop();    Nop();    Nop();    Nop();    Nop();    Nop();    Nop();
        CTMUCONbits.IDISSEN     = 1;        // Drain any charge on the circuit
        Nop();    Nop();    Nop();    Nop();    Nop();
        CTMUCONbits.IDISSEN     = 0;
        Nop();    Nop();    Nop();    Nop();    Nop();
        IFS0bits.AD1IF          = 0;
        AD1CON1bits.SAMP        = 0;
        while(!IFS0bits.AD1IF);             // Wait for the A/D conversion to finish
                                            // Note: This A/D conversion not used.
                                            // A/D mux must connect to the channel
                                            // for CTMU to drain charge

        // Charge touch circuit

        // Since the charge is time dependent, set the CPU priority such
        // that we will not be interrupted during the read.
        SET_AND_SAVE_CPU_IPL( current_ipl, 7 );

        IFS0bits.AD1IF          = 0;

        AD1CON1bits.SAMP        = 1;        // Manually start the conversion
        CTMUCONbits.EDG2STAT    = 0;        // Make sure edge2 is 0
        CTMUCONbits.EDG1STAT    = 1;        // Set edge1 - Start Charge

        for (j = 0; j < CHARGE_TIME_COUNT; j++);    // Delay for CTMU charge time

        CTMUCONbits.EDG1STAT    = 0;        // Clear edge1 - Stop Charge

        // Re-enable interrupts.
        RESTORE_CPU_IPL( current_ipl );

        IFS0bits.AD1IF          = 0;
        AD1CON1bits.SAMP        = 0;
        while(!IFS0bits.AD1IF);             // Wait for the A/D conversion to finish

        value                   = ADC1BUF0; // Read the value from the A/D conversion


        //Discharge the touch circuit
        IFS0bits.AD1IF          = 0;
        AD1CON1bits.SAMP        = 1;        // Manually start the conversion

        // Wait for A/D conversion to begin
        Nop();    Nop();    Nop();    Nop();    Nop();    Nop();    Nop();    Nop();
        CTMUCONbits.IDISSEN     = 1;        // Drain any charge on the circuit
        Nop();    Nop();    Nop();    Nop();    Nop();
        CTMUCONbits.IDISSEN     = 0;        // End charge drain
        Nop();    Nop();    Nop();    Nop();
        IFS0bits.AD1IF          = 0;
        AD1CON1bits.SAMP        = 0;        // Perform conversion
        while(!IFS0bits.AD1IF);             // Wait for the A/D conversion to finish
        IFS0bits.AD1IF          = 0;
        AD1CON1bits.DONE        = 0;        // Note: The A/D conversion not used
                                            // A/D mux must connect to the channel
                                            // for CTMU to drain charge
        //End of CTMU read


        bigVal                  = value  * 16;                  // bigVal is current measurement left shifted 4 bits
        smallAvg                = average[buttonIndex]  / 16;   // smallAvg is the current average right shifted 4 bits
        rawCTMU[buttonIndex]    = bigVal;                       // raw array holds the most recent bigVal values

        // On power-up, reach steady-state readings

        if (first > 0)
        {
            first--;
            average[buttonIndex] = bigVal;
            SetNextChannel();
            break;
        }

        // Is a keypad button pressed or released?

        if (bigVal < (average[buttonIndex] - trip[buttonIndex]))
        {
            // Pressed
            switch(buttonIndex)
            {
                case TOUCHPAD1:    buttons.BTN1  = 1;  break;
                case TOUCHPAD2:    buttons.BTN2  = 1;  break;
                case TOUCHPAD3:    buttons.BTN3  = 1;  break;
                case TOUCHPAD4:    buttons.BTN4  = 1;  break;
                case TOUCHPAD5:    buttons.BTN5  = 1;  break;
            }

        }
        else if (bigVal > (average[buttonIndex] - trip[buttonIndex] + hyst[buttonIndex]))
        {
            // Released
            switch(buttonIndex)
            {
                case TOUCHPAD1:    buttons.BTN1  = 0;  break;
                case TOUCHPAD2:    buttons.BTN2  = 0;  break;
                case TOUCHPAD3:    buttons.BTN3  = 0;  break;
                case TOUCHPAD4:    buttons.BTN4  = 0;  break;
                case TOUCHPAD5:    buttons.BTN5  = 0;  break;
            }
        }

        // Implement quick-release for a released button

        if (bigVal  > average[buttonIndex])
        {
            average[buttonIndex] = bigVal;                                      // If raw is above Average, reset to high average.
        }

        // Average in the new value.  Always Average (all buttons)
        // Counting 0..8 has effect of every 9th count cycling the next button.
        // Counting 0..4 will average faster and also can use 0..4*m, m=0,1,2,3..
        if(i == 0)
        {
            if (AvgIndex < AVG_DELAY)
            {
                AvgIndex++;
            }
            else
            {
                AvgIndex = 0;
            }
        }

        if (AvgIndex == AVG_DELAY)
        {
            // Average in raw value.
            average[buttonIndex] = average[buttonIndex] + (value - smallAvg);
        }

        // Determine next sensor to test.

        SetNextChannel();

    }

    if((screenState == SCREEN_GRAPH) || (screenState == SCREEN_CAPTURE))
    {
        // Read the potentiometer and store it for the demo.
        GraphReadPotentiometer();
    }

    #ifdef USE_TOUCHPAD_STATE_MACHINE
        GestureStateMachine();
    #endif

    AD1CHS0 = tempADch;  //restore A/D channel select
}