diff --git a/compiler/LabComm.java b/compiler/LabComm.java index 1334d2b24aa8ee7472c375487bda0b7202dbb679..c5a59b83bca2b93582425d400b29ad2b0d61134a 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 0000000000000000000000000000000000000000..9606105aec69274c4b08fa3d9bd181a1f35683d7 --- /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 0000000000000000000000000000000000000000..8e15646352ec1d9a84bbc6504ef6b46e16bf7823 --- /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 0000000000000000000000000000000000000000..fb86d9f6b81cb2104e9f1722828c4132f8046d2c --- /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 0000000000000000000000000000000000000000..971767d85e923881e5a3e5f28c66f3b302374a39 --- /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 0000000000000000000000000000000000000000..28fddc27a50c93ec91d9db5ced4ab3d58a215a01 --- /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 0000000000000000000000000000000000000000..9fcb6df01cc550b0ff752365e1022ebfc962ec78 --- /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 0000000000000000000000000000000000000000..7dcdcb0c06be2494f719ddb2d1d5f841fc7f3e2c --- /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 0000000000000000000000000000000000000000..91ac48357dd6ccd7990024c02f01a74cab3b1b58 --- /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 0000000000000000000000000000000000000000..8d31dce0ebea49dafbe574ea63d74ff5dd49569b --- /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 0000000000000000000000000000000000000000..f296d4d0de253a5758efb8ce408c759c247f9c79 --- /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 0000000000000000000000000000000000000000..c6406ea5d3069279beb23378a5cec15524b6be46 --- /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