Cable Column

WOOD AND WIND COMPUTING
Bill Cable : RR 2 Box 92 : Cornish, NH 03745 : 603 675 2218

This issue of UPDATE initiates me as the QL Editor. I am happy to assist Bill Jones in producing this magazine so important to North American QL users. Late summer is a very busy time for me. Have to prepare for winter. I hope to be able to put more time into the job in the next issue. It is important that we get maximum participation from the QL base we have. We have QL users at all levels of expertise and with many different configurations of equipment. As editor I want to provide something for everyone and a lot for most. My background is mostly with computer software and even then there is a lot I don’t know. I hope I will get help, advice, criticism from readers. I would like programs to print for readers to type in. I would also like to print reviews of hardware and software. And tips about perks and quirks of the QL. Also I need to know what readers want to see. One quality of UPDATE that I like is its friendly non pretentious flavor. We all have a lot to learn about using our QLs more effectively and UPDATE is a forum for doing it.

The first computer I ever owned was a QL that I bought in 1986. So I am relatively new to personal computing and Sinclair computers. I have a degree in mathematics (1967, University of Florida). That was before computer courses were offered on campus. But my various jobs led me into computer programming. Mostly in FORTRAN on DEC machines but also in BASIC at Dartmouth College (the birthplace of BASIC). I got burned out programming for others by 1980 and started a cabinetry shop. But I wanted to get back into computing for myself on a part time basis and started looking around for a computer. Having limited resources I was attracted to the QL. It was selling for $150 when I bought my first one. I was quite impressed. I felt like I had almost as much power as I did on the large computers I used to work on and a much nicer language and operating system to work with. The PSION programs that came with it were very good also. Being so close to A+ (source of all US QLs) I became a dealer and sold QL’s locally and worked with several businesses writing custom ARCHIVE programs for them. Then I started selling my software nationally on my own, through Peter Hale‘s EMSOFT, and finally as issue disks for UPDATE.

Writing software takes an enormous investment in time up front. You have to have it before you can sell it. Writing major pieces of software for the North American QL market stands little chance of much financial success and so has to be done during spare time. Active QL users probably number less than 2000. That is a pretty small number to write software for. I would like to make a request to all QL users for all of us writing software for North America (Peter Hale, Bob Hartung, Al Feng, David McCall, myself, and others). Please consider our software. Get a catalog from EMSOFT and check out the advertisements and issue disks descriptions in UPDATE. See what we have to offer. We are trying to provide a service to QL users. We have the ability to write software as good as any coming from overseas. We all do this on the side but could put more energy into it if we had more financial success. You have one great advantage in dealing with us. We can be contacted by mail or phone about our software and can respond to your specific problems. We not only sell programs but are interested in helping all QL owners get the most from their computers. And we are definitely doing it out of love for the QL and not for the money.

BOOTING UP : Programs to help

In the description below I will use ‘mdv1_’ in the description. Those with floppy drives can subetitute ‘flp1_’. Each time we turn on our QL or reset it we have a chance to boot up. Load a program from mdv1_ called ‘boot’ which gets things going. So a boot program is a SUPERBASIC program named ‘boot’ that automatically starts a more complex (usually executable machine code) program(s). All we have to do is press <F1> or type ‘lrun mdv1_boot<ENTER>. The PSION programs (QUILL,ARCHIVE, ABACUS,EASEL) have boot programs like this. The real PSION machine code programs are called qlwp, qldb, qlss,qlbg and each cartridge has a boot program which starts execution of the machine code. Often it would be more convenient if we did a few things : set time/date, activate a toolkit, load speedscreen, etc before starting the program. Everyone should make sure the time/date is correct at boot up. It is irritating to start a program that makes use of the time/date only to find that it is wrong and we can’t set it from within the program. Toolkits and disk interfaces often time/date stamp files when saved. This can sometimes be very important in identifying a file. The TRUMPCARD/TK2 Toolkit has print buffering, ‘hot key’ screen dump, and ‘hot key’ macro capability plus much more. We should set these features on boot up. Many of you may wonder what are these toolkits everyone talks about. They are extensions to SUPERBASIC and QDOS that give new useful commands or make corrections to ROM bugs. They may be on ROM or in the disk interface, or loaded into RAM at start up. It usually takes some action on our part to activate them. Usually the best time to do that is at boot up time. Depending what program(s) we will be running we will want various toolkit features initialized. It usually makes sense to reboot upon quitting a program unless multitasking or saving files in RAM disk. The system is ‘clean’ after a reboot.

