
DOWNLOAD

\ Filename: lbk332.f
\ Author: jack j. woehr jax@well.UUCP JAX on GEnie SYSOP, RCFB (303) 278-0364
\ Copyright (c) 1991, Vesta Technology, Inc.
\ ALL RIGHTS RESERVED.
\ Platform: SBC332 w/ VFSE
\ Purpose: Primitives & exercise LBK332 board.
\ Dependencies: Platform; W@ W! (16-bit ops)
\               TRUE FALSE 0<> from Core Extensions
\               YREG332.F and QSM332.F must be loaded
\               Some code meant to execute only in Supervisor mode.
\ References: MC68332 USER'S MANUAL [MC68332UM/AD] Motorola, 1990
\             GE Solid State Data Book SSD-260C Printed 12-87 [GE-SSD]
\ $Log:   V:/vestasrc/forth/68332/tpuqsm/vcs/lbk332.f_v  $
\ 
\    Rev 1.6   29 Jul 1992 16:15:28   jax
\ fixed stack diagrams
\ 
\    Rev 1.5   14 Jul 1992 11:24:38   jax
\ cleanup edits
\ 
\    Rev 1.4   01 Jul 1992 13:01:14   jax
\ added delays and extra test words
\ 
\    Rev 1.3   11 Jun 1992 15:11:02   jax
\ Added KEYPAD-DISABLE to LCD prims
\ 
\    Rev 1.2   11 Jun 1992 14:38:52   jax
\ Added LCD and Keypad control
\ 
\    Rev 1.1   10 Jun 1992 17:02:50   jax
\ added functionality
\ 
\    Rev 1.0   09 Jun 1992 16:40:48   jax
\ Initial revision.

\

BASE @
HEX

\
\ ** Utilities

\ Kludgy delays, may have to be adjusted when PAUSE is implemented.
\ Reason for this delay: 1) Receive RAM doesn't seem to be written
\ yet even when SPI says it's done in the SPSR.SPIF register, and
\ 2) This stuff seems to be too fast for the LCD display.

: 20-MS ( --)
    2000 0 DO ( PAUSE) LOOP ;

: 100-MS ( --)
    10000 0 DO ( PAUSE) LOOP ;

\
\ ** Setting up for QSPI for the LBK332
\ These routines can serve as models for other types of QSPI setup,
\ though actual values, e.g., baud, int vects & int levels might be
\ different in a different application. The ones here are specific
\ to the CDP68HC68P1 used on the LBK332.

\ [MC68332UM/AD] 5.4.3.1
\ Write first to set output state. Specifically, we had better make
\ sure that the LBK332 Chip Select is not active (low) (PCS0/_SS).
: QPDR-SETUP ( --) QPDR.PCS0/_SS QPDR TRUE SET-YREG ;

\ [MC68332UM/AD] 5.4.3.3
\ Then configure direction bits MISO input, PCS0 MOSI output
: QDDR-SETUP ( --)
    QDDR.MISO QDDR FALSE SET-YREG
    QDDR.PCS0/_SS QDDR.SCK OR QDDR.MOSI OR QDDR TRUE SET-YREG
;

\ [MC68332UM/AD] 5.5.4.6
\ Init RAM
: QSPI-RAM-INIT ( --) ;

\ [MC68332UM/AD] 5.4.3
: QPAR-BITS ( chip-sel-mask --)
    [ QPAR.PCS0/_SS QPAR.PCS1 OR QPAR.PCS2 OR QPAR.PCS2 OR ] LITERAL
    DUP ROT AND                 \ constrain chip select mask
    SWAP INVERT QPAR W@ AND     \ NAND off CS bits in current reg mask
    OR                          \ OR in new chip select mask
    QPAR.MOSI QPAR.MISO OR OR   \ OR in these bits
    QPAR W!                     \ store new mask
;

