• We recently switched our forum platform. If you experience any issues please email support@crystalfontz.com

CFA63x Protocol

Heffo

New member
Hi,

I was wondering what would be the best way to re-sync with the data coming from a CFA63x.

Say you start to receive a packet like this...

Command = 0x43 [Response to Read User Flash, could be any command]
Length = 0x87 [ Data Length, Obviously corrupt, largest valid data length is 0x16 (22)]

If from this point, I read 0x87 bytes of data, I will read the rest of this packet (including CRC) and probably the next few incoming packets, as data.

If I discard what I have read then I have the remainder of this packet in my serial RX buffer.

Any thoughts?

Also, I noticed the command codes are nice and sequential across all the units, except command 15 which is missing?

Sending a Cmd 15 with the 635 WinTest with no data (or a basic packet like 0x01) returns a valid response with a command reported as QueryFans. My 635 has no fans attached owing to the fact that it is sitting on top of my scanner on my bench not down in the tower.

Does the command work or is it borked somehow?

Regards,
Robert Heffernan
Looking for additional LCD resources? Check out our LCD blog for the latest developments in LCD technology.
 

CF Mark

Administrator
I resync (only done on LCD init) using a few full length ping packets.
After init, ive never found resyncs necessary as all incoming packets are buffered and processed.
All corrupted, short, etc recieved packets are discarded.

Command 15 was used in an early FW version of the 633 (and maybe others).
While im just guessing here (CF_Techwill know the answer), command 15 was probably later seen as being unnecessary, and dropped to make way for other FW code.
 
First off, I have absolutely no experience with the CFA6xx serial displays. However, I am a programmer with a large amount of comm protocol type code experience. I took a quick look at the CFA635 data sheet, to see what's involved. Here is my suggestion:

When you encounter a bad packet, test the input buffer for the next packet for validity. If it's good, you are in sync. If it's bad or the input times out without a full packet, send a ping packet:
0x00 0x04 0x55 0xAA 0x3C 0xC3 [CRCL] [CRCH] (or such other data that you think will be unique). Then parse the input buffer until the expected response is received:
0x40 0x04 0x55 0xAA 0x3C 0xC3 , and the CRC is valid....
OR until 250 ms elapses without any input.

This may involve discarding valid report packets until sync is verified. You might disable reporting while 'syncing', to simplify the process.

(edit: while I was reading the datasheet, CCAdmin beat me to it.)
 
Last edited:

Heffo

New member
Thanks guys,

I have been thinking of it for a while myself, and thought of reading bytes and dumping them until I get a valid command & length byte. I like cosmicvoid's ping packet idea, but changed a little, i'll send a ping with very specific data, and discard bytes until I get that data back. I'll discard another 2 bytes after that (packet CRC) and I should be back in action.

I am only worried about the sync since I want the code I am writing to be as robust and error-tolerant as possible. I am also working on another tool to help with that.

Regards,
Robert
 
... i'll send a ping with very specific data, and discard bytes until I get that data back. I'll discard another 2 bytes after that (packet CRC) and I should be back in action..
To be really robust, don't discard the CRC bytes for your expected data ping; apply them to the packet. How would you know the packet was really valid, and not just a coincidence of bad data that imitated your packet?
 

CF Tech

Administrator
From this page:

http://www.crystalfontz.com/software/633WinTest

download:

http://www.crystalfontz.com/software/633WinTest#docs

and look in serial.cpp for ubyte check_for_packet(void):
Code:
//============================================================================
//                              check_for_packet()
//
// check_for_packet() will see if there is a valid packet in the input buffer.
// If there is, it will copy it into incoming_response and return 1. If there
// is not it will return 0. incoming_packet may get partially filled with
// garbage if there is not a valid packet available.
//----------------------------------------------------------------------------

int
  tossed=0;

ubyte check_for_packet(void)
  {
  //Clear the return packet.
  memset(&incoming_response,0,sizeof(COMMAND_PACKET));
  Sync_Read_Buffer();
  ubyte
    i;
  //First off, there must be at least 4 bytes available in the input stream
  //for there to be a valid command in it (command, length, no data, CRC).
  if(BytesAvail()<4)
    return(0);
  //The "peek" stuff allows us to look into the RS-232 buffer without
  //removing the data.
  Sync_Peek_Pointer();
  //Only commands 0 through MAX_COMMAND are valid.
  if(MAX_COMMAND<(0x3F&(incoming_response.command=PeekByte())))
    {
    //Throw out one byte of garbage. Next pass through should re-sync.
    GetByte();
    tossed++;
    return(0);
    }
  //There is a valid command byte. Get the data_length. The data length
  //must be within reason.
  if(MAX_DATA_LENGTH<(incoming_response.data_length=PeekByte()))
    {
    //Throw out one byte of garbage. Next pass through should re-sync.
    GetByte();
    tossed++;
    return(0);
    }
  //Now there must be at least incoming_response.data_length+sizeof(CRC) bytes
  //still available for us to continue.
  if((int)PeekBytesAvail()<(incoming_response.data_length+2))
    //It looked like a valid start of a packet, but it does not look
    //like the complete packet has been received yet.
    return(0);
  //There is enough data to make a packet. Transfer over the data.
  for(i=0;i<incoming_response.data_length;i++)
    incoming_response.data[i]=PeekByte();
  //Now move over the CRC.
  incoming_response.CRC.as_bytes[0]=PeekByte();
  incoming_response.CRC.as_bytes[1]=PeekByte();
  //Now check the CRC.
  if(incoming_response.CRC.as_word==
     get_crc((ubyte *)&incoming_response,incoming_response.data_length+2))
    {
    //This is a good packet. I'll be horn swaggled. Remove the packet
    //from the serial buffer.
    AcceptPeekedData();
    //Let our caller know that incoming_response has good stuff in it.
    return(1);
    }
  //The CRC did not match. Toss out one byte of garbage. Next pass through
  //should re-sync.
  GetByte();
  tossed++;
  return(0);
  }
//============================================================================
That routine will find any valid packets in any arbitrary noise, and automatically re-syncs as quickly as possible (on a byte-by-byte basis). It essentially slides a "template" byte-by-byte along the serial data stream looking for matches, and only throws out the absolute minimum data that absolutely has to be in error.

You will need to have the ability to "peek" (inspect without removing data) into your incoming serial data stream. Since that is not directly possible with the windows serial stuff, I add a small buffer between windows an check_for_packet() that allows peeking.
 
Top