The programs described below should be helpful to all configurations of QLs. You incorporate them on the microdrive of the program you want to boot up on. Each of the PSION microdrives for instance. The current boot program on your microdrive must be renamed with a name of your choice (or copied to new name then ‘boot’ deleted). The 3 programs described below then need to be copied over. They will help you easily set the time/date and activate your toolkit if your have one. In this instance I used some of the features of my TRUMP CARD/TK2 system and microdrive version of speedscreen to illustrate a QUILL application. If you have a different toolkit, no toolkit, no cartridge speedscreen, or a different program to set up for you can adapt the initializing portion of the boot program (lines 1170 to 1390) to your needs.

I tried to make a boot up system that can be easily adapted to each boot up situation. It consists of 3 programs plus your own boot program which is renamed. They are :

1.  boot               initializes tool kit, verifies date, merges
                       last_date and date_set if needed, starts old
                       boot program which has been renamed.

2.  boot_date_set      prompts, sets, saves time/date

3.  boot_last_date     stores last time/date setting

4.  (your old boot)    starts up your program as it use to. Just
                       renamed. On your QUILL cartridge (disk) you
                       could rename boot to boot_quill.

This boot system has the following features :

1. Quick loading. That is why boot_date_set is only merged if needed.
2. Single key presses for quick entry.
2. Initialize (activate toolkit features, speedscreen)only if desired.
3. Force time/date set if out of range (as when first powered up).
4. Verify time/date if within range (as after a reset).
5. Use standard time (am/pm) instead of military time in displays.
6. Loads and runs a preset program (your original boot program).

From SUPERBASIC type in the programs as listed. Save each one when finished by its name. The line numbers of boot and boot_date_set should not overlap because they are sometimes merged. You need to have a full screen for window #2 for program entry. ‘window #2,512,206,0,0 : cls #2<ENTER>’ will take care of that. If you don’t have a toolkit the best way to start is ‘auto 1000<ENTER>’. With TK2 typing ‘ed 1000<ENTER>’ gets you going.

After the 3 programs are typed in and saved you can pick a program to use it on. QUILL is what this particular code is set up for. Take your copy of QUILL (not the original) and put it in mdv1_. Have the cartridge of the boot programs you just entered in mdv2_. Now :

copy mdv1_boot to mdv1_boot_quill<ENTER>          (rename boot)
delete mdv1_boot<ENTER> (delete old copy)
copy mdv2_boot to mdv1_boot<ENTER>
copy mdv2_boot_date_set to mdv1_boot_date_set<ENTER>
copy mdv2_boot_last_date to mdv1_boot_last_date<ENTER>

Now you are all set. Pull the cartidges out reset. Put the modified QUILL in mdv1_ and press <F1>. If you find there is not enough room on the cartridge you can delete CLONE, INSTALL_BAS, CONFIG_BAS on your PSION copy.

If you are using a different program besides QUILL then substitute its name for QUILL and changes line 1040 of boot to reflect that change.

BOOT – program 1

