        TITLE   'PURDUE AUTOPATCH CONTROL PROGRAM'
        NAM     WR9ACZ
  
* WR9ACZ AUTO-PATCH CONTROLER 
* COPYRIGHT (C) 1976, HOWARD CUNNINGHAM 
* 
*       01/17/76        INITIAL VERSION 
*       10/23/76        CONFIGURED FOR WINCE BOARD
  
  
* ASSEMBLY CONSTANTS
  
CKPD    EQU     4               CLOCK PERIOD IN MSEC
CSPD    EQU     CKPD*256/1000   HIGH BYTE PERIOD IN SECONDS 
SPEED   EQU     18              MORSE SENDING RATE IN WPM 
DITLEN  EQU     1200/SPEED/CKPD DOT PERIOD IN CLOCK TICKS 
QUELEN  EQU     10              MAX DIGITS IN DIAL PULSE QUEUE
IDTONE  EQU     ^00111000       IDENT TONE, COLUMN 4
BPTONE  EQU     ^01000011       BEEP TONE, ROW 3
  
  
* I/O DATA REGESTER BIT DEFINITIONS 
  
BCAR    EQU     ^10000000       CARRIER (MUST BE HIGH ORDER BIT)
BRNG    EQU     ^01000000       RINGER
BUSE    EQU     ^00100000       PHONE IN USE
BPRV    EQU     ^00010000       PRIVILEGED COMMANDS 
BHIF    EQU     ^00001000       INPUT HIGH IN FREQ
BLOF    EQU     ^00000100       INPUT LOW IN FREQ 
  
BLSN    EQU     ^00001000       XMIT PATCH AUDIO
BCON    EQU     ^00000100       CONNECT PATCH 
BOFF    EQU     ^00000010       OUT OF SERVICE
BTRN    EQU     ^00000001       TRANSMIT
  
  
* FIXED RAM LOCATIONS 
  
        ORG     0 
FWARAM  EQU     . 
  
CLOCK   RMB     2               CLOCK TICKS MOD 2**16 
WATCH   RMB     1               WATCH DOG TIMER 
CURTSK  RMB     2               CURRENT TASK TABLE INDEX
XMIT    RMB     1               TRANSMIT WHEN NON-ZERO
ACCESS  RMB     2               AUTO PATCH ACCESS CODE
A911    RMB     1               NON-ZERO IF ACCESS VIA 911
DIGITS  RMB     2               NUMBER OF DIGITS IN DIAL QUEUE
SNDING  RMB     1               NON-ZERO IF CODE IN PROGRESS
ASMBLY  RMB     2               TOUCH TONE DIGIT ASSEMBLY 
ACTIVE  RMB     1               NON-ZERO IF PATCH ACTIVE
POKE    RMB     1               SHORT TRANSMISSION COUNTER
QUEUE   RMB     QUELEN          DIAL DIGIT QUEUE
  
FREMEM  EQU     * 
  
  
* I/O REGISTERS 
  
PIAS    EQU     $200
  
        ORG     $210
IOAD    RMB     1               I/O A-SIDE DATA 
IOAC    RMB     1               A-SIDE CONTROL
IOBD    RMB     1               I/O B-SIDE DATA 
IOBC    RMB     1               B-SIDE CONTROL
  
        ORG     $240
TTID    RMB     1               TOUCH TONE INPUT DATA 
TTIC    RMB     1               INPUT CONTROL 
TTOD    RMB     1               TOUCH TONE OUTPUT DATA
TTOC    RMB     1               OUTPUT CONTROL
  
  
* INTERRUPT VECTORS 
  
        ORG     $FFF8 
        FDB     INTRPT          HARDWARE
        FDB     EXEC            SOFTWARE
        FDB     RESET           NON-MASKABLE
        FDB     RESET           POWER UP
  
  
* TASK ENTRY POINT TABLE
  
        ORG     $FC00 
TASKS   FDB     COR             CARRIER OPERATION 
        FDB     CONTRL          CONTROL FUNCTION PROCESSER
        FDB     DIAL            DIAL PULSE GENERATOR
        FDB     RINGER          INCOMMING CALL DETECTOR 
        FDB     IDENT           IDENTIFIER
