Re: LZ: Link Programming Help


[Prev][Next][Index][Thread]

Re: LZ: Link Programming Help



houston 00 wrote:
> Second, can somebody send me some examples of link programs (the source,
> please!)
K, read this attatchment.  :)

Cheers and Good Luck,
-- 
~Keith
TSK3000@Prodigy.Net
----
VISIT THE OFFICIAL CSHELL HOMEPAGE AT:
http://pages.prodigy.net/tsk3000/CShell/
This txt file covers the port 7 of the TI-85, that is the port that is 
connected to the link.  With the information presented here, you should
know enough to be able to write a two player game, a file transfer program,
or even connect two calculators together for any purpose.

Circuit-
The jack that connects the two calculators has three connections.  The big 
one is GND.  Then other two are W and R.  They are both at 5V when not 
activated and pulled to ground when they are.  

Example-
I wrote this program to help illustrate how the link works.  For now, just
type it in, it will all be clear later. (hopefully)

#include "TI-85.H"

;Program Title
.org 0
.db "Port 7",0

Init:
     CALL_ROM(CLEARLCD)
KeyLoop:
     call GET_KEY
     cp   $37
     jr   z, Exit
     cp   $02                 ; <-?
     jr   z, SendW
     cp   $03                 ; ->?
     jr   z, SendR
     cp   $01                 ; \/ ?
     jr   z, SendWR           
     cp   $04                 ; /\ ?
     jp   z, SendN
    

     ld   hl, $FC10
     in   a, ($07)
     ld   (hl), a
     ld   hl, $FC20
     ld   B, 11111111b
     ld   (hl), B

     jr   KeyLoop

SendN:
     ld   a, $C0
     out  ($07), a
     jr   KeyLoop

SendR:
     ld   a, $D4
     out  ($07), a
     jr   KeyLoop

SendW:
     ld   a, $E8
     out  ($07), a
     jr   KeyLoop

SendWR:
     ld   a, $FC
     out  ($07), a
     jr   KeyLoop

Exit:
     ld   a, $C0
     out  ($07), a
     ret
.end


This will display a guide line at the top left of the LCD and over 
that it will show the status of port 7.  The Left, Right, Down, and Up 
keys will control the output of turning W, R, both W and R, and neither
When you turn them active, you can see bits 2 and 3 turn on as they
are puuled to ground (0V).  Bits 1 and 0 show the input, notice if it
is not connected to anything that it will show both, meaning that they are
at 5V or not active.  When you turn on W or R, that pixel should shut off
as it is pulled to ground, becomes 0V and is active. (0V=active, 5V=not 
active).  Fool around with this, try hooking it up to someone elses
TI-85 and have them send or recieve stuff as you run port7.asm.  Learn 
from it.

Sending Junk-
Now that you know how it works (you do, right?)  Here is how to make it
do what you want.  Use the command 
out ($07), a
to send what's in the accumulator to the port 7.  Here is what you should
send:
11000000 ($C0) = Neither pulled to ground
11101000 ($E8) = W pulled to ground
11010100 ($D4) = R pulled to ground
11111100 ($FC) = W & R pulled to ground
So you jsut put the value in the accumulator and then out it to port 7!

Recieving Junk-
To recieve is also simple, just read the bottom two bytes (remember the
program at the begining)  Basicly if the bit is on then it is at 5V
and thus not active or off.  so you first 
in a, ($07) 
in order to put what's in port 7 into the accumulator. then you
and $03 
to mask off bits 0 and 1, the input bits.  then all you do is compare it 
to what you want.  
00000011 = Neither is pulled to ground
00000010 = R is pulled to ground
00000001 = W is pulled to ground
00000000 = R & W are pulled to ground
NOTE: you cannot tell wheither YOUR TI-85 or the TI-85 on the other end 
of the link cable are pulling it to ground.  You might try also putting
the rest into account, however.  

Protocols-
The protocol that the TI-85 uses to send bytes is as follows:
The sending 85 pulls one wire for bit 0:
     W=1   R=0
The recieving 85 pulls the other wire in confirmation
Both 85s clear the link
Loop again for next bit

