66KerbalSimpit::KerbalSimpit (Stream &serial)
77{
88 _serial = &serial;
9+ packetDroppedNbr = 0 ;
910}
1011
1112bool KerbalSimpit::init ()
@@ -25,7 +26,6 @@ bool KerbalSimpit::init()
2526 _outboundBuffer[i+1 ] = KERBALSIMPIT_VERSION [i];
2627 }
2728 i = i + 1 ;
28- _receiveState = WaitingFirstByte;
2929 _send (0x00 , _outboundBuffer, i); // Send SYN
3030
3131 // Wait for an answer. If no answer in 1 sec, return false
@@ -38,26 +38,28 @@ bool KerbalSimpit::init()
3838 }
3939 }
4040
41- // Read all the bytes available and look for the SYNACK
41+ _receivedIndex = 0 ;
4242 while (_serial->available ()){
43- if ( _serial->read () == 0xAA ) { // First byte of header
44- while (!_serial-> available ()); // Wait for a next byte
45- if (_serial-> read () == 0x50 ) { // Second byte of header
46- while (!_serial-> available ()); // Wait for a next byte
47- _serial-> read (); // size
48- while (!_serial-> available ()); // Wait for a next byte
49- if (_serial-> read () == 0x00 ) { // type
50- while (!_serial-> available ()); // Wait for a next byte
51- if (_serial-> read () == 0x01 ) { // first byte of payload, we got a SYNACK
52- // TODO: Do we care about tracking handshake state?
53- _outboundBuffer[ 0 ] = 0x02 ;
54- _send ( 0x00 , _outboundBuffer, i); // Send ACK
55- return true ;
56- }
57- }
58- }
43+ _inboundBuffer[_receivedIndex] = _serial->read ();
44+ if (!_inboundBuffer[_receivedIndex]){
45+ cobsDecode (_inboundBuffer, _receivedIndex + 1 , _inboundDecodedBuffer);
46+ _receivedIndex = 0 ;
47+
48+ // Test is the message received is a SYNACK
49+ if (_inboundDecodedBuffer[ 0 ] == SYNC_MESSAGE && _inboundDecodedBuffer[ 1 ] == 0x01 ){
50+ _outboundBuffer[ 0 ] = 0x02 ;
51+ _send ( 0x00 , _outboundBuffer, i); // Send ACK
52+
53+ // Log the serial buffer size
54+ printToKSP ( " Buffer receive size : " + String ( SERIAL_RX_BUFFER_SIZE ));
55+ return true ;
56+ } else {
57+ return false ;
58+ }
5959 }
60+ _receivedIndex ++;
6061 }
62+
6163 return false ;
6264}
6365
@@ -109,59 +111,93 @@ void KerbalSimpit::printToKSP(String msg, byte options){
109111
110112void KerbalSimpit::_send (byte messageType, byte msg[], byte msgSize)
111113{
112- _serial->write (0xAA );
113- _serial->write (0x50 );
114- _serial->write (msgSize);
115- _serial->write (messageType);
116- for (int x=0 ; x<msgSize; x++) {
117- _serial->write (*(msg+x));
114+ _msgBuffer[0 ] = messageType;
115+ byte checksum = messageType;
116+ for (byte i = 0 ; i < msgSize; i++){
117+ _msgBuffer[i+1 ] = msg[i];
118+ checksum ^= msg[i];
118119 }
120+ _msgBuffer[msgSize+1 ] = checksum;
121+
122+ byte encodedMsgSize = cobsEncode (_msgBuffer, msgSize + 2 , _encodedBuffer);
123+ for (byte x=0 ; x<encodedMsgSize; x++) {
124+ _serial->write (_encodedBuffer[x]);
125+ }
126+ _serial->write ((byte) 0 ); // Encoded buffer does not have the null terminating byte.
119127}
120128
121129void KerbalSimpit::update ()
122130{
123- while (_serial->available ()) {
124- _readBuffer = _serial->read ();
125- switch (_receiveState) {
126- case WaitingFirstByte:
127- if (_readBuffer == 0xAA ) {
128- _receiveState = WaitingSecondByte;
129- } else {
130- _receiveState = WaitingFirstByte;
131- }
132- break ;
133- case WaitingSecondByte:
134- if (_readBuffer == 0x50 ) {
135- _receiveState = WaitingSize;
136- } else {
137- _receiveState = WaitingFirstByte;
138- }
139- break ;
140- case WaitingSize:
141- if (_readBuffer > MAX_PAYLOAD_SIZE ) {
142- _receiveState = WaitingFirstByte;
131+ while (_serial->available ()){
132+ _inboundBuffer[_receivedIndex] = _serial->read ();
133+ _receivedIndex ++;
134+
135+ if (!_inboundBuffer[_receivedIndex - 1 ]){
136+ byte decodedSize = cobsDecode (_inboundBuffer, _receivedIndex + 1 , _inboundDecodedBuffer);
137+
138+ // Account for the overhead of 1 byte of COBS
139+ if (decodedSize != _receivedIndex - 1 ){
140+ // Ill-formed packet
141+ packetDroppedNbr ++;
143142 } else {
144- _inboundSize = _readBuffer;
145- _receiveState = WaitingType;
143+ // Check checksum
144+ byte checksum = 0 ;
145+ for (byte x = 0 ; x < decodedSize - 2 ; x++){
146+ checksum ^= _inboundDecodedBuffer[x];
147+ }
148+ if (checksum != _inboundDecodedBuffer[decodedSize-2 ]){
149+ // Discard message, bad checksum
150+ packetDroppedNbr ++;
151+ } else {
152+ _messageHandler (_inboundDecodedBuffer[0 ], _inboundDecodedBuffer + 1 , decodedSize - 3 );
153+ }
146154 }
147- break ;
148- case WaitingType:
149- _inboundType = _readBuffer;
150155 _receivedIndex = 0 ;
151- _receiveState = WaitingData;
152- break ;
153- case WaitingData:
154- _inboundBuffer[_receivedIndex] = _readBuffer;
155- _receivedIndex++;
156- if (_receivedIndex == _inboundSize) {
157- _receiveState = WaitingFirstByte;
158- if (_messageHandler != NULL ) {
159- _messageHandler (_inboundType, _inboundBuffer, _inboundSize);
160- }
161- }
162- break ;
163- default :
164- _receiveState = WaitingFirstByte;
165156 }
166157 }
167158}
159+
160+ size_t KerbalSimpit::cobsEncode (const void *data, size_t length, uint8_t *buffer)
161+ {
162+ uint8_t *encode = buffer; // Encoded byte pointer
163+ uint8_t *codep = encode++; // Output code pointer
164+ uint8_t code = 1 ; // Code value
165+
166+ for (const uint8_t *byte = (const uint8_t *)data; length--; ++byte)
167+ {
168+ if (*byte) // Byte not zero, write it
169+ *encode++ = *byte, ++code;
170+
171+ if (!*byte || code == 0xff ) // Input is zero or block completed, restart
172+ {
173+ *codep = code, code = 1 , codep = encode;
174+ if (!*byte || length)
175+ ++encode;
176+ }
177+ }
178+ *codep = code; // Write final code value
179+
180+ return (size_t )(encode - buffer);
181+ }
182+
183+ size_t KerbalSimpit::cobsDecode (const uint8_t *buffer, size_t length, void *data)
184+ {
185+ const uint8_t *byte = buffer; // Encoded input byte pointer
186+ uint8_t *decode = (uint8_t *)data; // Decoded output byte pointer
187+
188+ for (uint8_t code = 0xff , block = 0 ; byte < buffer + length; --block)
189+ {
190+ if (block) // Decode block byte
191+ *decode++ = *byte++;
192+ else
193+ {
194+ if (code != 0xff ) // Encoded zero, write it
195+ *decode++ = 0 ;
196+ block = code = *byte++; // Next block length
197+ if (!code) // Delimiter code found
198+ break ;
199+ }
200+ }
201+
202+ return (size_t )(decode - (uint8_t *)data);
203+ }
0 commit comments