NONPRE  EQU     *-TASKS/2 
*       FDB     $3C6C           CRAMERKIT TERMINAL MONITOR
TSKCNT  EQU     *-TASKS/2 
  
  
* EXECUTIVE CONTROL TABLES
  
STKLEN  EQU     16              LENGTH OF STACK FOR EACH TASK 
STACKS  EQU     FREMEM          TASK STACK POINTERS 
STKORG  EQU     2*TSKCNT+STACKS STACK AREA
LWARAM  EQU     TSKCNT*STKLEN+STKORG-1
        PAGE
* EXECUTIVE 
* 
*       THE EXECUTIVE IS RESPONSIBLE FOR INITIALIZATION OF THE
*       MACHINE AFTER RESET AND FOR DISTRIBUTION OF CONTROL 
*       BETWEEN TASKS AFTER A SOFTWARE INTERRUPT. 
  
* RESET ENTRY 
  
RESET   LDX     &LWARAM 
RES1    CLR     0,X             CLEAR RAM AND I/O 
        DEX 
        CPX     &FWARAM-1 
        BNE     RES1
  
* INITIALIZE I/O
  
        LDX     &PIAS 
        COM     TTOD-PIAS,X     SET OUTPUT DATA DIRECTION 
        COM     IOBD-PIAS,X 
        LDA A   &^00111101
        STA A   IOAC-PIAS,X     ENABLE INT FROM I/O A-SIDE
        DEC A 
        STA A   IOBC-PIAS,X     BUT NOT OTHERS
        STA A   TTIC-PIAS,X 
        STA A   TTOC-PIAS,X 
  
* PRESET TASK DATA AREAS
  
        LDS     &TASKS-1
        LDX     &2*TSKCNT 
        LDA A   &STKORG-8 
RES2    DEX                     ADVANCE TO NEXT TASK
        DEX 
        ADD A   &STKLEN         COMPUTE STACK LOCATION
        STA A   STACKS+1,X
        STX     CURTSK
        LDX     STACKS,X
        PUL B                   STORE ENTRY PC IN STACK 
        STA B   6,X 
        PUL B 
        STA B   7,X 
        LDX     CURTSK
        BNE     RES2            LOOP FOR EACH TASK
        BRA     EXE1            ENTER EXECUTIVE 
  
* SOFTWARE INTERRUPT ENTRY
  
EXEC    LDX     CURTSK
        STS     STACKS-2,X      SAVE CURRENT TASK'S STACK 
        DEX 
        DEX                     ADVANCE TO NEXT TASK
        BNE     EXE2
EXE1    LDX     &2*TSKCNT       START OVER WITH FIRST TASK
        CLR     WATCH           RESET WATCH DOG EVERY MAJOR CYCLE 
        LDA A   &^00110101
        STA A   IOAC            SCOPE SYNC
        LDA A   &^00111101
        STA A   IOAC
EXE2    STX     CURTSK
        LDS     STACKS-2,X      LOAD NEXT TASKS STACK 
        RTI 
  
  
* INTERRUPT HANDLER 
* 
*       THE REAL TIME CLOCK IS INCREMENTED BY 1 MODULO 2**16
*       FOR EACH CLOCK INTERRUPT.  IF THE COUNT OF CLOCK TICKS
*       SINCE THE BEGINNING OF THE LAST EXECUTIVE MAJOR CYCLE 
*       EXCEEDS 255 (APROX 1 SECOND) A TASK IS ASSUMED TO BE
*       HUNGUP AND A RESET IS INITIATED.
  
INTRPT  TST     IOAD            CLEAR INTERRUPT 
        LDX     CLOCK 
        INX                     BUMP CLOCK
        STX     CLOCK 
        INC     WATCH 
        BEQ     RESET           IF WE SEEM TO BE HUNGUP 
        LDA A   CURTSK+1
        CMP A   &TSKCNT-NONPRE*2
        BLE     EXEC            IF CURRENT TASK PREEMPTABLE 
        RTI 
  
  
        PAGE
* REENTRANT SUBROUTINE BEEP 
* 
*       ACKNOWLEDGE VIA MORSE CODE. ON ENTRY (A) IS ENCODED CHARACTER.
*       ON EXIT (A) IS ZERO, (B) IS PRESERVED.
  
BEEP    PSH B 
        LDA B   &BPTONE         SELECT FREQUENCY
        BSR     CODE
        PUL B                   RESTORE (B) 
        RTS 
  
  
