
The 68HC11 and related processors from Motorola are quite popular. These devices are very simple to interface to the PAK-I or -II floating point math coprocessors as well as the PAK I/O and Pulse coprocessors. Of course, the PAK-V (PWM) and PAK-VI (PS/2 keyboard) use RS-232 communications, so they are simple to interface as well.
The code below is an SBasic library that allows you to communicate with a PAK-I or II to perform 32-bit floating point math. If you don't use SBasic, just comment out the existing getarg0 and getarg1 routines and replace them with the commented versions. You'll also need to provide 4 bytes to store the arguments (are come up with your own scheme). In SBasic, JSR _PULL takes an argument off the data stack and places it in the D register.
The code assumes you have the data line connected to PC.6 and the clock to PC.7. You can change these definitions if you like (look after the asmfunc statements in the .LIB file). Call PAKINIT and then PAKRESET before issuing any other commands.
Here is a summary of the commands provided:
pakinit - Init PAK I/O on Port C
pakreset - Reset PAK communications system
paksend - Send a byte to the PAK
pakrcv - Receive a byte from the PAK
pakwait - Wait for 0 bit and receive a byte from the PAK
pakloadx - Put 32 bits of data in PAK's X register
pakloady - Put 32 bits of data in PAK's Y register
pakint2x - Load 16 bit integer in PAK's X register as float
pakreadint - Returns PAK's X register as a 16 bit integer
pakid - Returns PAKs ID
pakx2y - Set Y with X
paky2x - Sets X wth Y
pakmult - X=X*Y
pakswap - Swap X and Y
pakchs - X=-X
pakdiv - X = X/Y
pakadd - X=X+Y
paksub - X=X-Y
pakopt - Set PAK options
pakabs - X= |X|
paksto - Store X in register 0 or 1
pakrcl - Recall X from register 0 or 1
pakdir - Set I/O direction
pakrio - Read I/O register
pakwio - Write I/O register
You can refer to the PAK-I manual for more details.
You can read the listings below, or download both PAK1.lib and PAK1a.lib (pak1hc11.zip). PAK1.lib assumes you are using a single port and 2 wires. PAK1a.lib assumes you are using separate input and output pins (3 wires).
The basic routines (PAKINIT, PAKRESET, PAKSEND, PAKRCV, and PAKWAIT) will work equally well with any of the PAK families that don't use RS232 (that is the PAK-I and II math coprocessors, the PAK-III and IV I/O coprocessors, and the PAK-VII pulse input coprocessor).
You might also be interested in our 68HC11 PCBUG tips page. You'll find our free 68HC811E2 EEPROM talker there along with some other useful tips.
Here is the Library file:
' PAK-I Interface library (will work with other PAKs too)
' By Al Williams http://www.al-williams.com/awce
' Assumes 8MHz clock or less
' Version 3
' definitions
asmfunc pakinit
asmfunc pakreset
asmfunc paksend
asmfunc pakrcv
asmfunc pakwait
asmfunc pakloadx
asmfunc pakloady
asmfunc pakint2x
asmfunc pakreadint
asmfunc pakwio
asmfunc pakid
asmfunc pakx2y
asmfunc paky2x
asmfunc pakmult
asmfunc pakswap
asmfunc pakchs
asmfunc pakdiv
asmfunc pakadd
asmfunc paksub
asmfunc pakopt
asmfunc pakabs
asmfunc paksto
asmfunc pakrcl
asmfunc pakdir
asmfunc pakrio
asm
* Make changes here to suit your setup
port equ _portc * PAK-I port
maskclock equ $80 * Mask for clock bit
maskdata equ $40 * Mask for Sin/Sout bit
ddr equ _ddrc * Associated DDR register
dirmask equ %11000000 * DDR mask
* If you are using SBasic use these getargx routines
getarg0 jmp _pull
getarg1 jmp _pull
* If you are using ASM comment out the getargx routines above
* and use these instead (or change to suit your own scheme)
* You'll need to define 4 bytes of RAM for arg0 and arg1 somewhere else
* arg0 equ $20 * free ram location (2 bytes)
* arg1 equ $22 * another free ram location (2 bytes)
* getarg0 ldd arg0
* rts
* getarg1 ldd arg1
* rts
portr equ port-_ioregs
ddrr equ ddr-_ioregs
* statement; no arguments
pakinit
* initial setup for PAK-I
* PC6=SIN/SOUT
* PC7=CLK
clra
staa port
ldaa #dirmask
staa ddr * set for outputs
rts
* statement; no arguments
pakreset
ldx #_ioregs
bclr portr,X,#maskdata * data starts @ 0
* set clock high
bset portr,X,#maskclock
* set data high
bset portr,X,#maskdata
* set clock low
bclr portr,X,#maskclock
rts
* SBasic statement, 1 argument
paksend
jsr getarg0 * get first argument
* Send data in B
paksendb
ldx #_ioregs
ldaa #8 ; number of bits
bset ddrr,X,#maskdata
* B has byte
paksloop
bset portr,X,#maskdata
bitb #$80
bne paksone
bclr portr,X,#maskdata
paksone
bset portr,X,#maskclock
bclr portr,X,#maskclock
lslb
deca
bne paksloop
rts
pakwait
ldx #_ioregs
bclr ddrr,X,#maskdata
brset portr,X,#maskdata,pakwait
* return, but no real argument
pakrcv
* dummy argument in D
* could make it 0=wait; 1=no wait; $100=no data $00xx for data xx
* but for now
ldx #_ioregs
bclr ddrr,X,#maskdata * make data input
clrb
ldaa #8 * bit count
pakrloop
lslb
brclr portr,X,#maskdata,pakrzero
orab #1
pakrzero
bset portr,X,#maskclock
bclr portr,X,#maskclock
brn *
brn *
deca
bne pakrloop
rts
* If you are changing the port
* nothing past here needs to change
pakloadx
ldab #1
bra pakload
pakloady
ldab #2
pakload
jsr paksendb
jsr getarg0 * get first argument
psha
pshb
jsr getarg1 * get 2nd argument
jsr paksnd2
pulb
pula
paksnd2
pshb
tab
jsr paksendb
pulb
jsr paksendb
rts
pakint2x
pshb
psha
ldab #1
jsr paksendb
clrb
jsr paksendb
clrb
jsr paksendb
pulb
jsr paksendb
pulb
jsr paksendb
brn *
brn *
ldab #7
jsr paksendb
jmp pakwait
pakreadint
ldab #$B
jsr paksendb
bsr pakwait
ldab #3
jsr paksendb
* slight delay for processing
brn *
brn *
brn *
brn *
* discard first 2 bytes
bsr pakrcv
bsr pakrcv
bsr pakrcv
pshb
bsr pakrcv
pula
rts
pakwio
ldab #$16
jsr paksendb
jsr getarg0 * get first argument
jsr paksendb
rts
pakid
ldab #$8
bra paksendw
pakx2y
ldab #$17 * X->Y
jmp paksendb
paky2x
ldab #$18 * Y->X
jmp paksendb
pakchs
ldab #$A
jmp paksendb
pakmult
ldab #$C
paksendw
jsr paksendb
jmp pakwait
pakdiv
ldab #$D
bra paksendw
paksub
ldab #$E
bra paksendw
pakadd
ldab #$F
bra paksendw
pakopt
pshb
ldab #$10
jsr paksendb
pulb
jmp paksendb
pakabs
ldab #$11
jmp paksendb
pakswap
ldab #$4
jmp paksendb
paksto
andb #1
clc
rorb
rorb
addb #$12
jmp paksendb
pakrcl
andb #1
clc
rorb
rorb
addb #$13
jmp paksendb
pakrio
ldab #$15
jsr paksendb
brn *
brn *
jmp pakrcv
pakdir
pshb
ldab #$14
jsr paksendb
pulb
jmp paksendb
endasm
The above code assumes you are using a data pin where you can change the direction. If you want to use 3 wires to connect (a dedicated input and output pin plus the clock pin) you can replace the code above starting with the asm keyword with the following:
* Use the file above up to ASM asm * Make changes here to suit your setup inpport equ _porta * PAK-I port outport equ _porta clkport equ _porta maskclock equ $10 * Mask for clock bit maskdin equ $4 * Mask for Sin/Sout bit maskdout equ $20 * If you are using SBasic use these getargx routines getarg0 jmp _pull getarg1 jmp _pull * If you are using ASM comment out the getargx routines above * and use these instead (or change to suit your own scheme) * You'll need to define 4 bytes of RAM for arg0 and arg1 somewhere else * arg0 equ $20 * free ram location (2 bytes) * arg1 equ $22 * another free ram location (2 bytes) * getarg0 ldd arg0 * rts * getarg1 ldd arg1 * rts inpportr equ inpport-_ioregs outportr equ outport-_ioregs clkportr equ clkport-_ioregs * statement; no arguments pakinit * initial setup for PAK-I * PC6=SIN/SOUT * PC7=CLK clra * initialize clk and data to 0 (change to suit) staa outport staa clkport rts * statement; no arguments pakreset ldx #_ioregs bclr outportr,X,#maskdout * data starts @ 0 * set clock high bset clkportr,X,#maskclock * set data high bset outportr,X,#maskdout * set clock low bclr clkportr,X,#maskclock rts * SBasic statement, 1 argument paksend jsr getarg0 * get first argument * Send data in B paksendb ldx #_ioregs ldaa #8 ; number of bits * B has byte paksloop bset outportr,X,#maskdout bitb #$80 bne paksone bclr outportr,X,#maskdout paksone bset clkportr,X,#maskclock bclr clkportr,X,#maskclock lslb deca bne paksloop bset outportr,X,#maskdout * data idle rts pakwait ldx #_ioregs brset inpportr,X,#maskdin,pakwait * return, but no real argument pakrcv * dummy argument in D * could make it 0=wait; 1=no wait; $100=no data $00xx for data xx * but for now ldx #_ioregs clrb ldaa #8 * bit count pakrloop lslb brclr inpportr,X,#maskdin,pakrzero orab #1 pakrzero bset clkportr,X,#maskclock bclr clkportr,X,#maskclock brn * brn * deca bne pakrloop rts * If you are changing the port * nothing past here needs to change * The rest of the code is the same as the first example
Finally, here is a simple example of using the coprocessor:
' PAK test
include "regs11.lib"
include "pak1.lib"
declare i
declare v
declare v1
declare v2
declare v3
declare v4
sci_init:
pokeb baud, $30 ' 9600 baud
pokeb sccr2, $0c ' enable rcvr and xmtr
return
main:
pakinit
gosub sci_init
pakreset
pakdir $FF ' set all PAK pins to outputs
print "Begin"
v=pakid(0) ' read PAK ID
printx v
if v=$22 then
pokeb portb,$80 ' light LED on B.7 if ID successful
else
pokeb portb,$40
endif
v2=7
for v4=1 to 100 ' compute on 1 to 100
pakwio 0 ' LEDs on PAK outputs off
' load x=5
v=pakint2x(v4) ' Load V4 into X
pakx2y ' Save X in Y
v=pakint2x(v2) ' Load V2 into X
pakswap ' Swap X and Y
v=pakdiv(0) ' X=X/Y
pakswap ' Swap X and Y
v=pakint2x(5) ' Load X with 5
v=pakadd(0) ' X=X+Y
' Convert X to 10X so we can read it out
' and reinsert the decimal point
' The FCONVERT program tells us that 10 is $82200000
pakloady $8220,0 ' Y=10 = $82200000
v=pakmult(0) ' X=X*Y
v=pakreadint(0) ' Read X as 16 bit int
' Reconstruct the part to the left and right of decimal
print v4;"/";v2;"+ 5 =";v/10;".";v MOD 10
pakwio $FF ' All PAK LEDs on (briefly)
next
end

Site contents © 1997-2018 by AWC, Houston TX (281) 334-4341