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