chiark / gitweb /
parses and transmits features; compiled but not tested (including suppressed features...
authorian <ian>
Mon, 30 Jun 2008 12:23:06 +0000 (12:23 +0000)
committerian <ian>
Mon, 30 Jun 2008 12:23:06 +0000 (12:23 +0000)
hostside/actual.c
hostside/homes.record
hostside/realtime.h
hostside/record-y.y
hostside/record.c
hostside/startup.c

index c371b1371edacdda9ced5dc389ae0cfbb471fac5..e38f81a797d915f6053acca0a5a659fd5a3a9853 100644 (file)
@@ -4,6 +4,9 @@
  */
 
 #include "realtime.h"
+#include "nmra.h"
+
+/*---------- polarity ----------*/
 
 static PicInsn polarityinsn= { { 0x90 }, 0 };
 
@@ -48,3 +51,54 @@ void actual_inversions_segment(Segment *seg) {
 void actual_inversions_done(void) {
   serial_transmit(&polarityinsn);
 }
+
+/*---------- features ----------*/
+
+static void feat_updated_cmd(FeaturesAddr *a, int ix, Nmra *n /*destroyed*/) {
+  assert(a->rn[ix].pi.l);
+  retransmit_relaxed_cancel(&a->rn[ix]);
+  retransmit_relaxed_queue(&a->rn[ix], n);
+}
+
+static void feat_updated_funcs(FeaturesAddr *a, int ix,
+                              void (*enco)(Nmra *n, int addr, unsigned map),
+                              unsigned thiscmd) {
+  Nmra n;
+  if (!(a->all & thiscmd)) return;
+  enco(&n,a->addr,a->current);
+  feat_updated_cmd(a,ix,&n);
+}
+
+void features_updated(FeaturesAddr *a) {
+  /* idempotent; call this after updating a->current */
+
+  feat_updated_funcs(a,0, enco_nmra_funcs0to4,  0x0001f);
+  feat_updated_funcs(a,1, enco_nmra_funcs5to8,  0x001e0);
+  feat_updated_funcs(a,2, enco_nmra_funcs9to12, 0x01e00);
+
+  if (a->all & FEATURES_SPEEDSTEP_BIT) {
+    Nmra n;
+    enco_nmra_speed126(&n, a->addr,
+                      a->current & FEATURES_SPEEDSTEP_BIT
+                      ? a->speedstep : 0,
+                      !!(a->all & FEATURES_SPEEDSTEP_REVERSE));
+    feat_updated_cmd(a,3, &n);
+  }
+}
+
+void features_start_xmit(void) {
+  FeaturesAddr *a;
+  Nmra n;
+  int ix;
+
+  for (a=feataddrs_head; a; a=a->next) {
+    for (ix=0; ix<FEATURESADDR_TRANSMITS; ix++) {
+      RetransmitRelaxedNode *rn= &a->rn[ix];
+      if (!rn->pi.l) {
+       enco_nmra_idle(&n);
+       retransmit_relaxed_queue(rn,&n);
+      }
+    }
+    features_updated(a);
+  }
+}
index 05275b9063736515c09d2c02bc562d97615ccbac..1cf948451968d69d9a0ec446b85d9420fb68e483 100644 (file)
@@ -5,12 +5,15 @@ feature shinkansen head               is 1 5
 feature shinkansen head-red    is 1 6
 feature shinkansen tail                is 1 7
 feature shinkansen tail-red    is 1 8
+feature -                      is 1 4
 
 feature santafe head           is 2 5
 feature santafe tail           is 2 6
+feature -                      is 2 4
 
 feature bavarian head          is 4 5
 feature bavarian tail          is 4 6
+feature -                      is 4 4
 
 feature hoover motor           is 5 step 60
 
index 7dc083c69fdfe6557b8c02a5f3012ee67fe2cf9e..2b76cb0d49c20bb0acfaa7325a7a243175c9ec30 100644 (file)
@@ -73,17 +73,20 @@ void retransmit_relaxed_cancel(RetransmitRelaxedNode *rn);
   /* 0..2 are func0to4 func5to8 func9to12 and speed cmd
    * pi.l is 0 if not transmitting */
 
+#define FEATURES_SPEEDSTEP_BIT     0x4000u /* in a->current, a->all, f->bits */
+#define FEATURES_SPEEDSTEP_REVERSE 0x8000u /* in a->all */
+
 typedef struct FeaturesAddr {
   struct FeaturesAddr *next;
-  int addr, cbitmap;
+  int addr, speedstep;
+  unsigned current, all;
   RetransmitRelaxedNode rn[FEATURESADDR_TRANSMITS];
 } FeaturesAddr;
 
 typedef struct {
   char *pname; /* first, for pname1st_compar */
   FeaturesAddr *a;
-  int bitval; /* may have no or several bits set */
-  int speedstep; /* -ve means backwards; 0 means not to use motor for feat */
+  unsigned bits; /* may have no or several bits set */
 } FeaturesFeature;
 
 typedef struct FeaturesTarget {
@@ -182,6 +185,9 @@ int picinsn_polarity_testbit(const PicInsn *pi, const SegmentInfo *segi);
   /* this belongs in {au,skel}proto-pic.[ch] really but it's
    * more convenient here. */
 
+void features_start_xmit(void);
+void features_updated(FeaturesAddr *a);
+
 /*---------- from movpos.c ----------*/
 
 void points_turning_on(void);
index 5042851e35f2e2f3f4d290a071b387491df809ad..b71c55e85d2ab5938550deb1279a5ee760826ac3 100644 (file)
@@ -61,10 +61,10 @@ line:               /* empty */
        {         if ($2) record_seg_at($2,$4);
        }
        |       FEATURE feature IS feataddr NUM
-       {         if ($2) record_feature_nmrafeat($2,$4,$5);
+       {         if (trains) record_feature_nmrafeat($2,$4,$5);
        }
        |       FEATURE feature IS feataddr STEP NUM
-       {         if ($2) record_feature_motor($2,$4,$6);
+       {         if (trains) record_feature_motor($2,$4,$6);
        }
 
 backwards:     /* empty */ { $$= 0; }
@@ -87,6 +87,7 @@ dbl:          DBL
 seg:           ident { $$= record_pname2seg($1); }
 train:         ident { $$= record_pname2train($1); }
 feature:       ident ident { $$= record_pname2feature($1,$2); }
+       |       '-' { $$= 0; }
 feataddr:      NUM { $$= record_feataddr($1); }
 
 end:           END NL
index dedd6637a5c32346414caaeada6b556dfa5f08e6..d76747840fbf4aa5bbdbe387d56a3a2557d88986 100644 (file)
@@ -12,6 +12,8 @@
  *  seg <segpn> at <movposcomb>
  *  feature <trainorfeatpn> <featpn> is <addr> <nmranum>
  *  feature <trainorfeatpn> <featpn> is <addr> step [-]<nmranum>
+ *  feature - is <addr> <nmranum>             } prevents enabling feature;
+ *  feature - is <addr> step [-]<nmranum>     }  xmits turning it off
  *
  * speed is floating point in m/s
  */
@@ -98,7 +100,8 @@ FeaturesAddr *record_feataddr(int num) {
       int i;
       node->next= 0;
       node->addr= num;
-      node->cbitmap= 0;
+      node->speedstep= 0;
+      node->current= node->all= 0;
       for (i=0; i<4; i++) node->rn[i].pi.l= 0;
     }));
   
@@ -109,7 +112,6 @@ FeaturesFeature *record_pname2feature(const char *targpn, const char *featpn) {
   int i;
   FeaturesTarget *targ;
   FeaturesFeature *feat;
-  if (!trains) return 0; /* 2nd pass only */
 
   ARY_FIND_OR_APPEND
     (feattargs,n_feattargs,i,targ, !strcmp(targ->pname, targpn), ({
@@ -122,8 +124,7 @@ FeaturesFeature *record_pname2feature(const char *targpn, const char *featpn) {
     (targ->feats,targ->n_feats,i,feat, !strcmp(feat->pname, featpn), ({
       feat->pname= mstrdup(featpn);
       feat->a= 0;
-      feat->bitval= 0;
-      feat->speedstep= 0;
+      feat->bits= 0;
     }));
 
   return feat;
@@ -229,36 +230,43 @@ found:
 
 /*---------- features ----------*/
 
-static void record_feature_addr(FeaturesFeature *feat, FeaturesAddr *addr) {
+static void record_feature_bits(FeaturesFeature *feat, FeaturesAddr *addr,
+                               unsigned bits) {
+  if (!feat) /* `-' feature */
+    return;
   if (feat->a && feat->a != addr)
     record_yyerror("feature includes multiple decoder addresses");
   feat->a= addr;
+  feat->bits |= bits;
+  addr->all |= bits;
 }
 
 void record_feature_nmrafeat(FeaturesFeature *feat, FeaturesAddr *addr,
                             int num) {
   int bitval;
 
-  record_feature_addr(feat,addr);
-  
   if (num<0 || num>12) record_yyerror("NMRA function out of range 0..12");
   bitval= 1<<num;
 
-  if (feat->bitval & bitval)
-    record_yyerror("feature bit respecified unnecessarily");
-
-  feat->bitval |= bitval;
+  if (addr->all & bitval)
+    record_yyerror("feature bit respecified");
+  
+  record_feature_bits(feat,addr,bitval);
 }
 
 void record_feature_motor(FeaturesFeature *feat, FeaturesAddr *addr,
                          int speed) {
-  record_feature_addr(feat,addr);
-
   if (speed<-126 || speed>126) record_yyerror("motor speed out of range");
   if (!speed) record_yyerror("zero motor speed?!");
+  if (addr->speedstep) record_yyerror("feature specifies multiple speeds");
+
+  record_feature_bits(feat,addr,FEATURES_SPEEDSTEP_BIT);
 
-  if (feat->speedstep) record_yyerror("feature specifies multiple speeds");
-  feat->speedstep= speed;
+  addr->speedstep= speed;
+  if (addr->speedstep<0) {
+    addr->all |= FEATURES_SPEEDSTEP_REVERSE;
+    addr->speedstep= -addr->speedstep;
+  }
 }
 
 static int pname1st_compar(const void *av, const void *bv) {
index 853700c7ac1dee375d824e201ae6067725a5f95f..1e42ae82815e84abd8b90a9d80a6b41057fcb609 100644 (file)
@@ -134,6 +134,7 @@ static void sta_goto(StartupState new_state) {
   case Sta_Resolving:
     resolve_begin();
     points_turning_on();
+    features_start_xmit();
     enco_pic_on(&piob);
     break;
   case Sta_Finalising: