I am using an Arduino Due with an SD where i store .wav files. A utility is already made that can read data from the serial port. It receives a large CHUNK that reads in 4096 Bytes pieces:
if (strcmp(command, "CHUNK") == 0) {
// t_chunk is index of the chunk. Given that the chunk size (524288 == 512Kb) is larger than the wav file (482278) data will only be sent in CHUNK 0 with all the data.
// to_receive is the size of data being sent, in this case 482278
char fname_buffer[12];
t_chunk = atoi(SerialIO.get_param(0));
to_receive = atoi(SerialIO.get_param(1));
sprintf(fname_buffer, "tmp_%lu.up", t_chunk);
_tmp_file = BingMachine.SD.open(fname_buffer, O_WRITE | O_TRUNC | O_CREAT);
total_read = t_chunk * FIO_CHUNK_SIZE;
this_read = 0;
_error = OK;
while (this_read < to_receive) {
if (to_receive - this_read < FIO_TX_SIZE) { //FIO_TX_SIZE == 4096
to_read = to_receive - this_read;
} else {
to_read = FIO_TX_SIZE;
}
read = Serial.readBytes(_buffer, to_read);
if (read == 0) {
// This is a timeout handler
}
} else {
_tmp_file.write(_buffer, read);
this_read += read;
total_read += read;
}
}
_tmp_file.close();
When the last piece of data is read, and it is smaller than 4096, the amount read (stored in read
is smaller than the ammount requested to_read
.
DEBUG: Received 4096 bytes
DEBUG: Writing
DEBUG: Wrote 479232 out of 482278
DEBUG: Waiting
DEBUG: Received 3010 bytes
DEBUG: Writing
DEBUG: Wrote 482242 out of 482278
DEBUG: Waiting
DEBUG: Received 0 bytes
The code requests 3046 bytes but instead it receives 3010. Serial.available()
returns 0 after reading the 3010 bytes suggesting there is no more data to receive. I checked and 482278 is the size of the file.
Here-s the python script where i send the data:
with open(src_fname, 'rb') as f:
f.seek(0, 2) # move the cursor to the end of the file
size = f.tell()
f.seek(0, 0)
n_chunks = math.ceil(size / (512 * 1024))
t_chunk = 0
while t_chunk < n_chunks:
# check for a previous upload
send_cmd(miniterm, 'CHECK {}'.format(t_chunk))
# Get the HASH
output = get_output(miniterm)
error = get_status(output)
if error == 0:
remote_hash = get_hash(output)
print(
"LOCAL: Local Chunk Hash {} - Remote Chunk Hash {}".format(
all_hashs[t_chunk], remote_hash))
# If the hash is correct, send next chunk
if remote_hash == all_hashs[t_chunk]:
t_chunk += 1
continue
# Check failed, just upload this chunk
to_send = min(CHUNK_SIZE, size - (t_chunk * CHUNK_SIZE))
send_cmd(miniterm, 'CHUNK {} {}'.format(t_chunk, to_send))
# Send the chunk
f.seek(t_chunk * CHUNK_SIZE, 0)
miniterm.serial.write(f.read(CHUNK_SIZE))
miniterm.serial.flush()