
                                                    Model 100 Hints and Tips
                                                                
                The following is a series of "hints and tricks" for getting the most out of the TRS-80 Model 100.
                                                                
          This file is intended to become an ongoing 'mini-magazine' within this SIG. Plans for future updates include
                          deciphering some ROM code for use within BASIC and Machine Language programs.
                                                                
     _____________________________________________________________________________________________________________________
                                                                
     * "Printer Not Ready"
       
   There is a problem within the TRS-80 Model 100 that makes the machine seem to "hang". This is usually caused by pressing
   the PRINT key, which attempts to copy the contents of the non-graphic Model 100 screen to an attached printer. The problem
   manifests itself if there is no printer attached.
   
   Additionally, this can be caused by a BASIC or Machine Language (M/L) program, or one of the ROM programs TEXT, TELCOM,
   SCHEDL, and ADDRSS attempting to output to a non-existant printer.
   
   Usually, pressing SHIFT-BREAK will produce an "aborted" message within a ROM program, or "?IO Error" within a BASIC
   program. If a machine language program is executing and the (non-documented) error vector is not 'plugged', an "?IO Error"
   will be generated and a return will be made to BASIC.
   
   Disabling the PRINT key is touchy at best. Actually, it is possible to disable the key, and all the 'miniature' keys
   immediately underneath the display (F1-F8, PASTE, LABEL, PAUSE/ BREAK, etc.). In my opinion, though, the loss of the
   function keys is greater than the problem of the PRINT key.
   
   Since there is no easy, '1-poke' method of totazlly disabling the printer in the Model 100, we must be satisfied with the
   "?IO Error" in BASIC (unless it is trapped with an ON ERROR statement). On the other hand, there is a simple way in
   Machine Language or BASIC to tell if there is a printer attached.
   
    BASIC
 IF (INP(187)AND6)<>2 THEN PRINT"Not Ready"

    Z80 Assembly Language:
   
   
   
PUSH    BC              ;Save BC
LD      B,A             ;Save A Reg
IN      A,(0BBH)        ;Get printer status
AND     06H             ;Mask off non-status
XOR     02H             ;Set flag bits
LD      A,B             ;Restore A Reg
POP     BC              ;Restore BC
JP      NZ,NOTRDY       ;Not ready if Non-Zero ...
                        ;Printer Ready if code falls
                        ;through

     _____________________________________________________________________________________________________________________
                                                                
   The PASTE buffer has been documented by more than one program (although NOT by Radio Shack!) to reside at the address at
   F88CH-F88DH (63628-63629 decimal). This address is stored in typical 8080 LSB/MSB format. What isn't so well documented is
   that the two bytes preceding that address F88A-F88BH (63630-63631 decimal) contain the pointer to the text returned by
   pressing the SHIFT and PRINT keys simultaneously. (In BASIC, SHIFT-PRINT points to the text "llist" followed by a carriage
   return in ROM... try it!) Both of these "buffers" are terminated by a null byte, or CHR$(0). The SHIFT-PRINT key can thus
   be useful in both BASIC and Machine Language programs.
   
     _____________________________________________________________________________________________________________________
                                                                
     * "Carrier Detect in Basic"
       
   A useful routine has been uploaded to the SIG called DIALER.100 and was submitted by Jerry Kohl [71256,23]. It is heavily
   commented and explains a useful application of a routine that "times out" if carrier is not detected within a given amount
   of time. The routine also contains an npublished entry point to TERM mode within TELCOM without losing carrier.
   
     _____________________________________________________________________________________________________________________
                                                                
     * Tandy BUG Department:
       
   The CHKDC ROM Call documented by Tandy at 5AA9H contains a "small" bug. It seems that the routine was actually written for
   the ADRSS and SCHEDL ROM programs to search for ADRS.DO and NOTE.DO. The limitation here is that the routine will only
   work if the filename being searched for contains 4 characters or less in the file name (preceding the required ".").
   
   How to get around this problem:
   
   The solution is really quite simple, just load the A register with 10 (Hex 0A) and enter the routine at the addess 5AABH.
   
     _____________________________________________________________________________________________________________________
                                                                
     * What is the Shack up to next?
       
   I have heard from more than one source that the price cut we saw on the Model 100 a couple of months ago is going to be
   repeated sometime at the end of March or beginning of April.
   
     _____________________________________________________________________________________________________________________
                                                                
     * BREAK key disable
       
   Disabling the BREAK key can be accomplished by POKEing a value of 128 into the reserved RAM location 63056 (Hex F650).
   
   This effectively eliminates all of the top row of keys (function keys, etc.). To re-enable, just POKE the value 0 back
   into the same location.
   
     _____________________________________________________________________________________________________________________
                                                                
