9 static void changereq_internal(Train *tra, int newcommanded, int inautostop);
10 static void accel_more(TimeoutEvent *toev);
12 void speedmanager_reset_train(Train *tra) {
18 tra->accel.target= tra->accel.commanded= 0;
19 toev_init(&tra->accel.more);
20 enco_nmra_speed126(&n, tra->addr, 0, tra->backwards);
21 retransmit_urgent_queue_relaxed(&tra->accel.rn, &n);
22 ec= safety_requestspeed(tra, 0);
24 safety_panic(tra, 0, "position reset impossible!");
27 static void xmit_speed(Train *tra) {
29 enco_nmra_speed126(&n, tra->addr,
30 tra->accel.curve[tra->accel.commanded].step,
32 retransmit_urgent_requeue(&tra->accel.rn, &n);
35 void speedmanager_autostop(Train *tra) {
36 if (tra->speed < AUTOSTOP_MAXSPEED) {
37 toev_stop(&tra->accel.more);
38 tra->accel.commanded= tra->accel.target= tra->speed= 0;
41 changereq_internal(tra, 0, 1);
45 static void estop_done(TimeoutEvent *toev) {
46 Train *tra= (void*)((char*)toev - offsetof(Train, accel.more));
47 retransmit_urgent_cancel(&tra->accel.rn);
48 speedmanager_reset_train(tra);
51 void speedmanager_emergencystop(Train *tra) {
54 toev_stop(&tra->accel.more);
55 enco_nmra_estop1(&n, tra->addr);
56 retransmit_urgent_requeue(&tra->accel.rn, &n);
58 toev_stop(&tra->accel.more);
59 tra->accel.more.callback= estop_done;
60 tra->accel.more.duration= ESTOP_DEADTIME;
61 toev_start(&tra->accel.more);
64 static void adjust_next(Train *tra, int inautostop) {
67 if (tra->accel.target > tra->accel.commanded) {
68 tra->accel.commanded++;
69 tra->accel.more.duration= tra->accel.curve[tra->accel.commanded].upwait;
70 newspeed= tra->accel.curve[tra->accel.commanded].speed;
71 } else if (tra->accel.target < tra->accel.commanded) {
72 newspeed= tra->accel.curve[tra->accel.commanded].speed;
73 tra->accel.commanded--;
74 tra->accel.more.duration= tra->accel.curve[tra->accel.commanded].downwait;
80 ErrorCode ec= safety_requestspeed(tra, newspeed);
82 assert(newspeed > tra->speed);
83 assert(tra->accel.target >= tra->accel.commanded);
84 tra->accel.target= --tra->accel.commanded;
85 toev_stop(&tra->accel.more);
92 toev_stop(&tra->accel.more);
93 tra->accel.more.callback= accel_more;
94 toev_start(&tra->accel.more);
98 static void accel_more(TimeoutEvent *toev) {
99 Train *tra= (void*)((char*)toev - offsetof(Train, accel.more));
103 static void changereq_internal(Train *tra, int newcommanded, int inautostop) {
106 if (!tra->accel.more.running) {
107 assert(tra->accel.commanded == tra->accel.target);
110 if (tra->accel.target > tra->accel.commanded) {
111 newold= tra->accel.commanded+1;
112 reverse= newcommanded < newold;
113 } else if (tra->accel.target < tra->accel.commanded) {
114 newold= tra->accel.commanded-1;
115 reverse= newcommanded > newold;
119 tra->accel.target= newcommanded;
122 /* switch from accel to decel or vice versa */
123 toev_stop(&tra->accel.more);
124 tra->accel.commanded= newold;
130 void speedmanager_speedchange_request(Train *tra, long speed) {
131 changereq_internal(tra, speed, 0);
132 int a, b, try, found;
133 const SpeedCurveEntry *curve= tra->accel.curve;
135 if (tra->estopping) {
136 logmsg(EC_Invalid, tra, 0, "speed request ignored during emergency stop");
140 for (a=0, b=tra->accel.curvesz;
144 if (curve[try].speed > speed) b= try; else a= try+1;
146 /* Loop postconditions:
148 * either a=try+1 never executed ie all curve[].speed > speed
150 * or curve[a-1].speed <= speed
151 * either b=try never executed ie all curve[].speed <= speed
152 * hence b=trai->nsteps
153 * or curve[b].speed > speed
155 found= a>1 ? a-1 : speed ? 1 : 0;
157 if (curve[found].speed < speed && speed != INT_MAX)
158 logmsg(EC_Invalid, tra,0,
159 "requested speed %ld excessive; capping at %ld",
160 speed, curve[found].speed);
162 changereq_internal(tra, found, 0);