Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(link statistics): Add Link Statistics API #78

Merged
merged 5 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/flight_modes/flight_modes.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief Example of how to read flight modes from a receiver.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down
100 changes: 100 additions & 0 deletions examples/link_stats/link_stats.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* @file link_stats.ino
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief Example of how to read link statistics from a receiver.
* @version 1.0.0
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
* @section License GNU General Public License v3.0
* This example is a part of the CRSF for Arduino library.
* CRSF for Arduino is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CRSF for Arduino is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CRSF for Arduino. If not, see <https://www.gnu.org/licenses/>.
*
*/

#include "CRSFforArduino.hpp"

/* Tested with the following equipment:
- Controller: RadioMaster TX16S Max Edition Mk1
- Firmware: EdgeTX 2.10.0 Nightly
- Lua Script: iNav OpenTX Telemetry Widget 2.2.3
- Transmitter Module: RadioMaster Ranger
- Firmware: ExpressLRS 3.3.1
- Receiver: RadioMaster RP3 Diversity
- Firmware: ExpressLRS 3.3.1
- Development Board: Adafruit Metro M4 Express
- Board Package: Adafruit SAMD Boards 1.7.5
- Framework: Arduino 1.8.13
- Library: CRSF for Arduino 1.0.0
*/

CRSFforArduino *crsf = nullptr;

void onLinkStatisticsUpdate(serialReceiverLayer::link_statistics_t);

void setup()
{
Serial.begin(115200);
while (!Serial)
{
delay(10);
}

Serial.println("Link Statistics Example.");

crsf = new CRSFforArduino();

if (!crsf->begin())
{
Serial.println("CRSF for Arduino failed to initialise.");

delete crsf;
crsf = nullptr;

while (1)
{
delay(10);
}
}

// Set link statistics callback.
crsf->setLinkStatisticsCallback(onLinkStatisticsUpdate);

Serial.println("Ready.");
delay(1000);
}

void loop()
{
crsf->update();
}

void onLinkStatisticsUpdate(serialReceiverLayer::link_statistics_t linkStatistics)
{
static unsigned long lastPrint = 0;
if (millis() - lastPrint >= 200)
{
lastPrint = millis();
Serial.print("Link Statistics: ");
Serial.print("RSSI: ");
Serial.print(linkStatistics.rssi);
Serial.print(", Link Quality: ");
Serial.print(linkStatistics.lqi);
Serial.print(", Signal-to-Noise Ratio: ");
Serial.print(linkStatistics.snr);
Serial.print(", Transmitter Power: ");
Serial.println(linkStatistics.tx_power);
}
}
2 changes: 1 addition & 1 deletion examples/platformio/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief This is the main development file for CRSF for Arduino.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down
2 changes: 1 addition & 1 deletion examples/rc_channels/rc_channels.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief Example of how to read rc channels from a receiver.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down
2 changes: 1 addition & 1 deletion examples/telemetry/telemetry.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief Example of how to send telemetry back to your RC handset using CRSF for Arduino.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down
6 changes: 4 additions & 2 deletions src/CFA_Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief This is the configuration file for CRSF for Arduino.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down Expand Up @@ -37,7 +37,7 @@ namespace crsfForArduinoConfig
Versioning is done using Semantic Versioning 2.0.0.
See https://semver.org/ for more information. */
#define CRSFFORARDUINO_VERSION "1.0.0"
#define CRSFFORARDUINO_VERSION_DATE "2024-1-20"
#define CRSFFORARDUINO_VERSION_DATE "2024-2-6"
#define CRSFFORARDUINO_VERSION_MAJOR 1
#define CRSFFORARDUINO_VERSION_MINOR 0
#define CRSFFORARDUINO_VERSION_PATCH 0
Expand Down Expand Up @@ -84,6 +84,8 @@ information back to your controller. */
#define CRSF_TELEMETRY_FLIGHTMODE_ENABLED 0
#define CRSF_TELEMETRY_GPS_ENABLED 1

#define CRSF_LINK_STATISTICS_ENABLED 1