* REENTRANT SUBROUTINE CODE-SENDER
* 
*       MORSE CODE IS SENT VIA THE TOUCH-TONE GENERATOR.  THE 
*       SNDING INTERLOCK INSURES CONTIGUOUS CODE IF CALLS ARE 
*       MADE WITH NO INTERVIENING SWI.
*       ON ENTRY (A) IS AN ENCODED MORSE CHARACTER, (B) IS
*       TOUCH TONE BUTTON PATTERN FOR DESIRED TONE.  ON EXIT
*       (B) IS PRESERVED, (A) IS ZERO.
  
* INTERRLOCK
  
CODE    INC     XMIT
COD0    TST     SNDING
        BEQ     COD1            IF SENDER AVAILABLE 
        SWI 
        BRA     COD0            WAIT FOR OTHER TASK TO FINISH 
COD1    INC     SNDING
  
* SEND CHARACTER
  
COD2    LSR A 
        BEQ     COD4            IF END OF LETTER
        STA B   TTOD            START TONE
        PSH A 
        LDA A   &DITLEN 
        BCC     COD3            IF DIT NEXT 
        LDA A   &3*DITLEN 
COD3    BSR     DELAY 
        CLR     TTOD            STOP TONE 
        LDA A   &DITLEN 
        BSR     DELAY 
        PUL A 
        BRA     COD2
  
* FINISH UP 
  
COD4    LDA A   &2*DITLEN       LETTER SPACE
        BSR     DELAY 
        DEC     SNDING
        DEC     XMIT
        RTS 
  
  
* REENTRANT SUBROUTINES DELAY, PAUSE
* 
*       KILL TIME FOR (A) CLOCK TICKS.  EXECUTIVE LOOP CYCLE TIME 
*       NEED NOT BE FASTER THAN THE CLOCK.  ON EXIT (A) IS ZERO,
*       (B) IS PRESERVED.  ENTRY PAUSE WILL DELAY 1 SECOND. 
  
PAUSE   CLR A 
DELAY   PSH B 
        LDA B   CLOCK+1         START TIME
DEL1    SWI 
DEL2    CMP B   CLOCK+1 
        BEQ     DEL1            IF SAME TIME
        INC B 
        DEC A 
        BNE     DEL2            LOOP UNTIL TIME IS UP 
        PUL B 
        RTS 
  
  
* REENTRANT SUBROUTINES ON, OFF 
* 
*       SELECTIVLY MANIPULATE OUTPUT LINES SELECTED BY (A). 
*       ON EXIT (A) IS DESTROYED. 
  
ON      ORA A   IOBD            OR IN BIT 
        BRA     OFF1
OFF     COM A 
        AND A   IOBD            MASK OFF BIT
OFF1    STA A   IOBD
        RTS 
        PAGE
* TASK COR
* 
*       CARRIER OPERATION AND THREE MINUTE TIMER. 
  
* WAIT FOR CARRIER
  
COR     SWI 
        TST     IOAD
        BPL     COR             WAIT FOR CARRIER
        LDA A   &BOFF 
        BIT A   IOBD
        BNE     COR             IGNORE CARRIER IF OUT OF SERVICE
        LDA A   &BTRN 
        BSR     ON              TRANSMIT ON 
  
* PAUSE FOR CARRIER DELAY (SHORT TRANSMISSIONS ONLY)
  
COR1    BSR     PAUSE 
        TST     IOAD            SENSE SHORT TRANSMISSION
        BPL     COR5
        LDA A   &6              RESET POKE COUNTER
        STA A   POKE
COR5    DEC     POKE
        BPL     COR4            IF NOT MAD YET
        LDA A   &^11011         MORSE Q 
        BSR     BEEP
        LDA A   &^10100         MORSE F 
        BSR     BEEP
        LDA A   &^110           MORSE A 
        JSR     BEEP
  
* WAIT FOR CARRIER DROP OR TIMEOUT, SAMPLE FREQUENCY
  
COR4    LDA A   CLOCK           START THREE MINUTE TIMER
        ADD A   &3*60/CSPD
        CLR B 
