Serial Flow Control

I am working on a project in which I need to send large ammounts of data to the arduino, but the arduino processes the data (by design) much to slow to accept it all before overfilling the buffer. I am wondering if somebody here might be able to assist me in building either hardware or software, or both type of flow control into the arduino's serial library, and allowing one to be chosen in the setup method. I think this would be a great addition to the arduino core, and would really appreciate some help.

The problem with building any kind of flow control into the serial function is that serial communication is two way. Whatever "I'm ready" message the Arduino sent would have to be understood and implemented in EVERY device that wanted to talk to the Arduino, whether it was reading from, or writing to, the Arduino, and whether the processing on the Arduino was slow or fast.

Implementing flow control yourself is easy, since you control both ends of the communication link.

When the Arduino is ready to receive, it could send a single letter, 'G' for go.

The sender would do whatever it wanted, while watching for a 'G' from the Arduino. When it saw a 'G' from the Arduino, it would send whatever packet of data the Arduino needed to perform some operation, and then go back to waiting for another 'G'.

The Arduino, after sending a 'G', would wait for data to process, read that data, process it, and, then, send another 'G'.

Anything more specific than this would require more knowledge of your sending application, the type and size of data being sent, and the type of processing being performed on the Arduino.

Flow control usually falls into two different methods, software control via control characters (the old Xon or Xoff protocol for example) or by using some of the defined RS-232 control line signals.

The software method means you are somewhat resistive to what data you can send as pure binary data might be interpreted as control commands rather then as a data byte. It works OK for sending Ascii printable characters, etc.

The hardware method would be pretty easy at the Arduino end because the built in FTDI chip already breaks out some of those RS-232 control signals (but at TTL volatge levels) but doesn't wire them to the AVR processor chip. Short wire jumpers to digital input and output pins would allow your Arduino program to signal the other end of the comm link to stop or start it's data stream. You would however also have to program or configure the other end of the link to also control and respond to those control signals for proper data flow control.

Lefty

Is there a way to read if the serial buffer is full, and/or how big is it on the 328P Duemilanove. I was planning on using Xon/Xoff, as I am communicating with my computer, which already has Xon/Xoff implemented. I realized that even if I know how big the serial buffer is, I cannot build the Xon/Xoff sending part into the loop, as the loop takes as long as what I am doing in it, so by the time it has counted up, and is ready to send the off command, it will be to late. Any idea how i could keep track of how filled the buffer is?

Edit:
From what I can tell, the best way seems to be to put it in the hardwareserial.cpp file, in the store_char function. I just cannot make heads or tales enough of what is happening in there, to be able to do it myself. Any suggestions on what I could do. If worse comes to worse, can I just increase the size of the serial buffer by changing the RX_BUFFER_SIZE definition to a higher number?

Edit 2:
I edited the store_char function to hopefully enable transmitting of the Xoff character, but haven’t tried it yet. I was told on another forum to put the test for the empty buffer into the read function, but don’t know how to test if the buffer is empty. In the mean time Here is what I changed

int flow_count = 0;

inline void store_char(unsigned char c, ring_buffer *rx_buffer)
{
      int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE;

      // if we should be storing the received character into the location
      // just before the tail (meaning that the head would advance to the
      // current location of the tail), we're about to overflow the buffer
      // and so we don't write the character or advance the head.
      if (i != rx_buffer->tail) {
            rx_buffer->buffer[rx_buffer->head] = c;
            rx_buffer->head = i;
      }
      flow_count++;
      if(flow_count >= 120) {
            while (!((*_ucsra) & (1 << _udre)))
            ;

      *_udr = 0x13;
      }
}

Does that look right?