I have been working on a MEGA 2560 project for quite some time, and it has been going well so far. This time, adding some more software I found a problem that I thought I was fine with. Reading in serial data (MIDI, at 31-something Kbps), I was receiving Sys-X dumps from synthesizers and storing it to EEPROMs. (For older Korg DW-6000 and DW-8000) But I am now adding a new model, the Kawai K3m and it's a bit different. It doesn't have much more data, but it splits all the data into 4-bit nibbles so it sends a lot more bytes in one burst. The Korgs send send over 3000 bytes for a dump and that has worked reliably for hundreds of dumps.
The Korgs send data in 32 and 57 byte bursts, but the Kawai is sending a 78 byte burst, and after 63 bytes it quits consistently. Clearly the 64-byte Rx buffer is being overrun. I took out all the things I thought could be dragging the speed down (combining nibbles and storing them), and just did a quick get-and-save into an array now. But it still conks out at 63 bytes. So apparently I don't quite understand how to keep the buffer from overrunning.
Here's the stripped-down code from the Kawai that isn't working. I don't know how to get it much more efficient. I also present for comparison the two older routines that proved solid for thousands of dumps, where I do a lot of processing in the while loop before getting the next byte, I don't know why this routine isn't clearing out the Rx buffer in time. Of course the Kawai is a 35+ year old machine, so there's no option to get in and modify the code or the bit rate. It is what it is.
Please, please do not ask me to provide the whole program. It's 21908 lines of code. I'm not even sure I can post that much. I don't believe it is very relevant to this overrun.
The Kawai code snippet that is not working:
byte K3input[78]; //stores MIDI input before processing data.
byte MIDIinput = 0;
int count = 1; //counts for 7+70+1=78 bytes received, then exits. 7 is header, 70 is data chunk (35x2), and 1 is EOX.
while (count < 79) {
if (Serial1.available()) {
MIDIinput = Serial1.read();
if (MIDIinput != 0xFE) {
K3input[count] = MIDIinput;
count++;
}
}
}
And the same section in the DW6000 that works:
timeout = millis() + 4000; //4 second timeout
while ( (count < 57) && (timeout > millis() ) ) {
if (Serial1.available()) {
MIDIinput = Serial1.read();
if (EchoOut==true) { Serial3.write(MIDIinput); }
count++;
}
//MANY OTHER STATEMENTS HERE
}
And the DW8000 code that works:
timeout = millis() + 4000; //4 second timeout
while ( (count < 32) && (timeout>millis()) ) {
if (Serial1.available()) {
MIDIinput = Serial1.read();
if (EchoOut==true) { Serial3.write(MIDIinput); }
count++;
}
//MANY OTHER STATEMENTS HERE
}
These other two working examples that show "MANY OTHER STATEMENTS HERE" have pages of data moving and shuffling, masking and combining before re-looping in the while loop to read another byte of data, so I can't figure out what is so slow about the first, non-working example. Exactly how the bytes are processed in the examples is different, but the fundamental Rx of the data into the program was cut & pasted.
I read as much as I practically can in the forums, and found topics that touch on the matter, but not really addressing the overruns directly, they seem to show this tight loop will work. I also have a hard time believing a nearly 40 year old appliance would have a processor that can overload a (properly programmed) AT processor today. So yea, the problem has to be me and my code. Hopefully someone can spot where my obvious brain-fart has made it's mark.