*/
Want to see what people are talking about? See the latest forum posts.
*/

View \COMBAR.PAS

QCOM is a small library of RS232 communications routines

Submitted By: WEBMASTER
Rating: starstarstarstarstar (Rate It)


{ Copyright (C) 1989 by Alpac Systems
                        Finn J. R. Nielsen
                        1741 W. Orchid Lane
                        Phoenix, AZ 85021 }

Program ComBar; uses QCom, Crt, Dos;

Const
  minSize = 256;          { Limits for various size queues }
  medSize = 3000;
  maxSize = 6000;

  Full_block = 219;       { graphics character values }
  Low_block = 221;
  Esc = 27;
  Cr = 13;

  baud_labels: array[ord(B110)..ord(B38400)] of word =
               (110,150,300,600,1200,2400,4800,9600,19200,38400);
  protocol_labels: array[ord(XoffProtocol)..ord(DsrProtocol)] of string[13] =
                   ('Xoff Protocol','Dsr Protocol ');

Var
  Comm1, Comm2: ^CommPort;
  Config: commConfig;
  testBaud: BaudRates;
  testProtocol: ProtocolType;
  done, completely_done: boolean;
  origVideo: byte;
  msgLimit, inLimit, outLimit: word;
  inCurMsgNo, outCurMsgNo, inErr: word;
  curQ1, curQ2: word;
  ch: char;
  testStart: longint;

{ Get a time stamp with resolution to nearest second for elapsed time
  calculations }

Function timeStamp: longint;
Var
  hour, min, sec, hund: word;
Begin
  GetTime(hour,min,sec,hund);
  if hund > 50 then inc(sec);
  timeStamp := sec + min*60 + hour*3600;
End;

{ Display a text string at specified screen coordinates }
Procedure Display(X,Y: integer; msg: string255);
Begin
  GotoXY(X,Y);
  Write(msg);
End;

{ Show a status message in upper right corner of screen - update elapsed
  time display }

Procedure Status(statColor: byte; Msg: string255);
Var
  oldAttr: byte;

Begin
  oldAttr := textAttr;
  gotoXY(68,2);
  textBackground(statColor);
  textColor(White);
  highVideo;
  write(Msg);
  textAttr := oldAttr;
  gotoXY(35,16); write(timeStamp - testStart,'  ');
End;

{ Produce a bar graph, which approximates the occupancy rate of a
  specified queue. In this case, the display is VERY "approximate".}

Procedure UpdGraf(Var prevVal: word; Y, qCount, qSize: word);
Var
  oldAttr: byte;
  longTemp: longInt;
  bar_ch: char;
  newInc, newQ: integer;
  ix: word;

Begin
  oldAttr := textAttr;
  textBackground(Black);
  textColor(Red);
  longTemp := qCount * longint(150);
  newQ := longTemp div qSize;
  newInc := newQ - ((prevVal shr 1) shl 1);
  bar_ch := char(Full_block);
  if newInc > 0 then gotoXY(4+(prevval shr 1),Y)
  else
  begin
    bar_ch := char(Low_block);
    textColor(Green);
    gotoXY(4+(newQ shr 1),Y);
    write(bar_ch);
  end;
  if (newInc shr 1) <> 0 then
    for ix := 0 to (abs(newInc) shr 1) do write(bar_ch);
  if (newInc mod 2) <> 0 then write(bar_ch);
  textAttr := oldAttr;
  prevVal := newQ;
End;

Procedure UpdQueueGraf;
Begin
  UpdGraf(curQ1,11,Comm1^.oCount,Comm1^.oSize);
  UpdGraf(curQ2,14,Comm2^.iCount,Comm2^.iSize);
End;

Procedure FinishScreen;
Begin
  Status(Black,'Finished ...');
  textAttr := origVideo;
  gotoXY(1,23);
End;

{ Initialize the test screen }
Procedure InitScreen;
Begin
  clrScr;
  origVideo := textAttr;
  textAttr := 7;
  highVideo;
  display(4,3,'Turnaround Cable Test (COM1: and COM2:)');
  lowVideo;
  textColor(Cyan);
  display(4,18,'Protocol:');
  display(40,18,'Baud rate:');
  display(4,22,'(Press any key for next test, <esc> to exit)');
  display(4,5,'Writing COM1: until >       bytes in output queue');
  display(4,6,'Reading COM2: until <      bytes in input queue');
  display(4,8,'Input msg:');
  display(4,10,'COM1: output queue (6,000 bytes):');
  display(4,13,'COM2: input queue (3,000 bytes):');
  display(4,16,'Elapsed seconds for this test:');
  textColor(Blue);
  display(4,20,
  'Program material Copyright (C) 1989 by Alpac Systems and Finn J. Nielsen');
  textAttr := 7;
  inErr := 0;
  curQ1 := 0;
  curQ2 := 0;
End;

{ Initialize the comm ports to default configurations }
Procedure InitPorts;
Begin
  Comm1 := Connect(1,minSize,maxSize);
  Comm2 := Connect(2,medSize,minSize);
  Config := DeflCfg;
End;

{ Assign random values to queue char limits }
Procedure ChooseParams;
Begin
  inLimit := random(medSize div 2);
  gotoXY(26,6); write(inLimit:4);
  outLimit := random(maxSize * 3 div 4);
  gotoXY(26,5); write(outLimit:5);
End;

{ Generate some output messages. Stop when the output queue fills beyond
  the limit specified in "outLimit" variable }

Procedure FillOutQ;
Var
  outMsg: string255;