\ [MC68332UM/AD] 5.5.4.1 .. Set up as master of 8 bit xfers, 2.1MHz,
\ Data changes on leading edge, sampled on falling edge.
: SPCR0-SETUP ( --)
    SPCR0.MSTR                  \ SBC332 is master
    8 >SPCR0.BITS LSHIFT OR     \ CDP68HC68P1 is 8 bit xfers
    SPCR0.CPHA OR               \ [GE-SSD] pg. 537 Fig. 3
    FF OR                       \ SPCR0.SPBR 33 KHz frequency (Table 5-9)
    SPCR0 TRUE SET-YREG         \ install mask register
;

\ [MC68332UM/AD] 5.5.4.2 .. Set up but don't start up
: SPCR1-SETUP ( --)
    SPCR1.DSCKL >SPCR1.DSCKL LSHIFT
    SPCR1.DTL OR SPCR1.SPE OR SPCR1 FALSE SET-YREG
;

\ [MC68332UM/AD] 5.5.4.3 .. Reads to this register get
\ actual reg contents, not necessarily last-written which
\ latter is buffered during serial xfer, taking effect next xfer.
\ We setup here for no interrupts, no wraparound, etc.
\ Of course, application will change this ... this is just init,
\ and is powerup default.
: SPCR2-SETUP ( --) 0 SPCR2 W! ;

\ [MC68332UM/AD] 5.5.4.4 .. We don't need any of this stuff.
: SPCR3-SETUP ( --) 0 SPCR3 W! ;

\ ** Setup of QSM in order prescribed by [MC68332UM/AD] 5.4.1
: QSM-SETUP ( --)
    FALSE QSM-SUPERVISOR
    1 QSM-IARB!
    FALSE QSM-STOP
    FALSE QSM-FREEZE
    40 QIVR W!
    1 1 QSM-INT-LEVEL
    QPDR-SETUP
    QDDR-SETUP
    QSPI-RAM-INIT
    QPAR.PCS0/_SS QPAR-BITS
    SPCR0-SETUP
    SPCR1-SETUP
    SPCR2-SETUP
    SPCR3-SETUP
;

\ Set QSPI a-runnin'
: QSPI-START ( --) SPCR1.SPE SPCR1 TRUE SET-YREG ;

\ Orderly QSPI shutdown
: QSPI-SHUTDOWN ( --)
    SPCR3.HALT SPCR3 TRUE SET-YREG
    BEGIN ( PAUSE) SPSR W@ SPSR.HALTA AND 0<> UNTIL
    SPCR1.SPE SPCR1 FALSE SET-YREG
;

\ Clear a HALT condition
: UNHALT ( --) SPCR3.HALT SPCR3 FALSE SET-YREG ;

\ Return indicates of QSPI was inactive and thus able to conduct
\ one two-byte transaction. Presumes only PCS0/_SS from among the
\ chip selects is assigned to QSPI; otherwise, the command masks
\ should contain appropriate states for the other chip selects.
: LBK332! ( u1 u2 -- flag)
    SPCR1 W@ SPCR1.SPE AND 0=
    IF
        TRAN-RAM 2 + W!
        TRAN-RAM W!
        COMD-RAM.CONT COMD-RAM C!   \ PCS0/_SS low
        0 COMD-RAM 1+ C!            \ ditto
        SPCR2.NEWQP FALSE SPCR2 SET-YREG
        [ 1 >SPCR2.ENDQP LSHIFT SPCR2.ENDQP AND ]
        LITERAL SPCR2 TRUE SET-YREG
        QSPI-START
        TRUE
        20-MS       \ kludge delay for Receive RAM to get written
    ELSE
        2DROP FALSE
    THEN
;

: QSPI-DONE? ( -- flag)
    SPSR W@ SPSR.SPIF AND 0<> ;

: QSPI-READY? ( -- flag)
    SPCR1 W@ SPCR1.SPE AND 0= ;

: WAIT-QSPI-DONE ( --)
    BEGIN ( PAUSE) QSPI-DONE? UNTIL ;

