示例#1
0
void CAN1RxMsgProcess(void)
{
    CANRxMessageBuffer *message;

    if(isCAN1MsgReceived == FALSE)
    {
        return;
    }

    isCAN1MsgReceived = FALSE;

    message = CANGetRxMessage(CAN1, CAN_CHANNEL1);
    lcdInstruction("0;0H");
    unsigned int sid = message->msgSID.SID;

    unsigned int data = message->data[0] << 8;
    unsigned int data2 = message->data[1];
    float temp = (data + data2) * 0.1;

    sprintf(buffer, "%u", sid);
    lcdString(buffer);

    sprintf(buffer, "%2.2fF", temp);

    lcdInstruction("1;0H");
    lcdString("ET: ");
    lcdString(buffer);

    CANUpdateChannel(CAN1, CAN_CHANNEL1);
    CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);

}
示例#2
0
void __attribute__((vector(47), interrupt(ipl4), nomips16)) CAN2InterruptHandler(void)
{

    /* This is the CAN2 Interrupt Handler. Note that there
    * are many events in the CAN2 module that can cause
    * this interrupt. These events are enabled by the
    * CANEnableModuleEvent() function. In this example,
    * only the RX_EVENT is enabled. */


    /* Check if the source of the interrupt is RX_EVENT.
    * This is redundant  since only this event is enabled
    * in this example but this shows one scheme for handling
    * interrupts. */
    if((CANGetModuleEvent(CAN2) & CAN_RX_EVENT) != 0)
    {

        /* Within this, you can check which event caused the
        * interrupt by using the CANGetPendingEventCode() function
        * to get a code representing the highest priority active
        * event.*/

        if(CANGetPendingEventCode(CAN2) == CAN_CHANNEL1_EVENT)
        {
            /* This means that channel 1 caused the event.
            * The CAN_RX_CHANNEL_NOT_EMPTY event is persistent. You
            * could either read the channel in the ISR
            * to clear the event condition or as done
            * here, disable the event source, and set
            * an application flag to indicate that a message
            * has been received. The event can be
            * enabled by the application when it has processed
            * one message.
            *
            * Note that leaving the event enabled would
            * cause the CPU to keep executing the ISR since
            * the CAN_RX_CHANNEL_NOT_EMPTY event is persistent (unless
            * the not empty condition is cleared.)
            * */

            CANEnableChannelEvent(CAN2, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);
            isCAN2MsgReceived = TRUE;
        }
    }

    /* The CAN2 Interrupt flag is  cleared at the end of the
    * interrupt routine. This is because the event
    * that could have caused this interrupt  to occur
    * (CAN_RX_CHANNEL_NOT_EMPTY) is disabled. Attempting to
    * clear the CAN2 interrupt flag when the the CAN_RX_CHANNEL_NOT_EMPTY
    * interrupt is enabled will not have any effect because the
    * base event is still present. */

    INTClearFlag(INT_CAN2);


}
示例#3
0
CAN1InterruptHandler(void)
{
    if ((CANGetModuleEvent(CAN1) & CAN_RX_EVENT) != 0)
    {
        if(CANGetPendingEventCode(CAN1) == CAN_CHANNEL1_EVENT)
        {
            CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);
            isCAN1MsgReceived = TRUE;
        }
    }
    INTClearFlag(INT_CAN1);
}
示例#4
0
void CAN1Init(void)
{
    CAN_BIT_CONFIG canBitConfig;
    UINT baudPrescalar;
    CANEnableModule(CAN1, TRUE);
    CANSetOperatingMode(CAN1, CAN_CONFIGURATION);
    while(CANGetOperatingMode(CAN1) != CAN_CONFIGURATION);

    // Standard Values
    canBitConfig.phaseSeg2Tq = CAN_BIT_3TQ;
    canBitConfig.phaseSeg1Tq = CAN_BIT_5TQ;
    canBitConfig.propagationSegTq = CAN_BIT_1TQ;
    canBitConfig.phaseSeg2TimeSelect = TRUE;
    canBitConfig.sample3Time = TRUE;
    canBitConfig.syncJumpWidth = CAN_BIT_1TQ;

    // Set speed to 1Mbit/s
    CANSetSpeed(CAN1, &canBitConfig, SYSTEM_FREQ, CAN_BUS_SPEED);

    // 256 bytes of storage space
    CANAssignMemoryBuffer(CAN1, CAN1MessageFifoArea, (2*8*16));

    CANConfigureChannelForTx(CAN1, CAN_CHANNEL0, 8, CAN_TX_RTR_DISABLED,
            CAN_LOW_MEDIUM_PRIORITY);

    CANConfigureChannelForRx(CAN1, CAN_CHANNEL1, 8, CAN_RX_FULL_RECEIVE);

    CANConfigureFilter(CAN1, CAN_FILTER0, 0x5F1, CAN_SID);

    CANConfigureFilterMask(CAN1, CAN_FILTER_MASK0, 0x7FF, CAN_SID, CAN_FILTER_MASK_IDE_TYPE);

    CANLinkFilterToChannel(CAN1, CAN_FILTER0, CAN_FILTER_MASK0, CAN_CHANNEL1);

    CANEnableFilter(CAN1, CAN_FILTER0, TRUE);

    CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);

    CANEnableModuleEvent(CAN1, CAN_RX_EVENT, TRUE);

    INTSetVectorPriority(INT_CAN_1_VECTOR, INT_PRIORITY_LEVEL_4);
    INTSetVectorSubPriority(INT_CAN_1_VECTOR, INT_SUB_PRIORITY_LEVEL_0);
    INTEnable(INT_CAN1, INT_ENABLED);

    CANSetOperatingMode(CAN1, CAN_NORMAL_OPERATION);
    while(CANGetOperatingMode(CAN1) != CAN_NORMAL_OPERATION);

    
}
示例#5
0
CANRxMessageBuffer* CAN1RxMsgProcess(void)
{
    /* This function will check if a CAN
    * message is available in CAN1 channel 1.
    * If so , the message is read. Byte 0 of
    * the received message will indicate if
    * LED6 should be switched ON or OFF. */

    CANRxMessageBuffer * message;

    if(isCAN1MsgReceived == FALSE)
    {
    /* CAN1 did not receive any message so
    * exit the function. Note that the
    * isCAN1MsgReceived flag is updated
    * by the CAN1 ISR. */

        return 0;
    }

    /* Message was received. Reset message received flag to catch
    * the next message and read the message. Note that
    * you could also check the CANGetRxMessage function
    * return value for null to check if a message has
    * been received. */

    isCAN1MsgReceived = FALSE;

    message = CANGetRxMessage(CAN1,CAN_CHANNEL1);

    /* Call the CANUpdateChannel() function to let
    * CAN 1 module know that the message processing
    * is done. Enable the receive channale not empty event
    * so that the CAN module generates an interrupt when
    * the event occurs the next time.*/


    CANUpdateChannel(CAN1, CAN_CHANNEL1);
    CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);
    return message;

}
示例#6
0
s32
nu__Can__add_channel_tx(const struct nu__Can *c, CAN_CHANNEL channel,
            u32 channel_msg_size, CAN_TX_RTR rtr_enabled,
            CAN_TXCHANNEL_PRIORITY tx_priority, CAN_CHANNEL_EVENT interrupt_events)
{
    s32 err;

    if ((err = go_config_mode(c)) < 0) {
        go_normal_mode(c);
        return err;
    }

    CANConfigureChannelForTx(c->module, channel, channel_msg_size, rtr_enabled, tx_priority);
    CANEnableChannelEvent(c->module, channel, interrupt_events, TRUE);

    if ((err = go_normal_mode(c)) < 0)
        return err;

    return 0;
}
示例#7
0
s32
nu__Can__add_channel_rx(const struct nu__Can *c, CAN_CHANNEL chn, u32 channel_msg_size,
                    CAN_RX_DATA_MODE data_only, CAN_CHANNEL_EVENT interrupt_events)
{
    s32 err;

    if ((err = go_config_mode(c)) < 0) {
        go_normal_mode(c);
        return err;
    }

    CANConfigureChannelForRx(c->module, chn, channel_msg_size, data_only);
    CANConfigureFilter(c->module, CAN_FILTER0, 0, CAN_SID);
    CANConfigureFilterMask(c->module, CAN_FILTER_MASK0, 0, CAN_SID, CAN_FILTER_MASK_ANY_TYPE);
    CANLinkFilterToChannel(c->module, CAN_FILTER0, CAN_FILTER_MASK0, CAN_CHANNEL1);
    CANEnableFilter(c->module, CAN_FILTER0, TRUE);
    CANEnableChannelEvent(c->module, chn, interrupt_events, TRUE);

    if ((err = go_normal_mode(c)) < 0)
        return err;

    return 0;
}
示例#8
0
CANRxMessageBuffer* CAN2RxMsgProcess(void)
{
    /* This function will check if CAN 2 received
    * a message from CAN1. If so it will then read
    * CAN2 Channel 1.
    * Byte 0 of the received message will indicate
    * if the LED5 should be switched ON or OFF. */

    CANRxMessageBuffer * message;

    if(isCAN2MsgReceived == FALSE)
    {
            /* CAN2 did not receive any message
             * so exit the function. Note that the
             * isCAN2MsgReceived flag is updated
             * by the CAN2 ISR. */

            return 0;
    }
    /* Message was received. Reset isCAN2MsgReceived flag
    * to catch the next message. */

    isCAN2MsgReceived = FALSE;

    message = CANGetRxMessage(CAN2,CAN_CHANNEL1);

    /* Call the CANUpdateChannel() function to let
    * the CAN module know that the message processing
    * is done. Enable the event so that the CAN module
    * generates an interrupt when the event occurs.*/


    CANUpdateChannel(CAN2, CAN_CHANNEL1);
    CANEnableChannelEvent(CAN2, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);
    return message;
}
示例#9
0
void CAN1Init(void)
{
    CAN_BIT_CONFIG canBitConfig;

    /* This function will intialize
    * CAN1 module. */

    /* Step 1: Switch the CAN module
    * ON and switch it to Configuration
    * mode. Wait till the switch is
    * complete */

    CANEnableModule(CAN1,TRUE);

    CANSetOperatingMode(CAN1, CAN_CONFIGURATION);
    while(CANGetOperatingMode(CAN1) != CAN_CONFIGURATION);

    /* Step 2: Configure the CAN Module Clock. The
    * CAN_BIT_CONFIG data structure is used
    * for this purpose. The propagation segment,
    * phase segment 1 and phase segment 2
    * are configured to have 3TQ. The
    * CANSetSpeed function sets the baud.*/

    canBitConfig.phaseSeg2Tq            = CAN_BIT_3TQ;
    canBitConfig.phaseSeg1Tq            = CAN_BIT_3TQ;
    canBitConfig.propagationSegTq       = CAN_BIT_3TQ;
    canBitConfig.phaseSeg2TimeSelect    = TRUE;
    canBitConfig.sample3Time            = TRUE;
    canBitConfig.syncJumpWidth          = CAN_BIT_2TQ;

    CANSetSpeed(CAN1,&canBitConfig,SYSTEM_FREQ,CAN_BUS_SPEED);

    /* Step 3: Assign the buffer area to the
    * CAN module.
    */

    CANAssignMemoryBuffer(CAN1,CAN1MessageFifoArea,(2 * 8 * 16));

    /* Step 4: Configure channel 0 for TX and size of
    * 8 message buffers with RTR disabled and low medium
    * priority. Configure channel 1 for RX and size
    * of 8 message buffers and receive the full message.
    */

    CANConfigureChannelForTx(CAN1, CAN_CHANNEL0, 8, CAN_TX_RTR_DISABLED, CAN_LOW_MEDIUM_PRIORITY);
    CANConfigureChannelForRx(CAN1, CAN_CHANNEL1, 8, CAN_RX_FULL_RECEIVE);

    /* Step 5: Configure filters and mask. Configure
    * filter 0 to accept EID messages with ID 0x0.
    * Configure filter mask 0 to compare none of the ID
    * bits and to filter by the ID type specified in
    * the filter configuration. Messages accepted by
    * filter 0 should be stored in channel 1. */

    //CANConfigureFilter      (CAN1, CAN_FILTER0, 0x201, CAN_SID);
    CANConfigureFilter(CAN1, CAN_FILTER0, 0x0, CAN_EID);
    //The following Filter mask allows the program to listen for all CAN_EIDs change 0x0
    //(the third parameter in CANConfigureFilterMask) to compare bits to mask
    CANConfigureFilterMask  (CAN1, CAN_FILTER_MASK0, 0x0, CAN_EID, CAN_FILTER_MASK_IDE_TYPE);
    CANLinkFilterToChannel  (CAN1, CAN_FILTER0, CAN_FILTER_MASK0, CAN_CHANNEL1);
    CANEnableFilter         (CAN1, CAN_FILTER0, TRUE);
    
    /* Step 6: Enable interrupt and events. Enable the receive
    * channel not empty event (channel event) and the receive
    * channel event (module event).
    * The interrrupt peripheral library is used to enable
    * the CAN interrupt to the CPU. */

    CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);
    CANEnableModuleEvent (CAN1, CAN_RX_EVENT, TRUE);

    /* These functions are from interrupt peripheral
    * library. */

    INTSetVectorPriority(INT_CAN_1_VECTOR, INT_PRIORITY_LEVEL_4);
    INTSetVectorSubPriority(INT_CAN_1_VECTOR, INT_SUB_PRIORITY_LEVEL_0);
    INTEnable(INT_CAN1, INT_ENABLED);

    /* Step 7: Switch the CAN mode
     * to normal mode. */

    CANSetOperatingMode(CAN1, CAN_NORMAL_OPERATION);
    while(CANGetOperatingMode(CAN1) != CAN_NORMAL_OPERATION);

}
示例#10
0
//================================================
// Configure the CAN1 interrupt handler
//================================================
void __ISR(_CAN_1_VECTOR, CAN1_INT_PRIORITY) Can1InterruptHandler(void)
{
  // Check if the source of the interrupt is RX_EVENT. This is redundant since
  // only this event is enabled in this example but this shows one scheme for
  // handling events

  if ((CANGetModuleEvent(CAN1) & CAN_RX_EVENT) != 0)
  {
    LED_CAN_TOGGLE;

    CANRxMessageBuffer *message;

    /*
     * CHANNEL 1 = SWITCHES STATES
     */
    if (CANGetPendingEventCode(CAN1) == CAN_CHANNEL1_EVENT)
    {

      CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);

      message = CANGetRxMessage(CAN1, CAN_CHANNEL1);

      CanSwitches_t switches;
      switches.bytes.low  = message->data[0];
      switches.bytes.high = message->data[1];

      if (buttons.buttons.bits.steerWheelSw1  != switches.bits.sw1 )
      {
        buttons.buttons.bits.steerWheelSw1  = switches.bits.sw1;
        buttons.chng.bits.steerWheelSw1     = 1;
      }

      if (buttons.buttons.bits.steerWheelSw4  != switches.bits.sw4 )
      {
        buttons.buttons.bits.steerWheelSw4  = switches.bits.sw4;
        buttons.chng.bits.steerWheelSw4     = 1;
      }

      if (buttons.buttons.bits.steerWheelSw10 != switches.bits.sw10)
      {
        buttons.buttons.bits.steerWheelSw10 = switches.bits.sw10;
        buttons.chng.bits.steerWheelSw10    = 1;
      }

      LED_CAN_TOGGLE;
      CANUpdateChannel(CAN1, CAN_CHANNEL1);
      CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);

    }

    /*
     * CHANNEL 2 = WIND ANGLE
     */
    if (CANGetPendingEventCode(CAN1) == CAN_CHANNEL2_EVENT)
    {

      CANEnableChannelEvent(CAN1, CAN_CHANNEL2, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);

      message = CANGetRxMessage(CAN1, CAN_CHANNEL2);

      memcpy((void *) &rxWindAngle, &message->data[0], 4);
      
      oNewWindAngle = 1;

      CANUpdateChannel(CAN1, CAN_CHANNEL2);
      CANEnableChannelEvent(CAN1, CAN_CHANNEL2, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);
    }
  }

  // The CAN1 Interrupt flag is  cleared at the end of the interrupt routine.
  // This is because the event source that could have caused this interrupt to
  // occur (CAN_RX_CHANNEL_NOT_EMPTY) is disabled. Attempting to clear the
  // CAN1 interrupt flag when the the CAN_RX_CHANNEL_NOT_EMPTY interrupt is
  // enabled will not have any effect because the base event is still present.
  INTClearFlag(INT_CAN1);
}
示例#11
0
/*********************************************************************
 * Function:        void CAN2TCPBridgeTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void CAN2TCPBridgeTask(void)
{
	static enum _BridgeState
	{
		SM_HOME = 0,
		SM_SOCKET_OBTAINED
	} BridgeState = SM_HOME;
	static TCP_SOCKET MySocket = INVALID_SOCKET;
	WORD wMaxPut, wMaxGet, w;
	BYTE *RXHeadPtrShadow, *RXTailPtrShadow;
	BYTE *TXHeadPtrShadow, *TXTailPtrShadow;


	switch(BridgeState)
	{
		case SM_HOME:
			#if defined(USE_REMOTE_TCP_SERVER)
				// Connect a socket to the remote TCP server
				MySocket = TCPOpen((DWORD)USE_REMOTE_TCP_SERVER, TCP_OPEN_ROM_HOST, CAN2TCPBRIDGE_PORT, TCP_PURPOSE_CAN_2_TCP_BRIDGE);
			#else
			MySocket = TCPOpen(0, TCP_OPEN_SERVER, CAN2TCPBRIDGE_PORT, TCP_PURPOSE_CAN_2_TCP_BRIDGE);
			#endif

			
			// Abort operation if no TCP socket of type TCP_PURPOSE_CAN_2_TCP_BRIDGE is available
			// If this ever happens, you need to go add one to TCPIPConfig.h
			if(MySocket == INVALID_SOCKET)
				break;

			// Eat the first TCPWasReset() response so we don't 
			// infinitely create and reset/destroy client mode sockets
			TCPWasReset(MySocket);
			
			// We have a socket now, advance to the next state
			BridgeState = SM_SOCKET_OBTAINED;
			break;

		case SM_SOCKET_OBTAINED:
			// Reset all buffers if the connection was lost
			if(TCPWasReset(MySocket))
			{
				// Optionally discard anything in the CAN FIFOs
				RXHeadPtr = vCANRXFIFO;
				RXTailPtr = vCANRXFIFO;
				TXHeadPtr = vCANTXFIFO;
				TXTailPtr = vCANTXFIFO;
				
				// If we were a client socket, close the socket and attempt to reconnect
				#if defined(USE_REMOTE_TCP_SERVER)
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					BridgeState = SM_HOME;
					break;
				#endif
			}
		
			// Don't do anything if nobody is connected to us
			if(!TCPIsConnected(MySocket))
				break;
			

			// Read FIFO pointers into a local shadow copy.  Some pointers are volatile 
			// (modified in the ISR), so we must do this safely by disabling interrupts
			RXTailPtrShadow = (BYTE*)RXTailPtr;
			TXHeadPtrShadow = (BYTE*)TXHeadPtr;
				

			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);
			CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, FALSE);

			RXHeadPtrShadow = (BYTE*)RXHeadPtr;
			TXTailPtrShadow = (BYTE*)TXTailPtr;
			

			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);		
			if(TXHeadPtrShadow != TXTailPtrShadow)
				CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, TRUE);
			//
			// Transmit pending data that has been placed into the CAN RX FIFO (in the ISR)
			//
			wMaxPut = TCPIsPutReady(MySocket);	// Get TCP TX FIFO space
			wMaxGet = RXHeadPtrShadow - RXTailPtrShadow;	// Get CAN RX FIFO byte count
			if(RXHeadPtrShadow < RXTailPtrShadow)
				wMaxGet += sizeof(vCANRXFIFO);
			if(wMaxPut > wMaxGet)				// Calculate the lesser of the two
				wMaxPut = wMaxGet;
			if(wMaxPut)							// See if we can transfer anything
			{
				// Transfer the data over.  Note that a two part put 
				// may be needed if the data spans the vCANRXFIFO 
				// end to start address.
				w = vCANRXFIFO + sizeof(vCANRXFIFO) - RXTailPtrShadow;
				if(wMaxPut >= w)
				{
					TCPPutArray(MySocket, RXTailPtrShadow, w);
					RXTailPtrShadow = vCANRXFIFO;
					wMaxPut -= w;
				}
				TCPPutArray(MySocket, RXTailPtrShadow, wMaxPut);
				RXTailPtrShadow += wMaxPut;

				// No flush.  The stack will automatically flush and do 
				// transmit coallescing to minimize the number of TCP 
				// packets that get sent.  If you explicitly call TCPFlush()
				// here, latency will go down, but so will max throughput 
				// and bandwidth efficiency.
			
			}

			//
			// Transfer received TCP data into the CAN TX FIFO for future transmission (in the ISR)
			//
			wMaxGet = TCPIsGetReady(MySocket);	// Get TCP RX FIFO byte count
			wMaxPut = TXTailPtrShadow - TXHeadPtrShadow - 1;// Get CAN TX FIFO free space
			if(TXHeadPtrShadow >= TXTailPtrShadow)
				wMaxPut += sizeof(vCANTXFIFO);
			if(wMaxPut > wMaxGet)				// Calculate the lesser of the two
				wMaxPut = wMaxGet;
			if(wMaxPut)							// See if we can transfer anything
			{
				// Transfer the data over.  Note that a two part put 
				// may be needed if the data spans the vCANTXFIFO 
				// end to start address.
				w = vCANTXFIFO + sizeof(vCANTXFIFO) - TXHeadPtrShadow;
				if(wMaxPut >= w)
				{
					TCPGetArray(MySocket, TXHeadPtrShadow, w);
					TXHeadPtrShadow = vCANTXFIFO;
					wMaxPut -= w;
				}
				TCPGetArray(MySocket, TXHeadPtrShadow, wMaxPut);
				TXHeadPtrShadow += wMaxPut;
			}
			
			// Write local shadowed FIFO pointers into the volatile FIFO pointers.
			
			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, FALSE);
			CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, FALSE);
			
			RXTailPtr = (volatile BYTE*)RXTailPtrShadow;
			TXHeadPtr = (volatile BYTE*)TXHeadPtrShadow;
			
			CANEnableChannelEvent(CAN1, CAN_CHANNEL1, CAN_RX_CHANNEL_NOT_EMPTY, TRUE);
			if(TXHeadPtrShadow != TXTailPtrShadow)
				CANEnableChannelEvent(CAN1, CAN_CHANNEL0, CAN_TX_CHANNEL_ANY_EVENT, TRUE);

			break;
	}
}