1000 REMark                    BOOT                       B Cable     9/89
1010 REMark boot program : initialize tool kit, check/set date, start program
1020 :
1030 LET boot_dev$ = "mdv1_" : REMark boot device
1040 LET to_run$ = "boot_quill" : REMark program to run after initializing
1050 LET sys_id$="MY SYSTEM" : REMark your identification for the screen
1060 :
1070 LET year = 1989 : LET month = 12 : LET day = 20 : REMark default time/date
1080 LET hour = 16 : LET minute = 30 : LET second = 0
1090 :
1100 LET l=7.889221E8 : REMark 1986 - The lower limit for good date
1110 LET u=1.104368E9 : REMark 1999 - The upper limit for good date
1120 :
1130 OPEN #1,con_512x206a0x0 : OPEN #2,con_512x206a0x0 : CLS #0
1140 REMark querry for initialization
1150 head sys_id$ : CSIZE 0,0 : AT 2,55 : PRINT "for : ";to_run$
1160 AT 3,55 : PRINT "On : ";boot_dev$ : CSIZE 2,1
1170 AT 7,0: CLS 4: PRINT "Initialize [y/n] : "; : PAPER 7 : INK 0 : PRINT " ";
1180 LET a$ = INKEY$(-1) : PRINT a$!; : PAPER 0 : INK 7 : CLS 3 : CSIZE 0,0
1190 IF a$=="y"
1200 REMark tk2_ext initialization
1210 AT 10,31 : PRINT "-Initialization-"
1220 AT 13,31 : PRINT "Activating TK2_EXT" : TK2_EXT
1230 REMark screen dump with <ALT>d key press
1240 AT 14,26 : PRINT "Setting up <ALT>d screen dump"
1250 SDP_SET 1,1,0,0: SDP_KEY d
1260 REMark print buffer
1270 AT 15,29 : PRINT "Setting up print buffer" : PRT_USE ser,ser
1280 REMark some altkey (hot keys for quill)
1290 AT 16,10
1300 PRINT "QUILL HOT KEYS : <ALT>p - prints, <ALT>t - top, <ALT>b - bottom"
1310 ALTKEY 'p',CHR$(240)&CHR$(112)&CHR$(10)&CHR$(10)&CHR$(10)
1320 ALTKEY 't',CHR$(240)&"G"&"T"
1330 ALTKEY 'b',CHR$(240)&'G'&'B'
1340 PAUSE 200
1350 REMark Speedscreen initialization
1360 AT 17,31 : PRINT "loading speedscreen ..."
1370 LET x = RESPR(11240)
1380 LBYTES boot_dev$&"speedscreen_code",x
1390 CALL x
1400 END IF
1410 REMark if date within limits verify
1420 LET a$ = "y" :
1430 IF DATE>l AND DATE<u
1440 head "VERIFYING TIME AND DATE"
1450 LET d$=DATE$ : LET d = d$(13 TO 14) : LET p$ = " am"
1460 IF d>11 : LET p$ = " pm" : IF d>12 : LET d = d-12 : END IF : END IF
1470 AT 4,5 : PRINT d$(6 TO 11)!!d$(1 TO 4);!!!DAY$!!!d;d$(15 TO);p$
1480 PRINT "Change time/date [y/n] : "; : PAPER 7 : INK 0 : PRINT " ";
1490 LET a$ = INKEY$(-1) : PRINT a$!; : PAPER 0 : INK 7 : CLS 3 : CSIZE 0,0
1500 END IF
1510 REMark merge last date, time/date setter if needed
1520 IF a$ = "y"
1530 AT 17,1: PRINT "Getting last date. If you get a 'not found' error type :"
1540 AT 18,1 : PRINT TO 25;"lrun ";boot_dev$;"boot_date_set<ENTER>"
1550 MERGE boot_dev$&"boot_last_date" : last_date : REMark get last date
1560 AT 17,1 : CLS 4 : CLS 2 : PRINT "merging "&boot_dev$&"boot_date_set ..."
1570 MERGE boot_dev$&"boot_date_set" : REMark merge date setting procedures
1580 date_set
1590 END IF
1600 REMark start program if any
1610 head "STARTING A PROGRAM" : CSIZE 0,0
1620 AT 10,1: PRINT "ENTER device_program to start [<ENTER> = ";to_run$;"] :";
1630 INPUT i$ : IF i$ = "" : LET i$ = boot_dev$&to_run$ : END IF : CLS : INK 5
1640 AT 6,1 : IF i$ = "" : PRINT "Done" : ELSE : PRINT "lrun ";i$ : END IF
1650 IF i$<>"" : LRUN i$ : END IF : STOP
1660 :
1670 DEFine PROCedure head(h$)
1680 CLS #1 : CSIZE 2,1 : PAPER 7 : INK 0 : AT 0,0 : CLS 4
1690 AT 0,20-LEN(h$)/2 : PRINT h$ : PAPER 0 : INK 7
1700 END DEFine head$

