home *** CD-ROM | disk | FTP | other *** search
- .PL 54
- .MT 2
- .MB 2
- .HE INTERRUPT DRIVEN ROUTINES VIA THE CTRL PF KEYS
- .FO PAGE #
- .HM 1
- .FM 1
- While most of the time spent on the Epson Geneva PX-8
- Portable Computer would be spent running stock programs such as a
- Spreadsheet or an Editor, there are times that a User might wish
- to jump out of a given program, run a special function, and
- return to the main program. It is possible to perform such a
- jump on the PX provided that the interrupt routine being jumped
- to is written correctly. This paper is written for those
- programmers who wish to expand the abilities of the Geneva. The
- paper is a guide of what to do and what not to do when writing
- such software.
-
- There are some limits that the reader should know about
- before working on any interrupt driven software. First, the
- software MUST BE in machine code. If you are unable to develop
- such software in machine code, don't bother to read the rest of
- this paper because there is no way to enable the PX-8 to accept
- an interrupt routine in anything other than machine code.
-
- Another problem is the fact that no interrupt routine in RAM
- will work if any of it is located below $8000. The reason for
- this limit is the fact that during interrupts, the RAM from $0000
- to $7FFF is switched out and the Operating System (OS) ROM is
- switched into its place. Thus any calls to any routine located
- below $8000 would result in an unexpected jump into the OS ROM.
- It is possible to locate an interrupt routine below the CCP;
- however such a move is not wise. The reason it's not wise is the
- fact that the routine is sitting within the TPA Area and could be
- erased by a somewhat large or memory hungry program. Some users
- may wish to perform the trick of moving the routine above the CCP
- and changing the BDOS jump vector. While this trick is safer to
- use, a word of warning is required. If the size of the internal
- RAM Disk is changed or if the User BIOS size is changed, said
- routine will be garbaged. The safest place to locate an
- interrupt routine is within the User BIOS Area.
-
- One final limit encountered when writing an interrupt driven
- routine. Standard BDOS and BIOS routines do not work correctly
- and should NOT be called. However there is a way around this
- limit and is covered within this paper.
-
- During any interrupt operation, the lower RAM ($0000-$7FFF)
- is switched out and the OS ROM is switched in. Therefore, an
- interrupt routine may perform direct calls to the OS ROM.
- However unless you have source code, the correct address of where
- to jump to would be unknown, but there is a solution in the
- version 2.2B ROM (the new version OS ROM), vector table #3.
-
- First a few words about the different tables: When a
- program on the PX-8 executes a BIOS function such as Warm Boot, a
- jump to location 0 occurs. If the internal RAM Disk and the User
- BIOS area are both set to 0 bytes, location 0 jumps to location
- $EB03. This location is the WBOOT vector found in table #1 of
- the BIOS jump vectors. Location $EB03 jumps to table #2,
- location $EC03. Table #2 starts at $EC00, ends at $EC80, and
- every line on this table is the same: CALL $EC81. While this
- might surprise some readers, the function of this table is quite
- logical. Remember that a CALL instruction pushes the return
- address of the next instruction to the stack, thus the stack
- holds the address of the the CALLing Vector+3. All the program
- needs to do is to POP the HL register and perform a quick
- subtraction to determine the CALLing vector. The result is
- stored for later reference. Thus, 43 bank switching routines are
- not required because all calls can use the same bank select
- routine. When the OS ROM is called, the BIOS routines will
- recover the CALLing vector and jump to the proper BIOS routine.
-
- In the "old" version of the OS, CP/M 2.2, the proper jump
- location was found by a vector table located within ROM. The
- "new" version of the OS ROM has its jump vector table located
- within upper RAM. This vector table is known as table #3. Below
- is the locations of each vector and its function:
-
- STANDARD BIOS CALLS:
- ====================
-
- FD90 JMP 2C89 ; COLD BOOT
- FD93 JMP 2CCB ; WARM BOOT
- FD96 JMP 363D ; CONST
- FD99 JMP 3663 ; CONIN
- FD9C JMP 369D ; CONOUT
- FD9F JMP 36B1 ; LIST
- FDA2 JMP 36D2 ; PUNCH
- FDA5 JMP 36C3 ; READER
- FDA8 JMP 2F18 ; HOME
- FDAB JMP 2F24 ; SELDSK
- FDAE JMP 2FDD ; SETTRK
- FDB1 JMP 2FE3 ; SETSEC
- FDB4 JMP 2FE8 ; SETDMA
- FDB7 JMP 2FF9 ; READ
- FDBA JMP 2FEF ; WRITE
- FDBD JMP 4178 ; LISTST
- FDC0 JMP 2FEC ; SECTRAN
-
- EXTENDED BIOS CALLS:
- ====================
-
- FDC3 JMP 422C ; PSET
- FDC6 JMP 36E1 ; SCRNDUMP
- FDC9 JMP 3907 ; BEEP
- FDCC JMP 3D42 ; RSOPEN
- FDCF JMP 3D5C ; RSCLOSE
- FDD2 JMP 3D60 ; RSINST
- FDD5 JMP 414F ; RSOUTST
- FDD8 JMP 3D63 ; RSIN
- FDDB JMP 415E ; RSOUT
- FDDE JMP 4299 ; TIMDAT
-
- FDE1 RET ; MEMORY (DOES NOT PERFORM A FUNCTION WITHIN
- FDE2 NOP ; THE PX-8, IT JUST RETURNS.)
- FDE3 NOP
- FDE4 JMP 3D71 ; RSIOX
- FDE7 RET ; LIGHTPEN (THIS DOESN'T PERFORM A FUNCTION
- FDE8 NOP ; WITHIN THE PX-8, IT JUST RETURNS.)
- FDE9 NOP
- FDEA JMP 43FE ; MASKI
- FDED JMP ECF9 ; LOADX
- FDF0 JMP ECFF ; STORX
- FDF3 JMP ECF3 ; LDIRX
- FDF6 JMP ED0B ; JUMPX
- FDF9 JMP ED05 ; CALLX
- FDFC JMP 41FD ; GETPFK
- FDFF JMP 41FE ; PUTPFK
- FE02 JMP 4416 ; ADCVRT
- FE05 JMP 4438 ; SLAVE
- FE08 JMP 5F6B ; RDVRAM
- FE0B JMP 6D3C ; MCTTX
- FE0E JMP 2DF9 ; POWEROFF
- FE11 DI ; USER BIOS (THIS MUST BE DEFINED BY THE USER
- FE12 RST 05 ; DEFAULT CONTAINS GARBAGE LIKE THIS.)
- FE13 RST 05
-
- A few words of warning to those who might wish to call these
- vectors direct from a program in TPA: IT WON'T WORK! Remember
- that these vectors are a direct call to the OS ROM. Thus unless
- the OS ROM is paged into lower memory, the vectors are not
- meaningful. However, if the OS ROM is active, any routine that
- needs to call BIOS routines, MUST do so through these vectors.
-
- There are several types of interrupts that can occur on the
- PX-8, see below:
-
- 7508: ALARM, KB INTERRUPT
- 8251: RS232 RECEIVE INTERRUPT
- CD: RS232 CD INTERRUPT
- ICF: BAR CODE READER INTERRUPT
- OVF: FREE RUNNING COUNTER OVERFLOW INTERRUPT
- EXT: EXTERNAL DEVICE INTERRUPT
-
- All of the above interrupts, if desired, can point to a user
- defined routine in User BIOS. The routine in User BIOS can call
- any of the above BIOS Vectors in table #3; however there are a
- few things the programmer should watch out for when writing User
- BIOS Code.
-
- To understand what to watch out for, please refer to the
- source code listing for PFDIR11, starting at location $EA80.
- This program is designed to provide a directory listing of drive
- A: whenever CTRL-PF1 is pressed. When this CTRL-Key is pressed,
- an interrupt is generated that causes control to jump to the
- address found at location $F1C0-$F1C1. The default address for
- this location is a return instruction. The return just causes
- the CTRL-Key to do nothing. However when PFDIR11 is run, the
- address at this vector is changed to point to $EA80 and this
- address is the start of my PFDIR routine.
-
- The first section of code, $EA80-EA85, looks at the MODE
- FLAG ($F0B8). The bits within this flag tell what MODE the PX-8
- is in, for example:
-
- $F0B8: MODE FLAG, a 1 = active, a 0 = not on
-
- BIT FUNCTION
- -----------------------
- 7 POWER ON/OFF
- 6 SYSTEM INITIALIZE
- 5 PASSWORD ACCEPT
- 4 MENU DISPLAY
- 3 CP/M MODE
- 2 SYSTEM SCREEN
- 1 ALARM, INTERRUPT
- 0 ALARM, 0 START
-
- The bits that are tested are: 5,4,2,1, and 0, but first a
- look at the bits that are not tested, bits 7,6, and 3. There is
- no need to test bit 7 because PFDIR can only be run when the
- power is on. Bit 6 could be tested, but is unnecessary because a
- system initialize would disable the CTRL-PF Key Functions. I
- have no idea how or even if bit 3 is ever used, because I'm
- unable to come up with a condition where its set. As for the
- bits that are tested, in all cases if the program were allowed to
- run, either there would be a system crash, or upon return from
- the directory, the original screen would be trashed.
-
- Another test performed early in the program ($EA86-$EA8A)
- looks at what mode the LCD is in (mode 0,1,2, or 3). This
- program will work in mode 0 only. While the program could work
- in mode 1, the display of the directory would be a mess. Screen
- modes 2 and 3 would result in the directory erasing all or part
- of the current work on the screen.
-
- One interesting thing discovered while writing PFDIR, was
- the fact that once PFDIR was running, there's no reason why a
- user couldn't press CTRL-PF1 again. If done, the PX-8 will stack
- both interrupts, thereby running the second PF Key press before
- it could finish running the first PF Key press. In fact the
- stack could hold several CTRL-PF Key presses. While this might
- be a big joke to some users, "Lets see how many times we can
- press CTRL-PF1 before the stack overflows!", the result of
- pressing the CTRL-PF key a second time would be to destroy what's
- on the original work screen. The code at $EA8B-$EA94 keeps this
- from occurring. A single byte, RFLAG (Run FLAG), is tested to
- see if the program is already running.
-
- Early versions of PFDIR caused problems when more than 1
- drive was being used. The result would be that whenever any
- drive other than A: was in use, if PFDIR was run, a BDOS ERROR
- would occur when PFDIR was finished. The reason for this error
- was the fact that the disk work space area was altered by PFDIR.
- The solution to this problem was simple, just save the disk work
- space area on entry to PFDIR and then restore this area upon
- exit. See sections $EA95-$EA9F and $EB62-$EB6C to see how this
- was done.
-
- PFDIR should not alter or destroy any characters on the
- current LCD Display, thus, I assumed that the current virtual
- screen was the area in use and the other virtual screen was not
- being used. The subroutine SWAPVS (Swap Virtual Screens) located
- at $EB76-$EB84 is a simple routine that selects the other screen.
- If the current screen is 1, this routine selects screen 2, or if
- the current screen is 2, it selects 1. By using the other
- virtual screen, your current work screen is saved from being
- altered and will be reselected when the program returns.
-
- A number of ROM Routines are called by PFDIR. The direct
- calls into ROM were done because the routine required did not
- exist in the BIOS tables. Such calls are:
-
- BINASC: Convert a binary number in the HL register into
- printable ASCII, store at IX register location.
-
- SCRNPR: Print the string pointed to by the HL register
- to the LCD. This routine does not look at the
- IO byte ($3) or make use of CTRL-P. $FF = the
- end of the string.
-
- LCDOUT: The same as SCRNPR, except this one just prints
- only a single character found in the C register
- to the LCD.
-
- CONINP: This is just like the BIOS routine CONTIN except
- that this routine does NOT look at the IO Byte,
- so that the Keyboard is always the input device.
-
- The rest of the program is a simple Directory type program
- and because it runs much like a standard program in TPA, it will
- not be covered point for point. In fact the only sections worth
- noting are section $EB62-$EB6C, $EB6D-$EB74, and $EB75.
-
- $EB62-$EB6C restores the disk work area back to its original
- form. Section $EB6D-$EB74 selects the original virtual screen
- and resets the RFLAG (Run FLAG) so that a later press of CTRL-PF1
- will allow the program to run again. Last of all, $EB75 is a
- return instruction, which is the end of our routine. Notice that
- this instruction is a simple return (RET) and not a return from
- interrupt (RETI or RETN). The OS code in the upper RAM takes
- care of enabling the lower RAM memory and returning to the
- current program.
-
- A program such as PFDIR is designed to avoid crashing or
- affecting the current program in any way. In some rare cases you
- may wish to have the control PF Keys alter or change something
- within the program. If that is the case, upper RAM ($8000-$FFFF)
- is always on line and can be altered at any time; however lower
- RAM ($0000-$7FFF) is bank selected out during an interrupt.
- Thus, the BIOS routines in table #3, LOADX, STORX, or LDIRX
- should be used to address the lower section of RAM memory.
-
- The section at $EBA2-$EBA8 is run whenever the CTRL-PF1
- function should be disabled and the default condition (no action,
- just return), is to be restored. The code that does this just
- loads the default value $3970 into the control PF1 vector.
-
- The last section of interest is $EBF0-$EBFF. This section
- is really not part of the program, but is still useful. The code
- here is a header for the User BIOS Area. The header is useful
- for telling what routine is loaded into the User BIOS Area.
- Epson standards require that the header MUST BE in locations
- $EBF0-$EBFF. The following is a break down of each byte in the
- User BIOS Header:
-
- $EBF0-$EBF1: This contains the following ASCII Upper Case
- letters, "UB" (User Bios). The letters "US" are
- reserved for "User bios Scheduler data". These are
- the ONLY 2 letter markers used to identify the
- start of a legal header.
-
- $EBF2-$EBF9: 8 ASCII letters are used like a file name to
- identify what routine is active in the User BIOS
- Area.
-
- $EBFA: This is the number of 256 byte pages that the User
- BIOS Routine takes.
-
- $EBFB: If this byte is $00, the routine may NOT be
- disabled. Any other number allows for a release
- routine to be run.
-
- $EBFC-$EBFD: If the address $EBFB does not equal $00, then this
- is the address of the release routine that
- disables the hooks of the User BIOS Routine.
-
- $EBFE: This byte is not used, but is set to $00.
-
- $EBFF: This is the checksum of the first 15 bytes, the
- checksum is computed in this way:
- CS = 0 - BYTE1 - BYTE2 - BYTE3 - ... - BYTE15