chore: New module/serial API (#3055)
* WiP: new module interface * WiP: softserial timer DMA * WiP: setup() and send() in one step and remove methods specific to internal or external module * fixes and extra port config * horus targets * module ports have moved * T8 support (only internal module) * fix nv14 * stupid GCC.... * disable BT * remove nv14 telem driver * remove old aux serial driver * Move module buffers out of pulses.h * Soft serial fixes and PXX1 support * Fixed PPM module output * Fixed CLI * compilation fixes * Ported bluetooth and flysky gimbal to new serial driver * Re-enable soft-serial RX * fixes and cleanup * nv14 fixes * Fix flysky gimbals * Ghost module * 16 bytes of RAM * Remove getByte from module API * Ghost cleanup * fix: _half_duplex_input() must be called after usart init * WiP * more cleanup * Remove board specific settings from PXX1 / PXX2 drivers * A bit of PXX2 header cleanup * Add support for OVER8 and ONEBIT * Add some support for inverters (NV14 / EL18) * Support NV14 power fixes in generic board * Fix polarity handling * Fix RX DMA * Fix mixer not running * Add soft-serial polarity control * Quick fix for telemetry polling while module port is changed * Fix bootloader DEBUG * Fix MPM telemetry * Fix pulse start * DSM2 soft-serial fallback * DSMP async module restart * Fix CRSF LUA upstream * Remove global variable telemetryProtocol * Use HAL/LL constants * Fix various issue with AFHDS3 and NV14/EL18 internal module * Fixed S.PORT unit tests * fix: update widx after writing at current index * fix: init error condition * Fix: possible infinite loop in _find_port() * Add support for bidir S.PORT init * Add support for "getLastByte" in HW serial driver * PXX1: Add support for S.PORT based on IDLE callback * Fix rebase error * Fix softserial _rx_fifo_push() * Add softserial support for waitForTxCompleted() * Fix MPM flashing (internal / external) * Fixed external MPM * Activate RX DMA on internal module Seems to work with serial passthrough without issues, at least on the L3R PRO. * Fix softserial DMA on stdlcd F4 targets * Add softserial support for 32bit timers (mostly TIM2) * More precise soft-serial * Fix MPM update using inverters & HW uart * Raise S.PORT DMA/USART IRQ prio to achieve faster switching to input * Remove useless delays * Fix flashing external ELRS module * Added a retry mechanism for FrSky S.PORT update * Remove useless enableRx() * External FrSky modules are all flashed via S.PORT * Remove power management unit update This was only used on the first batch of X-lite.
This commit is contained in:
@@ -23,7 +23,6 @@
|
||||
#include "ghost_menu.h"
|
||||
|
||||
#include "opentx.h"
|
||||
#include "aux_serial_driver.h"
|
||||
|
||||
const char *ghstRfProfileValue[GHST_RF_PROFILE_COUNT] = { "Auto", "Norm", "Race", "Pure", "Long", "Unused", "Race2", "Pure2" };
|
||||
const char *ghstVtxBandName[GHST_VTX_BAND_COUNT] = { "- - -" , "IRC", "Race", "BandE", "BandB", "BandA" };
|
||||
@@ -92,14 +91,6 @@ const GhostSensor ghostSensors[] = {
|
||||
{0x00, NULL, UNIT_RAW, 0},
|
||||
};
|
||||
|
||||
uint8_t getGhostModuleAddr() {
|
||||
#if SPORT_MAX_BAUDRATE < 400000
|
||||
return g_model.moduleData[EXTERNAL_MODULE].ghost.telemetryBaudrate == GHST_TELEMETRY_RATE_400K ? GHST_ADDR_MODULE_SYM : GHST_ADDR_MODULE_ASYM;
|
||||
#else
|
||||
return GHST_ADDR_MODULE_SYM;
|
||||
#endif
|
||||
}
|
||||
|
||||
const GhostSensor *getGhostSensor(uint8_t id)
|
||||
{
|
||||
for (const GhostSensor * sensor = ghostSensors; sensor->id; sensor++) {
|
||||
@@ -132,75 +123,78 @@ void processGhostTelemetryValueString(const GhostSensor * sensor, const char * s
|
||||
}
|
||||
}
|
||||
|
||||
bool checkGhostTelemetryFrameCRC()
|
||||
static bool checkGhostTelemetryFrameCRC(const uint8_t* frame, uint32_t len)
|
||||
{
|
||||
uint8_t len = telemetryRxBuffer[1];
|
||||
uint8_t crc = crc8(&telemetryRxBuffer[2], len - 1);
|
||||
return (crc == telemetryRxBuffer[len + 1]);
|
||||
uint8_t crc = crc8(frame, len - 1);
|
||||
return (crc == frame[len - 1]);
|
||||
}
|
||||
|
||||
// hifirst
|
||||
uint16_t getTelemetryValue_u16(uint8_t index)
|
||||
static uint16_t _get_u16(const uint8_t* frame, uint8_t offset)
|
||||
{
|
||||
return (telemetryRxBuffer[index] << 8) | telemetryRxBuffer[index + 1];
|
||||
return (frame[offset] << 8) | frame[offset + 1];
|
||||
}
|
||||
|
||||
// lofirst
|
||||
uint16_t getTelemetryValue_u16le(uint8_t index)
|
||||
static uint16_t _get_u16le(const uint8_t* frame, uint8_t offset)
|
||||
{
|
||||
return (telemetryRxBuffer[index + 1] << 8) | telemetryRxBuffer[index];
|
||||
return (frame[offset + 1] << 8) | frame[offset];
|
||||
}
|
||||
|
||||
// hifirst
|
||||
uint32_t getTelemetryValue_s32(uint8_t index)
|
||||
static uint32_t _get_s32(const uint8_t* frame, uint8_t offset)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
val <<= 8, val |= telemetryRxBuffer[index + i];
|
||||
val <<= 8, val |= frame[offset + i];
|
||||
return val;
|
||||
}
|
||||
|
||||
// lofirst
|
||||
uint32_t getTelemetryValue_s32le(uint8_t index)
|
||||
static uint32_t _get_s32le(const uint8_t* frame, uint8_t offset)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
val <<= 8, val |= telemetryRxBuffer[index + 3 - i];
|
||||
val <<= 8, val |= frame[offset + 3 - i];
|
||||
return val;
|
||||
}
|
||||
|
||||
void processGhostTelemetryFrame()
|
||||
void processGhostTelemetryFrame(uint8_t module, uint8_t* buffer, uint32_t length)
|
||||
{
|
||||
if (!checkGhostTelemetryFrameCRC()) {
|
||||
uint8_t frame_len = buffer[1];
|
||||
auto frame = buffer + 2;
|
||||
if (!checkGhostTelemetryFrameCRC(frame, frame_len)) {
|
||||
TRACE("[GS] CRC error");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t id = telemetryRxBuffer[2];
|
||||
uint8_t id = frame[0];
|
||||
switch(id) {
|
||||
case GHST_DL_OPENTX_SYNC:
|
||||
{
|
||||
uint32_t update_interval = getTelemetryValue_s32(3);
|
||||
int32_t offset = getTelemetryValue_s32(7);
|
||||
uint32_t update_interval = _get_s32(frame, 1);
|
||||
int32_t offset = _get_s32(frame, 5);
|
||||
|
||||
// values are in units of 100ns
|
||||
update_interval /= 10;
|
||||
offset /= 10;
|
||||
|
||||
getModuleSyncStatus(EXTERNAL_MODULE).update(update_interval, offset);
|
||||
getModuleSyncStatus(module).update(update_interval, offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case GHST_DL_LINK_STAT:
|
||||
{
|
||||
#if defined(BLUETOOTH)
|
||||
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
|
||||
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY &&
|
||||
bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
bluetooth.write(buffer, length);
|
||||
}
|
||||
#endif
|
||||
uint8_t rssiVal = min<uint8_t>(telemetryRxBuffer[3], 120); // RSSI is a negative value, but sent as a positive integer.
|
||||
uint8_t lqVal = min<uint8_t>(telemetryRxBuffer[4], 100);
|
||||
uint8_t snrVal = min<uint8_t>(telemetryRxBuffer[5], 100);
|
||||
// RSSI is a negative value, but sent as a positive integer.
|
||||
uint8_t rssiVal = min<uint8_t>(frame[1], 120);
|
||||
uint8_t lqVal = min<uint8_t>(frame[2], 100);
|
||||
uint8_t snrVal = min<uint8_t>(frame[3], 100);
|
||||
|
||||
processGhostTelemetryValue(GHOST_ID_RX_RSSI, - rssiVal);
|
||||
processGhostTelemetryValue(GHOST_ID_RX_LQ, lqVal);
|
||||
@@ -216,10 +210,10 @@ void processGhostTelemetryFrame()
|
||||
telemetryStreaming = 0;
|
||||
}
|
||||
|
||||
processGhostTelemetryValue(GHOST_ID_TX_POWER, getTelemetryValue_u16(6));
|
||||
processGhostTelemetryValue(GHOST_ID_FRAME_RATE, getTelemetryValue_u16(8));
|
||||
processGhostTelemetryValue(GHOST_ID_TOTAL_LATENCY, getTelemetryValue_u16(10));
|
||||
uint8_t rfModeEnum = min<uint8_t>(telemetryRxBuffer[12], GHST_RF_PROFILE_MAX);
|
||||
processGhostTelemetryValue(GHOST_ID_TX_POWER, _get_u16(frame, 4));
|
||||
processGhostTelemetryValue(GHOST_ID_FRAME_RATE, _get_u16(frame, 6));
|
||||
processGhostTelemetryValue(GHOST_ID_TOTAL_LATENCY, _get_u16(frame, 8));
|
||||
uint8_t rfModeEnum = min<uint8_t>(frame[10], GHST_RF_PROFILE_MAX);
|
||||
|
||||
// RF mode string, one char at a time
|
||||
const GhostSensor * sensor = getGhostSensor(GHOST_ID_RF_MODE);
|
||||
@@ -231,18 +225,19 @@ void processGhostTelemetryFrame()
|
||||
case GHST_DL_VTX_STAT:
|
||||
{
|
||||
#if defined(BLUETOOTH)
|
||||
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
|
||||
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY &&
|
||||
bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
bluetooth.write(buffer, length);
|
||||
}
|
||||
#endif
|
||||
uint8_t vtxBandEnum = min<uint8_t>(telemetryRxBuffer[8], GHST_VTX_BAND_MAX);
|
||||
uint8_t vtxBandEnum = min<uint8_t>(frame[6], GHST_VTX_BAND_MAX);
|
||||
|
||||
const GhostSensor * sensor = getGhostSensor(GHOST_ID_VTX_BAND);
|
||||
const char * vtxBandString = ghstVtxBandName[vtxBandEnum];
|
||||
|
||||
processGhostTelemetryValue(GHOST_ID_VTX_FREQ, getTelemetryValue_u16(4));
|
||||
processGhostTelemetryValue(GHOST_ID_VTX_POWER, getTelemetryValue_u16(6));
|
||||
processGhostTelemetryValue(GHOST_ID_VTX_CHAN, min<uint8_t>(telemetryRxBuffer[9], 8));
|
||||
processGhostTelemetryValue(GHOST_ID_VTX_FREQ, _get_u16(frame, 2));
|
||||
processGhostTelemetryValue(GHOST_ID_VTX_POWER, _get_u16(frame, 4));
|
||||
processGhostTelemetryValue(GHOST_ID_VTX_CHAN, min<uint8_t>(frame[7], 8));
|
||||
processGhostTelemetryValueString(sensor, vtxBandString);
|
||||
break;
|
||||
}
|
||||
@@ -251,7 +246,7 @@ void processGhostTelemetryFrame()
|
||||
{
|
||||
GhostMenuFrame * packet;
|
||||
GhostMenuData * lineData;
|
||||
packet = (GhostMenuFrame * ) telemetryRxBuffer;
|
||||
packet = (GhostMenuFrame * )buffer;
|
||||
lineData = (GhostMenuData *) &reusableBuffer.ghostMenu.line[packet->lineIndex];
|
||||
lineData->splitLine = 0;
|
||||
reusableBuffer.ghostMenu.menuStatus = packet->menuStatus;
|
||||
@@ -271,39 +266,42 @@ void processGhostTelemetryFrame()
|
||||
|
||||
case GHST_DL_PACK_STAT: {
|
||||
#if defined(BLUETOOTH)
|
||||
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
|
||||
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY &&
|
||||
bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
bluetooth.write(buffer, length);
|
||||
}
|
||||
#endif
|
||||
processGhostTelemetryValue(GHOST_ID_PACK_VOLTS, getTelemetryValue_u16le(3));
|
||||
processGhostTelemetryValue(GHOST_ID_PACK_AMPS, getTelemetryValue_u16le(5));
|
||||
processGhostTelemetryValue(GHOST_ID_PACK_MAH, getTelemetryValue_u16le(7) * 10);
|
||||
processGhostTelemetryValue(GHOST_ID_PACK_VOLTS, _get_u16le(frame, 1));
|
||||
processGhostTelemetryValue(GHOST_ID_PACK_AMPS, _get_u16le(frame, 3));
|
||||
processGhostTelemetryValue(GHOST_ID_PACK_MAH, _get_u16le(frame, 5) * 10);
|
||||
break;
|
||||
}
|
||||
|
||||
case GHST_DL_GPS_PRIMARY: {
|
||||
#if defined(BLUETOOTH)
|
||||
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
|
||||
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY &&
|
||||
bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
bluetooth.write(buffer, length);
|
||||
}
|
||||
#endif
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_LAT, ((int32_t)getTelemetryValue_s32le(3)) / 10);
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_LONG, ((int32_t)getTelemetryValue_s32le(7)) / 10);
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_ALT, (int16_t)getTelemetryValue_u16le(11));
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_LAT, ((int32_t)_get_s32le(frame, 1)) / 10);
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_LONG, ((int32_t)_get_s32le(frame, 5)) / 10);
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_ALT, (int16_t)_get_u16le(frame, 9));
|
||||
break;
|
||||
}
|
||||
|
||||
case GHST_DL_GPS_SECONDARY: {
|
||||
#if defined(BLUETOOTH)
|
||||
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY && bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
bluetooth.write(telemetryRxBuffer, telemetryRxBufferCount);
|
||||
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY &&
|
||||
bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
bluetooth.write(buffer, length);
|
||||
}
|
||||
#endif
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_HDG, getTelemetryValue_u16le(5) / 10);
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_HDG, _get_u16le(frame, 3) / 10);
|
||||
|
||||
// ground speed is passed via GHST as cm/s, converted to km/h for OpenTx
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_GSPD, (getTelemetryValue_u16le(3) * 36 + 50) / 100);
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_SATS, telemetryRxBuffer[7]);
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_GSPD, (_get_u16le(frame, 1) * 36 + 50) / 100);
|
||||
processGhostTelemetryValue(GHOST_ID_GPS_SATS, frame[5]);
|
||||
break;
|
||||
}
|
||||
case GHST_DL_MAGBARO: {
|
||||
@@ -312,10 +310,10 @@ void processGhostTelemetryFrame()
|
||||
}
|
||||
#if defined(LUA)
|
||||
default:
|
||||
if (luaInputTelemetryFifo && luaInputTelemetryFifo->hasSpace(telemetryRxBufferCount-2) ) {
|
||||
for (uint8_t i=1; i<telemetryRxBufferCount-1; i++) {
|
||||
// destination address and CRC are skipped
|
||||
luaInputTelemetryFifo->push(telemetryRxBuffer[i]);
|
||||
// destination address and CRC are skipped
|
||||
if (luaInputTelemetryFifo && luaInputTelemetryFifo->hasSpace(length - 2) ) {
|
||||
for (uint8_t i = 1; i < length - 1; i++) {
|
||||
luaInputTelemetryFifo->push(buffer[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -323,31 +321,6 @@ void processGhostTelemetryFrame()
|
||||
}
|
||||
}
|
||||
|
||||
void processGhostTelemetryData(uint8_t data)
|
||||
{
|
||||
if (telemetryRxBufferCount == 0 && data != GHST_ADDR_RADIO) {
|
||||
TRACE("[GH] address 0x%02X error", data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (telemetryRxBufferCount < TELEMETRY_RX_PACKET_SIZE) {
|
||||
telemetryRxBuffer[telemetryRxBufferCount++] = data;
|
||||
}
|
||||
else {
|
||||
TRACE("[GH] array size %d error", telemetryRxBufferCount);
|
||||
telemetryRxBufferCount = 0;
|
||||
}
|
||||
|
||||
if (telemetryRxBufferCount > 4) {
|
||||
uint8_t length = telemetryRxBuffer[1];
|
||||
if (length + 2 == telemetryRxBufferCount) {
|
||||
processGhostTelemetryFrame();
|
||||
telemetryRxBufferCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ghostSetDefault(int index, uint8_t id, uint8_t subId)
|
||||
{
|
||||
TelemetrySensor &telemetrySensor = g_model.telemetrySensors[index];
|
||||
|
||||
Reference in New Issue
Block a user