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