home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / microcrn / issue_34.arc / SCOPE.FIG < prev   
Text File  |  1987-01-07  |  10KB  |  250 lines

  1.  
  2. (( This is Real World Figure 5 -- Oscilliscope Test Program ))
  3.  
  4. program test; {oscilliscope tester for Kaypro 2X.  By Bruce Eckel 8/86}
  5.  
  6. const
  7.      A_CONTROL: byte = $22;     {Control and Data I/O locations}
  8.      A_DATA: byte = $20;        {for each of the Z80 PIO ports}
  9.      B_CONTROL: byte = $23;
  10.      B_DATA: byte = $21;
  11.  
  12.      MODE : byte = $4f;         {0100 1111  mode 1 = input}
  13.      INT : byte = $07;          {0000 0111 interrupts disabled}
  14. var
  15.      temp,val : byte;
  16.  
  17. function noise_test : boolean; {this keeps the screen from
  18. flickering because of the noise in the bottom bit of the A/D
  19. converter}
  20. begin
  21.      if (             { part of what this function does is }
  22.      (temp <> val)    { stall the program while the A/D    }
  23.      and              { converter catches up }
  24.      (temp <> (val+1)))
  25.      then noise_test := true else noise_test := false;
  26. end;
  27. begin
  28.      port[A_CONTROL]:= MODE;   {initialize port A of the pio}
  29.      port[A_CONTROL]:= INT;    { port B is done the same way }
  30.  
  31. ClrScr; write(#27,'C4'); { Turn kaypro cursor off }
  32.  
  33. { Turbo's "port array" is used to write to the PIO.  The first
  34. one starts the A/D converter.  Note that most of the programming
  35. effort is just to make the screen output nice.  The following
  36. line is really all there is to running the A/D converter. }
  37.  
  38. val := port[A_DATA];
  39.  
  40. repeat begin
  41.        temp := port[A_DATA];
  42.        if  noise_test then begin
  43.               val := temp;
  44.               GotoXY(30,10); clreol; write('binary ',val, '     ');
  45.               { Note I take the value, divide it by the number of
  46.                steps, and multiply by the voltage range (my power
  47.                supply doesn't quite make it to 5.0).  The ":4:3"
  48.                is formatting information for Turbo.  Check the
  49.                results with your multimeter. }
  50.               write(((val/255) * 4.99 ):4:3, ' volts');
  51.               end;
  52.        end
  53. until keypressed;
  54. write(#27,'B4');  { Turn cursor back on }
  55. end.
  56.  
  57.  
  58. ((*************************************************************))
  59.  
  60. (( This is Real World Figure 6 -- Oscilliscope Program -- A/D ))
  61.  
  62.  
  63. program scope;    { oscilliscope program for A/D example.  By Bruce Eckel 8/86 }
  64. type
  65.      direction = (FALLING, RISING); { trigger on rising or falling edge }
  66.      binary = (ON,OFF);         { whether to turn a pixel on or off }
  67.      pixel_control = string[2]; { how to turn pixel on or off       }
  68.      screen_buffer = array[0..159] of integer; { Kaypro screen is 160 
  69.                                                   pixels wide }
  70. const
  71.      A_CONTROL: byte = $22;     {Control and Data I/O locations}
  72.      A_DATA: byte = $20;        {for the Z80 PIO port A }
  73.      MODE : byte = $4f;         {0100 1111  mode 1 = input}
  74.      INT : byte = $07;          {0000 0111 ints disabled}
  75.      min_capture_band : integer = 3; {minimum triggering search window}
  76. var
  77.    CH : char;  trigger_edge : direction;
  78.    low_capture_bound, high_capture_bound : integer;
  79.    sample_rate, pause_rate : integer;
  80.    point_buffer, pixel_buffer, old_pixel : screen_buffer;
  81.    loopcntr, dly, dlycntr : integer;
  82.    cursor_off, cursor_on : string[3];
  83.    pixel_off, pixel_on : pixel_control;
  84.    dim, bright, reverse_video, normal_video : string[3];
  85.    revdim,normal: string[6];
  86.  
  87. procedure terminal_customization; { should make it a little easier to}
  88. begin                             { customize for other computers.   }
  89.      cursor_off := #27 + 'C4';
  90.      cursor_on  := #27 + 'B4';
  91.      pixel_off  := #27 + ' ';
  92.      pixel_on   := #27 + '*';
  93.      dim := #27 + 'B1';           { If you don't have these features, just }
  94.      bright := #27 + 'C1';        { set the strings to ''.                 }
  95.      reverse_video := #27 + 'B0';
  96.      normal_video := #27 + 'C0';
  97.      revdim := reverse_video + dim;
  98.      normal := normal_video + bright;
  99. end;
  100.  
  101. procedure pixel(on_or_off:binary; vertical_coord, horizontal_coord : integer);
  102. const
  103.      vertical_offset : integer = 131;  { the kaypro's screen doesn't start 
  104.                                          at 0,0}
  105.      horizontal_offset : integer =32;  { these offsets start it in lower 
  106.                                          left corner}
  107. var pixel_char : pixel_control;
  108. begin
  109.      if (on_or_off = ON) then pixel_char := pixel_on else 
  110.                                             pixel_char := pixel_off ;
  111.      write(pixel_char, chr(vertical_offset - vertical_coord),
  112.                        chr(horizontal_offset + horizontal_coord));
  113. end;
  114.  
  115. procedure refresh_screen(var new_screen, old_screen : screen_buffer);
  116. { displays contents of point_buffer while erasing old trace on screen. }
  117. var pixel_counter : integer;
  118. begin
  119.      for pixel_counter := 0 to 159 do begin  {Kaypro screen width again...}
  120.          pixel(OFF, old_screen[pixel_counter], pixel_counter);
  121.          pixel(ON, new_screen[pixel_counter], pixel_counter);
  122.          old_screen[pixel_counter] := new_screen[pixel_counter];
  123.          end;
  124. end;
  125.  
  126. procedure ADC_delay (multiplier:integer); { Tried using assembly language
  127. here, but the overhead of the INLINE statement overwhelmed my timing loop.
  128. Adjust this until you get something from your A/D converter. }
  129. var i,j: integer;
  130. begin for i := 1 to multiplier do begin j :=0; j:= 1; j:=2; end; end;
  131.  
  132. procedure trigger(edge: direction; low_bound, high_bound : integer);
  133. var presentval,lastval : integer; slope, edge_not : direction;
  134. begin
  135.      edge_not := direction(ord(edge) xor 1);  { invert edge }
  136.      slope := edge_not;
  137.      presentval := port[A_DATA];
  138.      while (slope = edge_not) do begin   { wait for the right direction }
  139.            while (not ((presentval > low_bound)  { ... and range of values }
  140.                       and (presentval < high_bound))) do begin
  141.                  ADC_delay(1);
  142.                  presentval := port[A_DATA];
  143.                  end;
  144.            lastval := presentval;
  145.            ADC_delay(1); presentval := port [A_DATA];
  146.            if (((edge = RISING) and ( presentval > lastval)) or
  147.                ((edge = FALLING) and ( presentval < lastval)))
  148.            then slope := edge;
  149.     end;
  150.     delay(dly); { trigger delay in milliseconds }
  151. end;
  152.  
  153. procedure get_samples(rate :integer);
  154. { tried passing the point_buffer array by variable, but it slowed things
  155. down enough to make the data look bad }
  156. var counter : integer;
  157. begin
  158.      for counter := 0 to 159 do begin
  159.          point_buffer[counter] := port[A_DATA]; { point_buffer is global }
  160.          ADC_delay(rate);
  161.          end;
  162. end;
  163.  
  164. procedure process_samples(var input_point, output_point : screen_buffer);
  165. { put samples in a form which can be displayed }
  166. var index : integer;
  167. begin
  168.      for index :=0 to 159 do              {steps in A/D conv \/}
  169.          output_point[index] := (trunc ((input_point[index]/255)*99));
  170. end;                                   {vertical steps on screen /\}
  171.  
  172. procedure menu; { too many variables to bother passing -- all changed globally}
  173. var i : integer;
  174. begin
  175.    clrscr; gotoxy(1,3);
  176.    writeln('      ',revdim,'Digital Oscilliscope Options Menu:',normal);
  177.   writeln;
  178.    writeln('    t : change trigger delay.  Current delay = ',
  179.                       revdim,dly,normal,' mS');writeln;
  180.      write('    e : rising or falling trigger edge : ',revdim);
  181.    if trigger_edge = rising then writeln('RISING',normal)
  182.    else writeln('FALLING',normal); writeln;
  183.    writeln('    o : change trigger offset : ',revdim,low_capture_bound,normal); 
  184.    writeln;
  185.    writeln('    c : change trigger capture band : ',revdim,
  186.                         high_capture_bound - low_capture_bound, normal); 
  187.    writeln;
  188.    writeln('    s : change sample rate.  Current rate = ',
  189.                       revdim,sample_rate,normal);writeln;
  190.    writeln('    p : change pause rate : ',revdim,pause_rate,normal); 
  191. writeln;
  192.    writeln('          <ESC> : quit');writeln;
  193.    writeln('              any other key returns to sampling');
  194.    while(not keypressed) do; read(kbd,ch);
  195.    if (CH in (['A'..'Z'] + ['a'..'z'] )) then begin
  196.       gotoxy(18,1);
  197.       case CH of
  198.        't','T': begin write('New trigger value : '); readln(dly); end;
  199.        'e','E': begin write('New trigger edge(0 for falling,1 for rising) : '); 
  200.                 readln(i);
  201.                 trigger_edge := direction(i); end;
  202.        'o','O': begin write('New offset : '); readln(low_capture_bound);
  203.                 if (high_capture_bound - low_capture_bound < min_capture_band)
  204.                 then high_capture_bound := low_capture_bound + min_capture_band;
  205.                 end;
  206.        'c','C': begin write('New capture band : '); readln(i);
  207.                 if (i < min_capture_band) then
  208.                    high_capture_bound := low_capture_bound + min_capture_band
  209.                    else high_capture_bound := low_capture_bound + i;
  210.                 end;
  211.        's','S': begin write('New sample rate : '); readln(sample_rate); end;
  212.        'p','P': begin write('New pause rate : '); readln(pause_rate); end;
  213.       end;
  214.    CH := ' ';
  215.   end;
  216.   clrscr;
  217. end;
  218.  
  219. procedure pause_for_input;  { user can change parameters via menu here }
  220. begin
  221.   gotoxy(1,1);write(reverse_video,dim,'PAUSE',normal_video,bright);
  222.   for dlycntr := 1 to 20000 do if (keypressed) then read(KBD,CH);
  223.   if (CH <> #27) and (CH <> ' ') then menu;
  224.   gotoxy(1,1); write ('     ');
  225. end;
  226.  
  227. {******************** main ***********************}
  228. begin
  229.      port[A_CONTROL]:= MODE;   {initialize the pio}
  230.      port[A_CONTROL]:= INT;
  231.  
  232. terminal_customization;
  233. write(cursor_off);
  234. dly := 18; low_capture_bound := 2; high_capture_bound := 5;
  235. sample_rate := 1; pause_rate := 5; trigger_edge := RISING;
  236. clrscr;  CH:=' ';
  237. while(CH <> #27) do begin
  238.   for loopcntr := 1 to pause_rate do begin
  239.       trigger(trigger_edge, low_capture_bound, high_capture_bound);
  240.       get_samples(sample_rate); { point_buffer changed as a global here }
  241.       process_samples(point_buffer,pixel_buffer);
  242.       refresh_screen(pixel_buffer, old_pixel);
  243.   end;
  244.   pause_for_input;
  245. end;
  246.  
  247. write(cursor_on);
  248. end.
  249.  
  250.