Subject: Tribbles

From: "Cyrano Jones" <cyranojones_lalp@...>
Date: Sun, 02 May 2004 09:50:06 -0000

unit unit_tribbles;

interface

function  sendbyte_as_tribbles(b: byte): boolean;
function  receivebyte_as_tribbles: byte;
function  receivebyte_as_tribbles_blocking: byte;
function  mailstationbusy: boolean;
procedure resettribble;
procedure resetmailstation; //on ms with reset mod only!

implementation
uses ports, crt, unit_globals; //globals is just for db flag

var timer: cardinal;
const bsyout = $08;
      stbout = $10;
      bsyin = $40;
      stbin = $80;
const tribmask: byte = $07;
      dibmask: byte = $03;

procedure e(code: integer);
begin
  if code=1 then
    writeln('timeout waiting for ms to drop busy.  ', code);
  if code=2 then
    writeln('timeout waiting for ms to ack.  ', code);
  if code=3 then
    writeln('timeout waiting for ms to strobe.  ', code);
  if code=4 then
    writeln('timeout waiting for ms to drop strobe.  ', code);
  if code=5 then
    writeln('timeout waiting for ms to drop busy/ack', code);
  if code=6 then
    writeln('aborted waiting for ms to send', code);
  errcount:=errcount+1;
  if errcount>20 then
  begin
    errcount:=0;
    writeln('Too many errors? hit esc to bail, other to continue:');
    repeat until keypressed; bail := (readkey = ^[);
    //bail needs to get reset somewhere!
  end;
end;

function sendtribble(t: byte): boolean;
begin
  timer:=250000; {arbitrary big number}
  //timer is dependent on your cpu speed, but this should be big enough.
  //timeouts should NOT happen, but if they do ('cause you forgot to hook
  //up the laplink) and this is too big, you will be waiting several
  //seconds or even weeks for the timeout error message.  I did it this
  //seemingly crappy way because I wanted the delay waiting for these
  //signal edges to be as short as possible.  I will leave it as an exercise
  //for someone who cares more than I do to calculate an appropriate cpu
  //speed dependent timeout value.

  portb[888] := bsyout;                     {raise our busy}

  repeat                                    {wait for ms to drop busy}
    timer:=timer-1;
    if timer=0 then begin e(1); exit(false); end;
  until (portb[889] and bsyin) = 0;
                                 //drop busy first, so won't trip reset
  portb[888] := t and tribmask;             {send trib & no busy }
  portb[888] := t and tribmask or stbout;   {send trib & strobe & no busy }

  repeat                                    {wait for ms to ack}
    timer:=timer-1;
    if timer=0 then begin e(2); exit(false); end;
  until (portb[889] and bsyin) <> 0;

  // drop strobe before raising busy, don't trip reset!!!
  portb[888] := 0;                          {drop strobe}
  portb[888] := bsyout;                     {drop strobe, raise busy}
  // busy stays up, till we wanna hear something.
  exit(true);
end;

function receivetribble: byte;
var t: byte;
    wastetime: cardinal;
begin
  //if db then write('receivetribble-');
  portb[888] := 0;  {drop our busy/ack}

  timer:=350000;    {arbitrary big number}

  repeat
    timer:=timer-1;
    if timer=0 then begin e(3); exit; end;
  until (portb[889] and stbin) = 0;         {wait for *inv* strobe}

  //delay(1); //should we wait for data to settle??? doesn't seem neccesary!
  t := portb[889] shr 3 and tribmask;       {grab trib}
  portb[888] := bsyout;                     {raise busy/ack}

  repeat
    timer:=timer-1;
    if timer=0 then begin e(4); exit; end;
  until (portb[889] and stbin) <> 0;        {wait for *inv* UNstrobe}
  //delay(1);//fudge, works, avoids false dataavail, but try in clearport instead

  //portb[888] := 0;  {drop busy/ack, so we're not sayin "I wanna send"}
  //portb[888] := bsyout;//TRY THIS, maybe don't want ms to send if we not listening
  // maybe busy means "I'm not listnen" rather than "I wanna talk"????
  // busy is left set since acking trib

  // The following repeat loop seems to stop false dataavail on clearports
  // (when clearport is called very close after here)
//// **** loop removed, to see if crud-catcher works instead
  //repeat
  //  timer:=timer-1;
  //  if timer=0 then begin e(5); exit(t); end;
  //until (portb[889] and bsyin) = 0;        {wait for UNbusy (done sendin)}
  //TODO: CHECK IF MBUG SEND ALWAYS DROPS its busy when done sendin,
  //      FERINST WHEN EXEC 'GO 0000'///////*********************
  exit(t);
end;

function sendbyte_as_tribbles(b: byte): boolean;
begin
  if not sendtribble(b) then exit(false);
  b:=b shr 3;
  if not sendtribble(b) then exit(false);
  b:=b shr 3;
  if not sendtribble(b) then exit(false);
  exit(true);
end;

function receivebyte_as_tribbles: byte;
var newbyte: byte;
begin
  //if db then write('receivebyte_as_tribbles---');
  newbyte := receivetribble + receivetribble shl 3 + (receivetribble and dibmask) shl 6;
  //if db then writeln;
  exit(newbyte);
end;

function receivebyte_as_tribbles_blocking: byte;
begin
// receivebyte_as_tribbles (above) will drop strobe (via receivetribble) and receive a byte, only if
// it comes within the timeout period.  Here we drop our busy before calling
// receivebyte_as_tribbles, and then wait for a strobe, avoiding the timeout
// that would occur if we just called receivebyte_as_tribbles directly.  When we see a
// strobe, we can hand off to the regular receivebyte_as_tribbles.
  portb[888] := 0;  {drop our busy/ack}

  repeat
    if keypressed then if readkey=^[ then begin e(6); exit($00); end;
  until (portb[889] and stbin) = 0;         {wait for *inv* strobe}

  exit(receivebyte_as_tribbles);
end;

function mailstationbusy: boolean;
begin
  exit((portb[889] and bsyin) <> 0);
end;

procedure  resettribble;
begin
  portb[888] := 0;
end;

procedure  resetmailstation;
// This will only reset a mailstation with my reset mod!!!!!
// It raises both busy and strobe together, which is detected by the mod.
// This saves using an extra conductor in cable, so a standard par laplink
// cable can be used.
begin
  portb[888] := stbout or bsyout;
  delay(100);  //3ms is minimum that works
  portb[888] := 0;
end;

end.

---

From: "John R. Hogerhuis" <jhoger@...>
Date: Sun, 02 May 2004 03:08:02 -0700

With the name Cyrano Jones, I knew the mortal enemies of the Klingon
Empire were going to come into the picture sooner or later.

---

From: "donhamilton2002" <donhamilton2002@...>
Date: Sun, 02 May 2004 19:02:19 -0000

--- In [email-masked], "Cyrano Jones"
> unit unit_tribbles;

WOW !

I have not seen pascal in years !!, or is this some pascal derivative.

Anyway,

Is there a schematic of the cable available ?

What is this extra wire you mentioned.

thanks

hamilton

---

From: "Cyrano Jones" <cyranojones_lalp@...>
Date: Mon, 03 May 2004 00:03:42 -0000

> I have not seen pascal in years !!, or is this some pascal derivative.

http://www.freepascal.org/

> Is there a schematic of the cable available ?

There are almost as many different pinouts for this cable
as there are websites with a pinout.  But all of them
have in common the pins that are actually used by the 
mailstation (pins 2, 3, 4, 5, 6, 15, 13, 12, 10, 11, and 
at least one of the eight ground pins) 

You need to cross the low 5 data pins at "one" end, to
the status pins at the other.
              D0  2  to  15
              D1  3  to  13 
              D2  4  to  12
              D3  5  to  10
              D4  6  to  11

And cross the 5 status lines at end "one" to the
low 5 data pins at the other. 
          /ACK 10  to  5
         BUSY 11  to  6 
PAPEROUT 12  to  4
            SEL 13  to  3
        /FAULT15  to  2

And at least one ground.
            GND 25 to 25 

> What is this extra wire you mentioned.

I used a Belkin F3D508-10.  IIRC, it did not
have any extra conductors, and I wanted to
be able to reset the mailstation from the PC.
So I added the logic to the mailstation
to reset whenever the PC asserted both
busy and strobe at the same time.  

NOTE!!!!! the "busy" and "strobe" signals refered
to in my code are NOT THE SAME as the
busy and strobe lines on your standard parallel port.
The signal names in the table above ARE the names
from the standard parallel port, just for reference.

I may make up a better diagram sometime.
Also, I noticed that the web inteface to the list
mangled the pascal code (removed indents).
I uploaded a zip of the same file to the file section.

Cyrano Jones