chiark / gitweb /
dump decoding of transmitted nmra data
authorian <ian>
Tue, 15 Jan 2008 22:34:36 +0000 (22:34 +0000)
committerian <ian>
Tue, 15 Jan 2008 22:34:36 +0000 (22:34 +0000)
hostside/realtime.c

index 18e1f132d95321db31e4373143100fe18de62c02..bfab9e21f52106fc29fe3f2217964dde045cc3bb 100644 (file)
@@ -109,6 +109,108 @@ ErrorCode safety_problem(Train *tra, Segment *seg, const char *fmt,...) {
   return EC_Safety;
 }
 
+/*---------- printing nmra data ----------*/
+
+typedef struct {
+  const Byte *i, *o;
+  int npending;
+  unsigned datapending;
+} NmraDecCtx;
+
+static void nmradec_init(NmraDecCtx *d, const PicInsn *pi) {
+  d->i= pi->d;
+  d->o= pi->d + pi->l;
+  d->npending= 0;
+  d->datapending= 0;
+}
+
+static void nmradec_getbits(NmraDecCtx *d, int *nbits_io, unsigned *bits_r) {
+  int use= *nbits_io;
+  while (d->npending < use) {
+    if (d->i >= d->o) break;
+    d->datapending <<= 7;
+    d->datapending |= *d->i & 0x7f;
+    d->npending += 7;
+    if (!(*d->i++ & 0x80)) break;
+  }
+  if (d->npending < use) use= d->npending;
+  d->npending -= use;
+  *bits_r= (d->datapending >> d->npending) & ~(~0u << use);
+  *nbits_io= use;
+}
+  
+static void nmra_decodeforpic(const PicInsn *pi,
+                             void (*on_idle)(void *u, int),
+                             void (*on_packet)(void *u, const Nmra*),
+                             void (*on_error)(void *u, int reasonchar),
+                             void *u) {
+  /* reasonchars:
+   *    #  - bad checksum
+   *    !  - too little idle
+   *    $  - truncated
+   */
+  NmraDecCtx d;
+  Nmra n;
+  int need_idle=7, got_idle=0;
+  unsigned got, csum;
+  int nbits;
+  
+  nmradec_init(&d,pi);
+  for (;;) {
+    nbits=1; nmradec_getbits(&d,&nbits,&got);
+    if (got) { got_idle++; continue; }
+    if (got_idle) on_idle(u,got_idle);
+    if (!nbits) return;
+    if (got_idle < need_idle) on_error(u,'!');
+    got_idle= 0;
+
+    n.l=0; csum=0;
+    do {
+      nbits=8; nmradec_getbits(&d,&nbits,&got);
+      n.d[n.l++]= got;
+      csum ^= got;
+      if (nbits<8) on_error(u,'$');
+
+      nbits=1; nmradec_getbits(&d,&nbits,&got);
+      if (nbits<1) on_error(u,'$');
+    } while (nbits && !got);
+
+    if (csum) on_error(u,'#');
+    else n.l--;
+
+    on_packet(u,&n);
+    need_idle= 14;
+  }
+}
+
+static void opn_idle(void *u, int idle) {
+  static const char dots[]= "......."; /* at least base/2 */
+  const int base= 14;
+  int largers= idle / base;
+  int units= idle % base;
+
+  oprintf(UPO," %.*s%.*s%.*s",
+         units/2, dots,
+         largers, ":::::::" /* enough */,
+         (units+1)/2, dots);
+}
+static void opn_error(void *u, int rc) { oprintf(UPO," %c",rc); }
+static void opn_packet(void *u, const Nmra *n) {
+  int i;
+  const char *delim= " <";
+  for (i=0; i<n->l; i++) {
+    oprintf(UPO,"%s%02x",delim,n->d[i]);
+    delim=" ";
+  }
+  oprintf(UPO,">");
+}
+
+static void oprint_nmradata(const PicInsn *pi) {
+  oprintf(UPO,"picio out nmradata");
+  nmra_decodeforpic(pi, opn_idle,opn_packet,opn_error, 0);
+  oprintf(UPO,"\n");
+}
+  
 /*---------- command channel handling (oop_read, obc) ----------*/
 
 static void command_doline(ParseState *ps, CommandInput *cmdi) {
@@ -159,7 +261,8 @@ static void *serial_readable(oop_source *evts, int fd,
                             oop_event evt, void *u0) {
   int r, buf_used;
 
-  r= read(serial_fd, &serial_buf.d, sizeof(serial_buf.d) - serial_buf.l);
+  r= read(serial_fd, &serial_buf.d + serial_buf.l,
+         sizeof(serial_buf.d) - serial_buf.l);
   if (r==0) die("serial port - eof");
   if (r==-1) {
     if (errno == EWOULDBLOCK || errno == EINTR)
@@ -204,6 +307,8 @@ void serial_transmit(const PicInsn *pi) {
       delim= ",";
     }
     oprintf(UPO,">\n");
+  } else if (pi->d[0] == 0xff) {
+    oprint_nmradata(pi);
   } else {
     picinsn_decode(pi, pic_command_infos, &pii, &objnum);
     if (!pii)