 
 
 
 /* CW monitor uses RI signal on COM1 (pin 8 of DB25 pin 9 on a DB9) */
 /* input stimulus. A space = +5v, mark = 0v works with RS 232 systems */
 /* CTS and DSR must be tied to space level (5v) for port to operate */
          /* CTS is 5/DB25 8/DB9 DSR is 6/DB25 6/DB9 */
 
#include <stdio.h>
#include <bios.h>
#include <dos.h>
#include <graphics.h>
#include <conio.h>
#include <sys\timeb.h>
#include <sys\types.h>
 
#define SIZE 32
#define PRINT_CHAR 0
#define PRINT_SPACE 1
#define PRINT_OVR 2
#define FLUSH 1
#define UPDATE 2
#define MARK  0x80
#define SPACE 0
#define RESET 0
#define SET   1
#define ON    1
#define OFF   0
#define DIT   1
#define DAH   2
#define NULL  0
#define HIGH  1
#define LOW   0
#define START 0
#define STOP  2
#define FINISH 1
#define READ 1
#define NORMAL 7
#define UP 6
#define DOWN 7
#define BELL 7
#define TICK 1
#define NOTICK 0
 
 
union REGS regs;
 
struct WINDOW {
unsigned char tlrow;
unsigned char tlcol;
unsigned char brrow;
unsigned char brcol;
unsigned char attr;
};
struct WINDOW screen = {11,0,19,79,NORMAL};
struct WINDOW spadscrn = {21,0,24,79,NORMAL};
int space_msec, mark_msec, temp, old_vmode, space_flag, row, col,
    loop, buffer[9], *bufptr, word_flag, word_mul, char_mul, prikey,
    char_flag, mark_count, init_flag, spad_flag, spad_row, spad_col,
    mark_stack[SIZE], *mark_ptr, md_stack[SIZE], *md_ptr, fence, *temp_ptr,
    sp_buffer[8], *sp_ptr, sp_count, filter_co, write_flag, write_char,
    tempkey, e_col, e_row, key, sec_char, dit_msec, skew_count, delta_sec,
    delta_msec, speed, wpm_flag, teach;
long avg, md_avg, md_val;
 
                   /* func declarations */
 
void char_print(int c_flag);
int read_port(int next_state);
void space_func(void);
void mark_func(void);
int stop_watch(void);
void entry_func(void);
void write(char *strptr);
void scroll(struct WINDOW window, int lines, int dir);
void spot_print(int attr, val);
void filter_print(int attr);
void auto_term(void);
void wpm_func(void);
void char_out(void);
void diagnostic(void);
                      /* initialize program */
 
           /* set up nominal operation parameters */
