Andriy Makukha / Mbed 2 deprecated football_project_wo_output

Dependencies:   mbed

Fork of football_project by MZJ

Committer:
elmbed
Date:
Sat Jan 16 19:11:49 2016 +0000
Revision:
60:d1fad57e8bfb
Parent:
59:297133497153
Child:
61:dd7002ceea96
Buggy pattern mode

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