Program Listing for File dji_serial.hpp
↰ Return to documentation for file (src/tap/communication/serial/dji_serial.hpp
)
/*
* Copyright (c) 2020-2021 Advanced Robotics at the University of Washington <robomstr@uw.edu>
*
* This file is part of Taproot.
*
* Taproot is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Taproot 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.
*
* You should have received a copy of the GNU General Public License
* along with Taproot. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef TAPROOT_DJI_SERIAL_HPP_
#define TAPROOT_DJI_SERIAL_HPP_
#include <cstdint>
#include "tap/algorithms/crc.hpp"
#include "tap/communication/serial/uart.hpp"
#include "tap/util_macros.hpp"
namespace tap
{
class Drivers;
}
namespace tap::communication::serial
{
class DJISerial
{
public:
struct FrameHeader
{
uint8_t headByte;
uint16_t dataLength;
uint8_t seq;
uint8_t CRC8;
} modm_packed;
template <int DATA_SIZE>
struct SerialMessage
{
explicit SerialMessage(uint8_t seq = 0)
{
header.headByte = 0xa5;
header.dataLength = sizeof(data);
header.seq = seq;
header.CRC8 = tap::algorithms::calculateCRC8(
reinterpret_cast<uint8_t *>(&header),
sizeof(header) - 1);
}
void setCRC16()
{
CRC16 = tap::algorithms::calculateCRC16(
reinterpret_cast<uint8_t *>(this),
sizeof(*this) - 2);
}
FrameHeader header;
uint16_t messageType;
uint8_t data[DATA_SIZE];
uint16_t CRC16;
} modm_packed;
static const uint16_t SERIAL_RX_BUFF_SIZE = 1024;
static const uint16_t SERIAL_HEAD_BYTE = 0xA5;
using ReceivedSerialMessage = SerialMessage<SERIAL_RX_BUFF_SIZE>;
DJISerial(Drivers *drivers, Uart::UartPort port, bool isRxCRCEnforcementEnabled = true);
DISALLOW_COPY_AND_ASSIGN(DJISerial)
mockable ~DJISerial() = default;
mockable void initialize();
mockable void updateSerial();
virtual void messageReceiveCallback(const ReceivedSerialMessage &completeMessage) = 0;
private:
enum SerialRxState
{
SERIAL_HEADER_SEARCH,
PROCESS_FRAME_HEADER,
PROCESS_FRAME_DATA
};
Uart::UartPort port;
SerialRxState djiSerialRxState;
ReceivedSerialMessage newMessage;
ReceivedSerialMessage mostRecentMessage;
uint16_t frameCurrReadByte;
bool rxCrcEnabled;
inline bool verifyCRC8(uint8_t *message, uint32_t messageLength, uint8_t expectedCRC8)
{
return tap::algorithms::calculateCRC8(message, messageLength) == expectedCRC8;
}
protected:
Drivers *drivers;
};
} // namespace tap::communication::serial
#endif // TAPROOT_DJI_SERIAL_HPP_