From 86517ff741047ccb13686dd002a275bac0642991 Mon Sep 17 00:00:00 2001
From: Sven Robertz <sven@cs.lth.se>
Date: Tue, 13 Aug 2013 12:43:40 +0200
Subject: [PATCH] added Oscar's RAPID generation and lib
---
compiler/LabComm.java | 17 ++
compiler/RAPID_CodeGen.jrag | 355 ++++++++++++++++++++++
examples/robot/App.config | 6 +
examples/robot/Follow.mod | 49 +++
examples/robot/LCRobot.lc | 38 +++
examples/robot/Program.cs | 52 ++++
examples/robot/Properties/AssemblyInfo.cs | 36 +++
examples/robot/RobotCtrl.csproj | 65 ++++
examples/robot/RobotCtrl.sln | 26 ++
lib/RAPID/LabComm.sys | 317 +++++++++++++++++++
lib/RAPID/README | 104 +++++++
lib/csharp/LabComm.csproj | 26 ++
12 files changed, 1091 insertions(+)
create mode 100644 compiler/RAPID_CodeGen.jrag
create mode 100644 examples/robot/App.config
create mode 100644 examples/robot/Follow.mod
create mode 100644 examples/robot/LCRobot.lc
create mode 100644 examples/robot/Program.cs
create mode 100644 examples/robot/Properties/AssemblyInfo.cs
create mode 100644 examples/robot/RobotCtrl.csproj
create mode 100644 examples/robot/RobotCtrl.sln
create mode 100644 lib/RAPID/LabComm.sys
create mode 100644 lib/RAPID/README
create mode 100644 lib/csharp/LabComm.csproj
diff --git a/compiler/LabComm.java b/compiler/LabComm.java
index 1334d2b..c5a59b8 100644
--- a/compiler/LabComm.java
+++ b/compiler/LabComm.java
@@ -80,6 +80,7 @@ public class LabComm {
String pythonFile = null;
String prettyFile = null;
String typeinfoFile = null;
+ String rapidFile = null;
for (int i = 0 ; i < args.length ; i++) {
if (fileName == null ||
@@ -119,6 +120,8 @@ public class LabComm {
prettyFile = args[i].substring(9);
} else if (args[i].startsWith("--typeinfo=")) {
typeinfoFile = args[i].substring(11);
+ } else if (args[i].equals("--rapid")) {
+ rapidFile = coreName + ".sys";
} else if (i == args.length - 1) {
fileName = args[i];
} else {
@@ -192,6 +195,13 @@ public class LabComm {
genPython(ast, pythonFile, prefix);
prettyOnStdout = false;
}
+ if (rapidFile != null) {
+ if (verbose) {
+ System.err.println("Generating RAPID: " + rapidFile);
+ }
+ genRAPID(ast, rapidFile, coreName);
+ prettyOnStdout = false;
+ }
if (prettyFile != null) {
if (verbose) {
System.err.println("Generating Pretty: " + prettyFile);
@@ -290,6 +300,13 @@ public class LabComm {
}
}
+ private static void genRAPID(Program p, String filename, String prefix) {
+ try {
+ p.RAPID_gen(filename, prefix);
+ } catch (IOException e) {
+ System.err.println("IOException: " + filename + " " + e);
+ }
+ }
}
diff --git a/compiler/RAPID_CodeGen.jrag b/compiler/RAPID_CodeGen.jrag
new file mode 100644
index 0000000..9606105
--- /dev/null
+++ b/compiler/RAPID_CodeGen.jrag
@@ -0,0 +1,355 @@
+
+aspect RAPID_env {
+ public class RAPID_env {
+ private String prefix;
+ private StringBuilder types;
+ private StringBuilder constants;
+ private StringBuilder procedures;
+ private PrintStream ps;
+
+ public RAPID_env(PrintStream ps, String prefix)
+ {
+ this.types = new StringBuilder();
+ this.constants = new StringBuilder();
+ this.procedures = new StringBuilder();
+ this.prefix = prefix;
+ this.ps = ps;
+ }
+
+ public String prefix() { return this.prefix; }
+
+ public String addRecord(String name, java.util.List<String> components)
+ {
+ String recordName = this.prefix + "_" + name;
+ types.append("\tRECORD " + recordName);
+ types.append("\n");
+ for (String c : components) {
+ types.append("\t\t" + c + "\n");
+ }
+ types.append("\tENDRECORD");
+ types.append("\n\n");
+ return recordName;
+ }
+
+ public void addConstant(String type, String name, String value) {
+ this.constants.append("\tLOCAL CONST " + type + " " + name +
+ " := " + value + ";\n");
+ }
+
+ public void addProc(String name, java.util.List<String> params,
+ java.util.List<String> stmts)
+ {
+ this.procedures.append("\tLOCAL PROC " + name + "(");
+ for (int i = 0; i < params.size(); i++) {
+ this.procedures.append(params.get(i));
+ if (i < params.size() - 1) {
+ this.procedures.append(", ");
+ }
+ }
+ this.procedures.append(")\n");
+ for (String stmt : stmts) {
+ this.procedures.append("\t\t" + stmt + "\n");
+ }
+ this.procedures.append("\tERROR\n\t\tRAISE ;\n\tENDPROC\n\n");
+ }
+
+ public void flush()
+ {
+ ps.println("MODULE " + prefix() + "(SYSMODULE)");
+ ps.println();
+ ps.print(types.toString());
+ ps.println();
+ ps.println("\tLOCAL CONST string prefix:=\"" + this.prefix + "\";");
+ ps.print(constants.toString());
+ ps.println();
+ ps.print(procedures.toString());
+ ps.println();
+ ps.print("ENDMODULE");
+ }
+ }
+}
+
+aspect RAPID_CodeGen {
+
+ public void ASTNode.RAPID_gen(RAPID_env env) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void Program.RAPID_gen(String file, String prefix)
+ throws IOException
+ {
+ PrintStream ps = new PrintStream(new FileOutputStream(new File(file)));
+ RAPID_env env = new RAPID_env(ps, prefix);
+ RAPID_gen(env);
+ }
+
+ public void Program.RAPID_gen(RAPID_env env)
+ {
+ for (int i = 0; i < getNumDecl(); i++) {
+ getDecl(i).RAPID_gen(env);
+ }
+ env.flush();
+ }
+
+ public void Decl.RAPID_gen(RAPID_env env) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void SampleDecl.RAPID_gen(RAPID_env env) {
+ // Add type declarations
+ String fullName = getType().RAPID_AddType(env, getName());
+ // Add signature constants
+ String sig_len_name = "signature_len_" + getName();
+ String sig_name = "signature_" + getName();
+ SignatureList sig = signature();
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ byte[] d = null;
+ int sig_len = 0;
+ for (int i = 0; i < sig.size(); i++) {
+ d = sig.getData(i);
+ for (int j = 0; d != null && j < d.length; j++) {
+ sb.append(d[j] + ",");
+ sig_len++;
+ }
+ }
+ sb.delete(sb.length() - 1, sb.length());
+ sb.append("]");
+ env.addConstant("num", sig_len_name, "" + sig_len);
+ env.addConstant("byte", sig_name + "{" + sig_len_name + "}",
+ sb.toString());
+
+ // Add decode procedures
+ ArrayList<String> params = new ArrayList<String>();
+ ArrayList<String> stmts = new ArrayList<String>();
+ params.add("VAR LabComm_Decoder_Sample s");
+ params.add("string handler");
+ stmts.add("s.prefix := prefix;");
+ stmts.add("s.name := \"" + getName() + "\";");
+ stmts.add("s.handler := handler;");
+ env.addProc("Dec_Reg_" + getName(), params, stmts);
+
+ params.clear();
+ stmts.clear();
+ params.add("VAR LabComm_Decoder_Sample s");
+ params.add("VAR rawbytes sig");
+ params.add("num user_id");
+ stmts.add("VAR byte tmp_sig{" + sig_len_name + "};");
+ stmts.add("IF RawBytesLen(sig)<>" + sig_len_name + " THEN");
+ stmts.add("\tRETURN;");
+ stmts.add("ENDIF");
+ stmts.add("FOR i FROM 1 TO " + sig_len_name + " DO");
+ stmts.add("\tUnpackRawBytes sig, i, tmp_sig{i}, \\Hex1;");
+ stmts.add("ENDFOR");
+ stmts.add("IF tmp_sig<>" + sig_name + " THEN");
+ stmts.add("\tRETURN;");
+ stmts.add("ENDIF");
+ stmts.add("s.user_id := user_id;");
+ env.addProc("Reg_If_Signature_Of_" + getName(), params, stmts);
+
+ params.clear();
+ stmts.clear();
+ params.add("VAR Decoder d");
+ params.add("VAR LabComm_Stream st");
+ params.add("VAR LabComm_Decoder_Sample s");
+ stmts.add("VAR " + fullName + " tmp;");
+ getType().RAPID_AddDecodeInstr(env, stmts, "tmp", "st");
+ stmts.add("% s.handler % tmp;");
+ env.addProc("Decode_And_Handle_" + getName(), params, stmts);
+
+ params.clear();
+ stmts.clear();
+ params.add("VAR Encoder e");
+ params.add("VAR LabComm_Stream st");
+ params.add("VAR LabComm_Encoder_Sample s");
+ stmts.add("s.prefix := prefix;");
+ stmts.add("s.name := \"" + getName() + "\";");
+ stmts.add("Encoder_Register_Sample e, st, s;");
+ env.addProc("Enc_Reg_" + getName(), params, stmts);
+
+ params.clear();
+ stmts.clear();
+ params.add("VAR Encoder e");
+ params.add("VAR LabComm_Stream s");
+ stmts.add("VAR rawbytes buffer;");
+ stmts.add("FOR i FROM 1 TO " + sig_len_name + " DO");
+ stmts.add("\tPackRawBytes " + sig_name +
+ "{i}, buffer, \\Network, i, \\Hex1;");
+ stmts.add("ENDFOR");
+ stmts.add("SocketSend s.soc, \\RawData:=buffer, \\NoOfBytes:=" +
+ sig_len_name + ";");
+ env.addProc("Encode_Signature_" + getName(), params, stmts);
+
+ params.clear();
+ stmts.clear();
+ params.add("VAR Encoder e");
+ params.add("VAR LabComm_Stream st");
+ params.add("VAR LabComm_Encoder_Sample s");
+ params.add("VAR " + fullName + " val");
+ stmts.add("Encode_Packed st, s.user_id;");
+ getType().RAPID_AddEncodeInstr(env, stmts, "val", "st");
+ env.addProc("Encode_" + getName(), params, stmts);
+ }
+
+ public String Type.RAPID_AddType(RAPID_env env, String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public String StructType.RAPID_AddType(RAPID_env env, String name) {
+ ArrayList<String> components = new ArrayList<String>();
+ for (int i = 0; i < getNumField(); i++) {
+ Field f = getField(i);
+ components.add(
+ f.getType().RAPID_AddType(env, name + "_" + f.getName()) +
+ " " + f.getName() + ";");
+ }
+ String typeName = env.addRecord(name, components);
+ return typeName;
+ }
+
+ public String FixedArrayType.RAPID_AddType(RAPID_env env, String name) {
+ String typeName = getType().RAPID_AddType(env, name + "_e");
+ if (getNumExp() > 1) {
+ throw new UnsupportedOperationException();
+ }
+ ArrayList<String> components = new ArrayList<String>();
+ for (int i = 1; i <= getExp(0).RAPID_getValue(); i++) {
+ components.add(typeName + " e" + i + ";");
+ }
+ String completeName = env.addRecord("list_" + name, components);
+ return completeName;
+ }
+
+ public String PrimType.RAPID_AddType(RAPID_env env, String name) {
+ if (getToken() == LABCOMM_SHORT ||
+ getToken() == LABCOMM_FLOAT ||
+ getToken() == LABCOMM_INT) {
+ return "num";
+ } else if (getToken() == LABCOMM_LONG) {
+ return "dnum";
+ } else if (getToken() == LABCOMM_STRING) {
+ return "string";
+ } else if (getToken() == LABCOMM_BOOLEAN) {
+ return "bool";
+ } else if (getToken() == LABCOMM_BYTE) {
+ return "byte";
+ }
+ throw new UnsupportedOperationException();
+ }
+
+ public void Type.RAPID_AddDecodeInstr(RAPID_env env,
+ java.util.List<String> instrs,
+ String var_name, String stream_name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void StructType.RAPID_AddDecodeInstr(RAPID_env env,
+ java.util.List<String> instrs,
+ String var_name, String stream_name) {
+ for (int i = 0; i < getNumField(); i++) {
+ getField(i).getType().RAPID_AddDecodeInstr(env, instrs,
+ var_name + "." + getField(i).getName(), stream_name);
+ }
+ }
+
+ public void FixedArrayType.RAPID_AddDecodeInstr(RAPID_env env,
+ java.util.List<String> instrs,
+ String var_name, String stream_name) {
+ for (int i = 1; i <= getExp(0).RAPID_getValue(); i++) {
+ getType().RAPID_AddDecodeInstr(env, instrs,
+ var_name + ".e" + i, stream_name);
+ }
+ }
+
+ public void PrimType.RAPID_AddDecodeInstr(RAPID_env env,
+ java.util.List<String> instrs,
+ String var_name, String stream_name) {
+ switch(getToken()) {
+ case LABCOMM_BYTE:
+ instrs.add("Decode_Byte " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_BOOLEAN:
+ instrs.add("Decode_Bool " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_SHORT:
+ instrs.add("Decode_Short " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_INT:
+ instrs.add("Decode_Int " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_LONG:
+ instrs.add("Decode_Long " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_FLOAT:
+ instrs.add("Decode_Float " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_STRING:
+ instrs.add("Decode_String " + stream_name + "," + var_name + ";");
+ break;
+ default:
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public void Type.RAPID_AddEncodeInstr(RAPID_env env,
+ java.util.List<String> instrs,
+ String var_name, String stream_name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void StructType.RAPID_AddEncodeInstr(RAPID_env env,
+ java.util.List<String> instrs,
+ String var_name, String stream_name) {
+ for (int i = 0; i < getNumField(); i++) {
+ getField(i).getType().RAPID_AddEncodeInstr(env, instrs,
+ var_name + "." + getField(i).getName(), stream_name);
+ }
+ }
+
+ public void FixedArrayType.RAPID_AddEncodeInstr(RAPID_env env,
+ java.util.List<String> instrs,
+ String var_name, String stream_name) {
+ for (int i = 1; i <= getExp(0).RAPID_getValue(); i++) {
+ getType().RAPID_AddEncodeInstr(env, instrs,
+ var_name + ".e" + i, stream_name);
+ }
+ }
+
+ public void PrimType.RAPID_AddEncodeInstr(RAPID_env env,
+ java.util.List<String> instrs,
+ String var_name, String stream_name) {
+ switch(getToken()) {
+ case LABCOMM_BYTE:
+ instrs.add("Encode_Byte " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_BOOLEAN:
+ instrs.add("Encode_Bool " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_SHORT:
+ instrs.add("Encode_Short " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_INT:
+ instrs.add("Encode_Int " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_LONG:
+ instrs.add("Encode_Long " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_FLOAT:
+ instrs.add("Encode_Float " + stream_name + "," + var_name + ";");
+ break;
+ case LABCOMM_STRING:
+ instrs.add("Encode_String " + stream_name + "," + var_name + ";");
+ break;
+ default:
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public int Exp.RAPID_getValue() {
+ throw new UnsupportedOperationException();
+ }
+
+ public int IntegerLiteral.RAPID_getValue() {
+ return Integer.parseInt(getValue());
+ }
+}
diff --git a/examples/robot/App.config b/examples/robot/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/examples/robot/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+ </startup>
+</configuration>
\ No newline at end of file
diff --git a/examples/robot/Follow.mod b/examples/robot/Follow.mod
new file mode 100644
index 0000000..fb86d9f
--- /dev/null
+++ b/examples/robot/Follow.mod
@@ -0,0 +1,49 @@
+MODULE Follow
+ PROC LCjt2jt(VAR LCRobot_jointtarget a, VAR jointtarget b)
+ b.robax.rax_1 := a.robax.rax_1;
+ b.robax.rax_2 := a.robax.rax_2;
+ b.robax.rax_3 := a.robax.rax_3;
+ b.robax.rax_4 := a.robax.rax_4;
+ b.robax.rax_5 := a.robax.rax_5;
+ b.robax.rax_6 := a.robax.rax_6;
+
+ b.extax.eax_a := a.extax.eax_a;
+ b.extax.eax_b := a.extax.eax_b;
+ b.extax.eax_c := a.extax.eax_c;
+ b.extax.eax_d := a.extax.eax_d;
+ b.extax.eax_e := a.extax.eax_e;
+ b.extax.eax_f := a.extax.eax_f;
+ ENDPROC
+
+ PROC handle_jointtarget(LCRobot_jointtarget val)
+ VAR jointtarget jt;
+ LCjt2jt val, jt;
+ MoveAbsJ jt, v100, z1, tool0, \WObj:=wobj0;
+ ENDPROC
+
+ PROC main()
+ VAR LabComm_Stream st;
+ VAR socketdev srv;
+ SocketCreate srv;
+ SocketBind srv, "127.0.0.1", 51337;
+ SocketListen srv;
+ WHILE TRUE DO
+ SocketAccept srv, st.soc;
+ Receive_targets st;
+ ENDWHILE
+ ENDPROC
+
+ PROC Receive_targets(VAR LabComm_Stream st)
+ VAR Decoder d;
+ VAR LabComm_Decoder_Sample s{1};
+ Init_Decoder d, st;
+ % "LCRobot:Dec_Reg_jointtarget" % s{1}, "handle_jointtarget";
+ WHILE TRUE DO
+ Decode_One d, st, s;
+ ENDWHILE
+ ERROR
+ SocketClose st.soc;
+ RETURN;
+ ENDPROC
+
+ENDMODULE
\ No newline at end of file
diff --git a/examples/robot/LCRobot.lc b/examples/robot/LCRobot.lc
new file mode 100644
index 0000000..971767d
--- /dev/null
+++ b/examples/robot/LCRobot.lc
@@ -0,0 +1,38 @@
+sample struct {
+ struct {
+ float x;
+ float y;
+ float z;
+ } trans;
+ struct {
+ float q1;
+ float q2;
+ float q3;
+ float q4;
+ } rot;
+ struct {
+ short cf1;
+ short cf4;
+ short cf6;
+ short cfx;
+ } robconfig;
+} robtarget;
+
+sample struct {
+ struct {
+ float rax_1;
+ float rax_2;
+ float rax_3;
+ float rax_4;
+ float rax_5;
+ float rax_6;
+ } robax;
+ struct {
+ float eax_a;
+ float eax_b;
+ float eax_C;
+ float eax_d;
+ float eax_e;
+ float eax_f;
+ } extax;
+} jointtarget;
\ No newline at end of file
diff --git a/examples/robot/Program.cs b/examples/robot/Program.cs
new file mode 100644
index 0000000..28fddc2
--- /dev/null
+++ b/examples/robot/Program.cs
@@ -0,0 +1,52 @@
+using se.lth.control.labcomm;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace RobotCtrl
+{
+ class Program
+ {
+
+ public static string IP_ADDRESS = "127.0.0.1";
+ public static int PORT = 51337;
+
+ static void Main(string[] args)
+ {
+ jointtarget val = new jointtarget { robax = new jointtarget.struct_robax(), extax = new jointtarget.struct_extax() };
+ TcpClient client = new TcpClient();
+ IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(Program.IP_ADDRESS), Program.PORT);
+ try
+ {
+ client.Connect(serverEndPoint);
+ LabCommEncoder enc = new LabCommEncoderChannel(client.GetStream(), true);
+ jointtarget.register(enc);
+ jointtarget.encode(enc, val);
+ for (int i = 0; i < 10; i++)
+ {
+ val.robax.rax_2 += 2;
+ jointtarget.encode(enc, val);
+ }
+ for (int i = 0; i < 20; i++)
+ {
+ val.robax.rax_2 -= 2;
+ jointtarget.encode(enc, val);
+ }
+ for (int i = 0; i < 10; i++)
+ {
+ val.robax.rax_2 += 2;
+ jointtarget.encode(enc, val);
+ }
+ }
+ finally
+ {
+ client.Close();
+ }
+ }
+ }
+}
diff --git a/examples/robot/Properties/AssemblyInfo.cs b/examples/robot/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..9fcb6df
--- /dev/null
+++ b/examples/robot/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("RobotCtrl")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("RobotCtrl")]
+[assembly: AssemblyCopyright("Copyright © 2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("bd5ee6d6-1dff-4043-8ca9-b56a29116e61")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/examples/robot/RobotCtrl.csproj b/examples/robot/RobotCtrl.csproj
new file mode 100644
index 0000000..7dcdcb0
--- /dev/null
+++ b/examples/robot/RobotCtrl.csproj
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{F0051A25-4FFF-4421-A5CB-01B512D6CEC5}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>RobotCtrl</RootNamespace>
+ <AssemblyName>RobotCtrl</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="LCRobot.cs" />
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\lib\csharp\LabComm.csproj">
+ <Project>{755cd5a6-c48e-4d35-b0be-8ec0fde1a2a1}</Project>
+ <Name>LabComm</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
diff --git a/examples/robot/RobotCtrl.sln b/examples/robot/RobotCtrl.sln
new file mode 100644
index 0000000..91ac483
--- /dev/null
+++ b/examples/robot/RobotCtrl.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RobotCtrl", "RobotCtrl.csproj", "{F0051A25-4FFF-4421-A5CB-01B512D6CEC5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabComm", "..\..\lib\csharp\LabComm.csproj", "{755CD5A6-C48E-4D35-B0BE-8EC0FDE1A2A1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F0051A25-4FFF-4421-A5CB-01B512D6CEC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F0051A25-4FFF-4421-A5CB-01B512D6CEC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F0051A25-4FFF-4421-A5CB-01B512D6CEC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F0051A25-4FFF-4421-A5CB-01B512D6CEC5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {755CD5A6-C48E-4D35-B0BE-8EC0FDE1A2A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {755CD5A6-C48E-4D35-B0BE-8EC0FDE1A2A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {755CD5A6-C48E-4D35-B0BE-8EC0FDE1A2A1}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {755CD5A6-C48E-4D35-B0BE-8EC0FDE1A2A1}.Release|Any CPU.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/lib/RAPID/LabComm.sys b/lib/RAPID/LabComm.sys
new file mode 100644
index 0000000..8d31dce
--- /dev/null
+++ b/lib/RAPID/LabComm.sys
@@ -0,0 +1,317 @@
+MODULE LabComm(SYSMODULE)
+
+ RECORD LabComm_Stream
+ socketdev soc;
+ ENDRECORD
+
+ RECORD LabComm_Decoder_Sample
+ string prefix;
+ string name;
+ num user_id;
+ string handler;
+ ENDRECORD
+
+ RECORD LabComm_Encoder_Sample
+ string prefix;
+ string name;
+ num user_id;
+ ENDRECORD
+
+ RECORD Decoder
+ num user_id;
+ ENDRECORD
+
+ RECORD Encoder
+ num next_user_id;
+ ENDRECORD
+
+ ! LabComm constants
+ CONST string LabCommVersion := "LabComm2013";
+ CONST num SAMPLE_DECL:=2;
+ CONST num SAMPLE_DATA:=64;
+
+ CONST num STRUCT_TYPE := 17;
+ CONST num ARRAY_TYPE := 16;
+ CONST num BYTE_TYPE := 37;
+ CONST num BOOL_TYPE := 37;
+ CONST num SHORT_TYPE := 34;
+ CONST num INT_TYPE := 37;
+ CONST num LONG_TYPE := 37;
+ CONST num FLOAT_TYPE := 37;
+
+ ! Error declarations
+ CONST errnum INCORRECT_LABCOMM_VERSION := 50;
+ CONST errnum UNKNOWN_PACKET_TYPE := 51;
+ CONST errnum UNKNOWN_SAMPLE_TYPE := 52;
+ CONST errnum INCORRECT_SAMPLE_SIGNATURE := 53;
+ CONST errnum SAMPLE_TYPE_NOT_REGISTERED := 54;
+ CONST errnum IMPLEMENTATION_LIMIT_REACHED := 55;
+
+ PROC Decode_Packed(VAR LabComm_Stream s, VAR num v, \ VAR rawbytes collect)
+ VAR rawbytes buffer;
+ SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=1;
+ UnpackRawBytes buffer,\Network,1,v,\IntX:=USINT;
+ IF Present(collect) THEN
+ CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
+ ENDIF
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Encode_Packed(VAR LabComm_Stream s, num v)
+ VAR rawbytes buffer;
+ PackRawBytes v,buffer,\Network,1,\IntX:=USINT;
+ SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=1;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Decode_Boolean(VAR LabComm_Stream s, VAR bool v, \ VAR rawbytes collect)
+ VAR rawbytes buffer;
+ VAR num tmp;
+ SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=1;
+ UnpackRawBytes buffer,\Network,1,tmp,\IntX:=USINT;
+ IF tmp = 0 THEN
+ v := FALSE;
+ ELSE
+ v := TRUE;
+ ENDIF
+ IF Present(collect) THEN
+ CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
+ ENDIF
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Encode_Boolean(VAR LabComm_Stream s, bool v)
+ VAR rawbytes buffer;
+ VAR num tmp;
+ IF v THEN
+ tmp := 1;
+ ELSE
+ tmp := 0;
+ ENDIF
+ PackRawBytes tmp,buffer,\Network,1,\IntX:=USINT;
+ SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=1;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Decode_Byte(VAR LabComm_Stream s, VAR byte v, \ VAR rawbytes collect)
+ VAR rawbytes buffer;
+ SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=1;
+ UnpackRawBytes buffer,\Network,1,v,\Hex1;
+ IF Present(collect) THEN
+ CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
+ ENDIF
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Encode_Byte(VAR LabComm_Stream s, byte v)
+ VAR rawbytes buffer;
+ PackRawBytes v,buffer,\Network,1,\Hex1;
+ SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=1;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Decode_Short(VAR LabComm_Stream s,VAR num v, \ VAR rawbytes collect)
+ VAR rawbytes buffer;
+ SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=2;
+ UnpackRawBytes buffer,\Network,1,v,\IntX:=INT;
+ IF Present(collect) THEN
+ CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
+ ENDIF
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Encode_Short(VAR LabComm_Stream s, num v)
+ VAR rawbytes buffer;
+ PackRawBytes v, buffer, \Network, 1, \IntX:=INT;
+ SocketSend s.soc, \RawData:=buffer, \NoOfBytes:=2;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Decode_Integer(VAR LabComm_Stream s, VAR num v, \ VAR rawbytes collect)
+ VAR rawbytes buffer;
+ SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=4;
+ UnpackRawBytes buffer,\Network,1,v,\IntX:=DINT;
+ IF Present(collect) THEN
+ CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
+ ENDIF
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Encode_Integer(VAR LabComm_Stream s, num v)
+ VAR rawbytes buffer;
+ PackRawBytes v,buffer,\Network,1,\IntX:=DINT;
+ SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=4;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Decode_Long(VAR LabComm_Stream s, VAR dnum v, \ VAR rawbytes collect)
+ VAR rawbytes buffer;
+ SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=8;
+ UnpackRawBytes buffer,\Network,1,v,\IntX:=LINT;
+ IF Present(collect) THEN
+ CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
+ ENDIF
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Encode_Long(VAR LabComm_Stream s, dnum v)
+ VAR rawbytes buffer;
+ PackRawBytes v,buffer,\Network,1,\IntX:=LINT;
+ SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=8;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Decode_Float(VAR LabComm_Stream s,VAR num v, \ VAR rawbytes collect)
+ VAR rawbytes buffer;
+ SocketReceive s.soc,\RawData:=buffer,\ReadNoOfBytes:=4;
+ UnpackRawBytes buffer,\Network,1,v,\Float4;
+ IF Present(collect) THEN
+ CopyRawBytes buffer, 1, collect, (RawBytesLen(collect)+1);
+ ENDIF
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Encode_Float(VAR LabComm_Stream s, num v)
+ VAR rawbytes buffer;
+ PackRawBytes v, buffer,\Network,1,\Float4;
+ SocketSend s.soc,\RawData:=buffer,\NoOfBytes:=4;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Decode_String(VAR LabComm_Stream st,VAR string s, \ VAR rawbytes collect)
+ VAR rawbytes buffer;
+ VAR num length;
+ IF Present(collect) THEN
+ Decode_Packed st, length, \collect:=collect;
+ ELSE
+ Decode_Packed st, length;
+ ENDIF
+ SocketReceive st.soc,\Str:=s,\ReadNoOfBytes:=length;
+ IF Present(collect) THEN
+ PackRawBytes s, collect, (RawBytesLen(collect)+1), \ASCII;
+ ENDIF
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Encode_String(VAR LabComm_Stream st, string s)
+ VAR rawbytes buffer;
+ VAR num length;
+ length := StrLen(s);
+ Encode_Packed st, length;
+ SocketSend st.soc,\Str:=s,\NoOfBytes:=length;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Encoder_Register_Sample(VAR Encoder e, VAR LabComm_Stream st, VAR LabComm_Encoder_Sample s)
+ s.user_id := e.next_user_id;
+ e.next_user_id := e.next_user_id + 1;
+ Encode_Packed st, SAMPLE_DECL;
+ Encode_Packed st, s.user_id;
+ Encode_String st, s.name;
+ % s.prefix + ":Encode_Signature_" + s.name % e, st;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Collect_Array(VAR LabComm_Stream s, VAR rawbytes sig)
+ VAR num num_dim;
+ VAR num dims;
+ Decode_Packed s, num_dim, \collect:=sig;
+ FOR i FROM 1 TO num_dim DO
+ Decode_Packed s, dims, \collect:=sig;
+ ENDFOR
+ Collect_Signature s, sig;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Collect_Struct(VAR LabComm_Stream s, VAR rawbytes sig)
+ VAR num num_elements;
+ VAR string tmp;
+ Decode_Packed s, num_elements, \collect:=sig;
+ FOR i FROM 1 TO num_elements DO
+ Decode_String s, tmp, \collect:=sig;
+ Collect_Signature s, sig;
+ ENDFOR
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Collect_Signature(VAR LabComm_Stream s, VAR rawbytes sig)
+ VAR num type_id;
+ Decode_Packed s, type_id, \collect:=sig;
+ TEST type_id
+ CASE STRUCT_TYPE:
+ Collect_Struct s, sig;
+ CASE ARRAY_TYPE:
+ Collect_Array s, sig;
+ CASE BYTE_TYPE, BOOL_TYPE, SHORT_TYPE, INT_TYPE, LONG_TYPE, SHORT_TYPE:
+ DEFAULT:
+ RAISE IMPLEMENTATION_LIMIT_REACHED;
+ ENDTEST
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Decode_One(VAR Decoder d, VAR LabComm_Stream s, VAR LabComm_Decoder_Sample samples{*})
+ VAR rawbytes buffer;
+ VAR num packet_type;
+ VAR num user_id;
+ VAR string type_name;
+ Decode_Packed s, packet_type;
+ WHILE packet_type = SAMPLE_DECL DO
+ Decode_Packed s, user_id;
+ Decode_String s, type_name;
+ Collect_Signature s, buffer;
+ FOR i FROM 1 TO Dim(samples, 1) DO
+ % samples{i}.prefix + ":Reg_If_Signature_Of_" + samples{i}.name % samples{i}, buffer, user_id;
+ ENDFOR
+ Decode_Packed s, packet_type;
+ ENDWHILE
+ IF packet_type >= SAMPLE_DATA THEN
+ FOR i FROM 1 TO Dim(samples, 1) DO
+ IF samples{i}.user_id = packet_type THEN
+ % samples{i}.prefix + ":Decode_And_Handle_" + samples{i}.name % d, s, samples{i};
+ ENDIF
+ ENDFOR
+ RETURN ;
+ ENDIF
+ RAISE UNKNOWN_PACKET_TYPE;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Init_Decoder(VAR Decoder d, VAR LabComm_Stream s)
+ VAR string version;
+ Decode_String s,version;
+ IF version<>LabCommVersion THEN
+ RAISE INCORRECT_LABCOMM_VERSION;
+ ENDIF
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ PROC Init_Encoder(VAR Encoder e, VAR LabComm_Stream s)
+ Encode_String s, LabCommVersion;
+ e.next_user_id := SAMPLE_DATA;
+ ERROR
+ RAISE ;
+ ENDPROC
+
+ENDMODULE
\ No newline at end of file
diff --git a/lib/RAPID/README b/lib/RAPID/README
new file mode 100644
index 0000000..f296d4d
--- /dev/null
+++ b/lib/RAPID/README
@@ -0,0 +1,104 @@
+The implementation of LabComm in RAPID
+
+Limitations of this implementation:
+ - The type double is not available due to limitations in RAPID. There is a
+ non-integer type with 64 bits but there is not marshalling utilities for it.
+ - Variable sized arrays is not available. There is no dynamic allocation,
+ possible solution is a max-size array (1024) and a integervalue denoting the
+ size.
+ - A RECORD (struct) cannot contain an array, but fixed size arrays are
+ available both in structs and stand alone. The current implementation creates
+ a RECORD with one member for each index in the array. Not an omptimal
+ solution, the alternativ would be a seperate variable.
+ - Decoding and encoding is done directly from a TCP socket.
+ - Every generated procedure is namespaced by declaring them LOCAL to the
+ generated module. They must be called by using runtime binding of procedure
+ names ( % proc_name % arg1, arg2, ...;). The generated types are not
+ declared local.
+
+Usage:
+
+# Declare a stream, LabComm_Stream:
+ $ VAR LabComm_Stream st;
+This contains a socketdev wich must be created and connected or instatiated
+through an accept.
+ $ SocketCreate st.soc;
+ $ SocketConnect st.soc, "127.0.0.1", 55555;
+or
+ $ SocketAccept server_socket, st.soc;
+
+# Initiate Encoder and/or Decoder with the stream:
+ $ VAR Decoder d;
+ $ Init_Decoder d, st;
+
+ $ VAR Encoder e;
+ $ Init_Encoder e, st;
+This will read/write the version of LabComm to ensure compatibility, current
+version is "LabComm2013".
+
+# Initiate the labcomm samples:
+LabComm trusts the application to manage each sample. It requests the samples,
+as a list, when performing decoding or encoding.
+This is done through the generated code which implies the procedures are LOCAL
+and must be called with runtime bindings.
+When initiating a decoder sample the name of the callback procedure to receive
+such samples is suplied as a string.
+ $ PROC handle_samplename(prefix_samplename val)
+ $ ...
+ $ ENDPROC
+ $ VAR LabComm_Decoder_Sample ds{1};
+ $ % prefix:Dec_Reg_samplename % ds{1}, "handle_samplename";
+NOTE: The callback must be of type procedure and not function. Functions cannot
+be called with runtime bindings.
+
+When initiating an encoder sample the stream must be supplied to let the
+encoder send the sample signature.
+ $ VAR LabComm_Encoder_Sample es{1};
+ $ % prefix:Enc_Reg_samplename % e, st, es{1};
+
+# Encode and/or decode samples:
+ $ Decode_One d, st, ds;
+It returns as soon as any sample is decoded. The decoded sample is supplied as
+argument to the callback procedure registered with the corresponding sample.
+ $ VAR prefix_samplename val;
+ $ <init val>
+ $ % prefix:Encode_samplename % e, st, es{1}, val;
+
+# Complete example:
+
+## LabComm definition:
+example.lc >>
+sample struct {
+ short sum;
+ short terms[2];
+} foo;
+<< EOF
+
+## RAPID CODE
+PROC handle_foo(example_foo val)
+ IF val.sum = val.terms.e1 + val.terms.e2 THEN
+ TPWrite "Verification successfull!";
+ ELSE
+ TPWrite "Verification failed!";
+ ENDIF
+ENDPROC
+
+
+PROC main()
+ VAR Decoder d;
+ VAR Encoder e;
+ VAR LabComm_Stream st;
+ VAR LabComm_Encoder_Sample es{1};
+ VAR LabComm_Decoder_Sample ds{1};
+ VAR example_foo val := [2,[1,1]];
+ SocketCreate st.soc;
+ SocketConnect st.soc, "127.0.0.1", 55555;
+ Init_Decoder d, st;
+ Init_Encoder e, st;
+ % "example:Enc_Reg_foo" % e, st, es{1};
+ % "example:Dec_Reg_foo" % ds{1}, "handle_foo";
+ % "example:Encode_foo" % e, st, es{1}, val;
+ Decode_One d, st, ds;
+ SocketClose st.soc;
+ENDPROC
+
diff --git a/lib/csharp/LabComm.csproj b/lib/csharp/LabComm.csproj
new file mode 100644
index 0000000..c6406ea
--- /dev/null
+++ b/lib/csharp/LabComm.csproj
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <AssemblyName>LabComm</AssemblyName>
+ <ProjectGuid>{755CD5A6-C48E-4D35-B0BE-8EC0FDE1A2A1}</ProjectGuid>
+ <!-- Properties which affect the build process -->
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)' == 'Debug'">
+ <OutputPath>bin\Debug\</OutputPath>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="se\lth\control\labcomm\LabCommDispatcher.cs" />
+ <Compile Include="se\lth\control\labcomm\LabCommDecoderRegistry.cs" />
+ <Compile Include="se\lth\control\labcomm\LabComm.cs" />
+ <Compile Include="se\lth\control\labcomm\LabCommSample.cs" />
+ <Compile Include="se\lth\control\labcomm\LabCommHandler.cs" />
+ <Compile Include="se\lth\control\labcomm\LabCommEncoderRegistry.cs" />
+ <Compile Include="se\lth\control\labcomm\LabCommDecoder.cs" />
+ <Compile Include="se\lth\control\labcomm\LabCommType.cs" />
+ <Compile Include="se\lth\control\labcomm\LabCommEncoderChannel.cs" />
+ <Compile Include="se\lth\control\labcomm\LabCommEncoder.cs" />
+ <Compile Include="se\lth\control\labcomm\LabCommDecoderChannel.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>
\ No newline at end of file
--
GitLab