 NAM RT68-V2

*        ****************
*        *              *
*        *  R T / 6 8   *
*        *     M X      *
*        *              *
*        ****************
*
* RT/68MX REAL TIME OPERATING SYSTEM
* (REVISED VERSION OF RT/68MR)
*
* COPYRIGHT (C) 1976,1977
* THE MICROWARE SYSTEMS CORPORATION
*
* RT/68 LISTING AND OBJECT MAY NOT BE
* REPRODUCED IN ANY FORM WITHOUT
* EXPRESS WRITTEN PERMISSION.

* MEMORY DEFINITIONS

* RT/68 EXECUTIVE USES 12 BYTES OF RAM
* BEGINNING AT 0, THESE ARE NOT NEEDED
* IN SINGLE TASK MODE AND MAY BE
* USED FOR ANY OTHER PURPOSE.
 ORG 0
SYSMOD RMB 1 RT MODE 0=USER 1=EXEC
CURTSK RMB 1 TASK CURRENTLY ACTIVE
TIMREM RMB 1 TASK TIME REMAINING
TSKTMR RMB 2 TIMED TASK COUNTER
CLOCK RMB 2 RT CLOCK COUNTER
INTREQ RMB 1 INTERRUPT REQUEST FLAG
TSKTMP RMB 1 RT EXEC TEMP VAL
PTYTMP RMB 1 RT EXEC TEMP VAL
TIMTSK RMB 1 TIMED TASK INTR STATUS
SYSPTY RMB 1 SYS PRIORITY LEVEL

 ORG $A000
IRQTSK RMB 2 IRQ TASK/VECTOR
BEGADR RMB 2
ENDADR RMB 2
NMITSK RMB 2 NMI TASK/VECTOR
SPTMP RMB 2 SP TMP VAL
RTMOD RMB 1 RT MODE FLAG
BKPOP RMB 1 BKPT OPCODE/FLAG
BKPADR RMB 2 BKPT ADDRESS
RELFLG RMB 1 SWI FLAG
ERRFLG RMB 1 ERROR FLAG/CODE
XTMP RMB 2
IOVECT RMB 2 ACIA ADDRESS VECTOR

 ORG $A042
STACK EQU * MONITOR STACK

* TASK STATUS TABLE
*
* CONSISTS OF 16 3-BYTE TASK STATUS WORDS, ONE FOR
* EACH POSSIBLE TASK. EACH TASK STATUS WORD CONTAINS
* A TASK STATUS BYTE (TSB) AND A 2-BYTE TASK STACK
* POINTER (TSP)
*
* THE TSB IS DEFINED AS FOLLOWS:
*
*   BIT 7    1=TASK ON  0=TASK OFF
*   BIT 6-3  TIME LIMIT IN TICKS (0-15)
*   BIT 2-0  TASK PRIORITY (0-7)
*
* THE TSP IS THE VALUE OF THE TASK'S STACK
* POINTER FOLLOWING THE LAST INTERRUPT, AND
* THEREFORE POINTS TO THE COMPLETE MPU
* REGISTER CONTENTS AT THE TIME THE TASK WAS
* INTERRUPTED. TO RESTART A TASK THE EXEC
* INITIALIZES THE SP FROM THE TSP AND
* EXECUTES AN RTI INSTRUCTION
*
 ORG $A050
TSKTBL RMB 48

* DEFINE PERIPHERIAL REGISTERS
 ORG $8004
PIADA RMB 1
PIACA RMB 1
PIADB RMB 1
PIACB RMB 1
ACIACS RMB 1
ACIADB RMB 1

 ORG $E000
* TAPE LOAD SUBROUTINE
*
* READS MIKBUG(TM) FORMATTED OBJECT TAPES
* INTO RAM.
*
* READER DEVICE IS CONTROLLED BY EITHER ASCII
* CONTROL CODES OR PIA READER CONTROL OUTPUT
* OUTPUT.
*
* TWO ERRORS ARE CHECKED: CHECKSUM AND
* NO CHANGE
LOAD LDAB #$3C TAPE ON CONSTANTS
 LDAA #$11 READER ON CODE
 BSR RDRCON LET IT ROLL
