-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
274 lines (243 loc) · 8.54 KB
/
main.cpp
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*
* This code will follow a black path between two black lines, using a
* very simple algorithm. It demonstrates auto-calibration and use of
* the 3pi IR sensors, motor control, bar graphs using custom
* characters, and music playback, making it a good starting point for
* developing your own more competitive line follower.
*/
// The 3pi include file must be at the beginning of any program that
// uses the Pololu AVR library and 3pi.
#include <pololu/Pololu3pi.h>
// This include file allows data to be stored in program space. The
// ATmega168 has 16k of program space compared to 1k of RAM, so large
// pieces of static data should be stored in program space.
#include <avr/pgmspace.h>
// Diferent modules
#include "modes/power/power.h"
#include "modes/dance/dance.h"
#include "modes/race/race.h"
// Introductory messages. The "PROGMEM" identifier causes the data to
// go into program space.
const char msg_panteras[]
PROGMEM = "Panteras";
const char msg_manila[]
PROGMEM = "Manila";
const char msg_select[]
PROGMEM = "select";
const char msg_mode[]
PROGMEM = "mode";
const char msg_race[]
PROGMEM = "race";
const char msg_dance[]
PROGMEM = "dance";
const char msg_power[]
PROGMEM = "power";
const char msg_paused[]
PROGMEM = "Paused";
const char msg_go[]
PROGMEM = "Go!";
const char msg_dancing[]
PROGMEM = "Dancing";
// BUTTONS FOR MODES
#define MODE_RACE_BUTTON BUTTON_A
#define MODE_DANCE_BUTTON BUTTON_B
#define MODE_POWER_BUTTON BUTTON_C
// Data for generating the characters used in load_custom_characters
// and display_readings. By reading levels[] starting at various
// offsets, we can generate all of the 7 extra characters needed for a
// bargraph. This is also stored in program space.
const char levels[]
PROGMEM = {
0b00000,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000,
0b11111,
0b11111,
0b11111,
0b11111,
0b11111,
0b11111,
0b11111
};
// This function loads custom characters into the LCD. Up to 8
// characters can be loaded; we use them for 7 levels of a bar graph.
void load_custom_characters() {
OrangutanLCD::loadCustomCharacter(levels + 0, 0); // no offset, e.g. one bar
OrangutanLCD::loadCustomCharacter(levels + 1, 1); // two bars
OrangutanLCD::loadCustomCharacter(levels + 2, 2); // etc...
OrangutanLCD::loadCustomCharacter(levels + 3, 3);
OrangutanLCD::loadCustomCharacter(levels + 4, 4);
OrangutanLCD::loadCustomCharacter(levels + 5, 5);
OrangutanLCD::loadCustomCharacter(levels + 6, 6);
OrangutanLCD::clear(); // the LCD must be cleared for the characters to take effect
}
// Initializes the 3pi, displays a welcome message, calibrates, and
// plays the initial music.
void initialize(Pololu3pi& device) {
// This must be called at the beginning of 3pi code, to set up the
// sensors. We use a value of 2000 for the timeout, which
// corresponds to 2000*0.4 us = 0.8 ms on our 20 MHz processor.
Pololu3pi::init(2000);
load_custom_characters(); // load the custom characters
// This function is required because it map in memory sensors
device.calibrateLineSensors(IR_EMITTERS_ON);
}
/**
* Muestra un mensaje de dos lineas en la pantalla
*/
void display_message(const char line1[], const char line2[]) {
OrangutanLCD::clear();
OrangutanLCD::gotoXY(0, 0);
OrangutanLCD::printFromProgramSpace(line1);
OrangutanLCD::gotoXY(0, 1);
OrangutanLCD::printFromProgramSpace(line2);
}
/**
* Muestra un mensaje de dos lineas en la pantalla
*/
void display_message_centred(const char line1[]) {
OrangutanLCD::clear();
OrangutanLCD::printFromProgramSpace(line1);
}
// This is the main function, where the code starts. All C programs
// must have a main() function defined somewhere.
int main() {
Pololu3pi device;
// set up the 3pi
initialize(device);
// Diferent modes
Dance DanceMode;
Power PowerMode;
Race RaceMode = Race(&device);
DanceMode.OnSetup();
RaceMode.OnSetup();
PowerMode.OnSetup();
// muestra mensaje "Panteras Manila"
display_message(msg_panteras, msg_manila);
OrangutanTime::delayMilliseconds(1000);
// muestra el mensaje select mode
display_message(msg_select, msg_mode);
unsigned char button_pressed = OrangutanPushbuttons::waitForButton(BUTTON_A | BUTTON_B | BUTTON_C);
// Modulo de juego seleccionado
unsigned char selected_game_mode;
while (1) {
// Seteamos el modo de juego
selected_game_mode = button_pressed;
// Segun el modo de juego mostramos cosas diferentes en la pantalla
switch (selected_game_mode) {
case MODE_RACE_BUTTON:
display_message(msg_race, msg_mode);
break;
case MODE_DANCE_BUTTON:
display_message(msg_dance, msg_mode);
break;
case MODE_POWER_BUTTON:
display_message(msg_power, msg_mode);
break;
}
// Esperamos hasta la confirmaci�n de modo de juego
button_pressed = OrangutanPushbuttons::waitForButton(BUTTON_A | BUTTON_B | BUTTON_C);
// Si el boton no es el de confirmaci�n, se cambia de modo de juego
if (button_pressed != selected_game_mode) {
continue; // Cambiamos de modo de juego
}
// On Start Activity
switch (selected_game_mode) {
case MODE_RACE_BUTTON:
RaceMode.OnStart();
break;
case MODE_DANCE_BUTTON:
DanceMode.OnStart();
break;
case MODE_POWER_BUTTON:
PowerMode.OnStart();
break;
}
GAME_MODE_LOOP_START:
// On Resume Activity
switch (selected_game_mode) {
case MODE_RACE_BUTTON:
RaceMode.OnResume();
display_message_centred(msg_go);
break;
case MODE_DANCE_BUTTON:
DanceMode.OnResume();
display_message_centred(msg_dancing);
break;
case MODE_POWER_BUTTON:
PowerMode.OnResume();
// El power mode ya lleva su propia imagen para el lcd
break;
}
// On Main loop
// WARNING: If is too slow change switch with while
while (!(button_pressed = OrangutanPushbuttons::isPressed(BUTTON_A | BUTTON_B | BUTTON_C))) {
switch (selected_game_mode) {
case MODE_RACE_BUTTON:
RaceMode.OnLoop();
break;
case MODE_DANCE_BUTTON:
DanceMode.OnLoop();
break;
case MODE_POWER_BUTTON:
PowerMode.OnLoop();
break;
}
}
OrangutanPushbuttons::waitForRelease(button_pressed);
// On Pause Activity
if (button_pressed == selected_game_mode) {
display_message_centred(msg_paused);
switch (selected_game_mode) {
case MODE_RACE_BUTTON:
RaceMode.OnPause();
break;
case MODE_DANCE_BUTTON:
DanceMode.OnPause();
break;
case MODE_POWER_BUTTON:
PowerMode.OnPause();
break;
}
} else {
// On Stop Activity
switch (selected_game_mode) {
case MODE_RACE_BUTTON:
RaceMode.OnPause();
RaceMode.OnStop();
break;
case MODE_DANCE_BUTTON:
DanceMode.OnPause();
DanceMode.OnStop();
break;
case MODE_POWER_BUTTON:
PowerMode.OnPause();
PowerMode.OnStop();
break;
}
continue;
}
button_pressed = OrangutanPushbuttons::waitForButton(BUTTON_A | BUTTON_B | BUTTON_C);
if (button_pressed != selected_game_mode) {
// On Stop Activity
switch (selected_game_mode) {
case MODE_RACE_BUTTON:
RaceMode.OnStop();
break;
case MODE_DANCE_BUTTON:
DanceMode.OnStop();
break;
case MODE_POWER_BUTTON:
PowerMode.OnStop();
break;
}
continue; // Cambiamos de modo de juego
} else {
goto GAME_MODE_LOOP_START;
}
}
}