-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.c
More file actions
225 lines (198 loc) · 6.09 KB
/
main.c
File metadata and controls
225 lines (198 loc) · 6.09 KB
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*******************************************
* Author: C2C Caleb Ziegler/CS-39
* Created: 5 NOV 2013
* Description: This program runs a simple
* game on the MSP430 that interfaces with
* the Geekbox. The coding style is a little
* unorthodox in this file because some
* functions are declared and implemented in
* main.c instead of game.c. I discussed this
* with C2C Mossing and he explained to me
* that declaring functions in main.c prevents
* errors with interrupts and ensures that global
* variables work correctly.
*******************************************/
#include <msp430.h>
#include "lcd.h"
#include "button.h"
#include "game.h"
#define UP 1
#define LEFT 2
#define RIGHT 3
#define DOWN 4
#define TRUE 1
#define FALSE 0
unsigned char position = 0;
char direction = 0;
char buttonflag = 0;
char timerflag = 0;
char count = 0;
char gameover = FALSE;
/*****************************************
* Main.c embedded header
******************************************/
//Simply resets the timer by reseting the count
//variable and clearing TAR (TAR is register that
//holds current count of Timer_A and TACLR clears it).
void clearTimer();
//Moves player up if button 1 is pressed, moves player
//left if button 2 is pressed, moves player right if button
//3 is pressed, and moves player down if button 4 is pressed.
void movePlayerforButtonPush(char buttonToTest);
//If buttonToTest is same as the button that triggered
//the interrupt and the interrupt was triggered on the falling
//edge, move player (asterisk) to new location.
void testAndRespondToButtonPush(char buttonToTest);
//If game has reached end state and a button press occurs, clear LCD,
//set player to the start, clear Timer_A, and restart game.
void Start_Over(char buttonToTest);
/**********************************
* Main.c Executable code
**********************************/
void main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
//Initializes the game
initSPI();
LCDinit();
LCDclear();
initButtons();
position = initPlayer();
clearPlayer(position);
updatePlayer(position);
initTimer();
__enable_interrupt();
while(1)
{
//Count every time Timer_A overflows
if (timerflag == 1)
{
timerflag = 0;
count++;
}
//After 2 seconds (0.5 seconds times four) without moving, game over
if(count >= 4)
{
TACTL &= ~TAIE; //Disable timer interrupt
__disable_interrupt(); //Disable all interrupts so button pushes won't interrupt writing to LCD
LCDclear();
gameover = TRUE;
MoveCursorLineOne();
writeString("Game ");
MoveCursorLineTwo();
writeString("Over ");
__enable_interrupt();
__delay_cycles(1000);
clearTimer();
TACTL |= TAIE; //Enable timer interrupt
}
//If player makes it to end spot, they win
if(position == 0xC7)
{
TACTL &= ~TAIE; //Disable timer interrupt
__disable_interrupt(); //Disable all interrupts so button pushes won't interrupt writing to LCD
LCDclear();
gameover = TRUE;
MoveCursorLineOne();
writeString("You ");
MoveCursorLineTwo();
writeString("Win ");
__enable_interrupt();
__delay_cycles(1000);
clearTimer();
TACTL |= TAIE; //Enable timer interrupt
}
}
}
/*********************************
* Main.c embedded implementation
*********************************/
void clearTimer()
{
count = 0;
TACTL |= TACLR; //clear TAR
}
void movePlayerforButtonPush(char buttonToTest)
{
switch(buttonToTest)
{
case BIT1:
position = movePlayer(position,UP);
break;
case BIT2:
position = movePlayer(position,LEFT);
break;
case BIT3:
position = movePlayer(position,RIGHT);
break;
case BIT4:
position = movePlayer(position,DOWN);
}
}
void testAndRespondToButtonPush(char buttonToTest)
{
if (buttonToTest & P2IFG) //If button being tested triggered interrupt, continue on
{
if (buttonToTest & P2IES) //If interrupt was triggered on falling edge (good button push), continue to move player
{
movePlayerforButtonPush(buttonToTest);
clearTimer();
} else //If interrupt was triggered on rising edge, button release occurred, so debounce
{
debounce();
}
P2IES ^= buttonToTest; //Toggle flag to select opposite edge of what occurred earlier (if falling edge, now select rising edge, and vice versa)
P2IFG &= ~buttonToTest; //Clear interrupt flag so this interrupt is not called again
}
}
void Start_Over(char buttonToTest)
{
if (buttonToTest & P2IFG) //Make sure one of the buttons triggered interrupt
{
if (buttonToTest & P2IES) //If triggered on falling edge, we have a button press, so start game over
{
gameover = FALSE;
LCDclear();
position = initPlayer();
clearPlayer(position);
updatePlayer(position);
clearTimer();
TACTL |= TAIE; //Enable Timer_A interrupt
} else //If interrupt was triggered on rising edge, no button press (release of button), so debounce
{
debounce();
}
P2IES ^= buttonToTest; //Make flag select opposite edge of what occurred earlier
P2IFG &= ~buttonToTest; //Clear interrupt flag to not call this interrupt again
}
}
/*********************************
* Interrupt Code
*********************************/
//Timer_A interrupt code
#pragma vector = TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR()
{
TACTL &= ~TAIFG;
timerflag = 1;
}
//Button interrupt code
#pragma vector = PORT2_VECTOR
__interrupt void Port_2_ISR(void)
{
if(gameover == FALSE)
{
//Test all buttons to see what one was pushed if not in end game condition
testAndRespondToButtonPush(BIT1);
testAndRespondToButtonPush(BIT2);
testAndRespondToButtonPush(BIT3);
testAndRespondToButtonPush(BIT4);
}
else
{
//Again, test all buttons to see if game should start over when in end game condition
Start_Over(BIT1);
Start_Over(BIT2);
Start_Over(BIT3);
Start_Over(BIT4);
}
}