BOOT_DATE_SET – program 2

5000 REMark                 BOOT_DATE_SET                  B Cable     9/89
5010 REMark Time/date setting procedures to be merged into boot program or
5020 REMark will run as a stand alone program
5030 :
5040 LET boot_dev$ = "mdv1_" : REMark The boot device
5050 LET year = 1989 : LET month = 9 : LET day = 20
5060 LET hour = 18 : LET minute = 30 : LET second = 0
5070 :
5080 OPEN #1,con_512x206a0x0 : OPEN #2,con_512x206a0x0
5090 :
5100 date_set : CLS
5110 :
5120 REMark prompt for all time/date fields
5130 DEFine PROCedure date_set
5140 LET what = 0 : LET second = 0 : CLS #0 : CLS : CSIZE 0,0
5150 AT 15,20 : PRINT " or ? single value, < or = move to min and max"
5160 AT 16,20 : PRINT "<space bar> toggles to next time/date field"
5170 AT 17,20 : PRINT "1 or 2 digit number also works with auto toggle"
5180 AT 18,20 : PRINT "<ENTER> when time and date are correct"
5190 AT 6,15 : PRINT "Date";TO 40;"Day";TO 59;"Time"
5200 AT 0,20 : CSIZE 2,1 : PRINT "SETTING DATE AND TIME"
5210 REPeat prompt_loop
5220 setter minute,31,0,59
5230 setter hour,28,0,23
5240 setter day,14,1,31
5250 setter month,10,1,12
5260 setter year,7,1962,1999
5270 setter second,34,0,59
5280 IF what = 10 : EXIT prompt_loop : END IF
5290 END REPeat prompt_loop
5300 CSIZE 0,0 : date_save
5310 END DEFine date_set
5320 :
5330 REMark actual time/date prompter
5340 DEFine PROCedure setter(value,col,min,max)
5350 IF what = 10 : RETurn : END IF : REMark <RETURN> key means no more
5360 REPeat setter_loop
5370 SDATE year,month,day,hour,minute,second
5380 display_date : CSIZE 2,1 : AT 5,col : PRINT ""
5390 LET what = CODE(INKEY$(-1))
5400 IF what=208: LET value=value+1: END IF : REMark up arrow
5410 IF what=216: LET value=value-1: END IF : REMark down arrow
5420 IF what=192: LET value=min: END IF : REMark left arrow
5430 IF what=200: LET value=max: END IF : REMark right arrow
5440 REMark see if numeric entry
5450 IF what>47 AND what<58
5460 LET what=what-48
5470 LET what2=CODE(INKEY$(100)) : REMark wait a little for 2nd digit
5480 IF what2 = 0
5490 LET value=what : REMark no 2nd digit
5500 IF max = 23 AND p$ = " pm" : LET value = value + 12 : END IF
5510 IF min = 1962 : LET value = value + 1990 : END IF
5520 LET what = 32 : REMark advance to next time/date field
5530 ELSE
5540 IF what2>47 AND what2<58 : REMark check for 2nd digit
5550 LET what2 = what2 - 48
5560 LET value = 10*what + what2
5570 IF max = 23 AND p$ = " pm" : LET value = value + 12 : END IF
5580 IF min = 1962 : LET value = 1900 + value : END IF
5600 END IF
5610 END IF
5620 END IF
5630 IF value>max: LET value=max: END IF : REMark check if too large
5640 IF value<min: LET value=min: END IF : REMark check if too small
5650 : REMark <space> or <RETURN>
5660 IF what = 10 OR what = 32
5670 AT 5,col : PRINT " " : RETurn
5680 END IF
5690 END REPeat setter_loop
5700 END DEFine setter
5710 :
5720 REMark saves new date parameters
5730 DEFine PROCedure date_save
5740 AT 14,0 : CLS 2 : AT 18,1 : PRINT "saving new date ..."
5750 DELETE boot_dev$&"boot_last_date" : REMark delete old file
5760 OPEN_NEW #3,boot_dev$&"boot_last_date" : REMark open new file
5770 PRINT #3,"9000 DEFINE PROCedure last_date" : REMark write procedure
5780 PRINT #3,"9010 let year=";year;":let month=";month;":let day=";day
5790 PRINT #3,"9020 let hour=";hour;":let minute=";minute;":let second=";0
5800 PRINT #3,"9030 sdate year,month,day,hour,minute,second"
5810 PRINT #3,"9040 END DEFine last_date"
5820 CLOSE #3
5830 END DEFine save_date
5840 : REMark display time/date cleary in am/pm
5850 DEFine PROCedure display_date
5860 CSIZE 2,1 : LET d$ = DATE$ : LET t$ = d$(13 TO) : LET d$ = d$(1 TO 12)
5870 LET t = t$(1 TO 2): LET p$ = " am": IF t > 11: LET p$ = " pm" : END IF
5880 IF t > 11
5890 LET p$ = " pm" : IF t > 12 : LET t$ = (t-12)&t$(3 TO) : END IF
5900 IF LEN(t$)<8 : LET t$ = " "&t$
5910 END IF
5920 IF t$(1)="0" : LET t$ = " "&t$(2 TO) : END IF
5930 AT 4,19 : PRINT DAY$ : AT 4,4 : PRINT d$; : AT 4,27 : PRINT t$;p$
5940 CSIZE 0,0
5950 END DEFine display_date
5960 : REMark makes centered screen headings
5970 DEFine PROCedure heading(head$)
5980 CLS #0 : CLS #1 : CSIZE 2,1 : PAPER 7 : INK 0 : AT 0,0 : CLS 4
5990 AT 0,20-LEN(head$)/2 : PRINT head$ : CSIZE 0,0 : PAPER 0 : INK 7
6000 END DEFine heading
6010 : REMark prompts until y(Y) or n(N) typed
6020 DEFine FuNction yorn(l,q$)
6030 REPeat loop
6040 AT 1,0 : CLS 4 : PRINT q$;" [y/n] : "; : PAPER 7 : INK 0 : PRINT " ";
6050 LET a$ = INKEY$(-1) : PRINT a$!; : PAPER 0 : INK 7 : CLS 3
6060 IF a$=="y" : RETurn 1 : END IF
6070 IF a$=="n" : RETurn 0 : END IF
6080 END REPeat loop
6090 END DEFine yorn$

