1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-20 10:54:14 +01:00

Merge remote-tracking branch 'revo/brian/rfm22_rf2' into revo

Conflicts:
	flight/PiOS/Common/pios_rfm22b.c
This commit is contained in:
James Cotton 2012-10-05 08:20:35 -05:00
commit 2191befe17
9 changed files with 148 additions and 196 deletions

View File

@ -60,8 +60,7 @@ typedef struct {
uint32_t source_id;
uint8_t type;
uint8_t data_size;
uint8_t tx_seq;
uint8_t rx_seq;
uint16_t seq_num;
} PHPacketHeader;
#define PH_MAX_DATA (PIOS_PH_MAX_PACKET - sizeof(PHPacketHeader) - RS_ECC_NPARITY)
@ -116,8 +115,7 @@ PHPacketHandle PHGetTXPacket(PHInstHandle h);
void PHReleaseTXPacket(PHInstHandle h, PHPacketHandle p);
uint8_t PHTransmitPacket(PHInstHandle h, PHPacketHandle p);
uint8_t PHTransmitData(PHInstHandle h, uint8_t *buf, uint16_t len);
int32_t PHVerifyPacket(PHInstHandle h, PHPacketHandle p, uint16_t received_len);
uint8_t PHReceivePacket(PHInstHandle h, PHPacketHandle p, bool rx_error);
uint8_t PHReceivePacket(PHInstHandle h, PHPacketHandle p);
#endif // __PACKET_HANDLER_H__

View File

