2 ******************************************************************************
5 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
6 * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
7 * @addtogroup GCSPlugins GCS Plugins
9 * @addtogroup Uploader Serial and USB Uploader Plugin
11 * @brief The USB and Serial protocol uploader plugin
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 /** PRIVATE DEFINITIONS **/
37 #define SYNC 225 // Sync character used in Serial Protocol
38 #define ESC 224 // ESC character used in Serial Protocol
39 #define ESC_SYNC 1 // ESC_SYNC character used in Serial Protocol
40 #define ACK_BIT 0x80 // Ack bit, bit 7 of sequence number, 1 = Acknowledge, 0 =
42 // packet location definitions.
48 // Make larger sized integers from smaller sized integers
49 #define MAKEWORD16(ub, lb) ((uint16_t)0x0000 | ((uint16_t)(ub) << 8) | (uint16_t)(lb))
50 #define MAKEWORD32(uw, lw) ((uint32_t)(0x0UL | ((uint32_t)(uw) << 16) | (uint32_t)(lw)))
51 #define MAKEWORD32B(b3, b2, b1, b0) ((uint32_t)((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | ((uint32_t)(b0)))
54 // Used to extract smaller integers from larger sized intergers
55 #define LOWERBYTE(w) (uint8_t)((w) & 0x00ff)
56 #define UPPERBYTE(w) (uint8_t)(((w) & 0xff00) >> 8)
57 #define UPPERWORD(lw) (uint16_t)(((lw) & 0xffff0000) >> 16)
58 #define LOWERWORD(lw) (uint16_t)((lw) & 0x0000ffff)
60 // Macros to operate on a target and bitmask.
61 #define CLEARBIT(a, b) ((a) = (a) & ~(b))
62 #define SETBIT(a, b) ((a) = (a) | (b))
63 #define TOGGLEBIT(a, b) ((a) = (a) ^ (b))
65 // test bit macros operate using a bit mask.
66 #define ISBITSET(a, b) (((a) & (b)) == (b) ? TRUE : FALSE)
67 #define ISBITCLEAR(a, b) ((~(a) & (b)) == (b) ? TRUE : FALSE)
70 /* Flag bit masks...*/
71 #define SENT_SYNCH (0x01)
72 #define ACK_RECEIVED (0x02)
73 #define ACK_EXPECTED (0x04)
75 #define SSP_AWAITING_ACK 0
80 static const uint16_t CRC_TABLE
[] = {
81 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
82 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
83 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
84 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
85 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
86 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
87 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
88 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
89 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
90 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
91 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
92 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
93 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
94 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
95 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
96 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
97 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
98 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
99 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
100 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
101 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
102 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
103 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
104 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
105 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
106 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
107 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
108 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
109 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
110 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
111 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
112 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
115 /** EXTERNAL DATA **/
117 /** EXTERNAL FUNCTIONS **/
119 /** VERIFICATION FUNCTIONS **/
122 /***********************************************************************************************************/
125 * \brief Initializes the communication port for use
126 * \param thisport = pointer to port structure to initialize
127 * \param info = config struct with default values.
131 * Must be called before calling the Send or REceive process functions.
134 void qssp::ssp_Init(const PortConfig_t
*const info
)
136 thisport
->maxRetryCount
= info
->max_retry
;
137 thisport
->timeoutLen
= info
->timeoutLen
;
138 thisport
->txBufSize
= info
->txBufSize
;
139 thisport
->rxBufSize
= info
->rxBufSize
;
140 thisport
->txBuf
= info
->txBuf
;
141 thisport
->rxBuf
= info
->rxBuf
;
142 thisport
->retryCount
= 0;
143 thisport
->sendSynch
= FALSE
; // TRUE;
144 thisport
->rxSeqNo
= 255;
145 thisport
->txSeqNo
= 255;
146 thisport
->SendState
= SSP_IDLE
;
147 thisport
->inputState
= (ReceiveState
)0;
148 thisport
->decodeState
= (DecodeState
)0;
149 thisport
->TxError
= 0;
150 thisport
->RxError
= 0;
151 thisport
->txSeqNo
= 0;
152 thisport
->rxSeqNo
= 0;
156 * \brief Runs the send process, checks for receipt of ack, timeouts and resends if needed.
157 * \param thisport = which port to use
158 * \return SSP_TX_WAITING - waiting for a valid ACK to arrive
159 * \return SSP_TX_TIMEOUT - failed to receive a valid ACK in the timeout period, after retrying.
160 * \return SSP_TX_IDLE - not expecting a ACK packet (no current transmissions in progress)
161 * \return SSP_TX_ACKED - valid ACK received before timeout period.
166 int16_t qssp::ssp_SendProcess()
168 int16_t value
= SSP_TX_WAITING
;
170 if (thisport
->SendState
== SSP_AWAITING_ACK
) {
171 if (sf_CheckTimeout() == TRUE
) {
172 if (thisport
->retryCount
< thisport
->maxRetryCount
) {
176 value
= SSP_TX_WAITING
;
178 // Give up, # of tries has exceeded the limit
179 value
= SSP_TX_TIMEOUT
;
180 CLEARBIT(thisport
->flags
, ACK_RECEIVED
);
181 thisport
->SendState
= SSP_IDLE
;
183 qDebug() << "Send TimeOut!";
187 value
= SSP_TX_WAITING
;
189 } else if (thisport
->SendState
== SSP_ACKED
) {
190 SETBIT(thisport
->flags
, ACK_RECEIVED
);
191 value
= SSP_TX_ACKED
;
192 thisport
->SendState
= SSP_IDLE
;
194 thisport
->SendState
= SSP_IDLE
;
201 * \brief Runs the receive process. fetches a byte at a time and runs the byte through the protocol receive state machine.
202 * \param thisport - which port to use.
203 * \return receive status.
208 int16_t qssp::ssp_ReceiveProcess()
211 int16_t packet_status
= SSP_RX_IDLE
;
214 b
= thisport
->pfSerialRead(); // attempt to read a char from the serial buffer
216 packet_status
= sf_ReceiveState(b
); // process the newly received byte in the receive state machine
218 // keep going until either we received a full packet or there are no more bytes to process
219 } while (packet_status
!= SSP_RX_COMPLETE
&& b
!= -1);
221 return packet_status
;
225 * \brief processes a single byte through the receive state machine.
226 * \param thisport = which port to use
227 * \return current receive status
233 int16_t qssp::ssp_ReceiveByte()
236 int16_t packet_status
= SSP_RX_IDLE
;
238 b
= thisport
->pfSerialRead();
240 packet_status
= sf_ReceiveState(b
);
242 return packet_status
;
246 * \brief Sends a data packet and blocks until timeout or ack is received.
247 * \param thisport = which port to use
248 * \param data = pointer to data to send
249 * \param length = number of data bytes to send. Must be less than 254
250 * \return true = ack was received within number of retries
251 * \return false = ack was not received.
256 uint16_t qssp::ssp_SendDataBlock(uint8_t *data
, uint16_t length
)
258 int16_t packet_status
= SSP_TX_WAITING
;
259 uint16_t retval
= FALSE
;
261 packet_status
= ssp_SendData(data
, length
); // send the data
262 // TODO the loop is non blocking and will spin as fast as the CPU allows
263 while (packet_status
== SSP_TX_WAITING
) { // check the status
264 (void)ssp_ReceiveProcess(); // process any bytes received.
265 packet_status
= ssp_SendProcess(); // check the send status
267 if (packet_status
== SSP_TX_ACKED
) { // figure out what happened to the packet
276 * \brief sends a chunk of data and does not block
277 * \param thisport = which port to use
278 * \param data = pointer to data to send
279 * \param length = number of bytes to send
280 * \return SSP_TX_BUFOVERRUN = tried to send too much data
281 * \return SSP_TX_WAITING = data sent and waiting for an ack to arrive
282 * \return SSP_TX_BUSY = a packet has already been sent, but not yet acked
287 int16_t qssp::ssp_SendData(const uint8_t *data
, const uint16_t length
)
289 int16_t value
= SSP_TX_WAITING
;
291 if ((length
+ 2) > thisport
->txBufSize
) {
292 // TRYING to send too much data.
293 value
= SSP_TX_BUFOVERRUN
;
294 } else if (thisport
->SendState
== SSP_IDLE
) {
296 if (thisport
->sendSynch
== TRUE
) {
297 sf_SendSynchPacket();
303 // TODO this method could allow a task/user to start a synchronisation step if a zero is mistakenly passed to this function.
304 // could add a check for a NULL data pointer, or use some sort of static flag that can only be accessed by a static function
305 // that must be called before calling this function.
306 // we are attempting to send a synch packet
307 thisport
->txSeqNo
= 0; // make this zero to cause the other end to re-synch with us
308 SETBIT(thisport
->flags
, SENT_SYNCH
);
310 // we are sending a data packet
311 CLEARBIT(thisport
->txSeqNo
, ACK_BIT
); // make sure we are not sending a ACK packet
312 thisport
->txSeqNo
++; // update the sequence number.
313 if (thisport
->txSeqNo
> 0x7F) { // check for sequence number rollover
314 thisport
->txSeqNo
= 1; // if we do have rollover then reset to 1 not zero,
315 // zero is reserviced for synchronization requests
320 CLEARBIT(thisport
->txSeqNo
, ACK_BIT
); // make sure we are not sending a ACK packet
321 thisport
->txSeqNo
++; // update the sequence number.
322 if (thisport
->txSeqNo
> 0x7F) { // check for sequence number rollover
323 thisport
->txSeqNo
= 1; // if we do have rollover then reset to 1 not zero,
324 // zero is reserved for synchronization requests
326 #endif // ifdef SYNCH_SEND
327 CLEARBIT(thisport
->flags
, ACK_RECEIVED
);
328 thisport
->SendState
= SSP_AWAITING_ACK
;
329 value
= SSP_TX_WAITING
;
330 thisport
->retryCount
= 0; // zero out the retry counter for this transmission
331 sf_MakePacket(thisport
->txBuf
, data
, length
, thisport
->txSeqNo
);
332 sf_SendPacket(); // punch out the packet to the serial port
333 sf_SetSendTimeout(); // do the timeout values
335 qDebug() << "Sent DATA PACKET:" << thisport
->txSeqNo
;
338 // error we are already sending a packet. Need to wait for the current packet to be acked or timeout.
341 qDebug() << "Error sending TX was busy";
348 * \brief Attempts to synchronize the sequence numbers with the other end of the connection.
349 * \param thisport = which port to use
350 * \return true = success
351 * \return false = failed to receive an ACK to our synch request
354 * A. send a packet with a sequence number equal to zero
355 * B. if timed out then:
356 * send synch packet again
357 * increment try counter
358 * if number of tries exceed maximum try limit then exit
361 uint16_t qssp::ssp_Synchronise()
363 int16_t packet_status
;
364 uint16_t retval
= FALSE
;
366 #ifndef USE_SENDPACKET_DATA
367 thisport
->txSeqNo
= 0; // make this zero to cause the other end to re-synch with us
368 SETBIT(thisport
->flags
, SENT_SYNCH
);
369 // TODO - should this be using ssp_SendPacketData()??
370 sf_MakePacket(thisport
->txBuf
, NULL
, 0, thisport
->txSeqNo
); // construct the packet
373 thisport
->SendState
= SSP_AWAITING_ACK
;
374 packet_status
= SSP_TX_WAITING
;
376 packet_status
= ssp_SendData(NULL
, 0);
378 while (packet_status
== SSP_TX_WAITING
) { // we loop until we time out.
379 ssp_ReceiveProcess(); // do the receive process
380 packet_status
= ssp_SendProcess(); // do the send process
382 thisport
->sendSynch
= FALSE
;
383 switch (packet_status
) {
387 case SSP_TX_BUSY
: // intentional fall through.
388 case SSP_TX_TIMEOUT
: // intentional fall through.
389 case SSP_TX_BUFOVERRUN
:
401 * \brief sends out a preformatted packet for a give port
402 * \param thisport = which port to use.
406 * Packet should be formed through the use of sf_MakePacket before calling this function.
408 void qssp::sf_SendPacket()
410 // add 3 to packet data length for: 1 length + 2 CRC (packet overhead)
411 uint8_t packetLen
= thisport
->txBuf
[LENGTH
] + 3;
413 // use the raw serial write function so the SYNC byte does not get 'escaped'
414 thisport
->pfSerialWrite(SYNC
);
415 for (uint8_t x
= 0; x
< packetLen
; x
++) {
416 sf_write_byte(thisport
->txBuf
[x
]);
418 thisport
->retryCount
++;
422 * \brief converts data to transport layer protocol packet format.
423 * \param txbuf = buffer to use when forming the packet
424 * \param pdata = pointer to data to use
425 * \param length = number of bytes to use
426 * \param seqNo = sequence number of this packet
430 * 1. This function does not try to interpret ACK or SYNCH packets. This should
431 * be done by the caller of this function.
432 * 2. This function will attempt to format all data upto the size of the tx buffer.
433 * Any extra data beyond that will be ignored.
434 * 3. TODO: Should this function return an error if data length to be sent is greater th tx buffer size?
437 void qssp::sf_MakePacket(uint8_t *txBuf
, const uint8_t *pdata
, uint16_t length
, uint8_t seqNo
)
439 uint16_t crc
= 0xffff;
443 // add 1 for the seq. number
444 txBuf
[LENGTH
] = length
+ 1;
445 txBuf
[SEQNUM
] = seqNo
;
446 crc
= sf_crc16(crc
, seqNo
);
448 length
= length
+ 2; // add two for the length and seqno bytes which are added before the loop.
449 for (bufPos
= 2; bufPos
< length
; bufPos
++) {
452 crc
= sf_crc16(crc
, b
); // update CRC value
454 txBuf
[bufPos
++] = LOWERBYTE(crc
);
455 txBuf
[bufPos
] = UPPERBYTE(crc
);
459 * \brief sends out an ack packet to given sequence number
460 * \param thisport = which port to use
461 * \param seqNumber = sequence number of the packet we would like to ack
468 void qssp::sf_SendAckPacket(uint8_t seqNumber
)
470 uint8_t AckSeqNumber
= SETBIT(seqNumber
, ACK_BIT
);
472 // create the packet, note we pass AckSequenceNumber directly
473 sf_MakePacket(thisport
->txBuf
, NULL
, 0, AckSeqNumber
);
476 qDebug() << "Sent ACK PACKET:" << seqNumber
;
478 // we don't set the timeout for an ACK because we don't ACK our ACKs in this protocol
482 * \brief writes a byte out the output channel. Adds escape byte where needed
483 * \param thisport = which port to use
484 * \param c = byte to send
490 void qssp::sf_write_byte(uint8_t c
)
492 if (c
== SYNC
) { // check for SYNC byte
493 thisport
->pfSerialWrite(ESC
); // since we are not starting a packet we must ESCAPE the SYNCH byte
494 thisport
->pfSerialWrite(ESC_SYNC
); // now send the escaped synch char
495 } else if (c
== ESC
) { // Check for ESC character
496 thisport
->pfSerialWrite(ESC
); // if it is, we need to send it twice
497 thisport
->pfSerialWrite(ESC
);
499 thisport
->pfSerialWrite(c
); // otherwise write the byte to serial port
503 /************************************************************************************************************
505 * NAME: uint16_t ssp_crc16( uint16_t crc, uint16_t data )
506 * DESCRIPTION: Uses crc_table to calculate new crc
509 * arg2: data - byte to calculate into CRC
513 *************************************************************************************************************/
515 * \brief calculates the new CRC value for 'data'
516 * \param crc = current CRC value
517 * \param data = new byte
518 * \return updated CRC value
524 uint16_t qssp::sf_crc16(uint16_t crc
, uint8_t data
)
527 return (crc
>> 8) ^ CRC_TABLE
[(crc
^ data
) & 0x00FF];
530 uint8_t cka
= crc
& 0xff;
531 uint8_t ckb
= (crc
>> 8) & 0xff;
534 return cka
| ckb
<< 8;
540 * \brief sets the timeout for the given packet
541 * \param thisport = which port to use
548 void qssp::sf_SetSendTimeout()
552 timeout
= thisport
->pfGetTime() + thisport
->timeoutLen
;
553 thisport
->timeout
= timeout
;
557 * \brief checks to see if a timeout occured
558 * \param thisport = which port to use
559 * \return true = a timeout has occurred
560 * \return false = has not timed out
565 uint16_t qssp::sf_CheckTimeout()
567 uint16_t retval
= FALSE
;
568 uint32_t current_time
;
570 current_time
= thisport
->pfGetTime();
571 if (current_time
> thisport
->timeout
) {
576 qDebug() << "timeout " << current_time
<< thisport
->timeout
;
583 /****************************************************************************
584 * NAME: sf_ReceiveState
585 * DESC: Implements the receive state handling code for escaped and unescaped data
586 * ARGS: thisport - which port to operate on
591 * 1. change from using pointer to functions.
592 ****************************************************************************/
594 * \brief implements the receive state handling code for escaped and unescaped data
595 * \param thisport = which port to use
596 * \param c = byte to process through the receive state machine
597 * \return receive status
602 int16_t qssp::sf_ReceiveState(uint8_t c
)
604 int16_t retval
= SSP_RX_RECEIVING
;
606 switch (thisport
->inputState
) {
607 case state_unescaped_e
:
609 thisport
->decodeState
= decode_len1_e
;
610 } else if (c
== ESC
) {
611 thisport
->inputState
= state_escaped_e
;
613 retval
= sf_DecodeState(c
);
615 break; // end of unescaped state.
616 case state_escaped_e
:
617 thisport
->inputState
= state_unescaped_e
;
619 thisport
->decodeState
= decode_len1_e
;
620 } else if (c
== ESC_SYNC
) {
621 retval
= sf_DecodeState(SYNC
);
623 retval
= sf_DecodeState(c
);
625 break; // end of the escaped state.
632 /****************************************************************************
633 * NAME: sf_DecodeState
634 * DESC: Implements the receive state finite state machine
635 * ARGS: thisport - which port to operate on
640 * 1. change from using pointer to functions.
641 ****************************************************************************/
644 * \brief implements the receiving decoding state machine
645 * \param thisport = which port to use
646 * \param c = byte to process
647 * \return receive status
652 int16_t qssp::sf_DecodeState(uint8_t c
)
656 switch (thisport
->decodeState
) {
658 // 'c' is ignored in this state as the only way to leave the idle state is
659 // recognition of the SYNC byte in the sf_ReceiveState function.
660 retval
= SSP_RX_IDLE
;
664 thisport
->decodeState
= decode_idle_e
;
666 retval
= SSP_RX_IDLE
;
669 thisport
->rxBuf
[LENGTH
] = c
;
670 thisport
->rxBufLen
= c
;
671 if (thisport
->rxBufLen
<= thisport
->rxBufSize
) {
672 thisport
->decodeState
= decode_seqNo_e
;
673 retval
= SSP_RX_RECEIVING
;
675 thisport
->decodeState
= decode_idle_e
;
676 retval
= SSP_RX_IDLE
;
680 thisport
->rxBuf
[SEQNUM
] = c
;
681 thisport
->crc
= 0xffff;
682 thisport
->rxBufLen
--; // subtract 1 for the seq. no.
683 thisport
->rxBufPos
= 2;
685 thisport
->crc
= sf_crc16(thisport
->crc
, c
);
686 if (thisport
->rxBufLen
> 0) {
687 thisport
->decodeState
= decode_data_e
;
689 thisport
->decodeState
= decode_crc1_e
;
691 retval
= SSP_RX_RECEIVING
;
694 thisport
->rxBuf
[(thisport
->rxBufPos
)++] = c
;
695 thisport
->crc
= sf_crc16(thisport
->crc
, c
);
696 if (thisport
->rxBufPos
== (thisport
->rxBufLen
+ 2)) {
697 thisport
->decodeState
= decode_crc1_e
;
699 retval
= SSP_RX_RECEIVING
;
702 thisport
->crc
= sf_crc16(thisport
->crc
, c
);
703 thisport
->decodeState
= decode_crc2_e
;
704 retval
= SSP_RX_RECEIVING
;
707 thisport
->decodeState
= decode_idle_e
;
708 // verify the CRC value for the packet
709 if (sf_crc16(thisport
->crc
, c
) == 0) {
710 // TODO shouldn't the return value of sf_ReceivePacket() be checked?
712 retval
= SSP_RX_COMPLETE
;
715 retval
= SSP_RX_IDLE
;
719 thisport
->decodeState
= decode_idle_e
; // unknown state so reset to idle state and wait for the next start of a packet.
720 retval
= SSP_RX_IDLE
;
726 /************************************************************************************************************
728 * NAME: int16_t sf_ReceivePacket( )
729 * DESCRIPTION: Receive one packet, assumed that data is in rec.buff[]
731 * RETURN: 0 . no new packet was received, could be ack or same packet
732 * 1 . new packet received
734 * SSP_PACKET_COMPLETE
738 *************************************************************************************************************/
740 * \brief receive one packet. calls the callback function if needed.
741 * \param thisport = which port to use
742 * \return true = valid data packet received.
743 * \return false = otherwise
747 * Created: Oct 7, 2010 12:07:22 AM by joe
750 int16_t qssp::sf_ReceivePacket()
752 int16_t value
= FALSE
;
754 if (ISBITSET(thisport
->rxBuf
[SEQNUM
], ACK_BIT
)) {
755 // Received an ACK packet, need to check if it matches the previous sent packet
756 if ((thisport
->rxBuf
[SEQNUM
] & 0x7F) == (thisport
->txSeqNo
& 0x7f)) {
757 // It matches the last packet sent by us
758 SETBIT(thisport
->txSeqNo
, ACK_BIT
);
759 thisport
->SendState
= SSP_ACKED
;
762 qDebug() << "Received ACK:" << (thisport
->txSeqNo
& 0x7F);
765 // else ignore the ACK packet
767 // Received a 'data' packet, figure out what type of packet we received...
768 if (thisport
->rxBuf
[SEQNUM
] == 0) {
770 qDebug() << "Received SYNC Request";
772 // Synchronize sequence number with host
774 thisport
->sendSynch
= TRUE
;
776 sf_SendAckPacket(thisport
->rxBuf
[SEQNUM
]);
777 thisport
->rxSeqNo
= 0;
779 } else if (thisport
->rxBuf
[SEQNUM
] == thisport
->rxSeqNo
) {
780 // Already seen this packet, just ack it, don't act on the packet.
781 sf_SendAckPacket(thisport
->rxBuf
[SEQNUM
]);
785 thisport
->rxSeqNo
= thisport
->rxBuf
[SEQNUM
];
786 // Let the application do something with the data/packet.
788 // skip the first two bytes (length and seq. no.) in the buffer.
790 qDebug() << "Received DATA PACKET seq=" << thisport
->rxSeqNo
<< "Data=" << (uint8_t)thisport
->rxBuf
[2] << (uint8_t)thisport
->rxBuf
[3] << (uint8_t)thisport
->rxBuf
[4];
792 pfCallBack(&(thisport
->rxBuf
[2]), thisport
->rxBufLen
);
794 // after we send the ACK, it is possible for the host to send a new packet.
795 // Thus the application needs to copy the data and reset the receive buffer
796 // inside of thisport->pfCallBack()
797 sf_SendAckPacket(thisport
->rxBuf
[SEQNUM
]);
804 qssp::qssp(port
*info
, bool debug
) : debug(debug
)
807 thisport
->maxRetryCount
= info
->max_retry
;
808 thisport
->timeoutLen
= info
->timeoutLen
;
809 thisport
->txBufSize
= info
->txBufSize
;
810 thisport
->rxBufSize
= info
->rxBufSize
;
811 thisport
->txBuf
= info
->txBuf
;
812 thisport
->rxBuf
= info
->rxBuf
;
813 thisport
->retryCount
= 0;
814 thisport
->sendSynch
= FALSE
; // TRUE;
815 thisport
->rxSeqNo
= 255;
816 thisport
->txSeqNo
= 255;
817 thisport
->SendState
= SSP_IDLE
;
818 thisport
->inputState
= (ReceiveState
)0;
819 thisport
->decodeState
= (DecodeState
)0;
820 thisport
->TxError
= 0;
821 thisport
->RxError
= 0;
822 thisport
->txSeqNo
= 0;
823 thisport
->rxSeqNo
= 0;
826 void qssp::pfCallBack(uint8_t *buf
, uint16_t size
)
831 qDebug() << "receive callback" << buf
[0] << buf
[1] << buf
[2] << buf
[3] << buf
[4];