From 0c2b0e61362ba6857e3086f351a477cd36271810 Mon Sep 17 00:00:00 2001 From: ian Date: Mon, 30 Jun 2008 12:23:06 +0000 Subject: [PATCH] parses and transmits features; compiled but not tested (including suppressed features like half speed) --- hostside/actual.c | 54 +++++++++++++++++++++++++++++++++++++++++++ hostside/homes.record | 3 +++ hostside/realtime.h | 12 +++++++--- hostside/record-y.y | 5 ++-- hostside/record.c | 38 ++++++++++++++++++------------ hostside/startup.c | 1 + 6 files changed, 93 insertions(+), 20 deletions(-) diff --git a/hostside/actual.c b/hostside/actual.c index c371b13..e38f81a 100644 --- a/hostside/actual.c +++ b/hostside/actual.c @@ -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; ixrn[ix]; + if (!rn->pi.l) { + enco_nmra_idle(&n); + retransmit_relaxed_queue(rn,&n); + } + } + features_updated(a); + } +} diff --git a/hostside/homes.record b/hostside/homes.record index 05275b9..1cf9484 100644 --- a/hostside/homes.record +++ b/hostside/homes.record @@ -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 diff --git a/hostside/realtime.h b/hostside/realtime.h index 7dc083c..2b76cb0 100644 --- a/hostside/realtime.h +++ b/hostside/realtime.h @@ -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); diff --git a/hostside/record-y.y b/hostside/record-y.y index 5042851..b71c55e 100644 --- a/hostside/record-y.y +++ b/hostside/record-y.y @@ -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 diff --git a/hostside/record.c b/hostside/record.c index dedd663..d767478 100644 --- a/hostside/record.c +++ b/hostside/record.c @@ -12,6 +12,8 @@ * seg at * feature is * feature is step [-] + * feature - is } prevents enabling feature; + * feature - is step [-] } 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<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) { diff --git a/hostside/startup.c b/hostside/startup.c index 853700c..1e42ae8 100644 --- a/hostside/startup.c +++ b/hostside/startup.c @@ -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: -- 2.30.2