Files
edgetx-gx12/radio/src/pulses/flysky.cpp
T
Raphael CoefficandGitHub 72193eda82 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.
2023-02-09 19:44:32 +10:00

655 lines
20 KiB
C++

/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* 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.
*
* Dedicate for FlySky NV14 board.
*/
#include "opentx.h"
#include "flysky.h"
#include "telemetry/flysky_nv14.h"
#define IS_VALID_COMMAND_ID(id) ((id) < CMD_LAST)
#ifndef custom_log
#define custom_log
#endif
enum AfhdsSpecialChars {
END = 0xC0, //Frame end
START = END,
ESC_END = 0xDC, //Escaped frame end - in case END occurs in fame then ESC ESC_END must be used
ESC = 0xDB, //Escaping character
ESC_ESC = 0xDD, //Escaping character in case ESC occurs in fame then ESC ESC_ESC must be used
};
// 0:OFF, 1:RF frame only, 2:TX frame only, 3:Both RF and TX frame
enum DEBUG_RF_FRAME_PRINT_E {
FRAME_PRINT_OFF = 0,
RF_FRAME_ONLY = 1,
TX_FRAME_ONLY = 2,
BOTH_FRAME_PRINT = 3
};
#define DEBUG_RF_FRAME_PRINT FRAME_PRINT_OFF
//#define DEBUG_RF_FRAME_PRINT BOTH_FRAME_PRINT
#define FLYSKY_MODULE_TIMEOUT 155 /* ms */
#define FLYSKY_PERIOD 4 /*ms*/
#define NUM_OF_NV14_CHANNELS (14)
#define VALID_CH_DATA(v) ((v) > 900 && (v) < 2100)
#define FAILSAVE_SEND_COUNTER_MAX (400)
#define gRomData g_model.moduleData[INTERNAL_MODULE].flysky
#define SET_DIRTY() storageDirty(EE_MODEL)
enum FlySkyBindState_E {
BIND_LOW_POWER,
BIND_NORMAL_POWER,
BIND_EXIT,
};
enum FlySkyRxPulse_E { FLYSKY_PWM, FLYSKY_PPM };
enum FlySkyRxPort_E { FLYSKY_IBUS, FLYSKY_SBUS };
enum FlySkyFirmwareType_E { FLYSKY_RX_FIRMWARE, FLYSKY_RF_FIRMWARE };
enum FlySkyChannelDataType_E {
FLYSKY_CHANNEL_DATA_NORMAL,
FLYSKY_CHANNEL_DATA_FAILSAFE
};
enum FlySkyPulseModeValue_E { PWM_IBUS, PWM_SBUS, PPM_IBUS, PPM_SBUS };
enum FlySkyPulseProtocol_E {
FLYSKY_AFHDS1,
FLYSKY_AFHDS2,
FLYSKY_AFHDS2A,
};
enum FlySkyModuleState_E {
STATE_SET_TX_POWER = 0,
STATE_INIT = 1,
STATE_GET_FW_VERSION_INIT = 2,
STATE_BIND = 3,
STATE_SET_RECEIVER_ID = 4,
STATE_SET_RX_PWM_PPM = 5,
STATE_SET_RX_IBUS_SBUS = 6,
STATE_SET_RX_FREQUENCY = 7,
STATE_UPDATE_RF_FIRMWARE = 8,
STATE_UPDATE_RX_FIRMWARE = 9,
STATE_UPDATE_HALL_FIRMWARE = 10,
STATE_UPDATE_RF_PROTOCOL = 11,
STATE_GET_RECEIVER_CONFIG = 12,
STATE_GET_RX_VERSION_INFO = 13,
STATE_GET_RF_VERSION_INFO = 14,
STATE_SET_RANGE_TEST = 15,
STATE_RANGE_TEST_RUNNING = 16,
STATE_IDLE = 17,
STATE_DISCONNECT = 18,
STATE_SEND_CHANNELS = 19,
};
#define AfhdsPwmMode (gRomData.mode & 2 ? FLYSKY_PPM : FLYSKY_PWM)
#define AfhdsIbusMode (gRomData.mode & 1 ? FLYSKY_SBUS : FLYSKY_IBUS)
struct rf_info_t {
uint8_t bind_power;
uint8_t protocol;
// 0: normal, COMMAND_ID0C_UPDATE_RF_FIRMWARE or CMD_UPDATE_FIRMWARE_END
uint8_t fw_state;
};
static uint8_t lastState = STATE_IDLE;
static uint32_t set_loop_cnt = 0;
static uint8_t _flysky_state;
static uint8_t _flysky_frame_index;
static uint8_t _flysky_crc;
static uint8_t _flysky_timeout;
static uint8_t _esc_state;
uint32_t NV14internalModuleFwVersion = 0;
static rf_info_t rf_info = {
.bind_power = BIND_LOW_POWER,
.protocol = FLYSKY_AFHDS2A, // never updated currently
.fw_state = 0,
};
typedef struct __attribute__((packed)) rxParams {
uint8_t outputMode;
uint8_t outputSerialMode;
uint16_t outputFreq;
} rxParams;
typedef struct __attribute__((packed)) fwVersion {
uint8_t target;
uint32_t version;
} fwVersion;
struct __attribute__((packed)) afhds2Resp {
uint8_t startByte;
uint8_t frame_number;
uint8_t frame_type;
uint8_t command_id;
uint8_t value;
};
uint8_t emptyRxID[] = {0, 0, 0, 0};
void setFlyskyState(uint8_t state);
void onFlySkyBindReceiver();
void onFlySkyModuleSetPower(bool isPowerOn);
void afhds2Command(uint8_t*& p_buf, uint8_t type, uint8_t cmd);
#define END 0xC0
#define ESC 0xDB
#define ESC_END 0xDC
#define ESC_ESC 0xDD
#define FRAME_TYPE_REQUEST_ACK 0x01
#define FRAME_TYPE_REQUEST_NACK 0x02
#define FRAME_TYPE_ANSWER 0x10
enum FlySkyModuleCommandID {
CMD_NONE=0,
CMD_RF_INIT=1,
CMD_BIND=2,
CMD_SET_RECEIVER_ID=3,
CMD_RF_GET_CONFIG=4,
CMD_SEND_CHANNEL_DATA=5,
CMD_RX_SENSOR_DATA=6,
CMD_SET_RX_PWM_PPM=7,
CMD_SET_RX_SERVO_FREQ=8,
CMD_GET_VERSION_INFO=9,
CMD_SET_RX_IBUS_SBUS=0xA,
CMD_SET_RX_IBUS_SERVO_EXT=0xB,
CMD_UPDATE_RF_FIRMWARE = 0x0C,
CMD_SET_TX_POWER = 0x0D,
CMD_SET_RF_PROTOCOL,
CMD_TEST_RANGE,
CMD_TEST_RF_RESERVED,
CMD_UPDATE_RX_FIRMWARE = 0x20,
CMD_LAST
};
void setFlyskyState(uint8_t state)
{
_flysky_state = state;
}
inline void initFlySkyCRC()
{
_flysky_crc = 0;
}
inline void putFlySkyByte(uint8_t*& p_buf, uint8_t byte)
{
if (END == byte) {
*p_buf++ = ESC;
*p_buf++ = ESC_END;
} else if (ESC == byte) {
*p_buf++ = ESC;
*p_buf++ = ESC_ESC;
} else {
*p_buf++ = byte;
}
}
inline void putFlySkyFrameByte(uint8_t*& p_buf, uint8_t byte)
{
_flysky_crc += byte;
putFlySkyByte(p_buf, byte);
}
inline void putFlySkyFrameCmd(uint8_t*& p_buf, uint8_t type, uint8_t cmd)
{
_flysky_crc += type + cmd;
putFlySkyByte(p_buf, type);
putFlySkyByte(p_buf, cmd);
}
inline void putFlySkyFrameBytes(uint8_t*& p_buf, uint8_t* data, int length)
{
for (int i = 0; i < length; i++) {
_flysky_crc += data[i];
putFlySkyByte(p_buf, data[i]);
}
}
inline void putFlySkyFrameHeader(uint8_t*& p_buf)
{
initFlySkyCRC();
*p_buf++ = END;
putFlySkyFrameByte(p_buf, _flysky_frame_index);
}
inline void putFlySkyFrameFooter(uint8_t*& p_buf)
{
if (++_flysky_frame_index == 0) {
_flysky_frame_index = 1;
}
putFlySkyByte(p_buf, _flysky_crc ^ 0xff);
*p_buf++ = END;
}
void afhds2Command(uint8_t*& p_buf, uint8_t type, uint8_t cmd)
{
putFlySkyFrameHeader(p_buf);
putFlySkyFrameCmd(p_buf, type, cmd);
putFlySkyFrameFooter(p_buf);
}
inline void putFlySkySendChannelData(uint8_t*& p_buf)
{
uint16_t pulseValue = 0;
uint8_t channels_start = g_model.moduleData[INTERNAL_MODULE].channelsStart;
uint8_t channels_last =
channels_start + 8 + g_model.moduleData[INTERNAL_MODULE].channelsCount;
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_NACK, CMD_SEND_CHANNEL_DATA);
if (moduleState[INTERNAL_MODULE].counter-- == 0) {
moduleState[INTERNAL_MODULE].counter = FAILSAVE_SEND_COUNTER_MAX;
putFlySkyFrameByte(p_buf, FLYSKY_CHANNEL_DATA_FAILSAFE);
putFlySkyFrameByte(p_buf, channels_last - channels_start);
for (uint8_t channel = channels_start; channel < channels_last; channel++) {
if (g_model.moduleData[INTERNAL_MODULE].failsafeMode == FAILSAFE_CUSTOM) {
int16_t failsafeValue = g_model.failsafeChannels[channel];
pulseValue =
limit<uint16_t>(0, 988 + ((failsafeValue + 1024) / 2), 0xfff);
} else if (g_model.moduleData[INTERNAL_MODULE].failsafeMode ==
FAILSAFE_HOLD) {
// protocol uses hold by default
pulseValue = 0xfff;
} else {
int16_t failsafeValue =
-1024 + 2 * PPM_CH_CENTER(channel) - 2 * PPM_CENTER;
pulseValue =
limit<uint16_t>(0, 988 + ((failsafeValue + 1024) / 2), 0xfff);
}
putFlySkyFrameByte(p_buf, pulseValue & 0xff);
putFlySkyFrameByte(p_buf, pulseValue >> 8);
}
if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY) {
TRACE("------FAILSAFE------");
}
} else {
putFlySkyFrameByte(p_buf, FLYSKY_CHANNEL_DATA_NORMAL);
putFlySkyFrameByte(p_buf, channels_last - channels_start);
for (uint8_t channel = channels_start; channel < channels_last; channel++) {
int channelValue =
channelOutputs[channel] + 2 * PPM_CH_CENTER(channel) - 2 * PPM_CENTER;
pulseValue = limit<uint16_t>(0, 988 + ((channelValue + 1024) / 2), 0xfff);
putFlySkyFrameByte(p_buf, pulseValue & 0xff);
putFlySkyFrameByte(p_buf, pulseValue >> 8);
}
}
}
void putFlySkyUpdateFirmwareStart(uint8_t*& p_buf, uint8_t cmd)
{
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, cmd);
}
bool checkFlySkyFrameCrc(const uint8_t* ptr, uint8_t size)
{
uint8_t crc = 0;
for (uint8_t i = 0; i < size; i++) {
crc += ptr[i];
}
if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY) {
if (ptr[2] != 0x06 || (set_loop_cnt++ % 50 == 0)) {
TRACE_NOCRLF("RF(%0d): C0", INTMODULE_USART_AFHDS2_BAUDRATE);
for (int idx = 0; idx <= size; idx++) {
TRACE_NOCRLF(" %02X", ptr[idx]);
}
TRACE_NOCRLF(" C0;" CRLF);
if ((crc ^ 0xff) != ptr[size]) {
TRACE("ErrorCRC %02X especting %02X", crc ^ 0xFF, ptr[size]);
}
}
}
return (crc ^ 0xff) == ptr[size];
}
inline void debugFrame(const uint8_t* rxBuffer, uint8_t rxBufferCount)
{
// debug print the content of the packet
char buffer[64 * 3];
char* pos = buffer;
if (rxBufferCount * 3 > sizeof(buffer)) rxBufferCount = 64;
for (int i = 0; i < rxBufferCount; i++) {
pos += snprintf(pos, buffer + sizeof(buffer) - pos, "%02X ", rxBuffer[i]);
}
(*pos) = 0;
TRACE("count [%d] data: %s", rxBufferCount, buffer);
}
inline void parseResponse(uint8_t* buffer, uint8_t dataLen)
{
afhds2Resp* resp = reinterpret_cast<afhds2Resp*>(buffer);
if (resp->startByte != END || dataLen < 2) return;
dataLen -= 2;
if (!checkFlySkyFrameCrc(buffer + 1, dataLen)) {
return;
}
if ((moduleState[INTERNAL_MODULE].mode != MODULE_MODE_BIND) &&
(resp->frame_type == FRAME_TYPE_ANSWER) &&
((_flysky_frame_index - 1) != resp->frame_number)) {
return;
} else if (resp->frame_type == FRAME_TYPE_REQUEST_ACK) {
_flysky_frame_index = resp->frame_number;
}
debugFrame(&resp->command_id, dataLen - 2);
switch (resp->command_id) {
default:
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_NORMAL &&
_flysky_state >= STATE_IDLE) {
setFlyskyState(STATE_SEND_CHANNELS);
if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY)
TRACE("State back to channel data");
}
break;
case CMD_RF_INIT:
if (resp->value == 0x01) { // action only RF ready
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_BIND)
setFlyskyState(STATE_BIND);
else
setFlyskyState(STATE_GET_FW_VERSION_INIT); // get version first
} else {
// Try one more time;
resetPulsesAFHDS2();
setFlyskyState(STATE_INIT);
}
break;
case CMD_BIND: {
if (resp->frame_type != FRAME_TYPE_ANSWER) {
setFlyskyState(STATE_IDLE);
return;
}
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_BIND)
moduleState[INTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
*((uint32_t*)gRomData.rx_id) =
*(reinterpret_cast<const uint32_t*>(&resp->value));
g_model.header.modelId[INTERNAL_MODULE] = gRomData.rx_id[3];
if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY)
TRACE("New Rx ID: %02X %02X %02X %02X", gRomData.rx_id[0],
gRomData.rx_id[1], gRomData.rx_id[2], gRomData.rx_id[3]);
SET_DIRTY();
resetPulsesAFHDS2();
setFlyskyState(STATE_INIT);
break;
}
case CMD_RF_GET_CONFIG:
setFlyskyState(STATE_GET_RECEIVER_CONFIG);
_flysky_timeout = FLYSKY_MODULE_TIMEOUT;
break;
case CMD_RX_SENSOR_DATA:
flySkyNv14ProcessTelemetryPacket(&resp->value, dataLen - 3);
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_NORMAL &&
_flysky_state >= STATE_IDLE) {
setFlyskyState(STATE_SEND_CHANNELS);
}
break;
case CMD_SET_RECEIVER_ID: {
// range check seems to be not working
// it disconnects receiver
// if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_RANGECHECK) {
// setFlyskyState(STATE_SET_RANGE_TEST);
//}
// else
setFlyskyState(STATE_SEND_CHANNELS);
return;
}
case CMD_TEST_RANGE:
if (moduleState[INTERNAL_MODULE].mode != MODULE_MODE_RANGECHECK)
resetPulsesAFHDS2();
else
setFlyskyState(STATE_RANGE_TEST_RUNNING);
break;
case CMD_SET_TX_POWER:
setFlyskyState(STATE_INIT);
break;
case CMD_SET_RX_PWM_PPM:
setFlyskyState(STATE_SET_RX_IBUS_SBUS);
break;
case CMD_SET_RX_IBUS_SBUS:
setFlyskyState(STATE_SET_RX_FREQUENCY);
break;
case CMD_SET_RX_SERVO_FREQ:
setFlyskyState(STATE_SEND_CHANNELS);
break;
case CMD_UPDATE_RF_FIRMWARE: {
rf_info.fw_state = STATE_UPDATE_RF_FIRMWARE;
setFlyskyState(STATE_IDLE);
break;
}
case CMD_GET_VERSION_INFO: {
if (_flysky_state == STATE_GET_FW_VERSION_INIT) {
memcpy(&NV14internalModuleFwVersion, &resp->value + 1,
sizeof(NV14internalModuleFwVersion));
setFlyskyState(STATE_SET_RECEIVER_ID);
break;
}
// if (dataLen > 4) {
// usbSetFrameTransmit(0x08, (uint8_t*) &resp->value + 1, dataLen - 4);
// }
if (lastState == STATE_GET_RF_VERSION_INFO ||
lastState == STATE_GET_RX_VERSION_INFO) {
lastState = STATE_INIT;
}
setFlyskyState(lastState);
break;
}
}
}
void processInternalFlySkyTelemetryData(uint8_t byte, uint8_t* buffer, uint8_t* len)
{
if (byte == END && *len > 0) {
parseResponse(buffer, *len);
*len = 0;
} else {
if (byte == ESC) {
_esc_state = 1;
} else {
if (_esc_state) {
_esc_state = 0;
if (byte == ESC_END)
byte = END;
else if (byte == ESC_ESC)
byte = ESC;
}
buffer[(*len)++] = byte;
if (*len >= TELEMETRY_RX_PACKET_SIZE) {
// TODO buffer is full, log an error?
*len = 0;
}
}
}
}
void resetPulsesAFHDS2()
{
NV14internalModuleFwVersion = 0;
_flysky_frame_index = 1;
setFlyskyState(STATE_SET_TX_POWER);
_flysky_timeout = 0;
_esc_state = 0;
uint16_t rx_freq = gRomData.rx_freq[0];
rx_freq += (gRomData.rx_freq[1] * 256);
if (50 > rx_freq || 400 < rx_freq) {
gRomData.rx_freq[0] = 50;
}
}
void setupPulsesAFHDS2(uint8_t*& p_buf)
{
auto buffer_start = p_buf;
putFlySkyFrameHeader(p_buf);
if (_flysky_state == STATE_DISCONNECT) {
TRACE("STATE_DISCONNECT");
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_SET_RECEIVER_ID);
putFlySkyFrameBytes(p_buf, emptyRxID, 4);
} else if (_flysky_state < STATE_SEND_CHANNELS) {
if (++_flysky_timeout >=
FLYSKY_MODULE_TIMEOUT / FLYSKY_PERIOD) {
_flysky_timeout = 0;
switch (_flysky_state) {
case STATE_INIT: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_RF_INIT);
} break;
case STATE_BIND: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_BIND);
putFlySkyFrameByte(p_buf, rf_info.bind_power);
uint32_t txID =
0; // internal module firmware does not allow changing TX id
putFlySkyFrameBytes(p_buf, (uint8_t*)(&txID), 4);
} break;
case STATE_SET_RECEIVER_ID: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_SET_RECEIVER_ID);
putFlySkyFrameBytes(p_buf, gRomData.rx_id, 4);
} break;
case STATE_GET_RECEIVER_CONFIG: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_ANSWER, CMD_RF_GET_CONFIG);
putFlySkyFrameByte(p_buf, AfhdsPwmMode); // 00:PWM, 01:PPM
putFlySkyFrameByte(p_buf, AfhdsIbusMode); // 00:I-BUS, 01:S-BUS
putFlySkyFrameByte(p_buf,
gRomData.rx_freq[0] < 50
? 50
: gRomData.rx_freq[0]); // receiver servo freq bit[7:0]
putFlySkyFrameByte(p_buf,
gRomData.rx_freq[1]); // receiver servo freq bit[15:8]
setFlyskyState(STATE_INIT);
} break;
case STATE_SET_TX_POWER: {
uint8_t power =
moduleState[INTERNAL_MODULE].mode == MODULE_MODE_RANGECHECK ? 0
: gRomData.rfPower ? 170
: 90;
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_SET_TX_POWER);
putFlySkyFrameByte(p_buf, power);
} break;
case STATE_SET_RANGE_TEST: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_TEST_RANGE);
putFlySkyFrameByte(p_buf, moduleState[INTERNAL_MODULE].mode ==
MODULE_MODE_RANGECHECK);
} break;
case STATE_RANGE_TEST_RUNNING: {
if (moduleState[INTERNAL_MODULE].mode != MODULE_MODE_RANGECHECK) {
// this will send stop command
setFlyskyState(STATE_SET_RANGE_TEST);
}
} break;
case STATE_SET_RX_PWM_PPM: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_SET_RX_PWM_PPM);
putFlySkyFrameByte(p_buf, AfhdsPwmMode); // 00:PWM, 01:PPM
} break;
case STATE_SET_RX_IBUS_SBUS: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_SET_RX_IBUS_SBUS);
putFlySkyFrameByte(p_buf, AfhdsIbusMode); // 0x00:I-BUS, 0x01:S-BUS
} break;
case STATE_SET_RX_FREQUENCY: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_SET_RX_SERVO_FREQ);
putFlySkyFrameBytes(p_buf, gRomData.rx_freq, 2);
} break;
case STATE_UPDATE_RF_PROTOCOL: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_SET_RF_PROTOCOL);
putFlySkyFrameByte(p_buf,
rf_info.protocol); // 0x00:AFHDS1 0x01:AFHDS2 0x02:AFHDS2A
} break;
case STATE_UPDATE_RX_FIRMWARE: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_UPDATE_RX_FIRMWARE);
} break;
case STATE_UPDATE_RF_FIRMWARE: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_UPDATE_RF_FIRMWARE);
} break;
case STATE_GET_RX_VERSION_INFO: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_GET_VERSION_INFO);
putFlySkyFrameByte(p_buf, FLYSKY_RX_FIRMWARE);
} break;
case STATE_GET_FW_VERSION_INIT:
case STATE_GET_RF_VERSION_INFO: {
putFlySkyFrameCmd(p_buf, FRAME_TYPE_REQUEST_ACK, CMD_GET_VERSION_INFO);
putFlySkyFrameByte(p_buf, FLYSKY_RF_FIRMWARE);
} break;
case STATE_IDLE:
initFlySkyCRC();
break;
default:
setFlyskyState(STATE_INIT);
initFlySkyCRC();
if ((DEBUG_RF_FRAME_PRINT & TX_FRAME_ONLY)) {
TRACE("State back to INIT\r\n");
}
return;
}
} else {
initFlySkyCRC();
return;
}
} else {
if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_BIND)
moduleState[INTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
putFlySkySendChannelData(p_buf);
}
putFlySkyFrameFooter(p_buf);
if (_flysky_state < STATE_SEND_CHANNELS) {
// uint8_t size = p_buf - buffer_start;
// debugFrame(buffer_start, size);
}
if ((DEBUG_RF_FRAME_PRINT & TX_FRAME_ONLY)) {
/* print each command, except channel data by interval */
uint8_t* data = buffer_start;
if (data[3] != CMD_SEND_CHANNEL_DATA || (set_loop_cnt++ % 100 == 0)) {
uint8_t size = p_buf - data;
TRACE_NOCRLF("TX(State%0d)%0dB:", _flysky_state, size);
for (int idx = 0; idx < size; idx++) {
TRACE_NOCRLF(" %02X", data[idx]);
}
TRACE_NOCRLF(";" CRLF);
}
}
}
// void usbDownloadTransmit(uint8_t *buffer, uint32_t size)
// {
// if (USB_SERIAL_MODE != getSelectedUsbMode()) return;
// buffer[0] = HALL_PROTOLO_HEAD;
// for (uint32_t idx = 0; idx < size; idx++)
// {
// #if !defined(SIMU)
// usbSerialPutc(buffer[idx]);
// #endif
// }
// }