
;
; PROGRAM: CH07FG19.ASM
;
; AUTHOR: WHEELER, T -- DEVRY KC
;
; THIS MATERIAL MUST BE ACKNOWLEDGED IF REUSED IN WHOLE OR
; OR PART. (c) 1996 TOM A. WHEELER
;
; THIS IS A DIGITAL VFO DRIVEN BY A 68HC05K1. OUTPUT IS ON A 16x1 LINE LCD
; DISPLAY, AND INPUT IS FROM A KEYPAD W/2 SWITCHES.
;
; FREQ RANGE IS 27.500 - 29.999 MHz IN 1 KHz STEPS.
;


PA      EQU     0
PADDR   EQU     4
PB      EQU     1
PBDDR   EQU     5
TDR     EQU     8               ;TIMER DATA REG
TCR     EQU     9               ;TIMER CONTROL REG

;
;KEYBOARD SCAN RETURN VALUES
;

UP      EQU     40H
DOWN    EQU     80H
FAST    EQU     20H

;
;CENTER OPERATING FREQUENCY

CENTER  EQU     !28000


        ORG     $E0             ;RAM STARTS HERE

;
;*** SYSTEM VARIABLES ***
;

TEMP1   DB      0
TEMPX   DB      0
TEMPA   DB      0
CURSOR  DB      0               ;CURRENT CURSOR LOCATION (0-15)
COUNTL  DB      0               ;USED FOR DELAY ROUTINE

N1      DW      0               ;USED FOR 16-BIT SUBTRACT
N2      DW      0

VALUE   DW      0               ;USED FOR 16-BIT SHIFT OUT TO PLL

FREQ    DW      0               ;CURRENT FREQUENCY IN KHz

;
;*** FAKE CODE AREA FOR SELF-MODIFYING INSTRUCTIONS ***
;

FAKE:   DW      0
        DW      0
        DW      0               ;6 BYTES ALLOWED HERE

;
; ------ MASK OPTION REGISTER -----
;


        ORG     MOR
        DB      28H             ;2-PIN RC OSC OPTION


;
;
; ----- ROM PROGRAM MODULE -----
;
;
        ORG     ROM

RESET:  RSP                     ;RESET STACK POINTER
        LDA     #0FFH
        STA     PADDR           ;PORT A IS ALL OUTPUT PINS
        LDA     #04H            ;DISABLE ALL CHIPS ON THIS PORT
        STA     PA
        JSR     INIT            ;INITIALIZE LCD

;
;FAKE DATA WRITE TO WAKE UP MC145170 PLL
;
        LDX     #!8
        JSR     PLL_TX

;
;SET MC145170 CONFIGURATION TO $E3
;
        LDA     #0E3H
        STA     VALUE
        LDX     #!8             ;CONFIG IS 8 BITS LONG.
        JSR     PLL_TX          ;CONFIG = $E3

;
;SEND REFERENCE DIVISOR. NOTE THAT DIVISOR IS SHIFTED LEFT ONCE IN
;MEMORY BECAUSE IT IS NOT 16 BITS LONG!
;

        LDA     #4FH
        STA     VALUE
        LDA     #60H		;$4F60 = 2 * 10,160 = 2 * R
        STA     VALUE+1
        LDX     #!15            ;REFERENCE IS 15 BITS LONG.
        JSR     PLL_TX

;
;MAIN PROGRAM. SET FREQUENCY TO 28.000 MHz; THEN USE UP/DOWN ARROWS TO
;MODIFY.
;

MAIN:   JSR     CLS

        LDA     #{CENTER & $FF}
        STA     FREQ+1
        LDA     #{CENTER > 8}
        STA     FREQ          ;FREQ = CENTER

LOOP:   JSR     HOME
        LDX     FREQ
        LDA     FREQ+1
        JSR     P_INT           ;PRINT FREQ
        LDA     #{STR1 & $FF}
        LDX     #{STR1 > 8}
        BSR     PRTSTG          ;PRINT UNITS (KHz)

        LDA     FREQ
        STA     VALUE
        LDA     FREQ+1
        STA     VALUE+1
        LDX     #!16
        JSR     PLL_TX          ;UPDATE PLL UNIT W/FREQUENCY DATA

