packages feed

language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/tests/delaytes.mod

MODULE DelayTest;

	(********************************************************)
	(*							*)
	(*	Test of how well we can read back the count	*)
	(*	of the timer that normally drives the speaker.	*)
	(*							*)
	(*	This program doesn't produce any output, I	*)
	(*	rely on the debugger to look at the results.	*)
	(*							*)
	(*	Programmer:	P. Moylan			*)
	(*	Last edited:	5 March 1995			*)
	(*	Status:		Working				*)
	(*							*)
	(********************************************************)

FROM SYSTEM IMPORT
    (* proc *)	BYTE, ADR;

FROM LowLevel IMPORT
    (* proc *)	InByte, OutByte, LowByte, HighByte, MakeWord, IANDB, IORB;

(************************************************************************)

VAR
    Sample: ARRAY [0..1000] OF BYTE;

(************************************************************************)

PROCEDURE SpeakerOff;

    (* Turns off both the timer gate and the speaker.	*)

    BEGIN
	OutByte (97, IANDB(InByte (97), 0FCH));
    END SpeakerOff;

(************************************************************************)

PROCEDURE SpeakerOn;

    (* Turns on the speaker and enables the timer gate.	*)

    BEGIN
	OutByte (97, IORB(InByte (97), 3));
    END SpeakerOn;

(************************************************************************)

PROCEDURE EnableTimerGate;

    (* Enables the timer gate without turning on the speaker.	*)

    BEGIN
	OutByte (97, IORB(IANDB(InByte (97), 0FCH), 1));
    END EnableTimerGate;

(************************************************************************)

PROCEDURE RunTheTest;

    CONST TimerControlPort = 67;  channel2 = 66;

    VAR j: CARDINAL;  CycleCount: BYTE;

    BEGIN
	CycleCount := 64;

	(*SpeakerOn;*)	(* As a check that the count's not too high	*)
	EnableTimerGate;

	(* The control byte sent to the timer control port specifies:	*)
	(* timer #2, one count bytes to follow, and mode 2.  CycleCount	*)
	(* specifies the frequency, via the formula			*)
	(* freq = 1193180/CycleCount.  This gives a frequency range of	*)
	(* 18.2 Hz (count=65535) to 1.193 MHz.				*)
	(* The bit assignments in the control byte are as follows:	*)
	(*	7-6	timer # (0, 1, or 2) (3 is for readback)	*)
	(*	5-4	00=different command, 01=low count byte to	*)
	(*		follow, 10=high count byte to follow, 11=two	*)
	(*		count bytes to follow (low order first)		*)
	(*	3-1	mode						*)
	(*	0	0=binary, 1=BCD					*)
	(* The results for different modes are:				*)
	(*	0,1	counts down to 0, then continues counting	*)
	(*		down from 65535					*)
	(*	2	counts down to 0, then restarts cycle with	*)
	(*		original count.					*)
	(*	3	(square wave) counts down to zero by twos,	*)
	(*		flips output and counts down to zero again,	*)
	(*		then restarts the cycle with original count.	*)
	(*	4	much the same as mode 1.  The difference is	*)
	(*		in hardware triggering, but for our present	*)
	(*		purposes that difference is irrelevant.		*)
	(*	5	counts down from some random number, ignores	*)
	(*		initial count.  I guess this is waiting for	*)
	(*		an external trigger.				*)
	(*	6	same as mode 2.					*)
	(*	7	same as mode 3.					*)

	OutByte (TimerControlPort, 094H);
	OutByte (channel2, CycleCount);

	(* Now read back the count, as fast as we can go. *)

	FOR j := 0 TO HIGH(Sample) DO

	    (* The "counter latch" command, to take a copy of the	*)
	    (* current count in timer #2, would be an 80H sent to the	*)
	    (* control port.  Since the count is always a one-byte	*)
	    (* quantity in our tests, we can save some time by skipping	*)
	    (* the "latch" step.					*)

	    (*OutByte (TimerControlPort, 80H);*)
	    Sample[j] := InByte (channel2);

	END (*FOR*);

	(* Result of test (obtained by looking with VID): on my DX/2	*)
	(* and using mode 3, each sample differed by 14, i.e. the	*)
	(* count changed by 14 in the time it took to get around the	*)
	(* loop.  The jitter was about plus or minus 2.			*)
	(* Removing run-time checks had negligible effect.		*)
	(* Going to mode 2, using a one-byte counter, and setting all	*)
	(* options to "fastest possible" got me to the point where	*)
	(* the decrement was usually 2 and sometimes 3.  I don't think	*)
	(* I can go any faster except by going to assembly language	*)
	(* - and even then it won't be very much faster.		*)
	(* Somewhat surprisingly, turning turbo mode off doesn't seem	*)
	(* to affect the results very much - I don't understand this.	*)

    END RunTheTest;

(************************************************************************)
(*			MODULE INITIALISATION				*)
(************************************************************************)

BEGIN
    RunTheTest;
    SpeakerOff;
END DelayTest.