13 #include "main.h" |
13 #include "main.h" |
14 #include "lowlevel.h" |
14 #include "lowlevel.h" |
15 |
15 |
16 const char ok[] PROGMEM="OK\n"; |
16 const char ok[] PROGMEM="OK\n"; |
17 const char busy[] PROGMEM="BUSY\n"; |
17 const char busy[] PROGMEM="BUSY\n"; |
18 const char prepare[] PROGMEM="!RACE PREPARE\n"; |
18 |
19 const char countdownstart[] PROGMEM="!COUNTDOWN\n"; |
19 const char prepare[] PROGMEM="!PRE\n"; |
20 const char racestart[] PROGMEM="!RACE START\n"; |
20 const char countdownstart[] PROGMEM="!SET\n"; |
21 |
21 const char racestart[] PROGMEM="!GO\n"; |
22 const char SHORTCUT[] PROGMEM="!SHORTCUT\n"; |
22 |
23 const char PANIC[] PROGMEM="!PANIC\n"; |
23 const char SHORTCUT[] PROGMEM="!OC\n"; |
|
24 const char PANIC[] PROGMEM="!STOP\n"; |
24 const char RESUME[] PROGMEM="!RESUME\n"; |
25 const char RESUME[] PROGMEM="!RESUME\n"; |
25 |
26 |
26 typedef union { |
27 typedef union { |
27 uint32_t value; |
28 uint32_t value; |
28 uint16_t word[2]; // high, low word |
29 uint16_t word[2]; // high, low word |
29 uint8_t byte[4]; // all four bytes |
30 uint8_t byte[4]; // all four bytes |
30 } u32; |
31 } u32; |
|
32 |
|
33 typedef union { |
|
34 uint16_t value; |
|
35 uint8_t byte[2]; // all two bytes |
|
36 } u16; |
31 |
37 |
32 #define FUEL_FULL 10000 |
38 #define FUEL_FULL 10000 |
33 #define FUEL_JUMPSTART 5000 |
39 #define FUEL_JUMPSTART 5000 |
34 #define FUEL_DIV_DEFAULT 25 |
40 #define FUEL_DIV_DEFAULT 25 |
35 #define PITLANE_SPEEDLIMIT 10 |
41 #define PITLANE_SPEEDLIMIT 10 |
46 unsigned trackswitch:1; // 1bit bool |
52 unsigned trackswitch:1; // 1bit bool |
47 unsigned canrefuel:1; // 1bit bool |
53 unsigned canrefuel:1; // 1bit bool |
48 unsigned unlimitedfuel:1; // 1bit bool |
54 unsigned unlimitedfuel:1; // 1bit bool |
49 unsigned trackchange:1; // 1bit bool |
55 unsigned trackchange:1; // 1bit bool |
50 uint16_t jumpstart_time, fuel; |
56 uint16_t jumpstart_time, fuel; |
51 uint8_t laps; |
57 uint16_t laps; |
52 u32 lap_time_start, lap_time; |
58 u32 lap_time_start, lap_time; |
53 } cardata; |
59 } cardata; |
54 |
60 |
55 static char s[8]; |
61 static char s[8]; |
56 static uint8_t countdown, countdown_loops; |
62 static uint8_t countdown, countdown_loops; |
163 if (switches.pitlane_finishline) slot[car].laps++; |
169 if (switches.pitlane_finishline) slot[car].laps++; |
164 } |
170 } |
165 if (status == 6) for (data=0; data<MAX_SLOTS; data++) slot[data].canrefuel = 0; |
171 if (status == 6) for (data=0; data<MAX_SLOTS; data++) slot[data].canrefuel = 0; |
166 if (status == 7) slot[car].canrefuel = 0; |
172 if (status == 7) slot[car].canrefuel = 0; |
167 } |
173 } |
|
174 |
|
175 /* Old ASCII Format: |
168 RS232_puts("RW:"); |
176 RS232_puts("RW:"); |
169 RS232_putc(car + '0'); |
177 RS232_putc(car + '0'); |
170 RS232_putc(':'); |
178 RS232_putc(':'); |
171 RS232_putc(type + '0'); |
179 RS232_putc(type + '0'); |
172 RS232_putc(':'); |
180 RS232_putc(':'); |
176 itoa(status, s, 16); |
184 itoa(status, s, 16); |
177 RS232_puts(s); |
185 RS232_puts(s); |
178 RS232_putc(':'); |
186 RS232_putc(':'); |
179 ultoa(sysclk.value, s, 16); |
187 ultoa(sysclk.value, s, 16); |
180 RS232_puts(s); |
188 RS232_puts(s); |
|
189 RS232_putc('\n'); |
|
190 */ |
|
191 |
|
192 // New binary protocol: TODO: compress sender & status, car & type |
|
193 RS232_puts("RW:\n"); |
|
194 RS232_putc(8); // 8 binary bytes following |
|
195 RS232_putc(car); |
|
196 RS232_putc(type); |
|
197 RS232_putc(sender); |
|
198 RS232_putc(status); |
|
199 RS232_putc(sysclk.byte[3]); |
|
200 RS232_putc(sysclk.byte[2]); |
|
201 RS232_putc(sysclk.byte[1]); |
|
202 RS232_putc(sysclk.byte[0]); |
181 RS232_putc('\n'); |
203 RS232_putc('\n'); |
182 } |
204 } |
183 |
205 |
184 int insert_queue(uint16_t tmp, uint8_t len) { |
206 int insert_queue(uint16_t tmp, uint8_t len) { |
185 if (transmit_buffer_queue == 0) { |
207 if (transmit_buffer_queue == 0) { |
300 break; |
323 break; |
301 |
324 |
302 case '+': // toggle panic mode |
325 case '+': // toggle panic mode |
303 RS232_puts_p(ok); |
326 RS232_puts_p(ok); |
304 if (mode != 0xff) { |
327 if (mode != 0xff) { |
305 mode = 0xff; |
328 mode = 0xff; |
306 RS232_puts_p(PANIC); |
329 RS232_puts_p(PANIC); |
307 } else { |
330 } else { |
308 mode = 0; |
331 mode = 0; |
309 RS232_puts_p(RESUME); |
332 RS232_puts_p(RESUME); |
310 } |
333 } |
311 break; |
334 break; |
312 |
335 |
313 case 'I': // get Information data (incl. important global parameter dump) |
336 case 'I': // get Information data (incl. important global parameter dump) |
|
337 // New binary protocol: |
|
338 RS232_puts("V:"); |
314 RS232_puts(VERSION); |
339 RS232_puts(VERSION); |
315 RS232_putc(':'); |
340 RS232_puts(":\n"); |
316 for (tmp=0;tmp<MAX_SLOTS;tmp++) RS232_putc(slot[tmp].speedlimit); // output speed limits |
341 RS232_putc(6 * MAX_SLOTS); // binary bytes following |
317 RS232_putc(':'); |
|
318 for (tmp=0;tmp<MAX_SLOTS;tmp++) RS232_putc(slot[tmp].speedminimum); // output minimum speed |
|
319 RS232_putc(':'); |
|
320 for (tmp=0;tmp<MAX_SLOTS;tmp++) { |
342 for (tmp=0;tmp<MAX_SLOTS;tmp++) { |
321 itoa(slot[tmp].fuel, s, 16); |
343 fuel.value = slot[tmp].fuel; |
322 RS232_putc(s); // output fuel levels (0=empty, 100=full, 0xff=no fuel option) |
344 jumpstart_time.value = slot[tmp].jumpstart_time; |
323 RS232_putc(','); |
345 RS232_putc(slot[tmp].speedlimit); // output speed limits |
|
346 RS232_putc(slot[tmp].speedminimum); // output minimum speed |
|
347 RS232_putc(fuel.byte[1]); // output fuel levels (0=empty, 100=full, 0xff=no fuel option) |
|
348 RS232_putc(fuel.byte[0]); // output fuel levels (0=empty, 100=full, 0xff=no fuel option) |
|
349 RS232_putc(jumpstart_time.byte[1]); // output jumpstart times |
|
350 RS232_putc(jumpstart_time.byte[0]); // output jumpstart times |
324 } |
351 } |
325 RS232_putc(':'); |
|
326 for (tmp=0;tmp<MAX_SLOTS;tmp++) { |
|
327 itoa(slot[tmp].jumpstart_time, s, 16); |
|
328 RS232_puts(s); // output jumpstart times |
|
329 RS232_putc(','); |
|
330 } |
|
331 RS232_putc(':'); |
|
332 RS232_putc('\n'); |
352 RS232_putc('\n'); |
333 break; |
353 break; |
334 |
354 |
335 } |
355 } |
336 |
356 |
481 if ((slot[2].speedminimum != 0) || ((getADC(CONTROLLER3_SPEED) / CONTROLLER_DIVISOR) > 0)) tmp |= 0b10010001; |
501 if ((slot[2].speedminimum != 0) || ((getADC(CONTROLLER3_SPEED) / CONTROLLER_DIVISOR) > 0)) tmp |= 0b10010001; |
482 if ((slot[3].speedminimum != 0) || ((getADC(CONTROLLER4_SPEED) / CONTROLLER_DIVISOR) > 0)) tmp |= 0b10001001; |
502 if ((slot[3].speedminimum != 0) || ((getADC(CONTROLLER4_SPEED) / CONTROLLER_DIVISOR) > 0)) tmp |= 0b10001001; |
483 if (slot[4].speedminimum != 0) tmp |= 0b10000101; |
503 if (slot[4].speedminimum != 0) tmp |= 0b10000101; |
484 if (slot[5].speedminimum != 0) tmp |= 0b10000011; |
504 if (slot[5].speedminimum != 0) tmp |= 0b10000011; |
485 } |
505 } |
486 // todo: wenn Daten enpfangen wurden hier eine Quittierung senden anstatt dem Active Word |
506 // TODO: wenn Daten enpfangen wurden hier eine Quittierung senden anstatt dem Active Word |
487 |
507 |
488 return insert_queue(tmp, 7); |
508 return insert_queue(tmp, 7); |
489 } |
509 } |
490 |
510 |
491 int do_pace_ghost(void) { |
511 int do_pace_ghost(void) { |
543 } |
563 } |
544 } |
564 } |
545 |
565 |
546 void check_cars(void) { |
566 void check_cars(void) { |
547 u32 clk, diff; |
567 u32 clk, diff; |
|
568 u16 laps; |
548 clk.value = sysclk.value; // freeze system clock time |
569 clk.value = sysclk.value; // freeze system clock time |
549 |
570 |
550 if (car0 != car0_state) { |
571 if (car0 != car0_state) { |
551 car0_state = car0; |
572 car0_state = car0; |
552 if (car0_state != 0) { |
573 if (car0_state != 0) { |
553 diff.value = clk.value - slot[car0-1].lap_time_start.value; |
574 diff.value = clk.value - slot[car0-1].lap_time_start.value; |
554 if ( diff.value > FINISHLINE_DIFF_BLOCK ) { |
575 if ( diff.value > FINISHLINE_DIFF_BLOCK ) { |
555 if (slot[car0-1].lap_time_start.value != 0) { |
576 if (slot[car0-1].lap_time_start.value != 0) { |
556 slot[car0-1].lap_time.value = diff.value; |
577 slot[car0-1].lap_time.value = diff.value; |
557 slot[car0-1].laps++; |
578 slot[car0-1].laps++; |
558 RS232_puts("L:3:"); // 3 = BB |
579 laps.value = slot[car0-1].laps; |
559 itoa(slot[car0-1].laps, s, 16); |
580 // New binary protocol: |
560 RS232_puts(s); |
581 RS232_puts("L:3:\n"); // 3 = BB |
561 RS232_putc(':'); |
582 RS232_putc(11); // binary bytes following |
562 RS232_putc('0'+car0_state); |
583 RS232_putc(laps.byte[1]); |
563 RS232_putc(':'); |
584 RS232_putc(laps.byte[0]); |
564 ultoa(diff.value, s, 16); |
585 RS232_putc(car0_state); // slot number |
565 RS232_puts(s); |
586 RS232_putc(diff.byte[3]); |
566 RS232_putc(':'); |
587 RS232_putc(diff.byte[2]); |
567 ultoa(clk.value, s, 16); |
588 RS232_putc(diff.byte[1]); |
568 RS232_puts(s); |
589 RS232_putc(diff.byte[0]); |
|
590 RS232_putc(sysclk.byte[3]); |
|
591 RS232_putc(sysclk.byte[2]); |
|
592 RS232_putc(sysclk.byte[1]); |
|
593 RS232_putc(sysclk.byte[0]); |
569 RS232_putc('\n'); |
594 RS232_putc('\n'); |
570 } |
595 } |
571 slot[car0-1].lap_time_start.value = clk.value; |
596 slot[car0-1].lap_time_start.value = clk.value; |
572 } |
597 } |
573 } |
598 } |
580 diff.value = clk.value - slot[car1-1].lap_time_start.value; |
605 diff.value = clk.value - slot[car1-1].lap_time_start.value; |
581 if ( diff.value > FINISHLINE_DIFF_BLOCK ) { |
606 if ( diff.value > FINISHLINE_DIFF_BLOCK ) { |
582 if (slot[car1-1].lap_time_start.value != 0) { |
607 if (slot[car1-1].lap_time_start.value != 0) { |
583 slot[car1-1].lap_time.value = diff.value; |
608 slot[car1-1].lap_time.value = diff.value; |
584 slot[car1-1].laps++; |
609 slot[car1-1].laps++; |
585 RS232_puts("L:1:"); // 1 = AA |
610 laps.value = slot[car1-1].laps; |
586 itoa(slot[car1-1].laps, s, 16); |
611 // New binary protocol: |
587 RS232_puts(s); |
612 RS232_puts("L:1:\n"); // 1 = AA |
588 RS232_putc(':'); |
613 RS232_putc(11); // binary bytes following |
589 RS232_putc('0'+car1_state); |
614 RS232_putc(laps.byte[1]); |
590 RS232_putc(':'); |
615 RS232_putc(laps.byte[0]); |
591 ultoa(diff.value, s, 16); |
616 RS232_putc(car1_state); // slot number |
592 RS232_puts(s); |
617 RS232_putc(diff.byte[3]); |
593 RS232_putc(':'); |
618 RS232_putc(diff.byte[2]); |
594 ultoa(clk.value, s, 16); |
619 RS232_putc(diff.byte[1]); |
595 RS232_puts(s); |
620 RS232_putc(diff.byte[0]); |
|
621 RS232_putc(sysclk.byte[3]); |
|
622 RS232_putc(sysclk.byte[2]); |
|
623 RS232_putc(sysclk.byte[1]); |
|
624 RS232_putc(sysclk.byte[0]); |
596 RS232_putc('\n'); |
625 RS232_putc('\n'); |
597 } |
626 } |
598 slot[car1-1].lap_time_start.value = clk.value; |
627 slot[car1-1].lap_time_start.value = clk.value; |
599 } |
628 } |
600 } |
629 } |
602 |
631 |
603 } |
632 } |
604 |
633 |
605 void slot_liveinfo(uint8_t idx) { |
634 void slot_liveinfo(uint8_t idx) { |
606 if (switches.liveinfo == 0) return; |
635 if (switches.liveinfo == 0) return; |
|
636 u16 fuel; |
607 |
637 |
608 if (switches.liveinfo == 1) { |
638 if (switches.liveinfo == 1) { |
609 // increment packet counter, if == 10 output some live info |
639 // increment packet counter, if == 10 output some live info |
610 if (slot[idx].seccnt == 10) { |
640 if (slot[idx].seccnt == 10) { |
611 // output current fuel status |
641 // output current fuel status |
612 RS232_putc('F'); |
642 fuel.value = slot[idx].fuel; |
613 RS232_putc(':'); |
643 // new Binary protocol: |
614 RS232_putc(idx + '0'); |
644 RS232_puts("F:\n"); |
615 RS232_putc(':'); |
645 RS232_putc(7); // binary bytes following |
616 itoa(slot[idx].fuel, s, 16); |
646 RS232_putc(idx); // slot |
617 RS232_puts(s); |
647 RS232_putc(fuel.byte[1]); |
618 RS232_putc(':'); |
648 RS232_putc(fuel.byte[0]); |
619 ultoa(sysclk.value, s, 16); |
649 RS232_putc(sysclk.byte[3]); |
620 RS232_puts(s); |
650 RS232_putc(sysclk.byte[2]); |
|
651 RS232_putc(sysclk.byte[1]); |
|
652 RS232_putc(sysclk.byte[0]); |
621 RS232_putc('\n'); |
653 RS232_putc('\n'); |
622 slot[idx].seccnt = 0; |
654 slot[idx].seccnt = 0; |
623 } else slot[idx].seccnt++; |
655 } else slot[idx].seccnt++; |
624 } else if ( (switches.liveinfo - 2) == idx ) { |
656 } else if ( (switches.liveinfo - 2) == idx ) { |
625 // output controller status LIVEINFO-2 for remote learning |
657 // output controller status LIVEINFO-2 for remote learning |
|
658 // TODO: old ascii protocol |
626 RS232_putc('L'); |
659 RS232_putc('L'); |
627 RS232_putc('N'); |
660 RS232_putc('N'); |
628 RS232_putc(':'); |
661 RS232_putc(':'); |
629 itoa(slot[idx].speed, s, 16); |
662 itoa(slot[idx].speed, s, 16); |
630 RS232_puts(s); |
663 RS232_puts(s); |
656 check_rails_shortcut(); |
689 check_rails_shortcut(); |
657 check_cars(); |
690 check_cars(); |
658 while (mode == 0xff) panic_mode(); |
691 while (mode == 0xff) panic_mode(); |
659 |
692 |
660 if (response_len > 0) { |
693 if (response_len > 0) { |
661 itoa(response, s, 2); |
694 //TODO: Track response data??? |
|
695 //itoa(response, s, 2); |
662 response_len = 0; |
696 response_len = 0; |
663 //RS232_puts("ANSWER RX: "); |
697 //RS232_puts("ANSWER RX: "); |
664 //RS232_puts(s); |
698 //RS232_puts(s); |
665 //RS232_putc('\n'); |
699 //RS232_putc('\n'); |
666 } |
700 } |