Category : Files from Magazines
Archive   : ISSUE-34.ZIP
Filename : SCOPE.FIG
Output of file : SCOPE.FIG contained in archive : ISSUE-34.ZIP
(( This is Real World Figure 5 -- Oscilliscope Test Program ))
program test; {oscilliscope tester for Kaypro 2X. By Bruce Eckel 8/86}
const
A_CONTROL: byte = $22; {Control and Data I/O locations}
A_DATA: byte = $20; {for each of the Z80 PIO ports}
B_CONTROL: byte = $23;
B_DATA: byte = $21;
MODE : byte = $4f; {0100 1111 mode 1 = input}
INT : byte = $07; {0000 0111 interrupts disabled}
var
temp,val : byte;
function noise_test : boolean; {this keeps the screen from
flickering because of the noise in the bottom bit of the A/D
converter}
begin
if ( { part of what this function does is }
(temp <> val) { stall the program while the A/D }
and { converter catches up }
(temp <> (val+1)))
then noise_test := true else noise_test := false;
end;
begin
port[A_CONTROL]:= MODE; {initialize port A of the pio}
port[A_CONTROL]:= INT; { port B is done the same way }
ClrScr; write(#27,'C4'); { Turn kaypro cursor off }
{ Turbo's "port array" is used to write to the PIO. The first
one starts the A/D converter. Note that most of the programming
effort is just to make the screen output nice. The following
line is really all there is to running the A/D converter. }
val := port[A_DATA];
repeat begin
temp := port[A_DATA];
if noise_test then begin
val := temp;
GotoXY(30,10); clreol; write('binary ',val, ' ');
{ Note I take the value, divide it by the number of
steps, and multiply by the voltage range (my power
supply doesn't quite make it to 5.0). The ":4:3"
is formatting information for Turbo. Check the
results with your multimeter. }
write(((val/255) * 4.99 ):4:3, ' volts');
end;
end
until keypressed;
write(#27,'B4'); { Turn cursor back on }
end.
((*************************************************************))
(( This is Real World Figure 6 -- Oscilliscope Program -- A/D ))
program scope; { oscilliscope program for A/D example. By Bruce Eckel 8/86 }
type
direction = (FALLING, RISING); { trigger on rising or falling edge }
binary = (ON,OFF); { whether to turn a pixel on or off }
pixel_control = string[2]; { how to turn pixel on or off }
screen_buffer = array[0..159] of integer; { Kaypro screen is 160
pixels wide }
const
A_CONTROL: byte = $22; {Control and Data I/O locations}
A_DATA: byte = $20; {for the Z80 PIO port A }
MODE : byte = $4f; {0100 1111 mode 1 = input}
INT : byte = $07; {0000 0111 ints disabled}
min_capture_band : integer = 3; {minimum triggering search window}
var
CH : char; trigger_edge : direction;
low_capture_bound, high_capture_bound : integer;
sample_rate, pause_rate : integer;
point_buffer, pixel_buffer, old_pixel : screen_buffer;
loopcntr, dly, dlycntr : integer;
cursor_off, cursor_on : string[3];
pixel_off, pixel_on : pixel_control;
dim, bright, reverse_video, normal_video : string[3];
revdim,normal: string[6];
procedure terminal_customization; { should make it a little easier to}
begin { customize for other computers. }
cursor_off := #27 + 'C4';
cursor_on := #27 + 'B4';
pixel_off := #27 + ' ';
pixel_on := #27 + '*';
dim := #27 + 'B1'; { If you don't have these features, just }
bright := #27 + 'C1'; { set the strings to ''. }
reverse_video := #27 + 'B0';
normal_video := #27 + 'C0';
revdim := reverse_video + dim;
normal := normal_video + bright;
end;
procedure pixel(on_or_off:binary; vertical_coord, horizontal_coord : integer);
const
vertical_offset : integer = 131; { the kaypro's screen doesn't start
at 0,0}
horizontal_offset : integer =32; { these offsets start it in lower
left corner}
var pixel_char : pixel_control;
begin
if (on_or_off = ON) then pixel_char := pixel_on else
pixel_char := pixel_off ;
write(pixel_char, chr(vertical_offset - vertical_coord),
chr(horizontal_offset + horizontal_coord));
end;
procedure refresh_screen(var new_screen, old_screen : screen_buffer);
{ displays contents of point_buffer while erasing old trace on screen. }
var pixel_counter : integer;
begin
for pixel_counter := 0 to 159 do begin {Kaypro screen width again...}
pixel(OFF, old_screen[pixel_counter], pixel_counter);
pixel(ON, new_screen[pixel_counter], pixel_counter);
old_screen[pixel_counter] := new_screen[pixel_counter];
end;
end;
procedure ADC_delay (multiplier:integer); { Tried using assembly language
here, but the overhead of the INLINE statement overwhelmed my timing loop.
Adjust this until you get something from your A/D converter. }
var i,j: integer;
begin for i := 1 to multiplier do begin j :=0; j:= 1; j:=2; end; end;
procedure trigger(edge: direction; low_bound, high_bound : integer);
var presentval,lastval : integer; slope, edge_not : direction;
begin
edge_not := direction(ord(edge) xor 1); { invert edge }
slope := edge_not;
presentval := port[A_DATA];
while (slope = edge_not) do begin { wait for the right direction }
while (not ((presentval > low_bound) { ... and range of values }
and (presentval < high_bound))) do begin
ADC_delay(1);
presentval := port[A_DATA];
end;
lastval := presentval;
ADC_delay(1); presentval := port [A_DATA];
if (((edge = RISING) and ( presentval > lastval)) or
((edge = FALLING) and ( presentval < lastval)))
then slope := edge;
end;
delay(dly); { trigger delay in milliseconds }
end;
procedure get_samples(rate :integer);
{ tried passing the point_buffer array by variable, but it slowed things
down enough to make the data look bad }
var counter : integer;
begin
for counter := 0 to 159 do begin
point_buffer[counter] := port[A_DATA]; { point_buffer is global }
ADC_delay(rate);
end;
end;
procedure process_samples(var input_point, output_point : screen_buffer);
{ put samples in a form which can be displayed }
var index : integer;
begin
for index :=0 to 159 do {steps in A/D conv \/}
output_point[index] := (trunc ((input_point[index]/255)*99));
end; {vertical steps on screen /\}
procedure menu; { too many variables to bother passing -- all changed globally}
var i : integer;
begin
clrscr; gotoxy(1,3);
writeln(' ',revdim,'Digital Oscilliscope Options Menu:',normal);
writeln;
writeln(' t : change trigger delay. Current delay = ',
revdim,dly,normal,' mS');writeln;
write(' e : rising or falling trigger edge : ',revdim);
if trigger_edge = rising then writeln('RISING',normal)
else writeln('FALLING',normal); writeln;
writeln(' o : change trigger offset : ',revdim,low_capture_bound,normal);
writeln;
writeln(' c : change trigger capture band : ',revdim,
high_capture_bound - low_capture_bound, normal);
writeln;
writeln(' s : change sample rate. Current rate = ',
revdim,sample_rate,normal);writeln;
writeln(' p : change pause rate : ',revdim,pause_rate,normal);
writeln;
writeln('
writeln(' any other key returns to sampling');
while(not keypressed) do; read(kbd,ch);
if (CH in (['A'..'Z'] + ['a'..'z'] )) then begin
gotoxy(18,1);
case CH of
't','T': begin write('New trigger value : '); readln(dly); end;
'e','E': begin write('New trigger edge(0 for falling,1 for rising) : ');
readln(i);
trigger_edge := direction(i); end;
'o','O': begin write('New offset : '); readln(low_capture_bound);
if (high_capture_bound - low_capture_bound < min_capture_band)
then high_capture_bound := low_capture_bound + min_capture_band;
end;
'c','C': begin write('New capture band : '); readln(i);
if (i < min_capture_band) then
high_capture_bound := low_capture_bound + min_capture_band
else high_capture_bound := low_capture_bound + i;
end;
's','S': begin write('New sample rate : '); readln(sample_rate); end;
'p','P': begin write('New pause rate : '); readln(pause_rate); end;
end;
CH := ' ';
end;
clrscr;
end;
procedure pause_for_input; { user can change parameters via menu here }
begin
gotoxy(1,1);write(reverse_video,dim,'PAUSE',normal_video,bright);
for dlycntr := 1 to 20000 do if (keypressed) then read(KBD,CH);
if (CH <> #27) and (CH <> ' ') then menu;
gotoxy(1,1); write (' ');
end;
{******************** main ***********************}
begin
port[A_CONTROL]:= MODE; {initialize the pio}
port[A_CONTROL]:= INT;
terminal_customization;
write(cursor_off);
dly := 18; low_capture_bound := 2; high_capture_bound := 5;
sample_rate := 1; pause_rate := 5; trigger_edge := RISING;
clrscr; CH:=' ';
while(CH <> #27) do begin
for loopcntr := 1 to pause_rate do begin
trigger(trigger_edge, low_capture_bound, high_capture_bound);
get_samples(sample_rate); { point_buffer changed as a global here }
process_samples(point_buffer,pixel_buffer);
refresh_screen(pixel_buffer, old_pixel);
end;
pause_for_input;
end;
write(cursor_on);
end.
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/