Andriy Makukha / Mbed 2 deprecated football_project_wo_output

Dependencies:   mbed

Fork of football_project by MZJ

Committer:
AntonLS
Date:
Tue Jan 19 07:25:15 2016 +0000
Revision:
66:18c214707b0c
Parent:
62:9b34dc1b265d
Child:
67:5650f461722a
Misc. tweaks.

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