WAIT:   JSR     KEYBD
	TAX
        AND     0C0H		;IGNORE "FAST" KEY
        BEQ     WAIT            ;WAIT FOR A KEYPRESS

	TXA
        AND     #FAST		;SEE IF "FAST" IS DEPRESSED
        BEQ     SLOW		;
        LDA     #!10		;"FAST" PRESSED MEANS 10 KHz STEP
        BRA     S2
SLOW:   LDA     #1		;"FAST" NOT PRESSED, USE 1 KHz STEPS
S2:     STA     N2+1
        CLRA
        STA     N2		

        LDA     FREQ		;LOAD CURRENT FREQUENCY INTO 16-BIT
        STA     N1		;ADD/SUBTRACT MAILDROP
        LDA     FREQ+1
        STA     N1+1


        JSR     KEYBD           ;GET THE KEY JUST STRUCK BY USER
        AND     #0C0H

        CMP     #UP		;IF "UP", ADD THE SPECIFIED FREQUENCY
        BNE     BUMP_DOWN	;STEP

;
;BUMP FREQ REGISTER UP
;
        JSR     ADD16           ;FREQ+=STEP;
        BRA     UPDATE

;
;BUMP FREQ REGISTER DOWN
;

BUMP_DOWN:
        JSR     SUB16           ;FREQ-=STEP;

UPDATE: LDA     N1		;UPDATE FREQUENCY REGISTER WITH SUBTRACTION
        STA     FREQ		;RESULT
        LDA     N1+1
        STA     FREQ+1
        LDX     #08H
        JSR     DELAY           ;CHEESY DEBOUNCER & DELAY
        BRA     LOOP            ;UPDATE FREQUENCY DISPLAY & PLL UNIT




;
;LCD DRIVER ROUTINES FOR OPTREX 16x1 DISPLAY UNIT
;
;

;
;PRINT STRING @ CURRENT CURSOR LOCATION.
;
;ENTRY: A=LSB STRING ADDRESS
;       X=MSB STRING ADDRESS
;
;STRING IS ASCII-Z. (00 TERMINATES STRING)
;
;EXIT: A,X DESTROYED.
;      THE STRING IS PRINTED.

LDVCT:  LDA     1000H           ;FAKE EXTENDED MODE INSTRUCTION
        RTS

PRTSTG: STA     TEMPA
        STX     TEMPX
        CLRX
P1:     LDA     LDVCT,X
        STA     FAKE,X
        INCX
        CPX     #4              ;MOVE 4 BYTES OF DATA
        BNE     P1
        LDA     TEMPA           ;ADDRESS LSB
        STA     FAKE+2
        LDA     TEMPX
        STA     FAKE+1          ;ADDRESS MSB

;
;*** OUTPUT THE STRING ***
;

P2:     JSR     FAKE            ;FETCH A BYTE
        BNE     P3              ;PRINT IF NON-ZERO
        RTS

P3:     JSR     CHROUT          ;PRINT IT
        INC     FAKE+2          ;INC LSB
        BNE     P2              ;NO CARRY, ETC
        INC     FAKE+1
        BRA     P2


;
;CURSOR ADDRESS TABLE FOR 16x1 DISPLAY
;

CTBL:   DB      80H,81H,82H,83H,84H,85H,86H,87H,0C0H,0C1H,0C2H,0C3H
        DB      0C4H,0C5H,0C6H,0C7H


HOME:   CLR     CURSOR
        BRA     E4
;
;TRANSMIT A CHARACTER TO THE LCD IN THE A-REGISTER.
;

CHROUT: STA     TEMPA
        STX     TEMPX
        CMP     #0CH            ;"CLS" CHAR?
        BEQ     CLS
        CMP     #0DH
        BEQ     HOME

;
;SEND CHARACTER
;
        BSET    1,PA            ;"RS"=1 FOR DATA
        BSR     LCDTX2          ;TRANSMIT THE CHARACTER

;
;MOVE CURSOR TO NEXT PLACE ON DISPLAY
;
        INC     CURSOR          ;GET NEXT CURSOR LOCATION
        BCLR    4,CURSOR        ;IT'S MOD 16