@ -43,7 +43,6 @@ typedef struct {
PHPacket *rx_packets;
uint8_t rx_win_start;
uint8_t rx_win_end;
uint16_t tx_seq_id;
xSemaphoreHandle lock;
PHOutputStream output_stream;
PHDataHandler data_handler;
@ -52,8 +51,6 @@ typedef struct {
} PHPacketData, *PHPacketDataHandle;
// Private functions
static uint8_t PHLSendAck(PHPacketDataHandle data, PHPacketHandle p);
static uint8_t PHLSendNAck(PHPacketDataHandle data, PHPacketHandle p);
static uint8_t PHLTransmitPacket(PHPacketDataHandle data, PHPacketHandle p);
/**
@ -71,7 +68,6 @@ PHInstHandle PHInitialize(PacketHandlerConfig *cfg)
if (!data)
return 0;
data->cfg = *cfg;
data->tx_seq_id = 0;
// Allocate the packet windows
data->tx_packets = pvPortMalloc(sizeof(PHPacket) * data->cfg.win_size);
@ -318,40 +314,6 @@ uint8_t PHTransmitData(PHInstHandle h, uint8_t *buf, uint16_t len)
return PHLTransmitPacket(data, p);
}
/**
* Verify that a buffer contains a valid packet.
* \param[in] h The packet handler instance data pointer.
* \param[in] p A pointer to the packet buffer.
* \param[in] received_len The length of data received.
* \return < 0 Failure
* \return > 0 Number of bytes consumed.
*/
int32_t PHVerifyPacket(PHInstHandle h, PHPacketHandle p, uint16_t received_len)
{
// Verify the packet length.
// Note: The last two bytes should be the RSSI and AFC.
uint16_t len = PHPacketSizeECC(p);
if (received_len < (len + 2))
{
DEBUG_PRINTF(1, "Packet length error %d %d\n\r", received_len, len + 2);
return -1;
}
// Attempt to correct any errors in the packet.
decode_data((unsigned char*)p, len);
// Check that there were no unfixed errors.
bool rx_error = check_syndrome() != 0;
if(rx_error)
{
DEBUG_PRINTF(1, "Error in packet\n\r");
return -2;
}
return len + 2;
}
/**
* Process a packet that has been received.
* \param[in] h The packet handler instance data pointer.
@ -360,7 +322,7 @@ int32_t PHVerifyPacket(PHInstHandle h, PHPacketHandle p, uint16_t received_len)
* \return 0 Failure
* \return 1 Success
*/
uint8_t PHReceivePacket(PHInstHandle h, PHPacketHandle p, bool rx_error)
uint8_t PHReceivePacket(PHInstHandle h, PHPacketHandle p)
{
PHPacketDataHandle data = (PHPacketDataHandle)h;
uint16_t len = PHPacketSizeECC(p);
@ -373,81 +335,23 @@ uint8_t PHReceivePacket(PHInstHandle h, PHPacketHandle p, bool rx_error)
case PACKET_TYPE_STATUS:
if (!rx_error)
// Pass on the channels to the status handler.
if(data->status_handler)
data->status_handler((PHStatusPacketHandle)p, rssi, afc);
// Pass on the channels to the status handler.
if(data->status_handler)
data->status_handler((PHStatusPacketHandle)p, rssi, afc);
break;
case PACKET_TYPE_ACKED_DATA:
// Send the ACK / NACK
if (rx_error)
{
DEBUG_PRINTF(1, "Sending NACK\n\r");
PHLSendNAck(data, p);
}
else
{
PHLSendAck(data, p);
// Pass on the data.
if(data->data_handler)
data->data_handler(p->data, p->header.data_size, rssi, afc);
}
break;
case PACKET_TYPE_ACK:
{
// Find the packet ID in the TX buffer, and free it.
unsigned int i = 0;
for (unsigned int i = 0; i < data->cfg.win_size; ++i)
if (data->tx_packets[i].header.tx_seq == p->header.rx_seq)
PHReleaseTXPacket(h, data->tx_packets + i);
#ifdef DEBUG_LEVEL
if (i == data->cfg.win_size)
DEBUG_PRINTF(1, "Error finding acked packet to release\n\r");
#endif
}
break;
case PACKET_TYPE_NACK:
{
// Resend the packet.
unsigned int i = 0;
for ( ; i < data->cfg.win_size; ++i)
if (data->tx_packets[i].header.tx_seq == p->header.rx_seq)
PHLTransmitPacket(data, data->tx_packets + i);
#ifdef DEBUG_LEVEL
if (i == data->cfg.win_size)
DEBUG_PRINTF(1, "Error finding acked packet to NACK\n\r");
DEBUG_PRINTF(1, "Resending after NACK\n\r");
#endif
}
break;
case PACKET_TYPE_PPM:
if (!rx_error)
// Pass on the channels to the PPM handler.
if(data->ppm_handler)
data->ppm_handler(((PHPpmPacketHandle)p)->channels);
// Pass on the channels to the PPM handler.
if(data->ppm_handler)
data->ppm_handler(((PHPpmPacketHandle)p)->channels);
break;
case PACKET_TYPE_DATA:
if (!rx_error)
// Pass on the data to the data handler.
if(data->data_handler)
data->data_handler(p->data, p->header.data_size, rssi, afc);
// Pass on the data to the data handler.
if(data->data_handler)
data->data_handler(p->data, p->header.data_size, rssi, afc);
break;
default:
@ -473,58 +377,9 @@ static uint8_t PHLTransmitPacket(PHPacketDataHandle data, PHPacketHandle p)
if(!data->output_stream)
return 0;
// Set the sequence ID to the current ID.
p->header.tx_seq = data->tx_seq_id++;
p->header.source_id = data->cfg.source_id;
// Add the error correcting code.
encode_data((unsigned char*)p, PHPacketSize(p), (unsigned char*)p);
// Transmit the packet using the output stream.
if(data->output_stream(p) == -1)
return 0;
return 1;
}
/**
* Send an ACK packet.
* \param[in] data The packet handler instance data pointer.
* \param[in] p A pointer to the packet buffer of the packet to be ACKed.
* \return 1 Success
* \return 0 Failure
*/
static uint8_t PHLSendAck(PHPacketDataHandle data, PHPacketHandle p)
{
// Create the ACK message
PHPacketHeader ack;
ack.destination_id = p->header.source_id;
ack.type = PACKET_TYPE_ACK;
ack.rx_seq = p->header.tx_seq;
ack.data_size = 0;
// Send the packet.
return PHLTransmitPacket(data, (PHPacketHandle)&ack);
}
/**
* Send an NAck packet.
* \param[in] data The packet handler instance data pointer.
* \param[in] p A pointer to the packet buffer of the packet to be ACKed.
* \return 1 Success
* \return 0 Failure
*/
static uint8_t PHLSendNAck(PHPacketDataHandle data, PHPacketHandle p)
{
// Create the NAck message
PHPacketHeader ack;
ack.destination_id = p->header.source_id;
ack.type = PACKET_TYPE_NACK;
ack.rx_seq = p->header.tx_seq;
ack.data_size = 0;
// Set the packet.
return PHLTransmitPacket(data, (PHPacketHandle)&ack);
}

View File

@ -83,7 +83,6 @@ typedef struct {
// Error statistics.
uint32_t radioTxErrors;
uint32_t radioRxErrors;
uint32_t packetErrors;
uint16_t txBytes;
uint16_t rxBytes;
@ -262,7 +261,6 @@ static int32_t RadioInitialize(void)
// Initialize the statistics.
data->radioTxErrors = 0;
data->radioRxErrors = 0;
data->packetErrors = 0;
data->droppedPackets = 0;
data->comTxRetries = 0;
data->UAVTalkErrors = 0;
@ -315,12 +313,7 @@ static void radioReceiveTask(void *parameters)
if(rx_bytes == 0)
continue;
data->rxBytes += rx_bytes;
// Verify that the packet is valid and pass it on.
bool rx_error = PHVerifyPacket(pios_packet_handler, p, rx_bytes) < 0;
if(rx_error)
data->packetErrors++;
PHReceivePacket(pios_packet_handler, p, rx_error);
PHReceivePacket(pios_packet_handler, p);
p = NULL;
}
}
@ -416,7 +409,7 @@ static void radioStatusTask(void *parameters)
// Update the status
pipxStatus.DeviceID = PIOS_RFM22B_DeviceID(pios_rfm22b_id);
pipxStatus.Retries = data->comTxRetries;
pipxStatus.Errors = data->packetErrors;
pipxStatus.LinkQuality = PIOS_RFM22B_LinkQuality(pios_rfm22b_id);
pipxStatus.UAVTalkErrors = data->UAVTalkErrors;
pipxStatus.Dropped = data->droppedPackets;
pipxStatus.Resets = PIOS_RFM22B_Resets(pios_rfm22b_id);
@ -425,7 +418,7 @@ static void radioStatusTask(void *parameters)
pipxStatus.RXRate = (uint16_t)((float)(data->rxBytes * 1000) / STATS_UPDATE_PERIOD_MS);
data->rxBytes = 0;
pipxStatus.LinkState = PIPXSTATUS_LINKSTATE_DISCONNECTED;
pipxStatus.RSSI = data->RSSI;
pipxStatus.RSSI = PIOS_RFM22B_LinkQuality(pios_rfm22b_id);
LINK_LED_OFF;
// Update the potential pairing contacts
@ -450,7 +443,6 @@ static void radioStatusTask(void *parameters)
if(pairID && (data->pairStats[i].pairID == pairID) && (data->pairStats[i].rssi > -127))
{
pipxStatus.Retries += data->pairStats[i].retries;
pipxStatus.Errors += data->pairStats[i].errors;
pipxStatus.UAVTalkErrors += data->pairStats[i].uavtalk_errors;
pipxStatus.Dropped += data->pairStats[i].dropped;
pipxStatus.Resets += data->pairStats[i].resets;

View File

@ -548,7 +548,7 @@ static void UAVTalkSendTask(void *parameters)
else if(ev.event == EV_PACKET_RECEIVED)
{
// Receive the packet.
PHReceivePacket(pios_packet_handler, (PHPacketHandle)ev.obj, false);
PHReceivePacket(pios_packet_handler, (PHPacketHandle)ev.obj);
}
else if(ev.event == EV_TRANSMIT_PACKET)
{

View File

@ -71,7 +71,7 @@
#define RADIOSTATS_UPDATE_PERIOD_MS 250
// this is too adjust the RF module so that it is on frequency
#define OSC_LOAD_CAP 0x7F // cap = 12.5pf .. default
#define OSC_LOAD_CAP 0x7F // cap = 12.5pf .. default
#define OSC_LOAD_CAP_1 0x7D // board 1
#define OSC_LOAD_CAP_2 0x7B // board 2
#define OSC_LOAD_CAP_3 0x7E // board 3
@ -206,10 +206,26 @@ struct pios_rfm22b_dev {
// ezmac status register
uint8_t ezmac_status;
// The packet transmission counts
uint32_t tx_packet_count;
uint32_t rx_packet_count;
// The dropped packet counters
uint8_t slow_block;
uint8_t fast_block;
uint8_t slow_good_packets;
uint8_t fast_good_packets;
uint8_t slow_corrected_packets;
uint8_t fast_corrected_packets;
uint8_t slow_error_packets;
uint8_t fast_error_packets;
uint8_t slow_link_quality;
uint8_t fast_link_quality;
// Stats
uint16_t resets;
uint32_t errors;
uint32_t irqs_processed;
uint16_t timeouts;
uint16_t errors;
// the current RSSI (register value)
uint8_t rssi;
// RSSI in dBm
@ -557,10 +573,24 @@ int32_t PIOS_RFM22B_Init(uint32_t *rfm22b_id, uint32_t spi_id, uint32_t slave_nu
rfm22b_dev->int_status2 = 0;
rfm22b_dev->ezmac_status = 0;
// Initlize the link stats.
rfm22b_dev->slow_block = 0;
rfm22b_dev->fast_block = 0;
rfm22b_dev->slow_good_packets = 0;
rfm22b_dev->fast_good_packets = 0;
rfm22b_dev->slow_corrected_packets = 0;
rfm22b_dev->fast_corrected_packets = 0;
rfm22b_dev->slow_error_packets = 0;
rfm22b_dev->fast_error_packets = 0;
rfm22b_dev->slow_link_quality = 255;
rfm22b_dev->fast_link_quality = 255;
// Initialize the stats.
rfm22b_dev->resets = 0;
rfm22b_dev->timeouts = 0;
rfm22b_dev->errors = 0;
rfm22b_dev->irqs_processed = 0;
rfm22b_dev->tx_packet_count = 0;
rfm22b_dev->rx_packet_count = 0;
rfm22b_dev->rssi = 0;
rfm22b_dev->rssi_dBm = -127;
@ -696,13 +726,38 @@ void PIOS_RFM22B_SetDestinationId(uint32_t rfm22b_id, uint32_t dest_id)
rfm22b_dev->destination_id = (dest_id == 0) ? 0xffffffff : dest_id;
}
int16_t PIOS_RFM22B_Resets(uint32_t rfm22b_id)
uint16_t PIOS_RFM22B_Resets(uint32_t rfm22b_id)
{
struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id;
if(!PIOS_RFM22B_validate(rfm22b_dev))
return 0;
return rfm22b_dev->resets;
}
uint16_t PIOS_RFM22B_Timeouts(uint32_t rfm22b_id)
{
struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id;
if(!PIOS_RFM22B_validate(rfm22b_dev))
return 0;
return rfm22b_dev->timeouts;
}
uint8_t PIOS_RFM22B_LinkQuality(uint32_t rfm22b_id)
{
struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id;
if(!PIOS_RFM22B_validate(rfm22b_dev))
return 0;
return rfm22b_dev->slow_link_quality;
}
int8_t PIOS_RFM22B_RSSI(uint32_t rfm22b_id)
{
struct pios_rfm22b_dev *rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id;
if(!PIOS_RFM22B_validate(rfm22b_dev))
return 0;
return rfm22b_dev->rssi_dBm;
}
static void PIOS_RFM22B_RxStart(uint32_t rfm22b_id, uint16_t rx_bytes_avail)
{
struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id;
@ -741,11 +796,11 @@ bool PIOS_RFM22B_Send_Packet(uint32_t rfm22b_id, PHPacketHandle p, uint32_t max_
/**
* Receive a packet from the radio.
* \param[in] rfm22b_id The rfm22b device.
* \param[in] p A pointer to the packet handle.
* \param[in] pret A pointer to the packet handle.
* \param[in] max_delay The maximum time to delay waiting for a packet.
* \return The number of bytes received.
*/
uint32_t PIOS_RFM22B_Receive_Packet(uint32_t rfm22b_id, PHPacketHandle *p, uint32_t max_delay)
uint32_t PIOS_RFM22B_Receive_Packet(uint32_t rfm22b_id, PHPacketHandle *pret, uint32_t max_delay)
{
struct pios_rfm22b_dev * rfm22b_dev = (struct pios_rfm22b_dev *)rfm22b_id;
if (!PIOS_RFM22B_validate(rfm22b_dev))
@ -763,9 +818,60 @@ uint32_t PIOS_RFM22B_Receive_Packet(uint32_t rfm22b_id, PHPacketHandle *p, uint3
uint32_t rx_len = 0;
if (rfm22b_dev->rx_packet_prev)
{
*p = rfm22b_dev->rx_packet_prev;
PHPacketHandle p = rfm22b_dev->rx_packet_prev;
uint16_t len = PHPacketSizeECC(p);
// Attempt to correct any errors in the packet.
decode_data((unsigned char*)p, len);
// Check if there were any errors
bool rx_error = check_syndrome() != 0;
if(rx_error)
{
// We have an error. Try to correct it.
if (correct_errors_erasures((unsigned char*)p, len, 0, 0) == 0)
{
// We couldn't correct the error, so drop the packet.
rfm22b_dev->fast_error_packets++;
PHReleaseRXPacket(pios_packet_handler, p);
}
else
{
// We corrected the error.
rfm22b_dev->fast_corrected_packets++;
rx_error = false;
}
}
// Return the packet if there were not uncorrectable errors.
if (!rx_error)
{
rfm22b_dev->fast_good_packets++;
*pret = p;
rx_len = rfm22b_dev->rx_packet_len;
// Update the link statistics if necessary.
uint8_t fast_block = (p->header.seq_num >> 2) & 0xff;
uint8_t slow_block = (p->header.seq_num >> 4) & 0xff;
if (rfm22b_dev->fast_block != fast_block)
{
rfm22b_dev->fast_link_quality = (uint8_t)(((4 + (uint16_t)rfm22b_dev->fast_good_packets - rfm22b_dev->fast_error_packets) << 5) - 1);
rfm22b_dev->slow_good_packets += rfm22b_dev->fast_good_packets;
rfm22b_dev->slow_corrected_packets += rfm22b_dev->fast_corrected_packets;
rfm22b_dev->slow_error_packets += rfm22b_dev->fast_error_packets;
rfm22b_dev->fast_good_packets = rfm22b_dev->fast_corrected_packets = rfm22b_dev->fast_error_packets = 0;
rfm22b_dev->fast_block = fast_block;
}
if (rfm22b_dev->slow_block != slow_block)
{
rfm22b_dev->slow_link_quality = (uint8_t)(((16 + (uint16_t)rfm22b_dev->slow_good_packets - rfm22b_dev->slow_error_packets) << 3) - 1);
rfm22b_dev->slow_good_packets = rfm22b_dev->slow_corrected_packets = rfm22b_dev->slow_error_packets = 0;
rfm22b_dev->slow_block = slow_block;
}
}
rfm22b_dev->rx_packet_prev = NULL;
rx_len = rfm22b_dev->rx_packet_len;
}
return rx_len;
@ -791,7 +897,6 @@ static void PIOS_RFM22B_Task(void *parameters)
// Wait for a signal indicating an external interrupt or a pending send/receive request.
if ( xSemaphoreTake(g_rfm22b_dev->isrPending, ISR_TIMEOUT / portTICK_RATE_MS) == pdTRUE ) {
rfm22b_dev->irqs_processed++;
lastEventTicks = xTaskGetTickCount();
// Process events through the state machine.
@ -1246,6 +1351,12 @@ static enum pios_rfm22b_event rfm22_txStart(struct pios_rfm22b_dev *rfm22b_dev)
rfm22b_dev->tx_data_rd = rfm22b_dev->tx_data_wr = 0;
return RFM22B_EVENT_RX_MODE;
}
// Add the error correcting code.
p->header.source_id = rfm22b_dev->deviceID;
p->header.seq_num = rfm22b_dev->tx_packet_count++;
encode_data((unsigned char*)p, PHPacketSize(p), (unsigned char*)p);
rfm22b_dev->tx_packet = p;
rfm22b_dev->packet_start_ticks = xTaskGetTickCount();
if (rfm22b_dev->packet_start_ticks == 0)
@ -1317,20 +1428,14 @@ static bool rfm22_sendStatus(struct pios_rfm22b_dev *rfm22b_dev)
PHPacketHandle sph = (PHPacketHandle)&(rfm22b_dev->status_packet);
// Queue the status message
rfm22b_dev->status_packet.header.source_id = rfm22b_dev->deviceID;
rfm22b_dev->status_packet.header.destination_id = 0xffffffff; // Broadcast
rfm22b_dev->status_packet.header.type = PACKET_TYPE_STATUS;
rfm22b_dev->status_packet.header.data_size = PH_STATUS_DATA_SIZE(&(rfm22b_dev->status_packet));
rfm22b_dev->status_packet.header.tx_seq = 0;
rfm22b_dev->status_packet.header.rx_seq = 0;
rfm22b_dev->status_packet.errors = rfm22b_dev->errors;
rfm22b_dev->status_packet.resets = rfm22b_dev->resets;
rfm22b_dev->status_packet.retries = 0;
rfm22b_dev->status_packet.uavtalk_errors = 0;
rfm22b_dev->status_packet.dropped = 0;
// Add the error correcting code.
encode_data((unsigned char*)sph, PHPacketSize(sph), (unsigned char*)sph);
if (xQueueSend(rfm22b_dev->packetQueue, &sph, 0) != pdTRUE)
return false;

View File

@ -83,7 +83,10 @@ extern void PIOS_RFM22B_SetTxPower(uint32_t rfm22b_id, enum rfm22b_tx_power tx_p
extern void RFM22_SetDatarate(uint32_t rfm22b_id, enum rfm22b_datarate datarate, bool data_whitening);
extern void PIOS_RFM22B_SetDestinationId(uint32_t rfm22b_id, uint32_t dest_id);
extern uint32_t PIOS_RFM22B_DeviceID(uint32_t rfb22b_id);
extern int16_t PIOS_RFM22B_Resets(uint32_t rfm22b_id);
extern uint16_t PIOS_RFM22B_Resets(uint32_t rfm22b_id);
extern uint16_t PIOS_RFM22B_Timeouts(uint32_t rfm22b_id);
extern uint8_t PIOS_RFM22B_LinkQuality(uint32_t rfm22b_id);
extern int8_t PIOS_RFM22B_RSSI(uint32_t rfm22b_id);
extern bool PIOS_RFM22B_Send_Packet(uint32_t rfm22b_id, PHPacketHandle p, uint32_t max_delay);
extern uint32_t PIOS_RFM22B_Receive_Packet(uint32_t rfm22b_id, PHPacketHandle *p, uint32_t max_delay);

View File

@ -52,7 +52,7 @@ ConfigPipXtremeWidget::ConfigPipXtremeWidget(QWidget *parent) : ConfigTaskWidget
} else {
qDebug() << "Error: Object is unknown (PipXSettings).";
}
autoLoadWidgets();
autoLoadWidgets();
addApplySaveButtons(m_pipx->Apply, m_pipx->Save);
addUAVObjectToWidgetRelation("PipXSettings", "TelemetryConfig", m_pipx->TelemPortConfig);
@ -75,7 +75,7 @@ ConfigPipXtremeWidget::ConfigPipXtremeWidget(QWidget *parent) : ConfigTaskWidget
addUAVObjectToWidgetRelation("PipXStatus", "RSSI", m_pipx->RSSI);
addUAVObjectToWidgetRelation("PipXStatus", "AFC", m_pipx->RxAFC);
addUAVObjectToWidgetRelation("PipXStatus", "Retries", m_pipx->Retries);
addUAVObjectToWidgetRelation("PipXStatus", "Errors", m_pipx->Errors);
addUAVObjectToWidgetRelation("PipXStatus", "LinkQuality", m_pipx->LinkQuality);
addUAVObjectToWidgetRelation("PipXStatus", "UAVTalkErrors", m_pipx->UAVTalkErrors);
addUAVObjectToWidgetRelation("PipXStatus", "Resets", m_pipx->Resets);
addUAVObjectToWidgetRelation("PipXStatus", "Dropped", m_pipx->Dropped);

View File

@ -1051,9 +1051,9 @@
</widget>
</item>
<item row="8" column="2">
<widget class="QLabel" name="label_19">
<widget class="QLabel" name="LinkQualityLabel">
<property name="text">
<string>Errors</string>
<string>Link Quality</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -1061,7 +1061,7 @@
</widget>
</item>
<item row="8" column="3">
<widget class="QLineEdit" name="Errors">
<widget class="QLineEdit" name="LinkQuality">
<property name="maximumSize">
<size>
<width>101</width>

View File

@ -10,15 +10,14 @@
<field name="FrequencyBand" units="" type="uint8" elements="1" defaultvalue="0"/>
<field name="FrequencyStepSize" units="" type="float" elements="1" defaultvalue="0"/>
<field name="DeviceID" units="" type="uint32" elements="1" defaultvalue="0"/>
<field name="AFC" units="" type="int32" elements="1" defaultvalue="0"/>
<field name="Retries" units="" type="uint16" elements="1" defaultvalue="0"/>
<field name="Errors" units="" type="uint16" elements="1" defaultvalue="0"/>
<field name="UAVTalkErrors" units="" type="uint16" elements="1" defaultvalue="0"/>
<field name="Dropped" units="" type="uint16" elements="1" defaultvalue="0"/>
<field name="Resets" units="" type="uint16" elements="1" defaultvalue="0"/>
<field name="TXRate" units="Bps" type="uint16" elements="1" defaultvalue="0"/>
<field name="RXRate" units="Bps" type="uint16" elements="1" defaultvalue="0"/>
<field name="RSSI" units="dBm" type="int8" elements="1" defaultvalue="0"/>
<field name="LinkQuality" units="" type="uint8" elements="1" defaultvalue="0"/>
<field name="LinkState" units="function" type="enum" elements="1" options="Disconnected,Connecting,Connected" defaultvalue="Disconnected"/>
<field name="PairIDs" units="" type="uint32" elements="4" defaultvalue="0"/>
<field name="PairSignalStrengths" units="dBm" type="int8" elements="4" defaultvalue="-127"/>