Andriy Makukha / Mbed 2 deprecated football_project_wo_output

Dependencies:   mbed

Fork of football_project by MZJ

Committer:
AntonLS
Date:
Sun Apr 03 08:56:32 2016 +0000
Revision:
75:1b357bee1839
Parent:
72:84365ba93d6b
Prevent repeated BAD CRC on ACK msg.  Response added for u beep cmd to prevent BT buffer problem.  New radio-send flush methods.

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