home *** CD-ROM | disk | FTP | other *** search
-
- (( 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(' <ESC> : quit');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.
-