        TITLE   'TEACH MORSE CODE'
* TEACH MORSE CODE
* COPYRIGHT (C) 1976, HOWARD CUNNINGHAM 
  
* REVISION HISTORY
* 
*       10/02/76 INITIAL VERSION ADAPTED FROM 6800
*       10/07/76 DOUBLE WEIGHT IF AVERAGE > 90 PCT. ADDED.
*       10/07/76 LETTER PROBABILITY NEVER ZERO ADDED. 
*       12/06/76 REVISED RANDOM AND REMOVED PUNCTUATION 
*                TO SAVE SPACE IN 512 BYTE ROM. 
*       03/23/77 CORRECT TYPO IN DOUBLE WEIGHT PROBABILITY. 
  
* ASSEMBLY CONSTANTS
  
LINE    EQU     62      TERMINAL LINE LENGTH
FREQ    EQU     2000    MACHINE CYCLES PER MSEC 
WPM     EQU     15      CHARACTER TRANSMISSION SPEED
IDLE    EQU     3*50    IDLE RESPONSE WAIT
MAXNUM  EQU     26+10   MAXIMUM NUMBER OF CHARACTERS
PPIM    EQU     0FH     8255 MODE SELECT
  
* MONITOR SUBROUTINE ENTRIES
  
CO      EQU     8009H   COMMAND OUTPUT
CI      EQU     8003H   COMMAND INPUT 
CSTS    EQU     8012H   COMMAND INPUT STATUS
        EJECT 
        ORG     40H     RAM 
  
* GLOBAL DATA 
  
SEED    DW      1234H   RANDOM NUMBER (MUST BE NON-ZERO)
NUM     DW      ERROR+4 SIZE OF CURRENT ALPHABET
GIVE    DB      IDLE    RESPONSE WAIT TIME IN SEC/50
TOLD    DB      0       255 IF STUDENT WAS TOLD LETTER, 0 OTHERWISE 
COLUMN  DB      LINE    PRINT POSITIONS REMAINING ON LINE 
  
* OBJECT TIME STACK 
  
        DS      30
STACK   DS      0 
  
* ERROR RATE FUNCTION 
  
        ORG     100H    (MUST ORG AT MULTIPLE OF 100H)
ERROR   DB      255     TOTAL ERROR RATE
        DS      MAXNUM
  
* ENTRY POINT (FWA ROM) 
  
        ORG     200H
BEGIN   JMP     TEACH 
  
* CHARACTER CODE TABLES 
  
MORSE   EQU     *-1 
        DB      11011000B,11000100B,11001000B,11010000B 
        DB      11111100B,11110100B,11100100B,11110000B 
        DB      01111100B,01111000B,01101000B,01110000B 
        DB      01001000B,01010000B,01100000B,11100000B 
        DB      10000100B,10001000B,10011000B,10010000B 
        DB      10111000B,10101000B,10110000B,10100000B 
        DB      00111100B,00011100B,00101000B,00110000B 
        DB      00001100B,00000100B,00011000B,00001000B 
        DB      00010000B,00100000B,11000000B,01000000B 
  
ASCII   DB      25H     OVERALL PERCENTAGE
        DB      'Q7ZG'
        DB      '098O'
        DB      '1JPW'
        DB      'LRAM'
        DB      '6BXD'
        DB      'YCKN'
        DB      '23FU'
        DB      '45VH'
        DB      'SITE'
        EJECT 
* MAIN PROGRAM TEACH
* 
*       ENTRY VIA JUMP.  STACK POINTER IS REINITIALIZED.
*       INTERRUPTS ARE NOT USED.
  
TEACH   LXI     S,STACK 
        CALL    PRESET
TEA1    CALL    GRAPH 
TEA2    CALL    SELECT
        MVI     A,0 
        STA     TOLD    CLEAR STUDENT TOLD FLAG 
TEA3    CALL    SEND
        PUSH    D 
        CALL    CSTS    LOOK FOR ENTRY WHILE SENDING
        ANA     A 
        JZ      TEA4
        CALL    CI      DISCARD CHARACTER 
TEA4    MVI     B,0     CLEAR RESPONSE TIME COUNTER 
        MVI     C,0     CLEAR CORRECT RESPONSE FLAG 
TEA5    PUSH    B 
        CALL    RANDOM  MIX UP NUMBERS
        CALL    CSTS
        ANA     A 
        JZ      TEA6    IF NO RESPONSE YET
        CALL    CI      GET CHARACTER 
        POP     B 
        POP     D 
        CPI     0DH     CR
        JZ      TEA1    IF GRAPH COMMAND
        LXI     H,ASCII-ERROR 
        DAD     D 
        CMP     M 
        PUSH    D 
        JNZ     TEA5    IF WRONG GUESS
        MOV     C,A     SET CORRECT RESPONSE FLAG 
        JMP     TEA7
