Andriy Makukha / Mbed 2 deprecated football_project_wo_output

Dependencies:   mbed

Fork of football_project by MZJ

Committer:
AntonLS
Date:
Mon Jan 11 16:34:46 2016 +0000
Revision:
46:28c29ef61276
Parent:
45:1eb335c00cb2
Child:
47:c66d2995f957
Freeform improvements, etc.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elmbed 17:d8b901d791fd 1 #include <TA.h>
elmbed 17:d8b901d791fd 2 #include <types.h>
elmbed 17:d8b901d791fd 3
elmbed 17:d8b901d791fd 4 #define RED p3
elmbed 17:d8b901d791fd 5 #define GREEN p5
elmbed 17:d8b901d791fd 6 #define BLUE p6
elmbed 17:d8b901d791fd 7
elmbed 17:d8b901d791fd 8 #define ENABLE_1 p4
elmbed 17:d8b901d791fd 9 #define ENABLE_2 p7
elmbed 17:d8b901d791fd 10 #define ENABLE_3 p8
elmbed 17:d8b901d791fd 11
elmbed 17:d8b901d791fd 12 #define DEBUG_BAUD 57600 //57600
elmbed 26:40a0c775ff27 13 #define NUM_CONES 3
elmbed 17:d8b901d791fd 14 #define STATIONS 20 // max length of a pattern
elmbed 17:d8b901d791fd 15 #define SEQUENCES 9 // number of patterns to store
elmbed 17:d8b901d791fd 16
elmbed 17:d8b901d791fd 17 #define TRILAT_CONE 99
elmbed 17:d8b901d791fd 18
elmbed 17:d8b901d791fd 19 #define DEBOUNCE_MS 100
AntonLS 46:28c29ef61276 20 #define LIGHTS TOUCHLIGHTS
AntonLS 46:28c29ef61276 21 #define FAKEOUT 0x08
AntonLS 46:28c29ef61276 22 #define FAIL_QUICK 0x10
AntonLS 46:28c29ef61276 23 #define SILENT 0x20
elmbed 17:d8b901d791fd 24 #define GRACE_PERIOD 3000
elmbed 17:d8b901d791fd 25
elmbed 17:d8b901d791fd 26 #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need //////////////////////DEBUG messages on the console;
elmbed 17:d8b901d791fd 27 * it will have an impact on code-size and power consumption. */
elmbed 17:d8b901d791fd 28
elmbed 17:d8b901d791fd 29 #define LOOPBACK_MODE 0 // Loopback mode
elmbed 17:d8b901d791fd 30
elmbed 17:d8b901d791fd 31 #if NEED_CONSOLE_OUTPUT
elmbed 17:d8b901d791fd 32 #define DEBUG(...) { printf(__VA_ARGS__); }
elmbed 17:d8b901d791fd 33 #else
elmbed 17:d8b901d791fd 34 #define DEBUG(...) /* nothing */
elmbed 17:d8b901d791fd 35 #endif /* #if NEED_CONSOLE_OUTPUT */
elmbed 17:d8b901d791fd 36
elmbed 18:affef3a7db2a 37 #if 1
elmbed 17:d8b901d791fd 38 extern int random(int numberone, int numbertwo);
elmbed 17:d8b901d791fd 39
elmbed 17:d8b901d791fd 40 unsigned long millis();
elmbed 17:d8b901d791fd 41 unsigned long micros();
elmbed 17:d8b901d791fd 42
elmbed 17:d8b901d791fd 43 TA ta;
elmbed 17:d8b901d791fd 44
elmbed 18:affef3a7db2a 45 static bool active_cones[NUM_CONES + 1]; // + 1 so we can be 1 based like the cone numbers are
elmbed 17:d8b901d791fd 46
elmbed 28:8e74ddc4f70f 47 const static int CONTROL_CONE = 1;
elmbed 28:8e74ddc4f70f 48
elmbed 23:26f27c462976 49 #ifdef MASTER
elmbed 18:affef3a7db2a 50 static Mode_t mode = PATTERN;
elmbed 18:affef3a7db2a 51 static patternState_t state_p = IDLE_P;
elmbed 18:affef3a7db2a 52 static inputState_t state_i = IDLE_I;
elmbed 23:26f27c462976 53 #else
elmbed 23:26f27c462976 54 State_t state = IDLE;
elmbed 23:26f27c462976 55 #endif
elmbed 17:d8b901d791fd 56
elmbed 18:affef3a7db2a 57 static Message m1 = { 'm',0,2 };
elmbed 17:d8b901d791fd 58
elmbed 18:affef3a7db2a 59 static Message *m = &m1;
elmbed 18:affef3a7db2a 60 static Message m2 = { 'm',0,2 };
elmbed 18:affef3a7db2a 61 static Message *m_in = &m2;
elmbed 17:d8b901d791fd 62
elmbed 18:affef3a7db2a 63 static uint8_t active_cone = 0;
elmbed 38:76e49d045a3b 64 static unsigned long timeout = 10000L;
elmbed 18:affef3a7db2a 65 static uint8_t mask = 0x07;
elmbed 18:affef3a7db2a 66 static uint8_t fakeout = 0;
elmbed 18:affef3a7db2a 67 static uint8_t fail_quick = 0;
elmbed 18:affef3a7db2a 68 static uint8_t index = 0;
elmbed 18:affef3a7db2a 69 static bool new_state = false;
elmbed 18:affef3a7db2a 70 static bool tag_start = false; // flag to indicate we should wait for the user to activate the first station before going through the sequence
elmbed 18:affef3a7db2a 71
elmbed 17:d8b901d791fd 72 static bool in_menu = false;
elmbed 17:d8b901d791fd 73 static bool warning = false;
elmbed 17:d8b901d791fd 74 static bool penalty = false;
elmbed 17:d8b901d791fd 75 static bool logging = false;
elmbed 17:d8b901d791fd 76
elmbed 17:d8b901d791fd 77 // course setup (probably should make some of these persistant settings)
elmbed 18:affef3a7db2a 78 static uint8_t active_sequence = 0;
elmbed 18:affef3a7db2a 79 static uint8_t station = 1;
elmbed 18:affef3a7db2a 80 static uint8_t cone = 0;
elmbed 18:affef3a7db2a 81 static uint16_t ltime = 0;
elmbed 17:d8b901d791fd 82
elmbed 17:d8b901d791fd 83 volatile bool triggered;
elmbed 17:d8b901d791fd 84 volatile bool pin;
elmbed 17:d8b901d791fd 85 volatile bool ping = false;
elmbed 18:affef3a7db2a 86
elmbed 17:d8b901d791fd 87 static volatile bool captured = false;
elmbed 17:d8b901d791fd 88 static volatile unsigned long ping_timer = 0;
elmbed 17:d8b901d791fd 89 static volatile unsigned long dist_timeout = 0;
elmbed 17:d8b901d791fd 90
elmbed 17:d8b901d791fd 91 // all sequence data
elmbed 17:d8b901d791fd 92 uint8_t cone_table[STATIONS * SEQUENCES];
elmbed 17:d8b901d791fd 93 uint8_t mask_table[STATIONS * SEQUENCES];
elmbed 17:d8b901d791fd 94 uint16_t time_table[STATIONS * SEQUENCES];
elmbed 17:d8b901d791fd 95
elmbed 17:d8b901d791fd 96 // pointer to active table
elmbed 17:d8b901d791fd 97 uint8_t *cones = (uint8_t*)cone_table;
elmbed 17:d8b901d791fd 98 uint8_t *masks = (uint8_t*)mask_table;
elmbed 17:d8b901d791fd 99 uint16_t *times = (uint16_t*)time_table;
elmbed 17:d8b901d791fd 100
elmbed 17:d8b901d791fd 101 static bool lonely = false;
elmbed 17:d8b901d791fd 102
elmbed 17:d8b901d791fd 103 // Function prototypes
elmbed 23:26f27c462976 104 #ifdef MASTER
elmbed 17:d8b901d791fd 105 void spin();
elmbed 17:d8b901d791fd 106 patternState_t stateFromCone(uint8_t cone);
elmbed 17:d8b901d791fd 107 void printSplit(unsigned long timer);
elmbed 17:d8b901d791fd 108 uint8_t getRandomCone(void);
elmbed 17:d8b901d791fd 109 void clearCones(void);
elmbed 17:d8b901d791fd 110 void powerupCones(uint8_t sound);
elmbed 17:d8b901d791fd 111 void failCones(void);
elmbed 17:d8b901d791fd 112 void resetSensors(void);
elmbed 17:d8b901d791fd 113 void successCones(void);
elmbed 17:d8b901d791fd 114 void find_cones(void);
elmbed 17:d8b901d791fd 115 void printMsAsSeconds(unsigned long number);
elmbed 17:d8b901d791fd 116 void spinButtons(void);
elmbed 17:d8b901d791fd 117 uint8_t checkButtons(void);
elmbed 17:d8b901d791fd 118 Event getInputEvent(void);
elmbed 17:d8b901d791fd 119 void getRadioInput(char *ibuffer, int size);
elmbed 17:d8b901d791fd 120 void interpret(char parameter, int value);
elmbed 23:26f27c462976 121 #endif
elmbed 23:26f27c462976 122
elmbed 23:26f27c462976 123 extern "C" void writeToPhone(char *format, ...);
elmbed 17:d8b901d791fd 124
elmbed 38:76e49d045a3b 125
AntonLS 39:b1f864b71318 126 static const int active_colour = 0x00FF00; /// 0x00FF;
AntonLS 39:b1f864b71318 127 static const int warn_colour = 0xFFA500; /// 0xF050;
AntonLS 39:b1f864b71318 128 static const int fail_colour = 0x00; /// 0x0000FF;
AntonLS 39:b1f864b71318 129 static const int touch_colour = 0x0000FF; /// 0x005050;
AntonLS 39:b1f864b71318 130 static const int success_colour = 0x00FF00; /// 0xFFFF;
AntonLS 39:b1f864b71318 131 static const int pen_colour = 0xFFFF00; /// 0x10FF;
AntonLS 39:b1f864b71318 132 static const int idle_colour = 0xFF0000; /// 0x00;
elmbed 38:76e49d045a3b 133
elmbed 17:d8b901d791fd 134 char local_input[50] = {0};
elmbed 17:d8b901d791fd 135
elmbed 17:d8b901d791fd 136 //DigitalOut red(RED);
elmbed 17:d8b901d791fd 137 //DigitalOut enable1(ENABLE_1);
elmbed 17:d8b901d791fd 138 //DigitalOut green(GREEN);
elmbed 17:d8b901d791fd 139 //DigitalOut blue(BLUE);
elmbed 17:d8b901d791fd 140 //DigitalOut enable2(ENABLE_2);
elmbed 17:d8b901d791fd 141 //DigitalOut enable3(ENABLE_3);
elmbed 17:d8b901d791fd 142
elmbed 23:26f27c462976 143 #ifdef MASTER
elmbed 23:26f27c462976 144 static void master_setup()
elmbed 17:d8b901d791fd 145 {
elmbed 28:8e74ddc4f70f 146 ta.initialize(NODE_ID);
elmbed 17:d8b901d791fd 147
elmbed 17:d8b901d791fd 148 uint16_t sent = 0;
elmbed 17:d8b901d791fd 149 uint16_t lost = 0;
elmbed 17:d8b901d791fd 150 unsigned long start = micros();
elmbed 17:d8b901d791fd 151 //while (millis() - now <= ACK_TIME){
elmbed 17:d8b901d791fd 152 m->command = 'p';
elmbed 17:d8b901d791fd 153 m->value = 0;
elmbed 17:d8b901d791fd 154 m->cone = 0;
elmbed 17:d8b901d791fd 155
elmbed 23:26f27c462976 156
elmbed 23:26f27c462976 157 //find_cones(); // this causes the beep to be interrupted
elmbed 23:26f27c462976 158 //ta.beep(100);
elmbed 17:d8b901d791fd 159 int i;
elmbed 23:26f27c462976 160
elmbed 28:8e74ddc4f70f 161 for(i = 1; i < NUM_CONES + 1; ++i)
elmbed 28:8e74ddc4f70f 162 {
elmbed 28:8e74ddc4f70f 163 active_cones[i] = false;
elmbed 28:8e74ddc4f70f 164 }
elmbed 17:d8b901d791fd 165
elmbed 28:8e74ddc4f70f 166 unsigned long time = 0;
elmbed 17:d8b901d791fd 167
elmbed 17:d8b901d791fd 168 // pull course sequences from non-volatile memory
elmbed 28:8e74ddc4f70f 169 for(uint8_t i = 0; i <STATIONS * SEQUENCES; ++i)
elmbed 28:8e74ddc4f70f 170 {
elmbed 17:d8b901d791fd 171 cone_table[i] = i+1;
elmbed 17:d8b901d791fd 172 mask_table[i] = 1;
elmbed 17:d8b901d791fd 173 time_table[i] = 1000;
elmbed 17:d8b901d791fd 174 }
elmbed 18:affef3a7db2a 175
elmbed 18:affef3a7db2a 176 ta.post_color(0xFF0000);
elmbed 40:dec5270e03e9 177
elmbed 40:dec5270e03e9 178 srand(millis());
elmbed 17:d8b901d791fd 179 }
elmbed 23:26f27c462976 180 #else
elmbed 23:26f27c462976 181 static void slave_setup()
elmbed 23:26f27c462976 182 {
elmbed 28:8e74ddc4f70f 183 ta.initialize(NODE_ID);
AntonLS 46:28c29ef61276 184 /// ta.beep(250);
elmbed 23:26f27c462976 185 }
elmbed 23:26f27c462976 186 #endif
elmbed 23:26f27c462976 187
elmbed 23:26f27c462976 188 void setup()
elmbed 23:26f27c462976 189 {
elmbed 23:26f27c462976 190 #ifdef MASTER
elmbed 23:26f27c462976 191 master_setup();
elmbed 23:26f27c462976 192 #else
elmbed 23:26f27c462976 193 slave_setup();
elmbed 23:26f27c462976 194 #endif
elmbed 23:26f27c462976 195 }
elmbed 23:26f27c462976 196
elmbed 23:26f27c462976 197 #ifdef SLAVE
elmbed 23:26f27c462976 198 static void slave_loop()
elmbed 23:26f27c462976 199 {
elmbed 23:26f27c462976 200 static unsigned long start = 0;
elmbed 23:26f27c462976 201 static unsigned long timeout;
elmbed 23:26f27c462976 202 static bool process_next_as_time = false;
elmbed 23:26f27c462976 203 static bool process_next_as_mask = false;
elmbed 23:26f27c462976 204 static unsigned long timer;
elmbed 23:26f27c462976 205 static State_t last_state = IDLE;
elmbed 28:8e74ddc4f70f 206 static int counter = 0;
elmbed 23:26f27c462976 207
AntonLS 46:28c29ef61276 208 ta.spin();
AntonLS 46:28c29ef61276 209
elmbed 23:26f27c462976 210 if(last_state != state)
elmbed 23:26f27c462976 211 {
elmbed 23:26f27c462976 212 if(state == ACTIVE_TARGET)
elmbed 38:76e49d045a3b 213 writeToPhone("State is ACTIVE_TARGET\r\n");
elmbed 23:26f27c462976 214 if(state == IDLE)
elmbed 38:76e49d045a3b 215 writeToPhone("State is IDLE\r\n");
elmbed 23:26f27c462976 216 if(state == FAIL)
elmbed 38:76e49d045a3b 217 writeToPhone("State is FAIL\r\n");
elmbed 23:26f27c462976 218 if(state == SUCCESS)
elmbed 38:76e49d045a3b 219 writeToPhone("State is SUCCESS\r\n");
elmbed 23:26f27c462976 220 }
elmbed 23:26f27c462976 221 last_state = state;
AntonLS 31:a6110950f385 222
elmbed 23:26f27c462976 223 char message = 'n';
elmbed 23:26f27c462976 224 timer = millis() - start;
elmbed 23:26f27c462976 225
elmbed 23:26f27c462976 226 if(ta.recieve(m_in))
elmbed 23:26f27c462976 227 {
elmbed 28:8e74ddc4f70f 228 //ta.beep(1000);
elmbed 28:8e74ddc4f70f 229
elmbed 23:26f27c462976 230 message = m_in->command;
elmbed 23:26f27c462976 231 switch(m_in->command)
elmbed 23:26f27c462976 232 {
elmbed 23:26f27c462976 233 case 't':
elmbed 38:76e49d045a3b 234 timeout = 10000L;//m_in->value;
elmbed 23:26f27c462976 235 //serial.printf("timeout: ");
elmbed 23:26f27c462976 236 //serial.printf("%d\n",timeout);
elmbed 23:26f27c462976 237 break;
elmbed 23:26f27c462976 238 case 'm':
elmbed 23:26f27c462976 239 //serial.printf("config bits: ");
elmbed 23:26f27c462976 240 mask = m_in->value;
elmbed 23:26f27c462976 241 ta.setMask(mask);// & LIGHTS);
elmbed 23:26f27c462976 242 //serial.printf("%s\n",byte_to_binary(mask));
elmbed 23:26f27c462976 243 fakeout = mask & FAKEOUT;
elmbed 23:26f27c462976 244
elmbed 23:26f27c462976 245 //if(fakeout)
elmbed 23:26f27c462976 246 // serial.printf("fakeout!");
elmbed 23:26f27c462976 247
elmbed 23:26f27c462976 248 fail_quick = mask & FAIL_QUICK;
elmbed 23:26f27c462976 249 break;
elmbed 23:26f27c462976 250 default: break;
elmbed 23:26f27c462976 251 }
elmbed 23:26f27c462976 252 }
elmbed 23:26f27c462976 253
elmbed 23:26f27c462976 254 if(message == 'x')
elmbed 23:26f27c462976 255 {
AntonLS 46:28c29ef61276 256 ta.resetTouch();
elmbed 23:26f27c462976 257 }
elmbed 23:26f27c462976 258
elmbed 23:26f27c462976 259 if(message == 'f')
elmbed 23:26f27c462976 260 { // Fail
elmbed 23:26f27c462976 261 //serial.printf("Fail!\n");
elmbed 38:76e49d045a3b 262 writeToPhone("FAIL\r\n");
AntonLS 46:28c29ef61276 263 /// ta.post_color(fail_colour);
AntonLS 46:28c29ef61276 264 ta.pulse(25,200,3000,fail_colour);
elmbed 23:26f27c462976 265 state = FAIL;
elmbed 23:26f27c462976 266 }
elmbed 23:26f27c462976 267
elmbed 23:26f27c462976 268 if(message == 's')
elmbed 23:26f27c462976 269 { // Success
elmbed 23:26f27c462976 270 //serial.printf("Success!\n");
elmbed 38:76e49d045a3b 271 ta.post_color(0x0FFF00);
elmbed 23:26f27c462976 272 ta.beep(1500);
elmbed 23:26f27c462976 273 state = SUCCESS;
elmbed 23:26f27c462976 274 }
elmbed 23:26f27c462976 275
elmbed 23:26f27c462976 276 if(message == 'g')
elmbed 23:26f27c462976 277 { // This cone is the active target, GO!
elmbed 23:26f27c462976 278 start = millis();
elmbed 23:26f27c462976 279 warning = false;
elmbed 23:26f27c462976 280 penalty = false;
AntonLS 46:28c29ef61276 281 /// ta.post_color(active_colour);
AntonLS 46:28c29ef61276 282 ta.pulse(50,750,~0L,active_colour);
elmbed 23:26f27c462976 283 state = ACTIVE_TARGET;
elmbed 23:26f27c462976 284 //serial.printf("fakeout, fail_quick\n");
elmbed 23:26f27c462976 285 //serial.printf("%d",fakeout);
elmbed 23:26f27c462976 286 //serial.printf(", ");
elmbed 23:26f27c462976 287 //serial.printf("%d\n",fail_quick);
elmbed 23:26f27c462976 288 }
elmbed 23:26f27c462976 289
elmbed 23:26f27c462976 290 if(message == 'q')
elmbed 23:26f27c462976 291 { // Quit
elmbed 28:8e74ddc4f70f 292 writeToPhone("Clear!\r\n");
elmbed 23:26f27c462976 293 ta.pulse_off();
elmbed 38:76e49d045a3b 294 ta.mask_color(idle_colour);
elmbed 23:26f27c462976 295 state = IDLE;
elmbed 23:26f27c462976 296 }
elmbed 23:26f27c462976 297
elmbed 23:26f27c462976 298 if(message != 'n')
elmbed 23:26f27c462976 299 {
elmbed 23:26f27c462976 300 //serial.printf("%d",message);
elmbed 23:26f27c462976 301 //serial.printf(", ");
elmbed 23:26f27c462976 302 //serial.printf("%d\n",m_in->value);
elmbed 23:26f27c462976 303 }
elmbed 23:26f27c462976 304
elmbed 23:26f27c462976 305 if(message == 'u')
elmbed 23:26f27c462976 306 { // powerup noise
elmbed 23:26f27c462976 307 ta.powerup(m_in->value);
elmbed 23:26f27c462976 308 }
elmbed 23:26f27c462976 309
elmbed 23:26f27c462976 310 if(message == 'z')
elmbed 23:26f27c462976 311 {
elmbed 23:26f27c462976 312 m->value = m_in->value;
elmbed 23:26f27c462976 313 m->command = 'z';
elmbed 28:8e74ddc4f70f 314 m->cone = 1;
elmbed 23:26f27c462976 315 ta.send(m);
elmbed 23:26f27c462976 316 }
elmbed 23:26f27c462976 317
elmbed 23:26f27c462976 318 timer = millis() - start;
elmbed 23:26f27c462976 319
elmbed 23:26f27c462976 320 switch(state)
elmbed 23:26f27c462976 321 {
elmbed 23:26f27c462976 322 case ACTIVE_TARGET:
elmbed 23:26f27c462976 323 if(ta.activated() || ((timer > timeout) && (fakeout)))
elmbed 23:26f27c462976 324 {
elmbed 23:26f27c462976 325 m->command = 'd';
elmbed 23:26f27c462976 326 m->cone = CONTROL_CONE;
elmbed 23:26f27c462976 327 ta.send(m);
AntonLS 46:28c29ef61276 328 /// ta.post_color(success_colour);
elmbed 23:26f27c462976 329 ta.pulse_off();
elmbed 23:26f27c462976 330 state = IDLE;
elmbed 23:26f27c462976 331 //serial.printf("Done!\n");
elmbed 23:26f27c462976 332 }
elmbed 23:26f27c462976 333 else if(timer > timeout && !penalty)
elmbed 23:26f27c462976 334 {
elmbed 38:76e49d045a3b 335 writeToPhone("PEN\r\n");
elmbed 23:26f27c462976 336 //serial.printf("Penalty!\n");
elmbed 23:26f27c462976 337 penalty = true;
AntonLS 46:28c29ef61276 338 ta.pulse(350,600,~0L,pen_colour);
AntonLS 46:28c29ef61276 339 /// ta.post_color(pen_colour);
elmbed 23:26f27c462976 340 }
elmbed 23:26f27c462976 341 else if(timer > ((timeout*3)/4) && !warning)
elmbed 23:26f27c462976 342 {
elmbed 38:76e49d045a3b 343 writeToPhone("WARN\r\n");
elmbed 23:26f27c462976 344 //serial.printf("Warning!\n");
elmbed 23:26f27c462976 345 warning = true;
AntonLS 46:28c29ef61276 346 ta.pulse(350,750,~0L,warn_colour);
AntonLS 46:28c29ef61276 347 /// ta.post_color(warn_colour);
elmbed 23:26f27c462976 348 }
elmbed 23:26f27c462976 349 break;
elmbed 23:26f27c462976 350 case IDLE:
elmbed 38:76e49d045a3b 351 bool act = ta.activated();
elmbed 38:76e49d045a3b 352 ta.post_color(act?touch_colour:idle_colour);
elmbed 23:26f27c462976 353 break;
elmbed 23:26f27c462976 354 default:
elmbed 23:26f27c462976 355 break;
elmbed 23:26f27c462976 356 }
elmbed 23:26f27c462976 357 }
elmbed 23:26f27c462976 358 #endif
elmbed 23:26f27c462976 359
elmbed 23:26f27c462976 360 #ifdef MASTER
elmbed 23:26f27c462976 361 static void master_loop()
elmbed 23:26f27c462976 362 {
elmbed 23:26f27c462976 363 static Mode_t last_mode = mode;
elmbed 28:8e74ddc4f70f 364 static int counter = 0;
elmbed 23:26f27c462976 365
elmbed 23:26f27c462976 366 if (last_mode != mode)
elmbed 23:26f27c462976 367 {
elmbed 23:26f27c462976 368 if (mode == FREEFORM)
elmbed 40:dec5270e03e9 369 srand(millis());
elmbed 38:76e49d045a3b 370 writeToPhone("RR.\r\n");
elmbed 23:26f27c462976 371
elmbed 23:26f27c462976 372 if (mode == PATTERN)
elmbed 38:76e49d045a3b 373 writeToPhone("SP.\r\n");
elmbed 23:26f27c462976 374 }
elmbed 23:26f27c462976 375
elmbed 23:26f27c462976 376 last_mode = mode;
elmbed 23:26f27c462976 377
elmbed 23:26f27c462976 378 ta.spin();
elmbed 23:26f27c462976 379 //spinButtons();
elmbed 38:76e49d045a3b 380 //if((logging || micros() < dist_timeout) && ta.recieve(m_in))
elmbed 38:76e49d045a3b 381 // writeToPhone("CMD: %c",m_in->command);
elmbed 38:76e49d045a3b 382 // else
elmbed 23:26f27c462976 383 spin();
elmbed 23:26f27c462976 384 }
elmbed 23:26f27c462976 385 #endif
elmbed 17:d8b901d791fd 386
elmbed 17:d8b901d791fd 387 void loop()
elmbed 17:d8b901d791fd 388 {
elmbed 23:26f27c462976 389 #ifdef MASTER
elmbed 23:26f27c462976 390 master_loop();
elmbed 23:26f27c462976 391 #else
elmbed 23:26f27c462976 392 slave_loop();
elmbed 23:26f27c462976 393 #endif
elmbed 17:d8b901d791fd 394 }
elmbed 17:d8b901d791fd 395
elmbed 23:26f27c462976 396 static void getNext()
elmbed 17:d8b901d791fd 397 {
elmbed 23:26f27c462976 398 #ifdef MASTER
elmbed 17:d8b901d791fd 399 if(mode == FREEFORM)
elmbed 17:d8b901d791fd 400 {
elmbed 40:dec5270e03e9 401 active_cone = getRandomCone();
elmbed 38:76e49d045a3b 402
elmbed 38:76e49d045a3b 403 writeToPhone("GN_AC: %d\r\n", active_cone);
elmbed 38:76e49d045a3b 404
elmbed 17:d8b901d791fd 405 mask = 0x07;
elmbed 17:d8b901d791fd 406 ta.setMask(mask & LIGHTS);
AntonLS 46:28c29ef61276 407 timeout = ~0;
elmbed 38:76e49d045a3b 408
elmbed 17:d8b901d791fd 409 return;
elmbed 17:d8b901d791fd 410 }
elmbed 17:d8b901d791fd 411
elmbed 17:d8b901d791fd 412 active_cone = cones[index];
elmbed 17:d8b901d791fd 413 mask = masks[index];
elmbed 17:d8b901d791fd 414 fakeout = mask & FAKEOUT;
elmbed 17:d8b901d791fd 415 fail_quick = mask & FAIL_QUICK;
elmbed 17:d8b901d791fd 416 timeout = times[index];
elmbed 17:d8b901d791fd 417 index++;
elmbed 17:d8b901d791fd 418 DEBUG("Next cone is \n");
elmbed 17:d8b901d791fd 419 DEBUG("%d\n",active_cone);
elmbed 23:26f27c462976 420 #endif
elmbed 17:d8b901d791fd 421 }
elmbed 18:affef3a7db2a 422 #if 1
elmbed 23:26f27c462976 423 static void spin()
elmbed 17:d8b901d791fd 424 {
AntonLS 39:b1f864b71318 425 #ifdef MASTER
elmbed 17:d8b901d791fd 426 static patternState_t last_state = START_P;
elmbed 17:d8b901d791fd 427 static uint8_t last_cone = 255;
elmbed 17:d8b901d791fd 428 static unsigned long start;
elmbed 17:d8b901d791fd 429 static unsigned long timer;
elmbed 17:d8b901d791fd 430 static bool first; // first should be true when we first enter a state (even if we just exited the same state)
elmbed 17:d8b901d791fd 431 char command = 'n';
elmbed 17:d8b901d791fd 432 unsigned long value = 0;
elmbed 17:d8b901d791fd 433
elmbed 17:d8b901d791fd 434 m_in->command = 0;
elmbed 17:d8b901d791fd 435 m_in->value = 0;
elmbed 17:d8b901d791fd 436 m_in->cone = 0;
elmbed 17:d8b901d791fd 437
elmbed 17:d8b901d791fd 438 if(ta.recieve(m_in))
elmbed 17:d8b901d791fd 439 {
elmbed 38:76e49d045a3b 440 writeToPhone("SR: %d '%c'\r\n", m_in->cone, m_in->command);
elmbed 17:d8b901d791fd 441 command = m_in->command;
elmbed 17:d8b901d791fd 442 value = m_in->value;
elmbed 17:d8b901d791fd 443 }
elmbed 17:d8b901d791fd 444
elmbed 17:d8b901d791fd 445 first = false;
elmbed 17:d8b901d791fd 446
elmbed 17:d8b901d791fd 447 if(last_state != state_p || new_state)
elmbed 17:d8b901d791fd 448 {
elmbed 17:d8b901d791fd 449 if(state_p == START_P)
AntonLS 39:b1f864b71318 450 writeToPhone("State is START\r\n"); // PROTOCOL
elmbed 17:d8b901d791fd 451 if(state_p == WAITING_P)
AntonLS 39:b1f864b71318 452 writeToPhone("State is WAITING\r\n"); // PROTOCOL
elmbed 17:d8b901d791fd 453 if(state_p == ACTIVE_TARGET_P)
AntonLS 39:b1f864b71318 454 writeToPhone("State is ACTIVE_TARGET\r\n"); // PROTOCOL
elmbed 17:d8b901d791fd 455 if(state_p == IDLE_P)
AntonLS 39:b1f864b71318 456 writeToPhone("State is IDLE\r\n"); // PROTOCOL
elmbed 17:d8b901d791fd 457 if(state_p == FAIL_P)
AntonLS 39:b1f864b71318 458 writeToPhone("State is FAIL\r\n"); // PROTOCOL
elmbed 17:d8b901d791fd 459 if(state_p == SUCCESS_P)
AntonLS 39:b1f864b71318 460 writeToPhone("State is SUCCESS\r\n"); // PROTOCOL
elmbed 17:d8b901d791fd 461
elmbed 17:d8b901d791fd 462 first = true;
elmbed 17:d8b901d791fd 463 new_state = false;
elmbed 17:d8b901d791fd 464 }
elmbed 17:d8b901d791fd 465
elmbed 17:d8b901d791fd 466 last_state = state_p;
elmbed 17:d8b901d791fd 467 last_cone = active_cone;
elmbed 17:d8b901d791fd 468
elmbed 17:d8b901d791fd 469 timer = millis() - start;
elmbed 17:d8b901d791fd 470
elmbed 17:d8b901d791fd 471 switch(state_p)
elmbed 17:d8b901d791fd 472 {
elmbed 17:d8b901d791fd 473 case IDLE_P:
AntonLS 30:c60b0d52b067 474 ta.setMask( DEFTOUCHMASK );
elmbed 17:d8b901d791fd 475 if(!in_menu)
elmbed 38:76e49d045a3b 476 ta.post_color((ta.activated())?touch_colour:idle_colour);
elmbed 17:d8b901d791fd 477 break;
elmbed 17:d8b901d791fd 478
elmbed 17:d8b901d791fd 479 case START_P:
elmbed 38:76e49d045a3b 480 clearCones();
elmbed 17:d8b901d791fd 481 tag_start = false;
elmbed 38:76e49d045a3b 482 ta.post_color(idle_colour);
elmbed 17:d8b901d791fd 483 index = 0;
elmbed 17:d8b901d791fd 484 getNext();
elmbed 17:d8b901d791fd 485
elmbed 17:d8b901d791fd 486 if(timeout == 0)
elmbed 17:d8b901d791fd 487 { // timeout of 0 means wait indefinitely for the first cone to be activated, then start the rest of the sequence
elmbed 17:d8b901d791fd 488 timeout = ~0;
elmbed 17:d8b901d791fd 489 tag_start = true;
AntonLS 39:b1f864b71318 490 // DEBUG("Activate cone "); // May use this again in future.
AntonLS 39:b1f864b71318 491 // DEBUG("%d",active_cone);
AntonLS 39:b1f864b71318 492 // DEBUG(" to start.\n");
elmbed 38:76e49d045a3b 493 writeToPhone("ACS: %d\r\n", active_cone);
elmbed 17:d8b901d791fd 494 }
elmbed 17:d8b901d791fd 495
elmbed 17:d8b901d791fd 496 start = millis();
elmbed 17:d8b901d791fd 497 state_p = stateFromCone(active_cone);
elmbed 17:d8b901d791fd 498 if(active_cone == 0)
elmbed 17:d8b901d791fd 499 { // in this case stateFromCone returns SUCCESS_P, but really there was no course sequence
elmbed 17:d8b901d791fd 500 DEBUG("\n");
elmbed 17:d8b901d791fd 501 DEBUG("Empty course sequence!\n");
elmbed 38:76e49d045a3b 502 writeToPhone("ECS\r\n");
elmbed 17:d8b901d791fd 503 ta.post_color(0x0000FF);
elmbed 17:d8b901d791fd 504 state_p = IDLE_P;
elmbed 17:d8b901d791fd 505 break;
elmbed 17:d8b901d791fd 506 }
elmbed 17:d8b901d791fd 507 break;
elmbed 17:d8b901d791fd 508
elmbed 17:d8b901d791fd 509 case WAITING_P:
elmbed 17:d8b901d791fd 510 if(first)
elmbed 17:d8b901d791fd 511 {
elmbed 17:d8b901d791fd 512 m->command = 'm';
elmbed 17:d8b901d791fd 513 m->value = mask;
elmbed 17:d8b901d791fd 514 m->cone = active_cone;
elmbed 17:d8b901d791fd 515 ta.send(m);
elmbed 38:76e49d045a3b 516
elmbed 38:76e49d045a3b 517 wait_ms(300);
elmbed 17:d8b901d791fd 518 m->command = 't';
elmbed 17:d8b901d791fd 519 m->value = (uint32_t)timeout;
elmbed 17:d8b901d791fd 520 ta.send(m);
elmbed 38:76e49d045a3b 521
elmbed 38:76e49d045a3b 522 wait_ms(300);
elmbed 17:d8b901d791fd 523 m->command = 'g';
elmbed 17:d8b901d791fd 524 ta.send(m);
elmbed 17:d8b901d791fd 525
elmbed 38:76e49d045a3b 526 writeToPhone("ACW: %d\r\n", active_cone);
elmbed 17:d8b901d791fd 527 }
elmbed 17:d8b901d791fd 528
elmbed 38:76e49d045a3b 529 ta.post_color(( ta.activated())?touch_colour:idle_colour);
elmbed 17:d8b901d791fd 530
elmbed 17:d8b901d791fd 531 DEBUG("Waiting: %d %d %c\n", m_in->cone, active_cone, command);
elmbed 17:d8b901d791fd 532
elmbed 17:d8b901d791fd 533 if((m_in->cone == active_cone && command == 'd' ) || ((timer >= timeout) && fakeout))
elmbed 17:d8b901d791fd 534 {
elmbed 17:d8b901d791fd 535 if((timer >= timeout) && !fakeout)
elmbed 17:d8b901d791fd 536 {
elmbed 38:76e49d045a3b 537 writeToPhone("TSP\r\n");
elmbed 17:d8b901d791fd 538 }
elmbed 17:d8b901d791fd 539 printSplit(timer);
elmbed 17:d8b901d791fd 540 getNext();
elmbed 17:d8b901d791fd 541 start = millis();
elmbed 17:d8b901d791fd 542
elmbed 17:d8b901d791fd 543 state_p = stateFromCone(active_cone);
elmbed 17:d8b901d791fd 544
elmbed 17:d8b901d791fd 545 if(state_p == WAITING_P)
elmbed 17:d8b901d791fd 546 {
elmbed 38:76e49d045a3b 547 writeToPhone("NSW\r\n");
elmbed 17:d8b901d791fd 548 new_state = true;
elmbed 17:d8b901d791fd 549 }
elmbed 17:d8b901d791fd 550 }
elmbed 17:d8b901d791fd 551 else if(~timeout != 0 && mode == PATTERN && timer >= (timeout + ((fail_quick)?0:GRACE_PERIOD)))
elmbed 17:d8b901d791fd 552 {
elmbed 38:76e49d045a3b 553 writeToPhone("FW\r\n");
elmbed 17:d8b901d791fd 554 state_p = FAIL_P;
elmbed 17:d8b901d791fd 555 }
elmbed 17:d8b901d791fd 556 break;
elmbed 17:d8b901d791fd 557
elmbed 17:d8b901d791fd 558 case ACTIVE_TARGET_P:
elmbed 17:d8b901d791fd 559 if(first)
elmbed 17:d8b901d791fd 560 {
elmbed 17:d8b901d791fd 561 ta.setMask(mask);
elmbed 17:d8b901d791fd 562
elmbed 17:d8b901d791fd 563 warning = false;
elmbed 17:d8b901d791fd 564 penalty = false;
AntonLS 46:28c29ef61276 565 /// ta.post_color(active_colour);
AntonLS 46:28c29ef61276 566 ta.pulse(50,750,~0L,active_colour);
AntonLS 46:28c29ef61276 567 //if(!(mask & SILENT))ta.pulse(50,750,~0L,active_colour);
elmbed 17:d8b901d791fd 568 }
elmbed 17:d8b901d791fd 569 if(timer >= timeout)
elmbed 17:d8b901d791fd 570 {
elmbed 17:d8b901d791fd 571 if(!penalty)
elmbed 17:d8b901d791fd 572 {
AntonLS 46:28c29ef61276 573 /// ta.post_color(pen_colour);
AntonLS 46:28c29ef61276 574 ta.pulse(50,325,~0L,pen_colour);
elmbed 17:d8b901d791fd 575
elmbed 17:d8b901d791fd 576 penalty = true;
elmbed 17:d8b901d791fd 577 }
elmbed 38:76e49d045a3b 578 ta.post_color(pen_colour);
elmbed 17:d8b901d791fd 579 }
elmbed 17:d8b901d791fd 580 else if(timer > ((timeout*3)/4) && !warning)
elmbed 17:d8b901d791fd 581 {
elmbed 17:d8b901d791fd 582 warning = true;
AntonLS 46:28c29ef61276 583 /// ta.post_color(warn_colour);
AntonLS 46:28c29ef61276 584 ta.pulse(50,750,~0L,warn_colour);
elmbed 17:d8b901d791fd 585 }
elmbed 17:d8b901d791fd 586
elmbed 17:d8b901d791fd 587 if(ta.activated() || ((timer >= timeout) && fakeout))
elmbed 17:d8b901d791fd 588 {
elmbed 17:d8b901d791fd 589 if((timer >= timeout) && !fakeout)
elmbed 17:d8b901d791fd 590 DEBUG("Timesplit penalty! ");
elmbed 17:d8b901d791fd 591
elmbed 17:d8b901d791fd 592 printSplit(timer);
elmbed 38:76e49d045a3b 593 ta.post_color(success_colour);
elmbed 17:d8b901d791fd 594 getNext();
elmbed 17:d8b901d791fd 595 start = millis();
elmbed 17:d8b901d791fd 596 state_p = stateFromCone(active_cone);
elmbed 17:d8b901d791fd 597
elmbed 17:d8b901d791fd 598 if(state_p == ACTIVE_TARGET_P)
elmbed 17:d8b901d791fd 599 new_state = true;
elmbed 17:d8b901d791fd 600 ta.pulse_off();
elmbed 17:d8b901d791fd 601
elmbed 17:d8b901d791fd 602 }
elmbed 17:d8b901d791fd 603 else if(~timeout != 0 && mode == PATTERN && timer >= (timeout + ((fail_quick)?0:GRACE_PERIOD)))
elmbed 17:d8b901d791fd 604 {
elmbed 17:d8b901d791fd 605 state_p = FAIL_P;
elmbed 17:d8b901d791fd 606 ta.pulse_off();
elmbed 17:d8b901d791fd 607 }
elmbed 17:d8b901d791fd 608 //DEBUG.println(timeout + ((fail_quick)?0:GRACE_PERIOD));
elmbed 17:d8b901d791fd 609 //DEBUG.println(timeout);
elmbed 17:d8b901d791fd 610
elmbed 17:d8b901d791fd 611 break;
elmbed 17:d8b901d791fd 612
elmbed 17:d8b901d791fd 613 case FAIL_P:
elmbed 17:d8b901d791fd 614 if(first)
elmbed 17:d8b901d791fd 615 {
elmbed 17:d8b901d791fd 616 start = millis();
elmbed 17:d8b901d791fd 617 DEBUG("\n");
elmbed 17:d8b901d791fd 618 DEBUG("Timeout\n");
elmbed 17:d8b901d791fd 619 //ta.post_color();
AntonLS 46:28c29ef61276 620 ta.pulse(25,200,3000,fail_colour);
AntonLS 46:28c29ef61276 621 /// ta.post_color(fail_colour);
elmbed 17:d8b901d791fd 622
elmbed 17:d8b901d791fd 623 failCones();
elmbed 17:d8b901d791fd 624 //ta.fail();
elmbed 17:d8b901d791fd 625 }
elmbed 17:d8b901d791fd 626 else if(timer > 3000)
elmbed 17:d8b901d791fd 627 {
elmbed 17:d8b901d791fd 628 DEBUG("Clear!\n");
elmbed 17:d8b901d791fd 629 state_p = IDLE_P;
elmbed 17:d8b901d791fd 630 clearCones();
elmbed 17:d8b901d791fd 631 }
elmbed 17:d8b901d791fd 632 break;
elmbed 17:d8b901d791fd 633 case SUCCESS_P:
elmbed 17:d8b901d791fd 634 if(first)
elmbed 17:d8b901d791fd 635 {
elmbed 17:d8b901d791fd 636 start = millis();
elmbed 17:d8b901d791fd 637 DEBUG("\n");
elmbed 17:d8b901d791fd 638 DEBUG("Done!\n");
elmbed 38:76e49d045a3b 639 ta.post_color(success_colour);
elmbed 17:d8b901d791fd 640 ta.beep(1500);
elmbed 17:d8b901d791fd 641 successCones();
elmbed 17:d8b901d791fd 642 //ta.success();
elmbed 17:d8b901d791fd 643 }
elmbed 17:d8b901d791fd 644 else if(timer > 1500)
elmbed 17:d8b901d791fd 645 {
elmbed 17:d8b901d791fd 646 DEBUG("Clear!\n");
elmbed 17:d8b901d791fd 647 state_p = IDLE_P;
elmbed 17:d8b901d791fd 648 clearCones();
elmbed 17:d8b901d791fd 649 }
elmbed 17:d8b901d791fd 650 break;
elmbed 17:d8b901d791fd 651
elmbed 17:d8b901d791fd 652 default:
elmbed 38:76e49d045a3b 653 ta.post_color(idle_colour);
elmbed 17:d8b901d791fd 654 break;
elmbed 17:d8b901d791fd 655 }
elmbed 23:26f27c462976 656 #endif
elmbed 17:d8b901d791fd 657 }
elmbed 18:affef3a7db2a 658 #endif
elmbed 18:affef3a7db2a 659
elmbed 23:26f27c462976 660 #ifdef MASTER
elmbed 17:d8b901d791fd 661 void getRadioInput(char *ibuffer, int size)
elmbed 17:d8b901d791fd 662 {
elmbed 17:d8b901d791fd 663 static int i = 0;
elmbed 17:d8b901d791fd 664 int buffer_counter = 0;
elmbed 17:d8b901d791fd 665 static char parameter = '_';
elmbed 17:d8b901d791fd 666 static char buffer[MAX_LEN + 1];
AntonLS 45:1eb335c00cb2 667 static char trashArea[MAX_LEN + 1];
elmbed 17:d8b901d791fd 668 int value = 0;
elmbed 17:d8b901d791fd 669 char *endp = NULL;
AntonLS 45:1eb335c00cb2 670
elmbed 17:d8b901d791fd 671 // listen for commands coming over bluetooth
elmbed 17:d8b901d791fd 672 while (buffer_counter < size)
elmbed 17:d8b901d791fd 673 {
elmbed 17:d8b901d791fd 674 char ch = ibuffer[buffer_counter++];
elmbed 17:d8b901d791fd 675
elmbed 17:d8b901d791fd 676 if((ch == '\r' || ch == ';' || ch == '\n') && parameter != '_')
elmbed 17:d8b901d791fd 677 {
elmbed 17:d8b901d791fd 678 if(i > 1)
elmbed 17:d8b901d791fd 679 {
AntonLS 41:dee3fd34e37a 680 buffer[i-1] = 0;
elmbed 17:d8b901d791fd 681 if(parameter == 'l')
elmbed 17:d8b901d791fd 682 value = strtoul(buffer, &endp, 2);
AntonLS 41:dee3fd34e37a 683 else if(parameter == 'B')
AntonLS 41:dee3fd34e37a 684 value = strtoul(buffer, &endp, 16);
AntonLS 41:dee3fd34e37a 685 else
AntonLS 41:dee3fd34e37a 686 value = atoi(buffer);
elmbed 17:d8b901d791fd 687 }
elmbed 18:affef3a7db2a 688
elmbed 17:d8b901d791fd 689 interpret(parameter, value);
elmbed 17:d8b901d791fd 690 DEBUG("After interp: '%c'\r\n", parameter);
elmbed 17:d8b901d791fd 691 parameter = '_';
elmbed 17:d8b901d791fd 692 buffer[0] = 0;
elmbed 17:d8b901d791fd 693 i=0;
elmbed 17:d8b901d791fd 694 }
elmbed 17:d8b901d791fd 695 else
elmbed 17:d8b901d791fd 696 {
elmbed 17:d8b901d791fd 697 if(i==0)
elmbed 17:d8b901d791fd 698 parameter = ch;
elmbed 17:d8b901d791fd 699 else
elmbed 17:d8b901d791fd 700 buffer[i-1] = ch;
elmbed 17:d8b901d791fd 701 i++;
elmbed 17:d8b901d791fd 702 }
elmbed 17:d8b901d791fd 703
elmbed 17:d8b901d791fd 704 if(ch == '_' || ch == '\r' || ch == ';' || ch == '\n')
elmbed 17:d8b901d791fd 705 {
elmbed 17:d8b901d791fd 706 parameter = '_';
elmbed 17:d8b901d791fd 707 buffer[0] = 0;
elmbed 17:d8b901d791fd 708 i=0;
elmbed 17:d8b901d791fd 709 }
elmbed 17:d8b901d791fd 710 }
elmbed 17:d8b901d791fd 711 }
elmbed 17:d8b901d791fd 712
elmbed 23:26f27c462976 713 static void interpret(char parameter, int value)
elmbed 17:d8b901d791fd 714 {
elmbed 18:affef3a7db2a 715 int remainder;
elmbed 18:affef3a7db2a 716 uint16_t split;
elmbed 18:affef3a7db2a 717 uint16_t t;
elmbed 18:affef3a7db2a 718 uint8_t c;
elmbed 18:affef3a7db2a 719 uint8_t l;
elmbed 18:affef3a7db2a 720 int last;
elmbed 18:affef3a7db2a 721 int middle;
elmbed 18:affef3a7db2a 722 uint8_t length;
elmbed 18:affef3a7db2a 723 uint8_t offset;
elmbed 18:affef3a7db2a 724 int i;
elmbed 18:affef3a7db2a 725 uint8_t v;
elmbed 18:affef3a7db2a 726 uint16_t val;
elmbed 17:d8b901d791fd 727
elmbed 17:d8b901d791fd 728 switch(parameter)
elmbed 17:d8b901d791fd 729 {
elmbed 17:d8b901d791fd 730 case 'f':
elmbed 17:d8b901d791fd 731 if(lonely)
elmbed 17:d8b901d791fd 732 {
elmbed 18:affef3a7db2a 733 writeToPhone("Sorry, no other cones detected, please try detecting cones first.\r\n");
elmbed 17:d8b901d791fd 734 break;
elmbed 17:d8b901d791fd 735 }
elmbed 18:affef3a7db2a 736
elmbed 18:affef3a7db2a 737 writeToPhone("Entered freeform\r\n");
elmbed 17:d8b901d791fd 738 mode = FREEFORM;
elmbed 17:d8b901d791fd 739 state_p = START_P;
elmbed 17:d8b901d791fd 740 clearCones();
elmbed 18:affef3a7db2a 741 //find_cones();
elmbed 17:d8b901d791fd 742 break;
elmbed 17:d8b901d791fd 743 case 'p':
elmbed 17:d8b901d791fd 744 if(value == 0)
elmbed 17:d8b901d791fd 745 {
elmbed 18:affef3a7db2a 746 writeToPhone("\r\n");
elmbed 18:affef3a7db2a 747 writeToPhone("Running pattern %d\r\n", active_sequence + 1);
elmbed 18:affef3a7db2a 748
elmbed 17:d8b901d791fd 749 mode = PATTERN;
elmbed 17:d8b901d791fd 750 state_p = START_P;
elmbed 17:d8b901d791fd 751 active_cone = 0;
elmbed 18:affef3a7db2a 752
elmbed 17:d8b901d791fd 753 clearCones();
elmbed 17:d8b901d791fd 754 }
elmbed 17:d8b901d791fd 755 else
elmbed 17:d8b901d791fd 756 {
elmbed 18:affef3a7db2a 757 writeToPhone("Selected pattern %d\r\n", value);
elmbed 18:affef3a7db2a 758
elmbed 17:d8b901d791fd 759 if(value <= SEQUENCES && value > 0)
elmbed 17:d8b901d791fd 760 {
elmbed 17:d8b901d791fd 761 active_sequence = value - 1;
elmbed 17:d8b901d791fd 762 cones = (uint8_t*)cone_table + (value-1)*STATIONS;
elmbed 17:d8b901d791fd 763 times = (uint16_t*)time_table + (value-1)*STATIONS;
elmbed 17:d8b901d791fd 764 masks = (uint8_t*)mask_table + (value-1)*STATIONS;
elmbed 17:d8b901d791fd 765 }
elmbed 17:d8b901d791fd 766 else
elmbed 17:d8b901d791fd 767 {
AntonLS 41:dee3fd34e37a 768 writeToPhone("This pattern is not available. Please select a value between 1 and %d\r\n", SEQUENCES);
elmbed 17:d8b901d791fd 769 }
elmbed 17:d8b901d791fd 770 }
elmbed 17:d8b901d791fd 771 break;
AntonLS 41:dee3fd34e37a 772 case 'P':
AntonLS 41:dee3fd34e37a 773 if(value != 0)
AntonLS 41:dee3fd34e37a 774 {
AntonLS 41:dee3fd34e37a 775 if(value <= SEQUENCES && value > 0)
AntonLS 41:dee3fd34e37a 776 {
AntonLS 41:dee3fd34e37a 777 active_sequence = value - 1;
AntonLS 41:dee3fd34e37a 778 cones = (uint8_t*)cone_table + (value-1)*STATIONS;
AntonLS 41:dee3fd34e37a 779 times = (uint16_t*)time_table + (value-1)*STATIONS;
AntonLS 41:dee3fd34e37a 780 masks = (uint8_t*)mask_table + (value-1)*STATIONS;
AntonLS 41:dee3fd34e37a 781
AntonLS 41:dee3fd34e37a 782 // Side effect: Also sets current station to 1:
AntonLS 41:dee3fd34e37a 783 station = 1;
AntonLS 41:dee3fd34e37a 784 }
AntonLS 41:dee3fd34e37a 785 else
AntonLS 41:dee3fd34e37a 786 {
AntonLS 41:dee3fd34e37a 787 writeToPhone("Only from 1 to %d\r\n", SEQUENCES);
AntonLS 41:dee3fd34e37a 788 }
AntonLS 41:dee3fd34e37a 789 }
AntonLS 41:dee3fd34e37a 790 else // P; or P0;
AntonLS 41:dee3fd34e37a 791 {
AntonLS 41:dee3fd34e37a 792 writeToPhone("Nothing done\r\n");
AntonLS 41:dee3fd34e37a 793 }
AntonLS 41:dee3fd34e37a 794 break;
elmbed 17:d8b901d791fd 795 case 's':
AntonLS 41:dee3fd34e37a 796 writeToPhone("Selected station %d\r\n", value);
AntonLS 41:dee3fd34e37a 797 case 'S':
elmbed 17:d8b901d791fd 798 station = value;
elmbed 17:d8b901d791fd 799 break;
elmbed 17:d8b901d791fd 800 case 'd':
elmbed 18:affef3a7db2a 801 if(value == 0){
elmbed 17:d8b901d791fd 802 logging = false;
elmbed 17:d8b901d791fd 803 m->value = 0;
elmbed 17:d8b901d791fd 804 dist_timeout = micros() + 2000000;
elmbed 17:d8b901d791fd 805 }
elmbed 18:affef3a7db2a 806 if(value == 1){
elmbed 17:d8b901d791fd 807 logging = true;
elmbed 17:d8b901d791fd 808 m->value = 1;
elmbed 17:d8b901d791fd 809 }
elmbed 17:d8b901d791fd 810 m->command = 'd';
elmbed 17:d8b901d791fd 811 m->cone = TRILAT_CONE;
elmbed 17:d8b901d791fd 812 ta.send(m);
elmbed 18:affef3a7db2a 813 //Serial.print("Sent d");
elmbed 18:affef3a7db2a 814 //Serial.println(value);
elmbed 17:d8b901d791fd 815 break;
elmbed 17:d8b901d791fd 816 case 'c':
AntonLS 41:dee3fd34e37a 817 writeToPhone("Station %d will be cone %d\r\n", station, value);
AntonLS 41:dee3fd34e37a 818 case 'C':
elmbed 17:d8b901d791fd 819 c = value;
elmbed 18:affef3a7db2a 820 if(station <= STATIONS && station > 0)cones[station-1] = c;
elmbed 17:d8b901d791fd 821 break;
elmbed 17:d8b901d791fd 822 case 't':
elmbed 17:d8b901d791fd 823 t = (uint16_t)value;
elmbed 17:d8b901d791fd 824 remainder = t%1000;
AntonLS 19:afcbb425b3cf 825 writeToPhone("Station %d split time is: %d.%03d seconds.\r\n", station, t/1000, remainder);
AntonLS 41:dee3fd34e37a 826 case 'T':
AntonLS 41:dee3fd34e37a 827 t = (uint16_t)value;
AntonLS 41:dee3fd34e37a 828 // remainder = t%1000;
AntonLS 19:afcbb425b3cf 829 /// if(remainder < 100)writeToPhone("0");
AntonLS 19:afcbb425b3cf 830 /// if(remainder < 10)writeToPhone("0");
AntonLS 19:afcbb425b3cf 831 /// writeToPhone("%d seconds.\r\n",remainder);
elmbed 18:affef3a7db2a 832 if(station <= STATIONS && station > 0)times[station-1] = t;
elmbed 17:d8b901d791fd 833 break;
elmbed 17:d8b901d791fd 834 case 'l':
AntonLS 41:dee3fd34e37a 835 // l = 0;
elmbed 17:d8b901d791fd 836 l = (uint8_t)value;
elmbed 17:d8b901d791fd 837 masks[station-1] = l;
AntonLS 19:afcbb425b3cf 838 writeToPhone( "Station %d config bits: ", station );
AntonLS 19:afcbb425b3cf 839 writeBitsToPhone( l );
AntonLS 19:afcbb425b3cf 840 writeToPhone( "\r\n" );
elmbed 17:d8b901d791fd 841 break;
AntonLS 41:dee3fd34e37a 842 case 'B': // After setting bits, echo back station data.
AntonLS 41:dee3fd34e37a 843 l = (uint8_t)value;
AntonLS 41:dee3fd34e37a 844 masks[station-1] = l;
AntonLS 45:1eb335c00cb2 845 writeToPhone( "%c%02u;C%02u;T%05u;B%02x\r\n", (1==station) ? 'P' : 'S',
AntonLS 41:dee3fd34e37a 846 (1==station) ? active_sequence +1 : station,
AntonLS 41:dee3fd34e37a 847 cones[station-1], times[station-1], l );
AntonLS 41:dee3fd34e37a 848 break;
elmbed 17:d8b901d791fd 849 case 'q':
elmbed 17:d8b901d791fd 850 state_p = IDLE_P;
elmbed 17:d8b901d791fd 851 new_state = true; // force state reporting, even if we're already in IDLE
AntonLS 46:28c29ef61276 852 ta.pulse_off(); /// //
AntonLS 46:28c29ef61276 853 clearCones(); /// //
elmbed 17:d8b901d791fd 854 break;
elmbed 17:d8b901d791fd 855 case 'r':
elmbed 18:affef3a7db2a 856 //Serial.println(F(""));
AntonLS 39:b1f864b71318 857 // writeToPhone("Current pattern is %d:\r\n", active_sequence+1);
AntonLS 39:b1f864b71318 858 writeToPhone("Pattern is %d:\r\n", active_sequence+1); // PROTOCOL optimization
elmbed 18:affef3a7db2a 859 for(int i=0; i<STATIONS; i++){
AntonLS 39:b1f864b71318 860 // writeToPhone("Station %d: cone %d, ", i+1, cones[i]);
AntonLS 45:1eb335c00cb2 861 writeToPhone("S%02u,C%02u", i+1, cones[i]); // PROTOCOL optimization
elmbed 17:d8b901d791fd 862 split = times[i];
AntonLS 39:b1f864b71318 863 // printMsAsSeconds(split); // Removed for PROTOCOL optimization
elmbed 18:affef3a7db2a 864 //Serial.print(F("s timeout, lights: "));
AntonLS 39:b1f864b71318 865 // writeToPhone("s timeout, config bits: ");
AntonLS 45:1eb335c00cb2 866 writeToPhone(",T%05u", split); // PROTOCOL optimization
elmbed 17:d8b901d791fd 867 l = masks[i];
elmbed 17:d8b901d791fd 868 /*
elmbed 18:affef3a7db2a 869 if(l<0b10000000)
elmbed 18:affef3a7db2a 870 writeToPhone("0");
elmbed 18:affef3a7db2a 871 if(l<0b1000000)
elmbed 18:affef3a7db2a 872 writeToPhone("0");
elmbed 18:affef3a7db2a 873 if(l<0b100000)
elmbed 18:affef3a7db2a 874 writeToPhone("0");
elmbed 18:affef3a7db2a 875 if(l<0b10000)
elmbed 18:affef3a7db2a 876 writeToPhone("0");
elmbed 18:affef3a7db2a 877 if(l<0b1000)
elmbed 18:affef3a7db2a 878 writeToPhone("0");
elmbed 18:affef3a7db2a 879 if(l<0b100)
elmbed 18:affef3a7db2a 880 writeToPhone("0");
elmbed 18:affef3a7db2a 881 if(l<0b10)
elmbed 18:affef3a7db2a 882 writeToPhone("0");
elmbed 18:affef3a7db2a 883 */
AntonLS 39:b1f864b71318 884 // writeBitsToPhone( l, 3 ); // Removed for PROTOCOL optimization
AntonLS 39:b1f864b71318 885 writeToPhone(",B%02x", l); // PROTOCOL optimization
AntonLS 19:afcbb425b3cf 886 writeToPhone( "\r\n" );
elmbed 18:affef3a7db2a 887 //Serial.println(l, BIN);
elmbed 17:d8b901d791fd 888 }
elmbed 17:d8b901d791fd 889 break;
elmbed 17:d8b901d791fd 890 case 'u':
elmbed 17:d8b901d791fd 891 // let any pending messages clear
elmbed 18:affef3a7db2a 892 while(ta.get_buffer_size()){
elmbed 17:d8b901d791fd 893 ta.spin();
elmbed 17:d8b901d791fd 894 }
elmbed 18:affef3a7db2a 895 if(value == 1){
elmbed 18:affef3a7db2a 896 writeToPhone("Course leader!\r\n");
elmbed 17:d8b901d791fd 897 powerupCones(value);
elmbed 17:d8b901d791fd 898 ta.powerup(value);
elmbed 17:d8b901d791fd 899 }
elmbed 18:affef3a7db2a 900 if(value == 2){
elmbed 18:affef3a7db2a 901 writeToPhone("Split leader!\r\n");
elmbed 17:d8b901d791fd 902 powerupCones(value);
elmbed 18:affef3a7db2a 903 //ta.powerup(value);
elmbed 17:d8b901d791fd 904 }
elmbed 18:affef3a7db2a 905 if(value > 10 && value < 5000){
elmbed 17:d8b901d791fd 906 ta.beep(value);
elmbed 17:d8b901d791fd 907 }
elmbed 17:d8b901d791fd 908 break;
elmbed 17:d8b901d791fd 909 case 'w':
elmbed 18:affef3a7db2a 910 if(value > 0 && value <= SEQUENCES){
elmbed 17:d8b901d791fd 911 length = STATIONS;
elmbed 17:d8b901d791fd 912 offset = (value - 1) * STATIONS;
elmbed 18:affef3a7db2a 913 writeToPhone("Saved sequence %d\r\n", value);
elmbed 17:d8b901d791fd 914 }
elmbed 18:affef3a7db2a 915 else{
elmbed 17:d8b901d791fd 916 length = STATIONS * SEQUENCES;
elmbed 17:d8b901d791fd 917 offset = 0;
elmbed 18:affef3a7db2a 918 writeToPhone("Saved all sequences.\r\n");
elmbed 17:d8b901d791fd 919 }
elmbed 18:affef3a7db2a 920 for(i=offset;i<length+offset;i++){
elmbed 18:affef3a7db2a 921 //eeprom_update_byte(addressConeTable + i, cone_table[i]);
elmbed 18:affef3a7db2a 922 //eeprom_update_byte(addressMaskTable + i, mask_table[i]);
elmbed 18:affef3a7db2a 923 //eeprom_update_word(addressTimeTable + i, time_table[i]);
elmbed 17:d8b901d791fd 924 }
elmbed 17:d8b901d791fd 925 break;
elmbed 17:d8b901d791fd 926 case 'x':
elmbed 17:d8b901d791fd 927 resetSensors();
AntonLS 46:28c29ef61276 928 ta.resetTouch();
elmbed 17:d8b901d791fd 929 break;
elmbed 17:d8b901d791fd 930
elmbed 17:d8b901d791fd 931 case 'z':
elmbed 17:d8b901d791fd 932 find_cones();
elmbed 18:affef3a7db2a 933 /*m->value = value;
elmbed 17:d8b901d791fd 934 m->command = 'z';
elmbed 17:d8b901d791fd 935 m->cone = 2;
elmbed 18:affef3a7db2a 936 Serial.println("sending...");
elmbed 17:d8b901d791fd 937 ta.send(m);
elmbed 18:affef3a7db2a 938 Serial.println("sent");*/
elmbed 17:d8b901d791fd 939 break;
elmbed 17:d8b901d791fd 940 }
elmbed 17:d8b901d791fd 941 }
elmbed 23:26f27c462976 942
elmbed 23:26f27c462976 943 static patternState_t stateFromCone(uint8_t cone)
elmbed 17:d8b901d791fd 944 {
elmbed 17:d8b901d791fd 945 if(cone == 0 || index == STATIONS)
elmbed 17:d8b901d791fd 946 return SUCCESS_P;
elmbed 17:d8b901d791fd 947 if(cone == 1)
elmbed 17:d8b901d791fd 948 return ACTIVE_TARGET_P;
elmbed 17:d8b901d791fd 949
elmbed 17:d8b901d791fd 950 return WAITING_P;
elmbed 17:d8b901d791fd 951 }
elmbed 17:d8b901d791fd 952
elmbed 23:26f27c462976 953 static void printSplit(unsigned long timer)
elmbed 17:d8b901d791fd 954 {
elmbed 17:d8b901d791fd 955 if(tag_start)
elmbed 17:d8b901d791fd 956 {
elmbed 17:d8b901d791fd 957 //DEBUG("Sequence started at cone ");
elmbed 17:d8b901d791fd 958 //DEBUG("%d",active_cone);
elmbed 17:d8b901d791fd 959 //DEBUG(" (");
elmbed 17:d8b901d791fd 960 printMsAsSeconds(timer);
elmbed 17:d8b901d791fd 961 //DEBUG(" seconds).\n");
elmbed 17:d8b901d791fd 962 tag_start = false;
elmbed 17:d8b901d791fd 963 }
elmbed 17:d8b901d791fd 964 else
elmbed 17:d8b901d791fd 965 {
elmbed 17:d8b901d791fd 966 //DEBUG("Target cone is: ");
elmbed 17:d8b901d791fd 967 //DEBUG("%d",active_cone);
elmbed 17:d8b901d791fd 968 //DEBUG(", ");
elmbed 17:d8b901d791fd 969 printMsAsSeconds(timer);
elmbed 17:d8b901d791fd 970 //DEBUG(" split");
elmbed 17:d8b901d791fd 971 }
elmbed 17:d8b901d791fd 972 }
elmbed 17:d8b901d791fd 973
elmbed 23:26f27c462976 974 static uint8_t getRandomCone(void)
elmbed 17:d8b901d791fd 975 {
elmbed 40:dec5270e03e9 976 static uint8_t last_cone = 0;
elmbed 17:d8b901d791fd 977 uint8_t cone;
elmbed 40:dec5270e03e9 978 int counter = 0;
elmbed 17:d8b901d791fd 979
elmbed 17:d8b901d791fd 980 do
elmbed 17:d8b901d791fd 981 {
elmbed 40:dec5270e03e9 982 cone = (rand() % NUM_CONES);
elmbed 40:dec5270e03e9 983 ++cone;
elmbed 40:dec5270e03e9 984
elmbed 40:dec5270e03e9 985 if (cone == last_cone)
elmbed 40:dec5270e03e9 986 {
elmbed 40:dec5270e03e9 987 if (rand() % 2 == 1)
elmbed 40:dec5270e03e9 988 {
elmbed 40:dec5270e03e9 989 --cone;
elmbed 40:dec5270e03e9 990
elmbed 40:dec5270e03e9 991 if (cone <= 0)
elmbed 40:dec5270e03e9 992 {
elmbed 40:dec5270e03e9 993 cone = NUM_CONES;
elmbed 40:dec5270e03e9 994 }
elmbed 40:dec5270e03e9 995 }
elmbed 40:dec5270e03e9 996 else
elmbed 40:dec5270e03e9 997 {
elmbed 40:dec5270e03e9 998 ++cone;
elmbed 40:dec5270e03e9 999
elmbed 40:dec5270e03e9 1000 if (cone > NUM_CONES)
elmbed 40:dec5270e03e9 1001 {
elmbed 40:dec5270e03e9 1002 cone = 1;
elmbed 40:dec5270e03e9 1003 }
elmbed 40:dec5270e03e9 1004 }
elmbed 40:dec5270e03e9 1005 }
elmbed 17:d8b901d791fd 1006 }
elmbed 40:dec5270e03e9 1007 while(active_cones[cone] == false && ++counter < 10);
elmbed 17:d8b901d791fd 1008
elmbed 40:dec5270e03e9 1009 if (!active_cones[cone])
elmbed 40:dec5270e03e9 1010 {
elmbed 40:dec5270e03e9 1011 for (int i = 0; i < NUM_CONES; ++i)
elmbed 40:dec5270e03e9 1012 {
elmbed 40:dec5270e03e9 1013 if (i == last_cone || !active_cones[cone])
elmbed 40:dec5270e03e9 1014 {
elmbed 40:dec5270e03e9 1015 continue;
elmbed 40:dec5270e03e9 1016 }
elmbed 40:dec5270e03e9 1017
elmbed 40:dec5270e03e9 1018 cone = i;
elmbed 40:dec5270e03e9 1019 break;
elmbed 40:dec5270e03e9 1020 }
elmbed 40:dec5270e03e9 1021 }
elmbed 40:dec5270e03e9 1022
elmbed 40:dec5270e03e9 1023 last_cone = cone;
elmbed 17:d8b901d791fd 1024 return cone;
elmbed 17:d8b901d791fd 1025 }
elmbed 17:d8b901d791fd 1026
elmbed 23:26f27c462976 1027 static void clearCones(void)
elmbed 17:d8b901d791fd 1028 {
elmbed 38:76e49d045a3b 1029 #if 1
elmbed 17:d8b901d791fd 1030 uint8_t i;
elmbed 17:d8b901d791fd 1031 m->command = 'q';
elmbed 17:d8b901d791fd 1032
elmbed 17:d8b901d791fd 1033 for(i=2;i<NUM_CONES+1;i++)
elmbed 17:d8b901d791fd 1034 {
elmbed 17:d8b901d791fd 1035 m->cone = i;
elmbed 17:d8b901d791fd 1036 if(active_cones[i])
elmbed 17:d8b901d791fd 1037 ta.send(m);
elmbed 17:d8b901d791fd 1038 active_cones[i] = false;
elmbed 17:d8b901d791fd 1039 //ta.send("q", i);
elmbed 17:d8b901d791fd 1040 }
elmbed 17:d8b901d791fd 1041
elmbed 17:d8b901d791fd 1042 DEBUG("sent clear\r\n");
elmbed 23:26f27c462976 1043 #endif
elmbed 17:d8b901d791fd 1044 }
elmbed 17:d8b901d791fd 1045
elmbed 23:26f27c462976 1046 static void powerupCones(uint8_t sound)
elmbed 17:d8b901d791fd 1047 {
elmbed 23:26f27c462976 1048 #if 1
elmbed 17:d8b901d791fd 1049 uint8_t i;
elmbed 17:d8b901d791fd 1050 m->command = 'u';
elmbed 17:d8b901d791fd 1051 m->value = sound;
elmbed 17:d8b901d791fd 1052
elmbed 17:d8b901d791fd 1053 if(sound == 2)
elmbed 17:d8b901d791fd 1054 {
elmbed 28:8e74ddc4f70f 1055 if(active_cone == NODE_ID)
elmbed 17:d8b901d791fd 1056 {
elmbed 17:d8b901d791fd 1057 ta.powerup(sound);
elmbed 17:d8b901d791fd 1058 }
elmbed 17:d8b901d791fd 1059 else
elmbed 17:d8b901d791fd 1060 {
elmbed 17:d8b901d791fd 1061 m->cone = active_cone;
elmbed 17:d8b901d791fd 1062 ta.send(m);
elmbed 17:d8b901d791fd 1063 }
elmbed 17:d8b901d791fd 1064 }
elmbed 17:d8b901d791fd 1065 else
elmbed 17:d8b901d791fd 1066 {
elmbed 17:d8b901d791fd 1067 for(i=2;i<NUM_CONES+1;i++)
elmbed 17:d8b901d791fd 1068 {
elmbed 17:d8b901d791fd 1069 m->cone = i;
elmbed 17:d8b901d791fd 1070 if(active_cones[i])
elmbed 17:d8b901d791fd 1071 ta.send(m);
elmbed 17:d8b901d791fd 1072 //ta.send("f", i);
elmbed 17:d8b901d791fd 1073 }
elmbed 17:d8b901d791fd 1074 }
elmbed 23:26f27c462976 1075 #endif
elmbed 17:d8b901d791fd 1076 //DEBUG("sent powerup");
elmbed 17:d8b901d791fd 1077 }
elmbed 17:d8b901d791fd 1078
elmbed 23:26f27c462976 1079 static void failCones(void)
elmbed 17:d8b901d791fd 1080 {
elmbed 38:76e49d045a3b 1081 #if 1
elmbed 17:d8b901d791fd 1082 uint8_t i;
elmbed 17:d8b901d791fd 1083 m->command = 'f';
elmbed 17:d8b901d791fd 1084
elmbed 17:d8b901d791fd 1085 for(i=2;i<NUM_CONES+1;i++)
elmbed 17:d8b901d791fd 1086 {
elmbed 17:d8b901d791fd 1087 m->cone = i;
elmbed 17:d8b901d791fd 1088
elmbed 17:d8b901d791fd 1089 if(active_cones[i])
elmbed 17:d8b901d791fd 1090 ta.send(m);
elmbed 17:d8b901d791fd 1091 //ta.send("f", i);
elmbed 17:d8b901d791fd 1092 }
elmbed 17:d8b901d791fd 1093
elmbed 17:d8b901d791fd 1094 while(ta.get_buffer_size())
elmbed 17:d8b901d791fd 1095 {
elmbed 17:d8b901d791fd 1096 ta.spin();
elmbed 17:d8b901d791fd 1097 }
elmbed 17:d8b901d791fd 1098
elmbed 17:d8b901d791fd 1099 //DEBUG("sent fail\n");
elmbed 23:26f27c462976 1100 #endif
elmbed 17:d8b901d791fd 1101 }
elmbed 17:d8b901d791fd 1102
elmbed 23:26f27c462976 1103 static void resetSensors(void)
elmbed 17:d8b901d791fd 1104 {
elmbed 38:76e49d045a3b 1105 #if 1
elmbed 17:d8b901d791fd 1106 uint8_t i;
elmbed 17:d8b901d791fd 1107 m->command = 'x';
elmbed 17:d8b901d791fd 1108
elmbed 17:d8b901d791fd 1109 for(i=2;i<NUM_CONES+1;i++)
elmbed 17:d8b901d791fd 1110 {
elmbed 17:d8b901d791fd 1111 m->cone = i;
elmbed 17:d8b901d791fd 1112 if(active_cones[i])
elmbed 17:d8b901d791fd 1113 ta.send(m);
elmbed 17:d8b901d791fd 1114 //ta.send("f", i);
elmbed 17:d8b901d791fd 1115 }
elmbed 17:d8b901d791fd 1116
elmbed 17:d8b901d791fd 1117 DEBUG("sent sensor reset\n");
elmbed 23:26f27c462976 1118 #endif
elmbed 17:d8b901d791fd 1119 }
elmbed 17:d8b901d791fd 1120
elmbed 23:26f27c462976 1121 static void successCones(void)
elmbed 17:d8b901d791fd 1122 {
elmbed 38:76e49d045a3b 1123 #if 1
elmbed 17:d8b901d791fd 1124 uint8_t i;
elmbed 17:d8b901d791fd 1125 m->command = 's';
elmbed 17:d8b901d791fd 1126
elmbed 17:d8b901d791fd 1127 for(i=2;i<NUM_CONES+1;i++)
elmbed 17:d8b901d791fd 1128 {
elmbed 17:d8b901d791fd 1129 m->cone = i;
elmbed 17:d8b901d791fd 1130 if(active_cones[i])
elmbed 17:d8b901d791fd 1131 ta.send(m);
elmbed 17:d8b901d791fd 1132 //ta.send("s", i);
elmbed 17:d8b901d791fd 1133 }
elmbed 17:d8b901d791fd 1134
elmbed 17:d8b901d791fd 1135 while(ta.get_buffer_size())
elmbed 17:d8b901d791fd 1136 {
elmbed 17:d8b901d791fd 1137 ta.spin();
elmbed 17:d8b901d791fd 1138 }
elmbed 17:d8b901d791fd 1139
elmbed 17:d8b901d791fd 1140 //DEBUG("sent success\n");
elmbed 23:26f27c462976 1141 #endif
elmbed 17:d8b901d791fd 1142 }
elmbed 17:d8b901d791fd 1143
elmbed 23:26f27c462976 1144 static void find_cones(void)
elmbed 17:d8b901d791fd 1145 {
elmbed 17:d8b901d791fd 1146 while(ta.get_buffer_size())
elmbed 23:26f27c462976 1147 {
elmbed 17:d8b901d791fd 1148 ta.spin(); // wait for all messages to leave queue
elmbed 28:8e74ddc4f70f 1149 }
elmbed 17:d8b901d791fd 1150
elmbed 23:26f27c462976 1151 ta.beep_off();
elmbed 17:d8b901d791fd 1152 uint8_t i;
elmbed 17:d8b901d791fd 1153 m->command = 'z';
elmbed 28:8e74ddc4f70f 1154
elmbed 17:d8b901d791fd 1155 lonely = true;
elmbed 17:d8b901d791fd 1156
elmbed 29:ae208b014987 1157 writeToPhone("FC\r\n");
elmbed 29:ae208b014987 1158
elmbed 29:ae208b014987 1159 int retry_count = 0;
AntonLS 32:64e5d7340d82 1160
elmbed 26:40a0c775ff27 1161 for(i = 2; i < NUM_CONES + 1; ++i)
elmbed 17:d8b901d791fd 1162 {
elmbed 29:ae208b014987 1163 retry_count = 0;
elmbed 29:ae208b014987 1164 go_again:
elmbed 17:d8b901d791fd 1165 active_cones[i] = false;
elmbed 17:d8b901d791fd 1166 m->cone = i;
elmbed 17:d8b901d791fd 1167 ta.send_immediate(m);
elmbed 17:d8b901d791fd 1168
elmbed 17:d8b901d791fd 1169 unsigned long st = millis();
elmbed 29:ae208b014987 1170 unsigned long current = 0L;
elmbed 29:ae208b014987 1171 unsigned long delta = 0L;
elmbed 17:d8b901d791fd 1172
AntonLS 32:64e5d7340d82 1173 writeToPhone("S: %lu F: %d\r\n", st, i); /// DEBUG-only message
elmbed 23:26f27c462976 1174
elmbed 17:d8b901d791fd 1175 while(1)
elmbed 17:d8b901d791fd 1176 {
elmbed 23:26f27c462976 1177 current = millis();
elmbed 23:26f27c462976 1178 delta = current - st;
elmbed 17:d8b901d791fd 1179
elmbed 35:c1405da88d3a 1180 if(delta > 300L)
elmbed 23:26f27c462976 1181 {
elmbed 29:ae208b014987 1182 writeToPhone("FT: %d %lu\r\n", i, current);
elmbed 29:ae208b014987 1183
elmbed 29:ae208b014987 1184 if (++retry_count < 3)
elmbed 29:ae208b014987 1185 {
elmbed 29:ae208b014987 1186 goto go_again;
elmbed 29:ae208b014987 1187 }
elmbed 29:ae208b014987 1188 else
elmbed 29:ae208b014987 1189 {
elmbed 29:ae208b014987 1190 break;
elmbed 29:ae208b014987 1191 }
elmbed 28:8e74ddc4f70f 1192 }
elmbed 17:d8b901d791fd 1193 if(ta.recieve(m_in))
elmbed 17:d8b901d791fd 1194 {
elmbed 17:d8b901d791fd 1195 lonely = false;
elmbed 17:d8b901d791fd 1196 active_cones[m_in->cone] = true;
elmbed 17:d8b901d791fd 1197
elmbed 29:ae208b014987 1198 writeToPhone("FS: %d\r\n", m_in->cone);
elmbed 17:d8b901d791fd 1199 break;
elmbed 17:d8b901d791fd 1200 }
elmbed 17:d8b901d791fd 1201 }
elmbed 29:ae208b014987 1202
elmbed 29:ae208b014987 1203 wait_us(50);
elmbed 17:d8b901d791fd 1204 }
elmbed 17:d8b901d791fd 1205
elmbed 26:40a0c775ff27 1206 writeToPhone("available cones are: (1");
elmbed 17:d8b901d791fd 1207
elmbed 26:40a0c775ff27 1208 for(i = 2; i < NUM_CONES + 1; ++i)
elmbed 17:d8b901d791fd 1209 {
elmbed 17:d8b901d791fd 1210 if(active_cones[i])
elmbed 17:d8b901d791fd 1211 {
elmbed 26:40a0c775ff27 1212 writeToPhone(", %d", i);
elmbed 17:d8b901d791fd 1213 }
elmbed 17:d8b901d791fd 1214 }
elmbed 26:40a0c775ff27 1215
elmbed 26:40a0c775ff27 1216 writeToPhone(")\r\n");
elmbed 17:d8b901d791fd 1217 }
elmbed 17:d8b901d791fd 1218
elmbed 23:26f27c462976 1219 static void printMsAsSeconds(unsigned long number)
elmbed 17:d8b901d791fd 1220 {
elmbed 17:d8b901d791fd 1221 uint16_t remainder;
elmbed 17:d8b901d791fd 1222
elmbed 17:d8b901d791fd 1223 remainder = number%1000;
AntonLS 19:afcbb425b3cf 1224
AntonLS 39:b1f864b71318 1225 writeToPhone( "%d.%03d", number/1000, remainder ); /// Needs to stay without newline.
elmbed 17:d8b901d791fd 1226 }
elmbed 17:d8b901d791fd 1227
elmbed 23:26f27c462976 1228 static void spinButtons(void)
elmbed 17:d8b901d791fd 1229 {
elmbed 17:d8b901d791fd 1230 static inputState_t last_state = IDLE_I;
elmbed 17:d8b901d791fd 1231 static bool first_i; // first should be true when we first enter a state (even if we just exited the same state)
elmbed 17:d8b901d791fd 1232 static Event event;
elmbed 17:d8b901d791fd 1233 static uint8_t sequence = 0;
elmbed 17:d8b901d791fd 1234 static unsigned long start = 0;
elmbed 17:d8b901d791fd 1235 uint8_t section = 0;
elmbed 17:d8b901d791fd 1236
elmbed 17:d8b901d791fd 1237 //uint8_t buttons;
elmbed 17:d8b901d791fd 1238
elmbed 17:d8b901d791fd 1239 //timer = millis() - start;
elmbed 17:d8b901d791fd 1240 if(millis() > 500)
elmbed 17:d8b901d791fd 1241 event = getInputEvent();
elmbed 17:d8b901d791fd 1242
elmbed 17:d8b901d791fd 1243 if(event.type == Event::press)
elmbed 17:d8b901d791fd 1244 {
elmbed 17:d8b901d791fd 1245 in_menu = true;
elmbed 17:d8b901d791fd 1246 state_i = MENU_I;
elmbed 17:d8b901d791fd 1247 }
elmbed 17:d8b901d791fd 1248
elmbed 17:d8b901d791fd 1249 first_i = false;
elmbed 17:d8b901d791fd 1250
elmbed 17:d8b901d791fd 1251 if(last_state != state_i)
elmbed 17:d8b901d791fd 1252 {
elmbed 17:d8b901d791fd 1253 //if(state_i == IDLE_I)////////////DEBUG.println(F("");
elmbed 17:d8b901d791fd 1254 //if(state_i == RUNNING_I)//////////////DEBUG.println(F("State is WAITING");
elmbed 17:d8b901d791fd 1255 // need to print menu timeout?
elmbed 17:d8b901d791fd 1256 if(state_i == MENU_I)
elmbed 17:d8b901d791fd 1257 ////DEBUG("Menu\n");
elmbed 17:d8b901d791fd 1258 if(state_i == PATTERN_SELECT_I)
elmbed 17:d8b901d791fd 1259 ////DEBUG("Choosing pattern");
elmbed 17:d8b901d791fd 1260 first_i = true;
elmbed 17:d8b901d791fd 1261 }
elmbed 17:d8b901d791fd 1262
elmbed 17:d8b901d791fd 1263 last_state = state_i;
elmbed 17:d8b901d791fd 1264
elmbed 17:d8b901d791fd 1265 if(state_i == RUNNING_I)
elmbed 17:d8b901d791fd 1266 in_menu = false;
elmbed 17:d8b901d791fd 1267
elmbed 17:d8b901d791fd 1268 switch(state_i)
elmbed 17:d8b901d791fd 1269 {
elmbed 17:d8b901d791fd 1270 case IDLE_I:
elmbed 17:d8b901d791fd 1271 // display something distinctive
elmbed 17:d8b901d791fd 1272 if(event.type == Event::tap)
elmbed 17:d8b901d791fd 1273 {
elmbed 17:d8b901d791fd 1274 state_i = RUNNING_I;
elmbed 17:d8b901d791fd 1275 //send 'p' or 'f' command as appropriate
elmbed 17:d8b901d791fd 1276 if(mode == FREEFORM)
elmbed 17:d8b901d791fd 1277 interpret('f', 0);
elmbed 17:d8b901d791fd 1278 else
elmbed 17:d8b901d791fd 1279 interpret('p', 0);
elmbed 17:d8b901d791fd 1280 }
elmbed 35:c1405da88d3a 1281
elmbed 17:d8b901d791fd 1282 break;
elmbed 17:d8b901d791fd 1283 case RUNNING_I:
elmbed 17:d8b901d791fd 1284 if(event.type == Event::finish)
elmbed 17:d8b901d791fd 1285 state_i = IDLE_I;
elmbed 17:d8b901d791fd 1286 break;
elmbed 17:d8b901d791fd 1287 case MENU_I:
elmbed 17:d8b901d791fd 1288 if(first_i)
elmbed 17:d8b901d791fd 1289 interpret('q', 0);
elmbed 17:d8b901d791fd 1290 // every 3 seconds we cycle through the menu
elmbed 17:d8b901d791fd 1291 // one option per second
elmbed 17:d8b901d791fd 1292 // light changes color and stays on for 500ms
elmbed 17:d8b901d791fd 1293 section = ((millis() - start)%3000)/500;
elmbed 17:d8b901d791fd 1294
elmbed 17:d8b901d791fd 1295 if(section == 0)
elmbed 17:d8b901d791fd 1296 ta.post_color(0xFF);
elmbed 17:d8b901d791fd 1297 if(section == 1)
elmbed 17:d8b901d791fd 1298 ta.post_color(0);
elmbed 17:d8b901d791fd 1299 if(section == 2)
elmbed 17:d8b901d791fd 1300 ta.post_color(0xFF00);
elmbed 17:d8b901d791fd 1301 if(section == 3)
elmbed 17:d8b901d791fd 1302 ta.post_color(0);
elmbed 17:d8b901d791fd 1303 if(section == 4)
elmbed 17:d8b901d791fd 1304 ta.post_color(0xFF0000);
elmbed 17:d8b901d791fd 1305 if(section == 5)
elmbed 17:d8b901d791fd 1306 ta.post_color(0);
elmbed 17:d8b901d791fd 1307 if(event.type == Event::tap)
elmbed 17:d8b901d791fd 1308 {
elmbed 17:d8b901d791fd 1309 // set state here based on current light color
elmbed 17:d8b901d791fd 1310 if(section < 2)
elmbed 17:d8b901d791fd 1311 {
elmbed 17:d8b901d791fd 1312 mode = FREEFORM;
elmbed 17:d8b901d791fd 1313 ta.post_color(0xFF);
elmbed 17:d8b901d791fd 1314 ////////DEBUG.println(F("Freeform mode.");
elmbed 17:d8b901d791fd 1315 state_i = IDLE_I;
elmbed 17:d8b901d791fd 1316 break;
elmbed 17:d8b901d791fd 1317 }
elmbed 17:d8b901d791fd 1318
elmbed 17:d8b901d791fd 1319 if(section < 4)
elmbed 17:d8b901d791fd 1320 {
elmbed 17:d8b901d791fd 1321 mode = PATTERN;
elmbed 17:d8b901d791fd 1322 ta.post_color(0xFF00);
elmbed 17:d8b901d791fd 1323 ////////DEBUG.println(F("Pattern mode.");
elmbed 17:d8b901d791fd 1324 state_i = IDLE_I;
elmbed 17:d8b901d791fd 1325 break;
elmbed 17:d8b901d791fd 1326 }
elmbed 17:d8b901d791fd 1327
elmbed 17:d8b901d791fd 1328 if(section < 6)
elmbed 17:d8b901d791fd 1329 {
elmbed 17:d8b901d791fd 1330 state_i = PATTERN_SELECT_I;
elmbed 17:d8b901d791fd 1331 ta.post_color(0xFF0000);
elmbed 17:d8b901d791fd 1332 break;
elmbed 17:d8b901d791fd 1333 }
elmbed 17:d8b901d791fd 1334 }
elmbed 17:d8b901d791fd 1335 break;
elmbed 17:d8b901d791fd 1336 case PATTERN_SELECT_I:
elmbed 17:d8b901d791fd 1337 if(first_i)
elmbed 17:d8b901d791fd 1338 {
elmbed 17:d8b901d791fd 1339 sequence = active_sequence;
elmbed 17:d8b901d791fd 1340 mode = PATTERN;
elmbed 17:d8b901d791fd 1341 //start = millis();
elmbed 17:d8b901d791fd 1342 }
elmbed 17:d8b901d791fd 1343 if(event.type == Event::tap)
elmbed 17:d8b901d791fd 1344 {
elmbed 17:d8b901d791fd 1345 ta.beep(50);
elmbed 17:d8b901d791fd 1346 if(event.value == 1 && sequence > 0)
elmbed 17:d8b901d791fd 1347 {
elmbed 17:d8b901d791fd 1348 sequence--;
elmbed 17:d8b901d791fd 1349 }
elmbed 17:d8b901d791fd 1350
elmbed 17:d8b901d791fd 1351 if(event.value == 2 && sequence < SEQUENCES - 1)
elmbed 17:d8b901d791fd 1352 {
elmbed 17:d8b901d791fd 1353 sequence++;
elmbed 17:d8b901d791fd 1354 }
elmbed 17:d8b901d791fd 1355
elmbed 17:d8b901d791fd 1356 if(event.value == 3)
elmbed 17:d8b901d791fd 1357 {
elmbed 17:d8b901d791fd 1358 interpret('p', sequence + 1);
elmbed 17:d8b901d791fd 1359 state_i = IDLE_I;
elmbed 17:d8b901d791fd 1360 }
elmbed 17:d8b901d791fd 1361
elmbed 17:d8b901d791fd 1362 if(event.value != 3)
elmbed 17:d8b901d791fd 1363 {
elmbed 17:d8b901d791fd 1364 ////DEBUG("Menu says: sequence ");
elmbed 17:d8b901d791fd 1365 ////DEBUG("%d\n",sequence + 1);
elmbed 17:d8b901d791fd 1366 }
elmbed 17:d8b901d791fd 1367 break;
elmbed 17:d8b901d791fd 1368 case TEACH_I:
elmbed 17:d8b901d791fd 1369 // not implemented yet
elmbed 17:d8b901d791fd 1370 break;
elmbed 17:d8b901d791fd 1371 default: break;
elmbed 17:d8b901d791fd 1372 }
elmbed 17:d8b901d791fd 1373 }
elmbed 17:d8b901d791fd 1374 }
elmbed 17:d8b901d791fd 1375
elmbed 23:26f27c462976 1376 static uint8_t checkButtons(void)
elmbed 17:d8b901d791fd 1377 {
elmbed 17:d8b901d791fd 1378 static unsigned long last_time = 0;
elmbed 17:d8b901d791fd 1379 //static uint8_t last = 0;
elmbed 17:d8b901d791fd 1380 static uint8_t buttons = 0;
elmbed 17:d8b901d791fd 1381
elmbed 17:d8b901d791fd 1382 // listen for commands from the buttons
elmbed 17:d8b901d791fd 1383 unsigned long time = millis();
elmbed 17:d8b901d791fd 1384 // only check every DEBOUNCE_MS to avoid jitter
elmbed 17:d8b901d791fd 1385 if(time - last_time > DEBOUNCE_MS)
elmbed 17:d8b901d791fd 1386 {
elmbed 17:d8b901d791fd 1387 last_time = time;
AntonLS 31:a6110950f385 1388 buttons = ta.buttons() | TA::buttonsRising;
AntonLS 31:a6110950f385 1389 TA::buttonsRising = 0;
elmbed 17:d8b901d791fd 1390 }
elmbed 17:d8b901d791fd 1391
elmbed 17:d8b901d791fd 1392 return buttons;
elmbed 17:d8b901d791fd 1393 }
elmbed 17:d8b901d791fd 1394
elmbed 23:26f27c462976 1395 static Event getInputEvent(void)
elmbed 17:d8b901d791fd 1396 {
elmbed 17:d8b901d791fd 1397 static uint8_t last_buttons = 0;
elmbed 17:d8b901d791fd 1398 static unsigned long time1 = 0;
elmbed 17:d8b901d791fd 1399 static unsigned long time2 = 0;
elmbed 17:d8b901d791fd 1400 static unsigned long time3 = 0;
elmbed 17:d8b901d791fd 1401 unsigned long duration = 0;
elmbed 17:d8b901d791fd 1402 uint8_t buttons = 0;
elmbed 17:d8b901d791fd 1403 Event event;
elmbed 17:d8b901d791fd 1404 event.type = Event::none;
elmbed 17:d8b901d791fd 1405 event.value = 0;
elmbed 17:d8b901d791fd 1406
elmbed 17:d8b901d791fd 1407 buttons = checkButtons();
elmbed 17:d8b901d791fd 1408 uint8_t rising = buttons & ~last_buttons;
elmbed 17:d8b901d791fd 1409 uint8_t falling = ~buttons & last_buttons;
elmbed 17:d8b901d791fd 1410
elmbed 17:d8b901d791fd 1411 /*if(rising){
elmbed 17:d8b901d791fd 1412 //DEBUG.print("Rising ");
elmbed 17:d8b901d791fd 1413 //DEBUG.println(rising);
elmbed 17:d8b901d791fd 1414 }
elmbed 17:d8b901d791fd 1415 if(falling){
elmbed 17:d8b901d791fd 1416 //DEBUG.print("Falling ");
elmbed 17:d8b901d791fd 1417 //DEBUG.println(falling);
elmbed 17:d8b901d791fd 1418 }*/
elmbed 17:d8b901d791fd 1419 if(rising & 0x01)
elmbed 17:d8b901d791fd 1420 time1 = millis();
elmbed 17:d8b901d791fd 1421 if(rising & 0x02)
elmbed 17:d8b901d791fd 1422 time2 = millis();
elmbed 17:d8b901d791fd 1423 if(rising & 0x04)
elmbed 17:d8b901d791fd 1424 time3 = millis();
elmbed 17:d8b901d791fd 1425
elmbed 17:d8b901d791fd 1426 // simultaneous falling edges will cause lower values to be ignored
elmbed 17:d8b901d791fd 1427 if(falling & 0x01)
elmbed 17:d8b901d791fd 1428 {
elmbed 17:d8b901d791fd 1429 duration = millis() - time1;
elmbed 17:d8b901d791fd 1430 event.value = 1;
elmbed 17:d8b901d791fd 1431 }
elmbed 17:d8b901d791fd 1432
elmbed 17:d8b901d791fd 1433 if(falling & 0x02)
elmbed 17:d8b901d791fd 1434 {
elmbed 17:d8b901d791fd 1435 duration = millis() - time2;
elmbed 17:d8b901d791fd 1436 event.value = 2;
elmbed 17:d8b901d791fd 1437 }
elmbed 17:d8b901d791fd 1438
elmbed 17:d8b901d791fd 1439 if(falling & 0x04)
elmbed 17:d8b901d791fd 1440 {
elmbed 17:d8b901d791fd 1441 duration = millis() - time3;
elmbed 17:d8b901d791fd 1442 event.value = 3;
elmbed 17:d8b901d791fd 1443 }
elmbed 17:d8b901d791fd 1444
elmbed 17:d8b901d791fd 1445 if(duration > 0)
elmbed 17:d8b901d791fd 1446 event.type = Event::tap;
elmbed 17:d8b901d791fd 1447 if(duration > 2000)
elmbed 17:d8b901d791fd 1448 event.type = Event::press;
elmbed 17:d8b901d791fd 1449
elmbed 17:d8b901d791fd 1450 // give feedback that we've waited lng enough for a press
elmbed 17:d8b901d791fd 1451 unsigned long t = millis() - time1;
elmbed 17:d8b901d791fd 1452
elmbed 17:d8b901d791fd 1453 if(2020 > t && t > 2000 && (buttons & 0x01))
elmbed 17:d8b901d791fd 1454 ta.beep(20);
elmbed 17:d8b901d791fd 1455
elmbed 17:d8b901d791fd 1456 t = millis() - time2;
elmbed 17:d8b901d791fd 1457
elmbed 17:d8b901d791fd 1458 if(2020 > t && t > 2000 && (buttons & 0x02))
elmbed 17:d8b901d791fd 1459 ta.beep(20);
elmbed 17:d8b901d791fd 1460
elmbed 17:d8b901d791fd 1461 t = millis() - time3;
elmbed 17:d8b901d791fd 1462
elmbed 17:d8b901d791fd 1463 if(2020 > t && t > 2000 && (buttons & 0x04))
elmbed 17:d8b901d791fd 1464 ta.beep(20);
elmbed 17:d8b901d791fd 1465
elmbed 17:d8b901d791fd 1466 if(event.type != Event::none)
elmbed 17:d8b901d791fd 1467 {
elmbed 17:d8b901d791fd 1468 //DEBUG("Event: ");
elmbed 17:d8b901d791fd 1469 if(event.type == Event::tap)
elmbed 17:d8b901d791fd 1470 ////DEBUG("tap, ");
elmbed 17:d8b901d791fd 1471 if(event.type == Event::press)
elmbed 17:d8b901d791fd 1472 ////DEBUG("press, ");
elmbed 17:d8b901d791fd 1473
elmbed 17:d8b901d791fd 1474 uint8_t val = event.value;
elmbed 17:d8b901d791fd 1475 //DEBUG("%d\n",val);
elmbed 17:d8b901d791fd 1476 //////DEBUG.println(duration);
elmbed 17:d8b901d791fd 1477 }
elmbed 17:d8b901d791fd 1478
elmbed 17:d8b901d791fd 1479 last_buttons = buttons;
elmbed 17:d8b901d791fd 1480 return event;
elmbed 17:d8b901d791fd 1481 }
elmbed 18:affef3a7db2a 1482 #endif
elmbed 18:affef3a7db2a 1483
elmbed 18:affef3a7db2a 1484 #endif