blackbox/main.c

changeset 46
d200e3d8a550
parent 45
da820f138498
child 47
34ac9f92bc1e
equal deleted inserted replaced
45:da820f138498 46:d200e3d8a550
18 char prepare[] PROGMEM="!RACE PREPARE\n"; 18 char prepare[] PROGMEM="!RACE PREPARE\n";
19 char countdownstart[] PROGMEM="!COUNTDOWN\n"; 19 char countdownstart[] PROGMEM="!COUNTDOWN\n";
20 char racestart[] PROGMEM="!RACE START\n"; 20 char racestart[] PROGMEM="!RACE START\n";
21 21
22 typedef union { 22 typedef union {
23 uint32_t u32; 23 uint32_t value;
24 uint16_t word[2]; // high, low word 24 uint16_t word[2]; // high, low word
25 uint8_t byte[4]; // all four bytes 25 uint8_t byte[4]; // all four bytes
26 } u32; 26 } u32;
27
28 #define MAX_SLOTS 6
29 typedef struct {
30 uint8_t speedlimit, fuel, laps;
31 uint16_t jumpstart_time;
32 u32 lap_time_start, lap_time;
33 } cardata;
27 34
28 static unsigned char s[10]; 35 static unsigned char s[10];
29 static uint8_t countdown, countdown_loops; 36 static uint8_t countdown, countdown_loops;
30 uint8_t mode = 0; 37 uint8_t mode = 0;
31 // valid race modes: 38 // valid race modes:
32 // 0: free drive / idle 39 // 0: free drive / idle
33 // 1: waiting for countdown start 40 // 1: waiting for countdown start
34 // 2: race countdown initiated 41 // 2: race countdown initiated
35 // 3: Race start condition 42 // 3: Race start condition
36 43
37
38 #define MAX_SLOTS 6
39 volatile u32 sysclk; 44 volatile u32 sysclk;
40 volatile uint8_t sysclk_packettimer = 0; 45 volatile uint8_t sysclk_packettimer = 0;
41 46 volatile cardata slot[MAX_SLOTS];
42 volatile uint8_t speedlimit[MAX_SLOTS];
43 volatile uint8_t fuel[MAX_SLOTS];
44 volatile uint16_t jumpstart_time[MAX_SLOTS];
45
46 volatile uint16_t lap_time_start_low[MAX_SLOTS];
47 volatile uint16_t lap_time_start_high[MAX_SLOTS];
48 volatile uint16_t lap_time_low[MAX_SLOTS];
49 volatile uint16_t lap_time_high[MAX_SLOTS];
50 47
51 volatile uint16_t car0, car1; 48 volatile uint16_t car0, car1;
52 volatile uint16_t car0_new, car0_old; 49 volatile uint16_t car0_new, car0_old;
53 volatile uint16_t car1_new, car1_old; 50 volatile uint16_t car1_new, car1_old;
54 uint8_t car0_state, car1_state; 51 uint8_t car0_state, car1_state;
117 114
118 case 'L': // Limit maximum speed for a car 115 case 'L': // Limit maximum speed for a car
119 tmp = buffer[2]-'0'; 116 tmp = buffer[2]-'0';
120 if (tmp > 9) 117 if (tmp > 9)
121 tmp = buffer[2]-'A'+10; 118 tmp = buffer[2]-'A'+10;
122 speedlimit[buffer[1]-'0'] = tmp; 119 slot[buffer[1]-'0'].speedlimit = tmp;
123 RS232_puts_p(ok); 120 RS232_puts_p(ok);
124 break; 121 break;
125 122
126 case 'I': // get Information data (incl. important global parameter dump) 123 case 'I': // get Information data (incl. important global parameter dump)
127 RS232_puts(VERSION); 124 RS232_puts(VERSION);
128 RS232_putc(':'); 125 RS232_putc(':');
129 for (tmp=0;tmp<MAX_SLOTS;tmp++) RS232_putc(speedlimit[tmp]); // output speed limits 126 for (tmp=0;tmp<MAX_SLOTS;tmp++) RS232_putc(slot[tmp].speedlimit); // output speed limits
130 RS232_putc(':'); 127 RS232_putc(':');
131 for (tmp=0;tmp<MAX_SLOTS;tmp++) { 128 for (tmp=0;tmp<MAX_SLOTS;tmp++) {
132 itoa(fuel[tmp], s, 16); 129 itoa(slot[tmp].fuel, s, 16);
133 RS232_putc(s); // output fuel levels (0=empty, 100=full, 0xff=no fuel option) 130 RS232_putc(s); // output fuel levels (0=empty, 100=full, 0xff=no fuel option)
134 RS232_putc(','); 131 RS232_putc(',');
135 } 132 }
136 RS232_putc(':'); 133 RS232_putc(':');
137 for (tmp=0;tmp<MAX_SLOTS;tmp++) { 134 for (tmp=0;tmp<MAX_SLOTS;tmp++) {
138 itoa(jumpstart_time[tmp], s, 16); 135 itoa(slot[tmp].jumpstart_time, s, 16);
139 RS232_puts(s); // output jumpstart times 136 RS232_puts(s); // output jumpstart times
140 RS232_putc(','); 137 RS232_putc(',');
141 } 138 }
142 RS232_putc(':'); 139 RS232_putc(':');
143 RS232_putc('\n'); 140 RS232_putc('\n');
153 } 150 }
154 } 151 }
155 152
156 153
157 void jumpstart(uint8_t controller) { 154 void jumpstart(uint8_t controller) {
158 if (jumpstart_time[controller] == 0) { 155 if (slot[controller].jumpstart_time == 0) {
159 jumpstart_time[controller] = sysclk.word[1]; // low word 156 slot[controller].jumpstart_time = sysclk.word[0]; // low word
160 RS232_putc('~'); 157 RS232_putc('~');
161 RS232_putc('0'-controller); 158 RS232_putc('0'-controller);
162 RS232_putc(','); 159 RS232_putc(':');
163 itoa(jumpstart_time[controller], s, 16); 160 itoa(slot[controller].jumpstart_time, s, 16);
164 RS232_puts(s); 161 RS232_puts(s);
165 RS232_putc('\n'); 162 RS232_putc('\n');
166 } 163 }
167 164
168 } 165 }
173 uint16_t tmp = 0; 170 uint16_t tmp = 0;
174 switch (controller) { 171 switch (controller) {
175 case 0: 172 case 0:
176 if (mode!=1) tmp = ((getADC(CONTROLLER1_SPEED) / CONTROLLER_DIVISOR) & 0x0F); 173 if (mode!=1) tmp = ((getADC(CONTROLLER1_SPEED) / CONTROLLER_DIVISOR) & 0x0F);
177 if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; } 174 if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; }
178 if (tmp > speedlimit[controller]) tmp = speedlimit[controller]; 175 if (tmp > slot[controller].speedlimit) tmp = slot[controller].speedlimit;
179 tmp = tmp << 1; 176 tmp = tmp << 1;
180 if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER1_SW)) != 0) { 177 if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER1_SW)) != 0) {
181 tmp |= (1<<5); 178 tmp |= (1<<5);
182 if (mode == 0) LED(1,0); 179 if (mode == 0) LED(1,0);
183 } else if (mode == 0) LED(1,1); 180 } else if (mode == 0) LED(1,1);
184 break; 181 break;
185 case 1: 182 case 1:
186 if (mode!=1) tmp = ((getADC(CONTROLLER2_SPEED) / CONTROLLER_DIVISOR) & 0x0F); 183 if (mode!=1) tmp = ((getADC(CONTROLLER2_SPEED) / CONTROLLER_DIVISOR) & 0x0F);
187 if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; } 184 if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; }
188 if (tmp > speedlimit[controller]) tmp = speedlimit[controller]; 185 if (tmp > slot[controller].speedlimit) tmp = slot[controller].speedlimit;
189 tmp = tmp << 1; 186 tmp = tmp << 1;
190 if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER2_SW)) != 0) { 187 if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER2_SW)) != 0) {
191 tmp |= (1<<5); 188 tmp |= (1<<5);
192 if (mode == 0) LED(2,0); 189 if (mode == 0) LED(2,0);
193 } else if (mode == 0) LED(2,1); 190 } else if (mode == 0) LED(2,1);
194 break; 191 break;
195 case 2: 192 case 2:
196 if (mode!=1) tmp = ((getADC(CONTROLLER3_SPEED) / CONTROLLER_DIVISOR) & 0x0F); 193 if (mode!=1) tmp = ((getADC(CONTROLLER3_SPEED) / CONTROLLER_DIVISOR) & 0x0F);
197 if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; } 194 if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; }
198 if (tmp > speedlimit[controller]) tmp = speedlimit[controller]; 195 if (tmp > slot[controller].speedlimit) tmp = slot[controller].speedlimit;
199 tmp = tmp << 1; 196 tmp = tmp << 1;
200 if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER3_SW)) != 0) { 197 if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER3_SW)) != 0) {
201 tmp |= (1<<5); 198 tmp |= (1<<5);
202 if (mode == 0) LED(4,0); 199 if (mode == 0) LED(4,0);
203 } else if (mode == 0) LED(4,1); 200 } else if (mode == 0) LED(4,1);
204 break; 201 break;
205 case 3: 202 case 3:
206 if (mode!=1) tmp = ((getADC(CONTROLLER4_SPEED) / CONTROLLER_DIVISOR) & 0x0F); 203 if (mode!=1) tmp = ((getADC(CONTROLLER4_SPEED) / CONTROLLER_DIVISOR) & 0x0F);
207 if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; } 204 if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; }
208 if (tmp > speedlimit[controller]) tmp = speedlimit[controller]; 205 if (tmp > slot[controller].speedlimit) tmp = slot[controller].speedlimit;
209 tmp = tmp << 1; 206 tmp = tmp << 1;
210 if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER4_SW)) != 0) { 207 if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER4_SW)) != 0) {
211 tmp |= (1<<5); 208 tmp |= (1<<5);
212 if (mode == 0) LED(5,0); 209 if (mode == 0) LED(5,0);
213 } else if (mode == 0) LED(5,1); 210 } else if (mode == 0) LED(5,1);
273 270
274 // reset both car counters to overflow 271 // reset both car counters to overflow
275 car0_old = TIMER1_500NS; 272 car0_old = TIMER1_500NS;
276 car1_old = TIMER1_500NS; 273 car1_old = TIMER1_500NS;
277 274
278 sysclk.word[1]++; // increment 500ns timer low word 275 sysclk.value++; // increment 500ns timer
279 if (sysclk.word[1] == 0) sysclk.word[0]++; // increment upper 16bits
280 } 276 }
281 277
282 ISR ( TIMER2_COMP_vect ) { 278 ISR ( TIMER2_COMP_vect ) {
283 //OCR2 = TIMER2_50US; // make sure that timer2 is 50µs !!! 279 //OCR2 = TIMER2_50US; // make sure that timer2 is 50µs !!!
284 // data packet timer 100µs pro bit... 280 // data packet timer 100µs pro bit...
389 } 385 }
390 386
391 void reset_vars(void) { 387 void reset_vars(void) {
392 uint8_t i; 388 uint8_t i;
393 for (i=0; i<MAX_SLOTS; i++) { 389 for (i=0; i<MAX_SLOTS; i++) {
394 if (i<4) speedlimit[i] = 15; else speedlimit[i] = 0; 390 if (i<4) slot[i].speedlimit = 15; else slot[i].speedlimit = 0;
395 fuel[i] = 100; 391 slot[i].fuel = 100;
396 jumpstart_time[i] = 0; 392 slot[i].jumpstart_time = 0;
397 } 393 }
398 sysclk.word[1] = 0; 394 sysclk.value = 0;
399 sysclk.word[0] = 0;
400 } 395 }
401 396
402 void countdown_progress(void) { 397 void countdown_progress(void) {
403 // decrement COUNTDOWN_LOOPS 398 // decrement COUNTDOWN_LOOPS
404 if (countdown_loops>0) { 399 if (countdown_loops>0) {
412 case 4: LED(2, 1); break; 407 case 4: LED(2, 1); break;
413 case 3: LED(3, 1); break; 408 case 3: LED(3, 1); break;
414 case 2: LED(4, 1); break; 409 case 2: LED(4, 1); break;
415 case 1: LED(5, 1); break; 410 case 1: LED(5, 1); break;
416 case 0: { // RACE START! 411 case 0: { // RACE START!
417 sysclk.word[1] = 1; 412 sysclk.value = 0;
418 sysclk.word[0] = 0;
419 LEDS_OFF(); 413 LEDS_OFF();
420 LED(3, 1); 414 LED(3, 1);
421 mode = 3; 415 mode = 3;
422 } break; 416 } break;
423 } 417 }
424 } 418 }
425 419
426 void check_cars(void) { 420 void check_cars(void) {
427 uint16_t diff_low, diff_high; 421 u32 clk, diff;
422 clk.value = sysclk.value; // freeze system clock time
428 423
429 if (car0 != car0_state) { 424 if (car0 != car0_state) {
430 car0_state = car0; 425 car0_state = car0;
431 if (car0_state != 0) { 426 if (car0_state != 0) {
432 diff_high = sysclk.word[0] - lap_time_start_high[car0-1]; 427 diff.value = clk.value - slot[car0-1].lap_time_start.value;
433 diff_low = sysclk.word[1] - lap_time_start_low[car0-1]; // this could be a bug ;) 428 if ( diff.value > 3000 ) { // minimum 1.5 second for 1 lap!
434 if ( (diff_high > 0) || (diff_low>2000) ) { // minimum 1 second for 1 lap! 429 slot[car0-1].lap_time_start.value = clk.value;
435 lap_time_start_low[car0-1] = sysclk.word[1]; 430 slot[car0-1].lap_time.value = diff.value;
436 lap_time_start_high[car0-1] = sysclk.word[0];
437 lap_time_low[car0-1] = diff_low;
438 lap_time_high[car0-1] = diff_high;
439 RS232_putc('L'); 431 RS232_putc('L');
440 RS232_putc('A'); 432 RS232_putc('A');
441 RS232_putc('0'+car0_state); 433 RS232_putc('0'+car0_state);
442 RS232_putc(':'); 434 RS232_putc(':');
443 itoa(diff_high, s, 16); 435 ultoa(diff.value, s, 16);
444 RS232_puts(s);
445 RS232_putc(',');
446 itoa(diff_low, s, 16);
447 RS232_puts(s); 436 RS232_puts(s);
448 RS232_putc('\n'); 437 RS232_putc('\n');
449 } 438 }
450 } 439 }
451 } car0 = 0; 440 } car0 = 0;
452 441
453 if (car1 != car1_state) { 442 if (car1 != car1_state) {
454 car1_state = car1; 443 car1_state = car1;
455 if (car1_state != 0) { 444 if (car1_state != 0) {
456 diff_high = sysclk.word[0] - lap_time_start_high[car1-1]; 445 diff.value = clk.value - slot[car1-1].lap_time_start.value;
457 diff_low = sysclk.word[1] - lap_time_start_low[car1-1]; // this could be a bug ;) 446 if ( diff.value > 3000 ) { // minimum 1.5 second for 1 lap!
458 if ( (diff_high > 0) || (diff_low>2000) ) { // minimum 1 second for 1 lap! 447 slot[car1-1].lap_time_start.value = clk.value;
459 lap_time_start_low[car1-1] = sysclk.word[1]; 448 slot[car1-1].lap_time.value = diff.value;
460 lap_time_start_high[car1-1] = sysclk.word[0];
461 lap_time_low[car1-1] = diff_low;
462 lap_time_high[car1-1] = diff_high;
463 RS232_putc('L'); 449 RS232_putc('L');
464 RS232_putc('B'); 450 RS232_putc('B');
465 RS232_putc('0'+car1_state); 451 RS232_putc('0'+car1_state);
466 RS232_putc(':'); 452 RS232_putc(':');
467 itoa(diff_high, s, 16); 453 ultoa(diff.value, s, 16);
468 RS232_puts(s);
469 RS232_putc(',');
470 itoa(diff_low, s, 16);
471 RS232_puts(s); 454 RS232_puts(s);
472 RS232_putc('\n'); 455 RS232_putc('\n');
473 } 456 }
474 } 457 }
475 } car1 = 0; 458 } car1 = 0;
521 LED(4, 1); 504 LED(4, 1);
522 LED(5, 1); 505 LED(5, 1);
523 RS232_puts_p(prepare); 506 RS232_puts_p(prepare);
524 } else if (mode == 1) { 507 } else if (mode == 1) {
525 // Initiate race countdown 508 // Initiate race countdown
526 sysclk.word[1] = 1; 509 sysclk.value = 0;
527 sysclk.word[0] = 0;
528 countdown = 5; 510 countdown = 5;
529 countdown_loops = COUNTDOWN_DELAY; 511 countdown_loops = COUNTDOWN_DELAY;
530 mode = 2; 512 mode = 2;
531 LED(1, 0); 513 LED(1, 0);
532 LED(2, 0); 514 LED(2, 0);

mercurial