Timer.Bas
Introduction:
Timer is a GWBasic program that deviates from most of the command line
programs that you will likely see.
While it is running, it responds to the FUNCTION KEYS and ignores the
keyboard, with the exception of the control C, control BREAK and BREAK
keys. The FUNCTION KEYS perform different things, when in the run mode
than it does in the immediate mode. The Fn keys respond differently in
the RUN mode than in the EDIT mode.
KEY n,function
executes
durning the EDIT mode and are shown when KEY ON is in effect.
ON KEY (n) GOSUB
executes durning the RUN mode
after the KEY(n) ON
statement is declared.
Our program executes a GOTO
self where it will continue to spin untile
a FUNCTION KEY is closed.
This is quite nice; however, it can be a bear
for troubleshooting because a typical error mode is for the program to
lock up....Very irritating.
This program demonstrates HARD IO,
or writing directly to a peripheral
device by using the INP and OUT statements. Be careful whild using this
method, because unpredictable commands to a perif can really upset the
system. For example, the mother board has three timers can can be
rattled, but don't mess with the first two.
Timer 0 controls the real time clock and the incorrect count-down will
cause the clock to run at the wrong rate.
Timer 1 determines the refresh rate and if it is wrong, the
computer memory will become forgetful and crash.
Timer 2 (the third one) can be connected to the internal speaker to
generate a sound. We will use this one.
The function keys permit loading the timer with a desired frequency,
turning the speaker on and off directly with hard IO using the INP and
OUT statements. They are
also used to RUN the
program and terminate it.
To learn more about the neat thingys the timer can do, do a web search
for the specifications of the 8253 Timer.
What it does:
Run the program as with any other GWBasic program. On initalization, a
menu of the four FUNCTION KEY
events are displayed. Then the operator
is invited to Enter an audio frequency. The program then patiently
awaits a FUNCTION KEY
closure to perform any one of these four events.
F1 toggles between program start and program stop. If stopped it will
start. If running then it will stop.
F2 displays the Banner again and prompts for an input frequency,
followed by a return.
F3 turns the speaker on.
F4 turns the speaker off.
This is all this program does. The next section talks about how GWBasic
does it.
How to RUN it:
Start the program as you would start any other GWBasic program.
Enter some frequency to be sounded.
Close Key 3 to turn the sound on.
Close Key 4 to turn the sound off.
Close Key 2 to change the frequency.
Close key 3 to turn it on again
Close key 1 to stop the program......
Now you did it. The program is terminated and the sound is
beeping merrily... and you can't turn it off with the
FUNCTION KEY because the program isn't running.
Close Key 1 again to restart the program,
Close Key 4 to stop the music.
Exit the program again with another Key 1 closure.
Now wasn't that fun?
How it does it:
This program uses the FUNCTION KEYs
in both the RUN and the IMMEDIATE
mode of operation. This causes this program to resemble OOPS
programming that is used extensively in Window's programs. The
program
waits for an event by the operator to perform a function. The computer
may be used for other jobs during the wait time.
Interupt driven programs are valuable when a program must detect an
event. The program may be doing other things during this wait, as would
be the case if the program had to continuously poll the computer status
until some trigger event occured. In our program, the only activity we
do during that wait is to loop on self at LINE 780. However, other
activities could be programmed during this time and will honor the
FUNCTION KEY capture
whenever it happens. This simple program is
designed to demonstrate the programming philosophy.
Provide initial documentation and
then vectors off to the program
start.
10
'
Prog
timer
20 '
30 '
40 '
50 '
60 '
70 '
80 '
90 '
100 GOTO 650 '_____Branch to Program Start_____
Although un-necessary in this
program, it is good practice to code all
the sub-routines early on in the program. This permits the program to
be less time bound. Each time a sub routine is called, the interpreter
must search the code line by line until the sub routine is located.
This search can be minimized if the time sensitive programs are early
in the program. The four sub routines perform the functions described
in the Banner Menu.
110 '
120 '
Simply post intent and exit the
RUN mode into the IMMEDIATE mode.
Perhaps emptying the Type-ahead
Buffer with INKEY$ commands might be
added to swallow any characters typed during the RUN mode. These
keystrokes will be executed on entry into the IMMEDIATE mode if present.
130 PRINT "program terminate": END ' key 1 capture
140 '
150 '
The FUNCTION KEY events are
displayed as part of the program BANNER.
160 ' Banner and select frequency ' key 2 capture
170 CLS:
180 PRINT " Hard I/O to Timer 2"
190 PRINT " F1 Toggles between program RUN and program END"
200 PRINT " F2 Input and load the timer frequency"
210 PRINT " F3 Speaker on"
220 PRINT " F4 Speaker off"
230 '
A prompt to input an audio
frequency halts the program until RETURN
(ENTER) is typed.
Any invalid number entered will
result in a re-prompt.
240 LOCATE 7,1: PRINT SPC(70): LOCATE 7,1
250 INPUT "Enter a frequency 19 to 119380 HZ ",F$
260 F= INT(ABS(VAL(F$))): IF F<19 OR F> 1193180! THEN 910
270 '
The timer clock frequency of
1.193180 HZ is devided by the selected
frequency to obtain the down-count required for the counter to generate
the selected audio frequency. The value is integerized witn the INT
statement to illiminate any fractional component.
280 C= INT(1193180!/F)
The high 256 squared byte value is
stored in register HIX for loading
into the timer.
290 HIX= INT(C/256)
The high byte value is subtracted
from the timer frequency to obtain
the low 256 raised to the one, value.
300 LOX= C-(256*HIX)
310 '
The results of the calculations
are posted and the program returns to
wait for another FUNCTION KEY closure.
320 LOCATE 7,1: PRINT SPC(70): LOCATE 7,1
330 PRINT "Frequency=";F; " ";
340 PRINT "Timer Counter=";C;" ";
350 PRINT "hi byte=";HEX$(HIX);" ";
360 PRINT "lo byte=";HEX$(LOX);" "
370 RETURN
380 '
390 '
400 '
The load instruction prepares the
timer to receive two bytes, the low
byte and high byte for the count.
Then the low byte is and then the
high byte are loaded into the timer.
Notice the enable is at port
address 43 HEX and both bytes are loaded
into location 42 HEX
410 ' Load coutdown to timer 02 '
key 3
capture
420 OUT &H43,&HB6 ' input enable
430 OUT &H42,LOX ' low byte
440 OUT &H42,HIX ' high byte
450 '
460 '
470 '
The value in the PIA is read, the
two least significant bits are forced
to 11 and written back out to the PIA.
The 11 (binary) in the lsb
connects the timer output to the speaker.
480 ' Turn Speaker on
490 N= INP(&H61)
500 N= N OR 3 ' binary 0000 0011
510 OUT &H61, N
520 RETURN
530 '
540 '
The existing value in the PIA has
its two least significant bits set to
00, disconnecting the Speaker from the Timer.
550 ' Turn Speaker
off
'
key 4 capture
560 N= INP(&H61)
570 N= N AND 252 ' binary 1111 1100
580 OUT &H61,N
590 RETURN
600 '
610 '
620 '
630 '
640 '
Program environmental
initalization followed by a single one line loop
that waits for orders.......
650 ' ______ Program Start ______
Turn off the Immediate Mode
FUNCTION KEY menu at the bottom of the
monitor view-port.
660 KEY OFF
Define a low byte in LOX and high
byte in HIX to be loaded into the
timer on startup.
(this step is
un-necessary unless you later decide
to load and sound a tone on start up)
670 LOX= 54: HIX= 124
KEY(1) is programmed to RUN if
used in the IMMEDIATE mode.
680 KEY 1,"run"+CHR$(13)
690 KEY 3,""
700 KEY 4,""
ON KEY(1) through ON KEY(4) are
programmed to vector the their
respective sub-routines.
Key(1) ON throuth KEY(4) ON enable
the FUNCTION KEYs to execute during
the RUN mode.
710 ON KEY(1) GOSUB 130: KEY(1) ON
720 ON KEY(2) GOSUB 830: KEY(2) ON
730 ON KEY(3) GOSUB 410: KEY(3) ON
740 ON KEY(4) GOSUB 550: KEY(4) ON
The BANNER sub routine is called to permit the operator to INPUT an
audio frequency
and load the TIMER count-down register.
750 GOSUB 160 ' Banner and frequency select
760 '
Post that the program will halt
and wait for a FUNCTION KEY closure.
Then it will loop on self in line
770, keeping the program executing.
770 PRINT
"
waiting for function key closure"
780 GOTO 780
790 '
800 '
810 '
820 '
830 '
840 '
This is a handy way to
periodically save this program during editing,
for back-up purposes.
850 '
______________________________________
860 END ' Back-up work
870 PRINT "Backing up program": SAVE "timer",A
880 '______________ program end ___________________
Just a note on notes:
( Cute Pun on notes....;-)
If you are interested in the frequencies of the musical notes, this
might help.
440 HZ is the note A below middle C. The frequencies of the notes above
this number can be calculated by multiplying successive notes
re-cursively to get their frequency. Multiply each successive note by
the twelvth root of two to get the next note. For example 440 times the
2^(1/2) ... twelvth root of two... yields Bb. Do the same thing to the
frequency of Bb to get B, and so on. Notice that the exponents add
during multiplication, so multiplying a number times the twelvth root
of two, twelve times will eventually double that number. One octave.
This simple one liner with print out an octave beginning with A below
middle C.
A= 440: PRINT A: FOR N= 1 to 12: A= A^(
1/12 ): PRINT A: NEXT N
This one goes down an octave, using minus one twelvth for an exponent
because the exponents subtract.
A= 440: PRINT A: FOR N= 1 to 12: A= A^(
-1/12 ): PRINT A: NEXT N
_________________________________________________