COR2    SWI 
        TST     IOAD
        BPL     COR8            IF CARRIER HAS DROPED 
        TST     CLOCK+1 
        BNE     COR7
        ORA B   IOAD            SAMPLE FREQ AT REGULAR INTERVALS
COR7    CMP A   CLOCK 
        BNE     COR2            IF NOT YET TIMED OUT
        LDA A   &^11011         MORSE Q 
        JSR     BEEP
        LDA A   &BOFF           OUT OF SERVICE
        BSR     ON
        CLR     ACTIVE          HANGUP PHONE
  
* AUTO FREQUENCY NETTING RESPONSE 
  
COR8    BIT B   &BHIF+BLOF
        BEQ     COR3            IF ON FREQ
        LDA A   &500/CKPD 
        BSR     DELAY 
        LDA A   &^10000         MORSE H 
        BIT B   &BHIF 
        BNE     COR9            IF HIGH 
        LDA A   &^10010         MORSE L 
COR9    JSR     BEEP
  
* HOLD TRANSMITTER UP FOR OTHER TASKS 
  
COR3    SWI 
        LDA A   &BOFF 
        BIT A   IOBD
        BNE     COR6            IGNORE CARRIER IF OUT OF SERVICE
        TST     IOAD
        BMI     COR1            IF CARRIER IS BACK
COR6    LDA A   XMIT
        BNE     COR3            IF OTHER TASK REQUIRES TRANS
        LDA A   &BTRN 
        JSR     OFF             TURN OFF TRANSMITTER
        BRA     COR 
        PAGE
* TASK IDENTIFIER 
  
IDENT   SWI 
        LDA A   &BTRN 
        BIT A   IOBD
        BEQ     IDENT           IF NOT TRANSMITTING 
        LDX     &CALL 
        LDA A   0,X             GET FIRST CHAR
        LDA B   &IDTONE 
IDE1    JSR     CODE
        INX                     GET NEXT CHAR 
        LDA A   0,X 
        BNE     IDE1            IF NOT END OF TABLE 
        LDA B   CLOCK 
        ADD B   &4*60/CSPD      4 MINUTES 
IDE2    SWI 
        CMP B   CLOCK 
        BNE     IDE2            IF NOT YET TIME TO ID 
        BRA     IDENT 
  
  
* REPEATER IDENTIFICATION 
  
CALL    FCB     ^1
        FCB     ^1001           D 
        FCB     ^10             E 
        FCB     ^1
        FCB     ^1
        FCB     ^1110           W 
        FCB     ^1010           R 
        FCB     ^101111         9 
        FCB     ^110            A 
        FCB     ^10101          C 
        FCB     ^10011          Z 
        FCB     ^1
        FCB     0 
        PAGE
* TASK RINGER 
* 
*       THIS TASK SIGNALS WITH A MORSE CODE 5 WHENEVER AN INCOMMING 
*       CALL IS DETECTED.  NOTE, THE STRUCTURE OF COR WILL PREVENT
*       SPONTAINOUS OPERATION OF THE REPEATER.
  
RINGER  SWI 
        LDA A   &BRNG 
        BIT A   IOAD
        BEQ     RINGER          IF NOT RINGING
        LDA A   &^100000        MORSE 5 
        JSR     BEEP
        JSR     PAUSE 
        BRA     RINGER
        PAGE
* TASK DIAL-PULSER
* 
*       THE PATCH IS CONNECTED ACCORDING TO THE PATCH ACTIVITY FLAG.
*       DIGITS ARE REMOVED FROM THE DIGIT QUEUE 1 SECOND AFTER
*       THE FIRST DIGIT APPEARS.  IF THE PATCH IS ACTIVE, 
*       THE CONNECTION IS BROKEN TO PULSE THE LINE, OTHERWISE 
*       THE DIGIT IS IGNORED.  PATCH AUDIO IS MUTED DURRING DIALING 
*       AND WHEN CARRIER IS PRESENT.
  
* WAIT FOR PATCH ACTIVITY 
  
DIA0    LDA A   &BCON+BLSN
        JSR     OFF 
DIAL    SWI 
        LDA A   ACTIVE
        BEQ     DIAL            IF INACTIVE 
        LDA A   &BCON           CONNECT PATCH 
        JSR     ON
  
* WAIT FOR DIGIT, CONTROL AUDIO MUTING
  
