chiark / gitweb /
show debugp in debug section
[trains.git] / hostside / safety.h
1 /**/
2
3 #ifndef SAFETY_H
4 #define SAFETY_H
5
6 #include "../layout/layout-data.h"
7 #include "layoutinfo.h"
8
9 /*========== more basic types etc. ==========*/
10
11 typedef short TimeInterval; /*ms*/
12 typedef int ErrorCode;
13
14 /*---------- units and scales ----------*/
15
16 /*
17  * Distances are in mm.
18  * Times are in ms.
19  * Speeds are in fixed point: unit is 1/SPEED_UNIT m/s
20  */
21
22 #define SPEED_SHIFT 7
23 #define SPEED_UNIT (1L<<SPEED_SHIFT) /* ms/mm */
24
25 /*========== state of the layout ==========*/
26
27 typedef struct {
28   SegmentNum foredetect;   /* train's detectable part is at most maxinto   */
29   Distance maxinto, uncertainty;   /*   into foredetect but train may be   */
30   unsigned                         /*   uncertainty less far advanced      */
31     backwards:1; /* train is moving backwards wrt its own front and back */
32   Speed speed;
33 } TrainState;
34
35 typedef struct {
36   unsigned
37     owned:1, /* this track segment is reserved for a train */
38     tr_backwards:1, /* train's motion is (would be) backwards wrt track */
39     movfeat_moving:1, /* feature(s) have been told to change to movposcomb */
40     cm_autostop:1, /* train should stop on detection */
41     seg_inverted:1, /* polarity is inverted */
42     tr_updated:1; /* for use by safety.c:lay_train etc.; otherwise 0 */
43   TimeInterval until_here, /* ) nonnegative; */  /* ) always valid but */
44     until_detect;          /* ) 0 if already */  /* )  only meaningful */
45   TrainNum owner;                                /* )  iff owned       */
46   MovPosComb movposcomb;
47   /*polarity?*/
48 } SegmentState;
49
50 typedef struct {
51   TrainState trains[NUM_TRAINS];
52   SegmentState segments[NUM_SEGMENTS];
53 } State;
54
55 extern State safety_state;
56
57 /*========== embed.c ==========*/
58 /* surrounds the algorithms and machinery in a program: logging, error
59  * handling, arg parsing, etc.
60  */
61
62 void logmsg(ErrorCode ec, TrainNum tran, SegmentNum segn, const char *fmt,...)
63      __attribute__((format(printf,4,5)));
64
65 void safety_panic(TrainNum tran, SegmentNum segn, const char *fmt,...)
66      __attribute__((format(printf,3,4),noreturn));
67
68 ErrorCode safety_problem(TrainNum tran, SegmentNum segn, const char *fmt,...)
69      __attribute__((format(printf,3,4)));
70
71 /*========== safety.c ==========*/
72 /*
73  * safety.c is responsible for ensuring that things don't go
74  * physically wrong (eg, collisions, derailments, short circuits,
75  * etc.).
76  */
77
78 void safety_emergencystop(TrainNum);
79   /* Callable directly in response to application command. */
80
81 void safety_requestspeed(TrainNum tran, long newspeed);
82   /* To be called only by the speed manager, thus indirectly from
83    * user request.
84    * Will result in a call to speedmanager_speedchange_notify (and of
85    * course to actual_setspeed.  Speed manager must apply accel/decel
86    * curve so that if safety.c agrees the command, the actual speed of
87    * the train changes straight away (at least for decel).
88    */
89
90 void safety_notify_detection(SegmentNum segn);
91   /* To be called by actual.c when new train detection occurs. */
92
93 /*========== speedmgr.c ==========*/
94
95 void speedmanager_speedchange_notify(TrainNum tran);
96   /* To be called only by safety.c, whenever speed is actually set.
97    * New speed has already been recorded in State. */
98
99 /*========== actual.c ==========*/
100 /* actual.c should only be called from safety.c.
101  * It is responsible for communicating with the PICs, including
102  * repeating the NMRA commands and redacting detection information.
103  *
104  * In general, when State information is shared between actual.c
105  * and safety.c, actual.c is responsible for modifying State, and
106  * will then call an actual_... function to notify the change.
107  */
108
109 void actual_setspeed(TrainNum tran);
110 void actual_emergencystop(TrainNum tran);
111
112 void actual_inversions_start(void);
113 void actual_inversions_segment(SegmentNum);
114 void actual_inversions_done(void);
115   /* safety.c will call these in this order: first start, then segment
116    * for 0 or more segments (whose s.segments[segn].seg_inverted may
117    * or may not have changed), and finally done.  At done, the PICs
118    * should be told to (de)invert the segments as specified.  */
119   
120 /*
121  * Entrypoints are:                  Called from, and as a result of:
122  *   actual_setspeed                    safety.c
123  *   actual_emergencystop               safety.c
124  */
125
126 /*========== utils.c ==========*/
127
128 typedef struct TrackLocation TrackLocation;
129 struct TrackLocation { /* transparent, and manipulable by trackloc_... fns */
130   SegmentNum segn; /* current segment */
131   long into; /* distance from start of segment */
132   unsigned backwards:1; /* if 1, into is positive and measured from end */
133 };
134
135 long trackloc_remaininseg(const TrackLocation *tloc);
136   /* Returns dist that tloc can advance before it goes into next segment. */
137
138 void trackloc_further(TrackLocation *tloc, long *remain_io);
139   /* Advances tloc, decrementing *remain_io, until either
140    * *remain_io becomes zero, or tloc->segn changes. */
141
142 void trackloc_reverse(TrackLocation *tloc);
143   /* Reverses tloc without changing its actual location. */
144
145 const SegPosCombInfo *trackloc_segposcomb(const TrackLocation *tloc);
146 const SegmentLinkInfo *trackloc_segmentlink(const TrackLocation *tloc,
147                                             const SegPosCombInfo *pci,
148                                             unsigned far);
149
150 /*========== useful macros and declarations ==========*/
151
152 /*---------- calculations with fixed point speeds ----------*/
153
154 #define DIVIDE_ROUNDING_UP(num,den)   (((num) + (den) - 1) / (den))
155 #define DIVIDE_ROUNDING_DOWN(num,den) ( (num)             / (den))
156
157 #define SPEED_CALC_TIME(speed,dist,round) \
158   DIVIDE_ROUNDING_##round((dist) * SPEED_UNIT, (speed))
159
160 #define SPEED_CALC_DIST(speed,time,round) \
161   DIVIDE_ROUNDING_##round((time) * (speed), SPEED_UNIT)
162
163 /*---------- safety margin parameters ----------*/
164
165 #define CLEAR_FORESIGHT_TIME 500 /*ms*/
166 #define AUTOSTOP_MAXSPEED ((50 * SPEED_UNIT)/1000) /* 50 mm/s */
167 #define AUTOSTOP_UNCERTAINTY 20
168 #define ESTOP_UNCERTAINTY 300
169
170 #define SPEED_CLEAR_MULT SPEED_CALC_DIST(1,CLEAR_FORESIGHT_TIME,UP)
171
172 #endif /*SAFETY_H*/