LOAD2 BSR INCH
 CMPA #'S LOOK FOR START OF BLOCK
 BNE LOAD2 BRA IF NOT
 BSR INCH
 CMPA #'9 END OF FILE?
 BNE LOAD4 BRA IF NOT
LOAD3 LDAB #$34 TAPE OFF CONSTANTS
 LDAA #$13
RDRCON STAB PIACB PIA READER CTRL
 BRA OUTCH ASCII TAPE CONTROL
LOAD4 CMPA #'1 S1 DATA RECORD?
 BNE LOAD2 BRA IF NOT, LOOK AGAIN
 CLRB ACCB WILL GENERATE CHKSUM
 BSR BYTE PICK UP BYTE COUNT
 SUBA #2 LESS 2 FOR THE BLOCK ADDR
LOAD5 STAA BEGADR SAVE IT
 BSR BADDR GET BLOCK START ADDR IN X

* LOOP TO READ DATA BLOCK
LOAD6 BSR BYTE GET A DATA BYTE
 DEC BEGADR DECR BYTE COUNT
 BEQ LOAD7 BRA IF LAST BYTE
 STAA 0,X PUT IN MEMORY
 CMPA 0,X BE SURE IT CHANGED
 BNE LDMERR BRA TO ERROR- MUST BE ROM!!
 INX NEXT ADDR
 BRA LOAD6 NEXT BYTE

* B ADDS CHKSM FROM TAPE TO CALCULATED CHKSUM,
* SO BY ADDING ONE IT SHOULD ZERO
LOAD7 INCB
 BEQ LOAD2 BRA IF IT DID
 LDAA #$32 TOO BAD, GET THE ERROR CODE
 BRA LODERR
LDMERR LDAA #$31 NO CHANGE ERROR CODE
LODERR STAA ERRFLG
 BRA LOAD3

* BUILD 4 HEX CHAR VALUE (ADDRESS)
* RETURNS VALUE IN XR
BADDR BSR BYTE INPUT 2 LEFT CHRS
 STAA ENDADR
 BSR BYTE INPUT 2 RIGHT CHRS
 STAA ENDADR+1
 LDX ENDADR
 RTS

* INPUT A BYTE (2 HEX CHARS)
* RETURNS BINARY VALUE IN ACC A

BYTE PSHB INPUT 2 HEX CHAR
 BSR INHEX LEFT HEX CHAR
 ASLA
 ASLA
 ASLA
 ASLA
 TAB
 BSR INHEX RIGHT HEX CHAR
 ABA
 PULB
 PSHA
 ABA
 TAB
 PULA
 RTS
 NOP

* HEX OUTPUT AUX SUBROUTINES
OUTHL LSRA
 LSRA
 LSRA
 LSRA
OUTHR ANDA #$F
 ADDA #$30
 CMPA #$39
 BLS OUTCH
 ADDA #$7

OUTCH JMP OUT1CH
INCH JMP IN1CHR

* PRINT DATA STRING POINTED TO BY XR
* AND ENDING WITH ASCII EOT ($04)
PDATA2 BSR OUTCH
 INX
PDATA1 LDAA 0,X SUBR ENTRY POINT
 CMPA #4
 BNE PDATA2
 RTS

*
* CONSOLE MEMORY DUMP SUBROUTINE
*
* PRINTS BEG ADDR AND 16 BYTES OF DATA ON EACH LINE
* STARTING ADDR IN BEGADR
* ENDING ADDR IN ENDADR
*
DUMP JSR CRLF CR AND LF
 LDX #BEGADR
 BSR OUT4HS PRINT BEGINNING ADDR
 LDAB #16 BYTE COUNT FOR LINE
 LDX BEGADR GET BEG ADDR
DUMP1 BSR OUT2HS PRINT A BYTE
 DEX
 CPX ENDADR DONE YET?
 BNE DUMP2 BRA IF NOT
 RTS
DUMP2 INX ADV X TO NEXT BYTE
 DECB DEC LINE BYTE COUNT
 BNE DUMP1 BRA IF LINE NOT DONE
 STX BEGADR UPDATE BEGADR TO CURRENT ADDR
 BRA DUMP

HBAD LDAA #$33 INHEX ERROR RETURN
 STAA ERRFLG
 RTS