E4:     LDX     CURSOR
        LDA     CTBL,X          ;GET CURSOR VALUE
        BCLR    1,PA            ;"RS"=0 FOR CURSOR CONTROL
        BSR     LCDTX2          ;TRANSMIT CURSOR ADDRESS & RETURN
E5:     LDA     TEMPA
        LDX     TEMPX
        RTS

;
;CLEAR DISPLAY
;
CLS:    BCLR    1,PA            ;"RS"=0 FOR COMMAND MODE
        LDA     #01             ;COMMAND:CLEAR DISPL
        BSR     LCDTX2
        LDX     #7
        BSR     DELAY
        CLR     CURSOR
        BRA     E5


;
;CLEAR DISPLAY & INITIALIZE. CURSOR POSITIONED TO HOME.
;
;PORT A DDR MUST BE SET DURING POWER ON INITIALIZATION!
;


INIT:   LDA     #04H
        STA     PA              ;"E" & "RS" (D0, D1) --> 0

        LDA     #3
        STA     TEMP1

;
;THIS CODE SENDS THE "8-BIT INTERFACE" COMMAND REPEATEDLY ON D4-D7.
;THIS GETS THE ATTENTION OF THE LCD MODULE. SYNCHRONIZATION MUST BE
;OBTAINED FOR THE 4-BIT TRANSFERS TO COME.
;
I_LOOP: LDX     #7
        JSR     DELAY
        LDA     #30H
        BSR     LCDTX
        DEC     TEMP1
        BNE     I_LOOP
        LDX     #1
        JSR     DELAY

 ;
 ;NOW THAT SYNC HAS BEEN OBTAINED, SET UNIT FOR 4-BIT INTERFACE
 ;
        LDA     #20H            ;4-BIT I/F
        BSR     LCDTX

        LDA     #28H            ;16 CHARACTER DISPLAY
        BSR     LCDTX2


        LDA     #0CH
        BSR     LCDTX2          ;DISPLAY ON, CURSOR OFF, CURSOR=NON-BLINK
        LDA     #01             ;CLEAR DISPLAY & HOME CURSOR
        BSR     LCDTX2
        CLR     CURSOR
        LDX     #7              ;NEED 2 mS DELAY ON "CLS"
        BSR     DELAY
        LDA     #06             ;SET ENTRY MODE (INCREMENT CURSOR)
        BSR     LCDTX2
        BRA     E5


;
;SUBROUTINE: LCDTX2
;
;FUNCTION: TRANSMITS A BYTE IN .A TO THE LCD BY TWO CONSECUTIVE 4-BIT
;TRANSFERS.
;

LCDTX2: STA     TEMP1
        BSR     LCDTX           ;SEND THE MS NIBBLE
        LDA     TEMP1
        LSLA
        LSLA
        LSLA
        LSLA

;FALL THROUGH TO "LCDTX" FOR 2nd NIBBLE...

;
;SUBROUTINE: LCDTX(A)
;
;FUNCTION: TRANSMITS A CHARACTER (CONTROL OR DATA) TO DISPLAY, USING "E"
;TO CLOCK.
;
;THE 4-BIT "HALF-CHARACTER" IS IN THE A-REGISTER. X IS
;DESTROYED.
;

LCDTX:  TAX                     ;SAVE 4-BIT CHARACTER A MOMENT...
        LDA     #0FFH           ;PORT A IS TEMPORARILY AN OUTPUT...
        STA     PADDR
        LDA     PA
        AND     #$0F            ;DISCARD D4..D7 OF OLD PORT CONTENT
        STA     PA

        TXA                     ;RECALL HALF-CHARACTER
        AND     #$F0            ;DISCARD D0..D3
        ORA     PA              ;"OR" W/PA OLD CONTENTS
        STA     PA              ;** DATA OUTPUT TO PORT A HERE **

        BSET    0,PA            ;"E"=1
        NOP
        NOP                     ;DELAY A BIT
        BCLR    0,PA            ;"E"=0

        LDX     #30
LTX1:   DECX
        BNE     LTX1            ;DELAY FOR PROCESSING
        RTS



