Andriy Makukha / Mbed 2 deprecated football_project_wo_output

Dependencies:   mbed

Fork of football_project by MZJ

Committer:
elmbed
Date:
Sat Jan 09 11:12:29 2016 +0000
Revision:
40:dec5270e03e9
Parent:
39:b1f864b71318
Child:
42:ed38b8671e43
Free form random sort of working (not very random)

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