chiark / gitweb /
hostside: more length for bavarian
[trains.git] / hostside / skelproto-pic.c
index 69dd62f1d4db667d9087f831f0c32ac82dc773a9..ae775c26166365d42136d74989d6d364ef038a89 100644 (file)
@@ -1,34 +1,98 @@
 /* @skeleton@ @1@ @L@ */
 /*
- * arranges for the declarations of
+ * definitions of
  *  enco_pic_WHATEVER
- *  onrecv_pic_WHATEVER
+ *  on_pic_WHATEVER
  * and the tables
+ * and related functions
  */
 
-#include "hostside.h"
+#include <assert.h>
+
+#include "common.h"
 #include "auproto-pic.h"
 
-extern void enco_pic_anyinsn(PicInsn *out, const PicInsnInfo *pii,
-                            int objnum) {
-  unsigned long as= objnum;
+static void enco_pic_any(PicInsn *out, int opcode, int argsbits, int argsval) {
+  unsigned long as= argsval;
   int i;
 
-  out->l= 1 + pii->argbits/7;
+  assert(!(as & (~0UL << argsbits)));
+  out->l= 1 + argsbits/7;
   for (i= out->l - 1;
        i >= 0;
        i--, as >>= 7)
     out->d[i]= (as & 0x07fUL) | 0x080UL;
   out->d[out->l - 1] &= ~0x080UL;
-  out->d[0] |= pii->opcode;
+  out->d[0] |= opcode;
+}
+
+static void enco_pic_anyobjv(PicInsn *out, int opcode, int argsbits, int vbits,
+                           int obj, int v) {
+  assert((unsigned)v < (1u << vbits));
+  enco_pic_any(out, opcode, argsbits, obj << vbits | v);
+}
+
+#define C ,
+
+#define ENCO(w, xa, opcode, argsbits, obj)     \
+  extern void enco_pic_##w(PicInsn *out  xa) { \
+    enco_pic_any(out, opcode, argsbits, obj);  \
+  }
+
+#define ENCO2A(w, opcode, argsbits, vbits)                     \
+  extern void enco_pic_##w(PicInsn *out, int obj, int v) {     \
+    enco_pic_anyobjv(out, opcode, argsbits, vbits, obj, v);    \
+  }
+
+ENCO(@cnameyn@,          , @opcodeyn@, 0,                 0)   @h2p@ @nargs=0@
+ENCO(@cnameyn@, C int obj, @opcodeyn@, @arglen@,          obj) @h2p@ @nargs=1@
+ENCO2A(@cnameyn@,          @opcodeyn@, @argslen@, @vlen@)      @h2p@ @nargs=2@
+
+extern void enco_pic_pii(PicInsn *out, const PicInsnInfo *pii,
+                        int obj, int v) {
+  enco_pic_anyobjv(out, pii->opcode, pii->argsbits, pii->vbits, obj, v);
+}
+
+const PicInsnInfo *lookup_byopcode(Byte byte0, const PicInsnInfo *table) {
+  const PicInsnInfo *pi;
+  for (pi= table;
+       pi->name;
+       pi++)
+    if ((byte0 & pi->mask) == pi->opcode)
+      return pi;
+  return 0;
+}
+
+void picinsn_decode(const PicInsn *pi, const PicInsnInfo *table,
+                   const PicInsnInfo **pii_r, int *objnum_r, int *v_r) {
+  const PicInsnInfo *pii;
+  unsigned val= 0;
+
+  pii= pi->l > 0 ? lookup_byopcode(pi->d[0], table) : 0;
+
+  if (pii) {
+    val= pi->d[0];
+    if (pii->argsbits <= 6) {
+      if (pi->l != 1) pii= 0;
+    } else {
+      if (pi->l == 2 && !(pi->d[1] & 0x80u)) { val <<= 7; val |= pi->d[1]; }
+      else pii= 0;
+    }
+  }
+
+  if (pii) {
+    if (objnum_r) *objnum_r= (val & ((1u << pii->argsbits) - 1)) >> pii->vbits;
+    if (v_r)      *v_r=       val & ((1u << pii->vbits) - 1);
+  }
+  *pii_r= pii;
 }
 
 const PicInsnInfo pic_command_infos[]= {
-  { "@cnameyn@", @opcodeyn@, @arglen@ }, @h2p@
+  { "@cnameyn@", @opcodeyn@, @opcodemaskyn@, @argslen@, @vlen@, @noiselevel@, 0 }, @h2p@
   { 0 }
 };
 
 const PicInsnInfo pic_reply_infos[]= {
-  { "@cnameyn@", @opcodeyn@, @arglen@ }, @p2h@
+  { "@cnameyn@", @opcodeyn@, @opcodemaskyn@, @argslen@, @vlen@, @noiselevel@, on_pic_@cnameyn@ },@p2h@
   { 0 }
 };