Pages: [1]   Go Down
Author Topic: Transfering lossless data to PC and storing those  (Read 649 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi everyone,

I was recently working on my latest project. A GameBoy Advance cartridge reader. I currently have no problems at all reading the actual data from the ROM chip but I still need to transfer the data through the serial interface and store these in a file on the computer. The data transfer should be completely lossless and there should be no errors in the file lateron and I'm having big trouble to realize that since I can't just write all the bytes to the serial interface because there might be errors in the transfer and could possibly cause issues later.

So my question is: Is there any common protocol or even librarys out there that help me doing that?

I previously used C# and the serial port class to recieve data but I also have lots of trouble using that correctly since I'm to really able to program anything useful without using "loop waits" when it comes to wait for serial data to be avaiable at the computer.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Back in the eighties, people used lossy serial connections to move files all the time. There are a number of protocols that you could use:

http://en.wikipedia.org/wiki/Xmodem
http://en.wikipedia.org/wiki/Ymodem
http://en.wikipedia.org/wiki/Zmodem

I suspect that XModem would be the way to go. The protocol is fairly simple, and I suspect with a little searching you could find a good implementation.

Hope that helps.

Peter.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Greetings,

After giving your problem some thought, I decided it would be fun to implement the basic xmodem protocol. Here is the result:

Quote
#define XMODEM_SOH 0x01
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CAN 0x18

byte blknum = 0x01;
byte *block;

byte data[128];

// This function is called each time the xmodem protocol needs a
// new block to send.
void get_next_xmodem_block() {
  // Our virtual file is two blocks (256 bytes) long
  if(blknum < 3) {
    // If we have a next block to send, fill the buffer
    for(int i = 0; i < 128; i++) data = 'A' + (i % 26);
    // And assign the address.
    block = data;
  } else {
    // Assign NULL to indicate that we've already sent the last
    // block.
    block = NULL;
  }
  // This is mostly for debugging.
  if(block != NULL) digitalWrite(13, HIGH);
}

void setup() {
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  
  Serial.begin(115200);
  
  // Get the first block into the buffer.
  get_next_xmodem_block();
}


void serialEvent() {
  while(Serial.available() > 0) {
    byte c = Serial.read();

    // If we receive an <ACK>, prepare to send the next block.
    if(c == XMODEM_ACK) {
      blknum++;
      get_next_xmodem_block();
    }
  
    if(block == NULL) {
      // If we have no more blocks, send <EOT>
      Serial.write(XMODEM_EOT);
    } else {
      // Otherwise send a block
      Serial.write(XMODEM_SOH);
      Serial.write(blknum);
      Serial.write(0xFF - blknum);
      byte checksum = 0x00;
      for(int i = 0; i < 128; i++) {
        Serial.write(block);
        checksum += block;
      }
      Serial.write(checksum);
    }
  }
}

void loop() {
  // Thumb twiddling
}


I've tested this using minicom as the receiver on my linux box, and it works. You should know that this is a very naive implementation:

 - It uses checksums (which are slightly less robust when compared to CRCs)
 - It doesn't accept cancel messages (You'll notice the define for XMODEM_CAN doesn't get used anyplace
 - It only sends the file once, and then effectively hangs, sending <EOT> at every subsequent request
 - And it probably ignores half a dozen other corner cases

Hope this helps,

Peter.
Logged

Pages: [1]   Go Up
Jump to: