-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDropTargets.h
182 lines (155 loc) · 5.43 KB
/
DropTargets.h
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// This file must be included after RPU_config.h
#define DROP_TARGET_BANK_CLEARED 1
#define DROP_TARGET_BANK_CLEARED_IN_ORDER 2
#define DROP_TARGET_TYPE_BLY_1 0 // no solenoids to drop individual targets, one switch per target
#define DROP_TARGET_TYPE_STRN_1 1 // no solenoids to drop individual targets, one switch per target
#define DROP_TARGET_TYPE_STRN_2 2 // clearing solenoids for individual targets, one switch per target (aka memory drops)
#define DROP_TARGET_TYPE_WLLMS_1 3 // no solenoids to drop individual targets, one switch per target (momentary), switch for all targets down
#define DROP_TARGET_TYPE_WLLMS_2 4 // no solenoids to drop/reset individual, one switch per target
class DropTargetBank
{
public:
DropTargetBank(byte s_numSwitches, byte s_numSolenoids, byte s_bankType, byte s_solenoidOnTime);
~DropTargetBank();
void DefineSwitch(byte switchOrder, byte switchNum);
void DefineResetSolenoid(byte solIndex, byte solChannelNumber);
void AddAllTargetsSwitch(byte s_allTargetsSwitch);
byte HandleDropTargetHit(byte switchNum);
byte CheckIfBankCleared();
void Update(unsigned long currentTime);
void ResetDropTargets(unsigned long timeToReset, boolean ignoreQuickDrops=false);
byte GetStatus(boolean readSwitches = true);
private:
byte numSwitches;
byte bankType;
byte numSolenoids;
byte *switchArray;
byte *solArray;
byte allTargetsSwitch;
byte solenoidOnTime;
byte bankStatus;
byte bankBitmask;
unsigned long targetResetTime;
unsigned long ignoreDropsUntilTime;
boolean bankCleared;
boolean targetsHitInOrder;
byte numTargetsInOrder;
};
DropTargetBank::DropTargetBank(byte s_numSwitches, byte s_numSolenoids, byte s_bankType, byte s_solenoidOnTime) {
numSwitches = s_numSwitches;
numSolenoids = s_numSolenoids;
solenoidOnTime = s_solenoidOnTime;
bankType = s_bankType;
if (numSwitches) switchArray = new byte[numSwitches];
if (numSolenoids) solArray = new byte[numSolenoids];
allTargetsSwitch = 0xFF;
bankStatus = 0;
bankBitmask = 0;
bankCleared = false;
targetsHitInOrder = true;
numTargetsInOrder = 0;
for (byte count=0; count<numSwitches; count++) {
switchArray[count] = 0xFF;
bankBitmask *= 2;
bankBitmask |= 1;
}
for (byte count=0; count<numSolenoids; count++) solArray[count] = 0xFF;
targetResetTime = 0;
ignoreDropsUntilTime = 0;
}
DropTargetBank::~DropTargetBank() {
delete switchArray;
delete solArray;
}
void DropTargetBank::DefineSwitch(byte switchOrder, byte switchNum) {
if (switchOrder>=numSwitches) return;
switchArray[switchOrder] = switchNum;
}
void DropTargetBank::AddAllTargetsSwitch(byte s_allTargetsSwitch) {
if (bankType!=DROP_TARGET_TYPE_WLLMS_1) return;
allTargetsSwitch = s_allTargetsSwitch;
}
void DropTargetBank::DefineResetSolenoid(byte solIndex, byte solChannelNumber) {
if (solIndex>=numSolenoids) return;
solArray[solIndex] = solChannelNumber;
}
byte DropTargetBank::HandleDropTargetHit(byte switchNum) {
byte oldStatus = bankStatus;
byte targetBits = 0x00;
byte singleBit = 0x01;
if (ignoreDropsUntilTime) {
return 0;
}
for (byte count=0; count<numSwitches; count++) {
if (switchNum==switchArray[count]) {
// If this is a new hit, see if it's in order
if ((bankStatus & singleBit)==0x00) {
if (targetsHitInOrder && count==numTargetsInOrder) {
numTargetsInOrder += 1;
} else {
targetsHitInOrder = false;
numTargetsInOrder = 0;
}
}
targetBits |= singleBit;
break;
}
singleBit *= 2;
}
if (allTargetsSwitch!=0xFF) {
if (RPU_ReadSingleSwitchState(allTargetsSwitch) || switchNum==allTargetsSwitch) targetBits = bankBitmask & (~bankStatus);
}
bankStatus |= targetBits;
if (bankStatus==bankBitmask) bankCleared = true;
return bankStatus & ~oldStatus;
}
byte DropTargetBank::CheckIfBankCleared() {
if (bankCleared) {
if (targetsHitInOrder) return DROP_TARGET_BANK_CLEARED_IN_ORDER;
else return DROP_TARGET_BANK_CLEARED;
}
return 0;
}
byte DropTargetBank::GetStatus(boolean readSwitches) {
if (readSwitches) {
byte bitMask = 0x01;
byte returnStatus = 0x00;
for (byte count=0; count<numSwitches; count++) {
if (RPU_ReadSingleSwitchState(switchArray[count])) returnStatus |= bitMask;
bitMask *= 2;
}
return returnStatus;
} else {
return bankStatus;
}
}
void DropTargetBank::ResetDropTargets(unsigned long timeToReset, boolean ignoreQuickDrops) {
bankCleared = false;
targetsHitInOrder = true;
numTargetsInOrder = 0;
if (targetResetTime) {
// We've already requested this bank to reset, so don't queue it again
return;
}
if (numSolenoids) {
for (byte count=0; count<numSolenoids; count++) {
if (solArray[count]!=0xFF) RPU_PushToTimedSolenoidStack(solArray[count], solenoidOnTime, timeToReset);
}
targetResetTime = timeToReset + 100; // This could be based on solenoidOnTime, but that's not currently set in ms
if (ignoreQuickDrops) {
ignoreDropsUntilTime = targetResetTime + 100;
} else {
ignoreDropsUntilTime = 0;
}
}
return;
}
void DropTargetBank::Update(unsigned long currentTime) {
if (targetResetTime && currentTime>targetResetTime) {
bankStatus = GetStatus();
targetResetTime = 0;
}
if (ignoreDropsUntilTime && currentTime>ignoreDropsUntilTime) {
ignoreDropsUntilTime = 0;
}
}