Sending Code-
After reading about all of this I was still confused, so I dissasembled 
the resieve and send byte routines of the TI-85's ROM.  I discovered
their address from another GREAT txt file on port 7 (Don't ask me how
he figured them out) anyway, they are at page 5, 643Bh and 6559h
I will now go over and explain them (which is basicly the whole point 
of this text file, the previous stuff was review) 

;Send Byte   A=The sending byte
.org 0
     ld c, a        ; This just puts the byte to send in C
     ld b, $0008    ; There are 8 bits to send (Seriel remember)
SendBit:     
     ld de, $FFFF   ; This is for the timing loop
     rr c           ; This rotates the register c right and puts the right
                      bit in the carry flag.  So each loop has it's bit
                      put in the carry flag.  Pretty neat.
     jr nc, SendR   ; If there is no carry (i.e. the current bit is 0)
                      then send a R
     ld a, $E8      ; Else send a W because we have a 1
     jp SendIt      ; Then actually Send it!!
SendR:
     ld a, $D4      ; We have a 0, so send a R (D4h)
SendIt:
     out ($07), a   ; This actually sends it!
WaitConfirmation:
     in a, ($07)    ; Read the port
     and $03        ; Mask off bits 1 and 0 (see above text)
     jp z, Continue ; If it is zero (both R and W pulled to ground,
                      then continue
     in a, ($07)    ; If not, then read the port and try again
     and $03
     jp z, Continue 
     dec de         ; Both wern't active that means the calc on the
                      other side hasn't received it (The other TI should
                      pull the other one to ground to show that it has
                      recieved the bit) so loop through and try again.
                      It uses de as a counter (it was set in the beg)
     ld a, d
     or e           ; This basiclly does or e,d and will make z 0 if both
                      d and e are zero, or de is zero. (i.e. counter is
                      0 and we are done with loop, or a time-out)
     jp nz, WaitConfirmation 
Error:
     jp ErrorHandler; Branislav suggested this was an error handler,
                      I don't know, but whatever the case don't include it
                      in your implementations.  Instead, put in a jr to your
                      own error handlers.
     ld a, $0C      ; Get ready to clear R & W (C0h = both off, see above)
     out ($07), a   ; Actually clear them
     ld de, $FFFF   ; Get de counter ready for next loop to make sure 
                      link is cleared.  when de reaches 0 it times out.
ClearLoop:     
     dec de
     ld a, d
     or e           ; Again this is or e,d and will continue if de is not 0
     jr z, Error    ; We timed out, so go to error handler (see above)
     in a, ($07)    ; Read the port 7 again
     and $03        ; Performs a Self-Destruct
     cp $03         ; makes sure link is cleared, or both are not active
                      or both are at 5V
     jp nz, ClearLoop ; If not, then clear and wait again.   
     djnz SendBit   ; Basiclky a 'dec b' & 'jr nz, SendBit'  It will loop
                      again to send the next bit
     ret            ; Goes back to your program

You should use a method similar to this when making your programs.  Make
sure to always shut off both W and R when you are done using them, put 
them at 5V, send C0h to port 7.  Isn't it amazing all the work that 
calculator does while all you see is that little worm move in the upper
right corner of your LCD. :)

Recieve Byte Code-
;Recieve Byte A=recieved byte
     .org 0
     ld b, $08      ; There are 8 bits to recieve
     ld de, $FFFF   ; Setup timeout counter to wait for bit
                      if this de reaches 0 it is a time-out and it goes
                      to an error handler
     jr WaitLoopEnd ; This jumps to the end of the loop, I have NO idea
                      why this "jr" is here???
WaitLoop:
     in a, ($07)    ; Read port 7
     and $03        ; Mask the last two bits
     jr z, Error    ; Cause an error if BOTH are active
     cp $03         ; Compare it to 11 (Both NOT active)
     jp nz, Continue; If at least one is active, continue.  
                      Notice if both were active it would have caused an
                      error, so this is really only one being active
     in a, ($07)    ; Read port 7 again
     and $03        ; Mask the last two bits
     jr z, Error    ; I think this will cause an error if they are BOTH
                      active
     cp $03
     jp nz, Continue; Same as last time, continue if at lesat 1 is active
     dec de         ; Decrease counter
     ld a, d
     or e           ; or d, e
     jp nz, WaitLoop; If counter (de) is not 0 then loop again.
     jp TimeOut     ; Cause an error if we timed out waiting for a bit