/* Debug Options
- DEBUG_ENABLED: Enables or disables debug output over the selected serial port.
- CRSF_DEBUG_SERIAL_PORT: The serial port to use for debug output. Usually the native USB port.
Expand Down
12 changes: 11 additions & 1 deletion src/CRSFforArduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @brief This is the Sketch Layer, which is a simplified API for CRSF for Arduino.
* It is intended to be used by the user in their sketches.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down Expand Up @@ -170,6 +170,16 @@ namespace sketchLayer
#endif
}

void CRSFforArduino::setLinkStatisticsCallback(void (*callback)(serialReceiverLayer::link_statistics_t linkStatistics))
{
#if CRSF_LINK_STATISTICS_ENABLED > 0
_serialReceiver->setLinkStatisticsCallback(callback);
#else
// Prevent compiler warnings
(void)callback;
#endif
}

/**
* @brief Assigns a Flight Mode to the specified channel.
*
Expand Down
5 changes: 4 additions & 1 deletion src/CRSFforArduino.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @brief This is the Sketch Layer, which is a simplified API for CRSF for Arduino.
* It is intended to be used by the user in their sketches.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down Expand Up @@ -47,6 +47,9 @@ namespace sketchLayer
uint16_t rcToUs(uint16_t rc);
uint16_t readRcChannel(uint8_t channel, bool raw = false);

// Link statistics functions.
void setLinkStatisticsCallback(void (*callback)(serialReceiverLayer::link_statistics_t linkStatistics));

// Flight mode functions.
bool setFlightMode(serialReceiverLayer::flightModeId_t flightMode, uint8_t channel, uint16_t min, uint16_t max);
void setFlightModeCallback(void (*callback)(serialReceiverLayer::flightModeId_t flightMode));
Expand Down
2 changes: 1 addition & 1 deletion src/SerialReceiver/CRC/CRC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief A generic CRC8 implementation for the CRSF for Arduino library.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down
2 changes: 1 addition & 1 deletion src/SerialReceiver/CRC/CRC.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief A generic CRC8 implementation for the CRSF for Arduino library.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down
26 changes: 25 additions & 1 deletion src/SerialReceiver/CRSF/CRSF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief This decodes CRSF frames from a serial port.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down Expand Up @@ -132,6 +132,21 @@ namespace serialReceiverLayer
rcFrameReceived = true;
}
break;

#if CRSF_LINK_STATISTICS_ENABLED > 0
case CRSF_FRAMETYPE_LINK_STATISTICS:
if ((rxFrame.frame.deviceAddress == CRSF_ADDRESS_FLIGHT_CONTROLLER) && (rxFrame.frame.frameLength == CRSF_FRAME_ORIGIN_DEST_SIZE + CRSF_FRAME_LINK_STATISTICS_PAYLOAD_SIZE))
{
const crsf_payload_link_statistics_t *linkStatisticsPayload = (const crsf_payload_link_statistics_t *)&rxFrame.frame.payload;

/* Decode the link statistics. */
linkStatistics.rssi = (linkStatisticsPayload->active_antenna ? linkStatisticsPayload->uplink_rssi_2 : linkStatisticsPayload->uplink_rssi_1);
linkStatistics.lqi = linkStatisticsPayload->uplink_link_quality;
linkStatistics.snr = linkStatisticsPayload->uplink_snr;
linkStatistics.tx_power = (linkStatisticsPayload->uplink_tx_power < 9) ? tx_power_table[linkStatisticsPayload->uplink_tx_power] : 0;
}
break;
#endif
}
}
// #ifdef USE_DMA
Expand Down Expand Up @@ -178,6 +193,15 @@ namespace serialReceiverLayer
}
}

void CRSF::getLinkStatistics(link_statistics_t *linkStats)
{
#if CRSF_LINK_STATISTICS_ENABLED > 0
/* Copy the link statistics into the output structure. */
memcpy(linkStats, &linkStatistics, sizeof(link_statistics_t));
#else
#endif
}

