//
// Structure of a Station-2-Station controller from Station * to Station *
//
scchart STST " * to * Controller " {
// Set of permission variables for required tracks
input int *_perm;
// Set of request variables for required tracks for 11 trains
output bool *_req[11];
// Train number
input int trainNum;
// Number of the departure track in a station
input int depTrack;
// Number of the destination track in a station
input int destTrack;
// Cleanup flag for selecting the destination track
input bool cleanup;
// Debug flag for additional output
input bool debug;
// Arrival track
output int arrTrack;
// Variable with value for arrTrack for selecting correct station elements
int i_arrOnTrack;
// Handles departing from a station *
initial state *_ST {
// hostcode call for additional output when debug
entry debug / 'println([trainNum][ST-ST] ... )';
// State, which sets requests for needed tracks
initial state waitForPerm {
entry / *_ST_4_req[trainNum] = true;
entry / *_LN_0_req[trainNum] = true;
}
// Transition is taken, if all permissions are received
--> gotPerm with (*_ST_4_perm == trainNum) & (*_LN_0_perm == trainNum)
// Transition is taken, if some (not all) permissions are received
--> backOff with (*_ST_4_perm == trainNum) | (*_LN_0_perm == trainNum);
// State for waiting an additional tick when not all permissions are received
state backOff
--> backOff1;
// State, which releases the requests for needed tracks
state backOff1 {
entry / *_ST_4_req[trainNum] = false;
entry / *_LN_0_req[trainNum] = false;
}
// Transition to repeat requesting permissions procedure
--> waitForPerm;
final state gotPerm;
}
// Transition to the departure state
>-> Dep_*_ST;
// State, which handles the departure of a train
state Dep_*_ST {
// Set of entry-Actions with hostcode calls to set tracks, points and signals according to depTrack
entry / 'railPoint(*,STRAIGHT)';
entry / 'railSignal(*_LN_0, FWD, RED)';
entry / 'railTrack(*_LN_0,FWD,trainNum,NORMAL)';
entry / 'railTrack(*_ST_4,FWD,trainNum,NORMAL)';
entry depTrack == 1 / 'railSignal(*_ST_1, FWD, GREEN)';
entry depTrack == 2 / 'railSignal(*_ST_2, FWD, GREEN)';
entry depTrack == 3 / 'railSignal(*_ST_3, FWD, GREEN)';
//...
// Transition to next track segment, if contact is triggered
} --> *_LN_0 with 'railContact(*_LN_0,0)';
// .....................................................................................
// Set of track segment controlling states such as follows
// .....................................................................................
// Transition to next track segment, if contact is triggered
state *_LN_0 {
// Hostcode calls for outputs
entry / 'println("[trainNum][ST-ST] Entering *_LN_0")';
entry debug / 'println("[trainNum][ST-ST] Requesting permission for *_LN_1")';
// Entry-Actions with hostcode calls to set previous signal according to depTrack to RED
entry depTrack == 1 / 'railSignal(*_ST_1, FWD, RED)';
entry depTrack == 2 / 'railSignal(*_ST_2, FWD, RED)';
entry depTrack == 3 / 'railSignal(*_ST_3, FWD, RED)';
// Requesting the next track segment
entry / *_LN_1_req[trainNum] = true;
// Region for handling train driving
region Travel:
initial state Entry
// Transition to continuing state, if permitted
--> Continue with 'railContact(*_LN_0,0)' & (*_LN_1_perm == trainNum)
// Transition to slowing down else
--> Slowdown with 'railContact(*_LN_0,0)';
// State for slowing down the train
state Slowdown {
entry debug / 'println("[trainNum][ST-ST] Slowing down on *_LN_0")';
// Entry-Action with hostcode calls for slowing down the train
entry / 'railTrack(*_LN_0,FWD,trainNum,CAUTION)';
}
// Transition to waiting state
--> Waiting with 'railContact(*_LN_0,1)'
// Transition to continuing state, if permitted
--> Continue with *_LN_1_perm == trainNum;
// State for train waiting on permission
state Waiting {
entry debug / 'println("[trainNum][ST-ST] Stopping on *_LN_0")';
// Entry-Action with hostcode call for stopping the train
entry / 'railTrackBrake(*_LN_0)';
}
--> Continue with *_LN_1_perm == trainNum;
// State to continuing driving on the track
final state Continue {
entry debug / 'println("[trainNum][ST-ST] Continuing on *_LN_0")';
// Entry-Actions with hostcode calls to set tracks and signals for driving
entry / 'railSignal(*_LN_0,FWD,GREEN)';
entry / 'railTrack(*_LN_0,FWD,trainNum,NORMAL)';
entry / 'railTrack(*_LN_1,FWD,trainNum,NORMAL)';
entry / 'railSignal(*_LN_1, FWD, RED)';
};
// Region for handling cleanup functionalities
region Cleanup:
initial state Entry
// Transition to cleanup state
--> cleanup with 'railContact(*_LN_0,0)';
// State for cleaning up the previous track segments
final state cleanup {
entry debug / 'println("[trainNum][ST-ST] Entered *_LN_0 completely")';
// Entry-Action with hostcode call to switching off the previous track
entry / 'railTrackOff(*_ST_4)';
// Entry-Action to release the previous track
entry / *_ST_4_req[trainNum] = false;
};
// Transition to transitional state
}>-> *_LN_0_*_LN_1;
state *_LN_0_*_LN_1
// Transition to next track segment, if contact is triggered
--> *_LN_1 with 'railContact(*_LN_1,0)';
// ..................................................................................
// State for entering a station
state *_LN_5 {
// Variable for checking all needed permissions
int perm_all_next_segments = false;
entry / 'println("[trainNum][ST-ST] Entering *_LN_5")';
entry / 'railSignal(*_LN_4, FWD, RED)';
// Region for handling train driving such as above,
// only with perm_all_next_segments for permitting more than one track
region Travel:
initial state Entry
--> Continue with 'railContact(*_LN_5,0)' & perm_all_next_segments
--> Slowdown with 'railContact(*_LN_5,0)';
state Slowdown {
entry debug / 'println("[trainNum][ST-ST] Slowing down on *_LN_5")';
entry / 'railTrack(*_LN_5,FWD,trainNum,CAUTION)';
}
--> Waiting with 'railContact(*_LN_5,1)'
--> Continue with perm_all_next_segments;
state Waiting {
entry debug / 'println("[trainNum][ST-ST] Stopping on *_LN_5")';
entry / 'railTrackBrake(*_LN_5)';
}
--> Continue with perm_all_next_segments;
final state Continue {
entry debug / 'println("[trainNum][ST-ST] Continuing on *_LN_5")';
entry i_arrOnTrack == 1 / 'railTrack(*_ST_1,FWD,trainNum,NORMAL)';
entry i_arrOnTrack == 2 / 'railTrack(*_ST_2,FWD,trainNum,NORMAL)';
entry i_arrOnTrack == 3 / 'railTrack(*_ST_3,FWD,trainNum,NORMAL)';
//...
entry / arrTrack = i_arrOnTrack;
};
// Region for handling cleanup-functionalities such as above
region Cleanup:
initial state Entry
--> cleanup with 'railContact(*_LN_5,0)';
final state cleanup {
entry debug / 'println("[trainNum][ST-ST] Entered *_LN_5 completely")';
entry / 'railTrackOff(*_LN_4)';
entry / *_LN_4_req[trainNum] = false;
};
// Region for handling permissions of all needed tracks
region Permissions:
// State for requesting all needed tracks according to destination track and cleanup-Flag
initial state checking {
entry / *_ST_0_req[trainNum] = true;
entry destTrack == 1 | !cleanup / *_ST_1_req[trainNum] = true;
entry destTrack == 2 | !cleanup / *_ST_2_req[trainNum] = true;
entry destTrack == 3 | !cleanup / *_ST_3_req[trainNum] = true;
}
// Transitions for permitted tracks match wished tracks
--> success with destTrack == 1 & *_ST_0_perm == trainNum & *_ST_1_perm == trainNum / i_arrOnTrack = 1
--> success with destTrack == 2 & *_ST_0_perm == trainNum & *_ST_2_perm == trainNum / i_arrOnTrack = 2
--> success with destTrack == 3 & *_ST_0_perm == trainNum & *_ST_3_perm == trainNum / i_arrOnTrack = 3
// Transitions for permitted tracks don't match wished tracks
--> success with *_ST_0_perm == trainNum & *_ST_1_perm == trainNum / i_arrOnTrack = 1
--> success with *_ST_0_perm == trainNum & *_ST_2_perm == trainNum / i_arrOnTrack = 2
--> success with *_ST_0_perm == trainNum & *_ST_3_perm == trainNum / i_arrOnTrack = 3
// Transition for not all tracks permitted
--> resolving with *_ST_0_perm == trainNum | *_ST_3_perm == trainNum | *_ST_2_perm == trainNum | *_ST_1_perm == trainNum;
// State for waiting an additional tick
state resolving
--> resolving1;
// State for releasing track requests
state resolving1 {
entry / *_ST_0_req[trainNum] = false;
entry / *_ST_1_req[trainNum] = false;
entry / *_ST_2_req[trainNum] = false;
entry / *_ST_3_req[trainNum] = false;
}
// Transition for trying the requesting again
--> checking;
// State for waiting an additional tick
state success
--> success1;
// State for releasing not used track requests
final state success1 {
entry !(i_arrOnTrack == 1) / *_ST_1_req[trainNum] = false;
entry !(i_arrOnTrack == 2) / *_ST_2_req[trainNum] = false;
entry !(i_arrOnTrack == 3) / *_ST_3_req[trainNum] = false;
// Settting perm_all_next_segments to true
entry / perm_all_next_segments = true;
};
// Transition to station entry states
}>-> *_LN_5_*_ST;
// State waiting for station entry
state *_LN_5_*_ST
--> Arr_*_ST with i_arrOnTrack == 1 & 'railContact(*_ST_1,0)'
--> Arr_*_ST with i_arrOnTrack == 2 & 'railContact(*_ST_2,0)'
--> Arr_*_ST with i_arrOnTrack == 3 & 'railContact(*_ST_3,0)';
// State for setting tracks, points and signals according to i_arrOnTrack
// and releasing previous track request
state Arr_*_ST {
entry / 'railSignal(*_LN_5, FWD, RED)';
entry / 'railTrackOff(*_LN_5)';
entry / 'railTrack(*_ST_0,FWD,trainNum,SLOW)';
entry i_arrOnTrack == 1 / 'railTrack(*_ST_1,FWD,trainNum,SLOW)';
entry i_arrOnTrack == 2 / 'railTrack(*_ST_2,FWD,trainNum,SLOW)';
entry i_arrOnTrack == 3 / 'railTrack(*_ST_3,FWD,trainNum,SLOW)';
entry / *_LN_5_req[trainNum] = false;
initial state SlowEntry
--> Slow with i_arrOnTrack == 1 & 'railContact(*_ST_1,0)'
--> Slow with i_arrOnTrack == 2 & 'railContact(*_ST_2,0)'
--> Slow with i_arrOnTrack == 3 & 'railContact(*_ST_3,0)';
// State for switching off previous track and releasing the request
state Slow {
entry / 'railTrackOff(*_ST_0)';
entry / *_ST_0_req[trainNum] = false;
}
// Transitions to halt state, when train is at second contact of a track segment
--> Halt with i_arrOnTrack == 1 & 'railContact(*_ST_1,1)'
--> Halt with i_arrOnTrack == 2 & 'railContact(*_ST_2,1)'
--> Halt with i_arrOnTrack == 3 & 'railContact(*_ST_3,1)';
final state Halt {
// Entry-Actions for braking the train on correct track
entry i_arrOnTrack == 1 / 'railTrackBrake(*_ST_1)';
entry i_arrOnTrack == 2 / 'railTrackBrake(*_ST_2)';
entry i_arrOnTrack == 3 / 'railTrackBrake(*_ST_3)';
// Entry-Actions for waiting for timer on correct track
entry i_arrOnTrack == 1 / 'railArrival(trainNum, *_ST_1)';
entry i_arrOnTrack == 2 / 'railArrival(trainNum, *_ST_2)';
entry i_arrOnTrack == 3 / 'railArrival(trainNum, *_ST_3)';
};
}
>-> done;
state done
// Transition to final state, if timer is ready
--> reallyDone with 'railDeparture(trainNum)';
final state reallyDone;
} |