Linking Calculators

by Ciaran McCreesh
Created: 8th December 1999
Last Modified: 15th December 1999

Some games include multiplayer support using the linkport (Port 7). This page explains how to access the linkport and includes the ACZ ReceiveByte and SendByte routines.

The LinkPort

Possibly the most obvious port on the ti86 is the linkport. This is in fact Port 7. I've skipped Ports 3 to 6 for a number of reasons. Port 3 doesn't do anything useful - it lets you read the ON key. Port 4's function is not widely known, and rarely useful. Ports 5 and 6 are very useful but I'll explain them later.

The linkport takes a 2.5mm male Stereo Jack. When you look at one of these you'll see three wires, code-named black, red and white. The diagram below shows which is which.

Image showing linkport wire 'colours'

Turning wires on and off isn't as simple as you might think. The table below describes what happens depending on what you write to the link port. 'On' means the voltage between the black wire and the wire being tested is ~5 Volts and 'Off' means the voltage between the black wire and the wire being tested is ~0 Volts.

Value Written Red Wire White Wire
%11111100 Off Off
%11101000 On Off
%11010100 Off On
%11000000 On On

Reading the wires is even more complicated. You must first and the value you get in with 3, then compare to the following table:

Value Read Red Wire White Wire
0 Off Off
1 On Off
2 Off On
3 On On

LinkPort Routines

If you want to write a program that supports multiplayer you could use the linkport to enable multi-calculator communication. There are a few routines that do this, I've included the ACZ routines that were written by Pascal Bouron and Jimmy Mardell. I have resisted the urge to make these routines better (ie slightly optimised). Please don't ask me how these routines work - I haven't studied them in detail. I've left the original comments (?) in to help (???) you work out what's going on.

SendByte

This routine sends a byte of information to another calculator. It takes one input - the a register contains the value to send. It destroys all registers and op1 (a floating point 'register'). The carry flag is set on exit if there has been an error.


;======================================================
; SendByte                    [Assembly Coder's Zenith]
;  Originally by Pascal Bouron and Jimmy Mardell
;
; in: A = byte to send
; out: carry set = error
; destroyed: all registers, OP1
;======================================================
SendByte:
  ld hl,0
  ld (_OP1),hl
  ld b,8
  ld c,a                               ;byte to send
  ld a,$C0
  out (7),a
sbw_setport3:
  in a,(7)
  and 3
  cp 3
  jr z,sbcalc_bit
  call sbSendTest_ON
  jr sbw_setport3
sbcalc_bit:
  ld a,c
  and 1
  jr z,sbsend_one
sbsend_zero:
  ld a,$E8
  out (7),A
  jr sbwait_setport
sbsend_one:
  ld a,$D4
  out (7),A
sbwait_setport:
  call sbSendTest_ON
  in a,(7)
  and 3
  jr nz,sbwait_setport
  ld a,$C0
  out (7),A
  srl c
  djnz sbw_setport3
  xor a
  ret
sbSendTest_ON:
  ld a,%00111111
  out (1),a
  nop
  nop
  in a,(1)
  bit 6,a
  ret nz
  pop hl
  ret
ReceiveByte

This routine returns in a a value sent by SendByte. It destroys all registers and op1. The carry flag will be set if there has been an error.

;======================================================
; ReceiveByte                 [Assembly Coder's Zenith]
;  Originally by Pascal Bouron and Jimmy Mardell
;
; out: A = received byte    carry set = error
; destroyed: all registers, OP1
;======================================================
ReceiveByte:
  ld hl,0
  ld (_OP1),hl
  ld e,1                              ; for the OR
  ld c,0                              ; byte receive
  ld b,8                              ; counter
  ld a,$c0
  out (7),a
rb_w_Start:
  in a,(7)
  and 3
  cp 3
  jr nz,rb_get_bit
  call rbTest_ON
  jr rb_w_Start
rb_get_bit:
  cp 2
  jr z,rb_receive_zero
  ld a,c
  or e
  ld c,a
  ld a,$D4
  out (7),a
  jr rb_waitStop
rb_receive_zero:
  ld a,$E8
  out (7),a
rb_waitStop:
  call rbTest_ON
  in a,(7)
  and 3
  jr z,rb_waitStop
  ld a,$c0
  out (7),a
  rl e
  djnz rb_w_Start
  ld a,c
  ret
rbTest_ON:
  ld a,(_OP1)
  inc a
  ld (_OP1),a
  cp 255
  ret nz
  pop hl
  xor a
  ret