_PROGRAMMING THE MOTOROLA 68332_ by Jack J. Woehr [LISTING ONE] 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] 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. These are specific to 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 chip selects is assigned to \ QSPI; otherwise, command masks should contain states for 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 : @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 [LISTING TWO] DOWNLOAD \ Filename: qsm332.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: Defines and primitives for SBC332 Queued Serial Modul (QSM) \ Dependencies: Platform board; VFSE-332 operators W! W@ (16-bit ops). \ Needs: YREG332.F \ References: MC68332 USER'S MANUAL [MC68332UM/AD] Motorola, 1990 \ $Log: V:/vestasrc/forth/68332/tpuqsm/vcs/qsm332.f_v $ \ Rev 1.1 14 Jul 1992 11:26:26 jax \ cleanup edits \ Rev 1.0 17 Jun 1992 10:09:26 jax \ Initial revision. \ ** QSM registers and bits from MC68332UM/AD Tables 5-1 and 5-2. BASE @ HEX FFC00 YREG QMCR 8000 CONSTANT QMCR.STOP 4000 CONSTANT QMCR.FRZ1 2000 CONSTANT QMCR.FRZ0 80 CONSTANT QMCR.SUPV 0F CONSTANT QMCR.IARB \ field, not bit mask \ FFC02 YREG QTEST \ Not used in VFSE-332 \ 08 CONSTANT QTEST.TSBD \ 04 CONSTANT QTEST.SYNC \ 02 CONSTANT QTEST.TQSM \ 01 CONSTANT QTEST.TMM FFC04 YREG QILR \ 8 msbs \ FFC05 YREG QILR \ byte address, but SET-YREG uses W@ W! 3800 CONSTANT QILR.ILQSPI \ field 0B CONSTANT >QILR.ILQSPI \ bit shift 700 CONSTANT QILR.ILSCI \ field 08 CONSTANT >QILR.ILSCI \ bit shift FFC04 YREG QIVR \ 8 lsbs FF CONSTANT QIVR.INTV \ number \ FFC06 YREG RESERVED FFC08 YREG SCCR0 1FFF CONSTANT SCCR0.SCBR \ field FFC0A YREG SCCR1 4000 CONSTANT SCCR1.LOOPS 2000 CONSTANT SCCR1.WOMS 1000 CONSTANT SCCR1.ILT 800 CONSTANT SCCR1.PT 400 CONSTANT SCCR1.PE 200 CONSTANT SCCR1.M 100 CONSTANT SCCR1.WAKE 80 CONSTANT SCCR1.TIE 40 CONSTANT SCCR1.TCIE 20 CONSTANT SCCR1.RIE 10 CONSTANT SCCR1.ILIE 8 CONSTANT SCCR1.TE 4 CONSTANT SCCR1.RE 2 CONSTANT SCCR1.RWU 1 CONSTANT SCCR1.SBK FFC0C YREG SCSR 100 CONSTANT SCSR.TDRE 80 CONSTANT SCSR.TC 40 CONSTANT SCSR.RDRF 20 CONSTANT SCSR.RAF 10 CONSTANT SCSR.IDLE 8 CONSTANT SCSR.OR 4 CONSTANT SCSR.NF 2 CONSTANT SCSR.FE 1 CONSTANT SCSR.PF FFC0E YREG SCDR 100 CONSTANT SCDR.R8/T8 80 CONSTANT SCDR.R7/T7 40 CONSTANT SCDR.R6/T6 20 CONSTANT SCDR.R5/T5 10 CONSTANT SCDR.R4/T4 8 CONSTANT SCDR.R3/T3 4 CONSTANT SCDR.R2/T2 2 CONSTANT SCDR.R1/T1 1 CONSTANT SCDR.R0/T0 \ FFC10 YREG RESERVED \ FFC12 YREG RESERVED FFC14 YREG QPDR \ 8 lsbs only .. 8 msbs reserved 80 CONSTANT QPDR.TXD 40 CONSTANT QPDR.PCS3 20 CONSTANT QPDR.PCS2 10 CONSTANT QPDR.PCS1 8 CONSTANT QPDR.PCS0/_SS 4 CONSTANT QPDR.SCK 2 CONSTANT QPDR.MOSI 1 CONSTANT QPDR.MISO FFC16 YREG QPAR \ 8 msbs \ FFC17 YREG QPAR \ byte address, but SET-YREG uses W@ W! 4000 CONSTANT QPAR.PCS3 2000 CONSTANT QPAR.PCS2 1000 CONSTANT QPAR.PCS1 800 CONSTANT QPAR.PCS0/_SS 200 CONSTANT QPAR.MOSI 100 CONSTANT QPAR.MISO FFC16 YREG QDDR \ 8 lsbs 80 CONSTANT QDDR.TXD 40 CONSTANT QDDR.PCS3 20 CONSTANT QDDR.PCS2 10 CONSTANT QDDR.PCS1 8 CONSTANT QDDR.PCS0/_SS 4 CONSTANT QDDR.SCK 2 CONSTANT QDDR.MOSI 1 CONSTANT QDDR.MISO FFC18 YREG SPCR0 8000 CONSTANT SPCR0.MSTR 4000 CONSTANT SPCR0.WOMQ 3C00 CONSTANT SPCR0.BITS \ field 0A CONSTANT >SPCR0.BITS \ shift 200 CONSTANT SPCR0.CPOL 100 CONSTANT SPCR0.CPHA FF CONSTANT SPCR0.SPBR \ field FFC1A YREG SPCR1 8000 CONSTANT SPCR1.SPE 7F00 CONSTANT SPCR1.DSCKL \ field 08 CONSTANT >SPCR1.DSCKL \ shift FF CONSTANT SPCR1.DTL \ field FFC1C YREG SPCR2 8000 CONSTANT SPCR2.SPIFIE 4000 CONSTANT SPCR2.WREN 2000 CONSTANT SPCR2.WRTO F00 CONSTANT SPCR2.ENDQP \ field 08 CONSTANT >SPCR2.ENDQP \ shift 0F CONSTANT SPCR2.NEWQP \ field 00 CONSTANT >SPCR2.NEWQP \ shift FFC1E YREG SPCR3 \ 8 msbs \ FFC1F YREG SPCR3 \ byte address, but SET-YREG uses W@ W! 400 CONSTANT SPCR3.LOOPQ 200 CONSTANT SPCR3.HMIE 100 CONSTANT SPCR3.HALT FFC1E YREG SPSR \ 8 lsbs 80 CONSTANT SPSR.SPIF 40 CONSTANT SPSR.MODF 20 CONSTANT SPSR.HALTA 0F CONSTANT SPSR.CPTQP \ field \ FFC20 YREG RESERVED \ YFFC20 - YFFCFF FFD00 YREG REC-RAM \ YFFD00 - YFFD1F FFD20 YREG TRAN-RAM \ YFFD20 - YFFD3F FFD40 YREG COMD-RAM \ YFFD40 - YFFD4F 80 CONSTANT COMD-RAM.CONT 40 CONSTANT COMD-RAM.BITSE 20 CONSTANT COMD-RAM.DT 10 CONSTANT COMD-RAM.DSCK 08 CONSTANT COMD-RAM.PCS3 04 CONSTANT COMD-RAM.PCS2 02 CONSTANT COMD-RAM.PCS1 01 CONSTANT COMD-RAM.PCS0/_SS \ ** QSM Functionality \ *** [MC68332UM/AD 5.4.2.1] \ TRUE stops, FALSE enables QSM. Supervisor mode only. : QSM-STOP ( flag --) QMCR.STOP QMCR ROT SET-YREG ; \ To avoid complications at restart & prevent data corruption, first disable \ all submodules: SCI rx/tx should be disabled, and operation completion \ verified before asserting STOP. QSPI submodule should be stopped by asserting \ SPCR3.HALT and asserting STOP after HALTA flag set. TRUE causes QSM to HALT \ on transfer boundary when FREEZE asserted on IMB, FALSE causes QSM to ignore \ said signal. FREEZE is asserted when 332 enters the background mode. : QSM-FREEZE ( flag --) QMCR.FRZ1 QMCR ROT SET-YREG ; \ TRUE sets QSM supervisor-only access, FALSE (from supervisor mode, \ of course, resets to QSM user access permitted. : QSM-SUPERVISOR ( flag --) QMCR.SUPV QMCR ROT SET-YREG ; \ 0 causes 332 to view QSM int as spurious, 1 (lo) to 15 (hi) are \ interrupt arbitration priority levels. : QSM-IARB! ( 0-15 --) QMCR.IARB AND \ acceptable values 0 - 15 QMCR W@ \ fetch reg contents QMCR.IARB INVERT AND \ mask off IARB bits OR \ OR in desired mask QMCR W! \ store reg ; \ *** [MC68332UM/AD 5.4.2.2] is for when MCU is in test mode. \ Not used in Vesta Forth Standard Edition \ *** [MC68332UM/AD 5.4.2.3] \ Int levels 0-7; if same, QSPI given priority. : QSM-INT-LEVEL ( QSPI-level SCI-level --) >QILR.ILSCI LSHIFT QILR.ILSCI AND \ shift 0-7 mask and constrain SWAP >QILR.ILQSPI LSHIFT QILR.ILQSPI AND \ ditto OR \ form combination desired mask QILR W@ \ get register QILR.ILQSPI QILR.ILSCI OR INVERT AND \ mask off IL fields from reg OR \ OR in desired mask QILR W! \ store reg ; \ *** [MC68332UM/AD 5.4.2.4] \ Int vectors for QSPI/SCI are adjacent; bit D0 of int vect is 0 for SCI \ and 1 for QSPI. : QSM-INT-VECTOR ( vector --) QIVR.INTV AND QIVR W! ; \ *** [MC68332UM/AD 5.4.3] \ In general, bit assignments can be handled directly by the application \ using SET-YREG from YREGS322.F BASE ! END-DOWNLOAD