www.pudn.com > commutil.zip > PROTOCOL.CPP


// ******************************************************************** // 
//                                                                      // 
//      PROTOCOL.CPP                                                    // 
//      Copyright (c) 1993, Michael Holmes and Bob Flanders             // 
//      C++ Communication Utilities                                     // 
//                                                                      // 
//      Chapter 6: Transferring Files                                   // 
//      Last changed in chapter 6                                       // 
//                                                                      // 
//      This file contains a class and functions common to the          // 
//      implementation of communications protocol.  This class          // 
//      relies on an instance of the Comm class for access to the       // 
//      communications port.                                            // 
//                                                                      // 
// ******************************************************************** // 
 
 
class Protocol 
    { 
    public: 
        int  TimeOut(long *n);              // check for timeout 
        UINT CRC(char *s, int l),           // CRC calculation 
             CheckSum(char *s, int l);      // checksum calculation 
        void Purge(Comm *c, long to);       // purge incoming data 
    }; 
 
 
 
/* ******************************************************************** * 
 * 
 *  CheckSum -- calculate an 8-bit checksum for message 
 * 
 * ******************************************************************** */ 
 
UINT    Protocol::CheckSum(char *s,         // message data 
                           int  l)          // ..and length 
{ 
unsigned 
char    acc = 0;                            // accumulator 
 
 
while (l--)                                 // until out of length 
    acc += *(unsigned char *) s++;          // ..accumulate checksum 
 
return(acc);                                // return the byte checksum 
 
} 
 
 
 
/* ******************************************************************** * 
 * 
 *  CRC() -- calculate CRC for message 
 * 
 * ******************************************************************** */ 
 
UINT    Protocol::CRC(char *s,              // message data 
                      int  len)             // ..and length 
{ 
UINT    acc = 0,                            // crc accumulator 
        i;                                  // loop control 
 
while (len--)                               // loop thru entire message 
    { 
    acc = acc ^ (*s++ << 8);                // xor in new byte from msg 
 
    for (i = 0; i++ < 8;)                   // loop thru each of 8 bits 
        if (acc & 0x8000)                   // q. this bit on? 
            acc = (acc << 1) ^ 0x1021;      // a. yes .. shift and xor 
         else 
            acc <<= 1;                      // else .. just shift 
    } 
 
_asm    mov     ax, acc                     // ax = crc value 
_asm    xchg    ah, al                      // swap high and low bytes 
return (_AX);                               // ..and return the crc 
 
} 
 
 
 
/* ******************************************************************** * 
 * 
 *  TimeOut -- check for an event timeout 
 * 
 * ******************************************************************** */ 
 
int     Protocol::TimeOut(long *n)          // time to wait in ticks 
{ 
static  unsigned 
long    far *timer = (unsigned long far *)  // BIOS timer tick counter 
                        MK_FP(0x40, 0x6c),  // ..down in low memory 
        last,                               // last accessed time 
        work;                               // work variable 
 
 
work = *timer;                              // get current time 
 
if (*n > 0)                                 // q. first time call? 
    { 
    *n = -*n;                               // a. yes .. change sign 
    last = work;                            // ..and initialize counters 
    } 
 
if (work != last)                           // q. time pass? 
    {                                       // a. yes .. see how much 
    if (work <= last)                       // q. clock go past midnite? 
        (*n)++;                             // a. yes .. count as 1 tick 
     else 
        *n += (UINT)(work - last);          // else .. count everything 
 
    last = work;                            // start again w/curr time 
    } 
 
return(*n >= 0L);                           // return TRUE at timeout time 
 
} 
 
 
 
/* ******************************************************************** * 
 * 
 *  Purge -- Purge the line until a timeout occurs 
 * 
 * ******************************************************************** */ 
 
void    Protocol::Purge(Comm *c,            // comm instance to purge 
                        long to)            // timeout value in seconds 
{ 
long    timeout;                            // work timeout value 
char    ch,                                 // character buffer 
        lsr, msr;                           // lsr & msr for read request 
 
 
timeout = SECS(to);                         // set the timeout value 
 
for(;;)                                     // forever 
    { 
    if (TimeOut(&timeout))                  // q. timeout occur? 
        return;                             // a. yes .. exit now 
 
    if (c->Read(&ch, &lsr, &msr) == 0)      // q. any characters? 
        timeout = SECS(to);                 // a. yes.. restart timeout 
    } 
}