DIA4    SWI 
        LDA A   &BLSN 
        TST     IOAD
        BMI     DIA5            IF CARRIER, THEN MUTE 
        JSR     ON
        CLR A 
DIA5    JSR     OFF 
        LDA A   ACTIVE
        BEQ     DIA0            IF WE'VE HUNGUP 
        LDX     DIGITS
        BEQ     DIA4            WAIT FOR DIGITS 
        JSR     PAUSE 
  
* GET NEXT DIGIT FROM QUEUE 
  
DIA1    LDX     DIGITS          CHECK QUEUE 
        BEQ     DIA4            IF DONE DIALING 
        DEX 
        STX     DIGITS
        LDA B   QUEUE           GET DIGIT 
        LDX     &$FFFF          -1
DIA2    LDA A   QUEUE+2,X       MOVE QUEUE DOWN 
        STA A   QUEUE+1,X 
        INX 
        CPX     DIGITS
        BNE     DIA2
  
* PULSE CONNECTION FOR DIGIT
  
DIA3    LDA A   ACTIVE
        BEQ     DIA1            IF HUNGUP WHILE DIALING 
        LDA A   &BCON+BLSN      DISCONNECT PHONE AND AUDIO
        JSR     OFF 
        LDA A   &33/CKPD        10HZ, 33 PCT DUTY CYCLE 
        JSR     DELAY 
        LDA A   &BCON           LEAVE AUDIO MUTED 
        JSR     ON
        LDA A   &67/CKPD
        JSR     DELAY 
        DEC B                   COUNT PULSES
        BNE     DIA3            IF PULSES REMAINING 
        LDA A   &600/CKPD       600 MSEC INTER-DIGIT
        JSR     DELAY 
        BEQ     DIA1
        PAGE
* TASK CONTROL
* 
*       TOUCH TONE CONTROL FUNCTION PROCESSING AND AUTO-PATCH 
*       SUPERVISION.
  
CONTRL  JSR     GETDGT
        BEQ     CONTRL          IGNORE TIMEOUT
        LDA A   &BOFF 
  
* OUT OF SERVICE
  
CON1    CPX     &$1242
        BNE     CON2
        JSR     ON
        BRA     CON7
  
* IN SERVICE
  
CON2    CPX     &$4422
        BNE     CON3
        JSR     OFF 
        BRA     CON7
  
* COMPLETE SHUTDOWN (NOT ACKNOWLEDGED)
  
CON3    CPX     &$1824
        BNE     CON4
        STA A   IOBD
        SEI                     STOP CLOCK AND HALT 
        BRA     * 
  
* PROGRAM AUTO-PATCH ACCESS 
  
CON4    CPX     &$4421
        BNE     CON5
        LDA A   &BPRV           CHECK PRIVILEGE 
        BIT A   IOAD
        BEQ     CONTRL          IF NOT PRIVILEGED 
        LDX     &0
        STX     ASMBLY
        BSR     GETDGT
        BSR     GETDGT
        BSR     GETDGT
        STX     ACCESS          UPDATE ACCESS CODE
        BRA     CON7
  
* AUTO-PATCH ACCESS 
  
CON5    CLR B                   B=0 FOR NORMAL ACCESS 
        CPX     ACCESS
        BEQ     PATCH 
        INC B                   B=1 FOR 911 ACCESS
        CPX     &$911 
        BEQ     PATCH 
        BRA     CONTRL
  
  
* ACKNOWLEDGE CONTROL FUNCTIONS 
  
CON7    LDA A   &^1010          MORSE R 
        INC     XMIT            HOLD XMIT UP
CON9    BSR     DROP
        JSR     BEEP            SEND ACKNOWLEDGEMENT
        DEC     XMIT            DROP XMIT 
        BRA     CONTRL
  
* CONNECT PATCH 
  
PATCH   LDA A   &BOFF 
        BIT A   IOBD
        BNE     CONTRL          IF OUT OF SERVICE 
        INC     XMIT
        STA B   A911
        BSR     DROP
        LDA A   &^10001         MORSE B 
        LDA B   &BUSE 
        BIT B   IOAD
        BNE     CON9            IF PHONE IN USE 
        LDA A   &^10101         MORSE C 
        JSR     BEEP
        INC     ACTIVE          CONNECT PATCH 
  
* PROCESS DIGITS FOR PATCH
  