Continue:
     sub $02        ; This is where is gets interesting.  It will subtract
                      10b from the accumulator (or the last two bits of
                      what it received)  Remember a W=1 R=0. 
                      So:    W        R
                            01       10
                           -10 (02) -10
                           ----     ----
                            01 C     00  
                      The C means the carry flag was set because the result 
                      was less then 0, (-1h)  So now the Carry flag is set
                      if we recieved a W and clear if we recieved a R.  NICE
     jp nc, Got0    ; Go to the part for receiving a 0 if we had no carry
                      flag set (we got an R)
---------------------------------------------------------------------------
Got1:
     ld a, $D4      ; Get ready to send a R ($D4 = Send a R, see above text)
     out ($07), a   ; Send the W in confirmation that we recieved the bit.
                      now, both wires should be pulled
     rr c           ; This is neat.  We recieved a W or a 1, because of that
                      our carry flag was set. so now we are rotating that 
                      carry flag into the register c.  So each loop will
                      rotate the recieved bit into c until we have the 
                      complete byte.
     ld de, $FFFF   ; Get counter ready
LoopR:
     in a, ($07)    ; Read the link
     and $03        ; Tell the calc to emmit radio interference
     cp $02         ; Is the R (and ONLY the R) active?
                      The reason it does this is becasue when the sending
                      85 receives the confirmation signal it will clear it's
                      port, thus the W it sent will not be active when 
                      the port it clear.  The R will be, however, because
                      WE are the ones pulling it.  
     jp z, ClearLink
     dec de         ; lower time-out counter
     ld a, d
     or e           ; or e, d
     jp nz, LoopR   ; Loop until sending 85 has cleared it's side of the 
                      link.
     jr Error       ; We timed out, so cause an error.
--------------------------------------------------------------------------
ClearLink:
     ld a, $C0      ; get ready to clear our side of the link
     out ($07), a   ; Just Do It!
     ld d, $04      ; Get counter ready.  The reason it is so low is that
                      this time we aren't waiting for the other 85 to do
                      anything.  We are just clearing our side, so it SHOULD
                      clear AS SOON as we do it.  Thus the 3 loops.
ClearLoop:     
     dec d          ; Lower counter
     jr z, NextBit  ; If we time-out it says, "oh well" and continues with 
                      the next loop.  We can do this because if there is an
                      error, it will catch it on the next bit.  Note: there
                      is no need for the or d, e shtuph because we are
                      only dealing with the d, not de.
     in a, ($07)    ; See a pattern?
     and $03        
     cp $03         ; Is it clear?
     jp nz, ClearLoop ; If it's not clear, try again
NextBit:
     djnz WaitLoop  ; Go back and do it ALL over again if B is not 0
                      i.e. we have more bits to recieve
     ld a, c        ; We don't have any more bits to recieve, so put the
                      received byte in a.
     ret            ; and return ($C9)

----------------------------------------------------------------------------
Got0:
     ld a, $E8      ; This is where we were sent if we got a R (0)
                      Put E8h into a to send a confirming W
     out ($07), a   ; Confirm
     rr c           ; rotate the 0 (of the carry flag) into the register c
     ld de, $FFFF   ; Get counter ready for loop
LoopW:
     in a, ($07)    ; perform a memory checksum :)
     and $03        ; Mask off last two bits.
     cp $01         ; Is ONLY the W active.  (See above for indepth analysis)
     jp z, ClearLink; Go clear link and finish 
     dec de         ; Decrease counter
     ld a, d
     or e           ; or e, d
     jp nz, LoopW   ; Keep Looping!
Error:
     jr ErrorHandler ; This is where we are sent if there is an error 
                      (except for one time at the beg) It goes off
                      somewhere in lala land.

OK!  You should now thoughrouly understand the port 7 and how to use it.
Remember, don't limit yourself to this, get creative.  And also remember I
didn't write this code, it is the ROM function call that is built into 
the TI-85.  I would like to thank Dan Eble (TI-85 GOD!), Branislav 
Bozgai, and of course Texas Instruments.  If you have any comments or 
questions you can reach me at:
site@xnet.com

References: