Copyright 2014 Craig Scratchley, craig_scratchley AT alumni.sfu.ca
Sender StateChart for XMODEM file-transfer protocol. March 25, 2014
Real events are either
SER (serial character recieved),
KB_C (cancel command received from keyboard) TM (timeout occurred)
[Entry]
ctx.useCrc=true; ctx.prep1stBlk(); ctx.errCnt=0; ctx.firstCrcBlk=true; ctx.KbCan = false; ctx.tm(TM_VL); [Exit]
Ordinarily…
TM_VL (Very Long timeout) gives 60 seconds TM_SOH (normal timeout waiting for SOH) gives 10 seconds
TM_CHAR (inter-character timeout) gives 1 second TM_2CHAR gives a period longer than the
inter-character timeout of 1 sec.
CompleteSenderTopLevel
onEvent(KB_C)
[!ctx.KbCan]
/ctx.KbCan = true; ctx.tmRed(TM_VL – TM_2CHAR);
ctx.can8() should not be called immediately after the checksum for a block has been written to the medium, or some CAN characters may be purged.
H
[Entry] [Exit]
START
[Entry] [Exit]
SERcancelable
onEvent(SER)
[(c==NAK || c==’C’) & ctx.bytesRd] /if (c==NAK) {ctx.useCrc=false;
ctx.cs1stBlk();
ctx.firstCrcBlk=false;} ctx.sendBlkPrepNext(); ctx.tm(TM_VL);
onEvent(SER)
[(c==ACK) & ctx.bytesRd & !ctx.KbCan] /ctx.sendBlkPrepNext();
ctx.errCnt=0; ctx.firstCrcBlk=false; ctx.tm(TM_VL);
ACKNAK
[Entry] [Exit]
onEvent(SER)
[(c==NAK || (c==’C’ & ctx.firstCrcBlk)) & (ctx.errCnt < errB) & !ctx.KbCan] /ctx.resendBlk();
ctx.errCnt++; ctx.tm(TM_VL);
onEvent(SER)
[c != CAN & !ctx.KbCan] /ctx.tmPop();
onEvent(KB_C) /ctx.can8(); ctx.result="KbCancelled";
onEvent(SER)
[(c==ACK) & !ctx.bytesRd & !ctx.KbCan] /ctx.sendByte(EOT);ctx.errCnt=0; ctx.tm(TM_VL);ctx.firstCrcBlk=false;
EOT1
[Entry] [Exit]
EOTEOT
[Entry] [c==NAK & !ctx.KbCan] [Exit]
/ctx.sendByte(EOT); ctx.errCnt=0; ctx.tm(TM_SOH);
onEvent(SER) [c==NAK & (ctx.errCnt < errB) & !ctx.KbCan] /ctx.sendByte(EOT); ctx.errCnt++;
onEvent(SER)
[((c == NAK) || (c == 'C')) & !ctx.bytesRd]
/if (c==NAK) {ctx.firstCrcBlk=false;} ctx.sendByte(EOT); ctx.tm(TM_VL);
onEvent(SER)
[c==ACK]
/ctx.result="1st EOT ACK'd"; /*should delay TM_2CHAR */ ctx.sendByte(EOT);
onEvent(TM) /ctx.can8();
if (ctx.KbCan)
onEvent(SER)
onEvent(SER) [(c=='C' & ctx.firstCrcBlk) & (ctx.errCnt < errB) & !ctx.KbCan] /ctx.sendByte(EOT); ctx.tm(TM_VL); ctx.errCnt++;
onEvent(TM) /ctx.result="Timeout waiting for ACK of 2nd EOT";
onEvent(TM) [!ctx.KbCan] /ctx.tmPop();
CAN
[Entry] [Exit]
onEvent(SER)
[c == CAN] /ctx.tmPush(TM_CHAR);
onEvent(KB_C) /ctx.KbCan=true;
onEvent(SER) [ctx.KbCan]
/ctx.can8(); ctx.result="KbCancelled";
onEvent(SER) [c==ACK] /ctx.result="Done";
onEvent(SER)
[c==CAN] /ctx.clearCan(); ctx.result="RcvCancelled";
ctx.result="KbCancelled"; else
ctx.result="Timeout";
onEvent(SER)
[((c=='C' & ctx.firstCrcBlk) || c==NAK) & !ctx.KbCan] /ctx.can8();
ctx.result="ExcessiveNAKsOrCs";