Files
edgetx-gx12/radio/src/pulses/pxx2.h
T
WismyYaoandGitHub 629f98a930 Wismy/frsky new receivers (#7449)
Add internal module OTA
Change virtual keys for X-Lite(S) Lua scripts
2020-03-24 15:15:10 +01:00

468 lines
10 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 _PULSES_PXX2_H_
#define _PULSES_PXX2_H_
#include "fifo.h"
#include "io/frsky_pxx2.h"
#include "./pxx.h"
#define PXX2_TYPE_C_MODULE 0x01
#define PXX2_TYPE_ID_REGISTER 0x01
#define PXX2_TYPE_ID_BIND 0x02
#define PXX2_TYPE_ID_CHANNELS 0x03
#define PXX2_TYPE_ID_TX_SETTINGS 0x04
#define PXX2_TYPE_ID_RX_SETTINGS 0x05
#define PXX2_TYPE_ID_HW_INFO 0x06
#define PXX2_TYPE_ID_SHARE 0x07
#define PXX2_TYPE_ID_RESET 0x08
#define PXX2_TYPE_ID_AUTHENTICATION 0x09
#define PXX2_TYPE_ID_TELEMETRY 0xFE
#define PXX2_TYPE_C_POWER_METER 0x02
#define PXX2_TYPE_ID_POWER_METER 0x01
#define PXX2_TYPE_ID_SPECTRUM 0x02
#define PXX2_TYPE_C_OTA 0xFE
#define PXX2_TYPE_ID_OTA 0x02
#define PXX2_CHANNELS_FLAG0_FAILSAFE (1 << 6)
#define PXX2_CHANNELS_FLAG0_RANGECHECK (1 << 7)
#define PXX2_RX_SETTINGS_FLAG0_WRITE (1 << 6)
#define PXX2_RX_SETTINGS_FLAG1_TELEMETRY_DISABLED (1 << 7)
#define PXX2_RX_SETTINGS_FLAG1_READONLY (1 << 6)
#define PXX2_RX_SETTINGS_FLAG1_FASTPWM (1 << 4)
#define PXX2_RX_SETTINGS_FLAG1_FPORT (1 << 3)
#define PXX2_RX_SETTINGS_FLAG1_TELEMETRY_25MW (1 << 2)
#define PXX2_RX_SETTINGS_FLAG1_ENABLE_PWM_CH5_CH6 (1 << 1)
#define PXX2_TX_SETTINGS_FLAG0_WRITE (1 << 6)
#define PXX2_TX_SETTINGS_FLAG1_EXTERNAL_ANTENNA (1 << 3)
#define PXX2_HW_INFO_TX_ID 0xFF
#if defined(COLORLCD)
#define SPECTRUM_ANALYSER_POWER_FLOOR -120 /*dBm*/
#else
#define SPECTRUM_ANALYSER_POWER_FLOOR -120 /*dBm*/
#endif
#define PXX2_AUTH_REFUSED_FLAG 0xA5
enum PXX2ModuleModelID {
PXX2_MODULE_NONE,
PXX2_MODULE_XJT,
PXX2_MODULE_ISRM,
PXX2_MODULE_ISRM_PRO,
PXX2_MODULE_ISRM_S,
PXX2_MODULE_R9M,
PXX2_MODULE_R9M_LITE,
PXX2_MODULE_R9M_LITE_PRO,
PXX2_MODULE_ISRM_N,
PXX2_MODULE_ISRM_S_X9,
PXX2_MODULE_ISRM_S_X10E,
PXX2_MODULE_XJT_LITE,
PXX2_MODULE_ISRM_S_X10S,
PXX2_MODULE_ISRM_X9LITES,
};
static const char * const PXX2ModulesNames[] = {
"---",
"XJT",
"ISRM",
"ISRM-PRO",
"ISRM-S",
"R9M",
"R9MLite",
"R9MLite-PRO",
"ISRM-N",
"ISRM-S-X9",
"ISRM-S-X10E",
"XJT Lite",
"ISRM-S-X10S",
"ISRM-X9LiteS"
};
inline const char * getPXX2ModuleName(uint8_t modelId)
{
if (modelId < DIM(PXX2ModulesNames))
return PXX2ModulesNames[modelId];
else
return PXX2ModulesNames[0];
}
enum {
MODULE_OPTION_EXTERNAL_ANTENNA,
MODULE_OPTION_POWER,
MODULE_OPTION_SPECTRUM_ANALYSER,
MODULE_OPTION_POWER_METER,
};
/* Module options order:
* - External antenna (0x01)
* - Power (0x02)
* - Spektrum analyser (0x04)
* - Power meter (0x08)
*/
static const uint8_t PXX2ModuleOptions[] = {
#if defined(SIMU)
0b11111111, // None = display all options on SIMU
#else
0b00000000, // None = no option available on unknown modules
#endif
0b00000001, // XJT
0b00000001, // ISRM
0b00001101, // ISRM-PRO
0b00000101, // ISRM-S
0b00000010, // R9M
0b00000010, // R9MLite
0b00000110, // R9MLite-PRO
0b00000100, // ISRM-N
0b00000100, // ISRM-S-X9
0b00000101, // ISRM-S-X10E
0b00000001, // XJT_LITE
0b00000101, // ISRM-S-X10S
0b00000100, // ISRM-X9LITES
};
inline uint8_t getPXX2ModuleOptions(uint8_t modelId)
{
if (modelId < DIM(PXX2ModuleOptions))
return PXX2ModuleOptions[modelId];
else
return PXX2ModuleOptions[0];
}
inline bool isPXX2ModuleOptionAvailable(uint8_t modelId, uint8_t option)
{
return getPXX2ModuleOptions(modelId) & (1 << option);
}
enum ModuleCapabilities {
MODULE_CAPABILITY_COUNT
};
static const char * const PXX2ReceiversNames[] = {
"---",
"X8R",
"RX8R",
"RX8R-PRO",
"RX6R",
"RX4R",
"G-RX8",
"G-RX6",
"X6R",
"X4R",
"X4R-SB",
"XSR",
"XSR-M",
"RXSR",
"S6R",
"S8R",
"XM",
"XM+",
"XMR",
"R9",
"R9-SLIM",
"R9-SLIM+",
"R9-MINI",
"R9-MM",
"R9-STAB", // R9-STAB has OTA
"R9-MINI-OTA", // this one has OTA (different bootloader)
"R9-MM-OTA", // this one has OTA (different bootloader)
"R9-SLIM+-OTA", // this one has OTA (different bootloader)
"Archer-X", // this one has OTA (internal module)
"R9MX", // this one has OTA
"R9SX", // this one has OTA
};
inline const char * getPXX2ReceiverName(uint8_t modelId)
{
if (modelId < DIM(PXX2ReceiversNames))
return PXX2ReceiversNames[modelId];
else
return PXX2ReceiversNames[0];
}
enum {
RECEIVER_OPTION_OTA,
};
/* Receiver options order:
* - OTA (0x01)
*/
static const uint8_t PXX2ReceiverOptions[] = {
#if defined(SIMU)
0b11111111, // None = display all options on SIMU
#else
0b00000000, // None = display all options on SIMU
#endif
0b11111110, // X8R
0b11111110, // RX8R
0b11111110, // RX8R-PRO
0b11111110, // RX6R
0b11111110, // RX4R
0b11111110, // G-RX8
0b11111110, // G-RX6
0b11111110, // X6R
0b11111110, // X4R
0b11111110, // X4R-SB
0b11111110, // XSR
0b11111110, // XSR-M
0b11111110, // RXSR
0b11111110, // S6R
0b11111110, // S8R
0b11111110, // XM
0b11111110, // XM+
0b11111110, // XMR
0b11111110, // R9
0b11111110, // R9-SLIM
0b11111110, // R9-SLIM+
0b11111110, // R9-MINI
0b11111110, // R9-MM
0b11111111, // R9-STAB+OTA
0b11111111, // R9-MINI+OTA
0b11111111, // R9-MM+OTA
0b11111111, // R9-SLIM+OTA
0b11111111, // ARCHER-X
0b11111111, // R9MX
0b11111111, // R9SX
};
inline uint8_t getPXX2ReceiverOptions(uint8_t modelId)
{
if (modelId < DIM(PXX2ReceiverOptions))
return PXX2ReceiverOptions[modelId];
else
return PXX2ReceiverOptions[0];
}
inline bool isPXX2ReceiverOptionAvailable(uint8_t modelId, uint8_t option)
{
return getPXX2ReceiverOptions(modelId) & (1 << option);
}
enum ReceiverCapabilities {
RECEIVER_CAPABILITY_FPORT,
RECEIVER_CAPABILITY_TELEMETRY_25MW,
RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6,
RECEIVER_CAPABILITY_COUNT
};
enum PXX2Variant {
PXX2_VARIANT_NONE,
PXX2_VARIANT_FCC,
PXX2_VARIANT_EU,
PXX2_VARIANT_FLEX
};
enum PXX2RegisterSteps {
REGISTER_INIT,
REGISTER_RX_NAME_RECEIVED,
REGISTER_RX_NAME_SELECTED,
REGISTER_OK
};
enum PXX2BindSteps {
BIND_MODULE_TX_INFORMATION_REQUEST = -2,
BIND_MODULE_TX_SETTINGS_REQUEST = -1,
BIND_INIT,
BIND_RX_NAME_SELECTED,
BIND_INFO_REQUEST,
BIND_START,
BIND_WAIT,
BIND_OK
};
enum PXX2OtaUpdateSteps {
OTA_UPDATE_START = BIND_OK + 1,
OTA_UPDATE_START_ACK,
OTA_UPDATE_TRANSFER,
OTA_UPDATE_TRANSFER_ACK,
OTA_UPDATE_EOF,
OTA_UPDATE_EOF_ACK
};
enum PXX2ReceiverStatus {
PXX2_HARDWARE_INFO,
PXX2_SETTINGS_READ,
PXX2_SETTINGS_WRITE,
PXX2_SETTINGS_OK
};
extern ModuleFifo intmoduleFifo;
extern ModuleFifo extmoduleFifo;
class Pxx2CrcMixin {
protected:
void initCrc()
{
crc = 0xFFFF;
}
void addToCrc(uint8_t byte)
{
crc -= byte;
}
uint16_t crc;
};
class Pxx2Transport: public DataBuffer<uint8_t, 64>, public Pxx2CrcMixin {
protected:
void addWord(uint32_t word)
{
addByte(word);
addByte(word >> 8);
addByte(word >> 16);
addByte(word >> 24);
}
void addByte(uint8_t byte)
{
Pxx2CrcMixin::addToCrc(byte);
addByteWithoutCrc(byte);
};
void addByteWithoutCrc(uint8_t byte)
{
*ptr++ = byte;
}
};
class Pxx2Pulses: public Pxx2Transport {
friend class Pxx2OtaUpdate;
public:
bool setupFrame(uint8_t module);
void setupAuthenticationFrame(uint8_t module, uint8_t mode, const uint8_t * outputMessage);
protected:
void setupHardwareInfoFrame(uint8_t module);
void setupRegisterFrame(uint8_t module);
void setupAccstBindFrame(uint8_t module);
void setupAccessBindFrame(uint8_t module);
void setupResetFrame(uint8_t module);
void setupShareMode(uint8_t module);
void setupModuleSettingsFrame(uint8_t module);
void setupReceiverSettingsFrame(uint8_t module);
void setupChannelsFrame(uint8_t module);
void setupTelemetryFrame(uint8_t module);
void setupSpectrumAnalyser(uint8_t module);
void setupPowerMeter(uint8_t module);
void sendOtaUpdate(uint8_t module, const char * rxName, uint32_t address, const char * data);
void addHead()
{
// send 7E, do not CRC
Pxx2Transport::addByteWithoutCrc(0x7E);
// reserve 1 byte for LEN
Pxx2Transport::addByteWithoutCrc(0x00);
}
void addFrameType(uint8_t type_c, uint8_t type_id)
{
// TYPE_C + TYPE_ID
Pxx2Transport::addByte(type_c);
Pxx2Transport::addByte(type_id);
}
uint8_t addFlag0(uint8_t module);
void addFlag1(uint8_t module);
void addPulsesValues(uint16_t low, uint16_t high);
void addChannels(uint8_t module);
void addFailsafe(uint8_t module);
void addCrc()
{
Pxx2Transport::addByteWithoutCrc(Pxx2CrcMixin::crc >> 8);
Pxx2Transport::addByteWithoutCrc(Pxx2CrcMixin::crc);
}
void initFrame()
{
// init the CRC counter
initCrc();
// reset the frame pointer
Pxx2Transport::initBuffer();
// add the frame head
addHead();
}
void endFrame()
{
uint8_t size = getSize() - 2;
if (size > 0) {
// update the frame LEN = frame length minus the 2 first bytes
data[1] = getSize() - 2;
// now add the CRC
addCrc();
}
else {
Pxx2Transport::initBuffer();
}
}
};
class Pxx2OtaUpdate {
public:
Pxx2OtaUpdate(uint8_t module, const char * rxName):
module(module),
rxName(rxName)
{
}
void flashFirmware(const char * filename);
protected:
uint8_t module;
const char * rxName;
const char * doFlashFirmware(const char * filename);
bool waitStep(uint8_t step, uint8_t timeout);
const char * nextStep(uint8_t step, const char * rxName, uint32_t address, const uint8_t * buffer);
};
#endif