: WAIT-QSPI-READY ( --)
    BEGIN ( PAUSE) QSPI-READY? UNTIL ;

\ Constants for controlling the two CDP68HC68P1 chips, addressed
\ 0 and 1. Port 0 is all outputs, except for KEY*. Port 1 is an output to
\ write to the LCD, and an input to read the keypad.
\ [GE-SSD] pp. 537-539

00 CONSTANT PORT0
40 CONSTANT PORT1

00 CONSTANT DATA-REG
20 CONSTANT DIR-REG

00 CONSTANT READ
10 CONSTANT WRITE

00 CONSTANT WRITE-BITS
08 CONSTANT RESET-BITS
0C CONSTANT SET-BITS

\ These only need to be set if you want to read the compare flag
00 CONSTANT ONE-NON-MATCH
01 CONSTANT ALL-MATCH
02 CONSTANT ALL-NON-MATCH
03 CONSTANT ONE-MATCH

: PORT0-SETUP ( --)
    [ PORT0 DIR-REG WRITE WRITE-BITS OR OR OR ] LITERAL
    7F LBK332! DROP  \ port 0 all output except KEY*
;

: PORT1-IN ( --)
    [ PORT1 DIR-REG WRITE WRITE-BITS OR OR OR ] LITERAL
    00 LBK332! DROP
;

: PORT1-OUT ( --)
    [ PORT1 DIR-REG WRITE WRITE-BITS OR OR OR ] LITERAL
    FF LBK332! DROP
;

: LBK332-CONFIG ( --)
    PORT0-SETUP PORT1-IN         \ must be changed to write LCD
;

\ ** IO Port Control

\ Bits from Port 0
01 CONSTANT R/W*        \ Read/Write for LCD Port
02 CONSTANT ENLCD0      \ LCD 0 Enable
04 CONSTANT ENLCD1      \ LCD 1 Enable
08 CONSTANT ENKEY*      \ CS for the 74HC541 which reads keypad
10 CONSTANT ENBEEP*     \ Beeper enable
20 CONSTANT TONE0/RS    \ RS for LCD  .. D0 of Beeper pitch
40 CONSTANT TONE1       \ n/a for LCD .. D1 of Beeper pitch
80 CONSTANT KEY*        \ Active low when there is a keypress

05 CONSTANT TONE-SHIFT  \ Shift for pitch bitmask

\ Only reads data, discards compare mask.
: PORT0@ ( -- u)
    WAIT-QSPI-READY
    [ PORT0 DATA-REG READ OR OR ] LITERAL
    DUP LBK332! DROP
    WAIT-QSPI-DONE
    REC-RAM 2 + W@
;

\ Writes data
: PORT0! ( u --)
    WAIT-QSPI-READY
    [ PORT0 DATA-REG WRITE WRITE-BITS OR OR OR ] LITERAL
    SWAP LBK332! DROP
;

\ sets data
: PORT0-SET! ( u --)
    WAIT-QSPI-READY
    [ PORT0 DATA-REG WRITE SET-BITS OR OR OR ] LITERAL
    SWAP LBK332! DROP
;

\ resets data
: PORT0-RESET! ( u --)
    WAIT-QSPI-READY
    [ PORT0 DATA-REG WRITE RESET-BITS OR OR OR ] LITERAL
    SWAP LBK332! DROP
;

\ Only reads data, discards compare mask.
: PORT1@ ( -- u)
    WAIT-QSPI-READY
    [ PORT1 DATA-REG READ OR OR ] LITERAL
    DUP LBK332! DROP
    WAIT-QSPI-DONE
    REC-RAM 2 + W@
;

\ Writes data
: PORT1! ( u --)
    WAIT-QSPI-READY
    [ PORT1 DATA-REG WRITE WRITE-BITS OR OR OR ] LITERAL
    SWAP LBK332! DROP
;

\ ** Keypad Control
\ Enable, disable keypad reader. Necessary so that keypad data
\ doesn't trash LCD writes.
: KEYPAD-ENABLE ( --) ENKEY* PORT0-RESET! ;
: KEYPAD-DISABLE ( --) ENKEY* PORT0-SET! ;

\ Is a key currently pressed?
: PKEY? ( -- flag) PORT0@ KEY* AND 0= ;

\ @PKEY returns a mask in which D0-D2 are octal row and
\ D3-D5 are octal column. The mask is only valid if KEY*
\ is currently reading HI (i.e., a key is currently pressed).
: @PKEY ( -- mask)
    PORT1-IN KEYPAD-ENABLE PORT1@ KEYPAD-DISABLE
;

\ ** LCD Control
\ Delays may have to be written into these LCD words depending
\ upon serial clock rate. 
: LCD0-CMD! ( u --)
    KEYPAD-DISABLE
    PORT1-OUT PORT1!
    R/W* PORT0-RESET!
    TONE0/RS PORT0-RESET!
    ENLCD0 PORT0-SET!
    ENLCD0 PORT0-RESET!
    100-MS      \ kludge delay for slow LCD
;

: LCD0-DATA! ( u --)
    KEYPAD-DISABLE
    PORT1-OUT PORT1!
    R/W* PORT0-RESET!
    TONE0/RS PORT0-SET!
    ENLCD0 PORT0-SET!
    ENLCD0 PORT0-RESET!
    100-MS      \ kludge delay for slow LCD
;

: LCD1-CMD! ( u --)
    KEYPAD-DISABLE
    PORT1-OUT PORT1!
    R/W* PORT0-RESET!
    TONE0/RS PORT0-RESET!
    ENLCD1 PORT0-SET!
    ENLCD1 PORT0-RESET!
    100-MS      \ kludge delay for slow LCD
;

: LCD1-DATA! ( u --)
    KEYPAD-DISABLE
    PORT1-OUT PORT1!
    R/W* PORT0-RESET!
    TONE0/RS PORT0-SET!
    ENLCD1 PORT0-SET!
    ENLCD1 PORT0-RESET!
    100-MS      \ kludge delay for slow LCD
;

\ ** Generic LCD0 Stuph ... RTFM if this doesn't work
: LCD0-HOME ( --) 02 LCD0-CMD! ;
: LCD0-CLEAR ( --) 01 LCD0-CMD! ;

: LCD0-INIT ( --)
    38 LCD0-CMD!
    0F LCD0-CMD!
    LCD0-HOME
    LCD0-CLEAR
;

: LCD0-TYPE ( c-addr u --)
    OVER + SWAP ?DO I C@ LCD0-DATA! LOOP ;

\ ** Beeper

\ Deactivate the #@$!* beeper
: UNBEEP ( --) PORT0@ ENBEEP* OR PORT0!  ;

\ Beep at pitches 0 - 3
: BEEP ( u --)
    4 MOD TONE-SHIFT LSHIFT
    PORT0@ [ TONE0/RS TONE1 OR ] LITERAL INVERT AND
    OR ENBEEP* INVERT AND PORT0!
;

\ ** Initialize

: LBK332-SETUP ( --) QSM-SETUP PORT0-SETUP ;

\ ** Quicky Test

: TEST-LBK332 ( --)
    LBK332-SETUP LCD0-INIT
    BEGIN
        BEGIN UNBEEP PKEY? EKEY? OR UNTIL
        PKEY?
        IF
            LCD0-HOME LCD0-CLEAR
            @PKEY
            1F AND DUP 3 RSHIFT
            DUP 4 MOD BEEP
            S" Row: " LCD0-TYPE
            30 OR LCD0-DATA!
            7 AND 30 OR
            DUP 4 MOD BEEP
            S"  Column: " LCD0-TYPE
            LCD0-DATA!
            BEGIN PKEY? 0= EKEY? OR UNTIL
        ELSE
            KEY DROP UNBEEP EXIT
        THEN
    AGAIN
;

BASE !    
END-DOWNLOAD
