====== FLASH ATTACK CABLE PLANS & CONCEPTS ======
{{:larry:comp:flash_attack:flashsetup.jpg?200 |}}**Notes on Hardware and Software using the Flash Attack Style Parallel Port Data Cable**
This cable is used in the 2-PET game Flash Attack as well as in the article from December 1980 Byte Magazine titled "Multi-Machine Games" (by Tim Stryker & Ken Wasserman). Even though this was originally intended just for the PET, like many of the Commodore 8-bit computer features, the interfacing and BASIC are similar enough that it can be applied to many of the machines in the 8-bit line.
So with the proper effort your two-machine game or other application can be between any combination of PET, VIC-20, Commodore 64/128, and Plus/4.
Possible non-commodore communication with this method could be accomplished through IBM compatible parallel ports as well (but that is for someone else to delve into)...
===== Hardware: =====
{{:larry:projects:flashcable.jpg?200 |}}<= Image of a completed cable (note sound wires were added after construction and end in the center, thus the taping at even increments.) Below the main cable is the sound wire with a small pc board for the resistors and the 1/8" plug for the amplifier. (see bottom of this page for sound connector diagram.)
The flash Attack cable uses the Commodore's Parallel data port located on the back of most Commodore 8-bit computers, the pinout for the PET VIC-20, and Commodore 64/128 are the same (except the CB2 sound is unnecessary on non-PET systems, but could be implemented if you really want to...) The Plus/4 will work too (sans the CB2 Sound), but the wiring is... different (see farther down).
==== FA Cable Diagram: ====
{{:larry:projects:facable.gif |}}The cable uses mainly two 12/24 edge board connectors and a length of flat ribbon cable (3 to 5 feet is usual), the minimum conductors needed are 8, one wire for ground, and the seven data lines between the computers, 8 conductors are necessary
==== Pinout: ====
^ Pin ^ Description ^
| A |Ground|
| C |Parallel Data Line bit 0|
| D |Parallel Data Line bit 1|
| E |Parallel Data Line bit 2|
| F |Parallel Data Line bit 3|
| H |Parallel Data Line bit 4 (this pin is used on only one connector!)|
| J |Parallel Data Line bit 5|
| K |Parallel Data Line bit 6|
| L |Parallel Data Line bit 7|
| M |CB2 Handshake Line (used for PET sound in this text)|
| N |Ground|
==== Plus/4: the Commodore Exception (color coded cross-over lines for clarity): ====
{{:larry:projects:fap4cable.gif |}}The plus/4 can also be used but due to the differences of the parallel port pinout the connector has to be wired differently. Also it may not work with a Datasette connected as pin 4 is also used for Datasette sense line. (**NOTE:** if two plus/4 are being wired together one connector has to have a bridge wire between pin H and pin N)
=== Plus/4 Specific Pinout (I don't envy you on wiring this mess) ===
^ Pin ^ Description ^
| A |Ground|
| B |Parallel Data Line bit 0|
| K |Parallel Data Line bit 1|
| 4 |Parallel Data Line bit 2 (also 'cassette sense', unplug datasette before use)|
| 5 |Parallel Data Line bit 3|
| 6 |Parallel Data Line bit 4* (this pin is used on only one connector!)|
| 7 |Parallel Data Line bit 5|
| J |Parallel Data Line bit 6|
| F |Parallel Data Line bit 7|
The connectors will fit in the Plus/4 if you file off a tad of the left/right edges of the opening for the parallel port.
==== FA Cable Parts: ====
^ QTY ^ DESCRIPTION ^
| 2 |12/24 contact Edge board Connectors with .156" spacing between contacts*|
| 1 |3 to 5 feet of 8 or 9 conductor ribbon cable or wire|
| 2 |Connector housings (hard to find in the U.S.)\\ or\\ 4 screws to use as connector grips (I suggest size 6-32 x 1.5" machine screws)|
* //Edge board connectors can be purchased (in any quantity) from Digikey Corporation Part # EDC307240-ND ($2.08 ea or $18.43 for 10)//
==== Adding PET Sound Circuitry: ====
{{:larry:projects:cablepetsound.gif |}} if you also require CB2 sound output for PET usage.
For PET sound add:
^ QTY ^ DESCRIPTION ^
| 2 |50-500k resistors|
| 1 |small piece of breadboard or electrical tape (to isolate bare wires)|
| 1 |1/8" phono plug|
| 1 |Small Audio Amplifier\\ (like the one used in Radio Shack's Handset Listener part # 430-0231B) about $12|
Wire as described above, with the ground as the casing and the CB2 signal going to the tip. Notes on how to create your own sound with a note table can be found on the PET FAQ.
----
* //remember if you make a cable, one side must have bit 4 grounded, only one side!)//
===== Software: =====
Communication via the flash attack cable can be easily accomplished in BASIC or Assembly Language, and mainly deals with setting the 'data' direction of the ports and reading and sending bytes. The data bytes are sent in two 4-bit chunks (called nybbles) with the other four lines used to see who sends first (that;s what the jumper on one end if for ), indicate that data has been sent/received by the other computer.
==== BASIC test program ====
This is a two way communications test program where each computer can type to the other, using the principles of a simple recieve-send-recieve-send-recieve protocol. Everything you type on one machine will appear on the other, and visa-versa. To end the program properly one person types a shifted-Q character, it will end the program on both computers. Line 210 checks for the presence of the wire on pin 4 if that computer does have the wire, it will start by sending, the other program will know to receive by the same test.
100 REM*** PROGRAM TO TEST INTER-
110 REM*** MACHINE COMMUNICATIONS
120 REM***
130 REM PARALLEL PRT: PET-59471, 64-56577, VIC20-37151, PLUS/4-64784
140 PRT=59471
150 REM DATA DIR. REGISTER: PET-59459, 64-56579, VIC20-37139, PLUS/4-64800
160 DDR=59459
200 GOSUB 10000
205 POKE DDR,239
210 IF PEEK(PRT) AND 16 THEN 260
220 GET S$
230 IF S$ = "[SHIFT-Q]" THEN S$ = CHR$(0)
240 GOSUB 10200
250 IF S$ = "[SHIFT-Q]" THEN 999
260 GOSUB 10400
270 PRINT R$;
280 IF R$ <> "[SHIFT-Q]" THEN 220
999 END
10000 REM***
10010 REM*** ROUTINE TO INITIALIZE PORT
10020 REM*** INPUTS: NONE
10030 REM*** OUTPUTS: NONE
10040 REM***
10050 POKE PRT,255
10060 POKE DDR,255
10070 RETURN
10200 REM***
10210 REM*** ROUTINE TO SEND BYTE
10220 REM*** INPUT: S$ = BYTE TO BE SENT
10230 REM***
10240 REM*** OUTPUTS: NONE
10250 REM***
10260 HN = INT(ASC(S$)/16)
10270 LN = ASC(S$)-HN*16
10275 POKE DDR,111
10280 POKE PRT,LN+128+32
10290 IF PEEK(PRT) AND 128 THEN 10290
10300 POKE PRT,HN+128+64
10310 IF PEEK(PRT) AND 128 THEN 10330
10320 GOTO 10310
10330 POKE PRT,255
10340 RETURN
10400 REM***
10410 REM*** ROUTINE TO RECEIVE BYTE
10420 REM*** INPUTS: NONE
10430 REM*** OUTPUT: R$ = BYTE RECEIVED
10440 REM***
10445 POKE DDR,128
10450 IF PEEK(PRT) AND 64 THEN 10450
10460 LN = PEEK(PRT) AND 15
10470 POKE PRT,127
10480 IF PEEK(PRT) AND 32 THEN 10480
10490 HN = PEEK(PRT) AND 15
10500 POKE PRT,255
10510 R$ = CHR$(HN*16+LN)
10520 RETURN
==== ML ASSEMBLER ====
DISASSEMBLY OF FLASH ATTACK CABLE ROUTINES (MERLIN 128 FORMAT)
********************************
* IMPROVED COMM-LINK *
* ROUTINES FOR COMMODORE 8-BIT *
* COMPUTERS *
*------------------------------*
* BY LARRY ANDERSON *
* REV DATE: 06/25/91 *
********************************
;
* 64 VERSION:
;
CHKCMA = $AEFD ;CHECK FOR COMMA
EVALEXP = $AD9E ;EVAUATE EXPRESSION AND LEAVE IN FAC#1
FLTFIX = $B7F7 ;FLOATING POINT TO FIXED INTERGER UN-SIGNED
;
GETIN = $FFE4 ;GET CHARACTER FROM INPUT DEVICE
KYTBL = $CF00 ;KEYBOARD DECODE TABLE (KEYPRESS TO PETASCII)
;
FIXFLT = $B3A2 ;FIXED INTERGER (IN .Y) TO FLOATING POINT
PORT = $DD01 ;PARALLEL PORT ACCESS
DDR = $DD03 ;PARALLEL PORT DATA DIRECTION REGISTER
;
VECTORS = $033C
;
;
;
TEMP = VECTORS+1 ;TEMPORARY
UTIL1 = VECTORS+2 ;AND UTILITY BYTES
UTIL2 = VECTORS+3
;
ORG $C000 ;CODE WILL BE ASSEMBLED TO 49152-
;
; USAGE:
; FIRST, SET UP USR JUMP IN BASIC:
; POKE785,0:POKE786,192
; SECONDWHEN READY, DETERMINE WHO SENDS/RECIEVES FIRST BY USING THIS:
: POKE 59459,239:IF PEEK(59471) AND 16 THEN ***
; ONE COMPUTER WILL BRANCH, THE OTHER WON'T
;
; ML USAGE:
; TO SEND BYTES USE: SYS 49155,[#],[#],[#],[ETC],256 ([#] =0-255, AT LEAST ONE)
; TO RECEIVE BYTES: NUM=USR(0) (ONE AT A TIME)
; TO SEND BLOCK OF MEMORY: SYS 49158,[START ADDRESS],[END ADDRESS]
; TO RECEIVE BLOCK OF MEMORY: SYS 49161
;
JMP USRPROC ;USR() INPUT PROCESSOR: 0 PORT RECEIVE, -1 GET KYBD
JMP SNDBYTS ;SEND BYTES: SYS SEND,0,23,123,33,>=256(END)
JMP SNDBLK ;SEND BLOCK: SYS ADDR,START,END
JMP RCVBLK ;RECEIVE BLOCK
JMP CLRPORT ;RESET PORT
;
* SUBROUTINE TO GET NUMBERS
;
GETNUM JSR CHKCMA ;GET A NUMBER APPENDED TO THE CALLING SYS
JSR EVALEXP ; I.E. SYS 49152,123
JMP FLTFIX ; NUMBER WILL BE UNSIGNED IN FAC1 AND Y/A
SNDBYT JSR SETUP
STA TEMP ;STORE COPY OF BYTE
LDX #$6F ;DDR MASK BYTE: 01101111
STX DDR ;SET DDR TO: IOOIOOOO
ORA #$F0 ;MASK OUT LOW NYBBLE: ----****
AND #$BF ;ADD IN NEW DATA: 1011**** (LOW NYBBLE READY)
STA PORT ;SEND LOW-NYBBLE ON CABLE
LDA TEMP ;GET SEND BYTE AGAIN
LSR ;SHIFT RIGHT -****---
LSR ;SHIFT RIGHT --****--
LSR ;SHIFT RIGHT ---****-
LSR ;SHIFT RIGHT ----****
CLC
ORA #$D0 ;ADD IN NEW DATA: 1101**** (HIGH NYBBLE READY)
SNLOOP1 BIT PORT ;CHECK THE STATUS OF DATA RECEIVED 0------
BMI SNLOOP1 ;KEEP CHECKING TILL RECEIVED
STA PORT ;SEND HIGH-NYBBLE ON CABLE
SNLOOP2 BIT PORT ;CHECK STATUS OF DATA RECEIVED 1------
BPL SNLOOP2 ;KEEP CHECKING TILL RECEIVED
JSR CLRPORT ;RESET PORT
JMP SETDOWN ;ALL DONE
;
RCVBYT JSR SETUP
LDA #$80 ;DDR MASK BYTE: 10000000
STA DDR ;SET DDR TO: OIIIIIII
STA PORT ;SET PORT AS WELL
RNLOOP1 BIT PORT ;WAIT TILL LOW NYBBLE READY -1------
BVS RNLOOP1 ;KEEP CHECKING TILL SET
LDA PORT ;GET LOW-NYBBLE FROM CABLE
AND #$0F ;GET RID OF STATUS GARBAGE: ----****
STA TEMP ;SAVE IT AWAY
LDA #$7F ;SET DATA RECEIVED 01111111
STA PORT ;TELL SENDER
LDA #$20
RNLOOP2 BIT PORT ;WAIT TILL HIGH NYBBLE READY
BNE RNLOOP2 ;KEEP CHECKING TILL SET
LDA PORT ;GET HIGH-NYBBLE FROM CABLE
ASL ;SHIFT LEFT ---****-
ASL ;SHIFT LEFT --****--
ASL ;SHIFT LEFT -****---
ASL ;SHIFT LEFT ****----
CLC
ORA TEMP ;COMBINE TO GET FULL BYTE
JSR CLRPORT ;RESET PORT (WILL SET DATA RECEIVED)
JMP SETDOWN
;
CLRPORT LDX #$FF ;RESET MASK: 1111111
STX DDR ;RESET DATA DIRECTION REGISTER: OOOOOOOO
STX PORT ;RESET PORT BUS: 11111111
RTS
;
SETUP STY UTIL1
STX UTIL2
RTS
;
SETDOWN LDY UTIL1
LDX UTIL2
RTS
;
USRPROC JSR FLTFIX ;CONVERT USR(X) INTO TWO BYTES UN-SIGNED)
CPY #$00 ;IF HI-BYTE =0, YOU WANT IT FROM THE COM PORT?
BEQ GETBYT ;YES, GET IT PLEASE..
JSR GETIN ;GET VALUE FROM KEYBOARD
LDA KYTBL,Y ;GET NEW PROCESSEED VALUE
TAY
JMP FIXFLT ;FINISH BY CONV IT TO BASIC READY VAL.
GETBYT JSR RCVBYT ;GET A BYTE FROM THE CABLE
TAY ;SET LO SYSTEM POINTERS ACCORDINGLY
LDA #$00 ; " "
JMP FIXFLT ;FIX BYTE TO BE RETURNED AND RETURN
;
SNDBYTS JSR GETNUM ;GET NEXT VALUE
CMP #$00 ;IS THIS THE END? (GREATER THAN 255?)
BNE ENDSEND ;YES, LETS END THIS.
TYA ;NO, TRANSFER LO TO ACCUMULATOR.
JSR SNDBYT ;SEND IT OVER COMM
JMP SNDBYTS ;GET NEXT VALUE.
ENDSEND RTS ;ALL DONE.
;
; THE FOLLOWING BLOCK SEND/RECIEVE ROUTINE USES SELF-MODIFYING
; M/L CODE; SOMETHING YOUR MOM OR YOUR PROGRAMMING INSTRUCTORS
; WARNED YOU TO AVOID. BUT COOL PROGRAMMERS WHO LIVE DANGROUSLY
; GET ALL THE CHICKS.
;
SNDBLK LDA #$0D
JSR SETMODE
JSR GETNUM ;GET START ADDRESS OF BLOCK
STA BLKPTR1+2 ;STORE IT IN BLOCK MOVER
JSR SNDBYT ;SEND IT OVER CABLE
TYA ;GET LOW PART OF ADDRESS
STA BLKMOV+1 ;STORE IT IN BLOCK MOVER
JSR SNDBYT ;SEND IT OVER CABLE
JSR GETNUM ;GET END ADDRESS OF BLOCK
STA BLKPTR5+1 ;PUT IT IN BLOCK MOVER
JSR SNDBYT ;SEND IT OVER CABLE
TYA ;GET LOW PART OF ADDRESS
STA BLKPTR3+1 ;PUT IT IN BLOCK MOVER
JSR SNDBYT ;SEND IT OVER CABLE
JMP BLKMOV
;
RCVBLK LDA #$06
JSR SETMODE
JSR RCVBYT ;GET START ADDR HI
STA BLKPTR2+2 ;STORE IN BLOCK MOVER
JSR RCVBYT ;GET START ADDR LOW
STA BLKMOV+1 ;STORE IN BLOCK MOVER
JSR RCVBYT ;GET END ADDR HI
STA BLKPTR5+1 ;STORE IN BLOCK MOVER
JSR RCVBYT ;GET END ADDR LO
STA BLKPTR3+1 ;STORE IN BLOCK MOVER
;
;************************************
;DUAL PURPOSE BLOCK RECEIVE/TRANSMIT
;, - CODE IS MOFIFIED BY SETMODE
;
BLKMOV LDY #$FF ;SET LOW COUNTER TO ??
BLKPTR1 JSR RCVBYT ;GET A BYTE
BLKPTR2 STA $FF00,Y ;STORE IT IN MEMORY
BLKPTR3 CPY #$FF ;LOW BYTES MATCH?
BNE MLOOP1 ;NO, CONTINUE
BLKPTR4 LDA BLKPTR2+2 ;GET HIGH ADDRESS
BLKPTR5 CMP #$FF ;HIGH BYTES MATCH?
BEQ MLOOP3 ;YES! EXIT
MLOOP1 INY ;INCREMENT COUNTER
BNE BLKPTR1 ;PAGE JUMP?
BLKPTR6 INC BLKPTR2+2 ;YES, NEW PAGE
JMP BLKPTR1 ;START AGAIN
MLOOP3 RTS
;
SETMODE TAX ;STORE ROUTINE VALUE
LDA PTABLE,X ;GET LOW BYTE OF ADDR HI LOC
STA BLKPTR4+1 ;STORE IT IN BOTH COMPARE
STA BLKPTR6+1 ; AND INCREMENT REGISTERS
DEX ;SET FOR SUBROUTINE MODIFICATIONS
LDY #$06 ;SET COUNTDOWN COUNTER
SLOOP1 LDA PTABLE,X ;READ MODIFICATIONS
STA BLKPTR1-1,Y ;WRITE MODIFICATIONS
DEX ;DECREMENT COUNTERS
DEY
BNE SLOOP1 ;DONE?
RTS ;YEP!
;
PTABLE JSR RCVBYT ;RECEIVE MODIFICATIONS
STA $FF00,Y ; FOR BLKMOV SUBROUTINE
DFB