7 #if defined(USE_MSP_OVER_TELEMETRY)
9 #include "build/build_config.h"
11 #include "common/utils.h"
13 #include "fc/fc_msp.h"
17 #include "telemetry/crsf.h"
18 #include "telemetry/msp_shared.h"
19 #include "telemetry/smartport.h"
21 #define TELEMETRY_MSP_VERSION 1
22 #define TELEMETRY_MSP_VER_SHIFT 5
23 #define TELEMETRY_MSP_VER_MASK (0x7 << TELEMETRY_MSP_VER_SHIFT)
24 #define TELEMETRY_MSP_ERROR_FLAG (1 << 5)
25 #define TELEMETRY_MSP_START_FLAG (1 << 4)
26 #define TELEMETRY_MSP_SEQ_MASK 0x0F
27 #define TELEMETRY_MSP_RES_ERROR (-10)
30 TELEMETRY_MSP_VER_MISMATCH
=0,
31 TELEMETRY_MSP_CRC_ERROR
=1,
35 STATIC_UNIT_TESTED
uint8_t checksum
= 0;
36 STATIC_UNIT_TESTED mspPackage_t mspPackage
;
37 static mspRxBuffer_t mspRxBuffer
;
38 static mspTxBuffer_t mspTxBuffer
;
39 static mspPacket_t mspRxPacket
;
40 static mspPacket_t mspTxPacket
;
42 void initSharedMsp(void)
44 mspPackage
.requestBuffer
= (uint8_t *)&mspRxBuffer
;
45 mspPackage
.requestPacket
= &mspRxPacket
;
46 mspPackage
.requestPacket
->buf
.ptr
= mspPackage
.requestBuffer
;
47 mspPackage
.requestPacket
->buf
.end
= mspPackage
.requestBuffer
;
49 mspPackage
.responseBuffer
= (uint8_t *)&mspTxBuffer
;
50 mspPackage
.responsePacket
= &mspTxPacket
;
51 mspPackage
.responsePacket
->buf
.ptr
= mspPackage
.responseBuffer
;
52 mspPackage
.responsePacket
->buf
.end
= mspPackage
.responseBuffer
;
55 static void processMspPacket(void)
57 mspPackage
.responsePacket
->cmd
= 0;
58 mspPackage
.responsePacket
->result
= 0;
59 mspPackage
.responsePacket
->buf
.end
= mspPackage
.responseBuffer
;
61 mspPostProcessFnPtr mspPostProcessFn
= NULL
;
62 if (mspFcProcessCommand(mspPackage
.requestPacket
, mspPackage
.responsePacket
, &mspPostProcessFn
) == MSP_RESULT_ERROR
) {
63 sbufWriteU8(&mspPackage
.responsePacket
->buf
, TELEMETRY_MSP_ERROR
);
65 if (mspPostProcessFn
) {
66 mspPostProcessFn(NULL
);
69 sbufSwitchToReader(&mspPackage
.responsePacket
->buf
, mspPackage
.responseBuffer
);
72 void sendMspErrorResponse(uint8_t error
, int16_t cmd
)
74 mspPackage
.responsePacket
->cmd
= cmd
;
75 mspPackage
.responsePacket
->result
= 0;
76 mspPackage
.responsePacket
->buf
.end
= mspPackage
.responseBuffer
;
78 sbufWriteU8(&mspPackage
.responsePacket
->buf
, error
);
79 mspPackage
.responsePacket
->result
= TELEMETRY_MSP_RES_ERROR
;
80 sbufSwitchToReader(&mspPackage
.responsePacket
->buf
, mspPackage
.responseBuffer
);
83 bool handleMspFrame(uint8_t *frameStart
, int frameLength
)
85 static uint8_t mspStarted
= 0;
86 static uint8_t lastSeq
= 0;
88 if (sbufBytesRemaining(&mspPackage
.responsePacket
->buf
) > 0) {
92 if (mspStarted
== 0) {
96 mspPacket_t
*packet
= mspPackage
.requestPacket
;
97 sbuf_t
*frameBuf
= sbufInit(&mspPackage
.requestFrame
, frameStart
, frameStart
+ (uint8_t)frameLength
);
98 sbuf_t
*rxBuf
= &mspPackage
.requestPacket
->buf
;
99 const uint8_t header
= sbufReadU8(frameBuf
);
100 const uint8_t seqNumber
= header
& TELEMETRY_MSP_SEQ_MASK
;
101 const uint8_t version
= (header
& TELEMETRY_MSP_VER_MASK
) >> TELEMETRY_MSP_VER_SHIFT
;
103 if (version
!= TELEMETRY_MSP_VERSION
) {
104 sendMspErrorResponse(TELEMETRY_MSP_VER_MISMATCH
, 0);
108 if (header
& TELEMETRY_MSP_START_FLAG
) {
109 // first packet in sequence
110 uint8_t mspPayloadSize
= sbufReadU8(frameBuf
);
112 packet
->cmd
= sbufReadU8(frameBuf
);
114 packet
->buf
.ptr
= mspPackage
.requestBuffer
;
115 packet
->buf
.end
= mspPackage
.requestBuffer
+ mspPayloadSize
;
117 checksum
= mspPayloadSize
^ packet
->cmd
;
119 } else if (!mspStarted
) {
120 // no start packet yet, throw this one away
122 } else if (((lastSeq
+ 1) & TELEMETRY_MSP_SEQ_MASK
) != seqNumber
) {
123 // packet loss detected!
128 const uint8_t bufferBytesRemaining
= sbufBytesRemaining(rxBuf
);
129 const uint8_t frameBytesRemaining
= sbufBytesRemaining(frameBuf
);
130 uint8_t payload
[frameBytesRemaining
];
132 if (bufferBytesRemaining
>= frameBytesRemaining
) {
133 sbufReadData(frameBuf
, payload
, frameBytesRemaining
);
134 sbufAdvance(frameBuf
, frameBytesRemaining
);
135 sbufWriteData(rxBuf
, payload
, frameBytesRemaining
);
140 sbufReadData(frameBuf
, payload
, bufferBytesRemaining
);
141 sbufAdvance(frameBuf
, bufferBytesRemaining
);
142 sbufWriteData(rxBuf
, payload
, bufferBytesRemaining
);
143 sbufSwitchToReader(rxBuf
, mspPackage
.requestBuffer
);
144 while (sbufBytesRemaining(rxBuf
)) {
145 checksum
^= sbufReadU8(rxBuf
);
148 if (checksum
!= *frameBuf
->ptr
) {
150 sendMspErrorResponse(TELEMETRY_MSP_CRC_ERROR
, packet
->cmd
);
156 sbufSwitchToReader(rxBuf
, mspPackage
.requestBuffer
);
161 bool sendMspReply(uint8_t payloadSize
, mspResponseFnPtr responseFn
)
163 static uint8_t checksum
= 0;
164 static uint8_t seq
= 0;
166 uint8_t payloadOut
[payloadSize
];
168 sbuf_t
*payloadBuf
= sbufInit(&payload
, payloadOut
, payloadOut
+ payloadSize
);
169 sbuf_t
*txBuf
= &mspPackage
.responsePacket
->buf
;
171 // detect first reply packet
172 if (txBuf
->ptr
== mspPackage
.responseBuffer
) {
175 uint8_t head
= TELEMETRY_MSP_START_FLAG
| (seq
++ & TELEMETRY_MSP_SEQ_MASK
);
176 if (mspPackage
.responsePacket
->result
< 0) {
177 head
|= TELEMETRY_MSP_ERROR_FLAG
;
179 sbufWriteU8(payloadBuf
, head
);
181 uint8_t size
= sbufBytesRemaining(txBuf
);
182 sbufWriteU8(payloadBuf
, size
);
185 sbufWriteU8(payloadBuf
, (seq
++ & TELEMETRY_MSP_SEQ_MASK
));
188 const uint8_t bufferBytesRemaining
= sbufBytesRemaining(txBuf
);
189 const uint8_t payloadBytesRemaining
= sbufBytesRemaining(payloadBuf
);
190 uint8_t frame
[payloadBytesRemaining
];
192 if (bufferBytesRemaining
>= payloadBytesRemaining
) {
194 sbufReadData(txBuf
, frame
, payloadBytesRemaining
);
195 sbufAdvance(txBuf
, payloadBytesRemaining
);
196 sbufWriteData(payloadBuf
, frame
, payloadBytesRemaining
);
197 responseFn(payloadOut
);
203 sbufReadData(txBuf
, frame
, bufferBytesRemaining
);
204 sbufAdvance(txBuf
, bufferBytesRemaining
);
205 sbufWriteData(payloadBuf
, frame
, bufferBytesRemaining
);
206 sbufSwitchToReader(txBuf
, mspPackage
.responseBuffer
);
208 checksum
= sbufBytesRemaining(txBuf
) ^ mspPackage
.responsePacket
->cmd
;
210 while (sbufBytesRemaining(txBuf
)) {
211 checksum
^= sbufReadU8(txBuf
);
213 sbufWriteU8(payloadBuf
, checksum
);
215 while (sbufBytesRemaining(payloadBuf
)>1) {
216 sbufWriteU8(payloadBuf
, 0);
221 responseFn(payloadOut
);