1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-19 09:54:15 +01:00

NACKs implemented on both ground and flight side, connect time goes under a few seconds now.

This commit is contained in:
elafargue 2011-04-30 19:32:42 +02:00
parent 1c6d760371
commit 6b00ed3866
3 changed files with 78 additions and 14 deletions

View File

@ -33,12 +33,13 @@
// Private constants
#define SYNC_VAL 0x3C
#define TYPE_MASK 0xFC
#define TYPE_MASK 0xF8
#define TYPE_VER 0x20
#define TYPE_OBJ (TYPE_VER | 0x00)
#define TYPE_OBJ_REQ (TYPE_VER | 0x01)
#define TYPE_OBJ_ACK (TYPE_VER | 0x02)
#define TYPE_ACK (TYPE_VER | 0x03)
#define TYPE_NACK (TYPE_VER | 0x04)
#define MIN_HEADER_LENGTH 8 // sync(1), type (1), size (2), object ID (4)
#define MAX_HEADER_LENGTH 10 // sync(1), type (1), size (2), object ID (4), instance ID (2, not used in single objects)
@ -89,7 +90,8 @@ static uint8_t updateCRC(uint8_t crc, const uint8_t* data, int32_t length);
static int32_t objectTransaction(UAVObjHandle objectId, uint16_t instId, uint8_t type, int32_t timeout);
static int32_t sendObject(UAVObjHandle obj, uint16_t instId, uint8_t type);
static int32_t sendSingleObject(UAVObjHandle obj, uint16_t instId, uint8_t type);
static int32_t receiveObject(uint8_t type, UAVObjHandle obj, uint16_t instId, uint8_t* data, int32_t length);
static int32_t sendNack(uint32_t objId);
static int32_t receiveObject(uint8_t type, uint32_t objId, uint16_t instId, uint8_t* data, int32_t length);
static void updateAck(UAVObjHandle obj, uint16_t instId);
/**
@ -328,9 +330,11 @@ int32_t UAVTalkProcessInputStream(uint8_t rxbyte)
break;
// Search for object, if not found reset state machine
// except if we got a OBJ_REQ for an object which does not
// exist, in which case we'll send a NACK
obj = UAVObjGetByID(objId);
if (obj == 0)
if (obj == 0 && type != TYPE_OBJ_REQ)
{
stats.rxErrors++;
state = STATE_SYNC;
@ -338,7 +342,7 @@ int32_t UAVTalkProcessInputStream(uint8_t rxbyte)
}
// Determine data length
if (type == TYPE_OBJ_REQ || type == TYPE_ACK)
if (type == TYPE_OBJ_REQ || type == TYPE_ACK || type == TYPE_NACK)
length = 0;
else
length = UAVObjGetNumBytes(obj);
@ -360,8 +364,15 @@ int32_t UAVTalkProcessInputStream(uint8_t rxbyte)
}
instId = 0;
if (obj == 0)
{
// If this is a NACK, we skip to Checksum
state = STATE_CS;
rxCount = 0;
}
// Check if this is a single instance object (i.e. if the instance ID field is coming next)
if (UAVObjIsSingleInstance(obj))
else if (UAVObjIsSingleInstance(obj))
{
// If there is a payload get it, otherwise receive checksum
if (length > 0)
@ -432,7 +443,7 @@ int32_t UAVTalkProcessInputStream(uint8_t rxbyte)
}
xSemaphoreTakeRecursive(lock, portMAX_DELAY);
receiveObject(type, obj, instId, rxBuffer, length);
receiveObject(type, objId, instId, rxBuffer, length);
stats.rxObjectBytes += length;
stats.rxObjects++;
xSemaphoreGiveRecursive(lock);
@ -451,17 +462,22 @@ int32_t UAVTalkProcessInputStream(uint8_t rxbyte)
/**
* Receive an object. This function process objects received through the telemetry stream.
* \param[in] type Type of received message (TYPE_OBJ, TYPE_OBJ_REQ, TYPE_OBJ_ACK, TYPE_ACK)
* \param[in] obj Handle of the received object
* \param[in] type Type of received message (TYPE_OBJ, TYPE_OBJ_REQ, TYPE_OBJ_ACK, TYPE_ACK, TYPE_NACK)
* \param[in] objId ID of the object to work on
* \param[in] instId The instance ID of UAVOBJ_ALL_INSTANCES for all instances.
* \param[in] data Data buffer
* \param[in] length Buffer length
* \return 0 Success
* \return -1 Failure
*/
static int32_t receiveObject(uint8_t type, UAVObjHandle obj, uint16_t instId, uint8_t* data, int32_t length)
static int32_t receiveObject(uint8_t type, uint32_t objId, uint16_t instId, uint8_t* data, int32_t length)
{
static UAVObjHandle obj;
int32_t ret = 0;
// Get the handle to the Object. Will be zero
// if object does not exist.
obj = UAVObjGetByID(objId);
// Process message type
switch (type) {
@ -501,7 +517,13 @@ static int32_t receiveObject(uint8_t type, UAVObjHandle obj, uint16_t instId, ui
break;
case TYPE_OBJ_REQ:
// Send requested object if message is of type OBJ_REQ
sendObject(obj, instId, TYPE_OBJ);
if (obj == 0)
sendNack(objId);
else
sendObject(obj, instId, TYPE_OBJ);
break;
case TYPE_NACK:
// Do nothing on flight side, let it time out.
break;
case TYPE_ACK:
// All instances, not allowed for ACK messages
@ -673,6 +695,44 @@ static int32_t sendSingleObject(UAVObjHandle obj, uint16_t instId, uint8_t type)
return 0;
}
/**
* Send a NACK through the telemetry link.
* \param[in] objId Object ID to send a NACK for
* \return 0 Success
* \return -1 Failure
*/
static int32_t sendNack(uint32_t objId)
{
int32_t dataOffset;
txBuffer[0] = SYNC_VAL; // sync byte
txBuffer[1] = TYPE_NACK;
// data length inserted here below
txBuffer[4] = (uint8_t)(objId & 0xFF);
txBuffer[5] = (uint8_t)((objId >> 8) & 0xFF);
txBuffer[6] = (uint8_t)((objId >> 16) & 0xFF);
txBuffer[7] = (uint8_t)((objId >> 24) & 0xFF);
dataOffset = 8;
// Store the packet length
txBuffer[2] = (uint8_t)((dataOffset) & 0xFF);
txBuffer[3] = (uint8_t)(((dataOffset) >> 8) & 0xFF);
// Calculate checksum
txBuffer[dataOffset] = updateCRC(0, txBuffer, dataOffset);
// Send buffer
if (outStream!=NULL) (*outStream)(txBuffer, dataOffset+CHECKSUM_LENGTH);
// Update stats
stats.txBytes += dataOffset+CHECKSUM_LENGTH;
// Done
return 0;
}
/**
* Update the crc value with new data.
*

View File

@ -655,18 +655,22 @@ bool UAVTalk::transmitObject(UAVObject* obj, quint8 type, bool allInstances)
*/
bool UAVTalk::transmitNack(quint32 objId)
{
int dataOffset = 8;
txBuffer[0] = SYNC_VAL;
txBuffer[1] = TYPE_NACK;
qToLittleEndian<quint16>(0x0, &txBuffer[2]); // Length
qToLittleEndian<quint32>(objId, &txBuffer[4]);
// Calculate checksum
txBuffer[8] = updateCRC(0, txBuffer, 8);
txBuffer[dataOffset] = updateCRC(0, txBuffer, dataOffset);
qToLittleEndian<quint16>(dataOffset, &txBuffer[2]);
// Send buffer, check that the transmit backlog does not grow above limit
if ( io->bytesToWrite() < TX_BUFFER_SIZE )
{
io->write((const char*)txBuffer, 8+CHECKSUM_LENGTH);
io->write((const char*)txBuffer, dataOffset+CHECKSUM_LENGTH);
}
else
{

View File

@ -66,7 +66,7 @@ private slots:
private:
// Constants
static const int TYPE_MASK = 0xFC;
static const int TYPE_MASK = 0xF8;
static const int TYPE_VER = 0x20;
static const int TYPE_OBJ = (TYPE_VER | 0x00);
static const int TYPE_OBJ_REQ = (TYPE_VER | 0x01);