[LISTING FOUR]

DOWNLOAD

\ Filename: 9346_332.f
\ Authors: jack woehr jax@well.UUCP JAX on GEnie SYSOP, RCFB (303) 278-0364
\ Copyright (c) 1992, Vesta Technology, Inc.
\ ALL RIGHTS RESERVED.
\ Platform: sbc332 w/ VFSE-332 with a 93C46 microWire EEPROM on SPI bus.
\ Purpose: excercise 93C46 serial EEPROM using '332 QSPI
\ Dependencies: TRUE FALSE 0<> from Core Extensions
\		YREG from file YREG332.F
\               QSM code from file QSM332.F
\               Hardware Platform
\		This code appropriate to the 64-word 93C46 EEPROM but with
\		minor modifications ( i.e., 9-BIT-XFERS etc.) it could apply
\		to any microWire device.
\ References:   MC68332 USER'S MANUAL [MC68332UM/AD. (c)Motorola, 1990]
\               HYUNDAI HY93C64 Data Sheet [HYUNDAI (C) 1986]
\ $Log:   V:/vestasrc/forth/68332/tpuqsm/vcs/9346_332.f_v  $
\    Rev 1.1   07 Aug 1992 13:01:52   jax
\ Corrected some comments.
\    Rev 1.0   06 Aug 1992 13:42:10   jax
\ Initial revision.
\

BASE @
HEX
\

\ ** Setting up for QSPI for the 93C46 MicroWire EEPROM
\ 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) (PCS2).
: QPDR-SETUP ( --) QPDR.PCS2 QPDR FALSE SET-YREG ;

\ Toggling the default state of PCS2 so we can fake a MicroWire bus.
: PCS2-HI ( --) QPDR.PCS2 QPDR TRUE  SET-YREG ;
: PCS2-LO ( --) QPDR.PCS2 QPDR FALSE SET-YREG ;

\ [MC68332UM/AD] 5.4.3.3
\ Then configure direction bits SPCR0.SPBRs MISO input, PCS2 MOSI output
\ SCK is of course an output since SBC332 is master.
: QDDR-SETUP ( --)
    QDDR.MISO QDDR FALSE SET-YREG
    QDDR.PCS2 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.PCS3 OR ] LITERAL
    DUP ROT AND                 \ constrain chip select mask
    SWAP INVERT QPAR W@ AND     \ NIMP 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 16-bit xfers, 33 KHz,
\ Data changes on leading edge, sampled on leading edge.
: SPCR0-SETUP ( --)
    SPCR0.CPOL			\ leave SCLK high when inactive 
    SPCR0 TRUE SET-YREG
    SPCR0.CPHA			\ Change leading, sample falling edge
    SPCR0 TRUE SET-YREG
    SPCR0.MSTR			\ SBC332 is master
    SPCR0.SPBR OR               \ SPCR0.SPBR 33 KHz frequency (MCUM Table 5-9)
    SPCR0 TRUE SET-YREG         \ install mask register
;
\ Switch to 9-bit xfers.
: 9-BIT-XFERS ( --)
	[ 0F >SPCR0.BITS LSHIFT ] LITERAL SPCR0 FALSE SET-YREG
	[ 09 >SPCR0.BITS LSHIFT ] LITERAL SPCR0 TRUE SET-YREG ;
\ Switch to 10-bit xfers.
: 10-BIT-XFERS ( --)
	[ 0F >SPCR0.BITS LSHIFT ] LITERAL SPCR0 FALSE SET-YREG
	[ 0A >SPCR0.BITS LSHIFT ] LITERAL SPCR0 TRUE SET-YREG ;
\ Switch to 16-bit xfers to complete a message
: 16-BIT-XFERS ( --)
    [ 0F >SPCR0.BITS LSHIFT ] LITERAL SPCR0 FALSE SET-YREG
    [ 0  >SPCR0.BITS LSHIFT ] LITERAL SPCR0 TRUE SET-YREG
;
\ [MC68332UM/AD] 5.5.4.2 .. Set up but don't start up
\ In the case of the LBK332, the defaults are acceptable
\ but we initialize here "for show".
: SPCR1-SETUP ( --)
    0 SPCR1.DSCKL AND >SPCR1.DSCKL LSHIFT
    0 SPCR1.DTL AND OR SPCR1 TRUE SET-YREG
    SPCR1.SPE 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.PCS2 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 ;

\ ** 93C46 MicroWire EEPROM
\ Return indicates of QSPI was inactive and thus able to conduct
\ one one-byte transaction. Presumes only PCS2 from among the
\ chip selects is assigned to QSPI; otherwise, the command RAM masks
\ should contain appropriate states for the other chip selects.
: MW! ( 9b -- flag)
    SPCR1 W@ SPCR1.SPE AND 0=
    IF
        2* TRAN-RAM W!
        COMD-RAM.BITSE COMD-RAM.PCS2 OR
        COMD-RAM C!   \ PCS2 high, bit select enabled, not continuous
        10-BIT-XFERS
        [ SPCR2.NEWQP SPCR2.ENDQP OR ]
        LITERAL SPCR2 FALSE SET-YREG
        QSPI-START
        TRUE
    ELSE
        DROP 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 ;

\ As above, two word message. More complicated because we have
\ to fake a Microwire 9 + 16 xfer without letting PCS2 drop between.
\ This is used in reading EEPROM cells.
: MW2!R ( 9b 16b -- flag)
    SPCR1 W@ SPCR1.SPE AND 0=
    IF
        TRAN-RAM 2 + W!
        2* TRAN-RAM W!	\ Shift left once for trailing zero bit
        COMD-RAM.PCS2 COMD-RAM.BITSE COMD-RAM.CONT OR OR
        COMD-RAM C!	\ PCS2 high, bit select enabled, continuous
        COMD-RAM.PCS2 COMD-RAM.BITSE OR
        COMD-RAM 1+ C!	\ PCS2 high, bit select enabled, not continuous
        10-BIT-XFERS
        SPCR2.NEWQP SPCR2.ENDQP OR SPCR2 FALSE SET-YREG
        [ 0 SPCR2.NEWQP AND
          0 >SPCR2.ENDQP LSHIFT SPCR2.ENDQP AND OR ]
        LITERAL SPCR2 TRUE SET-YREG
        PCS2-HI \ hand-manipulate so it doesn't fall between transactions  
        QSPI-START
        WAIT-QSPI-DONE    
        16-BIT-XFERS
        [ 1 SPCR2.NEWQP AND
          1 >SPCR2.ENDQP LSHIFT SPCR2.ENDQP AND OR ]
        LITERAL SPCR2 TRUE SET-YREG
        QSPI-START
        WAIT-QSPI-DONE
        PCS2-LO \ drop our hand-held chip select
        TRUE
    ELSE
        2DROP FALSE
    THEN
;
\ A slightly different version for writing to EEPROM cells
: MW2!W ( 9b 16b -- flag)
    SPCR1 W@ SPCR1.SPE AND 0=
    IF
        TRAN-RAM 2 + W!
        TRAN-RAM W!	\ *Don't* shift left once for trailing zero bit
        COMD-RAM.PCS2 COMD-RAM.BITSE COMD-RAM.CONT OR OR
        COMD-RAM C!	\ PCS2 high, bit select enabled, continuous
        COMD-RAM.PCS2 COMD-RAM.BITSE OR
        COMD-RAM 1+ C!	\ PCS2 high, bit select enabled, not continuous
        10-BIT-XFERS
        SPCR2.NEWQP SPCR2.ENDQP OR SPCR2 FALSE SET-YREG
        [ 0 SPCR2.NEWQP AND
          0 >SPCR2.ENDQP LSHIFT SPCR2.ENDQP AND OR ]
        LITERAL SPCR2 TRUE SET-YREG
        PCS2-HI \ hand-manipulate so it doesn't fall between transactions  
        QSPI-START
        WAIT-QSPI-DONE    
        16-BIT-XFERS
        [ 1 SPCR2.NEWQP AND
          1 >SPCR2.ENDQP LSHIFT SPCR2.ENDQP AND OR ]
        LITERAL SPCR2 TRUE SET-YREG
        QSPI-START
        WAIT-QSPI-DONE
        PCS2-LO \ drop our hand-held chip select
        TRUE
    ELSE
        2DROP FALSE
    THEN
;

\ EEPROM Constants
0100 CONSTANT _EWDS     \ erase/write disable onboard 9346
0110 CONSTANT _WRAL     \ write all for onboard 9346
0120 CONSTANT _ERAL     \ erase all for onboard 9346
0130 CONSTANT _EWEN     \ erase/write enable onboard 9346
0140 CONSTANT WR_9346   \ write mask for onboard 9346 EEPROM
0180 CONSTANT RD_9346   \ read mask for onboard 9346 EEPROM
01C0 CONSTANT _ERASE    \ erase a register for onboard 9346

\ Erase/Write enable all.
: EWEN ( --)
    WAIT-QSPI-READY
    _EWEN MW! DROP
    WAIT-QSPI-DONE
;
\ Erase/Write disable all.
: EWDS ( --)
    WAIT-QSPI-READY
    _EWDS MW! DROP
    WAIT-QSPI-DONE
;
\ Erase (FFFF) all EEPROM cells.
: ERAL ( --)
    WAIT-QSPI-READY
    _ERAL MW! DROP
    WAIT-QSPI-DONE
;
\ Erase (FFFF) one EEPROM cell.
: EERASE ( ee-addr --)
    WAIT-QSPI-READY
    _ERASE SWAP MW! DROP
    WAIT-QSPI-DONE
;
\ Write a value to all EEPROM cells
: WRAL ( 16b --)
    WAIT-QSPI-READY
    _WRAL SWAP MW2!W DROP
    WAIT-QSPI-DONE
;
\ Conduct the write transaction.
: EE! ( 16b ee-addr -- )
    WAIT-QSPI-READY
    WR_9346 OR SWAP MW2!W DROP
    WAIT-QSPI-DONE
;
\ Read the receive RAM.
: GET-EE ( -- 16b) REC-RAM 2 + W@ ;

\ Conduct the read transaction.
: (EE@) ( ee-addr -- )
    WAIT-QSPI-READY
    RD_9346 OR 0 MW2!R DROP
    WAIT-QSPI-DONE
;
\ Observation indicates we need this much delay after the QSPI
\ claims to be finished before we attempt to read the receive RAM.
: EE@ ( ee-addr -- 16b) (EE@) 42000 0 DO ( PAUSE) LOOP GET-EE ;

BASE !
END-DOWNLOAD
