-
Notifications
You must be signed in to change notification settings - Fork 0
/
qsp.cpp
137 lines (118 loc) · 3.49 KB
/
qsp.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "Arduino.h"
#include "variables.h"
#include "qsp.h"
uint8_t crc8_dvb_s2(uint8_t crc, uint8_t a)
{
crc ^= a;
for (int ii = 0; ii < 8; ++ii) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0xD5;
} else {
crc = crc << 1;
}
}
return crc;
}
void qspComputeCrc(QspConfiguration_t *qsp, uint8_t dataByte)
{
qsp->crc = crc8_dvb_s2(qsp->crc, dataByte);
}
void qspClearPayload(QspConfiguration_t *qsp)
{
for (uint8_t i = 0; i < QSP_PAYLOAD_LENGTH; i++)
{
qsp->payload[i] = 0;
}
qsp->payloadLength = 0;
}
/**
* Init CRC with salt based on 4 byte bind key
*/
void qspInitCrc(QspConfiguration_t *qsp, uint8_t bindKey[]) {
qsp->crc = 0;
for (uint8_t i = 0; i < 4; i++) {
qspComputeCrc(qsp, bindKey[i]);
}
}
qspDecodingStatus_e qspDecodeIncomingFrame(
QspConfiguration_t *qsp,
uint8_t incomingByte,
uint8_t bindKey[]
) {
static uint8_t frameId;
static uint8_t payloadLength;
static uint8_t receivedPayload;
static uint8_t receivedChannel;
if (qsp->protocolState == QSP_STATE_IDLE)
{
qspInitCrc(qsp, bindKey);
qspClearPayload(qsp);
receivedPayload = 0;
qsp->frameDecodingStartedAt = millis();
//Frame ID and payload length
qspComputeCrc(qsp, incomingByte);
qsp->frameId = (incomingByte >> 4) & 0x0f;
//If frameID makes no sense, mark it all as faulty frame
if (qsp->frameId >= QSP_FRAME_COUNT) {
qsp->protocolState = QSP_STATE_IDLE;
return QSP_DECODING_STATUS_ERROR;
}
payloadLength = qspFrameLengths[qsp->frameId];
receivedChannel = incomingByte & 0x0f;
qsp->protocolState = QSP_STATE_FRAME_TYPE_RECEIVED;
}
else if (qsp->protocolState == QSP_STATE_FRAME_TYPE_RECEIVED)
{
if (receivedPayload >= QSP_PAYLOAD_LENGTH) {
qsp->protocolState = QSP_STATE_IDLE;
}
//Now it's time for payload
qspComputeCrc(qsp, incomingByte);
qsp->payload[receivedPayload] = incomingByte;
receivedPayload++;
if (receivedPayload == payloadLength)
{
qsp->protocolState = QSP_STATE_PAYLOAD_RECEIVED;
qsp->payloadLength = payloadLength;
}
}
else if (qsp->protocolState == QSP_STATE_PAYLOAD_RECEIVED)
{
if (qsp->crc == incomingByte) {
//CRC is correct
qsp->onSuccessCallback(receivedChannel);
} else {
qsp->onFailureCallback();
}
// In both cases switch to listening for next preamble
qsp->protocolState = QSP_STATE_IDLE;
}
return QSP_DECODING_STATUS_OK;
}
/**
* Encode frame is corrent format and write to hardware
*/
void qspEncodeFrame(
QspConfiguration_t *qsp,
uint8_t buffer[],
uint8_t *size,
uint8_t radioChannel,
uint8_t bindKey[]
) {
//Salt CRC with bind key
qspInitCrc(qsp, bindKey);
//Write frame type and length
// We are no longer sending payload length, so 4 bits are now free for other usages
// uint8_t data = qsp->payloadLength & 0x0f;
uint8_t data = radioChannel;
data |= (qsp->frameToSend << 4) & 0xf0;
qspComputeCrc(qsp, data);
buffer[0] = data;
for (uint8_t i = 0; i < qsp->payloadLength; i++)
{
qspComputeCrc(qsp, qsp->payload[i]);
buffer[i + 1] = qsp->payload[i];
}
buffer[qsp->payloadLength + 1] = qsp->crc;
*size = qspFrameLengths[qsp->frameToSend] + 2; //Total length of QSP frame
}