Re: Hello - and where to begin?
Nick Maroudas <[email protected]> Mon, 10 Mar 2008 10:58:47 +0200
| Newsgroups | gmane.comp.lang.forth.colorforth |
|---|---|
| Message-ID | <[email protected]> |
Quoting "Ray St. Marie" <[email protected]>: > On Sun, Mar 9, 2008 at 1:14 AM, Ray St. Marie > <[email protected]> wrote: > > I'd like to learn to use the system timer and if > anyone would care to > enlighten me... please? > > Ray > Nick here: Dear Ray, Thanks for your interest, below are further details; rather long, but might be suitable for one of John Drake's tutorials. Caritas, NickM *************************** Timing and Music - Tutorial Howerd Oakford's CFDOS4 has three blocks which illustrate the use of PC timers. You can make a boot floppy from DOS by following the instructions on Howerd's website; or just copy his bootable image cfdos4.blk with Linux, dd if=cfdos4.blk of=/dev/fd0 The PC has 3 timers. The newest and fastest is the 64 bit RDTSC (Time Stamp Counter) which ticks at CPU rate, ns, and loads the time, in clock ticks, onto EAX lo & EDX hi. CF has a macro word "time" which calls RDTSC, with lo 32 bits on stack, EAX. The first thing Howerd does is to bring this macro word "time" into his forth dictionary, block 20, forth : time time ; --u I find it useful to stack the higher 32 bits as well. This can be called by the the forth word "a", which stacks EDX. So my version of "time" is "clk", ( still in forth) : clk time a ; --ulo uhi Block 28 uses the fast 64 bit PC timer to make delays in msec "ms" and "secs". Howard uses the PC's second timer for calibration. Real Time Clock (RTC) at port 70h, ticks hi and lo every second. Howerd defines a variable "khz" to store the number of PC CPU ticks in one sec, divided by 1000 to bring it to ms. (I find "1ms" a useful memnonic for "khz"). The word "cal" ought to put your CPU's clock rate into the variable "khz". : cal hi lo time invert ( howerd's word to change sign) hi lo time + ( time diff, no of clks in 1 sec) 1000 / khz ! ; ( ditto, in 1 msec) But if the CPU is faster than 1GHz, a one sec calibration period will be too long, because the lower 32 bit register of the RDTS counter will overflow. Hence I call the higher 32 bit register as well, and scale the 2 numbers appropriately before adding them to make a 32 bit time scale. : clk time 10 shr a 31 and 22 shl + ; --u ( hi+lo, scaled) : cal clk invert clk + 1000 / khz ! ; Having calibrated his time interval (for length of a note) Howerd then uses the PC's 3rd timer to set the frequency. The Programmable Interrupt Timers (PIT) tick microsec. See Mark Feldman's tutorial "Controlling the PC speaker" on the popular Australian website, "JollySWAGman" http://www.bsdg.org/SWAG/SOUND/0107.PAS.html The PC speaker is tied to the NMI status port 61h. There are caveats about writing to some other bits (see Intel doc ICH7) but, essentially, bit 0 will activate the speaker and bit 1 will tie it to the pulses from PIT 2. This timer is selected by writing a byte to port 43, and its oscillatory half-period is entered as hibyte lobyte-- to port 42h. Therefor Howerd introduces the macro word "swapbytes" and defines a forth word to "split" 16bits into 2 bytes, before moving on to make music. Block 68 is straightforward, and rather neat. It save a bit of repetitive naming by use of the CF facility where one word can elide into its successor if its ";" is omited. : tn ( this is the note length t, scaled to msec) : hz ( this is the PIT rate 1,193,000 ticks per sec, divided by the freq in Hz - actually, this is the pulse period) : tone ( the period is split and written to PIT2, which sets up oscillation freq; PIT2 output is tied to speaker by writing a 3 to port 61, then it is untied - after t msec - by replacing the 3 with a 1; this silences the tone, plus 20 ms delay before next tone) ; *************************