123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /*
- This program 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.
- 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.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /*
- implementation of MSP and BLHeli-4way protocols for pass-through ESC
- calibration and firmware update
- With thanks to betaflight for a great reference implementation
- */
- #pragma once
- #include <AP_Common/AP_Common.h>
- #include <AP_HAL/AP_HAL.h>
- #if HAL_SUPPORT_RCOUT_SERIAL
- #define HAVE_AP_BLHELI_SUPPORT
- #include <AP_Param/AP_Param.h>
- #include "msp_protocol.h"
- #include "blheli_4way_protocol.h"
- #define AP_BLHELI_MAX_ESCS 8
- class AP_BLHeli {
- public:
- AP_BLHeli();
-
- void update(void);
- void update_telemetry(void);
- bool process_input(uint8_t b);
- static const struct AP_Param::GroupInfo var_info[];
- struct telem_data {
- uint8_t temperature; // degrees C
- uint16_t voltage; // volts * 100
- uint16_t current; // amps * 100
- uint16_t consumption;// mAh
- uint16_t rpm; // eRPM
- uint16_t count;
- uint32_t timestamp_ms;
- };
- // get the most recent telemetry data packet for a motor
- bool get_telem_data(uint8_t esc_index, struct telem_data &td);
- static AP_BLHeli *get_singleton(void) {
- return _singleton;
- }
- // send ESC telemetry messages over MAVLink
- void send_esc_telemetry_mavlink(uint8_t mav_chan);
-
- private:
- static AP_BLHeli *_singleton;
-
- // mask of channels to use for BLHeli protocol
- AP_Int32 channel_mask;
- AP_Int32 channel_reversible_mask;
- AP_Int8 channel_auto;
- AP_Int8 run_test;
- AP_Int16 timeout_sec;
- AP_Int16 telem_rate;
- AP_Int8 debug_level;
- AP_Int8 output_type;
- AP_Int8 control_port;
- AP_Int8 motor_poles;
-
- enum mspState {
- MSP_IDLE=0,
- MSP_HEADER_START,
- MSP_HEADER_M,
- MSP_HEADER_ARROW,
- MSP_HEADER_SIZE,
- MSP_HEADER_CMD,
- MSP_COMMAND_RECEIVED
- };
- enum mspPacketType {
- MSP_PACKET_COMMAND,
- MSP_PACKET_REPLY
- };
- enum escProtocol {
- PROTOCOL_SIMONK = 0,
- PROTOCOL_BLHELI = 1,
- PROTOCOL_KISS = 2,
- PROTOCOL_KISSALL = 3,
- PROTOCOL_CASTLE = 4,
- PROTOCOL_MAX = 5,
- PROTOCOL_NONE = 0xfe,
- PROTOCOL_4WAY = 0xff
- };
- enum motorPwmProtocol {
- PWM_TYPE_STANDARD = 0,
- PWM_TYPE_ONESHOT125,
- PWM_TYPE_ONESHOT42,
- PWM_TYPE_MULTISHOT,
- PWM_TYPE_BRUSHED,
- PWM_TYPE_DSHOT150,
- PWM_TYPE_DSHOT300,
- PWM_TYPE_DSHOT600,
- PWM_TYPE_DSHOT1200,
- PWM_TYPE_PROSHOT1000,
- };
- enum MSPFeatures {
- FEATURE_RX_PPM = 1 << 0,
- FEATURE_INFLIGHT_ACC_CAL = 1 << 2,
- FEATURE_RX_SERIAL = 1 << 3,
- FEATURE_MOTOR_STOP = 1 << 4,
- FEATURE_SERVO_TILT = 1 << 5,
- FEATURE_SOFTSERIAL = 1 << 6,
- FEATURE_GPS = 1 << 7,
- FEATURE_RANGEFINDER = 1 << 9,
- FEATURE_TELEMETRY = 1 << 10,
- FEATURE_3D = 1 << 12,
- FEATURE_RX_PARALLEL_PWM = 1 << 13,
- FEATURE_RX_MSP = 1 << 14,
- FEATURE_RSSI_ADC = 1 << 15,
- FEATURE_LED_STRIP = 1 << 16,
- FEATURE_DASHBOARD = 1 << 17,
- FEATURE_OSD = 1 << 18,
- FEATURE_CHANNEL_FORWARDING = 1 << 20,
- FEATURE_TRANSPONDER = 1 << 21,
- FEATURE_AIRMODE = 1 << 22,
- FEATURE_RX_SPI = 1 << 25,
- FEATURE_SOFTSPI = 1 << 26,
- FEATURE_ESC_SENSOR = 1 << 27,
- FEATURE_ANTI_GRAVITY = 1 << 28,
- FEATURE_DYNAMIC_FILTER = 1 << 29,
- };
- /*
- state of MSP command processing
- */
- struct {
- enum mspState state;
- enum mspPacketType packetType;
- uint8_t offset;
- uint8_t dataSize;
- uint8_t checksum;
- uint8_t buf[192];
- uint8_t cmdMSP;
- enum escProtocol escMode;
- uint8_t portIndex;
- } msp;
- enum blheliState {
- BLHELI_IDLE=0,
- BLHELI_HEADER_START,
- BLHELI_HEADER_CMD,
- BLHELI_HEADER_ADDR_LOW,
- BLHELI_HEADER_ADDR_HIGH,
- BLHELI_HEADER_LEN,
- BLHELI_CRC1,
- BLHELI_CRC2,
- BLHELI_COMMAND_RECEIVED
- };
- /*
- state of blheli 4way protocol handling
- */
- struct {
- enum blheliState state;
- uint8_t command;
- uint16_t address;
- uint16_t param_len;
- uint16_t offset;
- uint8_t buf[256+3+8];
- uint8_t crc1;
- uint16_t crc;
- bool connected[AP_BLHELI_MAX_ESCS];
- uint8_t interface_mode[AP_BLHELI_MAX_ESCS];
- uint8_t deviceInfo[AP_BLHELI_MAX_ESCS][4];
- uint8_t chan;
- uint8_t ack;
- } blheli;
- const uint16_t esc_status_addr = 0xEB00;
-
- // protocol reported by ESC in esc_status
- enum esc_protocol {
- ESC_PROTOCOL_NONE=0,
- ESC_PROTOCOL_NORMAL=1,
- ESC_PROTOCOL_ONESHOT125=2,
- ESC_PROTOCOL_DSHOT=5,
- };
-
- // ESC status structure at address 0xEB00
- struct PACKED esc_status {
- uint8_t unknown[3];
- enum esc_protocol protocol;
- uint32_t good_frames;
- uint32_t bad_frames;
- uint32_t unknown2;
- };
-
-
- AP_HAL::UARTDriver *uart;
- AP_HAL::UARTDriver *debug_uart;
- AP_HAL::UARTDriver *telem_uart;
-
- static const uint8_t max_motors = AP_BLHELI_MAX_ESCS;
- uint8_t num_motors;
- struct telem_data last_telem[max_motors];
- // have we initialised the interface?
- bool initialised;
- // last valid packet timestamp
- uint32_t last_valid_ms;
- // when did we start the serial ESC output?
- uint32_t serial_start_ms;
- // have we disabled motor outputs?
- bool motors_disabled;
- // have we locked the UART?
- bool uart_locked;
- // mapping from BLHeli motor numbers to RC output channels
- uint8_t motor_map[max_motors];
- uint16_t motor_mask;
- // when did we last request telemetry?
- uint32_t last_telem_request_us;
- uint8_t last_telem_esc;
- static const uint8_t telem_packet_size = 10;
- bool telem_uart_started;
- uint32_t last_telem_byte_read_us;
- int8_t last_control_port;
- bool msp_process_byte(uint8_t c);
- void blheli_crc_update(uint8_t c);
- bool blheli_4way_process_byte(uint8_t c);
- void msp_send_reply(uint8_t cmd, const uint8_t *buf, uint8_t len);
- void putU16(uint8_t *b, uint16_t v);
- uint16_t getU16(const uint8_t *b);
- void putU32(uint8_t *b, uint32_t v);
- void putU16_BE(uint8_t *b, uint16_t v);
- void msp_process_command(void);
- void blheli_send_reply(const uint8_t *buf, uint16_t len);
- uint16_t BL_CRC(const uint8_t *buf, uint16_t len);
- bool isMcuConnected(void);
- void setDisconnected(void);
- bool BL_SendBuf(const uint8_t *buf, uint16_t len);
- bool BL_ReadBuf(uint8_t *buf, uint16_t len);
- uint8_t BL_GetACK(uint16_t timeout_ms=2);
- bool BL_SendCMDSetAddress();
- bool BL_ReadA(uint8_t cmd, uint8_t *buf, uint16_t n);
- bool BL_ConnectEx(void);
- bool BL_SendCMDKeepAlive(void);
- bool BL_PageErase(void);
- void BL_SendCMDRunRestartBootloader(void);
- uint8_t BL_SendCMDSetBuffer(const uint8_t *buf, uint16_t nbytes);
- bool BL_WriteA(uint8_t cmd, const uint8_t *buf, uint16_t nbytes, uint32_t timeout);
- uint8_t BL_WriteFlash(const uint8_t *buf, uint16_t n);
- bool BL_VerifyFlash(const uint8_t *buf, uint16_t n);
- void blheli_process_command(void);
- void run_connection_test(uint8_t chan);
- uint8_t telem_crc8(uint8_t crc, uint8_t crc_seed) const;
- void read_telemetry_packet(void);
-
- // protocol handler hook
- bool protocol_handler(uint8_t , AP_HAL::UARTDriver *);
- };
- #endif // HAL_SUPPORT_RCOUT_SERIAL
|