-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshapemotion.c
207 lines (171 loc) · 5.8 KB
/
shapemotion.c
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
/** \file shapemotion.c
* \brief This is a simple shape motion demo.
* This demo creates two layers containing shapes.
* One layer contains a rectangle and the other a circle.
* While the CPU is running the green LED is on, and
* when the screen does not need to be redrawn the CPU
* is turned off along with the green LED.
*/
#include <msp430.h>
#include <libTimer.h>
#include <lcdutils.h>
#include <lcddraw.h>
#include <p2switches.h>
#include <shape.h>
#include <abCircle.h>
#define GREEN_LED BIT6
AbRect rect10 = {abRectGetBounds, abRectCheck, {10,10}}; /**< 10x10 rectangle */
AbRArrow rightArrow = {abRArrowGetBounds, abRArrowCheck, 30};
AbRectOutline fieldOutline = { /* playing field */
abRectOutlineGetBounds, abRectOutlineCheck,
{screenWidth/2 - 10, screenHeight/2 - 10}
};
Layer layer4 = {
(AbShape *)&rightArrow,
{(screenWidth/2)+10, (screenHeight/2)+5}, /**< bit below & right of center */
{0,0}, {0,0}, /* last & next pos */
COLOR_PINK,
0
};
Layer layer3 = { /**< Layer with an orange circle */
(AbShape *)&circle8,
{(screenWidth/2)+10, (screenHeight/2)+5}, /**< bit below & right of center */
{0,0}, {0,0}, /* last & next pos */
COLOR_VIOLET,
&layer4,
};
Layer fieldLayer = { /* playing field as a layer */
(AbShape *) &fieldOutline,
{screenWidth/2, screenHeight/2},/**< center */
{0,0}, {0,0}, /* last & next pos */
COLOR_BLACK,
&layer3
};
Layer layer1 = { /**< Layer with a red square */
(AbShape *)&rect10,
{screenWidth/2, screenHeight/2}, /**< center */
{0,0}, {0,0}, /* last & next pos */
COLOR_RED,
&fieldLayer,
};
Layer layer0 = { /**< Layer with an orange circle */
(AbShape *)&circle14,
{(screenWidth/2)+10, (screenHeight/2)+5}, /**< bit below & right of center */
{0,0}, {0,0}, /* last & next pos */
COLOR_ORANGE,
&layer1,
};
/** Moving Layer
* Linked list of layer references
* Velocity represents one iteration of change (direction & magnitude)
*/
typedef struct MovLayer_s {
Layer *layer;
Vec2 velocity;
struct MovLayer_s *next;
} MovLayer;
/* initial value of {0,0} will be overwritten */
MovLayer ml3 = { &layer3, {1,1}, 0 }; /**< not all layers move */
MovLayer ml1 = { &layer1, {1,2}, &ml3 };
MovLayer ml0 = { &layer0, {2,1}, &ml1 };
void movLayerDraw(MovLayer *movLayers, Layer *layers)
{
int row, col;
MovLayer *movLayer;
and_sr(~8); /**< disable interrupts (GIE off) */
for (movLayer = movLayers; movLayer; movLayer = movLayer->next) { /* for each moving layer */
Layer *l = movLayer->layer;
l->posLast = l->pos;
l->pos = l->posNext;
}
or_sr(8); /**< disable interrupts (GIE on) */
for (movLayer = movLayers; movLayer; movLayer = movLayer->next) { /* for each moving layer */
Region bounds;
layerGetBounds(movLayer->layer, &bounds);
lcd_setArea(bounds.topLeft.axes[0], bounds.topLeft.axes[1],
bounds.botRight.axes[0], bounds.botRight.axes[1]);
for (row = bounds.topLeft.axes[1]; row <= bounds.botRight.axes[1]; row++) {
for (col = bounds.topLeft.axes[0]; col <= bounds.botRight.axes[0]; col++) {
Vec2 pixelPos = {col, row};
u_int color = bgColor;
Layer *probeLayer;
for (probeLayer = layers; probeLayer;
probeLayer = probeLayer->next) { /* probe all layers, in order */
if (abShapeCheck(probeLayer->abShape, &probeLayer->pos, &pixelPos)) {
color = probeLayer->color;
break;
} /* if probe check */
} // for checking all layers at col, row
lcd_writeColor(color);
} // for col
} // for row
} // for moving layer being updated
}
//Region fence = {{10,30}, {SHORT_EDGE_PIXELS-10, LONG_EDGE_PIXELS-10}}; /**< Create a fence region */
/** Advances a moving shape within a fence
*
* \param ml The moving shape to be advanced
* \param fence The region which will serve as a boundary for ml
*/
void mlAdvance(MovLayer *ml, Region *fence)
{
Vec2 newPos;
u_char axis;
Region shapeBoundary;
for (; ml; ml = ml->next) {
vec2Add(&newPos, &ml->layer->posNext, &ml->velocity);
abShapeGetBounds(ml->layer->abShape, &newPos, &shapeBoundary);
for (axis = 0; axis < 2; axis ++) {
if ((shapeBoundary.topLeft.axes[axis] < fence->topLeft.axes[axis]) ||
(shapeBoundary.botRight.axes[axis] > fence->botRight.axes[axis]) ) {
int velocity = ml->velocity.axes[axis] = -ml->velocity.axes[axis];
newPos.axes[axis] += (2*velocity);
} /**< if outside of fence */
} /**< for axis */
ml->layer->posNext = newPos;
} /**< for ml */
}
u_int bgColor = COLOR_BLUE; /**< The background color */
int redrawScreen = 1; /**< Boolean for whether screen needs to be redrawn */
Region fieldFence; /**< fence around playing field */
/** Initializes everything, enables interrupts and green LED,
* and handles the rendering for the screen
*/
void main()
{
P1DIR |= GREEN_LED; /**< Green led on when CPU on */
P1OUT |= GREEN_LED;
configureClocks();
lcd_init();
shapeInit();
p2sw_init(1);
shapeInit();
layerInit(&layer0);
layerDraw(&layer0);
layerGetBounds(&fieldLayer, &fieldFence);
enableWDTInterrupts(); /**< enable periodic interrupt */
or_sr(0x8); /**< GIE (enable interrupts) */
for(;;) {
while (!redrawScreen) { /**< Pause CPU if screen doesn't need updating */
P1OUT &= ~GREEN_LED; /**< Green led off witHo CPU */
or_sr(0x10); /**< CPU OFF */
}
P1OUT |= GREEN_LED; /**< Green led on when CPU on */
redrawScreen = 0;
movLayerDraw(&ml0, &layer0);
}
}
/** Watchdog timer interrupt handler. 15 interrupts/sec */
void wdt_c_handler()
{
static short count = 0;
P1OUT |= GREEN_LED; /**< Green LED on when cpu on */
count ++;
if (count == 15) {
mlAdvance(&ml0, &fieldFence);
if (p2sw_read())
redrawScreen = 1;
count = 0;
}
P1OUT &= ~GREEN_LED; /**< Green LED off when cpu off */
}