📄 protocol.c
字号:
vUart_StartTx(); #endif /* Update Rx counts */ u16RxAckCount++; /* Did we ask to send data ? */ if (eState == PR_STATE_ENQ) { /* Go to transmit state */ vProtocol_State(PR_STATE_TX); /* Transmit data packet */ vProtocol_Packet_Tx(&sPacketData); } /* Did we send data ? */ else if (eState == PR_STATE_TX) { /* Are we going to wait for the other end to send something ? */ if (bWait) { /* Go to wait state */ vProtocol_State(PR_STATE_WAIT); /* We've done our waiting */ bWait = FALSE; } else { /* Go to idle state */ vProtocol_State(PR_STATE_IDLE); } /* Reset packet */ vProtocol_Packet_Reset(&sPacketData); /* Just sent data so yield next time there is a clash */ bYield = TRUE; } } /* Nack ? */ else if (pu8Data[0] == CHAR_NACK) { #if PR_DEBUG vSerialQ_AddItem(TX_QUEUE, '\r'); vUart_StartTx(); #endif /* Update Rx counts */ u16RxAckCount++; /* Were we trying to send data ? */ if (eState == PR_STATE_ENQ) { /* Go to wait state */ vProtocol_State(PR_STATE_WAIT); } /* Were we trying to send data ? */ else if (eState == PR_STATE_TX) { /* Go to wait state */ vProtocol_State(PR_STATE_WAIT); /* Just sent data so yield next time there is a clash */ bYield = TRUE; } } /* Data ? */ else if (pu8Data[0] == CHAR_STX) { #if PR_DEBUG vSerialQ_AddItem(TX_QUEUE, ' '); vSerialQ_AddHex(TX_QUEUE, pu8Data[1], 2); vSerialQ_AddItem(TX_QUEUE, '\r'); #endif /* Update Rx counts */ u16RxStxCount++; /* Are we in receive state ? */ if (eState == PR_STATE_RX) { /* Go to idle state */ vProtocol_State(PR_STATE_IDLE); /* New unreceived packet ? */ if (bProtocol_RxSequence(pu8Data[1])) { /* Have we got space in the UART transmit buffer for the packet ? */ if (u16SerialQ_Free(TX_QUEUE) >= u16Length) { /* Copy frame data to serial buffer for output on UART */ for (i = 2; i < u16Length; i++) { /* Add item to Tx queue */ vSerialQ_AddItem(TX_QUEUE, pu8Data[i]); u16RxCount++; } #if PR_DEBUG vSerialQ_AddItem(TX_QUEUE, '\r'); #endif /* Start the tx process if it has stalled */ vUart_StartTx(); /* Transmit acknowledgement */ vProtocol_Packet_Ctrl(CHAR_ACK); } /* No room ? */ else { /* Transmit nack */ vProtocol_Packet_Ctrl(CHAR_NACK); } } /* Already received this frame ? */ else { /* Acknowledge it so it shouldn't be sent again */ vProtocol_Packet_Ctrl(CHAR_ACK); } /* Just received data don't yield next time there is a clash */ bYield = FALSE; } }}/**************************************************************************** * * NAME: Public internal data access functions * * DESCRIPTION: * * PARAMETERS: Name RW Usage * None. * * RETURNS: * None. * * NOTES: * None. ****************************************************************************/PUBLIC uint16 u16Protocol_GetRxCount(void) /**< Gets received data count */ {return u16RxCount;}PUBLIC uint16 u16Protocol_GetTxCount(void) /**< Gets transmitted data count */ {return u16TxCount;}PUBLIC uint16 u16Protocol_GetRxAckCount(void) /**< Gets received ack and nack count */ {return u16RxAckCount;}PUBLIC uint16 u16Protocol_GetTxAckCount(void) /**< Gets transmitted ack and nak count */ {return u16TxAckCount;}PUBLIC uint16 u16Protocol_GetRxStxCount(void) /**< Gets received stx count */ {return u16RxStxCount;}PUBLIC uint16 u16Protocol_GetTxStxCount(void) /**< Gets transmitted stx count */ {return u16TxStxCount;}PUBLIC uint16 u16Protocol_GetRxEnqCount(void) /**< Gets received enq count */ {return u16RxEnqCount;}PUBLIC uint16 u16Protocol_GetTxEnqCount(void) /**< Gets transmitted enq count */ {return u16TxEnqCount;}PUBLIC uint16 u16Protocol_GetClEnqCount(void) /**< Gets conflicting enq count */ {return u16ClEnqCount;}/**************************************************************************** * * NAME: vProtocol_State *//*! *\DESCRIPTION Set new state and restart timer. *//* PARAMETERS: Name RW Usage * None. * * RETURNS: * None. * * NOTES: * None. ****************************************************************************/PRIVATE void vProtocol_State(tePrState eNewState) /**< New protocol state */{ eState = eNewState; u8Timer = 0;}/**************************************************************************** * * NAME: bProtocol_RxSequence *//*! *\DESCRIPTION Checks received sequence number to check for new packets. * * If the received sequence is in the half of the sequence range ahead of * the value we were expecting treat the packet as new, otherwise treat the * packet as already received. *//* PARAMETERS: Name RW Usage * None. * * RETURNS: * None. * * NOTES: * None. ****************************************************************************/PRIVATE bool_t bProtocol_RxSequence(uint8 u8Sequence) /**< Received sequence */{ bool_t bNewSequence = FALSE; uint8 u8NewSequence; /* Calculate our expected sequence plus half the sequence range */ u8NewSequence = u8RxSequence + 128; /* Is our range not wrapped around ? */ if (u8NewSequence >= u8RxSequence) { /* Is the sequence we are testing within the acceptable range ? */ if (u8Sequence >= u8RxSequence && u8Sequence <= u8NewSequence) bNewSequence = TRUE; } /* Range is wrapped around */ else { /* Is the sequence we are testing within the acceptable range ? */ if (u8Sequence >= u8RxSequence || u8Sequence <= u8NewSequence) bNewSequence = TRUE; } /* If sequence is a new one update our next expected sequence */ if (bNewSequence) u8RxSequence = u8Sequence + 1; /** \retval TRUE packet is new \retval FALSE packet is old */ return bNewSequence;}/**************************************************************************** * * NAME vProtocol_Packet_Reset *//*! *\DESCRIPTION Reset packet to contain no data *//* PARAMETERS Name RW Usage * None. * * RETURNS * None. * * NOTES * None. ****************************************************************************/PRIVATE void vProtocol_Packet_Reset(tsPrPacket *psPacket) /**< Packet to reset */{ /* Zero length to reset the packet */ psPacket->u16Length = 0;}/**************************************************************************** * * NAME vProtocol_Packet_Tx *//*! *\DESCRIPTION Transmit data packet *//* PARAMETERS Name RW Usage * None. * * RETURNS * None. * * NOTES * None. ****************************************************************************/PRIVATE void vProtocol_Packet_Tx(tsPrPacket *psPacket) /**< Packet to transmit */{ #if PR_DEBUG /* Debug */ vSerialQ_AddString(TX_QUEUE, aszAddr[bCoord]); vSerialQ_AddItem(TX_QUEUE, ' '); vSerialQ_AddString(TX_QUEUE, aszCtrl[psPacket->au8Data[0]]); if (psPacket->au8Data[0] == CHAR_ENQ || psPacket->au8Data[0] == CHAR_STX) { vSerialQ_AddItem(TX_QUEUE, ' '); vSerialQ_AddHex(TX_QUEUE, psPacket->au8Data[1], 2); if (psPacket->au8Data[0] == CHAR_STX) { uint16 i; vSerialQ_AddItem(TX_QUEUE, '\r'); for (i=2; i<psPacket->u16Length; i++) vSerialQ_AddItem(TX_QUEUE, psPacket->au8Data[i]); } } vSerialQ_AddItem(TX_QUEUE, '\r'); vUart_StartTx(); #endif /* If source service is bound */ if (bNetwork_Source_Bound(1)) { /* Get radio to transmit data */ (void) eNetwork_Source_Tx(1, psPacket->u16Length, psPacket->au8Data); /* Network debugging */ #if NETWORK_DEBUG if (bNetwork_UartUp() && psPacket->au8Data[0] == (uint8) CHAR_STX) { if (bNetwork_IsString(psPacket->u16Length, &psPacket->au8Data[2])) { /* Debug with data */ vPrintf("vProtocol_Packet_Tx(%d, \"%s\")\n", psPacket->u16Length, (char *) &psPacket->au8Data[2]); } else { /* Debug without data */ vPrintf("vProtocol_Packet_Tx(%d,)\n", psPacket->u16Length); } } #endif } /* Update counters */ switch (psPacket->au8Data[0]) { case CHAR_STX: u16TxStxCount++; break; case CHAR_ENQ: u16TxEnqCount++; break; case CHAR_ACK: case CHAR_NACK: u16TxAckCount++; break; }}/**************************************************************************** * * NAME: vProtocol_Packet_Data *//*! *\DESCRIPTION Populate data packet with from UART receive queue. * * If the data packet is empty and there is data in the UART's receive queue * transfer the lot of data from the UART receive queue into the data packet * ready for transmission. *//* PARAMETERS: Name RW Usage * None. * * RETURNS: * None. * * NOTES: * None. ****************************************************************************/PRIVATE void vProtocol_Packet_Data(void){ /* Don't already have data in the packet ? */ if (sPacketData.u16Length == 0) { /* Something in the receive serial queue ? */ if (!bSerialQ_Empty(RX_QUEUE)) { /* Put in STX character so we know its data */ sPacketData.au8Data[sPacketData.u16Length++] = (uint8) CHAR_STX; /* Put in sequence counter */ sPacketData.au8Data[sPacketData.u16Length++] = u8TxSequence++; /* Add data until we run out or have filled our frame */ while ((!bSerialQ_Empty(RX_QUEUE)) && (sPacketData.u16Length < MAX_DATA_PER_FRAME)) { /* Set payload data */ sPacketData.au8Data[sPacketData.u16Length++] = u8SerialQ_RemoveItem(RX_QUEUE); u16TxCount++; } #if NETWORK_DEBUG /* Add a sneaky terminator if debugging */ sPacketData.au8Data[sPacketData.u16Length] = '\0'; #endif } }}/**************************************************************************** * * NAME: vProtocol_Packet_Ctrl *//*! *\DESCRIPTION Populate control packet and transmit it. * *//* PARAMETERS: Name RW Usage * None. * * RETURNS: * None. * * NOTES: * None. ****************************************************************************/PRIVATE void vProtocol_Packet_Ctrl(char cType) /**< Contorl code to send */{ /* Zero length prior to building packet */ sPacketCtrl.u16Length = 0; /* Set up new control character for sending - its new so we don't care if the previous one made it out or not */ sPacketCtrl.au8Data[sPacketCtrl.u16Length++] = (uint8) cType; /* If enquiry - add our current yield state */ if (cType == CHAR_ENQ) sPacketCtrl.au8Data[sPacketCtrl.u16Length++] = (uint8) bYield; /* Transmit the packet */ vProtocol_Packet_Tx(&sPacketCtrl);}/****************************************************************************//*** END OF FILE ***//****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -