chiark / gitweb /
Merge and end branch-hostside-wip-2008-01-25 PROPERLY; cvs up -j branch-hostside...
[trains.git] / hostside / skelproto-pic.c
index e828302587cdcb57e14fba46a108ee95cc533ebf..92c847d9caa787aba911f8cf09bd2c8ef2810be1 100644 (file)
@@ -1,34 +1,78 @@
 /* @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) {
+extern void enco_pic_any(PicInsn *out, int opcode, int argbits, int objnum) {
   unsigned long as= objnum;
   int i;
 
-  out->l= 1 + pii->argbits/7;
+  assert(!(as & (~0UL << argbits)));
+  out->l= 1 + argbits/7;
   for (i= out->l - 1;
-       i > 0;
+       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;
+}
+
+#define C ,
+#define ENCO(w, xa, opcode, argbits, objnum)           \
+  extern void enco_pic_##w(PicInsn *out  xa) {         \
+    return enco_pic_any(out, opcode, argbits, objnum); \
+  }
+
+ENCO(pii, C const PicInsnInfo *pii C int objn,pii->opcode,pii->argbits,objn)
+ENCO(@cnameyn@,             , @opcodeyn@, 0,0)             @h2p@ @arglentf=0@
+ENCO(@cnameyn@, C int objnum, @opcodeyn@, @arglen@,objnum) @h2p@ @arglentf=1@
+
+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) {
+  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->argbits <= 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 (objnum_r && pii) *objnum_r= val & ((1u << pii->argbits) - 1);
+  *pii_r= pii;
 }
 
 const PicInsnInfo pic_command_infos[]= {
-  { "@cnameyn@", @opcodeyn@, @arglen@ }, @h2p@
+  { "@cnameyn@", @opcodeyn@, @opcodemaskyn@, @arglen@, @noiselevel@, 0 }, @h2p@
   { 0 }
 };
 
 const PicInsnInfo pic_reply_infos[]= {
-  { "@cnameyn@", @opcodeyn@, @arglen@ }, @p2h@
+  { "@cnameyn@", @opcodeyn@, @opcodemaskyn@, @arglen@, @noiselevel@, on_pic_@cnameyn@ },@p2h@
   { 0 }
 };