* INPUT HEX CHARACTER, IF CHAR IS NOT
* HEX, THE ERROR FLAG IS SET TO THE
* ERROR CODE ($33 - ASCII 1)
INHEX BSR INCH INPUT ONE HEX CHAR
 SUBA #$30
 BCS HBAD
 CMPA #9
 BLS IHRET
 SUBA #7
 BCS HBAD
 CMPA #15
 BHI HBAD
IHRET RTS

 NOP
 NOP

* OUTPUT BYTE (TWO HEX CHARS) POINTED
* TO BY XR
OUT2H LDAA 0,X
 BSR OUTHL
 LDAA 0,X
 INX
 BRA OUTHR

* OUTPUT 4 HEX CHARS AND SPACE
OUT4HS BSR OUT2H

* OUTOUT 2 HEX CHARS AND SPACE
OUT2HS BSR OUT2H

* OUTPUT A SPACE
OUTS LDAA #$20
BOUT BRA OUTCH

* PRINT CONTENTS OF STACK
* FORMAT:
* SP CC B A XR PC
PRSTAK BSR CRLF PRINT CF+LF
 LDX #SPTMP
 BSR OUT4HS PRINT SP
 LDX SPTMP
PRSTK INX ENTRY TO PRINT TASK STACK
 BSR OUT2HS PRINT CC
 BSR OUT2HS PRINT ACC B
 BSR OUT2HS PRINT ACC A
 BRA PRSTK2 BRA OVER PATCH
CONTRL JMP CONENT PATCH FOR ADDR ALIGNMENT
PRSTK2 BSR OUT4HS PRINT XR
 BRA OUT4HS PRINT PC +RTS

* WRITE OBJECT TAPE SUBROUTINE
*
* GENERATES MIKBUG(TM) FORMATTED TAPES
* ON SYSTEM TAPE DEVICE (PAPER TAPE,
* AUDIO CASSETTE, ETC.)
*
* BEGINNING ADDRESS OF DATA IN "BEGADR"
* ENDING ADDRESS IN "ENDADR"
*
* ENTRY POINT IS "TAPOUT" - E0EE

* AUX. SUBR. TO OUTPUT BYTE + UPDATE
* CHECKSUM.
TAPAUX ADDB 0,X
 BRA OUT2H

TAPOUT LDAA #$12 TAPE ON CODE
 BSR OUTCH
*OUTPUT 60 NULL CHARS TO GENERATE
* EITHER A 6" LEADER FOR PAPER TAPE
* OR A 2 SECOND TAPE SPEEDUP DELAY
* (AT 30CPS) FOR AUDIO CASSETTES
 LDAB #60 LEADER/DELAY NULL COUNT
OUTLDR CLRA
 BSR JOUT1C
 DECB
 BNE OUTLDR

* SUBTRACT BEGADR FROM ENDADR
TOUT1 LDX #BEGADR
 LDAA 2,X
 LDAB 3,X
 SUBB 1,X
 SBCA 0,X
 BCC TOUT2 BRA IF BEG < END TO DUMP
 LDAA #$14 PUNCH OFF CODE
JOUT1C JMP OUTCH

* CALCULATE BYTE COUNT
TOUT2 BNE TOUT3 BRA IF HIGH BYTE NONZERO
 CMPB #16
 BCS TOUT4 BRA IF BLOCK < 16 BYTES
TOUT3 LDAB #15 SET FULL BLOCK
TOUT4 ADDB #4 ADD FOR B.C. + BEG ADDR.

* OUTPUT BLOCK HEADER
 BSR CRLF OUTPUT CR,LF,NULLS
 INX
 BSR JPDATA OUTPUT S,1
 PSHB SAVE BYTE COUNT
 TSX
 CLRB CLEAR CHECKSUM
 BSR TAPAUX PRINT BYTE CNT
 PULA
 SUBA #3 UPDATE BYTE COUNT
 PSHA
 LDX #BEGADR
 BSR TAPAUX OUTPUT BEG. ADDR
 BSR TAPAUX

* LOOP TO OUTPUT ONE BLOCK OF DATA
 LDX BEGADR XR POINTS TO CURRENT DATA BYT
TOUT5 BSR TAPAUX OUTPUT BYTE
 PULA
 DECA DECR BYTE COUNT
 PSHA
 BNE TOUT5 BRA IF BYTE CNT NOT ZERO

 INS
 STX BEGADR SAVE CURRENT ADDR
 COMB COMPL CHKSUM
 PSHB
 TSX
 BSR TAPAUX OUTPUT CHKSUM
 INS
 BRA TOUT1

* SUBROUTINE TO PRINT CR + LF
CRLF LDX #CRLSTR
JPDATA JMP PDATA1

* RT/68 CONSOLE MONITOR PROGRAM
*
* ACCEPTS COMMANDS FORM THE CONSOLE DEVICE
* AND EXECUTES THE APPROPRIATE FUNCTION.

* ENTRY POINT FOR RESTART
INIT LDS #STACK INITIALIZE PERIPHERALS
 STS SPTMP
 LDX #$8000
 STX IOVECT INIT ACIA VECTOR
* INITIALIZE CONTROL PIA
 INC 4,X
 LDAB #$16
 STAB 5,X
 INC 4,X
 LDAA #$05
 STAA 6,X
 LDAA #$34
 STAA 7,X
* INITIALIZE ACIA AT $8000
 LDAA #3
 STAA 0,X
 DECB
 STAB 0,X SET ACIA CSR
CONENT CLR BKPOP CONSOLE ROUTINE ENTRY POINT
 CLR RTMOD
CONSOL CLR ERRFLG
 LDS #STACK INIT SP
 BSR CRLF
 LDAA #'$ PRINT PROMPT
 BSR OUTEEE
 BSR INEEE INPUT COMMAND CODE

* COMMAND TABLE LOOKUP/EXECUTE LOOP
* SEARCHES FOR COMMAND CODE ON TABLE TO OBTAIN
* FUNCTION SUBROUTINE ADDRESS.
 LDX #CMDTBL-3 INIT X TO BEGINNING OF TABL
CMSRCH INX ADV TO NEXT ENTRY
 INX
 INX
 LDAB 0,X GET CODE FROM TABLE
 BEQ CMDERR IF ZERO, END OF TABLE
 CBA COMMAND CODE MATCH COMPARE
 BNE CMSRCH BACK TO ADV IF NOT
 LDX 1,X GET CMND SUBR ADDR FROM TABLE
 JSR 0,X DO IT
TSTENT BSR ERTEST TEST FOR ERROR
GOCON BRA CONSOL GET ANOTHER CMND

CMDERR LDAB #'6 ILLEGAL COMMAND CODE
 BRA ERROR

* SUBR TO SET 0R REMOVE BREAKPOINTS
SETBKP LDAA BKPOP GET BKPT FLAG OR OPCODE
 BEQ SBRET IF = 0, NO BKPT ACTIVE
 LDX BKPADR GET ADDR
* SWAP FLAG/OPCODE
 LDAB 0,X
 STAA 0,X
 STAB BKPOP
SBRET RTS

* "D" DUMP COMMAND
DMPCOM BSR GET2AD
 JMP DUMP

INEEE JMP IN1CHR

* SUBR TO PREPARE FOR USER PROGRAM
* EXECUTION. CALLED BY G, E, & S COMMANDS
*
SETRUN BSR SETBKP SET BKPT IF ANY
 LDAB #$1E
 LDAA RTMOD TEST IF MULTITASK MODE
 BEQ SETRN2 BRA IF NOT MULTI
 INCB ENABLE RT CLOCK INTR
 CLRA
 STAA SYSMOD
SETRN2 LDAA PIADA
 STAB PIACA
RETURN RTS

* "B" BREAKPOINT COMMAND ROUTINE
BKPCOM CLR BKPOP
 BSR GETADR
 STX BKPADR
 LDAA #$3F
 STAA BKPOP
 RTS

OUTEEE JMP OUT1CH

* SUBR TO READ ONE OR TWO ADDRESS
* PARAMETERS, COMMA LEADS ADDRESSES,
* (CR) CANCELS COMMAND
GET2AD BSR GETADR GET TWO ADDRESSES
 STX BEGADR

GETADR BSR INEEE GET ONE ADDRESS
 LDAB #$34
 CMPA #$0D
 BEQ CONSOL
 CMPA #',
 BNE ERROR
 JSR BADDR

* ERROR TEST SUBROUTINE
ERTEST LDAB ERRFLG
 BEQ RETURN

* ERROR HANDLER, PRINTS MESSAGE
* AND ERROR CODE
ERROR LDX #ERRMSG
 JSR PDATA1
 TBA
 BSR OUTEEE
 BRA GOCON

* "E" EXECUTE SINGLE TASK COMMAND
EXCOM BSR GETADR
 BSR SETRUN
 LDX ENDADR
 JMP 0,X

* "G" GO TO USER PGM OR RETURN FROM
* BREAKPOINT COMMAND ROUTINE
GOCOM LDS SPTMP
 BSR SETRUN
 RTI

* "P" WRITE TAPE COMMAND
PUNCOM BSR GET2AD
 JMP TAPOUT

* "S" COMMAND
* ACTIVATES AND INITIALIZES RT/68
* EXECUTIVE
SYSCOM CLR RELFLG
 LDAA #1
 STAA RTMOD
 LDX #PTYTMP
CLOOP CLR 0,X
 DEX
 BNE CLOOP
 STAA 0,X
 BSR SETRUN
 JMP EXEC02 JUMP TO RT EXEC ENTRY

* "M" MEMORY EXAMINE/CHANGE ROUTINE
* AFTER BEGINNING ADDR IS ENTERED, PGM
* PRINTS ADDR AND DATA IN HEX:
*    AAAA DD
* A SLASH AND NEW HEX DATA CHANGES LOACTION,
* A (LF) OPENS NEXT ADDR, AND A (CR) CLOSES
* FUNCTION
MEMCOM BSR GETADR GET BEG ADDR

* EXAMINE/CHANGE LOOP
MEM1 JSR CRLF
MEM2 LDAA #$0D PRINT LF
 BSR OUTEEE
 LDX #ENDADR
 JSR OUT4HS PRINT ADDRESS
 LDX ENDADR
 JSR OUT2H PRINT CONTENTS
 STX ENDADR
 JSR INEEE INPUT DELIMITER
 CMPA #$0A
 BEQ MEM2 BRA IF LF TO OPEN NEXT
 CMPA #'/
 BEQ MEM3 BRA IF CHANGE
 RTS

* CHANGE MEMORY LOCATION
MEM3 JSR BYTE READ NEW DATA
 BSR ERTEST
 DEX
 STAA 0,X STORE NEW DATA
 CMPA 0,X TEST FOR CHANGE
 BEQ MEM1 BRA IF OK TO OPEN NEXT
 LDAB #$35 ERROR CODE
 BRA ERROR

*       REAL TIME OPERATING SYSTEM COMPONENTS
*
* CONSISTS OF:
*
*              INTERRUPT PROCESSORS
*              TASK EXECUTIVE
*              AUX. SUBROUTINES
*


* BREAKPOINT SERVICE ROUTINE
RUNBKP TSX GET SP IN XR
 BSR ADJSTK DECR PC ON STACK
 LDX 5,X GET TASK PC OFF STACK
 CPX BKPADR COMPARE TO PRESET ADR
 BEQ RUNBK2 BRA IF SAME
 LDAB #$37 SET ERROR FLAG
 STAB ERRFLG
RUNBK2 JSR SETBKP REMOVE BKPT OPCODE
 LDAA #$16
 STAA PIACA OFF RT CLOCK + ABORT INTR
 STS SPTMP SAVE TASK SP
 JSR PRSTAK DUMP STACK
 JMP TSTENT ENTER CONSOLE MONITOR

* SUBR TO DECREMEMT PC ON STACK
ADJSTK TST 0,X
 BNE ADSTK2
 DEC 5,X
ADSTK2 DEC 6,X
 RTS

* SWI ENTRY POINT, DETERMINES WHETHER
* BREAKPOINT OR PGM RELEASE FUNCTION

SINT EQU * SWI VECTOR DESTINATION
 LDAA RELFLG GET PGM RELEASE FLAG
 BEQ RUNBKP EXEC BKPT IF NOT SET
 CLR RELFLG RESET FLAG
 CLRB
 BRA EXEC09 GO TO EXEC TO SWAP