;
;DELAY(X)
;
;PRODUCE DELAY SET IN .X REGISTER.
;
;DELAY VALUE = 262*X + 17, INCLUDING JSR EXTENDED INSTRUCTION, AND RTS.
;
;TO GET A DESIRED # OF CYCLES, X=(T-17c)/(262c) WHERE c='CYCLE TIME'
;                              AND T=THE DESIRED DELAY, IN 'CYCLES'.
;

DELAY:  CLR     COUNTL
DELAY1: DEC     COUNTL
        BNE     DELAY1
        DECX
        BNE     DELAY1
        RTS

;
; *** DECIMAL OUTPUT ROUTINE. NUMBER SHOULD BE STORED IN X(MSB), A(LSB).
;     VALUE WILL BE DESTROYED. ***
;
;

PTABLE: DW      !10000
        DW      !1000
        DW      !100
        DW      !10
        DW      !1
        DW      !0              ;MARKS END-OF-TABLE

P_INT:  STX     N1
        STA     N1+1
        LDX     #0              ;POINT @ PTABLE
PLP1:   LDA     PTABLE,X
        STA     N2
        LDA     PTABLE+1,X
        STA     N2+1
        ORA     N2
        BNE     PLP2
        RTS

PLP2:   LDA     #'0'
        STA     TEMP1           ;CHAR TO COMPUTE
PLP2A:  BSR     SUB16
        BCS     P_PRINT
        INC     TEMP1
        BRA     PLP2A

P_PRINT:
        BSR     ADD16
        LDA     TEMP1
        JSR     CHROUT
        INCX
        INCX
        BRA     PLP1

;
;SUB16 : SUBTRACTS N2 CONTENTS FROM N1. N2 IS UNDISTURBED. SETS CARRY
;       IF APPROPRIATE.  N1 = N1 - N2
;

SUB16:  LDA     N1+1
        SUB     N2+1
        STA     N1+1
        LDA     N1
        SBC     N2
        STA     N1
        RTS

;
;ADD16: ADDS N2 CONTENTS TO N1. N1 = N1 + N2
;

ADD16:  LDA     N1+1
        ADD     N2+1
        STA     N1+1
        LDA     N2
        ADC     N1
        STA     N1
        RTS

;
;
;PLL_TX
;
;TRANSMIT A BIT-STRING TO THE PLL. X = THE NUMBER OF BITS TO SEND.
;THE LOCATIONS VALUE AND VALUE+1 HOLD THE STRING.
;
;

PLL_TX: BCLR    2,PA            ;SELECT PLL CHIP
PLL_LP: BCLR    1,PA            ;SERIAL CLOCK LOW
        LDA     PA
        AND     #7FH            ;ZERO D7 ON TRANSMIT DATA LINE
        STA     TEMP1
        LDA     VALUE
        AND     #80H            ;KEEP ONLY D7
        ORA     TEMP1
        STA     PA              ;DATA OUT TO DATA LINE
        ROL     VALUE+1
        ROL     VALUE           ;16-BIT SHIFT OF DATA
        BSET    1,PA            ;SERIAL CLOCK HIGH
        DECX
        BNE     PLL_LP
        BSET    2,PA            ;DISABLE PLL + COMPLETE TRANSFER
        RTS


;
; READ KEYBOARD. RETURNS 00 IF NO KEYS PRESSED.
;

KEYBD:  LDA     #0FH
        STA     PADDR           ;SET D4-D7 AS INPUTS...
        BSET    3,PA            ;TURN ON KEYBOARD
        LDA     PA
        AND     #0E0H            ;ISOLATE KEYS
        TAX                     ;SAVE CHARACTER
        LDA     #0FFH
        STA     PADDR           ;RESTORE PA TO ALL OUTPUTS...
        TXA                     ;RESTORE CHARACTER
        BCLR    3,PA            ;DISABLE KB
        RTS
;
; *** STRINGS ***
;

STR1:   DB      '  KHz',0



;
; *** VECTORS ***
;

        ORG     VECTORS

        DW      ROM             ;NO TIMER INTERRUPT ROUTINE
        DW      ROM             ;NO EXTERNAL IRQ SVC ROUTINE
        DW      ROM             ;NO SWI IRQ SVC ROUTINE
        DW      RESET           ;RESET VECTOR

        END




