chiark / gitweb /
giant reorg abolishes TrainNum most of the time; working on making it build
[trains.git] / hostside / safety.h
1 /**/
2
3 #ifndef SAFETY_H
4 #define SAFETY_H
5
6 #include <stdarg.h>
7
8 #include "../layout/layout-data.h"
9 #include "layoutinfo.h"
10 #include "errorcodes.h"
11
12 /*========== more basic types etc. ==========*/
13
14 typedef short TimeInterval; /*ms*/
15
16 /*---------- units and scales ----------*/
17
18 /*
19  * Distances are in mm.
20  * Times are in ms.
21  * Speeds are in fixed point: unit is 1/SPEED_UNIT m/s
22  */
23
24 #define SPEED_SHIFT 7
25 #define SPEED_UNIT (1L<<SPEED_SHIFT) /* ms/mm */
26
27 /*========== state of the layout ==========*/
28
29 typedef struct {
30   int step;
31   long speed;
32   TimeInterval upwait, downwait; /* between this insn and next one */
33 } SpeedCurveEntry;
34
35 struct Train {
36   /* Configuration (excluding speed curve): */
37   char *pname;
38   int addr;
39   Distance head, detectable, tail;
40
41   /* Location: */
42   Segment *foredetect;     /* train's detectable part is at most maxinto   */
43   Distance maxinto, uncertainty;   /*   into foredetect but train may be   */
44   unsigned                         /*   uncertainty less far advanced      */
45     backwards:1, /* train is moving backwards wrt its own front and back */
46
47   /* Speed: */
48     estopping:1; /* set and cleared by speed.c */
49   Speed speed; /* when accelerating/decelerating, is maximum at this moment */
50
51   struct {
52     int target; /* index into curve */
53     int commanded; /* when ac-/decel, eq last value xmitted */
54     TimeoutEvent more; 
55     RetransmitUrgentNode rn;
56
57     /* Configuration for acceleration: */
58     SpeedCurveEntry *curve;
59     int curvesz;
60   } accel;
61 };
62
63 struct Segment {
64   Train *owner;                                  /* or 0 */
65   unsigned
66     tr_backwards:1, /* train's motion is (would be) backwards wrt track */
67     movfeat_moving:1, /* feature(s) have been told to change to movposcomb */
68     cm_autostop:1, /* train should stop on detection */
69     seg_inverted:1, /* polarity is inverted */
70     tr_updated:1; /* for use by safety.c:lay_train etc.; otherwise 0 */
71   TimeInterval until_here, /* ) nonnegative; */  /* ) always valid but      */
72     until_detect;          /* ) 0 if already */  /* )  meaningful iff owner */
73   MovPosComb movposcomb;
74   const SegmentInfo *i;
75 };
76
77 extern int n_trains;
78 extern Train *trains;
79 extern Segment *segments;
80
81 /*========== embed.c ==========*/
82 /* surrounds the algorithms and machinery in a program: logging, error
83  * handling, arg parsing, etc.
84  */
85
86 void vlogmsg(ErrorCode ec, Train *tra, const SegmentInfo *segi,
87              const char *fmt, va_list al) __attribute__((format(printf,4,0)));
88 void logmsg(ErrorCode ec, Train *tra, const SegmentInfo *segi,
89             const char *fmt, ...) __attribute__((format(printf,4,5)));
90
91 void safety_vpanic(Train *tra, Segment *seg, const char *fmt, va_list al)
92      __attribute__((format(printf,3,0),noreturn));
93 void safety_panic(Train *tra, Segment *seg, const char *fmt,...)
94      __attribute__((format(printf,3,4),noreturn));
95
96 ErrorCode safety_problem(Train *tra, Segment *seg, const char *fmt, ...)
97      __attribute__((format(printf,3,4)));
98      /* simple wrapper around vlogmsg; implies and returns EC_Safety */
99
100 /*========== safety.c ==========*/
101 /*
102  * safety.c is responsible for ensuring that things don't go
103  * physically wrong (eg, collisions, derailments, short circuits,
104  * etc.).
105  */
106
107 void safety_emergencystop(Train*);
108   /* Callable directly in response to application command. */
109
110 ErrorCode safety_requestspeed(Train* tra, long newspeed);
111   /* To be called only by the speed manager, thus indirectly from
112    * user request.  Any error will have been logged.  On success,
113    * ->speed has been updated.  Speed manager is responsible for
114    * calling actual_setspeed.
115    */
116
117 void safety_setdirection(Train* tra, int sense_fixme_define_this_properly);
118
119 void safety_notify_detection(Segment *seg);
120   /* Called by startup.c when new train detection occurs in state Run. */
121
122 /*========== speedmgr.c ==========*/
123
124 void speedmanager_speedchange_request(Train *tra, long speed);
125   /* Callable directly in response to application command.
126    * speed may be LONG_MAX to mean maximum permitted.
127    */
128
129 void speedmanager_emergencystop(Train *tra);
130 void speedmanager_autostop(Train *tra);
131   /* These are responsible for calling actual_setspeed.
132    *
133    * After speedmanager_autostop, ->speed will have been updated to a
134    * new desired speed.  If it is 0 the train was going slowly and has
135    * been instructed to stop right now.
136    */
137
138 void speedmanager_reset_train(Train *tra);
139
140 /*========== actual.c ==========*/
141 /* actual.c should only be called from safety.c.
142  * It is responsible for communicating with the PICs, including
143  * repeating the NMRA commands and redacting detection information.
144  *
145  * In general, when State information is shared between actual.c
146  * and safety.c, safety.c is responsible for modifying State, and
147  * will then call an actual_... function to notify the change.
148  */
149
150 void actual_setspeed(Train *tra);
151 void actual_emergencystop(Train *tra);
152
153 void actual_inversions_start(void);
154 void actual_inversions_segment(Segment *seg);
155 void actual_inversions_done(void);
156   /* safety.c will call these in this order: first start, then segment
157    * for 0 or more segments (whose s.segments[segn].seg_inverted may
158    * or may not have changed), and finally done.  At done, the PICs
159    * should be told to (de)invert the segments as specified.  */
160   
161 /*
162  * Entrypoints are:                  Called from, and as a result of:
163  *   actual_setspeed                    safety.c
164  *   actual_emergencystop               safety.c
165  */
166
167 /*========== utils.c ==========*/
168
169 typedef struct TrackLocation TrackLocation;
170 struct TrackLocation { /* transparent, and manipulable by trackloc_... fns */
171   Segment *seg; /* current segment */
172   long into; /* distance from start of segment */
173   unsigned backwards:1; /* if 1, into is positive and measured from end */
174 };
175
176 long trackloc_remaininseg(const TrackLocation *tloc);
177   /* Returns dist that tloc can advance before it goes into next segment. */
178
179 void trackloc_further(TrackLocation *tloc, long *remain_io);
180   /* Advances tloc, decrementing *remain_io, until either
181    * *remain_io becomes zero, or tloc->segn changes. */
182
183 void trackloc_reverse(TrackLocation *tloc);
184   /* Reverses tloc without changing its actual location. */
185
186 const SegPosCombInfo *trackloc_segposcomb(const TrackLocation *tloc);
187 const SegmentLinkInfo *trackloc_segmentlink(const TrackLocation *tloc,
188                                             const SegPosCombInfo *pci,
189                                             unsigned far);
190
191 /*========== useful macros and declarations ==========*/
192
193 /*---------- calculations with fixed point speeds ----------*/
194
195 #define DIVIDE_ROUNDING_UP(num,den)   (((num) + (den) - 1) / (den))
196 #define DIVIDE_ROUNDING_DOWN(num,den) ( (num)             / (den))
197
198 #define SPEED_CALC_TIME(speed,dist,round) \
199   DIVIDE_ROUNDING_##round((dist) * SPEED_UNIT, (speed))
200
201 #define SPEED_CALC_DIST(speed,time,round) \
202   DIVIDE_ROUNDING_##round((time) * (speed), SPEED_UNIT)
203
204 /*---------- safety margin parameters ----------*/
205
206 #define CLEAR_FORESIGHT_TIME 500 /*ms*/
207 #define AUTOSTOP_MAXSPEED ((50 * SPEED_UNIT)/1000) /* 50 mm/s */
208 #define AUTOSTOP_UNCERTAINTY 20  /*mm*/
209 #define ESTOP_UNCERTAINTY 300  /*mm*/
210 #define ESTOP_DEADTIME    2000 /*ms*/
211
212 #define SPEED_CLEAR_MULT SPEED_CALC_DIST(1,CLEAR_FORESIGHT_TIME,UP)
213
214 #endif /*SAFETY_H*/