Poor performance reading data at 19,200, can it do this?

Hi All...

I have a project with a Sanguino (644P chip) in which I need to read a stream of serial binary data at 19,200 and do some processing on it, then log the results and do a few other things. The trouble is, it seems to take more processing power than I have available just to read the data in and assemble the packet. I am using a hardware port on the Sanguino with the hardware serial library.

My code is lengthy, but basically it reads a byte, checks to make sure it is > -1, then stors it in the proper spot in a data structure. The headers are all 4 bytes, including a byte that says how many bytes are int he payload, usually between 1 and 7. It then flags what kind of byte is expected next, and repeats. Once I have the packet and payload I do the checksum.

Once there is one error, there is a rash of them. So, after an error I flush() the Serial port, which throws away all the buffered data but lets me re-sync and receive more packets until the next error.

I have hacked HardwareSerial.cpp and increased the 128 byte buffer to 256, but all tht did was slightly postpone the enevitable.

So I'm at a loss. I think i am loosing bytes, but I'm not sure. Is an Arduino/Sanguino up to this task or am I asking too much from it?

Thanks...

You do not show us your code and you do not tell us anything about the sending device.....

How does the sending device send data ? in bursts ? continously ? at randdom intervals ?

at 19.200 baud and with each byte using 10 bits including the start and stop bits you could potentially be dealing with 1920 incoming bytes a second, depending on the sending side......

Well I'm not trying to hide the code, its just that its a little on the long side, but I'll paste it below. The data is a continious stream of nonstop binary data.

Thanks very much.

loop() 
{
  unsigned char readByte = 0;
  short raw = 0;
  
  raw = Serial1.read();
    
  if(raw >= 0) // If we didn't read a byte, its because none was available
  {
    // We did read a byte
    readByte = (unsigned char) raw;  
 
    // This function returns true if we have both a valid header
    // and a valid payload.
    bool result = processInByte(readByte);
   
    if(result)
    {
      // At this point it appears we have a valid packet header and packet payload. We can
      // now go ahead and process the data inside the packets.  

      processPacket();
      
      // If we're logging the NXB data, do it now
      if(logNxb)
      {
        logNxbPacket();
      }

      // Save data to the log
      if(logCsv)
      {
        if(logNow)
        {
          logNow = false;
          dataRec.logCsvRecord();
        }  
      }
    }
  }
  
  // * 
  // *
  // Check for button inpuit here
  // *
  // *

}
// Return true only when both header and payload packets are valid
bool processInByte(unsigned char readByte)
{
  errorLed.off();
  
  // The first byte of a new packet is 0x81, but we make sure
  // When reading real data we may start our of sync, so we will need to sync up
  // Also, an 0x81 byte may come along as part of the payload or header 
  // data, so we use the inProcessFlag to determine if we're assembling
  // a packet or waiting for one to start.
  
  if(readByte == 0x81 && !inProcessFlag) // Is this a "start of packet" byte?
  {
    // Flag that we are inside a packet
    inProcessFlag = true;
    payloadPos = 0;
        
    gHeader.setStartOfPacket(readByte);
    byteType = 'A'; // set for next read
    return false;
  }  
    
  switch(byteType)
  {  
    case 'A':
      gHeader.setPacketId(readByte);
      byteType = 'B';
      return false;
     
    case 'B':
      gHeader.setNumDataBytes(readByte);
      byteType = 'C';
      return false;
     
    case 'C':
      gHeader.setChecksum(readByte);
      byteType = 'D';
    
      if(!gHeader.isValid())
      {
        // some error occured reading the packet header. We may be out of sync or
        // the data may be corrupted on read. Either way, we can not process this
        // packet.

        errorLed.on();
       
        badPacketCounter++;

        if(wrtSerial)
        {
          Serial << "Bad Header" << endl;
          Serial << "Good Packets: " << goodPacketCounter << " Bad Packets: " << badPacketCounter << endl;
        }
      
        if(debugLog)
        {
          debugLogFile << "Bad Header" << endl;
          debugLogFile << "Good Packets: " << goodPacketCounter << " Bad Packets: " << badPacketCounter << endl;
          debugLogFile.sync();
        }
      
        // At this point, we just kill incoming bytes until the next SOP and start again
        inProcessFlag = false;       
        return false;
      }  
      else
      {
        // We have a valid header.
        return false; // Still need valid payload to return true
      }
   
    case 'D':
      // If we don't have a valid header, we just consume bytes
      // until the next SOP byte comes along.
      if(!gHeader.isValid())
      {
        return false;
      }   

      // Start payload data
      gPayload[payloadPos] = readByte;
      payloadPos++;
      if(payloadPos == gHeader.getNumDataBytes())
      {
        byteType = 'E';
      }  
      return false; // go for the next byte
   
    case 'E':
      // Serial << "E: process Status Byte: " << _HEX(readByte) << endl;
      // This is the last byte of the packet
      inProcessFlag = false;
      byteType = 'Z';  
       
      gHeader.setPayloadStatus(readByte);

      // Test the statusByte to make sure the checksum is valid
      unsigned char statusTemp = 0;
      for(unsigned char s = 0; s < gHeader.getNumDataBytes(); s++)
      {
        statusTemp ^= gPayload[s];
      }

      if(statusTemp != gHeader.getPayloadStatus())
      {
        // Bad payload. We can't use this packet.
        badPacketCounter++;
      
        if(wrtSerial)
        {
          Serial << "Good Packets: " << goodPacketCounter << " Bad packets: " << badPacketCounter << endl;
          Serial << "Valid Header: Packet ID " << "DEC: " << _DEC(gHeader.getPacketId()) << " Num DB: " << gHeader.getNumDataBytes() << endl;
          Serial << "BAD PAYLOAD CHECKSUM! Received Status Byte: " << _HEX(gHeader.getPayloadStatus()) << " Calculated Status Byte: " << _HEX(statusTemp) << endl;
          Serial << endl;
        }

        if(debugLog)
        {
          debugLogFile << "Good Packets: " << goodPacketCounter << " Bad packets: " << badPacketCounter << endl;
          debugLogFile << "Valid Header: Packet ID " << "DEC: " << _DEC(gHeader.getPacketId()) << " Num DB: " << gHeader.getNumDataBytes() << endl;
          debugLogFile << "BAD PAYLOAD CHECKSUM! Received Status Byte: " << _HEX(gHeader.getPayloadStatus()) << " Calculated Status Byte: " << _HEX(statusTemp) << endl;
          debugLogFile << endl;
          debugLogFile.sync();
        }
    
        // Give  a visual indication of the error
        errorLed.on();
      
     

        // JWA
        // After we receive a packet which fails its own checksum test, we get into a 
        // condition where many of the following payload packets report file. This is 
        // probably an issue with the code here, but I have not found it yet. Clearing
        // the incoming data buffer resolves this issue, although probably at the price 
        // of a packet. 
        //
        // This needs to be fixed, as this is just a nasty hack workaround.
        Serial1.flush();
      
        return false; 
      }
      else
      {
        // Valid payload!
        //return gHeader.validateChecksum();
        goodPacketCounter++;
        return true;
      }
     
  } // end switch
}