BOOT_LAST_DATE – program 3

9000 DEFine PROCedure last_date
9010 LET year=1989:LET month=9:LET day=24
9020 LET hour=6:LET minute=46:LET second=0
9030 SDATE year,month,day,hour,minute,second
9040 END DEFine last_date

Comments on programs :

BOOT is pretty straight forward. Lines 1030 and 1040 should make sense for your device and new boot program name. Lines 1170 to 1390 need to also apply to your system tool kit and desires. Remove and alter as desired. You can always skip that section by answering ‘n’ to the initialize question. At line 1420 the system clock function DATE returns the date in seconds which is compared to the lower and upper bounds set at lines 1100,1110. If the date is not sensible the BOOT_SET_DATE routine is merged. Otherwise you are asked whether the date is correct. After the date is okay you just hit <ENTER> to start the SUPERBASIC program set at line 1040 or you can enter something different.

BOOT_SET_DATE is set up so it will run as an independent program. You may have to run it that way if the BOOT_LAST_DATE file gets lost. Normally it will be merged with boot when needed. Of interest is the call from date_set to setter for each part of the date. The way SUPERBASIC works is that the variable ‘minute’ gets passed to ‘value'(see how they correspond in the argument list). The value of ‘minute’ in date_set upon return is whatever ‘value’ was set to in setter. I use some slicing and concatenation to get the date in the desirable form in display_date. Procedure date_save is interesting in that it create a file writes a procedure to it that can merged to boot if needed. This is a technique that can be very usefull.

BOOT_LAST_DATE is written by BOOT_DATE_SET except the first time when your write it.

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.