* IRQ INTERRUPT ENTRY POINT
* INCLUDES LOGIC TO DETECT AND CORRECT
* INTERRUPT ERROR OCCURRING WHEN SWI +
* NMI OCCUR SIMULTANEOUSLY. (SEE P. A-10
* OF M6800 APPLICATIONS MANUAL)

IRQ EQU * IRQ VECTOR DESTINATION
 LDAA RELFLG GET SWI FLAG
 BNE INTBAD BRA TO ERR CORR. IF SET
 LDX #IRQTSK PTR TO IRQ VECTOR/STATUS
 BRA RUNINT GOTO INTR SERVICE

* CORRECT SWI-IRQ COINC. ERROR
INTBAD TSX
 BSR ADJSTK DECR TASK PC ON STACK

* NMI INTERRUPT HANDLER
*
* TEST CONTROL PIA FOR ABORT OR CLOCK
* INTERRUPT AND PROCESS SAME
* IF NOT, EXECUTES USER INTERRUPT
NMI EQU * NMI VECTOR DEST.
 LDAA PIACA GET PIA STATUS REG
 LDAB PIADA CLEAR PIA INTR FLGS
 ASLA
 BMI RUNBK2 BRA IF ABORT INTR
 BCC NMI5 BRA IF USER INTR
* HERE IF CLOCK INTR ONLY
 LDAA RTMOD TEST SYS MOD
 BEQ NMI5 BRA TO USER INTR IF NOT
 LDX CLOCK
 INX
 STX CLOCK
* UPDATE TIMED TASK STATUS
 LDX TSKTMR GET THE TIMED TASK COUNTER
 BEQ NMI3 BRA IF NOT ACTIVE
 DEX DECR THE COUNTER
 STX TSKTMR
 BNE NMI3 BRA IF NOT EXPIRED
 LDAA TIMTSK GET TIMED TASK STAT BYTE
 BRA RNINT3 RUN AS INTERRUPT
* UPDATE REMAINING TIME OF CURRENT TASK
NMI3 LDAA TIMREM GET TIME LEFT
 BEQ NMI4 BRA IF UNLIMITED
 DECA
 STAA TIMREM
 BEQ EXEC01 BRA TO EXEC IF TIME UP
NMI4 LDAA INTREQ TEST FOR PENDING INTR.
 BNE EXEC01
 RTI
NMI5 LDX #NMITSK GET NMI STAT PTR

* GENERAL INTERRUPT PRESERVICE
* SELECTS PROPER MODE, AND EITHER
* RUNS OR SCHEDULES INTERRUPT SERVICE
* TASK ACCORDING TO THE APPROPRIATE
* STATUS BYTE
RUNINT LDAA RTMOD
 BNE RNINT2 BRA IF MULTITASK MODE
 LDX 0,X GET VECTOR
 JMP 0,X EXECUTE SAME AS MIKBUG

RNINT2 LDAA 0,X GET INTR STATUS BYTE
RNINT3 BSR TSKON TURN SERV. TASK ON
 TSTA CHK IMMED OR DEFERRED
 BPL INTRET BRA IF DEFERRED
 STAA INTREQ SET INTR REQ. FLAG
* FALL THRU TO EXECUTIVE

* RT/68 MULTI TASK EXECUTIVE PROGRAM
*
* SAVES CURRENT TASK STATUS IN TASK STATUS
* TABLE, THEN SEARCHES THE TABLE FOR THE
* HIGHEST PRIORITY RUNNABLE TASK AND STARTS
* IT. IF THERE IS MORE THAN ONE RUNNABLE TASK
* AT THE HIGHEST LEVEL, THE
* EXECUTIVE WII RUN THEM ROUND ROBIN

* TEST MODE TO PREVENT MULTIPLE
* EXECUTION OF EXEC BY INTERRUPTS
EXEC01 LDAB SYSMOD
 BNE INTRET BRA IF EXEC ALREADY ACTIVE
EXEC09 INCB SET EXEC MODE
 STAB SYSMOD
* SAVE CURRENT TASK SP ON TABLE
 LDAA CURTSK GET CURRENT TASK #
 BSR FNDTSB FIND ADDR OF TSB
 STS 1,X SAVE SP

* INITIALIZE EXEC TEMP VALUES
* PTYTMP = HIGHEST PRIORITY FOUND
* TSKTMP = TASK # FOR ABOVE
EXEC02 CLRA
 STAA INTREQ
 STAA PTYTMP
 STAA TSKTMP
 LDAA CURTSK