main()
{
teach = OFF;
init_flag = SET;
spad_flag = OFF;
row = 11;
col = 0;
spad_row = 21;
spad_col = 0;
prikey = 0;
write_flag = RESET;
fence = 100;
filter_co = 32;
char_mul =25;
word_mul = 67;
skew_count = 0;
for(temp_ptr = &mark_stack[0]; temp_ptr <= &mark_stack[SIZE -1]; temp_ptr++)
                      *temp_ptr = 100;
 
for(temp_ptr = &md_stack[0]; temp_ptr <= &md_stack[SIZE -1]; temp_ptr++)
                      *temp_ptr = 0;
mark_ptr = &mark_stack[0];
md_ptr = &md_stack[0];
sp_ptr = &sp_buffer[0];
sp_count = 0;
bufptr = &buffer[0];
 for(loop = 0; loop < 8; loop++)
         {*bufptr = NULL;
           bufptr++;
          }
 mark_count = 0;
 bufptr = &buffer[0];
 
      /* set up com1 as 4800bd 7 bits 1 stop, 1 start, no parity */
                   /* fakes a real good 2 ms time clock */
 
regs.x.dx = 0;
regs.h.ah = 0;
regs.h.al = 0xC2;
int86(0x14,&regs,&regs);
 
                /* set up entry and working screens */
                /* code displayed on screen 0 */
 
  
old_vmode = getvmode();
setvmode(3);
setcolor(9,3);
setapage(0);
clrscrn();
poscurs(0,7);
write("ROBO-COPy 73 Magazine Automated CW Copier by WB9DYI/Mike Hansen");
poscurs(2,7);
write("Change a copy parameter by typing it's first letter (L,W,F); then ");
poscurs(3,7);
write("modify value using +/- keys. Terminate change by pressing Enter key.");
poscurs(4,7);
write("Type H for help; Q exits to DOS; R resets copy parameters. Space bar");
poscurs(5,7);
write("toggles scratch pad area on/off. Type S to clear scratch pad area,");
poscurs(6,7);
write("C to clear copy area. M toggles between normal and teach modes.");
poscurs(8,2);
write("Letter Timing     dits.  Word Timing     dits.  Mode          Filter");
poscurs(10,0);
writechs('_',0x07,80);
poscurs(10,33);
write("WPM =    ");
poscurs(20,0);
writechs('-',0x07,80);
poscurs(20,30);
write("Scratch Pad      ");
setvpage(0);           /* copy starts at row 10 col 0 */
 
                         /* v_page 0 cleared for copy */
 
 
                       /* set up help screen, v_ page 1 */
 
setapage(1);
setcolor(9,3);
poscurs(0,9);
write("Intended for private use only. All commercial rights reserved.");
poscurs(2,27);
write("ROBO-COPy HELP SCREEN");
poscurs(3,10);
write("Decrease letter timing when the over run error ");
poscurs(4,10);
write("symbol # ocurrs frequently.");
poscurs(6,10);
write("Increase letter timing when longer characters");
poscurs(7,10);
write("break-up into short letters; example SOS = EEETTTEEE.");
poscurs(9,10);
write("If wordsruntogetherlikethis...decrease word timing.");
poscurs(11,10);
write("If letters a r e separated in words...increase word timing.");
poscurs(13,10);
write("A sampling filter helps reduce the effects of QRN. It has three ");
poscurs(14,10);
write("settings, LOW, MEDIUM and HI. LOW filtering is best for");
poscurs(15,10);
write("high speed reception, but is more susceptible to noise.");
poscurs(16,10);
write("When receiving noisy signals, HI filtering works to eliminate the");
poscurs(17,10);
write("interference but reduces copy speed to less than 30-35 WPM.");
poscurs(19,10);
write("Unrecognized characters and errors are displayed as *.");
poscurs(20,10);
write("Command characters like    are displayed in reverse video.");
poscurs(20,34);
writechs('S',0x70,1);
poscurs(20,35);
writechs('K',0x70,1);
poscurs(21,10);
write("Keep important QSO data like call signs, etc. in Scratch Pad");
poscurs(22,10);
write("by toggling area ON/OFF with Space bar. Type S to clear the area.");
poscurs(24,13);
write("Press space bar for more HELP, Press Enter key to exit HELP.");
                  /* screen 1 finished */
 
setapage(2);
poscurs(0,23);
write("Recommend receiver operation for ROBO-COPy");
poscurs(2,10);
write("The ROBO-COPy interface can be connected in parallel with either");
poscurs(3,10);
write("the speaker or low-impedance headphone outputs. The added load is");
poscurs(4,10);
write("about 330 ohms, and should have no noticeable effect on the quality");
poscurs(5,10);
write("or volume of the audio output. The output of the ROBO-COPy ");
poscurs(6,10);
write("interface should be connected to the COM1 port of the P.C..");
poscurs(8,30);
write("ROBO-COPying a CW station");
poscurs(10,20);
write("AGC = FAST, Noise Blanker = ON, CW Filter = ON");
poscurs(11,10);
write("1. Tune station as you would normally do for cw reception.");
poscurs(12,10);
write("2. Reduce audio and RF gain to the MINIMUM needed for solid copy.");
poscurs(13,10);
write("3. Increase audio gain until LED on ROBO-COPy interface flashes");
poscurs(14,10);
write("   bright, distinct dits and dahs.");
poscurs(24,25);
write("Press any key to exit HELP.");
 
setapage(0);
setvpage(0);
 
do
   {if(read_port(MARK) != SPACE)
             mark_func();
    space_func();
    }while (0 == 0);
 
 }/* end of main brace */
 
 
              /* start of program */
void space_func(void)
{
word_flag = START;
char_flag = START; /* start assembling character */
space_msec = 0;
while(read_port(MARK) == SPACE)
    { if(stop_watch() == TICK)
      space_msec = space_msec + 2;
 
             /* check keyboard */
       key = getkey();
       if(key != EOF || init_flag == SET)
           entry_func();
 
          /* background task of displaying data */
 
    if(write_flag == SET)  /* write to screen */
              {   char_out();
                  if(sec_char != 0)
                    {write_char = sec_char;
                     char_out();
                     }
               }
  
   if(teach == OFF)
      {
      dit_msec = avg/2;
      if(space_msec > (char_mul * dit_msec)/10  && char_flag == START &&
                                  mark_count > 0)
                           {char_print(PRINT_CHAR);
                            char_flag = FINISH;
                            wpm_func(); /* outputwpm */
                            }
     
if(space_msec > (word_mul * dit_msec)/10 && word_flag == START)
                            {word_flag = FINISH;
                             char_print(PRINT_SPACE);
                            }
 
      }
 
 
  
} /* done with background house keeping now back to biz */
        
                  /* process space */
  if(teach == ON)
      {
                    dit_msec = avg/2;
      if(space_msec > (char_mul * dit_msec)/10  && char_flag == START &&
                                  mark_count > 0)
              {char_print(PRINT_CHAR);
               char_flag = FINISH;
               wpm_func(); /* outputwpm */
               if(write_flag == SET)  /* write to screen */
                {char_out();
                  if(sec_char != 0)
                    {write_char = sec_char;
                     char_out();
                     }
                 }
               }
if(space_msec > (word_mul * dit_msec)/10 && word_flag == START)
                            {word_flag = FINISH;
                             char_print(PRINT_SPACE);
                             char_out();
                             }
     }
    return; /* return on mark */
} /* end of space_func  */
 
void mark_func(void)
 {
 
    /* MARK detected in space_func is timed here */
sp_count++;
if(sp_count > 7)
   {sp_count = 0;
    sp_ptr = &sp_buffer[0];
   }
*sp_ptr = space_msec;
sp_ptr++;
mark_msec = 2; /* add 2 for initial loop-compensates for sampling time */
 
           /* check for end of mark */
 
              while(read_port(SPACE) != SPACE)
                      {if(stop_watch() == TICK)
                         {if(mark_msec < 1000)
                           mark_msec = mark_msec + 2;
                          }
                       }
                  /* is mark within range ? */
    if(mark_msec < 10 )
                      return;
 
               mark_count++;
              if(mark_msec > fence)
                         *bufptr = DAH;
                 else *bufptr  = DIT;
                 bufptr++;
                 if(bufptr > &buffer[8])
                         char_print(PRINT_OVR);
 
       /* calculate latest mean deviation and store on stack */
 
                 md_ptr++;
                 if(md_ptr > &md_stack[SIZE -1])
                        md_ptr = &md_stack[0];
                 *md_ptr = mark_msec - avg;
 
         /* calculate new average of mean deviation */
          
                  md_avg = 0;
   for(temp_ptr = &md_stack[0]; temp_ptr <= &md_stack[SIZE -1]; temp_ptr++)
                  md_avg = md_avg + *temp_ptr;
                  md_avg = md_avg/SIZE;
 
      /* generate absolute value of mean deviation times 4 */
                  md_val = 4 * md_avg;
                  if(md_val < 0)
                       md_val = -1 * md_val;
 
 
    /* avoid corrupting average with skew due to repetition */
  
if(mark_msec < *mark_ptr + (*mark_ptr/8) ||
                          mark_msec > *mark_ptr - (*mark_ptr/8))
                    skew_count++;
                          else skew_count = 0;
           
            if(skew_count < 4 || md_val > avg)
                     
           {
                  /* load mark_stack with last mark */
                    mark_ptr++;
                     if(mark_ptr > &mark_stack[SIZE -1])
                          mark_ptr = &mark_stack[0];
                    *mark_ptr = mark_msec;
 
                  /* calculate new average */
                     avg = 0;
 for(temp_ptr = &mark_stack[0]; temp_ptr <= &mark_stack[SIZE -1]; temp_ptr++)
                        avg = avg + *temp_ptr;
                   avg = avg/SIZE;
 
               
          /* calculate new fence point */
                fence = avg +  md_avg;
                 }
             
  return;
}                   /* end of mark_func */
 
 
void char_print(int c_flag)
 
  { int temp, exp, loop, sum;
 
char letter[] ="ETIANMSURWDKGOHVF*L*PJBXCYZQ";
char alpha;
char *letter_ptr, *number_ptr;
sec_char = 0; /* reset special command character value */
write_flag = SET;
    if(c_flag == PRINT_OVR)
                write_char = '#';
 
    if(c_flag == PRINT_SPACE)
                write_char = ' ';
else{
    bufptr = &buffer[7];
    sum = 0;
    exp = 128;
    for(loop = 0; loop < 8; loop++)
                   {temp = *bufptr;
                      while(*bufptr == 0)
                         {exp = exp/2;
                          bufptr--;
                           }
                     }
     bufptr = &buffer[0];
      while(exp != 0)
                 { sum = sum + ((*bufptr) * exp);
                   exp = exp/2;
                   bufptr++;
                 }
 
        if(mark_count == 0)
                return;
       if((mark_count <= 4) && (sum < 29))
                  {letter_ptr = &letter[0];
                   alpha = *(letter_ptr + (sum - 1));
                   write_char = alpha;
                   }
        if(mark_count== 5)
                   {switch(sum){
                    case 62: write_char = '0';
                             break;
                    case 61: write_char = '9';
                             break;
                    case 59: write_char = '8';
                             break;
                    case 55: write_char = '7';
                             break;
                    case 47: write_char = '6';
                             break;
                    case 31: write_char = '5';
                             break;
                    case 32: write_char = '4';
                             break;
                    case 34: write_char = '3';
                             break;
                    case 38: write_char = '2';
                             break;
                    case 46: write_char = '1';
                             break;
                    case 33: write_char = 'S';
                             sec_char = 'N';
                             break;
                    case 41: write_char = 'A';
                             sec_char = 'R';
                             break;
                    case 39: write_char = 'A';
                             sec_char = 'S';
                             break;
                    case 52: write_char = 'K';
                             sec_char = 'A';
                             break;
                    case 48: write_char = '=';
                             break;
                    case 49: write_char = '/';
                             break;
                    case 53: write_char = '(';
                             break;
                    default: write_char = '*';
                      }
                    }
              
 
        if(mark_count == 6)
                        {switch(sum)
                           {case 68: write_char = 'S';
                                     sec_char = 'K';
                                     break;
                            case 75: write_char = '?';
                                     break;
                            case 84: write_char = '.';
                                     break;
                            case 114: write_char = ',';
                                     break;
                            case 93: write_char = ''';
                                     break;
                            case 76: write_char = 'I';
                                     sec_char = 'Q';
                                     break;
                            case 83: write_char = 'A';
                                     sec_char = 'L';
                                     break;
                            case 81: write_char = '"';
                                     break;
                            case 105: write_char = ';';
                                      break;
                            case 96: write_char = '-';
                                     break;
                            case 108: write_char = ')';
                                     break;
                            case 119: write_char = ':';
                                     break;
  
                           default: write_char = '*';
                            }
                       }
            if(mark_count == 7)
                              {if(sum == 136)
                                write_char = '$';
                               else write_char = '*';
                               }
 
            if(mark_count == 8)
                               {if(sum == 255)
                                   {write_char = 'H';
                                    sec_char = 'H';
                                    }
                                else write_char = '*';
                                }
 
}/* end of else */
for(bufptr = &buffer[0]; bufptr <= &buffer[7]; bufptr++)
                      *bufptr = 0; /* clear DIT/DAH buffer */
bufptr = &buffer[0];
mark_count = 0;
return;
} /* end of char_print function */
 
int read_port(int next_state)
{int fcount, temp, delay;
/* read_port has a sampling filter built in. There must be */
/*  filter_co times the next state before a transistion is reported via */
                /* the returned value */
fcount = 0;
do
   {fcount++;
    regs.x.dx = 0;
    regs.h.ah = 3;
    int86(0x14,&regs,&regs);
    temp = regs.h.al & 0x80;
    for(delay = 0; delay < 16; delay++)
              ;
    }while(temp == next_state && fcount < filter_co);
   
   if(fcount >= filter_co)
                 temp = next_state; /* successfully completed filter */
   else
       {if(next_state == MARK) /* noisy signal returns current state */
                 temp = SPACE;
           else temp = MARK;
        }
return(temp);
}
 
          /* stop_watch generates a 2 ms wait  */
          
int stop_watch(void)
 
{int loop;
regs.x.dx = 0;
regs.h.ah = 3;
int86(0x14,&regs,&regs);
 if(regs.h.ah & 0x40 == 0)
         return(NOTICK); /* xmit buffer not empty */
regs.x.dx = 0;  /* xmit buffer empty, fill it */
regs.h.ah = 1;
regs.h.al = ' ';
int86(0x14,&regs,&regs);
return(TICK);
}
  
void write(char *strptr)
{int row, col;
 
row = cursrow();
col = curscol();
 while(*strptr != NULL)
      {writechs(*strptr, 0x07,1);
       strptr++;
       col++;
       poscurs(row,col);
        }
 return;
 }
 
void entry_func(void)
{
cursoff();
e_row = 8; /* all parameters are on row 8 */
tempkey = key & 0x00FF;  /* makes sure key is upper case */
if(tempkey == '~')
            {diagnostic();
             return;
            }
if(tempkey > 0x60)
         tempkey = tempkey - 32;
if(init_flag == SET)
         {init_flag = RESET;
          tempkey = 'R';
         }
 
 switch(tempkey)
  {
   case 'C': scroll(screen, 0 , UP); /* clear scratch pad screen */
             row = 11;
             col = 0;
             break;
 
   case 'F': if(prikey != 0)
                 auto_term();
             filter_print(0x70);
             prikey = tempkey;
             break;
       
   case 'H': setvpage(1); /* Help just changes screens */
             temp = getch();
             if(temp == ' ')
                    {setvpage(2);
                     temp = getch();
                     }
             setvpage(0);
             break;
                    
 
   case 'L': if(prikey != 0)
                 auto_term();
             e_col = 16; /* highlite letter selection */
             spot_print(0x70, char_mul);
             prikey = tempkey;
             break;
          
 
   case 'W': if(prikey != 0)
                 auto_term();
             e_col = 39;
             spot_print(0x70, word_mul);
             prikey = tempkey;
             break;
 
          
   case ' ': if(spad_flag == ON) /* toggle scratch pad */
                {spad_flag = OFF;
                 poscurs(20,42);
                 writechs('O', 0x07,1);
                 poscurs(20,43);
                 writechs('F',0x07,2);
                 }
 
              else{
              spad_flag = ON;
              poscurs(spad_row, spad_col);
              writechs('|', 0x07, 1);
               spad_col++;
               if(spad_col > 79)
                  {spad_col = 0;
                     spad_row++;
                       if(spad_row > 24)
                         {spad_row = 24;
                          scroll(spadscrn, 1,UP);
                          }
                    }
              poscurs(20,42);
              writechs('O',0x70,1);
              poscurs(20,43);
              writechs('N',0x70,1);
              poscurs(20,44);
              writechs(' ',0x07,1);
              }
        break;
 
   case '+': if(prikey != 0)
                   {if(prikey == 'L')
                           {char_mul++;
                            if(char_mul > 45)
                              char_mul = 45;
                       e_col = 16;
                     spot_print(0x70, char_mul);
                             }
                     if(prikey == 'W')
                            {word_mul = word_mul + 1;
                                if(word_mul > 95)
                                   word_mul = 95;
                           e_col = 39;
                            spot_print(0x70, word_mul);
                              }
                     if(prikey == 'F')
                             {filter_co = filter_co + filter_co;
                                if(filter_co > 64)
                                    filter_co = 16;
                                filter_print(0x70);
                              }
                         }
             else putch(BELL);
                       break;
 
   case '-': if(prikey != 0)
                    {if(prikey == 'L')
                           {char_mul--;
                               if(char_mul < 5)
                                  char_mul = 5;
                            e_col = 16;
                            spot_print(0x70, char_mul);
                            }
                      if(prikey == 'W')
                            {word_mul = word_mul - 1;
                                if(word_mul < 25)
                                  word_mul = 25;
                            e_col = 39;
                            spot_print(0x70, word_mul);
                             }
                      if(prikey == 'F')
                             {filter_co = filter_co/2;
                               if(filter_co < 16)
                                    filter_co = 64;
                              filter_print(0x70);
                              }
                       }
            else putch(BELL);
            break;
 
          case 'R':  char_mul = 17;
                     word_mul = 67;
                     filter_co = 32;
                     prikey = 0;
                     e_col = 16;
                     poscurs(e_row, e_col);
                     spot_print(0x07, char_mul);
                     e_col = 39;
                     poscurs(e_row, e_col);
                     spot_print(0x07, word_mul);
                     e_col = 69;
                     poscurs(e_row, e_col);
                     filter_print(0x07);
                     spad_flag = OFF;
                     poscurs(20,42);
                     writechs('O', 0x07,1);
                     poscurs(20,43);
                     writechs('F',0x07,2);
                     poscurs(8,55);
                     if(teach == ON)
                        printf("Teach ");
                     else printf("Normal");
                  break;
          
 
          case 'S':  scroll(spadscrn, 0 , UP);
                     spad_col = 0;
                     spad_row = 21;
                     break;
 
          case 0x0D: prikey = 0;
                     e_col = 16;
                     poscurs(e_row, e_col);
                     spot_print(0x07, char_mul);
                     e_col = 39;
                     poscurs(e_row, e_col);
                     spot_print(0x07, word_mul);
                     e_col = 69;
                     poscurs(e_row, e_col);
                     filter_print(0x07);
                     break;
        case 'Q':setvmode(old_vmode);
                 regs.x.dx = 0;  /* Restore COM1 */
                 regs.h.ah = 0;
                 regs.h.al = 0xE3;
 /* re-set to 9600 bd 1 Start, 1 stop, no parity, 8 bits */
                 int86(0x14,&regs,&regs);
                 curson();
                 exit(0);
  
       case 'M':  poscurs(8,55);
                  if(teach == ON)
                    {teach = OFF;
                     printf("Normal");
                     }
                  else{
                     teach = ON;
                     printf("Teach ");
                      }
                   break;
 
            default: putch(BELL);
                     break;
            }/* end of switch*/
poscurs(row,col);
curson();
return; /* return from entry_func */
} /* end of entry_func */
           
void spot_print(int attr, val)
{int tens, ones;
            tens = val/10;
            ones = val - (10*tens);
            poscurs(e_row, e_col);
            if(tens == 0)
                  tens = -0x10; /* fake a space */
            writechs(tens + 0x30, attr, 1);
            e_col++;
            poscurs(e_row, e_col);
            writechs('.', attr, 1);
            e_col++;
            poscurs(e_row, e_col);
            writechs(ones + 0x30, attr, 1);
 return;
 
}
 
void filter_print(int attr)
{
 e_col = 71;
             if(filter_co == 16)
                    {poscurs(e_row, e_col);
                     writechs('L', attr, 1);
                     e_col++;
                     poscurs(e_row, e_col);
                     writechs('O', attr, 1);
                     e_col++;
                     poscurs(e_row, e_col);
                     writechs('W', attr, 1);
                     }
             if(filter_co == 32)
                    {poscurs(e_row, e_col);
                     writechs('M', attr, 1);
                     e_col++;
                     poscurs(e_row, e_col);
                     writechs('E', attr, 1);
                     e_col++;
                     poscurs(e_row, e_col);
                     writechs('D', attr, 1);
                     }
             if(filter_co == 64)
                    {poscurs(e_row, e_col);
                     writechs('H', attr, 1);
                     e_col++;
                     poscurs(e_row, e_col);
                     writechs('I', attr, 1);
                     e_col++;
                     poscurs(e_row, e_col);
                     writechs(' ', attr, 1);
                     }
 return;
} /* end of filter_print*/
 
void scroll(struct WINDOW window, int lines, int dir)
{
regs.h.ah = dir;
regs.h.al = lines;
regs.h.ch = window.tlrow;
regs.h.cl = window.tlcol;
regs.h.dh = window.brrow;
regs.h.dl = window.brcol;
regs.h.bh = window.attr;
int86(0x10,&regs,&regs);
return;
}
 
void auto_term(void)
{
e_row = 8;
e_col = 16;
spot_print(0x07, char_mul);
e_col = 39;
spot_print(0x07, word_mul);
filter_print(0x07);
return;
}
 
void wpm_func(void)
{int wpm, huns, tens;
if(avg <= 0)
    {poscurs(10, 39);
     writechs('*',0x07,3);
     return;
     }
wpm = 2400/avg;
huns = wpm/100;
wpm = wpm - (huns * 100);
tens = wpm/10;
wpm = wpm - (tens * 10);
poscurs(10,39);
if(huns == 0)
        huns = -0x10;
writechs(huns + 0x30, 0x07, 1);
poscurs(10,40);
if(tens == 0 && huns == -0x10 )
        tens = -0x10; /* fake a space */
writechs(tens + 0x30, 0x07,1);
poscurs(10,41);
writechs(wpm + 0x30, 0x07,1);
return;
}
void char_out(void)
     {
      int attr;
      write_flag = RESET;
      attr = 0x07;
      if(sec_char != 0)
         attr = 0x70;
      poscurs(row, col);
      writechs(write_char, attr, 1);
      col++;
         if(col > 79)
               {col = 0;
                  if(row < 19)
                        row++;
                    else
                      scroll(screen, 1, UP);
                 }
           if(spad_flag == ON)
                   {spad_col++;
                       if(spad_col > 79)
                            {spad_col = 0;
                              if(spad_row < 24)
                                  spad_row++;
                              else scroll(spadscrn, 1, UP);
                             }
                       poscurs(spad_row, spad_col);
                       writechs(write_char, attr, 1);
                    }
poscurs(row,col);
return;
       }
 
void diagnostic(void)
 
{int count, *ptr;
 
scroll(screen, 0, UP);
poscurs(11,0);
printf("Average mark milliseconds %li\n",avg);
printf("Last 8 mark times in milliseconds\n");
ptr = mark_ptr;
for(count = 0; count < 8 ; count++)
           {printf("%i  ", *ptr);
            ptr--;
            if(ptr < &mark_stack[0])
                 ptr = &mark_stack[SIZE -1];
            }
printf("\n");
printf("Average deviation from mean milliseconds %li\n",md_avg);
printf("Last 8 mean deviation times in milliseconds\n");
ptr = md_ptr;
for(count = 0; count <8 ; count++)
           {printf("%i   ", *ptr);
            ptr--;
            if(ptr < &md_stack[0])
                 ptr = &md_stack[SIZE - 1];
            }
printf("\n");
printf("Last 8 space times in milliseconds\n");
ptr = sp_ptr;
for(count = 0; count < 8 ; count++)
           {printf("%i   ", *ptr);
            ptr--;
            if(ptr < &sp_buffer[0])
                 ptr = &sp_buffer[7];
            }
printf("\n");
count = getch();
scroll(screen,0,UP);
row = 11;
col = 0;
return;
}
                                                                                                         