Model 100 ROM Calls

   This article is number two in the "hints and tricks" article for getting the most out of your Model 100. The topic of this
   particular session will be .
   
   Radio Shack has been kind enough to document quite a few ROM calls, but they do not state that these entry points are
   inviolate (ie. will not change with a new ROM revision), nor do they give too much information regarding how to use them
   in BASIC programs.
   
   The following is a series of ROM calls that can be used in to perform some odds and ends. To facilitate using some of the
   more "esoteric" calls, I will also be providing a method of providing an "interface" to BASIC variables.
   
   First, however, we will discuss the DOCUMENTED (by Tandy) ROM Calls that can be used directly in BASIC:
   
DISC:   52BBH   (21179 Decimal) Disconnect Phone Line

   This ROM Call will cause the internal modem to disconnect from the phone line.
   
   Typical BASIC Usage:
   
CALL 21179

     _____________________________________________________________________________________________________________________
                                                                
   CONN: 52D0H (21200) Pick up phone line
   
   This ROM Call will cause the internal modem to "pick up" the phone line. This would be used when trying to detect if
   carrier is present (see CARDET), but has other uses. A crude "dialing" mechanism could be done using the DISC and CONN ROM
   Calls to "pulse" the phone line. In fact, this is how the Model 100 actually dials!
   
   Typical BASIC usage:
   
CALL    21200

   DIAL 532DH (21293) Dial phone number string @ (HL)
   
   Here we come to the first ROM call that requires a parameter.
   
   The call expects to find a valid phone number "string" (see manual on auto-dial strings) at the address pointed to by the
   HL register. It is not documented, but the phone number must have a "terminator". This can either be a NULL CHR$(0), or an
   "auto-log" string. If an auto-log string is used, the Model 100 will wait indefinitely for carrier before sending the
   auto-log string.
   
   Typical BASIC usage: (Autodialer)
   
PH$="555-1212" + CHR$(0)        :' Phone Number in
PH$ V=VARPTR(PH$)               :' Get addr of variable
AD!=PEEK(V+1) + PEEK(V+2)*256   :' Get addr of string
CALL    21293, 0, AD!           :' Dial Phone Number
CALL    21200                   :' Keep Phone line open
PRINT"Please pick up phone"     :' Alert user
INPUT"Enter when ready"; A$     :' Wait till picked up
CALL    21179                   :' Disconnect Model 100

   (Auto-logon -- terminal program)
   
PH$="555-1212<=?U700000,0000^M?Ppsswrd^M?!G PCS154^M>" :' Phone Nbr + Auto Log
V=VARPTR(PH$)                   :' Get addr of variable
AD!=PEEK(V+1) + PEEK(V+2)*256   :' Get addr of string
CALL    21293, 0, AD!           :' Dial and auto log OPEN "MDM:7I1E" FOR INPUT AS 1  :' Open up Modem...
OPEN "MDM:7I1E" FOR OUTPUT AS 2 :' for input and output ...

     _____________________________________________________________________________________________________________________
                                                                
   CLRFLK 5A79H (23161) Clear function key definitions
   
   This ROM Call would be useful for resetting ALL the function key definitions. It is not too useful for BASIC programs, but
   it cannot be performed simillarly in a BASIC program (!).
   
   Typical BASIC usage:
   
CALL    23161

   STFNK 5A7CH (23164) Set function key table
   
   CSFKEY 5B46H (23366) Cold Start Function key table address
   
   BASFKY F80AH (63498 or -2308) Current function key def's used by BASIC
   
   The STFNK call is often used in BASIC program to reset the function keys to their default cold start values. It can also
   be used to set the keys to any value desired. The STFNK call requires the address of a table of function key values to be
   stored at (HL), or the second argument to a CALL function.
   
   Typical BASIC program -- Reset to Cold Start values:
   
CALL    23164, 0, 23366

   Typical BASIC program -- Change keys and reset back:
   
A$=""                           :'Define a dummy string
V=VARPTR(A$)                    :'Get addr of variable
POKE V,128                      :'128 characters long
POKE V+1,10                     :'Point to...
POKE V+2,248                    :'Current key def's
B$=A$                           :'Store def's in B$
FOR X=16 TO 128 STEP 16         :'Set up delimiters
C=ASC(MID$(B$,X,1)) OR 128      :'Get delimiter
MID$(B$,X,1)=CHR$(C)            :'Put it into string
NEXT X                          :'Continue
KEY 1, "F1"                     :'Now reset keys ...                            :'etc.  at end of pgm:
V=VARPTR(B$)                    :'Get addr of variable
AD!=PEEK(V+1) + PEEK(V+2)*256   :'Get addr of key def's
CALL    23164, 0, AD!           :'Reset key definitions

   In the above example, the code up to the "KEY 1" statement is used to save the current function key settings into the
   variable B$. The STFNK function call requires that the definitions for all the keys be "delimited" by setting the most
   significant bit of the last byte. The FOR...NEXT loop performs this delimiting. At the end of the program, assuming that
   the variable B$ has not been modified, the last three instructions are performed, which reset the function key definitions
   to their original values.
   
   RCVX 6D6DH (28013) Return number of characters in RS-232 queue in A
   
   This ROM call is not too useful to be used directly in BASIC because BASIC has no way of returning values from ROM Calls.
   
   But... we can create a machine language "front end" that will suffice nicely. You do not need to know machine language to
   use this routine:
   