* LOOP TO SEARCH THRU TABLE FOR
* HIGHEST RUNNABLE TASK
* STARTS WITH CURRENT TASK AND COUNTS
* DOWN SO LAST TASK TESTED IS THE
* CURRENT TASK # -1. THIS ALLOWS TASKS
* AT THE SAME PRIORITY LEVEL TO EXECUTE
* ROUND-ROBIN.
EXEC03 BSR FNDTSB FIND TSB
 BPL EXEC04 BRA IF TASK OFF
 ANDB #$07 MASK PRIORITY
 CMPB PTYTMP COMP. TO HIGHEST SO FAR
 BCS EXEC04 BRA IF LOWER
 STAB PTYTMP MAKE IT LATEST
 TAB CHANGE SET TASK #
 ORAB #$80 SET FOUND FLAG
 STAB TSKTMP
*ADVANCE TO NEXT TASK
EXEC04 DECA
 ANDA #$0F
 CMPA CURTSK SEE IF LAST TASK
 BNE EXEC03 BRA IF NOT FINISHED

* CHECK IF TASK FOUND IS RUNNABLE
 LDAB PTYTMP GET HI PRIORITY
 CMPB SYSPTY COMPARE TO SYS PRIORITY
 BCS EXEC02 SEARCH AGAIN IF LOWER
 LDAA TSKTMP TEST FOUND FLAG
 BPL EXEC02 BRA IF NOT SET

* RUNNABLE TASK FOUND, SET SYSTEM
* PARAMETERS TO RUN IT
 ANDA #$0F
 STAA CURTSK SET TASK #
 BSR FNDTSB GET TASK TSB
 LSRB EXTRACT TIME LIMIT
 LSRB
 LSRB
 ANDB #$0F
 STAB TIMREM
 LDS 1,X LOAD TASK SP
* TEST FOR ANY INTERRUPT THAT OCCURRED
* DURING EXEC MODE
 LDAA INTREQ
 BNE EXEC02
 CLR SYSMOD SET USER MODE
INTRET RTI RUN TASK

* RT EXECUTIVE AUX. SUBROUTINES
*
* ALL ARE REENTRANT SUBROUTINES THAT
* PASS PARAMETERS AS FOLLOWS:
*
* ENTRY: TASK # IN ACC A
*
* RETURN: TASK # IN ACC A
*         TASK STATUS BYTE (NEW) IN ACC B
*         ADDR OF TSB IN XR

* SUBR TO TURN TASK ON
TSKON BSR FNDTSB
 ORAB #$80
RESTSB STAB 0,X
 RTS

* SUBR TO TURN CURRENT TASK OFF
CTSKOF LDAA CURTSK

* SUBR TO TURN TASK OFF
TSKOFF BSR FNDTSB
 ANDB #$7F
 BRA RESTSB

* SUBR TO FIND TASK STATUS BYTE/WORD
FNDTSB PSHA
 ANDA #$0F
 TAB
 ASLA
 ABA
 ADDA #$50
 PSHA
 LDAA #$A0
 PSHA
 TSX
 LDAA 0,X
 INS
 INS
 LDAB 0,X
 PULA
 RTS

* CHARACTER AND BYTE I/O ROUTINES
*
* SELECTS INTERFACE TYPE (PIA OR ACIA)
* ACCORDING TO THE LEVEL OF PIA INPUT CB5
* IF ACIA TYPE IS SELECTED, THE ADDRESS
* OF THE ACIA IS OBTAINED FROM "IOVECT"
* WHICH WILL DEFAULT TO $8000

* READ CHAR WITHOUT PARITY OR RUBOUT
IN1CHR BSR INBYTE GET BYTE
 ANDA #$7F STRIP PARITY BIT
 CMPA #$7F TEST FOR RUBOUT
 BEQ IN1CHR AGAIN IF RUBOUT
 RTS

* READ 8-BIT BYTE
INBYTE PSHB
 BSR IOAUX SAVE XR + SAMPLE TYPE
 BNE ACIAIN

