📄 xymodem.c
字号:
#include "xymodem.h"
#include "heads.h"
unsigned int buf_filelen(unsigned char *ptr);
int ymodem_init(modem_struct *mblock)
{
int stat;
int max_tries = MODEM_MAX_RETRIES;
int crc_tries =MODEM_CRC_RETRIES;
unsigned char *bufptr = mblock->buf;
unsigned char *namptr = mblock->filename;
mblock->nxt_num = 0;
mblock->modemtype = 2;
mblock->rec_err = 0;
mblock->crc_mode = 1;
while (max_tries-- > 0)
{
stat = modem_recvdata(mblock);
if (0 == stat) // receive successful
{
//file name
while (*bufptr != '\0')
{
*namptr++ = *bufptr++;
}
*namptr = '\0';
bufptr++;
while (*bufptr == ' ')
{
bufptr++;
}
//file length
mblock->filelen = buf_filelen(bufptr);
//other data;
Uart_SendByte(MODEM_ACK);
return 0;
}
else if (2 == stat) // cancel transfer
{
return 2;
}
else if (-3 == stat)
{
if (mblock->cur_num == 1)
{
mblock->modemtype = 1;
mblock->nxt_num = 2;
return 1;
}
}
else // cancel transfer
{
if (crc_tries-- <= 0)
{
crc_tries = MODEM_CRC_RETRIES;
mblock->crc_mode = (mblock->crc_mode+1) & 1;
}
}
}
return -1;
}
/*****************************************************************************************
* 0: Transfer successful
* -1: Receive overtime
* -2: error
* -4: serious error
* 1: end of message
* 2: cancel transfer
******************************************************************************************/
int modem_recvdata(modem_struct *mblock)
{
int stat, hd_found=0, i;
int can_counter=0, eot_counter=0;
unsigned char *in_ptr = mblock->buf;
int cksum;
unsigned char ch, blk, cblk, crch, crcl;
Uart_RxEmpty(); // Clear receive buffer
if (mblock->nxt_num == 0)
{
if (mblock->crc_mode)
{
Uart_SendByte(MODEM_C);
}
else
{
Uart_SendByte(MODEM_NAK);
}
}
else
{
if (mblock->rec_err)
{
Uart_SendByte(MODEM_NAK);
}
else
{
if (mblock->nxt_num == 1)
{
if (mblock->crc_mode)
{
Uart_SendByte(MODEM_C);
}
else
{
Uart_SendByte(MODEM_NAK);
}
}
else
{
Uart_SendByte(MODEM_ACK);
}
}
}
while (!hd_found) // header block
{
stat = Uart_RecvByteTimeout(&ch);
if (stat == 0)
{
switch (ch)
{
case MODEM_SOH :
hd_found = 1;
mblock->len = 128;
break;
case MODEM_STX :
hd_found = 1;
mblock->len = 1024;
break;
case MODEM_CAN :
if ((++can_counter) >= MODEM_CAN_COUNT)
{
return 2;
}
break;
case MODEM_EOT : // End of Transfer
if ((++eot_counter) >= MODEM_EOT_COUNT)
{
Uart_SendByte(MODEM_ACK);
if (mblock->modemtype == 2) //Ymodem batch file transfer
{
Uart_SendByte(MODEM_C); // automatic transfer stop after single file
Uart_SendByte(MODEM_ACK);
Uart_SendByte(MODEM_C);
modem_cancle(); // cancel transfer after multiple file
}
return 1;
}
break;
default:
break;
}
}
else
{
return -1;
}
}
stat = Uart_RecvByteTimeout(&blk); // data block error or overtime
if (stat != 0)
{
return -1;
}
stat = Uart_RecvByteTimeout(&cblk); // data block
if (stat != 0)
{
return -1;
}
for (i=0; i < mblock->len ; i++)
{
stat = Uart_RecvByteTimeout(in_ptr++);
if (stat != 0)
{
return -1;
}
}
stat = Uart_RecvByteTimeout(&crch); //CRC
if (stat != 0)
{
return -1;
}
if (mblock->crc_mode)
{
stat = Uart_RecvByteTimeout(&crcl);
if (stat != 0)
{
return -1;
}
}
if (blk^cblk != 0xff)
{
return (-2);
}
if (mblock->crc_mode)
{
in_ptr = mblock->buf;
cksum = 0;
for (stat=mblock->len ; stat>0; stat--)
{
cksum = cksum^(int)(*in_ptr++) << 8;
for (i=8; i!=0; i--)
{
if (cksum & 0x8000)
cksum = cksum << 1 ^ 0x1021;
else
cksum = cksum << 1;
}
}
cksum &= 0xffff;
if (cksum != (crch<<8 | crcl))
{
mblock->rec_err = 1;
return (-2);
}
}
else
{
for (i=0; i<mblock->len; i++) // crc check method
{
cksum += mblock->buf[i];
}
if ((cksum&0xff)!=crch)
{
mblock->rec_err = 1;
return (-2);
}
}
mblock->cur_num = blk;
if (blk != mblock->nxt_num) // block check
{
return (-3);
}
mblock->nxt_num++;
mblock->rec_err = 0;
return 0;
}
unsigned int buf_filelen(unsigned char *ptr)
{
int datatype=10, result=0;
if (ptr[0]=='0' && (ptr[1]=='x' && ptr[1]=='X'))
{
datatype = 16;
ptr += 2;
}
for ( ; *ptr!='\0'; ptr++)
{
if (*ptr>= '0' && *ptr<='9')
{
result =result*datatype+*ptr-'0';
}
else
{
if (datatype == 10)
{
return result;
}
else
{
if (*ptr>='A' && *ptr<='F')
{
result = result*16 + *ptr-55; //55 = 'A'-10
}
else if (*ptr>='a' && *ptr<='f')
{
result = result*16 + *ptr-87; //87 = 'a'-10
}
else
{
return result;
}
}
}
}
return result;
}
void modem_cancle(void)
{
Uart_SendByte(0x18);
Uart_SendByte(0x18);
Uart_SendByte(0x18);
Uart_SendByte(0x18);
Uart_SendByte(0x18);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -