home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / cw / robocopy / robo.c < prev    next >
Text File  |  1990-09-20  |  30KB  |  979 lines

  1.  
  2.  
  3.  
  4.  /* CW monitor uses RI signal on COM1 (pin 8 of DB25 pin 9 on a DB9) */
  5.  /* input stimulus. A space = +5v, mark = 0v works with RS 232 systems */
  6.  /* CTS and DSR must be tied to space level (5v) for port to operate */
  7.           /* CTS is 5/DB25 8/DB9 DSR is 6/DB25 6/DB9 */
  8.  
  9. #include <stdio.h>
  10. #include <bios.h>
  11. #include <dos.h>
  12. #include <graphics.h>
  13. #include <conio.h>
  14. #include <sys\timeb.h>
  15. #include <sys\types.h>
  16.  
  17. #define SIZE 32
  18. #define PRINT_CHAR 0
  19. #define PRINT_SPACE 1
  20. #define PRINT_OVR 2
  21. #define FLUSH 1
  22. #define UPDATE 2
  23. #define MARK  0x80
  24. #define SPACE 0
  25. #define RESET 0
  26. #define SET   1
  27. #define ON    1
  28. #define OFF   0
  29. #define DIT   1
  30. #define DAH   2
  31. #define NULL  0
  32. #define HIGH  1
  33. #define LOW   0
  34. #define START 0
  35. #define STOP  2
  36. #define FINISH 1
  37. #define READ 1
  38. #define NORMAL 7
  39. #define UP 6
  40. #define DOWN 7
  41. #define BELL 7
  42. #define TICK 1
  43. #define NOTICK 0
  44.  
  45.  
  46. union REGS regs;
  47.  
  48. struct WINDOW {
  49. unsigned char tlrow;
  50. unsigned char tlcol;
  51. unsigned char brrow;
  52. unsigned char brcol;
  53. unsigned char attr;
  54. };
  55. struct WINDOW screen = {11,0,19,79,NORMAL};
  56. struct WINDOW spadscrn = {21,0,24,79,NORMAL};
  57. int space_msec, mark_msec, temp, old_vmode, space_flag, row, col,
  58.     loop, buffer[9], *bufptr, word_flag, word_mul, char_mul, prikey,
  59.     char_flag, mark_count, init_flag, spad_flag, spad_row, spad_col,
  60.     mark_stack[SIZE], *mark_ptr, md_stack[SIZE], *md_ptr, fence, *temp_ptr,
  61.     sp_buffer[8], *sp_ptr, sp_count, filter_co, write_flag, write_char,
  62.     tempkey, e_col, e_row, key, sec_char, dit_msec, skew_count, delta_sec,
  63.     delta_msec, speed, wpm_flag, teach;
  64. long avg, md_avg, md_val;
  65.  
  66.                    /* func declarations */
  67.  
  68. void char_print(int c_flag);
  69. int read_port(int next_state);
  70. void space_func(void);
  71. void mark_func(void);
  72. int stop_watch(void);
  73. void entry_func(void);
  74. void write(char *strptr);
  75. void scroll(struct WINDOW window, int lines, int dir);
  76. void spot_print(int attr, val);
  77. void filter_print(int attr);
  78. void auto_term(void);
  79. void wpm_func(void);
  80. void char_out(void);
  81. void diagnostic(void);
  82.                       /* initialize program */
  83.  
  84.            /* set up nominal operation parameters */
  85. main()
  86. {
  87. teach = OFF;
  88. init_flag = SET;
  89. spad_flag = OFF;
  90. row = 11;
  91. col = 0;
  92. spad_row = 21;
  93. spad_col = 0;
  94. prikey = 0;
  95. write_flag = RESET;
  96. fence = 100;
  97. filter_co = 32;
  98. char_mul =25;
  99. word_mul = 67;
  100. skew_count = 0;
  101. for(temp_ptr = &mark_stack[0]; temp_ptr <= &mark_stack[SIZE -1]; temp_ptr++)
  102.                       *temp_ptr = 100;
  103.  
  104. for(temp_ptr = &md_stack[0]; temp_ptr <= &md_stack[SIZE -1]; temp_ptr++)
  105.                       *temp_ptr = 0;
  106. mark_ptr = &mark_stack[0];
  107. md_ptr = &md_stack[0];
  108. sp_ptr = &sp_buffer[0];
  109. sp_count = 0;
  110. bufptr = &buffer[0];
  111.  for(loop = 0; loop < 8; loop++)
  112.          {*bufptr = NULL;
  113.            bufptr++;
  114.           }
  115.  mark_count = 0;
  116.  bufptr = &buffer[0];
  117.  
  118.       /* set up com1 as 4800bd 7 bits 1 stop, 1 start, no parity */
  119.                    /* fakes a real good 2 ms time clock */
  120.  
  121. regs.x.dx = 0;
  122. regs.h.ah = 0;
  123. regs.h.al = 0xC2;
  124. int86(0x14,®s,®s);
  125.  
  126.                 /* set up entry and working screens */
  127.                 /* code displayed on screen 0 */
  128.  
  129.   
  130. old_vmode = getvmode();
  131. setvmode(3);
  132. setcolor(9,3);
  133. setapage(0);
  134. clrscrn();
  135. poscurs(0,7);
  136. write("ROBO-COPy 73 Magazine Automated CW Copier by WB9DYI/Mike Hansen");
  137. poscurs(2,7);
  138. write("Change a copy parameter by typing it's first letter (L,W,F); then ");
  139. poscurs(3,7);
  140. write("modify value using +/- keys. Terminate change by pressing Enter key.");
  141. poscurs(4,7);
  142. write("Type H for help; Q exits to DOS; R resets copy parameters. Space bar");
  143. poscurs(5,7);
  144. write("toggles scratch pad area on/off. Type S to clear scratch pad area,");
  145. poscurs(6,7);
  146. write("C to clear copy area. M toggles between normal and teach modes.");
  147. poscurs(8,2);
  148. write("Letter Timing     dits.  Word Timing     dits.  Mode          Filter");
  149. poscurs(10,0);
  150. writechs('_',0x07,80);
  151. poscurs(10,33);
  152. write("WPM =    ");
  153. poscurs(20,0);
  154. writechs('-',0x07,80);
  155. poscurs(20,30);
  156. write("Scratch Pad      ");
  157. setvpage(0);           /* copy starts at row 10 col 0 */
  158.  
  159.                          /* v_page 0 cleared for copy */
  160.  
  161.  
  162.                        /* set up help screen, v_ page 1 */
  163.  
  164. setapage(1);
  165. setcolor(9,3);
  166. poscurs(0,9);
  167. write("Intended for private use only. All commercial rights reserved.");
  168. poscurs(2,27);
  169. write("ROBO-COPy HELP SCREEN");
  170. poscurs(3,10);
  171. write("Decrease letter timing when the over run error ");
  172. poscurs(4,10);
  173. write("symbol # ocurrs frequently.");
  174. poscurs(6,10);
  175. write("Increase letter timing when longer characters");
  176. poscurs(7,10);
  177. write("break-up into short letters; example SOS = EEETTTEEE.");
  178. poscurs(9,10);
  179. write("If wordsruntogetherlikethis...decrease word timing.");
  180. poscurs(11,10);
  181. write("If letters a r e separated in words...increase word timing.");
  182. poscurs(13,10);
  183. write("A sampling filter helps reduce the effects of QRN. It has three ");
  184. poscurs(14,10);
  185. write("settings, LOW, MEDIUM and HI. LOW filtering is best for");
  186. poscurs(15,10);
  187. write("high speed reception, but is more susceptible to noise.");
  188. poscurs(16,10);
  189. write("When receiving noisy signals, HI filtering works to eliminate the");
  190. poscurs(17,10);
  191. write("interference but reduces copy speed to less than 30-35 WPM.");
  192. poscurs(19,10);
  193. write("Unrecognized characters and errors are displayed as *.");
  194. poscurs(20,10);
  195. write("Command characters like    are displayed in reverse video.");
  196. poscurs(20,34);
  197. writechs('S',0x70,1);
  198. poscurs(20,35);
  199. writechs('K',0x70,1);
  200. poscurs(21,10);
  201. write("Keep important QSO data like call signs, etc. in Scratch Pad");
  202. poscurs(22,10);
  203. write("by toggling area ON/OFF with Space bar. Type S to clear the area.");
  204. poscurs(24,13);
  205. write("Press space bar for more HELP, Press Enter key to exit HELP.");
  206.                   /* screen 1 finished */
  207.  
  208. setapage(2);
  209. poscurs(0,23);
  210. write("Recommend receiver operation for ROBO-COPy");
  211. poscurs(2,10);
  212. write("The ROBO-COPy interface can be connected in parallel with either");
  213. poscurs(3,10);
  214. write("the speaker or low-impedance headphone outputs. The added load is");
  215. poscurs(4,10);
  216. write("about 330 ohms, and should have no noticeable effect on the quality");
  217. poscurs(5,10);
  218. write("or volume of the audio output. The output of the ROBO-COPy ");
  219. poscurs(6,10);
  220. write("interface should be connected to the COM1 port of the P.C..");
  221. poscurs(8,30);
  222. write("ROBO-COPying a CW station");
  223. poscurs(10,20);
  224. write("AGC = FAST, Noise Blanker = ON, CW Filter = ON");
  225. poscurs(11,10);
  226. write("1. Tune station as you would normally do for cw reception.");
  227. poscurs(12,10);
  228. write("2. Reduce audio and RF gain to the MINIMUM needed for solid copy.");
  229. poscurs(13,10);
  230. write("3. Increase audio gain until LED on ROBO-COPy interface flashes");
  231. poscurs(14,10);
  232. write("   bright, distinct dits and dahs.");
  233. poscurs(24,25);
  234. write("Press any key to exit HELP.");
  235.  
  236. setapage(0);
  237. setvpage(0);
  238.  
  239. do
  240.    {if(read_port(MARK) != SPACE)
  241.              mark_func();
  242.     space_func();
  243.     }while (0 == 0);
  244.  
  245.  }/* end of main brace */
  246.  
  247.  
  248.               /* start of program */
  249. void space_func(void)
  250. {
  251. word_flag = START;
  252. char_flag = START; /* start assembling character */
  253. space_msec = 0;
  254. while(read_port(MARK) == SPACE)
  255.     { if(stop_watch() == TICK)
  256.       space_msec = space_msec + 2;
  257.  
  258.              /* check keyboard */
  259.        key = getkey();
  260.        if(key != EOF || init_flag == SET)
  261.            entry_func();
  262.  
  263.           /* background task of displaying data */
  264.  
  265.     if(write_flag == SET)  /* write to screen */
  266.               {   char_out();
  267.                   if(sec_char != 0)
  268.                     {write_char = sec_char;
  269.                      char_out();
  270.                      }
  271.                }
  272.   
  273.    if(teach == OFF)
  274.       {
  275.       dit_msec = avg/2;
  276.       if(space_msec > (char_mul * dit_msec)/10  && char_flag == START &&
  277.                                   mark_count > 0)
  278.                            {char_print(PRINT_CHAR);
  279.                             char_flag = FINISH;
  280.                             wpm_func(); /* outputwpm */
  281.                             }
  282.      
  283. if(space_msec > (word_mul * dit_msec)/10 && word_flag == START)
  284.                             {word_flag = FINISH;
  285.                              char_print(PRINT_SPACE);
  286.                             }
  287.  
  288.       }
  289.  
  290.  
  291.   
  292. } /* done with background house keeping now back to biz */
  293.         
  294.                   /* process space */
  295.   if(teach == ON)
  296.       {
  297.                     dit_msec = avg/2;
  298.       if(space_msec > (char_mul * dit_msec)/10  && char_flag == START &&
  299.                                   mark_count > 0)
  300.               {char_print(PRINT_CHAR);
  301.                char_flag = FINISH;
  302.                wpm_func(); /* outputwpm */
  303.                if(write_flag == SET)  /* write to screen */
  304.                 {char_out();
  305.                   if(sec_char != 0)
  306.                     {write_char = sec_char;
  307.                      char_out();
  308.                      }
  309.                  }
  310.                }
  311. if(space_msec > (word_mul * dit_msec)/10 && word_flag == START)
  312.                             {word_flag = FINISH;
  313.                              char_print(PRINT_SPACE);
  314.                              char_out();
  315.                              }
  316.      }
  317.     return; /* return on mark */
  318. } /* end of space_func  */
  319.  
  320. void mark_func(void)
  321.  {
  322.  
  323.     /* MARK detected in space_func is timed here */
  324. sp_count++;
  325. if(sp_count > 7)
  326.    {sp_count = 0;
  327.     sp_ptr = &sp_buffer[0];
  328.    }
  329. *sp_ptr = space_msec;
  330. sp_ptr++;
  331. mark_msec = 2; /* add 2 for initial loop-compensates for sampling time */
  332.  
  333.            /* check for end of mark */
  334.  
  335.               while(read_port(SPACE) != SPACE)
  336.                       {if(stop_watch() == TICK)
  337.                          {if(mark_msec < 1000)
  338.                            mark_msec = mark_msec + 2;
  339.                           }
  340.                        }
  341.                   /* is mark within range ? */
  342.     if(mark_msec < 10 )
  343.                       return;
  344.  
  345.                mark_count++;
  346.               if(mark_msec > fence)
  347.                          *bufptr = DAH;
  348.                  else *bufptr  = DIT;
  349.                  bufptr++;
  350.                  if(bufptr > &buffer[8])
  351.                          char_print(PRINT_OVR);
  352.  
  353.        /* calculate latest mean deviation and store on stack */
  354.  
  355.                  md_ptr++;
  356.                  if(md_ptr > &md_stack[SIZE -1])
  357.                         md_ptr = &md_stack[0];
  358.                  *md_ptr = mark_msec - avg;
  359.  
  360.          /* calculate new average of mean deviation */
  361.           
  362.                   md_avg = 0;
  363.    for(temp_ptr = &md_stack[0]; temp_ptr <= &md_stack[SIZE -1]; temp_ptr++)
  364.                   md_avg = md_avg + *temp_ptr;
  365.                   md_avg = md_avg/SIZE;
  366.  
  367.       /* generate absolute value of mean deviation times 4 */
  368.                   md_val = 4 * md_avg;
  369.                   if(md_val < 0)
  370.                        md_val = -1 * md_val;
  371.  
  372.  
  373.     /* avoid corrupting average with skew due to repetition */
  374.   
  375. if(mark_msec < *mark_ptr + (*mark_ptr/8) ||
  376.                           mark_msec > *mark_ptr - (*mark_ptr/8))
  377.                     skew_count++;
  378.                           else skew_count = 0;
  379.            
  380.             if(skew_count < 4 || md_val > avg)
  381.                      
  382.            {
  383.                   /* load mark_stack with last mark */
  384.                     mark_ptr++;
  385.                      if(mark_ptr > &mark_stack[SIZE -1])
  386.                           mark_ptr = &mark_stack[0];
  387.                     *mark_ptr = mark_msec;
  388.  
  389.                   /* calculate new average */
  390.                      avg = 0;
  391.  for(temp_ptr = &mark_stack[0]; temp_ptr <= &mark_stack[SIZE -1]; temp_ptr++)
  392.                         avg = avg + *temp_ptr;
  393.                    avg = avg/SIZE;
  394.  
  395.                
  396.           /* calculate new fence point */
  397.                 fence = avg +  md_avg;
  398.                  }
  399.              
  400.   return;
  401. }                   /* end of mark_func */
  402.  
  403.  
  404. void char_print(int c_flag)
  405.  
  406.   { int temp, exp, loop, sum;
  407.  
  408. char letter[] ="ETIANMSURWDKGOHVF*L*PJBXCYZQ";
  409. char alpha;
  410. char *letter_ptr, *number_ptr;
  411. sec_char = 0; /* reset special command character value */
  412. write_flag = SET;
  413.     if(c_flag == PRINT_OVR)
  414.                 write_char = '#';
  415.  
  416.     if(c_flag == PRINT_SPACE)
  417.                 write_char = ' ';
  418. else{
  419.     bufptr = &buffer[7];
  420.     sum = 0;
  421.     exp = 128;
  422.     for(loop = 0; loop < 8; loop++)
  423.                    {temp = *bufptr;
  424.                       while(*bufptr == 0)
  425.                          {exp = exp/2;
  426.                           bufptr--;
  427.                            }
  428.                      }
  429.      bufptr = &buffer[0];
  430.       while(exp != 0)
  431.                  { sum = sum + ((*bufptr) * exp);
  432.                    exp = exp/2;
  433.                    bufptr++;
  434.                  }
  435.  
  436.         if(mark_count == 0)
  437.                 return;
  438.        if((mark_count <= 4) && (sum < 29))
  439.                   {letter_ptr = &letter[0];
  440.                    alpha = *(letter_ptr + (sum - 1));
  441.                    write_char = alpha;
  442.                    }
  443.         if(mark_count== 5)
  444.                    {switch(sum){
  445.                     case 62: write_char = '0';
  446.                              break;
  447.                     case 61: write_char = '9';
  448.                              break;
  449.                     case 59: write_char = '8';
  450.                              break;
  451.                     case 55: write_char = '7';
  452.                              break;
  453.                     case 47: write_char = '6';
  454.                              break;
  455.                     case 31: write_char = '5';
  456.                              break;
  457.                     case 32: write_char = '4';
  458.                              break;
  459.                     case 34: write_char = '3';
  460.                              break;
  461.                     case 38: write_char = '2';
  462.                              break;
  463.                     case 46: write_char = '1';
  464.                              break;
  465.                     case 33: write_char = 'S';
  466.                              sec_char = 'N';
  467.                              break;
  468.                     case 41: write_char = 'A';
  469.                              sec_char = 'R';
  470.                              break;
  471.                     case 39: write_char = 'A';
  472.                              sec_char = 'S';
  473.                              break;
  474.                     case 52: write_char = 'K';
  475.                              sec_char = 'A';
  476.                              break;
  477.                     case 48: write_char = '=';
  478.                              break;
  479.                     case 49: write_char = '/';
  480.                              break;
  481.                     case 53: write_char = '(';
  482.                              break;
  483.                     default: write_char = '*';
  484.                       }
  485.                     }
  486.               
  487.  
  488.         if(mark_count == 6)
  489.                         {switch(sum)
  490.                            {case 68: write_char = 'S';
  491.                                      sec_char = 'K';
  492.                                      break;
  493.                             case 75: write_char = '?';
  494.                                      break;
  495.                             case 84: write_char = '.';
  496.                                      break;
  497.                             case 114: write_char = ',';
  498.                                      break;
  499.                             case 93: write_char = ''';
  500.                                      break;
  501.                             case 76: write_char = 'I';
  502.                                      sec_char = 'Q';
  503.                                      break;
  504.                             case 83: write_char = 'A';
  505.                                      sec_char = 'L';
  506.                                      break;
  507.                             case 81: write_char = '"';
  508.                                      break;
  509.                             case 105: write_char = ';';
  510.                                       break;
  511.                             case 96: write_char = '-';
  512.                                      break;
  513.                             case 108: write_char = ')';
  514.                                      break;
  515.                             case 119: write_char = ':';
  516.                                      break;
  517.   
  518.                            default: write_char = '*';
  519.                             }
  520.                        }
  521.             if(mark_count == 7)
  522.                               {if(sum == 136)
  523.                                 write_char = '$';
  524.                                else write_char = '*';
  525.                                }
  526.  
  527.             if(mark_count == 8)
  528.                                {if(sum == 255)
  529.                                    {write_char = 'H';
  530.                                     sec_char = 'H';
  531.                                     }
  532.                                 else write_char = '*';
  533.                                 }
  534.  
  535. }/* end of else */
  536. for(bufptr = &buffer[0]; bufptr <= &buffer[7]; bufptr++)
  537.                       *bufptr = 0; /* clear DIT/DAH buffer */
  538. bufptr = &buffer[0];
  539. mark_count = 0;
  540. return;
  541. } /* end of char_print function */
  542.  
  543. int read_port(int next_state)
  544. {int fcount, temp, delay;
  545. /* read_port has a sampling filter built in. There must be */
  546. /*  filter_co times the next state before a transistion is reported via */
  547.                 /* the returned value */
  548. fcount = 0;
  549. do
  550.    {fcount++;
  551.     regs.x.dx = 0;
  552.     regs.h.ah = 3;
  553.     int86(0x14,®s,®s);
  554.     temp = regs.h.al & 0x80;
  555.     for(delay = 0; delay < 16; delay++)
  556.               ;
  557.     }while(temp == next_state && fcount < filter_co);
  558.    
  559.    if(fcount >= filter_co)
  560.                  temp = next_state; /* successfully completed filter */
  561.    else
  562.        {if(next_state == MARK) /* noisy signal returns current state */
  563.                  temp = SPACE;
  564.            else temp = MARK;
  565.         }
  566. return(temp);
  567. }
  568.  
  569.           /* stop_watch generates a 2 ms wait  */
  570.           
  571. int stop_watch(void)
  572.  
  573. {int loop;
  574. regs.x.dx = 0;
  575. regs.h.ah = 3;
  576. int86(0x14,®s,®s);
  577.  if(regs.h.ah & 0x40 == 0)
  578.          return(NOTICK); /* xmit buffer not empty */
  579. regs.x.dx = 0;  /* xmit buffer empty, fill it */
  580. regs.h.ah = 1;
  581. regs.h.al = ' ';
  582. int86(0x14,®s,®s);
  583. return(TICK);
  584. }
  585.   
  586. void write(char *strptr)
  587. {int row, col;
  588.  
  589. row = cursrow();
  590. col = curscol();
  591.  while(*strptr != NULL)
  592.       {writechs(*strptr, 0x07,1);
  593.        strptr++;
  594.        col++;
  595.        poscurs(row,col);
  596.         }
  597.  return;
  598.  }
  599.  
  600. void entry_func(void)
  601. {
  602. cursoff();
  603. e_row = 8; /* all parameters are on row 8 */
  604. tempkey = key & 0x00FF;  /* makes sure key is upper case */
  605. if(tempkey == '~')
  606.             {diagnostic();
  607.              return;
  608.             }
  609. if(tempkey > 0x60)
  610.          tempkey = tempkey - 32;
  611. if(init_flag == SET)
  612.          {init_flag = RESET;
  613.           tempkey = 'R';
  614.          }
  615.  
  616.  switch(tempkey)
  617.   {
  618.    case 'C': scroll(screen, 0 , UP); /* clear scratch pad screen */
  619.              row = 11;
  620.              col = 0;
  621.              break;
  622.  
  623.    case 'F': if(prikey != 0)
  624.                  auto_term();
  625.              filter_print(0x70);
  626.              prikey = tempkey;
  627.              break;
  628.        
  629.    case 'H': setvpage(1); /* Help just changes screens */
  630.              temp = getch();
  631.              if(temp == ' ')
  632.                     {setvpage(2);
  633.                      temp = getch();
  634.                      }
  635.              setvpage(0);
  636.              break;
  637.                     
  638.  
  639.    case 'L': if(prikey != 0)
  640.                  auto_term();
  641.              e_col = 16; /* highlite letter selection */
  642.              spot_print(0x70, char_mul);
  643.              prikey = tempkey;
  644.              break;
  645.           
  646.  
  647.    case 'W': if(prikey != 0)
  648.                  auto_term();
  649.              e_col = 39;
  650.              spot_print(0x70, word_mul);
  651.              prikey = tempkey;
  652.              break;
  653.  
  654.           
  655.    case ' ': if(spad_flag == ON) /* toggle scratch pad */
  656.                 {spad_flag = OFF;
  657.                  poscurs(20,42);
  658.                  writechs('O', 0x07,1);
  659.                  poscurs(20,43);
  660.                  writechs('F',0x07,2);
  661.                  }
  662.  
  663.               else{
  664.               spad_flag = ON;
  665.               poscurs(spad_row, spad_col);
  666.               writechs('|', 0x07, 1);
  667.                spad_col++;
  668.                if(spad_col > 79)
  669.                   {spad_col = 0;
  670.                      spad_row++;
  671.                        if(spad_row > 24)
  672.                          {spad_row = 24;
  673.                           scroll(spadscrn, 1,UP);
  674.                           }
  675.                     }
  676.               poscurs(20,42);
  677.               writechs('O',0x70,1);
  678.               poscurs(20,43);
  679.               writechs('N',0x70,1);
  680.               poscurs(20,44);
  681.               writechs(' ',0x07,1);
  682.               }
  683.         break;
  684.  
  685.    case '+': if(prikey != 0)
  686.                    {if(prikey == 'L')
  687.                            {char_mul++;
  688.                             if(char_mul > 45)
  689.                               char_mul = 45;
  690.                        e_col = 16;
  691.                      spot_print(0x70, char_mul);
  692.                              }
  693.                      if(prikey == 'W')
  694.                             {word_mul = word_mul + 1;
  695.                                 if(word_mul > 95)
  696.                                    word_mul = 95;
  697.                            e_col = 39;
  698.                             spot_print(0x70, word_mul);
  699.                               }
  700.                      if(prikey == 'F')
  701.                              {filter_co = filter_co + filter_co;
  702.                                 if(filter_co > 64)
  703.                                     filter_co = 16;
  704.                                 filter_print(0x70);
  705.                               }
  706.                          }
  707.              else putch(BELL);
  708.                        break;
  709.  
  710.    case '-': if(prikey != 0)
  711.                     {if(prikey == 'L')
  712.                            {char_mul--;
  713.                                if(char_mul < 5)
  714.                                   char_mul = 5;
  715.                             e_col = 16;
  716.                             spot_print(0x70, char_mul);
  717.                             }
  718.                       if(prikey == 'W')
  719.                             {word_mul = word_mul - 1;
  720.                                 if(word_mul < 25)
  721.                                   word_mul = 25;
  722.                             e_col = 39;
  723.                             spot_print(0x70, word_mul);
  724.                              }
  725.                       if(prikey == 'F')
  726.                              {filter_co = filter_co/2;
  727.                                if(filter_co < 16)
  728.                                     filter_co = 64;
  729.                               filter_print(0x70);
  730.                               }
  731.                        }
  732.             else putch(BELL);
  733.             break;
  734.  
  735.           case 'R':  char_mul = 17;
  736.                      word_mul = 67;
  737.                      filter_co = 32;
  738.                      prikey = 0;
  739.                      e_col = 16;
  740.                      poscurs(e_row, e_col);
  741.                      spot_print(0x07, char_mul);
  742.                      e_col = 39;
  743.                      poscurs(e_row, e_col);
  744.                      spot_print(0x07, word_mul);
  745.                      e_col = 69;
  746.                      poscurs(e_row, e_col);
  747.                      filter_print(0x07);
  748.                      spad_flag = OFF;
  749.                      poscurs(20,42);
  750.                      writechs('O', 0x07,1);
  751.                      poscurs(20,43);
  752.                      writechs('F',0x07,2);
  753.                      poscurs(8,55);
  754.                      if(teach == ON)
  755.                         printf("Teach ");
  756.                      else printf("Normal");
  757.                   break;
  758.           
  759.  
  760.           case 'S':  scroll(spadscrn, 0 , UP);
  761.                      spad_col = 0;
  762.                      spad_row = 21;
  763.                      break;
  764.  
  765.           case 0x0D: prikey = 0;
  766.                      e_col = 16;
  767.                      poscurs(e_row, e_col);
  768.                      spot_print(0x07, char_mul);
  769.                      e_col = 39;
  770.                      poscurs(e_row, e_col);
  771.                      spot_print(0x07, word_mul);
  772.                      e_col = 69;
  773.                      poscurs(e_row, e_col);
  774.                      filter_print(0x07);
  775.                      break;
  776.         case 'Q':setvmode(old_vmode);
  777.                  regs.x.dx = 0;  /* Restore COM1 */
  778.                  regs.h.ah = 0;
  779.                  regs.h.al = 0xE3;
  780.  /* re-set to 9600 bd 1 Start, 1 stop, no parity, 8 bits */
  781.                  int86(0x14,®s,®s);
  782.                  curson();
  783.                  exit(0);
  784.   
  785.        case 'M':  poscurs(8,55);
  786.                   if(teach == ON)
  787.                     {teach = OFF;
  788.                      printf("Normal");
  789.                      }
  790.                   else{
  791.                      teach = ON;
  792.                      printf("Teach ");
  793.                       }
  794.                    break;
  795.  
  796.             default: putch(BELL);
  797.                      break;
  798.             }/* end of switch*/
  799. poscurs(row,col);
  800. curson();
  801. return; /* return from entry_func */
  802. } /* end of entry_func */
  803.            
  804. void spot_print(int attr, val)
  805. {int tens, ones;
  806.             tens = val/10;
  807.             ones = val - (10*tens);
  808.             poscurs(e_row, e_col);
  809.             if(tens == 0)
  810.                   tens = -0x10; /* fake a space */
  811.             writechs(tens + 0x30, attr, 1);
  812.             e_col++;
  813.             poscurs(e_row, e_col);
  814.             writechs('.', attr, 1);
  815.             e_col++;
  816.             poscurs(e_row, e_col);
  817.             writechs(ones + 0x30, attr, 1);
  818.  return;
  819.  
  820. }
  821.  
  822. void filter_print(int attr)
  823. {
  824.  e_col = 71;
  825.              if(filter_co == 16)
  826.                     {poscurs(e_row, e_col);
  827.                      writechs('L', attr, 1);
  828.                      e_col++;
  829.                      poscurs(e_row, e_col);
  830.                      writechs('O', attr, 1);
  831.                      e_col++;
  832.                      poscurs(e_row, e_col);
  833.                      writechs('W', attr, 1);
  834.                      }
  835.              if(filter_co == 32)
  836.                     {poscurs(e_row, e_col);
  837.                      writechs('M', attr, 1);
  838.                      e_col++;
  839.                      poscurs(e_row, e_col);
  840.                      writechs('E', attr, 1);
  841.                      e_col++;
  842.                      poscurs(e_row, e_col);
  843.                      writechs('D', attr, 1);
  844.                      }
  845.              if(filter_co == 64)
  846.                     {poscurs(e_row, e_col);
  847.                      writechs('H', attr, 1);
  848.                      e_col++;
  849.                      poscurs(e_row, e_col);
  850.                      writechs('I', attr, 1);
  851.                      e_col++;
  852.                      poscurs(e_row, e_col);
  853.                      writechs(' ', attr, 1);
  854.                      }
  855.  return;
  856. } /* end of filter_print*/
  857.  
  858. void scroll(struct WINDOW window, int lines, int dir)
  859. {
  860. regs.h.ah = dir;
  861. regs.h.al = lines;
  862. regs.h.ch = window.tlrow;
  863. regs.h.cl = window.tlcol;
  864. regs.h.dh = window.brrow;
  865. regs.h.dl = window.brcol;
  866. regs.h.bh = window.attr;
  867. int86(0x10,®s,®s);
  868. return;
  869. }
  870.  
  871. void auto_term(void)
  872. {
  873. e_row = 8;
  874. e_col = 16;
  875. spot_print(0x07, char_mul);
  876. e_col = 39;
  877. spot_print(0x07, word_mul);
  878. filter_print(0x07);
  879. return;
  880. }
  881.  
  882. void wpm_func(void)
  883. {int wpm, huns, tens;
  884. if(avg <= 0)
  885.     {poscurs(10, 39);
  886.      writechs('*',0x07,3);
  887.      return;
  888.      }
  889. wpm = 2400/avg;
  890. huns = wpm/100;
  891. wpm = wpm - (huns * 100);
  892. tens = wpm/10;
  893. wpm = wpm - (tens * 10);
  894. poscurs(10,39);
  895. if(huns == 0)
  896.         huns = -0x10;
  897. writechs(huns + 0x30, 0x07, 1);
  898. poscurs(10,40);
  899. if(tens == 0 && huns == -0x10 )
  900.         tens = -0x10; /* fake a space */
  901. writechs(tens + 0x30, 0x07,1);
  902. poscurs(10,41);
  903. writechs(wpm + 0x30, 0x07,1);
  904. return;
  905. }
  906. void char_out(void)
  907.      {
  908.       int attr;
  909.       write_flag = RESET;
  910.       attr = 0x07;
  911.       if(sec_char != 0)
  912.          attr = 0x70;
  913.       poscurs(row, col);
  914.       writechs(write_char, attr, 1);
  915.       col++;
  916.          if(col > 79)
  917.                {col = 0;
  918.                   if(row < 19)
  919.                         row++;
  920.                     else
  921.                       scroll(screen, 1, UP);
  922.                  }
  923.            if(spad_flag == ON)
  924.                    {spad_col++;
  925.                        if(spad_col > 79)
  926.                             {spad_col = 0;
  927.                               if(spad_row < 24)
  928.                                   spad_row++;
  929.                               else scroll(spadscrn, 1, UP);
  930.                              }
  931.                        poscurs(spad_row, spad_col);
  932.                        writechs(write_char, attr, 1);
  933.                     }
  934. poscurs(row,col);
  935. return;
  936.        }
  937.  
  938. void diagnostic(void)
  939.  
  940. {int count, *ptr;
  941.  
  942. scroll(screen, 0, UP);
  943. poscurs(11,0);
  944. printf("Average mark milliseconds %li\n",avg);
  945. printf("Last 8 mark times in milliseconds\n");
  946. ptr = mark_ptr;
  947. for(count = 0; count < 8 ; count++)
  948.            {printf("%i  ", *ptr);
  949.             ptr--;
  950.             if(ptr < &mark_stack[0])
  951.                  ptr = &mark_stack[SIZE -1];
  952.             }
  953. printf("\n");
  954. printf("Average deviation from mean milliseconds %li\n",md_avg);
  955. printf("Last 8 mean deviation times in milliseconds\n");
  956. ptr = md_ptr;
  957. for(count = 0; count <8 ; count++)
  958.            {printf("%i   ", *ptr);
  959.             ptr--;
  960.             if(ptr < &md_stack[0])
  961.                  ptr = &md_stack[SIZE - 1];
  962.             }
  963. printf("\n");
  964. printf("Last 8 space times in milliseconds\n");
  965. ptr = sp_ptr;
  966. for(count = 0; count < 8 ; count++)
  967.            {printf("%i   ", *ptr);
  968.             ptr--;
  969.             if(ptr < &sp_buffer[0])
  970.                  ptr = &sp_buffer[7];
  971.             }
  972. printf("\n");
  973. count = getch();
  974. scroll(screen,0,UP);
  975. row = 11;
  976. col = 0;
  977. return;
  978. }