335 lines
13 KiB
C++
335 lines
13 KiB
C++
/*
|
|
* Copyright (C) OpenTX
|
|
*
|
|
* Based on code named
|
|
* th9x - http://code.google.com/p/th9x
|
|
* er9x - http://code.google.com/p/er9x
|
|
* gruvin9x - http://code.google.com/p/gruvin9x
|
|
*
|
|
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program 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.
|
|
*/
|
|
|
|
#ifndef _FRSKY_H_
|
|
#define _FRSKY_H_
|
|
|
|
#include "../definitions.h"
|
|
#include "telemetry_holders.h"
|
|
#include "../io/frsky_pxx2.h"
|
|
|
|
// Receive buffer state machine state enum
|
|
enum FrSkyDataState {
|
|
STATE_DATA_IDLE,
|
|
STATE_DATA_START,
|
|
STATE_DATA_IN_FRAME,
|
|
STATE_DATA_XOR,
|
|
};
|
|
|
|
#define FRSKY_SPORT_BAUDRATE 57600
|
|
|
|
#define FRSKY_D_BAUDRATE 9600
|
|
|
|
#define FRSKY_SPORT_PACKET_SIZE 9
|
|
|
|
#define WSHH_TIMEOUT10ms 60 // 600ms
|
|
|
|
#define FRSKY_SPORT_AVERAGING 4
|
|
#define FRSKY_D_AVERAGING 8
|
|
|
|
// Enumerate FrSky packet codes
|
|
#define LINKPKT 0xfe
|
|
#define USRPKT 0xfd
|
|
#define A11PKT 0xfc
|
|
#define A12PKT 0xfb
|
|
#define A21PKT 0xfa
|
|
#define A22PKT 0xf9
|
|
#define ALRM_REQUEST 0xf8
|
|
#define RSSI1PKT 0xf7
|
|
#define RSSI2PKT 0xf6
|
|
#define RSSI_REQUEST 0xf1
|
|
|
|
|
|
// FrSky PRIM IDs (1 byte)
|
|
#define DATA_FRAME 0x10
|
|
|
|
// FrSky old DATA IDs (1 byte)
|
|
#define GPS_ALT_BP_ID 0x01
|
|
#define TEMP1_ID 0x02
|
|
#define RPM_ID 0x03
|
|
#define FUEL_ID 0x04
|
|
#define TEMP2_ID 0x05
|
|
#define VOLTS_ID 0x06
|
|
#define GPS_ALT_AP_ID 0x09
|
|
#define BARO_ALT_BP_ID 0x10
|
|
#define GPS_SPEED_BP_ID 0x11
|
|
#define GPS_LONG_BP_ID 0x12
|
|
#define GPS_LAT_BP_ID 0x13
|
|
#define GPS_COURS_BP_ID 0x14
|
|
#define GPS_DAY_MONTH_ID 0x15
|
|
#define GPS_YEAR_ID 0x16
|
|
#define GPS_HOUR_MIN_ID 0x17
|
|
#define GPS_SEC_ID 0x18
|
|
#define GPS_SPEED_AP_ID 0x19
|
|
#define GPS_LONG_AP_ID 0x1A
|
|
#define GPS_LAT_AP_ID 0x1B
|
|
#define GPS_COURS_AP_ID 0x1C
|
|
#define BARO_ALT_AP_ID 0x21
|
|
#define GPS_LONG_EW_ID 0x22
|
|
#define GPS_LAT_NS_ID 0x23
|
|
#define ACCEL_X_ID 0x24
|
|
#define ACCEL_Y_ID 0x25
|
|
#define ACCEL_Z_ID 0x26
|
|
#define CURRENT_ID 0x28
|
|
#define VARIO_ID 0x30
|
|
#define VFAS_ID 0x39
|
|
#define VOLTS_BP_ID 0x3A
|
|
#define VOLTS_AP_ID 0x3B
|
|
#define FRSKY_LAST_ID 0x3F
|
|
#define D_RSSI_ID 0xF0
|
|
#define D_A1_ID 0xF1
|
|
#define D_A2_ID 0xF2
|
|
|
|
#define VFAS_D_HIPREC_OFFSET 2000
|
|
|
|
|
|
// FrSky new DATA IDs (2 bytes)
|
|
#define ALT_FIRST_ID 0x0100
|
|
#define ALT_LAST_ID 0x010f
|
|
#define VARIO_FIRST_ID 0x0110
|
|
#define VARIO_LAST_ID 0x011f
|
|
#define CURR_FIRST_ID 0x0200
|
|
#define CURR_LAST_ID 0x020f
|
|
#define VFAS_FIRST_ID 0x0210
|
|
#define VFAS_LAST_ID 0x021f
|
|
#define CELLS_FIRST_ID 0x0300
|
|
#define CELLS_LAST_ID 0x030f
|
|
#define T1_FIRST_ID 0x0400
|
|
#define T1_LAST_ID 0x040f
|
|
#define T2_FIRST_ID 0x0410
|
|
#define T2_LAST_ID 0x041f
|
|
#define RPM_FIRST_ID 0x0500
|
|
#define RPM_LAST_ID 0x050f
|
|
#define FUEL_FIRST_ID 0x0600
|
|
#define FUEL_LAST_ID 0x060f
|
|
#define ACCX_FIRST_ID 0x0700
|
|
#define ACCX_LAST_ID 0x070f
|
|
#define ACCY_FIRST_ID 0x0710
|
|
#define ACCY_LAST_ID 0x071f
|
|
#define ACCZ_FIRST_ID 0x0720
|
|
#define ACCZ_LAST_ID 0x072f
|
|
#define GPS_LONG_LATI_FIRST_ID 0x0800
|
|
#define GPS_LONG_LATI_LAST_ID 0x080f
|
|
#define GPS_ALT_FIRST_ID 0x0820
|
|
#define GPS_ALT_LAST_ID 0x082f
|
|
#define GPS_SPEED_FIRST_ID 0x0830
|
|
#define GPS_SPEED_LAST_ID 0x083f
|
|
#define GPS_COURS_FIRST_ID 0x0840
|
|
#define GPS_COURS_LAST_ID 0x084f
|
|
#define GPS_TIME_DATE_FIRST_ID 0x0850
|
|
#define GPS_TIME_DATE_LAST_ID 0x085f
|
|
#define A3_FIRST_ID 0x0900
|
|
#define A3_LAST_ID 0x090f
|
|
#define A4_FIRST_ID 0x0910
|
|
#define A4_LAST_ID 0x091f
|
|
#define AIR_SPEED_FIRST_ID 0x0a00
|
|
#define AIR_SPEED_LAST_ID 0x0a0f
|
|
#define RBOX_BATT1_FIRST_ID 0x0b00
|
|
#define RBOX_BATT1_LAST_ID 0x0b0f
|
|
#define RBOX_BATT2_FIRST_ID 0x0b10
|
|
#define RBOX_BATT2_LAST_ID 0x0b1f
|
|
#define RBOX_STATE_FIRST_ID 0x0b20
|
|
#define RBOX_STATE_LAST_ID 0x0b2f
|
|
#define RBOX_CNSP_FIRST_ID 0x0b30
|
|
#define RBOX_CNSP_LAST_ID 0x0b3f
|
|
#define SD1_FIRST_ID 0x0b40
|
|
#define SD1_LAST_ID 0x0b4f
|
|
#define ESC_POWER_FIRST_ID 0x0b50
|
|
#define ESC_POWER_LAST_ID 0x0b5f
|
|
#define ESC_RPM_CONS_FIRST_ID 0x0b60
|
|
#define ESC_RPM_CONS_LAST_ID 0x0b6f
|
|
#define ESC_TEMPERATURE_FIRST_ID 0x0b70
|
|
#define ESC_TEMPERATURE_LAST_ID 0x0b7f
|
|
#define X8R_FIRST_ID 0x0c20
|
|
#define X8R_LAST_ID 0x0c2f
|
|
#define S6R_FIRST_ID 0x0c30
|
|
#define S6R_LAST_ID 0x0c3f
|
|
#define GASSUIT_TEMP1_FIRST_ID 0x0d00
|
|
#define GASSUIT_TEMP1_LAST_ID 0x0d0f
|
|
#define GASSUIT_TEMP2_FIRST_ID 0x0d10
|
|
#define GASSUIT_TEMP2_LAST_ID 0x0d1f
|
|
#define GASSUIT_SPEED_FIRST_ID 0x0d20
|
|
#define GASSUIT_SPEED_LAST_ID 0x0d2f
|
|
#define GASSUIT_RES_VOL_FIRST_ID 0x0d30
|
|
#define GASSUIT_RES_VOL_LAST_ID 0x0d3f
|
|
#define GASSUIT_RES_PERC_FIRST_ID 0x0d40
|
|
#define GASSUIT_RES_PERC_LAST_ID 0x0d4f
|
|
#define GASSUIT_FLOW_FIRST_ID 0x0d50
|
|
#define GASSUIT_FLOW_LAST_ID 0x0d5f
|
|
#define GASSUIT_MAX_FLOW_FIRST_ID 0x0d60
|
|
#define GASSUIT_MAX_FLOW_LAST_ID 0x0d6f
|
|
#define GASSUIT_AVG_FLOW_FIRST_ID 0x0d70
|
|
#define GASSUIT_AVG_FLOW_LAST_ID 0x0d7f
|
|
#define SBEC_POWER_FIRST_ID 0x0e50
|
|
#define SBEC_POWER_LAST_ID 0x0e5f
|
|
#define DIY_FIRST_ID 0x5100
|
|
#define DIY_LAST_ID 0x52ff
|
|
#define DIY_STREAM_FIRST_ID 0x5000
|
|
#define DIY_STREAM_LAST_ID 0x50ff
|
|
#define FACT_TEST_ID 0xf000
|
|
#define RSSI_ID 0xf101
|
|
#define ADC1_ID 0xf102
|
|
#define ADC2_ID 0xf103
|
|
#define BATT_ID 0xf104
|
|
#define RAS_ID 0xf105
|
|
#define XJT_VERSION_ID 0xf106
|
|
#define R9_PWR_ID 0xf107
|
|
#define SP2UART_A_ID 0xfd00
|
|
#define SP2UART_B_ID 0xfd01
|
|
#define FUEL_QTY_FIRST_ID 0x0a10
|
|
#define FUEL_QTY_LAST_ID 0x0a1f
|
|
|
|
// Default sensor data IDs (Physical IDs + CRC)
|
|
#define DATA_ID_VARIO 0x00 // 0
|
|
#define DATA_ID_FLVSS 0xA1 // 1
|
|
#define DATA_ID_FAS 0x22 // 2
|
|
#define DATA_ID_GPS 0x83 // 3
|
|
#define DATA_ID_RPM 0xE4 // 4
|
|
#define DATA_ID_SP2UH 0x45 // 5
|
|
#define DATA_ID_SP2UR 0xC6 // 6
|
|
|
|
#define IS_HIDDEN_TELEMETRY_VALUE(id) ((id == SP2UART_A_ID) || (id == SP2UART_B_ID) || (id == XJT_VERSION_ID) || (id == RAS_ID) || (id == FACT_TEST_ID))
|
|
|
|
#define ALARM_GREATER(channel, alarm) ((g_model.frsky.channels[channel].alarms_greater >> alarm) & 1)
|
|
#define ALARM_LEVEL(channel, alarm) ((g_model.frsky.channels[channel].alarms_level >> (2*alarm)) & 3)
|
|
|
|
#define TELEMETRY_STREAMING() (telemetryData.rssi.value > 0)
|
|
#define TELEMETRY_RSSI() (telemetryData.rssi.value)
|
|
#define TELEMETRY_RSSI_MIN() (telemetryData.rssi.min)
|
|
|
|
#define TELEMETRY_CELL_VOLTAGE_MUTLIPLIER 1
|
|
|
|
#define TELEMETRY_GPS_SPEED_BP telemetryData.hub.gpsSpeed_bp
|
|
#define TELEMETRY_GPS_SPEED_AP telemetryData.hub.gpsSpeed_ap
|
|
|
|
#define TELEMETRY_ABSOLUTE_GPS_ALT (telemetryData.hub.gpsAltitude)
|
|
#define TELEMETRY_RELATIVE_GPS_ALT (telemetryData.hub.gpsAltitude + telemetryData.hub.gpsAltitudeOffset)
|
|
#define TELEMETRY_RELATIVE_GPS_ALT_BP (TELEMETRY_RELATIVE_GPS_ALT / 100)
|
|
|
|
#define TELEMETRY_RELATIVE_BARO_ALT_BP (telemetryData.hub.baroAltitude / 100)
|
|
#define TELEMETRY_RELATIVE_BARO_ALT_AP (telemetryData.hub.baroAltitude % 100)
|
|
|
|
#define TELEMETRY_BARO_ALT_PREPARE() div_t baroAltitudeDivision = div(getConvertedTelemetryValue(telemetryData.hub.baroAltitude, UNIT_DIST), 100)
|
|
#define TELEMETRY_BARO_ALT_FORMAT "%c%d.%02d,"
|
|
#define TELEMETRY_BARO_ALT_ARGS telemetryData.hub.baroAltitude < 0 ? '-' : ' ', abs(baroAltitudeDivision.quot), abs(baroAltitudeDivision.rem),
|
|
#define TELEMETRY_GPS_ALT_FORMAT "%c%d.%02d,"
|
|
#define TELEMETRY_GPS_ALT_ARGS telemetryData.hub.gpsAltitude < 0 ? '-' : ' ', abs(telemetryData.hub.gpsAltitude / 100), abs(telemetryData.hub.gpsAltitude % 100),
|
|
#define TELEMETRY_SPEED_UNIT (IS_IMPERIAL_ENABLE() ? SPEED_UNIT_IMP : SPEED_UNIT_METR)
|
|
#define TELEMETRY_GPS_SPEED_FORMAT "%d,"
|
|
#define TELEMETRY_GPS_SPEED_ARGS telemetryData.hub.gpsSpeed_bp,
|
|
|
|
#define TELEMETRY_CELLS_ARGS telemetryData.hub.cellsSum / 10, telemetryData.hub.cellsSum % 10, TELEMETRY_CELL_VOLTAGE(0)/100, TELEMETRY_CELL_VOLTAGE(0)%100, TELEMETRY_CELL_VOLTAGE(1)/100, TELEMETRY_CELL_VOLTAGE(1)%100, TELEMETRY_CELL_VOLTAGE(2)/100, TELEMETRY_CELL_VOLTAGE(2)%100, TELEMETRY_CELL_VOLTAGE(3)/100, TELEMETRY_CELL_VOLTAGE(3)%100, TELEMETRY_CELL_VOLTAGE(4)/100, TELEMETRY_CELL_VOLTAGE(4)%100, TELEMETRY_CELL_VOLTAGE(5)/100, TELEMETRY_CELL_VOLTAGE(5)%100, TELEMETRY_CELL_VOLTAGE(6)/100, TELEMETRY_CELL_VOLTAGE(6)%100, TELEMETRY_CELL_VOLTAGE(7)/100, TELEMETRY_CELL_VOLTAGE(7)%100, TELEMETRY_CELL_VOLTAGE(8)/100, TELEMETRY_CELL_VOLTAGE(8)%100, TELEMETRY_CELL_VOLTAGE(9)/100, TELEMETRY_CELL_VOLTAGE(9)%100, TELEMETRY_CELL_VOLTAGE(10)/100, TELEMETRY_CELL_VOLTAGE(10)%100, TELEMETRY_CELL_VOLTAGE(11)/100, TELEMETRY_CELL_VOLTAGE(11)%100,
|
|
#define TELEMETRY_CELLS_FORMAT "%d.%d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,"
|
|
#define TELEMETRY_CELLS_LABEL "Cell volts,Cell 1,Cell 2,Cell 3,Cell 4,Cell 5,Cell 6,Cell 7,Cell 8,Cell 9,Cell 10,Cell 11,Cell 12,"
|
|
|
|
#define TELEMETRY_CURRENT_FORMAT "%d.%d,"
|
|
#define TELEMETRY_CURRENT_ARGS telemetryData.hub.current / 10, telemetryData.hub.current % 10,
|
|
#define TELEMETRY_VFAS_FORMAT "%d.%d,"
|
|
#define TELEMETRY_VFAS_ARGS telemetryData.hub.vfas / 10, telemetryData.hub.vfas % 10,
|
|
#define TELEMETRY_VSPEED_FORMAT "%c%d.%02d,"
|
|
#define TELEMETRY_VSPEED_ARGS telemetryData.hub.varioSpeed < 0 ? '-' : ' ', abs(telemetryData.hub.varioSpeed / 100), abs(telemetryData.hub.varioSpeed % 100),
|
|
#define TELEMETRY_ASPEED_FORMAT "%d.%d,"
|
|
#define TELEMETRY_ASPEED_ARGS telemetryData.hub.airSpeed / 10, telemetryData.hub.airSpeed % 10,
|
|
#define TELEMETRY_OPENXSENSOR() (0)
|
|
|
|
#define TELEMETRY_CELL_VOLTAGE(k) (telemetryData.hub.cellVolts[k] * TELEMETRY_CELL_VOLTAGE_MUTLIPLIER)
|
|
#define TELEMETRY_MIN_CELL_VOLTAGE (telemetryData.hub.minCellVolts * TELEMETRY_CELL_VOLTAGE_MUTLIPLIER)
|
|
|
|
#define START_STOP 0x7E
|
|
#define BYTESTUFF 0x7D
|
|
#define STUFF_MASK 0x20
|
|
|
|
typedef enum {
|
|
TS_IDLE = 0, // waiting for 0x5e frame marker
|
|
TS_DATA_ID, // waiting for dataID
|
|
TS_DATA_LOW, // waiting for data low byte
|
|
TS_DATA_HIGH, // waiting for data high byte
|
|
TS_XOR = 0x80 // decode stuffed byte
|
|
} TS_STATE;
|
|
|
|
// FrSky D Telemetry Protocol
|
|
void processHubPacket(uint8_t id, int16_t value);
|
|
void frskyDProcessPacket(const uint8_t *packet);
|
|
|
|
// FrSky S.PORT Telemetry Protocol
|
|
void sportProcessTelemetryPacket(const uint8_t * packet);
|
|
void sportProcessTelemetryPacketWithoutCrc(uint8_t origin, const uint8_t * packet);
|
|
|
|
void telemetryWakeup();
|
|
void telemetryReset();
|
|
|
|
extern uint8_t telemetryProtocol;
|
|
void telemetryInit(uint8_t protocol);
|
|
|
|
void telemetryInterrupt10ms();
|
|
|
|
class TelemetryData {
|
|
public:
|
|
TelemetryExpiringDecorator<TelemetryValue> swrInternal;
|
|
TelemetryExpiringDecorator<TelemetryValue> swrExternal;
|
|
TelemetryFilterDecorator<TelemetryValue> rssi;
|
|
uint16_t xjtVersion;
|
|
bool varioHighPrecision;
|
|
|
|
void setSwr(uint8_t module, uint8_t value)
|
|
{
|
|
if (module == 0)
|
|
swrInternal.set(value);
|
|
else
|
|
swrExternal.set(value);
|
|
}
|
|
};
|
|
|
|
extern TelemetryData telemetryData;
|
|
|
|
bool pushFrskyTelemetryData(uint8_t data); // returns true when end of frame detected
|
|
void processFrskyTelemetryData(uint8_t data);
|
|
|
|
#if defined(NO_RAS)
|
|
inline bool isRasValueValid()
|
|
{
|
|
return false;
|
|
}
|
|
#elif defined(PXX2)
|
|
inline bool isRasValueValid()
|
|
{
|
|
return true;
|
|
}
|
|
#elif defined(PCBX10)
|
|
inline bool isRasValueValid()
|
|
{
|
|
return false;
|
|
}
|
|
#elif defined(PCBX9DP) || defined(PCBX9E)
|
|
inline bool isRasValueValid()
|
|
{
|
|
return telemetryData.xjtVersion != 0x0000 && telemetryData.xjtVersion != 0x00ff;
|
|
}
|
|
#else
|
|
inline bool isRasValueValid()
|
|
{
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
constexpr uint8_t FRSKY_BAD_ANTENNA_THRESHOLD = 0x33;
|
|
|
|
#endif // _FRSKY_H_
|