void calib_control_lever(struct ETMCVAR* petmcvar)
{
	int clcalstate = 0;		// state for control lever intial calibration
	int i;					// loop counter
	int adc_tmp;
	unsigned int t_led = DTWTIME + FLASHCOUNT;	//	initial t_led
	char vv[128];

	int ledCount = 0;
	int cycleCount = 1;
	#define ledPatternLength 32
	#define ledLag 3
	//	led test pattern with extension to effect circular behavior
		u32 ledTestPattern[] = 
	{
		0xffff,
		0xffff,
		0x0000,
		0x0000,
		0x0000,
		0x0000,
		0xffff,
		0xffff,
		0x0000,
		0x0000,
		0x0000,
		0x0000,
		LED_SAFE,
		LED_PREP,
		LED_ARM,
		LED_STOP,
		LED_GNDRLRTN,
		LED_RAMP,
		LED_CLIMB,
		LED_ABORT,
		LED_RECOVERY,
		LED_PREP,
		LED_RETRIEVE,
		LED_SAFE,		
		LED_ARM_PB,
		LED_PREP_PB,
		0x0000,
		0x0000,
		0x0000,
		0x0000,
		0x0000,
		0x0000,
		0xffff,
		0xffff,
		0x0000,
		0x0000,
		0x0000,
		0x0000
	};

	if (GPIOB_IDR & (1 << 1)) //	test for physical or glass CP
	{	//	physical CP
		xprintf (UXPRT,"\nBegin control lever calibration\n\r");
		// dummy read of SPI switches to deal with false 0000 initially returned
		spi2_rw(petmcvar->spi_ledout, petmcvar->spi_swin, SPI2SIZE);
		while(clcalstate < 6)
		{
			if (((int)(DTWTIME - t_led)) > 0) // Has the time expired?
			{ //	Time expired
				//	read filtered control lever adc last value and update min and max values
				adc_tmp = adc_last_filtered[CL_ADC_CHANNEL];
				cloffset = (cloffset < adc_tmp) ? cloffset : adc_tmp;
				clmax = (clmax > adc_tmp) ? clmax : adc_tmp;
				//	Read SPI switches
				//	get most current switch positions
				
				//	Not sure why 
				/*if (spi2_busy() != 0) // Is SPI2 busy?
				{ // SPI completed  
					spi2_rw(petmcvar->spi_ledout, petmcvar->spi_swin, SPI2SIZE); // Send/rcv SPI2SIZE bytes
					//	convert to a binary word for comparisons (not general for different SPI2SIZE)
					sw = (((int) petmcvar->spi_swin[0]) << 8) | (int) petmcvar->spi_swin[1];
					//sw = petmcvar->spi_swin;	*/
				
				//	usage of spi2rw() is bad.  Should wait for not busy after starting it.

				if (spi2_busy() != 0) // Is SPI2 busy?
				{ // Here, no.
					u32 tmp = petmcvar->cp_outputs;
	    			for (i = SPI2SIZE - 1; i >= 0; i--)
	    			{
	    				petmcvar->spi_ledout[i] = (char) tmp;
	    				tmp >>= 8;
	    			}
	    			petmcvar->cp_inputs = (((int) petmcvar->spi_swin[0]) << 8) | (int) petmcvar->spi_swin[1];
					spi2_rw(petmcvar->spi_ledout, petmcvar->spi_swin, SPI2SIZE); 
					xprintf(UXPRT, "%5u %5d %8x \n\r", clcalstate, adc_tmp, petmcvar->cp_inputs);	

					petmcvar->cp_outputs = 0;
					if ((clcalstate == 1) || (clcalstate == 2))
					{
						// LEDs chasing their tails
						for (i = 0; i < ledLag; i++)
						{
							petmcvar->cp_outputs |= ledTestPattern[ledCount + i];
						}
					}

					switch(clcalstate)
					{				
						case 0:	//	entry state
						{
							sprintf(vv, "Cycle control lever");
							lcd_printToLine(UARTLCD, 0, vv);
							sprintf(vv, "twice:");
							lcd_printToLine(UARTLCD, 1, vv);
							double_beep();
							clcalstate = 1;
						}
						case 1:	// waiting for CL to rest position	
						{
							if (petmcvar->cp_inputs & CLREST) break;
							clcalstate = 2;
							cloffset = clmax = adc_tmp;	//	reset min and max values
							sprintf(vv, "twice: 0");
							lcd_printToLine(UARTLCD, 1, vv);
							break;
						}
						case 2:	//	waiting for full scale position first time
						{
							if (petmcvar->cp_inputs & CLFS) break ;
							clcalstate = 3;
							sprintf(vv, "twice: 0.5");
							lcd_printToLine(UARTLCD, 1, vv);
							break;						
						}
						case 3:	//	wating for return to rest first time
						{
							if (petmcvar->cp_inputs & CLREST) break; 
							clcalstate = 4;
							// clcalstate = 6;		//	only requires 1 cycle
							sprintf(vv, "twice: 1  ");
							lcd_printToLine(UARTLCD, 1, vv);
							single_beep();
							break;
						}
						case 4:	//	waiting for full scale second time
						{
							if (petmcvar->cp_inputs & CLFS) break;
							clcalstate = 5;
							sprintf(vv, "twice: 1.5");
							lcd_printToLine(UARTLCD, 1, vv);
							break;					
						}
						case 5:	//	waiting for return to rest second time
						{
							if (petmcvar->cp_inputs & CLREST) break;
							single_beep();
							clcalstate = 6; 
						}
					}			
				}
				toggle_4leds(); 	// Advance some LED pattern
				ledCount++;
				if (ledCount >= ledPatternLength)
				{
					ledCount = 0;
				} 
				t_led += FLASHCOUNT; 	// Set next toggle time	
			}
Esempio n. 2
0
/* **************************************************************************************
 * void stateMachine(struct ETMCVAR* petmcvar);
 * @brief	: Run state machine
 * @param	: petmcvar = pointer vars passed from etmc0
 * ************************************************************************************** */
void stateMachine(struct ETMCVAR* petmcvar)
{ 
	struct CANRCVBUF can;


    if (statevar.launchResetFlag == 1)   // init variables for launch
     {
        //  reset variables for next launch
         statevar.state = 0;
         statevar.tensionMessageFlag = statevar.speedMessageFlag = 0;
         statevar.parametersRequestedFlag = 0;
         statevar.paramReceivedFlag = 0;
         statevar.launchResetFlag = 0;
         statevar.filt_torque = 0;  //  This should be set to 0 on entry to
                                    //  Prep from Safe in real system
     }

     
     #if LONGTIME     
     
     // update the long times
     simulationvar.tmpTime = DTWTIME;
     // check msbs for overflow toggle
     if (((simulationvar.tmpTime & 0x80000000) == 0) && ((simulationvar.oldTime & 0x80000000) == 1))
     {  //  DTWTIME has overflowed
        simulationvar.longTime += 0x0000000100000000;
     }
     simulationvar.longTime &= 0xffffffff00000000;
     simulationvar.longTime |= (u64) simulationvar.tmpTime;
     simulationvar.oldTime = simulationvar.tmpTime;     

     if (((long)(simulationvar.longTime - simulationvar.nextStepTime) >= 0))
        //&& (statevar.tensionMessageFlag == 1) 
        //&& (statevar.speedMessageFlag == 1))
        {
            (statevar.elapsedTics)++;
            can.id = CANID_TIME;    // time id
            if (++(petmcvar->fracTime) != stateparam.TICSPERSECOND)
            {
                can.dlc = 1;
                can.cd.uc[0] = petmcvar->fracTime;
            }
            else
            {                
                can.dlc = 5;
                can.cd.ui[0] = (petmcvar->unixtime)++;
                can.cd.uc[4] = (u8) 0;    //  status proxy
                petmcvar->fracTime = 0;
            }            
            msg_out_mc(&can); // output to CAN+USB
debug_mc_state1 = petmcvar->fracTime;
            // next on time Time message time                   
            simulationvar.nextStepTime  += stateparam.STEPTIMECLOCKS;
        }
        #else
        if (((int)(DTWTIME - simulationvar.nextStepTime) > 0))
            //&& (statevar.tensionMessageFlag == 1) 
            //&& (statevar.speedMessageFlag == 1))
        {
            (statevar.elapsedTics)++;
            can.id = CANID_TIME;    // time id
            if (++(petmcvar->fracTime) != stateparam.TICSPERSECOND)
            {
                can.dlc = 1;
                can.cd.uc[0] = petmcvar->fracTime;
            }
            else
            {                
                can.dlc = 5;
                can.cd.ui[0] = (petmcvar->unixtime)++;
                can.cd.uc[4] = (u8) 0;    //  status proxy
                petmcvar->fracTime = 0;
            }            
debug_mc_state1 = petmcvar->fracTime;
            msg_out_mc(&can); // output to CAN+USB
debug_mc_state2 = DTWTIME; // Time round trip to PS
            // next on time Time message time                   
            simulationvar.nextStepTime  += stateparam.STEPTIMECLOCKS;


// dummy control lever messages to flush buffer
can.id = CANID_CONTROL_LEVER;
can.dlc = 0;
can.dlc = 8; // Max size
can.cd.uc[0] = debug_mc_state1;    //  for debug        
for (int i = 0; i < 0; i++)
{
	msg_out_mc(&can);

}    
	} 
        #endif

    //  this needs to be moved into  SPIInOut()
    //  convert to a binary word for comparisons (not general for different SPI2SIZE)
    cpsw = (((int) petmcvar->spi_swin[0]) << 8) | (int) petmcvar->spi_swin[1];
            
    switch (statevar.state)
    {
        case 0: // prep                        
            //  This will be replaced with detection of pushing the ARM button
            //  if (calib_control_lever_get() < (float) 0.05)
        petmcvar->spi_ledout[1] = 0x01;
        if((cpsw & CPARM) == 0)
            { 
                statevar.state = 1; // going to armed state
                // setStateled(1);	// ??? LED
                sendStateMessage(2);
                mc_debug_print();
            }
            break;
        case 1: // armed            
            petmcvar->spi_ledout[1] = 0x01 & petmcvar->ledBlink;
            if ((statevar.parametersRequestedFlag == 0) 
                    && (calib_control_lever_get() > (float) 0.95))
            {
                // request launch parameters
            	can.id = CANID_PARAM_REQUEST;
can.cd.uc[0] = debug_mc_state1;    //  for debug
            	can.dlc = 0 + 1;
            	msg_out_mc(&can);
                statevar.parametersRequestedFlag = 1;
            }
            if ((statevar.parametersRequestedFlag == 1) 
                    && (calib_control_lever_get() < (float) 0.05))
            {
                // reset and wait for control lever again                
                statevar.parametersRequestedFlag = 0;
            }
            // when we get the response, start the simulation
            if (statevar.paramReceivedFlag == 1)
            {
            //    simulationvar.startTime = (double) DTWTIME; // not used?
                
                statevar.state = 2;
                single_beep();
                // setStateled(2); 	// LED ???
                petmcvar->spi_ledout[1] = 0x00;
                statevar.startProfileTics = statevar.elapsedTics;
                sendStateMessage(3);
                mc_debug_print();
            }
            break;
        case 2: // profile 1   soft start
            if ((statevar.elapsedTics - statevar.startProfileTics) 
                >= (stateparam.SOFT_START_TIME * stateparam.TICSPERSECOND))
            {
                statevar.state = 3;
                statevar.peakCableSpeed = measurements.lastCableSpeed;
                mc_debug_print();
            }
            break;
        case 3: // profile 2   constant tension ground roll
            statevar.peakCableSpeed = measurements.lastCableSpeed > statevar.peakCableSpeed
                    ? measurements.lastCableSpeed : statevar.peakCableSpeed;
            if (measurements.lastCableSpeed < (statevar.peakCableSpeed * stateparam.PEAK_CABLE_SPEED_DROP))
            {
                statevar.state = 4;
                statevar.startRampTics = statevar.elapsedTics;
                statevar.startRampTension = measurements.lastTension;
                single_beep();
                sendStateMessage(4);
                // setStateled(4);
                mc_debug_print();
            }
            break;
        case 4: // ramp
            if (statevar.elapsedTics - statevar.startRampTics > stateparam.RAMP_TIME * stateparam.TICSPERSECOND)
            {
                statevar.state = 5;
                // setStateled(5);
                single_beep();
                sendStateMessage(5);
                statevar.minCableSpeed = measurements.lastCableSpeed;
                mc_debug_print();
                statevar.taperFlag = 0;
            }
            break;
        case 5: // constant
            //  xprintf(UXPRT,"%6d\n\r", (double) measurements.lastCableSpeed);
            if (measurements.lastCableSpeed < statevar.minCableSpeed)
            {
                statevar.minCableSpeed = measurements.lastCableSpeed;
            }
            if (measurements.lastCableSpeed > statevar.minCableSpeed + stateparam.RELEASEDELTA)
            {
                single_beep();
                statevar.state = 6;
                // setStateled(6);
                sendStateMessage(6);
                mc_debug_print();
            }
            break;
        case 6: // recovery
             //xprintf(UXPRT,"%6d\n\r",measurements.lastCableSpeed);
            if (measurements.lastCableSpeed < stateparam.ZERO_CABLE_SPEED_TOLERANCE)
            {
                statevar.state = 0;
                single_beep();
                // setStateled(0);
                sendStateMessage(1);
                mc_debug_print();
                statevar.launchResetFlag = 1;                            
            }
            break;
    }   // end of switch (statevar.state)
    
    //  Template for Desired Tension and Control Law
    if ((statevar.tensionMessageFlag == 1) && (statevar.speedMessageFlag == 1))   
    {
        switch (statevar.state)
        {
            case 0: // prep
                statevar.setptTension = 0;
                break;

            case 1: // armed
                statevar.setptTension = 0;
                break;
            case 2: // profile 1   soft start
                statevar.setptTension = (float) (stateparam.GROUND_TENSION_FACTOR * stateparam.GLIDER_WEIGHT
                * 0.5  * (1 - cosf(stateparam.K1 * (statevar.elapsedTics - statevar.startProfileTics))));
                break;

            case 3: // profile 2   constant tension ground roll with taper
                // System.out.println(measurements.lastCableSpeed +  stateparam.PROFILE_TRIGGER_CABLE_SPEED);
                if (measurements.lastCableSpeed < stateparam.PROFILE_TRIGGER_CABLE_SPEED)
                {
                    statevar.setptTension = stateparam.GROUND_TENSION_FACTOR * stateparam.GLIDER_WEIGHT;
                    //xprintf(UXPRT,"%6d\n\r", (double) statevar.setptTension);	//  System.out.println(tension);
                } 
	             else
                {
                    statevar.setptTension = (float) (stateparam.GROUND_TENSION_FACTOR * stateparam.GLIDER_WEIGHT * cosf(stateparam.K2 * (measurements.lastCableSpeed - stateparam.PROFILE_TRIGGER_CABLE_SPEED)));
                    //xprintf(UXPRT,"%6d\n\r", (double) statevar.setptTension);	// System.out.println(tension);
                }
                break;
            case 4: // ramp
                statevar.setptTension = (float) ((statevar.startRampTension
                        + (stateparam.CLIMB_TENSION_FACTOR * stateparam.GLIDER_WEIGHT
                        - statevar.startRampTension)
                        * sinf(stateparam.K3 * (statevar.elapsedTics - statevar.startRampTics))));
                //xprintf(UXPRT,"%6d\n\r", (double) statevar.setptTension);	//  System.out.println(tension);
                break;
            case 5: // constant
                statevar.setptTension = (float) (stateparam.CLIMB_TENSION_FACTOR * stateparam.GLIDER_WEIGHT);
                if (statevar.taperFlag == 1)
                {
                    statevar.setptTension *= 0.4 + 0.6 * 0.5
                            * (1 + cosf(stateparam.K4 * (statevar.elapsedTics - statevar.taperTics)));
                }
                break;
            case 6: // recovery
                statevar.setptTension = stateparam.MAX_PARACHUTE_TENSION;
                if (measurements.lastCableSpeed > stateparam.PROFILE_TRIGGER_CABLE_SPEED)
                {
                    statevar.setptTension *= cosf(stateparam.K5 * (measurements.lastCableSpeed - stateparam.PARACHUTE_TAPER_SPEED));
                    //xprintf(UXPRT,"%6d\n\r",(double) statevar.setptTension);	// System.out.println(tension);
                }
                break;            
        }
        //  scale by control lever
        //statevar.setptTension *= calib_control_lever_get();   //  comment out to not have to hold handle

        //  filter the torque with about 1 Hz bandwidth
        statevar.setptTorque = statevar.setptTension * stateparam.TENSION_TO_TORQUE; 
        statevar.filt_torque += (statevar.setptTorque - statevar.filt_torque) 
        * ((float) 1.0 / ((8 * stateparam.TICSPERSECOND) / 64));

        // torqueMessage.set_short((short) (statevar.filt_torque / scaleoffset.torqueScale), 0); // torque
     	can.id = CANID_TORQUE;
        can.dlc = 2 + 1;
can.cd.uc[2] = debug_mc_state1;    //  for debug
        can.cd.us[0] = (short) (statevar.filt_torque / scaleoffset.torqueScale);
        msg_out_mc(&can);
        statevar.tensionMessageFlag = statevar.speedMessageFlag = 0;
    }            
}