Begin
  Status(Red,'Writing ... ');
  while (Comm1^.oCount < outLimit) and (not keypressed) do
  begin
    inc(outCurMsgNo);
    str(outCurMsgNo:6,outMsg);
    outMsg := 'Test message (34 bytes) no:'+outMsg+#13;
    PutString(Comm1,outMsg);
    updQueueGraf;
  end;
End;

{ Idle routine - waits for some data to be received in the input queue.
  If the transmitter doesn't have anything to send, then idle is also
  terminated. }

Procedure Idle;
Begin
  Status(Cyan,'Idling ...  ');
  repeat
    updQueueGraf;
  until
    ((Comm1^.CommFlags and XmitOn) = 0) or
    (Comm1^.oCount = 0) or
    keypressed;
End;

{ Read input messages until the input queue has fewer characters left than
  specified by "inLimit" variable.}

Procedure GetMessages;
Var
  inMsg, tempMsg: string255;
  convNo, convCode: word;
  oldVideo: byte;

Begin
  Status(Green,'Reading ... ');
  while (Comm2^.iCount > inLimit) and not keypressed do
  begin
    inc(inCurMsgNo);
    inMsg := GetString(Comm2,nil);
    tempMsg := copy(inMsg,28,6);
    val(tempMsg,convNo,convCode);
    tempMsg := copy(inMsg,1,27);
    if (length(inMsg) <> 34) or    { check input message integrity }
       (convCode <> 0) or
       (inMsg[34] <> #13) or
       (convNo <> inCurMsgNo) or
       (tempMsg <> 'Test message (34 bytes) no:') then
    begin
      inc(inErr);                  { lost some data, count errors and show }
      gotoXY(50,8);
      write('Lost data on ',inErr:4,' messages');
    end;
    tempMsg := copy(inMsg,1,34);
    oldVideo := textAttr;
    textBackground(Blue);
    display(15,8,tempMsg);
    textAttr := oldVideo;
    updQueueGraf;
  end;
End;

{ Flush both input and output queues by reading on the input side. The
  bargraph is interesting during this test section. Since updating the
  bargraph is relatively time consuming, and the update is done once
  for every character read, characters are received faster than they
  can be processed. The output buffer often has more data than can be
  contained in the smaller input queue. As a result, the bargraph visually
  shows the effect of transmission throttling by the protocol transfer }

Procedure FlushQueues;
Var
  ch: char;

Begin
  if keypressed then
  begin
    ch := readkey;
    done := (ch = char(Esc));
  end;
  if not done then
  begin
    Status(Blue,'Flushing ...');
    repeat
      while (Comm1^.oCount > 0) or (Comm2^.iCount > 0) do
      begin
        ch := GetChar(Comm2,nil);
        updQueueGraf;
      end;
      delay(10); {catch characters in transit - not in outq and not in inq }
    until (Comm1^.oCount = 0) and (Comm2^.iCount = 0);
  end;
  gotoXY(15,8); write(' ':34); { erase displayed input message }
End;

{ Main program

    Displays a screen showing progress of the test. The test itself is
    intended to do the following:

    1. Loop through various baud rates (starting with the high ones - so
       test can be aborted when boredom sets in at lower rates).

    2. For each baud rate loop through the available protocols.

    3. For each configuration of baud rate and protocol run a test
       consisting of some output and input messages. The number of
       messages used depends on the line speed assigned for the current
       test.

    4. Each test generates a sequence of output messages. These messages
       are inserted in the COM1: output queue. Output is suspended when
       a random upper limit is reached in the output queue (notice that
       the output queue is larger than the COM2: receiving queue).

    5. When output is suspended, enter an idle loop to wait for an
       appropriate amount of data to be received into the COM2: input
       queue. The amount of data to be received during the idle is
       either the amount required to empty the sending (COM1: output)
       queue or the amount required to trigger COM1: output suspension
       due to queue congestion in the COM2: input queue. Input queue
       congestion is signalled differently, depending on the active
       protocol.

    6. After the idle loop is finished, read some of the COM2: input
       data. The amount read is determined by a random character count.
       For each message read, check for message integrity. If any bad
       messages are found, the screen will be updated to show a count
       of bad messages.

    7. Before changing configuration (line speed or protocol), flush
       all queues on both the input and the output side. Queues are
       flushed by reading on the input side. Protocol handling is active
       during the flush.

    8. During the entire testing process, display two bargraphs showing
       the relative occupancy of the two queues. }

Begin
  Randomize;
  InitScreen;
  InitPorts;
  done := false;
  repeat
    For testBaud := B38400 downto B1200 do {skip really slow rates }
      For testProtocol := XoffProtocol to DsrProtocol do
        if not done then
        begin
          testStart := timeStamp;
          msgLimit := sqr(ord(testBaud)+1) * 8; { no of msgs in this test }
          outCurMsgNo := 0;                     { init message counters }
          inCurMsgNo := 0;
          Config.Baud := testBaud;
          Config.Protocol := testprotocol;
          SetConfig(Comm1,Config);
          SetConfig(Comm2,Config);
          repeat
            ChooseParams;                       { set buffer parametrs }
            display(14,18,protocol_labels[ord(testProtocol)]);
            gotoXY(51,18); write(baud_labels[ord(testBaud)],' ');
            FillOutQ;                           { generate some output }
            Idle;                               { idle until input received }
            GetMessages;                        { retrieve the input }
          until keypressed or (outCurMsgNo > msgLimit);
          FlushQueues;                          { flush both queues }
        end;
  until done;                                   { until <esc> is typed }
  FinishScreen;                                 { clean up screen }
End.

corner
© 1996-2008 CommunityHeaven LLC. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
North American business development: Nicolai Wadstrom. Publisher: Lars Hagelin.