speed <stuff>...
- feature <trainortarg> -|+|^ <feature>|*
- !feature <trainortarg> -|+|^ <feature>|*|<nmranum>
- fixme ???
- nb if <nmranum> is spec'd then <trainortarg> must be a name
+ feature <feattargetname> -|+|^ <feature>|* [[-|+|^] ...]
+ !nmrafeat <trainpname>|<addrnum> -|+|^ <nmranum> [[-|+|^] ...]
route <seg> <movposcomb> [<maxms>]
route <before>|- <seg> <after>|- [<maxms>] any suitable movposcomb
feat_updated_funcs(a,1, enco_nmra_funcs5to8, 0x001e0);
feat_updated_funcs(a,2, enco_nmra_funcs9to12, 0x01e00);
- if (a->all & FEATURES_SPEEDSTEP_BIT) {
+ if (a->all & FEATS_SPEEDSTEP_BIT) {
Nmra n;
enco_nmra_speed126(&n, a->addr,
- a->current & FEATURES_SPEEDSTEP_BIT
+ a->current & FEATS_SPEEDSTEP_BIT
? a->speedstep : 0,
- !!(a->all & FEATURES_SPEEDSTEP_REVERSE));
+ !!(a->all & FEATS_SPEEDSTEP_REVERSE));
feat_updated_cmd(a,3, &n);
}
}
void features_start_xmit(void) {
- FeaturesAddr *a;
+ FeaturesAddr **ap;
Nmra n;
- int ix;
+ int ix, ai;
- for (a=feataddrs_head; a; a=a->next) {
+ for (ai=0,ap=feataddrs; ai<n_feataddrs; ai++,ap++) {
+ FeaturesAddr *a= *ap;
for (ix=0; ix<FEATURESADDR_TRANSMITS; ix++) {
RetransmitRelaxedNode *rn= &a->rn[ix];
if (!rn->pi.l) {
/* 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 */
+#define FEATS_SPEEDSTEP_BIT 0x4000u /* a->{current,all,permit}, f->bits */
+#define FEATS_SPEEDSTEP_REVERSE 0x8000u /* in a->all */
typedef struct FeaturesAddr {
struct FeaturesAddr *next;
int addr, speedstep;
- unsigned current, all;
+ unsigned current, permit, all;
RetransmitRelaxedNode rn[FEATURESADDR_TRANSMITS];
} FeaturesAddr;
extern Train *trains;
extern Segment *segments;
-extern int n_feattargs;
+extern int n_feattargs, n_feataddrs;
extern FeaturesTarget *feattargs;
-extern FeaturesAddr *feataddrs_head;
+extern FeaturesAddr **feataddrs;
/*---------- global variables, in realtime.c ----------*/
#include "record-i.h"
#include "record-l.h"
-int n_feattargs;
+int n_feattargs, n_feataddrs;
FeaturesTarget *feattargs;
-FeaturesAddr *feataddrs_head;
+FeaturesAddr **feataddrs;
/*---------- input and error handling ----------*/
}while(0)
FeaturesAddr *record_feataddr(int num) {
- FeaturesAddr **search, *node;
+ FeaturesAddr **search;
+ int ix;
if (num<1 || num>0x3ff) record_yyerror("feature address out of range");
- SLIST_FIND_OR_INSERT
- (feataddrs_head,search,node, node->addr == num, ({
+ ARY_FIND_OR_APPEND
+ (feataddrs,n_feataddrs, ix,search, (*search)->addr == num, ({
int i;
- node->next= 0;
- node->addr= num;
- node->speedstep= 0;
- node->current= node->all= 0;
- for (i=0; i<4; i++) node->rn[i].pi.l= 0;
+ FeaturesAddr *item= mmalloc(sizeof(*item));
+ item->next= 0;
+ item->addr= num;
+ item->speedstep= 0;
+ item->current= item->permit= item->all= 0;
+ for (i=0; i<4; i++) item->rn[i].pi.l= 0;
+ *search= item;
}));
- return node;
+ return *search;
}
FeaturesFeature *record_pname2feature(const char *targpn, const char *featpn) {
record_yyerror("feature includes multiple decoder addresses");
feat->a= addr;
feat->bits |= bits;
+ addr->permit |= bits;
addr->all |= bits;
}
if (!speed) record_yyerror("zero motor speed?!");
if (addr->speedstep) record_yyerror("feature specifies multiple speeds");
- record_feature_bits(feat,addr,FEATURES_SPEEDSTEP_BIT);
+ record_feature_bits(feat,addr,FEATS_SPEEDSTEP_BIT);
addr->speedstep= speed;
if (addr->speedstep<0) {
- addr->all |= FEATURES_SPEEDSTEP_REVERSE;
+ addr->all |= FEATS_SPEEDSTEP_REVERSE;
addr->speedstep= -addr->speedstep;
}
}
return strcmp(*a,*b);
}
+static int feataddrp_compar(const void *av, const void *bv) {
+ const FeaturesAddr *const *a= av;
+ const FeaturesAddr *const *b= bv;
+ return (*a)->addr - (*b)->addr;
+}
+
static void features_postprocess(void) {
int i;
FeaturesTarget *targ;
qsort(feattargs, n_feattargs, sizeof(*feattargs), pname1st_compar);
+ qsort(feataddrs, n_feataddrs, sizeof(*feataddrs), feataddrp_compar);
for (i=0, targ=feattargs;
i<n_feattargs;