📄 txmodem.c
字号:
/*
====================================================================================
* this code needs standard functions memcpy() and memset()
* and input/output functions port_inbyte() and port_outbyte().
*
* the prototypes of the input/output functions are:
* INT32S port_inbyte(INT16U timeout); // msec timeout
* void port_outbyte(INT32S c);
=====================================================================================
*/
#include "modem.h"
#include "serial.h"
#include "brd.h"
#include "string.h"
#define port_outbyte urtPutData
#define port_inbyte getByteInTime
#define SOH 0x01
#define EOT 0x04
#define ACK 0x06
#define NAK 0x15
#define CAN 0x18
#define EOF 0x1A
#define STX 0x02
#define BS 0x08
/*add by hojin 5/12/2008*/
#define CTRLZ 0x1A
#if 0
void port_outbyte(INT8U trychar)
{
INT8U buf[2];
buf[0] = trychar;
lowLevel_write(buf,1);
}
INT8U port_inbyte(INT32U time_out)
{
INT8U ch;
INT32S i;
last_error = 0;
if(lowLevel_read(&ch,1) == 1)
return ch;
last_error = 1;
return ch;
}
#endif
/****************Portting End*******************/
static INT32S check(INT32S crc, INT8U *buf, INT32S sz)
{
if (crc)
{
INT16U crc = crc16_ccitt(buf, sz);
INT16U tcrc = (buf[sz]<<8)+buf[sz+1];
if (crc == tcrc)
return 1;
}
else
{
INT32S i;
INT8U cks = 0;
for (i = 0; i < sz; ++i)
{
cks += buf[i];
}
if (cks == buf[sz])
return 1;
}
return 0;
}
static void flushinput(void)
{
while (port_inbyte(DLY_1S) >= 0);
}
INT32S xmodemReceive(INT8U *dest, INT32S destsz)
{
INT8U xbuff[1030]; /* 1024 for XModem 1k + 3 head chars + 2 crc + nul */
INT8U *p;
INT32S bufsz, crc = 0;
INT8U trychar = 'C';
INT8U packetno = 1;
INT32S i, c, len = 0;
INT32S retry, retrans = MAXRETRANS, noDataRetry = MAXRETRANS ;
for(;;)
{
for( retry = 0; retry < 50; ++retry)
{
if (trychar)
port_outbyte(trychar);
c = port_inbyte((DLY_1S));
if (c >= 0)
{
noDataRetry = 15; /* 短线15秒之内能恢复连接不会产生错误。*/
switch (c)
{
case SOH:
bufsz = 128;
goto start_recv;
case STX:
bufsz = 1024;
goto start_recv;
case EOT:
flushinput();
port_outbyte(ACK);
return len; /* normal end */
case ESC_KEY:
c = port_inbyte(DLY_1S);
if (c == ESC_KEY) {
urtPrintf("\nCanceled by user in modem receive!\n");
return MODEM_USER_CAN; /* sync error */
}
break;
case CAN:
c = port_inbyte(DLY_1S);
if (c == CAN)
{
flushinput();
port_outbyte(ACK);
return MODEM_CANCLE; /* canceled by remote */
}
break;
default:
goto reject; /*add by hojin */
break;
}
}
else
{
if(trychar == 0)
{
if (--noDataRetry <= 0)
{
flushinput();
port_outbyte(CAN);
port_outbyte(CAN);
port_outbyte(CAN);
return MODEM_MID_NO_LINK; /* too many nodata retry error */
}
goto reject; /*hojin added */
}
}
}
if (trychar == 'C')
{
trychar = NAK;
continue;
}
flushinput();
port_outbyte(CAN);
port_outbyte(CAN);
port_outbyte(CAN);
return MODEM_START_NO_LINK; /* sync error */
start_recv:
if (trychar == 'C') crc = 1;
trychar = 0;
p = xbuff;
*p++ = c;
for (i = 0; i < (bufsz+(crc?1:0)+3); ++i)
{
c = port_inbyte(DLY_1S);
if (c < 0)
goto reject;
*p++ = (c & 0xff);
}
if (xbuff[1] == (INT8U)(~xbuff[2]) &&
(xbuff[1] == packetno || xbuff[1] == (INT8U)packetno-1) &&
check(crc, &xbuff[3], bufsz))
{
if (xbuff[1] == packetno)
{
INT32S count = destsz - len;
if (count > bufsz)
count = bufsz;
if (count > 0)
{
memcpy (&dest[len], &xbuff[3], count);
len += count;
}
++packetno;
retrans = MAXRETRANS+1;
}
if (--retrans <= 0)
{
flushinput();
port_outbyte(CAN);
port_outbyte(CAN);
port_outbyte(CAN);
return MODEM_PACKAGE_ERR; /* too many packet error retry error */
}
port_outbyte(ACK);
continue;
}
reject:
flushinput();
port_outbyte(NAK);
}
}
INT32S xmodemTransmit(const INT8U *src, INT32S srcsz)
{
INT8U xbuff[1030]; /* 1024 for XModem 1k + 3 head chars + 2 crc + nul */
INT32S bufsz, crc = -1;
INT8U packetno = 1;
INT32S i, c, len = 0;
INT32S retry;
for(;;) {
for( retry = 0; retry < 100; ++retry)
{
c = port_inbyte((DLY_1S)<<1);
if (c >= 0)
{
switch ((c & 0xff))
{
case 'C':
crc = 1;
goto start_trans;
case NAK:
crc = 0;
goto start_trans;
case CAN:
c = port_inbyte(DLY_1S);
if (c == CAN)
{
port_outbyte(ACK);
flushinput();
return MODEM_CANCLE; /* canceled by remote */
}
break;
default:
break;
}
}
}
port_outbyte(CAN);
port_outbyte(CAN);
port_outbyte(CAN);
flushinput();
return MODEM_START_NO_LINK; /* no sync */
for(;;)
{
start_trans:
xbuff[0] = SOH; bufsz = 128;
xbuff[1] = packetno;
xbuff[2] = ~packetno;
c = srcsz - len;
if (c > bufsz) c = bufsz;
if (c >= 0)
{
memset (&xbuff[3], 0, bufsz);
if (c == 0)
{
xbuff[3] = CTRLZ;
}
else
{
memcpy (&xbuff[3], &src[len], c);
if (c < bufsz) xbuff[3+c] = CTRLZ;
}
if (crc)
{
INT16U ccrc = crc16_ccitt(&xbuff[3], bufsz);
xbuff[bufsz+3] = (ccrc>>8) & 0xFF;
xbuff[bufsz+4] = ccrc & 0xFF;
}
else
{
INT8U ccks = 0;
for (i = 3; i < bufsz+3; ++i)
{
ccks += xbuff[i];
}
xbuff[bufsz+3] = ccks;
}
for (retry = 0; retry < MAXRETRANS; ++retry)
{
for (i = 0; i < bufsz+4+(crc?1:0); ++i)
{
port_outbyte(xbuff[i]);
}
c = port_inbyte(DLY_1S);
if (c >= 0 )
{
switch (c)
{
case ACK:
++packetno;
len += bufsz;
goto start_trans;
case CAN:
c = port_inbyte(DLY_1S);
if ( c == CAN)
{
port_outbyte(ACK);
flushinput();
return MODEM_CANCLE; /* canceled by remote */
}
break;
case NAK:
default:
break;
}
}
}
port_outbyte(CAN);
port_outbyte(CAN);
port_outbyte(CAN);
flushinput();
return MODEM_MID_NO_LINK; /* xmit error */
}
else
{
for (retry = 0; retry < 10; ++retry)
{
port_outbyte(EOT);
c = port_inbyte((DLY_1S)<<1);
if (c == ACK) break;
}
flushinput();
return (c == ACK) ? len : MODEM_OTHER_ERR;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -