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
68HCxx WebRing
This 68HCxx WebRing site owned by AWC.
[Previous Site | Next | Random | List All Sites | Join Ring]


Site contents © 1997-2014 by AWC, 310 Ivy Glen, League City, TX 77573    (281) 334-4341