home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 1
/
HamRadio.cdr
/
misc
/
bpq403a
/
sample.c
< prev
next >
Wrap
Text File
|
1990-01-13
|
9KB
|
411 lines
/************************************************************************/
/* EXAMPLE.C Jonathan Naylor G4KLX 13th January 1990*/
/**/
/* This program demonstrates the use of the INT 14H interface for*/
/* applications programs to access the G8BPQ node software.*/
/* The important routines have comments associated with them.*/
/* It was compiled using Microsoft C 5.10, it will probably compile*/
/* under Microsoft QuickC as well.*/
/**/
/* Any comments, queries etc about this code, should be directed to me*/
/* and not to John G8BPQ. He is busy enough supporting the Node s/ware*/
/* without answering questions about code he hasn't written.*/
/**/
/* Packet:G4KLX @ GB7DAD*/
/* Address:24 Castle View Drive*/
/*Cromford*/
/*Matlock*/
/*Derbyshire DE4 3RL*/
/* Telephone:0629 822037*/
/************************************************************************/
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <time.h>
#include <dos.h>
#define TRUE 1
#define FALSE 0
int Check_BPQ(int);
void Raise_RTS(int);
void Lower_RTS(int);
void Send_Break(int);
int Write_TNC(int, char *, unsigned int);
void Return_To_Node(int);
int Connected(char *, int);
int Read_TNC(int, char *, unsigned int);
void Set_TNC(int, int);
void Reset_TNC(int);
void cru(char *);
void Print_TNC(int);
void Delay(int);
int main(int argc, char *argv[])
{
char callsign[15];
char buffer[50];
int appl_number;
int port;
int i;
if (argc != 3)
{
fprintf(stderr, "Usage: example port application_number\n");
exit(1);
}
/* The INT 14H port number is 1 below the commonly used port*/
/* numbers. eg COM1: = 0, COM2: = 1 etc.*/
port = atoi(argv[1]) - 1;
appl_number = atoi(argv[2]);
if (!Check_BPQ(port))
exit(1);
Set_TNC(appl_number, port);
while (!kbhit())
{
if (Connected(callsign, port))
{
Print_TNC(port);
Send_Break(port);
strcpy(buffer, "CONV\r");
Write_TNC(port, buffer, strlen(buffer));
Print_TNC(port);
sprintf(buffer, "Hello %s\r", callsign);
Write_TNC(port, buffer, strlen(buffer));
Print_TNC(port);
strcpy(buffer, "Welcome to the G4KLX example program\r");
Write_TNC(port, buffer, strlen(buffer));
Print_TNC(port);
strcpy(buffer, "Bye Bye\r");
Write_TNC(port, buffer, strlen(buffer));
Print_TNC(port);
/* Returning the user to the Node immediately */
/* appears to lose the sent data, hence the delay */
Delay(3);
Return_To_Node(port);
Print_TNC(port);
}
}
Reset_TNC(port);
return(0);
}
/************************************************************************/
/* This checks for the G8BPQ Node signiature of X'AA55' in BOTH AX and*/
/* BX. COMBIOS and related programs only return it in AX. The version*/
/* number is also retrieved, this could be checked if using a newly*/
/* implemented feature of the code.*/
/************************************************************************/
int Check_BPQ(int port)
{
union REGS regs;
regs.x.dx = port;
regs.h.ah = 4;
int86(0x14, ®s, ®s);
if (regs.x.ax != 0xAA55 || regs.x.bx != 0xAA55)
{
fprintf(stderr, "example: G8BPQ node support not loaded\n");
return(FALSE);
}
regs.x.dx = port;
regs.h.ah = 0x1F;
regs.h.al = 0;
int86(0x14, ®s, ®s);
printf("Running G8BPQ node support version %d.%d\n",
regs.h.dh, regs.h.dl);
return(TRUE);
}
void Raise_RTS(int port)
{
union REGS regs;
regs.x.dx = port;
regs.h.ah = 6;
int86(0x14, ®s, ®s);
}
void Lower_RTS(int port)
{
union REGS regs;
regs.x.dx = port;
regs.h.ah = 5;
int86(0x14, ®s, ®s);
}
/************************************************************************/
/* Sending a break to the node software is the sure-fire way of getting*/
/* back to command mode from converse and transparant mode.*/
/************************************************************************/
void Send_Break(int port)
{
union REGS regs;
regs.x.dx = port;
regs.h.ah = 7;
int86(0x14, ®s, ®s);
}
/************************************************************************/
/* This function takes the same sort of arguments as the C library*/
/* function write(). It is a non blocking function that returns when*/
/* either all of the data has been sent to the node, or when the node*/
/* cannot accept any more data.*/
/************************************************************************/
int Write_TNC(int port, char *buffer, unsigned int count)
{
union REGS regs;
int attempts = 0;
int i;
for (i = 0; i < count; i++)
{
regs.x.dx = port;
regs.h.ah = 3;
do
{
attempts++;
int86(0x14, ®s, ®s);
}
while (!(regs.h.ah & 0x20) && (attempts < 6));
if (attempts == 6)
return(i);
attempts = 0;
regs.x.dx = port;
regs.h.ah = 1;
regs.h.al = buffer[i];
int86(0x14, ®s, ®s);
}
return(i);
}
/************************************************************************/
/* This is the gracefull way of getting rid of users, until recently the*/
/* only available option was to disconnect them from the node, this puts*/
/* them back to the node software.*/
/************************************************************************/
void Return_To_Node(int port)
{
union REGS regs;
regs.x.dx = port;
regs.h.ah = 0x1F;
regs.h.al = 0x10;
int86(0x14, ®s, ®s);
}
/************************************************************************/
/* This function serves two purposes, it indicates whether the*/
/* application is connected to a user, and if so, what their callsign*/
/* is. At present it does not return the users ssid, but it is available*/
/* if needed. The code gets the users callsign from the INT 14H and not*/
/* from parsing the "*** CONNECTED to ..." line. This piece of the code*/
/* makes use of a far pointer to the callsign within the Node software.*/
/* It then has to be converted to ASCII from AX25 format, which is*/
/* essentially shifting the characters right by one bit.*/
/************************************************************************/
int Connected(char *buffer, int port)
{
union REGS regs;
struct SREGS segregs;
unsigned char far *callsign;
int ssid;
int i;
regs.x.dx = port;
regs.h.ah = 0x1F;
regs.h.al = 1;
int86x(0x14, ®s, ®s, &segregs);
if (regs.x.si == 0)
return(FALSE);
FP_SEG(callsign) = segregs.es;
FP_OFF(callsign) = regs.x.si;
for (i = 0; (callsign[i] >> 1) != ' ' && i < 6; i++)
buffer[i] = callsign[i] >> 1;
buffer[i] = '\0';
ssid = (callsign[6] >> 1) & 0x0F;
return(TRUE);
}
/************************************************************************/
/* This routine is a non-blocking read of the port input stream.*/
/************************************************************************/
int Read_TNC(int port, char *buffer, unsigned int count)
{
union REGS regs;
int i = 0;
regs.x.dx = port;
regs.h.ah = 3;
int86(0x14, ®s, ®s);
while ((regs.h.ah & 0x01) && (i < count))
{
regs.x.dx = port;
regs.h.ah = 2;
int86(0x14, ®s, ®s);
buffer[i++] = regs.h.al;
regs.x.dx = port;
regs.h.ah = 3;
int86(0x14, ®s, ®s);
}
buffer[i] = '\0';
return(i);
}
void Set_TNC(int appl_number, int port)
{
char *command;
char buffer[15];
Raise_RTS(port);
Send_Break(port);
command = "ECHO ON\r";
Write_TNC(port, command, strlen(command));
Print_TNC(port);
sprintf(buffer, "APPL $%02X\r", appl_number);
Write_TNC(port, buffer, strlen(buffer));
Print_TNC(port);
command = "MONITOR OFF\r";
Write_TNC(port, command, strlen(command));
Print_TNC(port);
command = "CONOK ON\r";
Write_TNC(port, command, strlen(command));
Print_TNC(port);
}
void Reset_TNC(int port)
{
char *command;
Send_Break(port);
command = "APPL $00\r";
Write_TNC(port, command, strlen(command));
Print_TNC(port);
command = "CONOK OFF\r";
Write_TNC(port, command, strlen(command));
Print_TNC(port);
command = "ECHO OFF\r";
Write_TNC(port, command, strlen(command));
Print_TNC(port);
Lower_RTS(port);
}
/************************************************************************/
/* This function takes its name from a UNIX utility at Nottingham Uni*/
/* called Carriage Return Utility. It converts between the carriage*/
/* returns standards found on packet radio to the standards used in DOS*/
/************************************************************************/
void cru(char *string)
{
int i;
for (i = 0; string[i] != '\0'; i++)
{
switch (string[i])
{
case '\n':
string[i] = '\r';
break;
case '\r':
string[i] = '\n';
break;
}
}
}
void Print_TNC(int port)
{
char buffer[100];
Read_TNC(port, buffer, 99);
cru(buffer);
printf("%s", buffer);
}
/************************************************************************/
/* Delay for n seconds. In a "real" piece of software, it would be wise*/
/* to give time slices to DESQview at the point. The same can also be*/
/* said of the loop in main() where it is waiting for a user.*/
/************************************************************************/
void Delay(int delay)
{
time_t start_time;
time_t current_time;
time(&start_time);
do
{
time(¤t_time);
}
while ((current_time - start_time) < delay);
}