TEA6    MVI     C,20
        CALL    WAIT    KILL SOME TIME
        POP     B 
        MOV     A,B 
        INR     A 
        MOV     B,A     ADVANCE TIME COUNTER
        LDA     GIVE
        CMP     B 
        JNZ     TEA5    IF SOME TIME LEFT 
        LXI     H,TOLD
        MVI     M,255   RECORD TIMEOUT
TEA7    MOV     A,B     COMPUTE NEW SPEED 
        POP     D 
        STC 
        CMC 
        RAL             RESPONSE TIME X 2 
        JNC     TEA8
        MVI     A,255   SET TO MAXIMUM ON OVERFLOW
TEA8    LXI     H,GIVE
        MOV     B,M 
        CALL    WEIGHT  ADJUST SPEED
        MOV     M,A 
        LXI     H,ASCII-ERROR 
        DAD     D 
        PUSH    B       SAVE ANSWER 
        MOV     C,M 
        CALL    PRINT   OUTPUT CORRECT ANSWER 
        MVI     C,' ' 
        CALL    PRINT   DOUBLE SPACE
        MVI     C,250 
        CALL    WAIT
        POP     B 
        MOV     A,C 
        ANA     A 
        JZ      TEA3    IF INCORRECT, TRY IT OVER 
        CALL    GRADE 
        JMP     TEA2
        SPC      4
* SUBROUTINE PRESET 
* 
*       INITIALIZE I/O AND GLOBAL VARIABLES 
  
PRESET  LXI     H,ERROR+MAXNUM
PRE1    MVI     M,255   SET ERRORS TO MAXIMUM 
        DCR     L 
        JNZ     PRE1
        MVI     M,256*30/100 GUESS AVERAGE OF 70 PERCENT
        LXI     H,ERROR+4 
        SHLD    NUM     MINIMUM ALPHABET
        MVI     A,IDLE
        STA     GIVE    AVERAGE SPEED 
        LXI     H,1234H 
        SHLD    SEED    NON-ZERO RANDOM SEED
        MVI     A,0A6H
        OUT     PPIM    PROGRAM MODE 1 OUTPUT 
        RET 
        SPC      4
* SUBROUTINE RANDOM 
* 
*       TAUSWORTH GENERATOR USING PRIMITIVE TRINOMIAL 
*         X**15 + X + 1  WITH PERIOD 2**15 - 1. 
*       RETURNS 0 < (D,E) < 2**15.
  
RANDOM  LXI     H,SEED
        MOV     A,M 
        STC 
        CMC 
        RAL 
        MOV     D,A 
        INX     H 
        MOV     A,M 
        RAR 
        XRA     M 
        MOV     M,A 
        MOV     A,D 
        DCX     H 
        XRA     M 
        JNC     RAN1
        XRI     60H 
RAN1    MOV     M,A 
        MOV     E,A 
        RET 
        SPC      4
* SUBROUTINE SELECT 
* 
*       ON EXIT (D,E) CONTAINS A POINTER TO THE SELECTED
*       CHARACTER IN THE ERROR TABLE.  PRESERVES NO REGISTERS.
  
SELECT  CALL    RANDOM
        MOV     A,D 
        CMA             MAKE RANDOM NUMBER NEGATIVE 
        MOV     D,A 
SEL1    LHLD    NUM     BEGIN SCAN
SEL2    MOV     C,M     GET ERROR RATE
        MVI     B,0 
        INX     B       INSURE PROBABILITY IS NEVER ZERO
        XCHG
        DAD     B       ADD ERROR TO RANDOM NUMBER
        RC              STOP LOOP ON CARRY OUT
        XCHG
        DCR     L 
        JNZ     SEL2    SCAN REMAINDER OF TABLE 
        JMP     SEL1    START OVER
        SPC      4
* SUBROUTINE SEND 
* 
*       THE CHARACTER REFERENCED BY (D,E) IS SENT AS MORSE CODE.
*       ON EXIT D,E ARE PRESERVED.
  
SEND    LXI     H,MORSE-ERROR 
        DAD     D 
        MOV     B,M     GET MORSE LETTER
SEN1    MOV     A,B 
        STC 
        CMC 
        RAL             GET NEXT ELEMENT IN CARRY 
        MOV     B,A 
        MVI     C,1200/WPM      ONE DIT TIME IN MSEC
        JNC     SEN2
        MVI     C,3*1200/WPM    ONE DAH TIME
SEN2    ANA     A 
        RZ              IF LAST BIT WAS STOP BIT
        CALL    BEEP
        MVI     C,1200/WPM      INTER-ELEMENT SPACE 
        CALL    WAIT
        JMP     SEN1    LOOP FOR REMAINING BITS 
        SPC      4
* SUBROUTINE WAIT 
* 
*       DELAY C MSEC.  ON EXIT A AND C ARE ZERO,
*       ALL OTHER REGS ARE PRESERVED. 
  
