MODULE V24Tracer;
IMPORT
Commands, Streams, Modules, KernelLog, Serials;
TYPE
SerialPortTracer = OBJECT
VAR
port : Serials.Port;
seq : LONGINT;
ch : CHAR;
V24writer : Streams.Writer;
alive : BOOLEAN;
res : LONGINT;
PROCEDURE &Init*(seqNo, portNo, bps : LONGINT);
BEGIN
port := Serials.GetPort(portNo);
IF res = 0 THEN
port.Open(bps, 8, Serials.ParNo, Serials.Stop1, res);
Streams.OpenWriter(V24writer, port.Send);
seq := seqNo
END;
END Init;
PROCEDURE Close;
BEGIN
alive := FALSE;
port.Close()
END Close;
BEGIN {ACTIVE}
alive := TRUE;
WHILE alive DO
port.ReceiveChar(ch, res);
IF res = Serials.Ok THEN
IF fine THEN (* Display the origin of each character, its hex value and its printable value *)
KernelLog.Ln; KernelLog.Int(seq, 0); KernelLog.String(" --> : ");
KernelLog.Hex(ORD(ch), -2); KernelLog.Char("X");
IF ORD(ch) > 32 THEN KernelLog.String(" "); KernelLog.Char(ch) END
ELSE (* Display a stream of characters with the same origin. In order to obtain this result,
it is preferable, when a modem is tested, to operate it without echo - use an ATE0 command. *)
IF seq # activeseq THEN
activeseq := seq;
KernelLog.Ln; KernelLog.Int(seq, 0); KernelLog.String(" --> : ")
END;
IF ORD(ch) > 32 THEN KernelLog.Char(ch)
ELSIF (ch = " ") OR (ch = 0DX)OR (ch = 0AX) THEN KernelLog.Char(" ")
ELSE IF ch # 0AX THEN KernelLog.Hex(ORD(ch), -2); KernelLog.Char("X") END
END;
END;
(* Send the character just received to the other port *)
tracingport[(seq + 1) MOD 2].V24writer.Char(ch);
tracingport[(seq + 1) MOD 2].V24writer.Update();
ELSE
alive := FALSE;
KernelLog.String("Character in error "); KernelLog.Char(ch); KernelLog.Int(res, 4); KernelLog.Ln;
END;
END;
KernelLog.String("Tracer "); KernelLog.Int(seq, 0); KernelLog.String(" terminated."); KernelLog.Ln
END SerialPortTracer;
VAR running, fine : BOOLEAN;
tracingport : ARRAY 2 OF SerialPortTracer;
activeseq : LONGINT;
PROCEDURE SetMode*(context : Commands.Context);
VAR name : ARRAY 100 OF CHAR;
BEGIN
IF context.arg.GetString(name) & (name = "fine") THEN fine := TRUE ELSE fine := FALSE END;
context.out.String("Tracing mode "); context.out.String(name); context.out.Ln;
END SetMode;
PROCEDURE Enable*(context : Commands.Context);
VAR inPort, outPort, baud : LONGINT;
BEGIN
context.arg.SkipWhitespace; context.arg.Int(inPort, FALSE);
context.arg.SkipWhitespace; context.arg.Int(outPort, FALSE);
context.arg.SkipWhitespace; context.arg.Int(baud, FALSE);
NEW(tracingport[0], 0, inPort, baud);
NEW(tracingport[1], 1, outPort, baud);
running := TRUE;
context.out.String("Tracing active ... "); context.out.Ln;
activeseq := -1;
END Enable;
PROCEDURE Finalize;
END Finalize;
PROCEDURE Disable*;
BEGIN
tracingport[0].Close();
tracingport[1].Close();
END Disable;
BEGIN
fine := TRUE;
Modules.InstallTermHandler(Finalize)
END V24Tracer.
Use:
1. Add the device to be traced to serialport 0
2. Add the machine that knows the device to serialport 1 (eg. Windows/Linux/Unix/... with driver)
3. Start the tracer, guessing the connection settings eg. baud rate (coarse mode is better in many cases)
4. Start using the device
5. Look at the data in the kernel log
6. If output looks strange, disable the tracer, reguess the connection settings and goto 3
V24Tracer.Enable 0 1 9600 ~ InPort OutPort bps
V24Tracer.SetMode coarse ~
V24Tracer.SetMode fine ~
V24Tracer.Disable ~
SystemTools.Free V24Tracer ~