diff --git a/radio/src/pulses/afhds3.cpp b/radio/src/pulses/afhds3.cpp index 027811cea..dd6c210f1 100644 --- a/radio/src/pulses/afhds3.cpp +++ b/radio/src/pulses/afhds3.cpp @@ -20,11 +20,13 @@ */ #include "afhds3.h" +#include "afhds3_transport.h" +#include "pulses.h" + #include "../debug.h" #include "../definitions.h" -#include +// #include -#include "pulses.h" #include "telemetry/telemetry.h" #include "mixer_scheduler.h" #include "hal/module_driver.h" @@ -44,8 +46,6 @@ #define FAILSAFE_KEEP_LAST 0x8000 -#define MAX_RETRIES_AFHDS3 5 - //get channel value outside of afhds3 namespace int32_t getChannelValue(uint8_t channel); @@ -62,52 +62,6 @@ static uint8_t _phyMode_channels[] = { 12, // ROUTINE_LORA_12CH }; -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 -}; - -enum DeviceAddress -{ - TRANSMITTER = 0x01, - // MODULE = 0x03, - MODULE = 0x05, -}; - -enum FRAME_TYPE: uint8_t -{ - REQUEST_GET_DATA = 0x01, //Get data response: ACK + DATA - REQUEST_SET_EXPECT_DATA = 0x02, //Set data response: ACK + DATA - REQUEST_SET_EXPECT_ACK = 0x03, //Set data response: ACK - REQUEST_SET_NO_RESP = 0x05, //Set data response: none - RESPONSE_DATA = 0x10, //Response ACK + DATA - RESPONSE_ACK = 0x20, //Response ACK - NOT_USED = 0xff -}; - -enum COMMAND: uint8_t -{ - MODULE_READY = 0x01, - MODULE_STATE = 0x02, - MODULE_MODE = 0x03, - MODULE_SET_CONFIG = 0x04, - MODULE_GET_CONFIG = 0x06, - CHANNELS_FAILSAFE_DATA = 0x07, - TELEMETRY_DATA = 0x09, - SEND_COMMAND = 0x0C, - COMMAND_RESULT = 0x0D, - // MODULE_POWER_STATUS = 0x0F, - // MODULE_VERSION = 0x1F, - MODULE_VERSION = 0x20, - VIRTUAL_FAILSAFE = 0x99, // virtual command used to trigger failsafe - UNDEFINED = 0xFF -}; - enum COMMAND_DIRECTION { RADIO_TO_MODULE = 0, @@ -356,82 +310,9 @@ union AfhdsFrameData CommandResult_s CommandResult; }; -PACK(struct AfhdsFrame -{ - uint8_t startByte; - uint8_t address; - uint8_t frameNumber; - uint8_t frameType; - uint8_t command; - uint8_t value; - - AfhdsFrameData * GetData() - { - return reinterpret_cast(&value); - } -}); - #define FRM302_STATUS 0x56 -enum State -{ - UNKNOWN = 0, - SENDING_COMMAND, - AWAITING_RESPONSE, - IDLE -}; - -// one byte frames for request queue -struct Frame -{ - enum COMMAND command; - enum FRAME_TYPE frameType; - uint8_t payload; - uint8_t frameNumber; - bool useFrameNumber; - uint8_t payloadSize; -}; - -// simple fifo implementation because Pulses is used as member of union and can not be non trivial type -struct CommandFifo -{ - Frame commandFifo[8]; - volatile uint32_t setIndex; - volatile uint32_t getIndex; - - void clearCommandFifo(); - - inline uint32_t nextIndex(uint32_t idx) const - { - return (idx + 1) & (sizeof(commandFifo) / sizeof(commandFifo[0]) - 1); - } - - inline uint32_t prevIndex(uint32_t idx) const - { - if (idx == 0) - { - return (sizeof(commandFifo) / sizeof(commandFifo[0]) - 1); - } - return (idx - 1); - } - - inline bool isEmpty() const - { - return (getIndex == setIndex); - } - - inline void skip() - { - getIndex = nextIndex(getIndex); - } - - void enqueueACK(COMMAND command, uint8_t frameNumber); - - void enqueue(COMMAND command, FRAME_TYPE frameType, bool useData = false, uint8_t byteContent = 0); - -}; - -class ProtoState: public CommandFifo +class ProtoState { public: /** @@ -474,15 +355,9 @@ class ProtoState: public CommandFifo private: - inline void sendByte(uint8_t b); - - inline void putBytes(uint8_t* data, int length); - - inline void putFrame(COMMAND command, FRAME_TYPE frameType, uint8_t* data = nullptr, uint8_t dataLength = 0, uint8_t* frame_index = nullptr); - void parseData(uint8_t* rxBuffer, uint8_t rxBufferCount); - void setState(uint8_t state); + void setState(ModuleState state); bool syncSettings(); @@ -513,47 +388,43 @@ class ProtoState: public CommandFifo bool isConnectedMulticast(); Transport trsp; - void* trsp_buffer; - uint8_t frame_index; - uint8_t crc; - uint8_t state; - uint8_t timeout; - uint8_t esc_state; /** * Index of the module */ uint8_t module_index; + + /** + * Reported state of the HF module + */ + ModuleState state; + /** * Target mode to be set to the module one of MODULE_MODE_E */ uint8_t requestedModuleMode; - /** - * Internal operation state one of UNKNOWN, SENDING_COMMAND, AWAITING_RESPONSE, IDLE - * Used to avoid sending commands when not allowed to - */ - State operationState; - /** - * Actual repeat count for requested command/operation - incremented by every attempt sending anything - */ - uint16_t repeatCount; + /** * Command count used for counting actual number of commands sent in run mode */ uint32_t cmdCount; + /** * Command index of command to be send when cmdCount reached necessary value */ uint32_t cmdIndex; + /** * Actual power source of the module - should be requested time to time * Currently requested once */ enum MODULE_POWER_SOURCE powerSource; + /** * Pointer to module config - it is making operations easier and faster */ ModuleData* moduleData; + /** * Actual module configuration - must be requested from module */ @@ -597,9 +468,6 @@ static const COMMAND periodicRequestCommands[] = COMMAND::VIRTUAL_FAILSAFE }; -//Address used in transmitted frames - it constrains of target address and source address -const uint8_t FrameAddress = DeviceAddress::TRANSMITTER | (DeviceAddress::MODULE << 4); - //Static collection of afhds3 object instances by module static ProtoState protoState[NUM_MODULES]; @@ -630,40 +498,6 @@ void processTelemetryData(uint8_t data, uint8_t module) maxSize); } -void CommandFifo::clearCommandFifo() -{ - memclear(commandFifo, sizeof(commandFifo)); - setIndex = getIndex = 0; -} - -void CommandFifo::enqueueACK(COMMAND command, uint8_t frameNumber) -{ - uint32_t next = nextIndex(setIndex); - if (next != getIndex) { - commandFifo[setIndex].command = command; - commandFifo[setIndex].frameType = FRAME_TYPE::RESPONSE_ACK; - commandFifo[setIndex].payload = 0; - commandFifo[setIndex].payloadSize = 0; - commandFifo[setIndex].frameNumber = frameNumber; - commandFifo[setIndex].useFrameNumber = true; - setIndex = next; - } -} - -void CommandFifo::enqueue(COMMAND command, FRAME_TYPE frameType, bool useData, uint8_t byteContent) -{ - uint32_t next = nextIndex(setIndex); - if (next != getIndex) { - commandFifo[setIndex].command = command; - commandFifo[setIndex].frameType = frameType; - commandFifo[setIndex].payload = byteContent; - commandFifo[setIndex].payloadSize = useData ? 1 : 0; - commandFifo[setIndex].frameNumber = 0; - commandFifo[setIndex].useFrameNumber = false; - setIndex = next; - } -} - void ProtoState::getStatusString(char* buffer) const { strcpy(buffer, state <= ModuleState::STATE_READY ? moduleStateText[state] @@ -677,38 +511,11 @@ void ProtoState::getPowerStatus(char* buffer) const void ProtoState::processTelemetryData(uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize) { - if (rxBufferCount == 0 && byte != AfhdsSpecialChars::START) { - TRACE("AFHDS3 [SKIP] %02X", byte); - this->esc_state = 0; + if (!trsp.processTelemetryData(byte, rxBuffer, rxBufferCount, maxSize)) return; - } - if (byte == AfhdsSpecialChars::ESC) { - this->esc_state = rxBufferCount; - return; - } - - if (rxBufferCount > 1 && byte == AfhdsSpecialChars::END) { - rxBuffer[rxBufferCount++] = byte; - parseData(rxBuffer, rxBufferCount); - rxBufferCount = 0; - return; - } - - if (this->esc_state && byte == AfhdsSpecialChars::ESC_END) { - byte = AfhdsSpecialChars::END; - } - else if (esc_state && byte == AfhdsSpecialChars::ESC_ESC) { - byte = AfhdsSpecialChars::ESC; - } - //reset esc index - this->esc_state = 0; - - if (rxBufferCount >= maxSize) { - TRACE("AFHDS3 [BUFFER OVERFLOW]"); - rxBufferCount = 0; - } - rxBuffer[rxBufferCount++] = byte; + parseData(rxBuffer, rxBufferCount); + rxBufferCount = 0; } bool ProtoState::isConnectedUnicast() @@ -726,40 +533,22 @@ bool ProtoState::isConnectedMulticast() void ProtoState::setupFrame() { - if (operationState == State::AWAITING_RESPONSE) { - if (repeatCount++ < MAX_RETRIES_AFHDS3) { - return; //re-send - } - else - { - TRACE("AFHDS3 [NO RESP] module state %d", this->state); - clearFrameData(); - this->state = ModuleState::STATE_NOT_READY; - } - } - else if (operationState == State::UNKNOWN) { + bool trsp_error = false; + if (trsp.handleRetransmissions(trsp_error)) return; + + if (trsp_error) { this->state = ModuleState::STATE_NOT_READY; + clearFrameData(); } - repeatCount = 0; if (this->state == ModuleState::STATE_NOT_READY) { TRACE("AFHDS3 [GET MODULE READY]"); - putFrame(COMMAND::MODULE_READY, FRAME_TYPE::REQUEST_GET_DATA); + trsp.sendFrame(COMMAND::MODULE_READY, FRAME_TYPE::REQUEST_GET_DATA); return; } - // check waiting commands - if (!isEmpty()) { - Frame f = commandFifo[getIndex]; - putFrame(f.command, f.frameType, &f.payload, f.payloadSize, - f.useFrameNumber ? &f.frameNumber : &frame_index); - getIndex = nextIndex(getIndex); - TRACE( - "AFHDS3 [CMD QUEUE] cmd: 0x%02x frameType 0x%02x, useFrameNumber %d " - "frame Number %d size %d", - f.command, f.frameType, f.useFrameNumber, f.frameNumber, f.payloadSize); - return; - } + // process backlog + if (trsp.processQueue()) return; // config should be loaded already if (syncSettings()) { return; } @@ -771,7 +560,7 @@ void ProtoState::setupFrame() case STATE_BINDING: // TODO: poll status? handle timeout? // requestedModuleMode = MODULE_MODE_E::BIND; - // putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, + // trsp.sendFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, // &requestedModuleMode, 1); // return; break; @@ -781,13 +570,13 @@ void ProtoState::setupFrame() TRACE("AFHDS3 [BIND]"); setConfigFromModel(); - putFrame(COMMAND::MODULE_SET_CONFIG, + trsp.sendFrame(COMMAND::MODULE_SET_CONFIG, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, cfg.buffer, cfg.version == 0 ? sizeof(cfg.v0) : sizeof(cfg.v1)); requestedModuleMode = MODULE_MODE_E::BIND; - enqueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, true, - requestedModuleMode); + trsp.enqueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, true, + requestedModuleMode); return; // default: @@ -802,17 +591,18 @@ void ProtoState::setupFrame() // cfg.config.runPower = RUN_POWER::RUN_POWER_FIRST; // uint8_t data[] = { 0x13, 0x20, 0x02, cfg.config.runPower, 0 }; // TRACE("AFHDS3 SET TX POWER %d", moduleData->afhds3.runPower); - // putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, + // trsp.sendFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, // data, sizeof(data)); // return; // } // } else if (moduleMode == ::ModuleSettingsMode::MODULE_MODE_NORMAL) { + // if module is ready but not started if (this->state == ModuleState::STATE_READY || this->state == ModuleState::STATE_STANDBY) { + cmdCount = 0; - repeatCount = 0; requestInfoAndRun(true); return; } @@ -821,7 +611,7 @@ void ProtoState::setupFrame() if (state == STATE_BINDING) { TRACE("AFHDS3 [EXIT BIND]"); requestedModuleMode = MODULE_MODE_E::RUN; - putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, + trsp.sendFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &requestedModuleMode, 1); return; } @@ -843,7 +633,7 @@ void ProtoState::setupFrame() uint16_t failSafe[AFHDS3_MAX_CHANNELS + 1] = { ((AFHDS3_MAX_CHANNELS << 8) | CHANNELS_DATA_MODE::FAIL_SAFE), 0}; setFailSafe((int16_t*)(&failSafe[1])); - putFrame(COMMAND::CHANNELS_FAILSAFE_DATA, + trsp.sendFrame(COMMAND::CHANNELS_FAILSAFE_DATA, FRAME_TYPE::REQUEST_SET_NO_RESP, (uint8_t*)failSafe, AFHDS3_MAX_CHANNELS * 2 + 2); } else { @@ -851,31 +641,31 @@ void ProtoState::setupFrame() uint8_t failSafe[3 + AFHDS3_MAX_CHANNELS * 2] = { 0x11, 0x60, AFHDS3_MAX_CHANNELS * 2}; setFailSafe((int16_t*)(failSafe + 3)); - putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, + trsp.sendFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, failSafe, 3 + AFHDS3_MAX_CHANNELS * 2); } } else { - putFrame(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); + trsp.sendFrame(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); } } else { - putFrame(cmd, FRAME_TYPE::REQUEST_GET_DATA); + trsp.sendFrame(cmd, FRAME_TYPE::REQUEST_GET_DATA); } } else if (isConnected) { sendChannelsData(); } else { //default frame - request state - putFrame(MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); + trsp.sendFrame(MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); } } uint8_t* ProtoState::getBuffer() { - return (uint8_t*)trsp_buffer; + return trsp.getFrameBuffer(); } uint32_t ProtoState::getBufferSize() { - return trsp.getSize(trsp_buffer); + return trsp.getFrameSize(); } void ProtoState::init(uint8_t moduleIndex, bool resetFrameCount) @@ -883,22 +673,19 @@ void ProtoState::init(uint8_t moduleIndex, bool resetFrameCount) module_index = moduleIndex; #if defined(INTERNAL_MODULE_AFHDS3) if (moduleIndex == INTERNAL_MODULE) { - trsp_buffer = &intmodulePulsesData.afhds3; - trsp.init(Transport::Serial); + trsp.init(ByteTransport::Serial, &intmodulePulsesData.afhds3); } else #endif { - trsp_buffer = &extmodulePulsesData.afhds3; #if defined(AFHDS3_EXT_UART) - trsp.init(Transport::Serial); + trsp.init(ByteTransport::Serial, &extmodulePulsesData.afhds3); #else - trsp.init(Transport::Pulses); + trsp.init(ByteTransport::Pulses, &extmodulePulsesData.afhds3); #endif } //clear local vars because it is member of union moduleData = &g_model.moduleData[module_index]; - operationState = State::UNKNOWN; state = ModuleState::STATE_NOT_READY; clearFrameData(); } @@ -906,84 +693,10 @@ void ProtoState::init(uint8_t moduleIndex, bool resetFrameCount) void ProtoState::clearFrameData() { TRACE("AFHDS3 clearFrameData"); - trsp.reset(trsp_buffer); - clearCommandFifo(); - repeatCount = 0; + trsp.clear(); + cmdCount = 0; cmdIndex = 0; - frame_index = 1; - timeout = 0; - esc_state = 0; -} - -void ProtoState::sendByte(uint8_t b) -{ - trsp.sendByte(trsp_buffer, b); -} - -void ProtoState::putBytes(uint8_t* data, int length) -{ - for (int i = 0; i < length; i++) { - uint8_t byte = data[i]; - crc += byte; - if (END == byte) { - sendByte(ESC); - sendByte(ESC_END); - } - else if (ESC == byte) { - sendByte(ESC); - sendByte(ESC_ESC); - } - else { - sendByte(byte); - } - } -} - -void ProtoState::putFrame(COMMAND command, FRAME_TYPE frame, uint8_t* data, uint8_t dataLength, uint8_t* frameIndex) -{ - //header - operationState = State::SENDING_COMMAND; - trsp.reset(trsp_buffer); - crc = 0; - sendByte(START); - if (frameIndex == nullptr) { - frameIndex = &frame_index; - } - uint8_t buffer[] = {FrameAddress, *frameIndex, frame, command}; - putBytes(buffer, 4); - - //payload - if (dataLength > 0) { - putBytes(data, dataLength); - } - //footer - uint8_t crcValue = crc ^ 0xff; - putBytes(&crcValue, 1); - sendByte(END); - *frameIndex = *frameIndex + 1; - - switch (frame) { - case FRAME_TYPE::REQUEST_GET_DATA: - case FRAME_TYPE::REQUEST_SET_EXPECT_ACK: - case FRAME_TYPE::REQUEST_SET_EXPECT_DATA: - operationState = State::AWAITING_RESPONSE; - break; - default: - operationState = State::IDLE; - } - - trsp.flush(trsp_buffer); -} - -bool checkCRC(const uint8_t* data, uint8_t size) -{ - uint8_t crc = 0; - //skip start byte - for (uint8_t i = 1; i < size; i++) { - crc += data[i]; - } - return (crc ^ 0xff) == data[size]; } bool containsData(enum FRAME_TYPE frameType) @@ -995,7 +708,7 @@ bool containsData(enum FRAME_TYPE frameType) frameType == FRAME_TYPE::REQUEST_SET_NO_RESP); } -void ProtoState::setState(uint8_t state) +void ProtoState::setState(ModuleState state) { if (state == this->state) { return; @@ -1006,33 +719,29 @@ void ProtoState::setState(uint8_t state) setModuleMode(module_index, ::ModuleSettingsMode::MODULE_MODE_NORMAL); } if (state == ModuleState::STATE_NOT_READY) { - operationState = State::UNKNOWN; + trsp.clear(); } } void ProtoState::requestInfoAndRun(bool send) { if (!send) { - enqueue(COMMAND::MODULE_VERSION, FRAME_TYPE::REQUEST_GET_DATA); + trsp.enqueue(COMMAND::MODULE_VERSION, FRAME_TYPE::REQUEST_GET_DATA); } - // enqueue(COMMAND::MODULE_POWER_STATUS, FRAME_TYPE::REQUEST_GET_DATA); + // trsp.enqueue(COMMAND::MODULE_POWER_STATUS, FRAME_TYPE::REQUEST_GET_DATA); requestedModuleMode = MODULE_MODE_E::RUN; - enqueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, true, + trsp.enqueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, true, (uint8_t)requestedModuleMode); if (send) { - putFrame(COMMAND::MODULE_VERSION, FRAME_TYPE::REQUEST_GET_DATA); + trsp.sendFrame(COMMAND::MODULE_VERSION, FRAME_TYPE::REQUEST_GET_DATA); } } void ProtoState::parseData(uint8_t* rxBuffer, uint8_t rxBufferCount) { - if (!checkCRC(rxBuffer, rxBufferCount - 2)) { - TRACE("AFHDS3 [INVALID CRC]"); - return; - } AfhdsFrame* responseFrame = reinterpret_cast(rxBuffer); if (containsData((enum FRAME_TYPE) responseFrame->frameType)) { switch (responseFrame->command) { @@ -1046,14 +755,15 @@ void ProtoState::parseData(uint8_t* rxBuffer, uint8_t rxBufferCount) setState(ModuleState::STATE_NOT_READY); } break; - case COMMAND::MODULE_GET_CONFIG: - std::memcpy((void*) cfg.buffer, &responseFrame->value, sizeof(cfg.buffer)); + case COMMAND::MODULE_GET_CONFIG: { + size_t len = min(sizeof(cfg.buffer), rxBufferCount); + std::memcpy((void*) cfg.buffer, &responseFrame->value, len); // TRACE( // "AFHDS3 [MODULE_GET_CONFIG] bind power %d run power %d mode %d " // "pwm/ppm %d ibus/sbus %d", // cfg.config.bindPower, cfg.config.runPower, cfg.config.telemetry, // cfg.config.pulseMode, cfg.config.serialMode); - break; + } break; case COMMAND::MODULE_VERSION: std::memcpy((void*) &version, &responseFrame->value, sizeof(version)); TRACE("AFHDS3 [MODULE_VERSION] Product %d, HW %d, BOOT %d, FW %d", @@ -1066,7 +776,7 @@ void ProtoState::parseData(uint8_t* rxBuffer, uint8_t rxBufferCount) // break; case COMMAND::MODULE_STATE: TRACE("AFHDS3 [MODULE_STATE] %02X", responseFrame->value); - setState(responseFrame->value); + setState((ModuleState)responseFrame->value); break; case COMMAND::MODULE_MODE: TRACE("AFHDS3 [MODULE_MODE] %02X", responseFrame->value); @@ -1075,8 +785,8 @@ void ProtoState::parseData(uint8_t* rxBuffer, uint8_t rxBufferCount) } else { if (requestedModuleMode == MODULE_MODE_E::RUN) { - enqueue(COMMAND::MODULE_GET_CONFIG, FRAME_TYPE::REQUEST_GET_DATA); - enqueue(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); + trsp.enqueue(COMMAND::MODULE_GET_CONFIG, FRAME_TYPE::REQUEST_GET_DATA); + trsp.enqueue(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA); } requestedModuleMode = MODULE_MODE_UNKNOWN; } @@ -1129,36 +839,19 @@ void ProtoState::parseData(uint8_t* rxBuffer, uint8_t rxBufferCount) } } break; - case COMMAND::COMMAND_RESULT: - { - //AfhdsFrameData* respData = responseFrame->GetData(); - //TRACE("COMMAND RESULT %02X result %d datalen %d", respData->CommandResult.command, respData->CommandResult.result, respData->CommandResult.respLen); - } - break; + case COMMAND::COMMAND_RESULT: { + // AfhdsFrameData* respData = responseFrame->GetData(); + // TRACE("COMMAND RESULT %02X result %d datalen %d", + // respData->CommandResult.command, respData->CommandResult.result, + // respData->CommandResult.respLen); + } break; } } - if (responseFrame->frameType == FRAME_TYPE::REQUEST_GET_DATA || responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA) { + if (responseFrame->frameType == FRAME_TYPE::REQUEST_GET_DATA || + responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA) { TRACE("Command %02X NOT IMPLEMENTED!", responseFrame->command); } - else if (responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_ACK) { - //check if such request is not queued - if (!isEmpty()) { - Frame f = commandFifo[getIndex]; - if (f.frameType == FRAME_TYPE::RESPONSE_ACK && f.frameNumber == responseFrame->frameNumber) { - TRACE("ACK for frame %02X already queued", responseFrame->frameNumber); - return; - } - } - TRACE("AFHDS3 [QUEUE ACK] cmd %02X type %02X number %02X", responseFrame->command, responseFrame->frameType, responseFrame->frameNumber); - enqueueACK((enum COMMAND) responseFrame->command, responseFrame->frameNumber); - // TODO: send ACK immediately !!! - } - else if (responseFrame->frameType == FRAME_TYPE::RESPONSE_DATA || responseFrame->frameType == FRAME_TYPE::RESPONSE_ACK) { - if (operationState == State::AWAITING_RESPONSE) { - operationState = State::IDLE; - } - } } inline bool isSbus(uint8_t mode) @@ -1210,7 +903,7 @@ bool ProtoState::syncSettings() // cfg.config.runPower = moduleData->afhds3.runPower; // uint8_t data[] = {0x13, 0x20, 0x02, moduleData->afhds3.runPower, 0}; // TRACE("AFHDS3 SET TX POWER %d", moduleData->afhds3.runPower); - // putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, + // trsp.sendFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, // sizeof(data)); // return true; // } @@ -1226,7 +919,7 @@ bool ProtoState::syncSettings() // (uint8_t)(moduleData->afhds3.rxFreq() & 0xFF), // (uint8_t)(moduleData->afhds3.rxFreq() >> 8)}; // TRACE("AFHDS3 SET RX FREQ"); - // putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, + // trsp.sendFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, // sizeof(data)); // return true; // } @@ -1238,7 +931,7 @@ bool ProtoState::syncSettings() // cfg.config.pulseMode = modelPulseMode; // TRACE("AFHDS3 PWM/PPM %d", modelPulseMode); // uint8_t data[] = {0x16, 0x70, 0x01, (uint8_t)(modelPulseMode)}; - // putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, + // trsp.sendFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, // sizeof(data)); // return true; // } @@ -1250,7 +943,7 @@ bool ProtoState::syncSettings() // cfg.config.serialMode = modelSerialMode; // TRACE("AFHDS3 IBUS/SBUS %d", modelSerialMode); // uint8_t data[] = {0x18, 0x70, 0x01, (uint8_t)(modelSerialMode)}; - // putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, + // trsp.sendFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, // sizeof(data)); // return true; // } @@ -1260,7 +953,7 @@ bool ProtoState::syncSettings() // uint8_t data[] = {0x12, 0x60, 0x02, // (uint8_t)(moduleData->afhds3.failsafeTimeout & 0xFF), // (uint8_t)(moduleData->afhds3.failsafeTimeout >> 8)}; - // putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, + // trsp.sendFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, // sizeof(data)); // TRACE("AFHDS3 FAILSAFE TMEOUT, %d", moduleData->afhds3.failsafeTimeout); // return true; @@ -1289,7 +982,7 @@ void ProtoState::sendChannelsData() buffer[index] = channelValue; } - putFrame(COMMAND::CHANNELS_FAILSAFE_DATA, FRAME_TYPE::REQUEST_SET_NO_RESP, + trsp.sendFrame(COMMAND::CHANNELS_FAILSAFE_DATA, FRAME_TYPE::REQUEST_SET_NO_RESP, (uint8_t*)buffer, (channels + 1) * 2); } @@ -1297,7 +990,7 @@ void ProtoState::stop() { TRACE("AFHDS3 STOP"); requestedModuleMode = MODULE_MODE_E::STANDBY; - putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, + trsp.sendFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &requestedModuleMode, 1); } diff --git a/radio/src/pulses/afhds3.h b/radio/src/pulses/afhds3.h index 46e5ce281..b78ff425f 100644 --- a/radio/src/pulses/afhds3.h +++ b/radio/src/pulses/afhds3.h @@ -32,7 +32,7 @@ #include "fifo.h" #include "hal/module_driver.h" -#include "afhds3_transport.h" +#include "afhds3_module.h" #define AFHDS3_MIN_FREQ 50 #define AFHDS3_MAX_FREQ 400 diff --git a/radio/src/pulses/afhds3_module.h b/radio/src/pulses/afhds3_module.h new file mode 100644 index 000000000..93c51e260 --- /dev/null +++ b/radio/src/pulses/afhds3_module.h @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#pragma once + +#include +#include "hal.h" + +#define AFHDS_MAX_PULSES 128 + +// max number of transitions measured so far 290 + 10% +// TODO: define as a function of MAX_PULSES +#define AFHDS_MAX_PULSES_TRANSITIONS 320 + +#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) + #define AFHDS3_EXT_UART +#else + #define AFHDS3_EXT_SOFTSERIAL +#endif + +#define AFHDS3_UART_BAUDRATE 1500000 +#define AFHDS3_UART_COMMAND_TIMEOUT 5 + +#if defined(AFHDS3_SLOW) + #define AFHDS3_SOFTSERIAL_BAUDRATE 57600 + #define AFHDS3_SOFTSERIAL_COMMAND_TIMEOUT 20 +#else + #define AFHDS3_SOFTSERIAL_BAUDRATE 115200 + #define AFHDS3_SOFTSERIAL_COMMAND_TIMEOUT 15 +#endif + +namespace afhds3 +{ + +struct SerialData { + uint8_t pulses[AFHDS_MAX_PULSES]; + uint8_t* ptr; +}; + +struct PulsesData { + uint16_t pulses[AFHDS_MAX_PULSES_TRANSITIONS]; + uint16_t* ptr; +}; + +#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) +typedef SerialData ExtmoduleData; +#else +typedef PulsesData ExtmoduleData; +#endif + +#if defined(INTERNAL_MODULE_AFHDS3) +typedef SerialData IntmoduleData; +#endif + +}; diff --git a/radio/src/pulses/afhds3_transport.cpp b/radio/src/pulses/afhds3_transport.cpp index e5d1e4081..83c35910b 100644 --- a/radio/src/pulses/afhds3_transport.cpp +++ b/radio/src/pulses/afhds3_transport.cpp @@ -20,6 +20,8 @@ */ #include "afhds3_transport.h" +#include "opentx_helpers.h" +#include "debug.h" // timer is 2 MHz #if defined(AFHDS3_SLOW) @@ -30,9 +32,31 @@ #define BITLEN_AFHDS (17) #endif +#define MAX_RETRIES_AFHDS3 5 + namespace afhds3 { +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 +}; + +enum DeviceAddress +{ + TRANSMITTER = 0x01, + // MODULE = 0x03, + MODULE = 0x05, +}; + +//Address used in transmitted frames - it constrains of target address and source address +const uint8_t FrameAddress = DeviceAddress::TRANSMITTER | (DeviceAddress::MODULE << 4); + static void _serial_reset(void* buffer) { auto data = (SerialData*)buffer; @@ -105,7 +129,7 @@ uint32_t _pulses_getSize(void* buffer) return data->ptr - data->pulses; } -void Transport::init(Type t) +void ByteTransport::init(Type t) { if (t == Serial) { reset = _serial_reset; @@ -123,6 +147,304 @@ void Transport::init(Type t) flush = nullptr; getSize = nullptr; } -} +} + +void FrameTransport::init(ByteTransport::Type t, void* buffer) +{ + trsp.init(t); + trsp_buffer = buffer; + + clear(); +} + +void FrameTransport::clear() +{ + // reset send buffer + trsp.reset(trsp_buffer); + + // reset parser + esc_state = 0; +} + +void FrameTransport::sendByte(uint8_t b) +{ + trsp.sendByte(trsp_buffer, b); +} + +void FrameTransport::putBytes(uint8_t* data, int length) +{ + for (int i = 0; i < length; i++) { + uint8_t byte = data[i]; + crc += byte; + if (END == byte) { + sendByte(ESC); + sendByte(ESC_END); + } + else if (ESC == byte) { + sendByte(ESC); + sendByte(ESC_ESC); + } + else { + sendByte(byte); + } + } +} + +void FrameTransport::putFrame(COMMAND command, FRAME_TYPE frameType, uint8_t* data, + uint8_t dataLength, uint8_t frameIndex) +{ + //header + trsp.reset(trsp_buffer); + crc = 0; + sendByte(START); + + uint8_t buffer[] = {FrameAddress, frameIndex, frameType, command}; + putBytes(buffer, 4); + + //payload + if (dataLength > 0) { + putBytes(data, dataLength); + } + + //footer + uint8_t crcValue = crc ^ 0xff; + putBytes(&crcValue, 1); + sendByte(END); + trsp.flush(trsp_buffer); +} + +static bool _checkCRC(const uint8_t* data, uint8_t size) +{ + uint8_t crc = 0; + //skip start byte + for (uint8_t i = 1; i < size; i++) { + crc += data[i]; + } + return (crc ^ 0xff) == data[size]; +} + +bool FrameTransport::processTelemetryData(uint8_t byte, uint8_t* rxBuffer, + uint8_t& rxBufferCount, + uint8_t maxSize) +{ + if (rxBufferCount == 0 && byte != START) { + TRACE("AFHDS3 [SKIP] %02X", byte); + this->esc_state = 0; + return false; + } + + if (byte == ESC) { + this->esc_state = rxBufferCount; + return false; + } + + if (rxBufferCount > 1 && byte == END) { + rxBuffer[rxBufferCount++] = byte; + + if (!_checkCRC(rxBuffer, rxBufferCount - 2)) { + TRACE("AFHDS3 [INVALID CRC]"); + rxBufferCount = 0; + return false; + } + + return true; + } + + if (this->esc_state && byte == ESC_END) { + byte = END; + } + else if (esc_state && byte == ESC_ESC) { + byte = ESC; + } + //reset esc index + this->esc_state = 0; + + if (rxBufferCount >= maxSize) { + TRACE("AFHDS3 [BUFFER OVERFLOW]"); + rxBufferCount = 0; + } + rxBuffer[rxBufferCount++] = byte; + return false; +} + +void CommandFifo::clearCommandFifo() +{ + memclear(commandFifo, sizeof(commandFifo)); + setIndex = getIndex = 0; +} + +Frame* CommandFifo::getCommand() +{ + if (isEmpty()) return nullptr; + return &commandFifo[getIndex]; +} + +void CommandFifo::enqueueACK(COMMAND command, uint8_t frameNumber) +{ + uint32_t next = nextIndex(setIndex); + if (next != getIndex) { + commandFifo[setIndex].command = command; + commandFifo[setIndex].frameType = FRAME_TYPE::RESPONSE_ACK; + commandFifo[setIndex].payload = 0; + commandFifo[setIndex].payloadSize = 0; + commandFifo[setIndex].frameNumber = frameNumber; + commandFifo[setIndex].useFrameNumber = true; + setIndex = next; + } +} + +void CommandFifo::enqueue(COMMAND command, FRAME_TYPE frameType, bool useData, + uint8_t byteContent) +{ + uint32_t next = nextIndex(setIndex); + if (next != getIndex) { + commandFifo[setIndex].command = command; + commandFifo[setIndex].frameType = frameType; + commandFifo[setIndex].payload = byteContent; + commandFifo[setIndex].payloadSize = useData ? 1 : 0; + commandFifo[setIndex].frameNumber = 0; + commandFifo[setIndex].useFrameNumber = false; + setIndex = next; + } +} + +void Transport::init(ByteTransport::Type t, void* buffer) +{ + trsp.init(t, buffer); +} + +void Transport::clear() +{ + // reset frame + trsp.clear(); + + // reset command layer + fifo.clearCommandFifo(); + + frameIndex = 1; + repeatCount = 0; + + // reset internal state + operationState = State::UNKNOWN; +} + +void Transport::sendFrame(COMMAND command, FRAME_TYPE frameType, uint8_t* data, + uint8_t dataLength) +{ + operationState = State::SENDING_COMMAND; + repeatCount = 0; + + trsp.putFrame(command, frameType, data, dataLength, frameIndex); + frameIndex++; + + switch (frameType) { + case FRAME_TYPE::REQUEST_GET_DATA: + case FRAME_TYPE::REQUEST_SET_EXPECT_ACK: + case FRAME_TYPE::REQUEST_SET_EXPECT_DATA: + operationState = State::AWAITING_RESPONSE; + break; + default: + operationState = State::IDLE; + } +} + +void Transport::enqueue(COMMAND command, FRAME_TYPE frameType, bool useData, + uint8_t byteContent) +{ + fifo.enqueue(command, frameType, useData, byteContent); +} + +bool Transport::processQueue() +{ + // check waiting commands + auto f = fifo.getCommand(); + if (!f) return false; + + trsp.putFrame(f->command, f->frameType, &f->payload, f->payloadSize, + f->useFrameNumber ? f->frameNumber : frameIndex); + + TRACE( + "AFHDS3 [CMD QUEUE] cmd: 0x%02x frameType 0x%02x, useFrameNumber %d " + "frame Number %d size %d", + f->command, f->frameType, f->useFrameNumber, f->frameNumber, + f->payloadSize); + + if (!f->useFrameNumber) frameIndex++; + fifo.skip(); + + return true; +} + +bool Transport::handleRetransmissions(bool& error) +{ + if (operationState == State::AWAITING_RESPONSE) { + if (repeatCount++ < MAX_RETRIES_AFHDS3) { + error = false; + return true; // re-send + } + + TRACE("AFHDS3 [NO RESP]"); + error = true; + return false; + } + + if (operationState == State::UNKNOWN) { + error = true; + return false; + } + + error = false; + repeatCount = 0; + + return false; +} + +bool Transport::handleReply(uint8_t* buffer, uint8_t len) +{ + // TODO: check len... + + AfhdsFrame* responseFrame = reinterpret_cast(buffer); + if (responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_ACK) { + + // check if such request is not queued + auto f = fifo.getCommand(); + if (f && f->frameType == FRAME_TYPE::RESPONSE_ACK && + f->frameNumber == responseFrame->frameNumber) { + + // absorb retransmission + TRACE("ACK for frame %02X already queued", responseFrame->frameNumber); + return true; + } + + TRACE("AFHDS3 [QUEUE ACK] cmd %02X type %02X number %02X", + responseFrame->command, responseFrame->frameType, + responseFrame->frameNumber); + + fifo.enqueueACK((enum COMMAND)responseFrame->command, + responseFrame->frameNumber); + // TODO: send ACK immediately !!! + + } else if (responseFrame->frameType == FRAME_TYPE::RESPONSE_DATA || + responseFrame->frameType == FRAME_TYPE::RESPONSE_ACK) { + + if (operationState == State::AWAITING_RESPONSE) { + operationState = State::IDLE; + } + } + + return false; +} + +bool Transport::processTelemetryData(uint8_t byte, uint8_t* rxBuffer, + uint8_t& rxBufferCount, uint8_t maxSize) +{ + bool has_frame = trsp.processTelemetryData(byte, rxBuffer, rxBufferCount, maxSize); + if (has_frame && handleReply(rxBuffer, rxBufferCount)) { + rxBufferCount = 0; + return false; + } + + return has_frame; +} }; diff --git a/radio/src/pulses/afhds3_transport.h b/radio/src/pulses/afhds3_transport.h index 715b6be77..c507ccb1a 100644 --- a/radio/src/pulses/afhds3_transport.h +++ b/radio/src/pulses/afhds3_transport.h @@ -21,68 +21,195 @@ #pragma once -#include -#include "hal.h" - -#define AFHDS_MAX_PULSES 128 - -// max number of transitions measured so far 290 + 10% -// TODO: define as a function of MAX_PULSES -#define AFHDS_MAX_PULSES_TRANSITIONS 320 - -#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) - #define AFHDS3_EXT_UART -#else - #define AFHDS3_EXT_SOFTSERIAL -#endif - -#define AFHDS3_UART_BAUDRATE 1500000 -#define AFHDS3_UART_COMMAND_TIMEOUT 5 - -#if defined(AFHDS3_SLOW) - #define AFHDS3_SOFTSERIAL_BAUDRATE 57600 - #define AFHDS3_SOFTSERIAL_COMMAND_TIMEOUT 20 -#else - #define AFHDS3_SOFTSERIAL_BAUDRATE 115200 - #define AFHDS3_SOFTSERIAL_COMMAND_TIMEOUT 15 -#endif +#include "afhds3_module.h" +#include "definitions.h" namespace afhds3 { - -struct SerialData { - uint8_t pulses[AFHDS_MAX_PULSES]; - uint8_t* ptr; -}; - -struct PulsesData { - uint16_t pulses[AFHDS_MAX_PULSES_TRANSITIONS]; - uint16_t* ptr; -}; - -#if defined(EXTMODULE_USART) && defined(EXTMODULE_TX_INVERT_GPIO) -typedef SerialData ExtmoduleData; -#else -typedef PulsesData ExtmoduleData; -#endif - -#if defined(INTERNAL_MODULE_AFHDS3) -typedef SerialData IntmoduleData; -#endif - -struct Transport { - - enum Type { - Serial, - Pulses - }; +struct ByteTransport { + enum Type { Serial, Pulses }; + void (*reset)(void* buffer); void (*sendByte)(void* buffer, uint8_t b); void (*flush)(void* buffer); uint32_t (*getSize)(void* buffer); - + void init(Type t); }; +enum FRAME_TYPE: uint8_t +{ + REQUEST_GET_DATA = 0x01, //Get data response: ACK + DATA + REQUEST_SET_EXPECT_DATA = 0x02, //Set data response: ACK + DATA + REQUEST_SET_EXPECT_ACK = 0x03, //Set data response: ACK + REQUEST_SET_NO_RESP = 0x05, //Set data response: none + RESPONSE_DATA = 0x10, //Response ACK + DATA + RESPONSE_ACK = 0x20, //Response ACK + NOT_USED = 0xff +}; + +enum COMMAND: uint8_t +{ + MODULE_READY = 0x01, + MODULE_STATE = 0x02, + MODULE_MODE = 0x03, + MODULE_SET_CONFIG = 0x04, + MODULE_GET_CONFIG = 0x06, + CHANNELS_FAILSAFE_DATA = 0x07, + TELEMETRY_DATA = 0x09, + SEND_COMMAND = 0x0C, + COMMAND_RESULT = 0x0D, + // MODULE_POWER_STATUS = 0x0F, + // MODULE_VERSION = 0x1F, + MODULE_VERSION = 0x20, + VIRTUAL_FAILSAFE = 0x99, // virtual command used to trigger failsafe + UNDEFINED = 0xFF +}; + +// one byte frames for request queue +struct Frame +{ + enum COMMAND command; + enum FRAME_TYPE frameType; + uint8_t payload; + uint8_t frameNumber; + bool useFrameNumber; + uint8_t payloadSize; +}; + +union AfhdsFrameData; + +PACK(struct AfhdsFrame { + uint8_t startByte; + uint8_t address; + uint8_t frameNumber; + uint8_t frameType; + uint8_t command; + uint8_t value; + + AfhdsFrameData* GetData() + { + return reinterpret_cast(&value); + } +}); + +// simple fifo implementation because Pulses is used as member of union and can +// not be non trivial type +struct CommandFifo { + Frame commandFifo[8]; + volatile uint32_t setIndex; + volatile uint32_t getIndex; + + void clearCommandFifo(); + Frame* getCommand(); + + inline uint32_t nextIndex(uint32_t idx) const + { + return (idx + 1) & (sizeof(commandFifo) / sizeof(commandFifo[0]) - 1); + } + + inline uint32_t prevIndex(uint32_t idx) const + { + if (idx == 0) { + return (sizeof(commandFifo) / sizeof(commandFifo[0]) - 1); + } + return (idx - 1); + } + + inline bool isEmpty() const { return (getIndex == setIndex); } + + inline void skip() { getIndex = nextIndex(getIndex); } + + void enqueueACK(COMMAND command, uint8_t frameNumber); + + void enqueue(COMMAND command, FRAME_TYPE frameType, bool useData, + uint8_t byteContent); +}; + +struct FrameTransport +{ + ByteTransport trsp; + void* trsp_buffer; + + uint8_t crc; + // uint8_t timeout; + uint8_t esc_state; + + void init(ByteTransport::Type t, void* buffer); + void clear(); + + void sendByte(uint8_t b); + void putBytes(uint8_t* data, int length); + + void putFrame(COMMAND command, FRAME_TYPE frameType, uint8_t* data, + uint8_t dataLength, uint8_t frameIndex); + + uint32_t getFrameSize() { return trsp.getSize(trsp_buffer); } + + bool processTelemetryData(uint8_t byte, uint8_t* rxBuffer, + uint8_t& rxBufferCount, uint8_t maxSize); +}; + +class Transport +{ + enum State { + UNKNOWN = 0, + SENDING_COMMAND, + AWAITING_RESPONSE, + IDLE + }; + + FrameTransport trsp; + CommandFifo fifo; + + /** + * Internal operation state one of UNKNOWN, SENDING_COMMAND, AWAITING_RESPONSE, IDLE + * Used to avoid sending commands when not allowed to + */ + State operationState; + + /** + * Current frame index + */ + uint8_t frameIndex; + + /** + * Actual repeat count for requested command/operation - incremented by every + * attempt sending anything + */ + uint16_t repeatCount; + + bool handleReply(uint8_t* buffer, uint8_t len); + + public: + void init(ByteTransport::Type t, void* buffer); + + void clear(); + + void sendFrame(COMMAND command, FRAME_TYPE frameType, uint8_t* data = nullptr, + uint8_t dataLength = 0); + + void enqueue(COMMAND command, FRAME_TYPE frameType, bool useData = false, + uint8_t byteContent = 0); + + uint8_t* getFrameBuffer() { return (uint8_t*)trsp.trsp_buffer; } + uint32_t getFrameSize() { return trsp.getFrameSize(); } + + /** + * Process retransmissions + * error: transport is in error state + * @return true if something was just sent + */ + bool handleRetransmissions(bool& error); + + /** + * Process queue backlog + * @return true if something was just sent + */ + bool processQueue(); + + bool processTelemetryData(uint8_t byte, uint8_t* rxBuffer, + uint8_t& rxBufferCount, uint8_t maxSize); +}; }; diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index 592e45bfd..9587d3e62 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -29,7 +29,7 @@ #include "pxx2.h" #include "multi.h" #include "afhds2.h" -#include "afhds3_transport.h" +#include "afhds3_module.h" #include "modules_helpers.h" #include "ff.h" #include "hal/module_driver.h"