WAIT    MVI     A,FREQ/16 
WAI1    DCR     A 
        JNZ     WAI1    LOOP FOR A MSEC 
        DCR     C 
        JNZ     WAIT    IF MORE MSEC TO GO
        RET 
        SPC      4
* SUBROUTINE BEEP 
* 
*       DELAY C MSEC WHILE GENERATING A 1000HZ SIDETONE.
*       OUTPUT IS ON 8255 PORT PC4. 
*       ENTRY/EXIT SAME AS WAIT.
  
BEEP    MVI     A,FREQ/16/2 
BEE1    DCR     A 
        JNZ     BEE1    LOOP FOR 1/2 MSEC 
        MVI     A,1001B SET PC4 
        OUT     PPIM    LOW TO HIGH ON OUTPUT 
BEE2    MVI     A,FREQ/16/2 
BEE3    DCR     A 
        JNZ     BEE3    LOOP FOR SECOND 1/2 MSEC
        MVI     A,1000B CLEAR PC4 
        OUT     PPIM    HIGH TO LOW ON OUTPUT 
        DCR     C 
        JNZ     BEEP    IF MORE MSECS TO GO 
        RET 
        SPC      4
* SUBROUTINE WEIGHT 
* 
*       COMPUTES A WEIGHTED MOVING AVERAGE
*       AS FOLLOWS,  A = .875 * B + .125 * A
*       ALL OTHER REGS ARE PRESERVED. 
  
WEIGHT  ADD     B 
        RAR             (A+B)/2 
        ADD     B 
        RAR             ((A+B)/2+B)/2 
        ADD     B 
        RAR             (((A+B)/2+B)/2+B)/2 
        RET 
        SPC      4
* SUBROUTINES RETURN, PRINT 
* 
*       OUTPUT CR/LF OR CHARACTER IN C. 
*       ON EXIT D,E AND A ARE PRESERVED.
  
RETURN  LXI     H,COLUMN
        MVI     M,LINE+2
        MVI     C,0DH   CR
        CALL    PRINT 
        MVI     C,0AH   LF
PRINT   PUSH    D 
        PUSH    PSW 
        CALL    CO
        POP     PSW 
        POP     D 
        LXI     H,COLUMN
        DCR     M 
        JZ      RETURN  LOCAL CR/LF 
        RET 
        SPC      4
* SUBROUTINE GRADE
* 
*       INDIVIDUAL AND TOTAL ERROR RATES ARE
*       COMPUTED.  THE SIZE OF THE ALPHABET IS
*       INCREASED IF PERFORMANCE IS ADAQUATE. 
*       ON ENTRY D,C POINTS TO CHARACTER ERROR TABLE
*       ENTRY, (TOLD) IS 0 FOR CORRECT OR 255 FOR INCORRECT.
  
GRADE   LDA     TOLD
        XCHG
        MOV     B,M 
        CALL    WEIGHT  ADJUST INDIVIDUAL RATE
        MOV     M,A 
        XCHG
        LXI     H,ERROR 
        LDA     TOLD
        MOV     B,M 
        CALL    WEIGHT  ADJUST AVERAGE RATE 
        MOV     M,A 
        CPI     256*30/100
        JNC     GRA3    IF BAD AVERAGE
        CPI     256*10/100
        JNC     GRA0    IF GOOD, BUT NOT GREAT
        XCHG
        MOV     B,M 
        LDA     TOLD
        CALL    WEIGHT  COUNT SCORE TWICE IF HOT
        MOV     M,A 
GRA0    LHLD    NUM 
        MVI     A,256*40/100
GRA1    CMP     M 
        JC      GRA3    IF BAD INDIVIDUAL RATE
        DCR     L 
        JNZ     GRA1
GRA2    LXI     H,NUM   CHECK FOR COMPLETE ALPHABET 
        MVI     A,MAXNUM
        CMP     M 
        JZ      GRA3
        INR     M       ADD LETTER
GRA3    RET 
        SPC      4
* SUBROUTINE GRAPH
* 
*       THE PREDICTOR FUNCTION IS DISPLAYED.
*       ALL REGISTERS ARE DESTROYED.
  
GRAPH   LHLD    NUM 
        XCHG
GPH1    CALL    RETURN
        LXI     H,ASCII-ERROR 
        DAD     D 
        MOV     C,M     GET ASCII FOR CURRENT CHARACTER 
        CALL    PRINT 
        MVI     C,' ' 
        MOV     H,D 
        MOV     L,E 
        MOV     A,M     B IS ERROR RATE 
GPH2    CALL    PRINT   PRINT BAR GRAPH 
        MVI     C,'*' 
        SUI     255/LINE+1
        JNC     GPH2    IF A IS STILL POSITIVE
        MVI     C,250 
        CALL    WAIT    SLOW DOWN FOR FAST DISPLAYS 
        DCR     E 
        JP      GPH1    LOOP FOR ALL BARS 
        CALL    CI
        JMP     RETURN
  
        END 