PAT2    BSR     GETDGT
        BEQ     PAT3            IF TIMED OUT
        LDA B   A911
        BNE     PAT3            IF ACCESSED VIA 911 
        CPX     &$12
        BEQ     PAT3            IF DISCONNECT CODE
        CMP A   &10 
        BGT     PAT2            IF NON-DIALABLE DIGIT 
  
* QUEUE DIGIT FOR DIAL PULSER 
  
        LDX     DIGITS
        CPX     &QUELEN 
        BEQ     PAT3            IF QUEUE IS FULL
        STA A   QUEUE,X 
        INX                     POST INCREMENT QUEUE POINTER
        STX     DIGITS
        BRA     PAT2
  
* DISCONNECT PATCH
  
PAT3    CLR     ACTIVE
        LDA A   &^1111          MORSE O 
        BRA     CON9
  
  
* SUBROUTINE DROP 
* 
*       WAITS FOR INPUT CARRIER TO DROP.  (A) AND (B) ARE 
*       PRESERVED.
  
DROP    SWI 
        TST     IOAD
        BMI     DROP            IF CARRIER STILL THERE
        PSH A 
        LDA A   &500/CKPD       1/2 SECOND
        JSR     DELAY 
        PUL A 
        RTS 
  
  
* SUBROUTINE GET-DIGIT
* 
*       GET DIGIT WAITS FOR AND RETURNS IN (A) THE NEXT ENTERED TOUCH-
*       TONE DIGIT.  THE DIGIT IS ALSO SHIFTED INTO THE CODE NUMBER 
*       ASSEMBLY IN THE INDEX REGISTER.  A CARRIER DROP CLEARS THIS 
*       ASSEMBLY.  IF CARRIER IS NOT PRESENT FOR AN EXTENDED
*       PERIOD OF TIME GET DIGIT WILL TIME OUT RETURNING ZERO.
*       ON EXIT (B) IS DESTROYED. 
  
GETDGT  SWI 
        BSR     READTT
        BNE     GETDGT          WAIT FOR PREVIOUS TONE TO STOP
GET1    LDA B   CLOCK           START TIMER 
        ADD B   &3*60/CSPD      3 MINUTES 
GET2    SWI 
        LDA A   &BCAR+BPRV
        BIT A   IOAD
        BEQ     GET4            IF NEITHER CARRIER PRESENT
        BSR     READTT
        BEQ     GET1            IF NOT DIGIT YET
        LDA B   ASMBLY
        BIT B   &$F0
        BNE     GET5            IF ASSEMBLY FULL
        LDA B   &4
GET3    ASL     ASMBLY+1        LEFT SHIFT ASSEMBLY 
        ROL     ASMBLY
        DEC B 
        BNE     GET3            LOOP FOR 4 BITS 
        ORA A   ASMBLY+1
        STA A   ASMBLY+1        INSERT NEW DIGIT
        AND A   &^00001111
        BRA     GET5
GET4    CLR A                   CLEAR ON CARRIER DROP 
        STA A   ASMBLY
        STA A   ASMBLY+1
        CMP B   CLOCK           CHECK FOR TIMEOUT 
        BNE     GET2
GET5    LDX     ASMBLY          RETURN ARGS 
        TST A 
        RTS 
  
  
* SUBROUTINE READ-TOUCH-TONE
  
READTT  LDX     &TTLIST         SEARCH TABLE FOR LEGAL COMBINATION
        LDA A   &TTMAX
        LDA B   TTID            READ DEVICE 
REA1    CMP B   0,X 
        BEQ     REA2            IF FOUND LEGAL CODE 
        INX 
        DEC A 
        BNE     REA1            LOOP TO END OF LIST 
REA2    TST A 
        RTS 
  
TTLIST  FCB     ^10000100       C (&) 
        FCB     ^10000001       B (*) 
        FCB     ^10000010       A (0) 
        FCB     ^01000100       9 
        FCB     ^01000010       8 
        FCB     ^01000001       7 
        FCB     ^00100100       6 
        FCB     ^00100010       5 
        FCB     ^00100001       4 
        FCB     ^00010100       3 
        FCB     ^00010010       2 
        FCB     ^00010001       1 
  
TTMAX   EQU     *-TTLIST
  
  
        END 
        FIN 
