Browse Source

revived ShellSerial

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@7657 8c9fc860-2736-0410-a75d-ab315db34111
eth.morozova 7 years ago
parent
commit
1281d69baa
1 changed files with 195 additions and 210 deletions
  1. 195 210
      source/ShellSerial.Mod

+ 195 - 210
source/ShellSerial.Mod

@@ -4,10 +4,10 @@ MODULE ShellSerial; (** AUTHOR "staubesv/be" PURPOSE "Serial port utilities for
  *
  *
  * Usage:
  * Usage:
  *
  *
- *	ShellSerial.Open [portNbr BitsPerSecond Parity StopBits] ~ opens a shell listening to serial port <portNbr>
+ *	ShellSerial.Open [portNbr BitsPerSecond DataBits Parity StopBits] ~ opens a shell listening to serial port <portNbr>
  *
  *
- *	ShellSerial.YReceive [[filename] portNbr BitsPerSecond Parity StopBits] ~
- *	ShellSerial.XReceive [[filename] portNbr BitsPerSecond Parity StopBits] ~
+ *	ShellSerial.YReceive [[filename] portNbr BitsPerSecond DataBits Parity StopBits Prompt] ~
+ *	ShellSerial.XReceive [[filename] portNbr BitsPerSecond DataBits Parity StopBits Prompt] ~
  *
  *
  *	Whereas
  *	Whereas
  *		Parity = "odd"|"even"|"mark"|"space"|"no"
  *		Parity = "odd"|"even"|"mark"|"space"|"no"
@@ -15,7 +15,7 @@ MODULE ShellSerial; (** AUTHOR "staubesv/be" PURPOSE "Serial port utilities for
  *
  *
  * Examples:
  * Examples:
  *
  *
- *	ShellSerial.Open 1 115200 no 1 ~
+ *	ShellSerial.Open 1 115200 no 1 8 ~
  *	ShellSerial.YReceive ~
  *	ShellSerial.YReceive ~
  *	ShellSerial.XReceive ~
  *	ShellSerial.XReceive ~
  *
  *
@@ -25,164 +25,146 @@ MODULE ShellSerial; (** AUTHOR "staubesv/be" PURPOSE "Serial port utilities for
  *)
  *)
 
 
 IMPORT
 IMPORT
-	Modules, Kernel, Commands, Streams, Strings, Files, Serials, Shell, XYModem;
+	Modules, Kernel, Commands, Streams, (*Strings,*) Files, Serials, Shell, XYModem;
 
 
 CONST
 CONST
-
-	(* Serial port default settings *)
-	DefaultPort = 1;
-	DefaultBPS = 115200; DefaultParity = Serials.ParNo; DefaultStop = Serials.Stop1;
-
 	BufferSize = 1024;
 	BufferSize = 1024;
 
 
-	Prompt = "SHELL>";
+	DefaultPrompt = "SHELL>";
 
 
 VAR
 VAR
 	shells : ARRAY Serials.MaxPorts + 1 OF Shell.Shell;
 	shells : ARRAY Serials.MaxPorts + 1 OF Shell.Shell;
 
 
-(** Receive a file using Y-modem protocol *)
-PROCEDURE YReceive*(context : Commands.Context); (** [[filename] portNbr BitsPerSecond Parity StopBits] ~ *)
+PROCEDURE ModemReceive(context : Commands.Context; modemMode: LONGINT); (** [[filename] portNbr BitsPerSecond DataBits Parity StopBits] ~ *)
 VAR
 VAR
 	name : Files.FileName; file : Files.File;
 	name : Files.FileName; file : Files.File;
-	port : Serials.Port; portNbr, bps, parity, stop, res : LONGINT;
-	shellBps, shellData, shellParity, shellStop : LONGINT; isOpen : BOOLEAN;
+	port : Serials.Port; portNbr, bps, data, parity, stop, res : LONGINT;
+	isOpen0 : BOOLEAN;
+	bps0, data0, parity0, stop0 : LONGINT;
 	recv : XYModem.Receiver; awaitF : BOOLEAN;
 	recv : XYModem.Receiver; awaitF : BOOLEAN;
 	w : Streams.Writer; r : Streams.Reader;
 	w : Streams.Writer; r : Streams.Reader;
 	error: ARRAY 64 OF CHAR;
 	error: ARRAY 64 OF CHAR;
-BEGIN {EXCLUSIVE}
-	IF GetXYPars(context, name, portNbr, bps, parity, stop) THEN
-
-		port := Serials.GetPort(portNbr);
-		IF port = NIL THEN
-			context.error.String("Cannot find port "); context.error.Int(portNbr, 0); context.error.Ln;
-			RETURN;
-		END;
-
-		IF shells[portNbr] # NIL THEN
-			port.GetPortState(isOpen, shellBps, shellData, shellParity, shellStop);
-			IF isOpen THEN port.Close; END;
-		END;
-
-		port.Open(bps, 8, parity, stop, res);
-		IF res # Serials.Ok THEN
-			context.error.String("Could not open port "); context.error.Int(portNbr, 0); context.error.Ln;
-			RETURN;
-		END;
+	isTracePort: BOOLEAN;
+BEGIN
+	IF ~context.arg.GetString(name) THEN
+		context.result := 1;
+		context.error.String("Invalid port settings, res="); context.error.Int(res,0); context.error.Ln;
+		RETURN;
+	END;
+	
+	Serials.GetPortParameters(context.arg, portNbr, bps, data, parity, stop, res);
+	IF res # 0 THEN
+		context.result := 2;
+		context.error.String("Invalid port settings, res="); context.error.Int(res,0); context.error.Ln;
+		RETURN;
+	END;
 
 
-		context.out.String("YReceive "); context.out.String(name); context.out.Ln;
-		IF name # "" THEN
-			file := Files.New(name); awaitF := FALSE
-		ELSE
-			file := NIL; awaitF := TRUE
-		END;
+	port := Serials.GetPort(portNbr);
+	IF port = NIL THEN
+		context.result := 3;
+		context.error.String("Cannot find port "); context.error.Int(portNbr, 0); context.error.Ln;
+		RETURN;
+	END;
 
 
-		NEW(w, port.Send, BufferSize); NEW(r, port.Receive, BufferSize);
-		NEW(recv, w, r, file, XYModem.YModem);
-		IF ~awaitF THEN
-			recv.Await(error)
-		ELSE
-			recv.AwaitF(file, error)
-		END;
+	port.GetPortState(isOpen0, bps0, data0, parity0, stop0);
 
 
-		port.Close();
+	(* disable tracing over the selected port *)
+	IF Serials.IsTracePort(port) THEN
+		isTracePort := TRUE;
+		Serials.SetTracePort(-1,0,0,0,0, res);
+	END;
 
 
-		IF shells[portNbr] # NIL THEN
-			port.Open(shellBps, shellData, shellParity, shellStop, res);
-			IF res # Serials.Ok THEN
-				context.error.String("Warning: Could not re-open shell port "); context.error.Int(portNbr, 0); context.error.Ln;
-			END;
+	port.Close;
+	port.Open(bps, data, parity, stop, res);
+	IF res # Serials.Ok THEN
+		
+		context.result := 4;
+		
+		context.error.String("Could not open port "); context.error.Int(portNbr, 0);
+		context.error.String(", res="); context.error.Int(res,0);
+		context.error.Ln;
+
+		IF isTracePort THEN
+			Serials.SetTracePort(portNbr, bps0, data0, parity0, stop0, res);
+		ELSIF isOpen0 THEN
+			port.Open(bps0, data0, parity0, stop0, res);
 		END;
 		END;
 
 
-		Wait(1000); (* Give the port open time so we see the output below *)
-
-		IF error # "" THEN
-			context.error.String(" "); context.error.String(error)
-		ELSE
-			Files.Register(file);
-			IF awaitF THEN
-				file.GetName(name);
-				context.out.String("  "); context.out.String(name);
-				context.out.String(" ("); context.out.Int(file.Length(), 0); context.out.String(" Bytes"); context.out.String(")");
-			END;
-			context.out.String(" done.");
-		END;
-		context.out.Ln;
+		RETURN;
 	END;
 	END;
-END YReceive;
 
 
-(** Receive a file using X-modem protocol *)
-PROCEDURE XReceive*(context : Commands.Context); (** [[filename] portNbr BitsPerSecond Parity StopBits] ~ *)
-VAR
-	name : Files.FileName; file : Files.File;
-	port : Serials.Port; portNbr, bps, parity, stop, res: LONGINT;
-	recv : XYModem.Receiver; awaitF : BOOLEAN;
-	w : Streams.Writer; r : Streams.Reader;
-	shellBps, shellData, shellParity, shellStop : LONGINT; isOpen : BOOLEAN;
-	error: ARRAY 64 OF CHAR;
-BEGIN
-	IF GetXYPars(context, name, portNbr, bps, parity, stop) THEN
+	IF (modemMode = XYModem.XModem) OR (modemMode = XYModem.XModem1K) THEN
+		context.out.String("XReceive ");
+	ELSE
+		context.out.String("YReceive ");
+	END;
 
 
-		port := Serials.GetPort(portNbr);
-		IF port = NIL THEN
-			context.error.String("Cannot find port "); context.error.Int(portNbr, 0); context.error.Ln;
-			RETURN;
-		END;
+	context.out.String(name); context.out.Ln;
+	IF name # "" THEN
+		file := Files.New(name); awaitF := FALSE
+	ELSE
+		file := NIL; awaitF := TRUE
+	END;
 
 
-		IF shells[portNbr] # NIL THEN
-			port.GetPortState(isOpen, shellData, shellBps, shellParity, shellStop);
-			IF isOpen THEN port.Close; END;
-		END;
+	NEW(w, port.Send, BufferSize); NEW(r, port.Receive, BufferSize);
+	NEW(recv, w, r, file, modemMode);
+	IF ~awaitF THEN
+		recv.Await(error)
+	ELSE
+		recv.AwaitF(file, error)
+	END;
 
 
-		port.Open(bps, 8, parity, stop, res);
-		IF (res # Serials.Ok) THEN
-			context.error.String("Could not open port "); context.error.Int(portNbr, 0); context.error.Ln;
-			RETURN;
-		END;
+	port.Close();
 
 
-		context.out.String("YReceive "); context.out.String(name); context.out.Ln;
-		IF name # "" THEN
-			file := Files.New(name); awaitF := FALSE
-		ELSE
-			file := NIL; awaitF := TRUE
-		END;
-
-		NEW(w, port.Send, BufferSize); NEW(r, port.Receive, BufferSize);
-		NEW(recv, w, r, file, XYModem.XModem);
-		IF ~awaitF THEN
-			recv.Await(error)
-		ELSE
-			recv.AwaitF(file, error)
+	IF isTracePort THEN
+		Serials.SetTracePort(portNbr, bps0, data0, parity0, stop0, res);
+		IF res # Serials.Ok THEN
+			context.error.String("Warning: could not re-activate trace over port "); context.error.Int(portNbr, 0);
+			context.error.String(", res="); context.error.Int(res,0);
+			context.error.Ln;
 		END;
 		END;
-
-		port.Close();
-
-		IF shells[portNbr] # NIL THEN
-			port.Open(shellBps, shellData, shellParity, shellStop, res);
-			IF (res # Serials.Ok) THEN
-			END;
+	ELSIF isOpen0 THEN
+		port.Open(bps0, data0, parity0, stop0, res);
+		IF res # Serials.Ok THEN
+			context.error.String("Warning: could not re-open port "); context.error.Int(portNbr, 0);
+			context.error.String(", res="); context.error.Int(res,0);
+			context.error.Ln;
 		END;
 		END;
+	END;
 
 
-		Wait(1000); (* Give the port open time so we see the output below *)
+	Wait(1000); (* Give the port open time so we see the output below *)
 
 
-		IF error # "" THEN
-			context.error.String(" "); context.error.String(error)
-		ELSE
-			Files.Register(file);
-			IF awaitF THEN
-				file.GetName(name);
-				context.out.String("  "); context.out.String(name);
-				context.out.String(" ("); context.out.Int(file.Length(), 0); context.out.String(" Bytes"); context.out.String(")");
-			END;
-			context.out.String(" done.");
+	IF error # "" THEN
+		context.result := 5;
+		context.error.String(" "); context.error.String(error)
+	ELSE
+		Files.Register(file);
+		IF awaitF THEN
+			file.GetName(name);
+			context.out.String("  "); context.out.String(name);
+			context.out.String(" ("); context.out.Int(file.Length(), 0); context.out.String(" Bytes"); context.out.String(")");
 		END;
 		END;
+		context.out.String(" done.");
 		context.out.Ln;
 		context.out.Ln;
 	END;
 	END;
+END ModemReceive;
+
+(** Receive a file using X-modem protocol *)
+PROCEDURE XReceive*(context : Commands.Context); (** [[filename] portNbr BitsPerSecond DataBits Parity StopBits] ~ *)
+BEGIN
+	ModemReceive(context,XYModem.XModem);
 END XReceive;
 END XReceive;
 
 
-PROCEDURE IsDigit(ch: CHAR): BOOLEAN;
+(** Receive a file using Y-modem protocol *)
+PROCEDURE YReceive*(context : Commands.Context); (** [[filename] portNbr BitsPerSecond DataBits Parity StopBits] ~ *)
+BEGIN
+	ModemReceive(context,XYModem.YModem);
+END YReceive;
+
+(*PROCEDURE IsDigit(ch: CHAR): BOOLEAN;
 BEGIN
 BEGIN
 	RETURN (ch >= "0") & (ch <= "9")
 	RETURN (ch >= "0") & (ch <= "9")
-END IsDigit;
+END IsDigit;*)
 
 
 PROCEDURE Wait(ms: LONGINT);
 PROCEDURE Wait(ms: LONGINT);
 VAR timer: Kernel.Timer;
 VAR timer: Kernel.Timer;
@@ -190,119 +172,122 @@ BEGIN
 	NEW(timer); timer.Sleep(ms);
 	NEW(timer); timer.Sleep(ms);
 END Wait;
 END Wait;
 
 
-PROCEDURE GetXYPars(context : Commands.Context; VAR name: ARRAY OF CHAR; VAR port, bps, parity, stop: LONGINT): BOOLEAN;
+(*PROCEDURE GetSerialPortParameters(context : Commands.Context; VAR port, bps, data, parity, stop: LONGINT): BOOLEAN;
+VAR str : ARRAY 32 OF CHAR;
 BEGIN
 BEGIN
-	port := DefaultPort; bps := DefaultBPS; parity := DefaultParity; stop := DefaultStop;
-	IF context.arg.GetString(name) & IsDigit(name[0]) THEN
-		Strings.StrToInt(name, port);
-		IF (port < 1) OR (port > Serials.MaxPorts) THEN
-			context.error.String("wrong port number"); context.error.Ln;
-			RETURN FALSE
-		END;
-		context.arg.SkipWhitespace; context.arg.Int(bps, FALSE);
-		context.arg.SkipWhitespace; context.arg.String(name);
-		IF name = "odd" THEN
-			parity := Serials.ParOdd
-		ELSIF name = "even" THEN
-			parity := Serials.ParEven
-		ELSIF name = "mark" THEN
-			parity := Serials.ParMark
-		ELSIF name = "space" THEN
-			parity := Serials.ParSpace
-		ELSIF name # "no" THEN
-			context.error.String("wrong parity"); context.error.Ln;
-			RETURN FALSE
-		END;
-		context.arg.SkipWhitespace; context.arg.String(name);
-		IF name = "1.5" THEN
-			stop := Serials.Stop1dot5
-		ELSIF name = "2" THEN
-			stop := Serials.Stop2
-		ELSIF name # "1" THEN
-			context.error.String("wrong stop bits"); context.error.Ln;
-			RETURN FALSE
-		END;
-		context.arg.SkipWhitespace; context.arg.String(name);
+	bps := DefaultBPS; data := DefaultDataBits; parity := DefaultParity; stop := DefaultStop;
+
+	IF ~context.arg.GetInteger(port,FALSE) THEN
+		context.result := 1;
+		context.error.String("port number not specified"); context.error.Ln();
+		RETURN FALSE
 	END;
 	END;
-	RETURN TRUE
-END GetXYPars;
 
 
-PROCEDURE GetSerialPortParameters(context : Commands.Context; VAR port, bps, parity, stop: LONGINT): BOOLEAN;
-VAR str : ARRAY 32 OF CHAR;
-BEGIN
-	port := DefaultPort; bps := DefaultBPS; parity := DefaultParity; stop := DefaultStop;
-	context.arg.String(str);
-	IF IsDigit(str[0]) THEN
-		Strings.StrToInt(str, port);
-		IF (port < 1) OR (port > Serials.MaxPorts) THEN
-			context.error.String("wrong port number"); context.error.Ln();
-			RETURN FALSE
-		END;
-		context.arg.Int(bps, FALSE);
-		context.arg.String(str);
-		IF str = "odd" THEN
-			parity := Serials.ParOdd
-		ELSIF str = "even" THEN
-			parity := Serials.ParEven
-		ELSIF str = "mark" THEN
-			parity := Serials.ParMark
-		ELSIF str = "space" THEN
-			parity := Serials.ParSpace
-		ELSIF str # "no" THEN
-			context.error.String("wrong parity"); context.error.Ln();
-			RETURN FALSE
-		END;
-		context.arg.String(str);
-		IF str = "1.5" THEN
-			stop := Serials.Stop1dot5
-		ELSIF str = "2" THEN
-			stop := Serials.Stop2
-		ELSIF str # "1" THEN
-			context.error.String("wrong stop bits"); context.error.Ln();
-			RETURN FALSE
-		END
+	IF (port < 1) OR (port > Serials.MaxPorts) THEN
+		context.result := 2;
+		context.error.String("wrong port number"); context.error.Ln();
+		RETURN FALSE
+	END;
+
+	IF ~context.arg.GetInteger(bps, FALSE) THEN
+		RETURN TRUE;
+	END;
+
+	IF ~context.arg.GetInteger(data, FALSE) THEN
+		RETURN TRUE;
+	END;
+
+	IF ~context.arg.GetString(str) THEN
+		RETURN TRUE;
 	END;
 	END;
+
+	IF str = "odd" THEN
+		parity := Serials.ParOdd
+	ELSIF str = "even" THEN
+		parity := Serials.ParEven
+	ELSIF str = "mark" THEN
+		parity := Serials.ParMark
+	ELSIF str = "space" THEN
+		parity := Serials.ParSpace
+	ELSIF str # "no" THEN
+		context.result := 3;
+		context.error.String("wrong parity"); context.error.Ln();
+		RETURN FALSE
+	END;
+
+	IF ~context.arg.GetString(str) THEN
+		RETURN TRUE;
+	END;
+
+	IF str = "1.5" THEN
+		stop := Serials.Stop1dot5
+	ELSIF str = "2" THEN
+		stop := Serials.Stop2
+	ELSIF str # "1" THEN
+		context.result := 4;
+		context.error.String("wrong stop bits"); context.error.Ln();
+		RETURN FALSE
+	END;
+
 	RETURN TRUE
 	RETURN TRUE
-END GetSerialPortParameters;
+END GetSerialPortParameters;*)
 
 
 (** Open a shell listening on the specified <portNbr> *)
 (** Open a shell listening on the specified <portNbr> *)
-PROCEDURE Open*(context : Commands.Context); (** [portNbr BitsPerSecond Parity StopBits] ~ *)
+PROCEDURE Open*(context : Commands.Context); (** [portNbr BitsPerSecond DataBits Parity StopBits Prompt] ~ *)
 VAR
 VAR
-	port : Serials.Port; portNbr, bps, parity, stop, res : LONGINT;
+	port : Serials.Port; portNbr, bps, data, parity, stop, res : LONGINT;
+	prompt: ARRAY 32 OF CHAR;
 	w : Streams.Writer; r : Streams.Reader;
 	w : Streams.Writer; r : Streams.Reader;
 BEGIN {EXCLUSIVE}
 BEGIN {EXCLUSIVE}
-	IF ~GetSerialPortParameters(context, portNbr, bps, parity, stop) THEN
-		portNbr := DefaultPort; bps := DefaultBPS; parity := DefaultParity; stop := DefaultStop
+	Serials.GetPortParameters(context.arg, portNbr, bps, data, parity, stop, res);
+	IF res # 0 THEN
+		context.result := 1;
+		context.error.String("Invalid port settings, res="); context.error.Int(res,0); context.error.Ln;
+		RETURN;
 	END;
 	END;
+
 	port := Serials.GetPort(portNbr);
 	port := Serials.GetPort(portNbr);
 	IF port # NIL THEN
 	IF port # NIL THEN
-		IF shells[portNbr] # NIL THEN
-			shells[portNbr].Exit; shells[portNbr].AwaitDeath;
-			shells[portNbr] := NIL;
+		IF shells[portNbr-1] # NIL THEN
+			shells[portNbr-1].Exit; shells[portNbr-1].AwaitDeath;
+			shells[portNbr-1] := NIL;
 			port.Close;
 			port.Close;
 		END;
 		END;
-		port.Open(bps, 8, parity, stop, res);
+		port.Open(bps, data, parity, stop, res);
 		IF (res = Serials.Ok) THEN
 		IF (res = Serials.Ok) THEN
 			NEW(w, port.Send, BufferSize); NEW(r, port.Receive, BufferSize);
 			NEW(w, port.Send, BufferSize); NEW(r, port.Receive, BufferSize);
-			NEW(shells[portNbr], r, w, w, TRUE, Prompt);
+			IF ~context.arg.GetString(prompt) THEN prompt := DefaultPrompt; END;
+			NEW(shells[portNbr-1], r, w, w, TRUE, prompt);
 		ELSE
 		ELSE
-			context.error.String("Shell: Could not open port "); context.error.Int(portNbr, 0);
+			context.error.String("Shell: could not open port "); context.error.Int(portNbr, 0);
 			context.error.String(", res: "); context.error.Int(res, 0); context.error.Ln;
 			context.error.String(", res: "); context.error.Int(res, 0); context.error.Ln;
 		END;
 		END;
 	ELSE
 	ELSE
-		context.error.String("Shell: Serial port "); context.error.Int(portNbr, 0); context.error.String(" not found."); context.error.Ln;
+		context.error.String("Shell: serial port "); context.error.Int(portNbr, 0); context.error.String(" not found."); context.error.Ln;
 	END;
 	END;
 END Open;
 END Open;
 
 
 PROCEDURE Cleanup;
 PROCEDURE Cleanup;
-VAR port : Serials.Port; i : LONGINT;
+VAR
+	port : Serials.Port;
+	i, res : LONGINT;
+	isOpen0, isTracePort : BOOLEAN;
+	bps0, data0, parity0, stop0 : LONGINT;
 BEGIN
 BEGIN
 	FOR i := 0 TO LEN(shells)-1 DO
 	FOR i := 0 TO LEN(shells)-1 DO
 		IF (shells[i] # NIL) THEN
 		IF (shells[i] # NIL) THEN
-			shells[i].Exit; shells[i].AwaitDeath;
+			port := Serials.GetPort(i+1);
+			isTracePort := Serials.IsTracePort(port);
+			IF port # NIL THEN
+				port.GetPortState(isOpen0, bps0, data0, parity0, stop0);
+				port.Close;
+			END;
+			shells[i].Exit;
+			(*shells[i].AwaitDeath;*)
 			shells[i] := NIL;
 			shells[i] := NIL;
-			port := Serials.GetPort(i);
-			IF port # NIL THEN port.Close; END;
+			IF isTracePort THEN
+				Serials.SetTracePort(i+1, bps0, data0, parity0, stop0, res);
+			END;
 		END;
 		END;
 	END;
 	END;
 END Cleanup;
 END Cleanup;