JBM
Joined: 12 May 2004 Posts: 54 Location: edinburgh, Scotland
|
Xmodem library |
Posted: Fri Dec 23, 2005 6:43 pm |
|
|
This is a simple xmodem routine for sending a file. Hopefully the code will speak for itself.
This is published under the GPL, so make sure you know the freedoms you are (and are not) entitled to when using GPL'ed work, before including it in your own projects.
Code: | /*
xmodem.c - sends a file over RS232 using the xmodem protocol
Copyright Jimbob's Ma 2004
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
void send_xmodem_packet_header()
{
putc(1);
putc(packet_no);
putc(255-packet_no);
packet_no++;
}
#define POLY 0x1021
/* send_xmodem function: takes care of all xmodem-related stuff
* operates serially
* arguments:
* data: the data to send - may contain zero bytes if you really want
* length: the number of bytes in the data
* send_padding: set this to 1 if you want to pad this out to a full packet
* (probably set on the last packet to be sent)
*/
void send_xmodem(byte *data, int8 length, int8 send_padding)
{
static int8 bytes_sent = 0; /* Counts the bytes in each packet */
static signed int16 crc_register = 0; /* Keeps track of the CRC */
signed int8 bit; /* Used to compute CRC */
int8 padding = 0; /* Pad with spaces */
if (length == 0 && send_padding && bytes_sent > 0) {
length = 1;
data = &padding;
}
while (length > 0) {
if (bytes_sent == 0) { /* Start of a packet */
send_xmodem_packet_header();
}
/* Go through it byte-by-byte
For each byte, add to the CRC and send it */
while ((length > 0 || send_padding) && bytes_sent < 128) {
for (bit = 7; bit >= 0; bit--) {
/* Get out the MSB of the register */
int do_xor;
do_xor = (crc_register < 0);
crc_register <<= 1;
crc_register |= (*data >> bit) & 1;
if (do_xor) crc_register ^= POLY;
}
putc(*data);
bytes_sent++;
if (length <= 1 && send_padding) {
length = 0;
data = &padding;
} else {
data++; /* Move on to the next byte */
length--;
}
}
if (bytes_sent == 128) {
/* End of packet; add 2 zero bytes to the CRC and send it */
for (bit = 15; bit >= 0; bit--) {
/* Get out the MSB of the register */
int do_xor;
do_xor = (crc_register < 0);
crc_register <<= 1;
/* Since we're adding zero bytes, there is no
need to add any data bits to the register */
if (do_xor) crc_register ^= POLY;
}
putc(crc_register >> 8 );
putc(crc_register & 0xFF);
bytes_sent = 0;
/* Reset static variables for the next packet */
crc_register = 0;
}
}
} |
where packet_no is a global variable of type int8. |
|