* PIA SOFTWARE UART ROUTINE -
* INPUT ONE CHAR WITHOUT PARITY
PIAIN LDAA 4,X
 BMI PIAIN WAIT FOR START BIT
 CLR 6,X SET 1/2 BIT TIME
 BSR STRTBT RESET TIMER
 BSR WAITBT WAIT FOR TIMER
 LDAB #$04
 STAB 6,X SET TIMER TO FULL BIT TIME
 ASLB BIT COUNT=8
* LOOP TO INPUT 8 DATA BITS
PIAIN2 BSR WAITBT WAIT BIT TIME
 SEC
 ROL 4,X SHIFT OUT DATA
 RORA SHIFT IN A TO BUILD
 DECB DECR BIT COUNT
 BNE PIAIN2 BRA IF NOT DONE
 BSR WAITBT WAIT FOR STOP BIT
CHKSTB LDAB 6,X TEST FOR # STOP BITS
 ASLB
 BPL RESTOR
 BSR WAITBT
* RESTORE REGISTERS + RETURN
RESTOR LDX XTMP
 PULB
 RTS

* ACIA CHAR INPUT ROUTINE
ACIAIN LDAB 0,X GET STAT REG
 LSRB MOVE RDY BIT TO SIGN POS
 BCC ACIAIN WAIT IF NOT READY
 LDAA 1,X READ DATA
 BRA RESTOR BRA TO CLEANUP

* I/O SETUP SUBROUTINE
IOAUX STX XTMP SAVE XR
 LDX #$8000 LOAD XR WITH PERIPH PTR
 LDAB 6,X TEST FOR ACIA OR PIA
 BITB #$20
 BEQ AUXRET BRA IF PIA
 LDX IOVECT GET ACIA ADDRESS
AUXRET RTS

* SUBR TO WAIT FOR 1 BIT TIME
* AND RESET TIMER
WAITBT TST 6,X
 BPL WAITBT

* SUBROUTINE TO START (RESET) BIT TIMER
STRTBT INC 6,X
 DEC 6,X
 RTS
* OUTPUT 1 CHARACTER SUBROUTINE TO
* PIA OR ACIA
OUT1CH PSHB SAVE ACC B
 BSR IOAUX SETUP FOR ROUTINE
 BNE ACOUT USE ACIA SUBR IF TRUE

* PIA SOFTWARE UART CHAR OUTPUT
 LDAB #4
 STAB 4,X SPACE FOR START BIT
 STAB 6,X SET TIMER FOR FULL
 LDAB #10 INIT. BIT COUNTER
 BSR STRTBT RESET TIMER
* BIT OUTPUT LOOP
POUT1 BSR WAITBT WAIT BIT TIME
 STAA 4,X SET BIT OUTPUT
 SEC
 RORA SHIFT IN NEXT BIT
 DECB DEC BYTE COUNT
 BNE POUT1 BRA IF NOT LAST BIT
 BRA CHKSTB

* ACIA CHAR OUTPUT ROUTINE
ACOUT LDAB 0,X GET STAT REG
 LSRB SHIFT RDY BIT TO C
 LSRB
 BCC ACOUT BRA IF NOT READY
 STAA 1,X STORE DATA
 BRA RESTOR GO CLEANUP

* ERROR MESSAGE STRING
ERRMSG FCB $20,'E,'R,'R,$20,4

* CR/LF AND TAPE HEADER STRING
CRLSTR FCB $0D,$0A,0,0,0,4,'S,'1,4

*
* COMMAND CODE/ADDRESS TABLE
*
CMDTBL EQU *
 FCB 'B
 FDB BKPCOM
 FCB 'D
 FDB DMPCOM
 FCB 'E
 FDB EXCOM
 FCB 'G
 FDB GOCOM
 FCB 'L
 FDB LOAD
 FCB 'M
 FDB MEMCOM
 FCB 'P
 FDB PUNCOM
 FCB 'R
 FDB PRSTAK
 FCB 'S
 FDB SYSCOM
 FCB $1B (ESC) NEXT ROM OR USER DEFINE
 FDB $7000
 FCB 0 END

* INTERRUPT VECTORS
*
 FDB IRQ IRQ VECTOR
 FDB SINT SWI VECTOR
 FDB NMI NMI VECTOR
 FDB INIT RESTART VECTOR

 END
