software
complete code listing: geld.c
coin counting
Our coin sorter has a very unique way of deterring total coin value. This calculation is
performed by counting the total number of coins to enter each level and subtracting a level from the previous
one to generate the count for the previous level. The levels are numbered 0 to 3 where 0 is the highest level
and 3 is the lowest level. The following code produces our coin counts:
quarters = sensorCount[0] - sensorCount[1];
nickels = sensorCount[1] - sensorCount[2];
pennies = sensorCount[2] - sensorCount[3];
dimes = sensorCount[3];
sortTotal = (float)quarters*.25 + (float)dimes*.1 +
(float)nickels*.05 + (float)pennies*.01;
state system
The coin sorter code can be thought of as a complex state machine. Pressing keys on the keypad move
the software into different states. By keeping track of the state globally, any running process can
check to see how it should behave in the current state or move the machine into a different state.
For example, the numeric keys are only functional in the INPUT state.
#define READY 0
#define SORTING 1
#define GAMING 2
#define INPUT 3
#define INPUTDONE 4
#define CREDITS 5
keypad
Our matrix-encoded keypad is controlled by the Handyboard by individually activating
each row and checking which column is active. This process can be done in hardware
by using a keypad encoder chip, but is pretty simple to handle in software. Specifically,
the code activates a row, produces a 4-bit binary representation of the active columns, verifies
that only one key is pressed, and calls the key handler function with the row and column
of the pressed key. The keypad controller function is listed below:
void keypadLoop()
{
int row,prevRow,col,keypadOut;
for (row = 0; row < 4; row++)
digital_out(row,TRUE);
prevRow = 3;
row = 0;
while (1) {
digital_out(prevRow,TRUE);
digital_out(row,FALSE);
keypadOut = digital(14);
keypadOut = (keypadOut << 1) + digital(13);
keypadOut = (keypadOut << 1) + digital(12);
keypadOut = (keypadOut << 1) + digital(11);
if (keypadOut == 1)
getKey(row,0);
else if (keypadOut == 2)
getKey(row,1);
else if (keypadOut == 4)
getKey(row,2);
else if (keypadOut == 8)
getKey(row,3);
prevRow = row;
row = (row+1)%4;
}
}
numeric input
The game that is included with the sorter requires input numeric input from the user. This is
accomplished by first putting the system into state and keeping track of the keypad values that
have been entered. The value is calculated by multiplying the current value by 10 and adding the
new value. If a decimal is entered then the code also keeps track of an exponential multiplier
and uses it in the end to determine the floating point value. The two functions that achieve
this actually run in two separate processes, and have to monitor the machine state to determine
what to do.
float getInput(int currentState)
{
float val;
inputVal = 0;
inputExp = 0;
decimalMode = FALSE;
systemState = INPUT;
while (systemState != INPUTDONE);
if (inputExp < 0)
val = (float)inputVal * exp10((float)inputExp);
else
val = (float)inputVal;
printf("\n");
systemState = currentState;
return val;
}
void storeInput(int val)
{
if (val != -1) {
inputVal = 10*inputVal + val;
if (decimalMode)
inputExp--;
printf("%d",val);
}
else if (!decimalMode) {
/* val == -1 -> decimal point*/
decimalMode = TRUE;
printf(".");
}
}
sensors
The sensor checking code is crucial so that we can guarantee an accurate coin count. The key
feature of this code snippet is that as soon as a sensor detects something blocking it, the sensor
moves into a BLOCKED state and increments its counter. Until the sensor is unblocked and moved
into the UNBLOCKED state, the counter cannot become BLOCKED again and increment.
void sensorScan()
{
int i;
for (i=0; i < 4; i++) {
sensorState[i] = UNBLOCKED;
sensorCount[i] = 0;
}
while(systemState == SORTING) {
for (i=0; i < 4; i++) {
checkSensor(i);
}
}
}
void checkSensor(int s)
{
if (digital(s+7)) {
if (sensorState[s] == UNBLOCKED) {
sensorState[s] = BLOCKED;
sensorCount[s]++;
displayTotal();
}
}
else
sensorState[s] = UNBLOCKED;
}
|