00
NOP                     ;Offset byte for call
CD 6D 6D
CALL    RCVX            ;Call routine 77
LD      (HL),A          ;Store value in variable 23
INC     HL              ;Bump pointer 36 00
LD      (HL),00H        ;Zero MSB C9
RET                     ;And return 00
NOP                     ;Offset bytes

   The values on the left side of the listing above are the hexidecimal values of the assembly language instructions on the
   right. These values can be "paired" off to be stored in an "integer array" as shown below. The decimal equivalent of the
   integer pairs is shown to the right:
   
00 CD                  -13056
ML%(0) 6D 6D            28013
ML%(1) 66 23             9062
ML%(2) 36 00               54
ML%(3) C9 00              201
ML%(4)

   Thus, if we set up this array at the start of the program:
   
DIM ML%(4)                      :' Reserve space
FOR X=0 TO 4                    :' Four values
READ ML%(X)                     :' Store integer value
NEXT X                          :' Continue
DATA-31056,28013,9062,54,201    :' Data values

   At this point, we now have a relocatable machine language routine of our own. What does it do?? It allows us to call a ROM
   routine that returns a value in the A register, and get the value into an INTEGER variable in BASIC.
   
   How? Let's say that we want to call this routine stored in ML%(0-4) and return the value in the BASIC variable CT%.
   
   This would be accomplished as follows:
   
CT%=0                              :' Define variable
CALL VARPTR(ML%(0)), 0, VARPTR(CT%) :' Do routine
PRINT CT%                           :' Print the count

   Pretty simple, once it is implemented. The ML% array above is useful for other routines. All that need be changed is the
   value in ML%(1), which should contain the address of the routine to be called.
   
     _____________________________________________________________________________________________________________________
                                                                
   RV232C (6D7EH) (28030) Get character from RS-232 to A register
   
   This routine is another that can be useful in BASIC in conjunction with the ML% array shown above. Change the value of
   ML%(1) to 28030 by executing a statement like:
   
ML%(1) = 28030

   And the ML% routine can be used to get a character from the RS-232 queue. The advantage of using this routine (as opposed
   to the BASIC INPUT$ statement), is that ALL values passed from the RS-232 queue will be available. The INPUT$ statement
   does not allow the value CHR$(127) or CHR$(26)... in fact, receiving CHR$(26) has the effect of CLOSING the RS-232 file!!
   
   Typical BASIC program usage:
   
REM ML% Array set up with ML%(1) = 28030
CT% = 0                             :' Initialize variable
CALL VARPTR(ML%(0)), 0, VARPTR(CT%) :' Do routine
PRINT CT%                           :' Print the char

   SENDCQ 6E0BH (28171) Send XON Resume character
   
   SENDCS 6E1EH (28190) Send XOFF Pause character
   
   These two routines are usefull for pausing and resuming transmission from a host that acknowleges XON/XOFF protocol.
   
   This can be useful for times when general "housekeeping" must be done. After an XOFF character (Pause) is sent, the host
   should stop transmitting. At that point, the program can do what it needs to do, such as outputing to a slow device (such
   as cassette), etc. When ready to resume transmission, send the XON character (Resume).
   
   Typical BASIC usage:
   
CALL    28190                   :'Send XOFF Pause
GOSUB ---                       :'Do interesting things
CALL    28171                   :'Send XON Resume ...                             :'Continue receiving

     _____________________________________________________________________________________________________________________
                                                                
   SD232C 6E23H (28195) Send character in A to RS-232 port
   
   This routine can be used to send a single character to the RS-232 port. In all actuality, there is no real benefit to
   using this call, as the PRINT # command allows you to send as many characters at a time as you wish with no restrictions.
   
   Typical BASIC program usage:
   
CALL    28195, 3                :'Send ^C to HOST

     _____________________________________________________________________________________________________________________
                                                                
   CARDET 6EEFH (28399) Return carrier detect status in A
   
   Since this routine returns a value, it is necessary to use a machine language "front end". The ML% array described above
   can be used if the statement:
   
ML%(1) = 28399

   is executed. When the ML% routine is used to call the CARDET routine, the status returned is:
   
0       Carrier Detected
255     Carrier not found

   Typical BASIC program usage:
   
REM ML% Array setup as described above
CD% = 0                         :'Initialize variable
CALL VARPTR(ML%(0)), 0, VARPTR(CD%) :'Get carrier status
IF CD% = 0 THEN PRINT"CARRIER DETECTED" ELSE PRINT"NO CARRIER"

     _____________________________________________________________________________________________________________________
                                                                
   Look for other exciting installments in the near future.
   
   Comments and/or suggestions are welcome. Send them to larry gensch [72236,3516]
