home *** CD-ROM | disk | FTP | other *** search
- /*
- level1.c -- Level 1 synchronous transmission routines
-
- Poor Man's Packet (PMP)
- Copyright (c) 1991 by Andrew C. Payne All Rights Reserved.
-
- Permission to use, copy, modify, and distribute this software and its
- documentation without fee for NON-COMMERCIAL AMATEUR RADIO USE ONLY is hereby
- granted, provided that the above copyright notice appear in all copies.
- The author makes no representations about the suitability of this software
- for any purpose. It is provided "as is" without express or implied warranty.
-
- 07/24/89
- Andrew C. Payne
- */
-
- /* ----- Includes ----- */
- #include <stdio.h>
- #include <alloc.h>
- #include <dos.h>
- #include "pmp.h"
- #include "ports.h"
- #include "crc.h"
-
- /* ----- External Assembly Routines ----- */
- extern word timer(void);
- extern word transit(word when);
-
- #define MAXTXQUEUE 50 /* max size of TXQueue */
-
- /* ----- Local Variables ----- */
-
- static struct ax25_level1 *TXQueue[MAXTXQUEUE]; /* Transmit queue */
- static int TXQSize; /* number of items in queue */
- int TXQBytes; /* total bytes in queue */
-
- static int bitsent; /* # of bits sent */
-
- /* ----- CRC Generation and Checking ----- */
- /* CRCCheck(packet)
- Given a packet, generates a CRC, checks with existing CRC, and sets
- valid CRC.
- */
- int CRCCheck(struct ax25_level1 *packet)
- {
- word crc;
- int len; /* packet length, data bytes */
- int i;
- byte *p,t;
- word q;
-
- p = packet->data; /* pointer to data */
- len = packet->len-2; /* length less CRC bytes */
-
- /* compute CRC */
- crc = 0xffff; /* initialize */
- for(i=0; i<len; i++) {
- t = *p++ ^ (crc & 0xff);
- crc >>= 8;
- crc ^= crc_table[t];
- }
- q = ~crc;
-
- crc = *((word *)p); /* fetch existing */
- *((word *)p) = q; /* store computed one */
-
- return crc == q; /* return OK or not OK */
- }
-
- /* ----- Clock Skewing ----- */
- /* ClockAdjust(bitcount)
- Speeds up the BIOS clock depending on the number of bits specified.
- */
- void ClockAdjust(int bitcount)
- {
- if(ClockSkew) {
- bitcount = (bitcount / BITSPERTICK) - 1;
- while(bitcount-- > 0)
- geninterrupt(8); /* BIOS timer */
- }
- }
-
- /* ----- Transmission Subroutines ----- */
-
- /* sendflags(from,count)
- Sends 'count' opening flags, synced with the transition at time
- 'from'. Returns time of last transition.
- */
- static word sendflags(register word from, int count)
- {
- while(count--) {
- transit(from -= BITTIME);
- transit(from -= BITTIME*7);
- }
- bitsent += 8;
- return from; /* time of last transition */
- }
-
- /* sendpacketdata(from,p)
- Given a data packet, sends data packet synced with the transition
- at time 'from'. Returns the time of the last transition.
-
- NOTE: the 'c' variable MUST be an integer size.
- */
- static word sendpacketdata(word from, struct ax25_level1 *packet)
- {
- int len; /* bytes left to send */
- byte *p; /* pointer to data */
- word c; /* current character to transmit */
- int bit; /* bits left in c */
- int count; /* count of one bits */
-
-
- /* initialize pointers and counters */
- len = packet->len;
- p = packet->data;
-
- /* send the packet */
- bit = 0;
- while(TRUE) {
- count = 0;
-
- /* find next zero bit, or five consecutive ones */
- do {
- if(!bit) { /* end of byte? */
- if(len-- == 0) {
- if(count == 5) {
- transit(from -= BITTIME * 6);
- bitsent += 6;
- return from;
- } else
- return from - count * BITTIME;
- }
-
- c = *p++; /* get next byte */
- bit = 7;
- } else { /* else, next in next bit */
- c >>= 1;
- bit--;
- }
- count++;
- } while(count < 6 && (c & 1));
-
- /* if stuffed zero, undo last bit */
- if(count == 6) {
- bit++;
- c <<= 1;
- }
-
- /* make next transition */
- transit(from -= count * BITTIME);
- bitsent += count;
- }
- }
-
- /* ----- Transmitter Control ----- */
-
- /* TXKey(state)
- Sets the transmitter state to the state given (TRUE = 1 = keyup).
- Updates the status line on the screen.
- */
- void TXKey(int state)
- {
- if((state != 0) != (PTTLevel != 0))
- outportb(PTTPort,inportb(PTTPort) | PTTBit);
- else
- outportb(PTTPort,inportb(PTTPort) & ~PTTBit);
-
- ShowTXRX(state,FALSE);
- }
-
-
- /* ----- Transmit Queue Manipulation ----- */
-
- /* TXQInit()
- Initializes the level 1 transmit queue.
- */
- void TXQInit()
- {
- TXQBytes = TXQSize = 0; /* empty queue */
- }
-
- /* TXQAdd(packet)
- Adds a packet to the TXQueue. Returns TRUE if successful, or
- FALSE if error.
-
- Computes and sets CRC for packet.
-
- 'packet' is a pointer to an AX.25 level 1 packet record, that was
- alloced with the malloc() function.
- */
- int TXQAdd(struct ax25_level1 *packet)
- {
- /* check for full queue */
- if(TXQSize >= MAXTXQUEUE)
- return FALSE;
-
- /* compute and set CRC */
- (void) CRCCheck(packet);
-
- /* add to TXQueue */
- TXQBytes += packet->len;
- TXQueue[TXQSize++] = packet;
- return TRUE;
- }
-
- /* TXQEmpty()
- Assumes a clear channel, keys transmitter and empties TX queue.
-
- Frees all TX queue entries.
- */
- void TXQEmpty()
- {
- word from;
- int i;
-
- /* is there anything in the queue to send? */
- if(TXQSize) {
-
- TXKey(TRUE); /* key up transmitter */
- from = timer(); /* get current time */
- bitsent = 0; /* clear bit sent count */
- disable(); /* kill interrupts */
-
- /* send all packets in the TX Queue */
- from = sendflags(from,TXStartFlags); /* send flags */
- for(i=0; i<TXQSize; i++) {
- from = sendpacketdata(from,TXQueue[i]);
- from = sendflags(from,TXEndFlags);
- }
- TXKey(FALSE); /* drop transmitter key */
- enable(); /* interrupts allowed */
-
- /* attempt to re-adjust the BIOS clock */
- ClockAdjust(bitsent);
-
- /* free all packets in the TX Queue */
- for(i=0; i<TXQSize; i++) {
- #ifdef TRACE
- if(DebugMode)
- LogPacket(TXQueue[i],2); /* log the packet */
- #endif
- free(TXQueue[i]);
- }
- TXCount += TXQSize;
- TXQBytes = TXQSize = 0;
- }
- }
-
- /* TXQBytesInQ()
- Returns the number of bytes currently in the Level 1 TX queue.
- */
- int TXQBytesInQ(void)
- {
- return TXQBytes;
- }