uint8_t CRSF::calculateFrameCRC()
{
return crc8->calculate(rxFrame.frame.type, rxFrame.frame.payload, rxFrame.frame.frameLength - CRSF_FRAME_LENGTH_TYPE_CRC);
Expand Down
26 changes: 25 additions & 1 deletion src/SerialReceiver/CRSF/CRSF.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief This decodes CRSF frames from a serial port.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down Expand Up @@ -31,6 +31,28 @@

namespace serialReceiverLayer
{
// #if CRSF_LINK_STATISTICS_ENABLED > 0
typedef struct link_statistics_s
{
int16_t rssi = 0;
int16_t lqi = 0;
int16_t snr = 0;
int16_t tx_power = 0;
} link_statistics_t;

const uint16_t tx_power_table[9] = {
0, // 0 mW
10, // 10 mW
25, // 25 mW
100, // 100 mW
500, // 500 mW
1000, // 1 W
2000, // 2 W
250, // 250 mW
50 // 50 mW
};
// #endif

class CRSF
{
public:
Expand All @@ -41,13 +63,15 @@ namespace serialReceiverLayer
void setFrameTime(uint32_t baudRate, uint8_t packetCount = 10);
bool receiveFrames(uint8_t rxByte);
void getRcChannels(uint16_t *rcChannels);
void getLinkStatistics(link_statistics_t *linkStats);

private:
bool rcFrameReceived;
uint16_t frameCount;
uint32_t timePerFrame;
crsfProtocol::frame_t rxFrame;
crsfProtocol::frame_t rcChannelsFrame;
link_statistics_t linkStatistics;
genericCrc::CRC *crc8;
uint8_t calculateFrameCRC();
};
Expand Down
26 changes: 25 additions & 1 deletion src/SerialReceiver/CRSF/CRSFProtocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief This file contains enums and structs for the CRSF protocol.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand All @@ -28,6 +28,8 @@

#pragma once

#include "../../CFA_Config.hpp"

namespace crsfProtocol
{
enum rc_channels_e
Expand Down Expand Up @@ -116,6 +118,10 @@ namespace crsfProtocol
CRSF_FRAMETYPE_DISPLAYPORT_CMD = 0x7D,
} frameType_t;

#if CRSF_TELEMETRY_ENABLED == 1 || CRSF_LINK_STATISTICS_ENABLED == 1
#define CRSF_FRAME_ORIGIN_DEST_SIZE 2
#endif

typedef enum address_e
{
CRSF_ADDRESS_BROADCAST = 0x00,
Expand Down Expand Up @@ -184,6 +190,24 @@ namespace crsfProtocol
frameDefinition_t frame;
} frame_t;

#if CRSF_LINK_STATISTICS_ENABLED > 0
// Link Statistics frame.
// Uplink is the connection from the transmitter to the receiver. Downlink is in the opposite direction.
typedef struct crsf_payload_link_statistics_s
{
uint8_t uplink_rssi_1; // Uplink RSSI Antenna 1 (dBm * -1)
uint8_t uplink_rssi_2; // Uplink RSSI Antenna 2 (dBm * -1)
uint8_t uplink_link_quality; // Uplink Link Quality/Packet Success Rate (%)
int8_t uplink_snr; // Uplink Signal-to-Noise Ratio (dB)
uint8_t active_antenna; // Active Antenna (0 = Antenna 1, 1 = Antenna 2)
uint8_t rf_mode; // RF Mode (4 fps = 0, 50 fps = 1, 150 fps = 2, 250 fps = 3, 500 fps = 4, 1000 fps = 5)
uint8_t uplink_tx_power; // Uplink TX Power (0 mW = 0, 10 mW = 1, 25 mW = 2, 100 mW = 3, 250 mW = 4, 500 mW = 5, 1000 mW = 6, 2000 mW = 7)
uint8_t downlink_rssi; // Downlink RSSI (dBm * -1)
uint8_t downlink_link_quality; // Downlink Link Quality/Packet Success Rate (%)
int8_t downlink_snr; // Downlink Signal-to-Noise Ratio (dB)
} crsf_payload_link_statistics_t;
#endif

// Attitude Data to pass to the telemetry frame.
typedef struct attitudeData_s
{
Expand Down
2 changes: 1 addition & 1 deletion src/SerialReceiver/SerialBuffer/SerialBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief A generic serial buffer for the CRSF for Arduino library.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down
2 changes: 1 addition & 1 deletion src/SerialReceiver/SerialBuffer/SerialBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Cassandra "ZZ Cat" Robinson ([email protected])
* @brief A generic serial buffer for the CRSF for Arduino library.
* @version 1.0.0
* @date 2024-2-5
* @date 2024-2-6
*
* @copyright Copyright (c) 2024, Cassandra "ZZ Cat" Robinson. All rights reserved.
*
Expand Down
Loading
Loading