-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcart.adb
132 lines (108 loc) · 4.1 KB
/
cart.adb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
WITH Text_Io; USE Text_Io;
WITH NT_Console; USE NT_Console;
PACKAGE BODY Cart IS
task semaphore is
entry P; -- Dijkstra’s terminology
entry V; -- from the Dutch
end semaphore;
task body semaphore is
begin
loop
accept P; -- won’t accept another P until a caller asks for V
accept V;
end loop;
end semaphore;
function initCart return cart IS
C : cart;
BEGIN
for I in 0..8 loop
C.floorList(I) := initFloor(I);
C.buttons(I) := initButton;
end loop;
C.operationDelay := clock;
C.level := C.floorList(0);
C.max_level := C.level.level;
C.min_level := C.level.level;
C.dir := Up;
RETURN C;
END;
procedure driveCart(C : IN OUT cart) IS
BEGIN
C.operationDelay := C.operationDelay + 2.0;
delay until C.operationDelay;
semaphore.P;
if C.dir = Up AND
(isPressed(C.floorList(C.level.level).buttons(Up)) OR
isPressed(C.buttons(C.level.level)))
then
setFalse(C.floorList(C.level.level).buttons(Up));
setFalse(C.buttons(C.level.level));
calculateMinMax(C); -- Calculate new min max
C.operationDelay := C.operationDelay + 5.0; -- Opens door, could be improved by printing
delay until C.operationDelay;
elsif C.dir = Down AND
(isPressed(C.floorList(C.level.level).buttons(Down)) OR
isPressed(C.buttons(C.level.level)))
then
setFalse(C.floorList(C.level.level).buttons(Down));
setFalse(C.buttons(C.level.level));
calculateMinMax(C); -- Calculate new min max
C.operationDelay := C.operationDelay + 5.0; -- Opens door, could be improved by printing
delay until C.operationDelay;
end if;
if C.level.level < C.max_level AND C.dir = Up then
C.level.level := C.level.level + 1;
elsif C.level.level > C.min_level AND C.dir = Down then
C.level.level := C.level.level - 1;
elsif (C.level.level = C.min_level OR C.level.level < C.min_level) AND C.dir = Down then
C.dir := Up;
elsif (C.level.level = C.max_level OR C.level.level > C.max_level) AND C.dir = Up then
C.dir := Down;
end if;
semaphore.V;
END;
procedure pressCartButton(C : IN OUT cart; L : IN integer) IS
BEGIN
semaphore.P;
press(C.buttons(L));
calculateMinMax(C);
semaphore.V;
END;
procedure pressFloorButton(C : IN OUT cart; L : IN integer; D : IN direction) IS
BEGIN
semaphore.P;
press(C.floorList(L).buttons(D));
calculateMinMax(C);
semaphore.V;
END;
procedure calculateMinMax(C : IN OUT cart) IS
-- Calculate new min and max after change in button presses --
BEGIN
C.min_level := 8;
C.max_level := 0;
for L in 0..8 loop
if L < C.min_level AND
(isPressed(C.floorList(L).buttons(Up)) OR
isPressed(C.floorList(L).buttons(Down)) OR
isPressed(C.buttons(L)))
then
C.min_level := L;
end if;
if L > C.max_level AND
(isPressed(C.floorList(L).buttons(Up)) OR
isPressed(C.floorList(L).buttons(Down)) OR
isPressed(C.buttons(L)))
then
C.max_level := L;
end if;
end loop;
if C.min_level = 8 AND C.max_level = 0 then
C.min_level := C.level.level;
C.max_level := C.level.level;
end if;
END;
procedure destructCart is
BEGIN
abort semaphore;
END;
End Cart;