45 // valid race modes: |
45 // valid race modes: |
46 // 0: free drive / idle |
46 // 0: free drive / idle |
47 // 1: waiting for countdown start |
47 // 1: waiting for countdown start |
48 // 2: race countdown initiated |
48 // 2: race countdown initiated |
49 // 3: Race start condition |
49 // 3: Race start condition |
|
50 uint8_t liveinfo = 0; |
|
51 uint8_t fuel_enabled = 1; |
50 |
52 |
51 volatile u32 sysclk; |
53 volatile u32 sysclk; |
52 volatile uint8_t sysclk_packettimer = 0; |
54 volatile uint8_t sysclk_packettimer = 0; |
53 volatile cardata slot[MAX_SLOTS]; |
55 volatile cardata slot[MAX_SLOTS]; |
54 |
56 |
77 volatile uint16_t responsewire_data = 0; |
79 volatile uint16_t responsewire_data = 0; |
78 volatile uint16_t response; |
80 volatile uint16_t response; |
79 volatile uint8_t response_len; |
81 volatile uint8_t response_len; |
80 volatile uint8_t timer0_delay; |
82 volatile uint8_t timer0_delay; |
81 |
83 |
|
84 |
|
85 /* RESPONSEWIRE frame format: |
|
86 1 startbit |
|
87 2 car id bit 1 |
|
88 3 car id bit 2 |
|
89 4 car id bit 3 |
|
90 5 track change status bit 1 |
|
91 6 track change status bit 2 |
|
92 7 track change status bit 3 |
|
93 8 track change status bit 4 |
|
94 9 sender id bit 1 |
|
95 10 sender id bit 2 |
|
96 11 sender id bit 3 |
|
97 12 sender id bit 4 |
|
98 13 device type bit 1 |
|
99 14 device type bit 2 |
|
100 15 device type bit 3 |
|
101 16 stopbit |
|
102 */ |
|
103 |
|
104 /* PITLANE STATUS DEFINITION |
|
105 1 = AA |
|
106 2 = AB |
|
107 3 = BB |
|
108 4 = BA |
|
109 5 = BC |
|
110 6 = ZZ -> pitlane exit |
|
111 */ |
|
112 |
|
113 #define STARTSTOP 0b1000000000000001 |
|
114 void decode_responsewire(void) { |
|
115 uint16_t data = responsewire_data; |
|
116 // first check if start + stopbit are set |
|
117 // todo future: unsure but last bit doesnt get set?! |
|
118 /* |
|
119 if ((data & STARTSTOP) != STARTSTOP) { |
|
120 RS232_puts("RW BAD\n"); |
|
121 return; // incomplete response |
|
122 } |
|
123 */ |
|
124 // now extract the car id, track change status |
|
125 uint8_t car = ((data >> 1) & 0b111); |
|
126 uint8_t status = ((data >> 4) & 0b1111); |
|
127 uint8_t sender = ((data >> 8) & 0b1111); |
|
128 uint8_t type = ((data >> 12) & 0b111); |
|
129 if (type == 4) { |
|
130 // pitlane response |
|
131 if (status == 5) slot[car].canrefuel = 1; |
|
132 if (status == 6) for (data=0; data<MAX_SLOTS; data++) slot[data].canrefuel = 0; |
|
133 } |
|
134 RS232_puts("RW:"); |
|
135 itoa(car, s, 16); |
|
136 RS232_puts(s); |
|
137 RS232_putc(':'); |
|
138 itoa(type, s, 16); |
|
139 RS232_puts(s); |
|
140 RS232_putc(':'); |
|
141 itoa(sender, s, 16); |
|
142 RS232_puts(s); |
|
143 RS232_putc(':'); |
|
144 itoa(status, s, 16); |
|
145 RS232_puts(s); |
|
146 RS232_putc('\n'); |
|
147 } |
82 |
148 |
83 int insert_queue(uint16_t tmp, uint8_t len) { |
149 int insert_queue(uint16_t tmp, uint8_t len) { |
84 if (transmit_buffer_queue == 0) { |
150 if (transmit_buffer_queue == 0) { |
85 transmit_buffer_queue = tmp; |
151 transmit_buffer_queue = tmp; |
86 transmit_len_queue = len; |
152 transmit_len_queue = len; |
133 if (tmp > 9) |
199 if (tmp > 9) |
134 tmp = buffer[2]-'A'+10; |
200 tmp = buffer[2]-'A'+10; |
135 slot[buffer[1]-'0'].speedminimum = tmp; |
201 slot[buffer[1]-'0'].speedminimum = tmp; |
136 RS232_puts_p(ok); |
202 RS232_puts_p(ok); |
137 break; |
203 break; |
|
204 |
|
205 case 'F': // set fuel enabled |
|
206 fuel_enabled = buffer[1]-'0'; |
|
207 RS232_puts_p(ok); |
|
208 break; |
|
209 |
|
210 case '*': // set live information |
|
211 liveinfo = buffer[1]-'0'; |
|
212 RS232_puts_p(ok); |
|
213 break; |
|
214 |
138 |
215 |
139 case 'I': // get Information data (incl. important global parameter dump) |
216 case 'I': // get Information data (incl. important global parameter dump) |
140 RS232_puts(VERSION); |
217 RS232_puts(VERSION); |
141 RS232_putc(':'); |
218 RS232_putc(':'); |
142 for (tmp=0;tmp<MAX_SLOTS;tmp++) RS232_putc(slot[tmp].speedlimit); // output speed limits |
219 for (tmp=0;tmp<MAX_SLOTS;tmp++) RS232_putc(slot[tmp].speedlimit); // output speed limits |
252 tmp |= (0b1000000000 | (controller << 6)); |
329 tmp |= (0b1000000000 | (controller << 6)); |
253 // FUEL BIT GETS SET WHEN FUEL == 0, |
330 // FUEL BIT GETS SET WHEN FUEL == 0, |
254 // THIS REQUIRES PHYSICAL CAR FUEL LEVEL SET TO ZERO BEFORE! |
331 // THIS REQUIRES PHYSICAL CAR FUEL LEVEL SET TO ZERO BEFORE! |
255 if ( ((PIN(SW_FUEL_PORT) & _BV(SW_FUEL)) != 0) | (slot[controller].fuel == 0)) tmp |= 1; // benzinstand aktiv - tankmodusschalter |
332 if ( ((PIN(SW_FUEL_PORT) & _BV(SW_FUEL)) != 0) | (slot[controller].fuel == 0)) tmp |= 1; // benzinstand aktiv - tankmodusschalter |
256 if (insert_queue(tmp, 9)) { |
333 if (insert_queue(tmp, 9)) { |
257 if (speed != 0) { |
334 if (fuel_enabled) { |
258 // do the fuel calculation, regardless if fuel logic active or not |
335 if (speed != 0) { |
259 tmp = (uint8_t)(((slot[controller].accel * speed) + 1) / FUEL_DIVISOR); |
336 // do the fuel calculation, regardless if fuel logic active or not |
260 if (tmp == 0) tmp = 1; |
337 tmp = (uint8_t)(((slot[controller].accel * speed) + 1) / FUEL_DIVISOR); |
261 if (slot[controller].fuel > 0) { |
338 if (tmp == 0) tmp = 1; |
262 // enough fuel left to decrement? |
339 if (slot[controller].fuel > 0) { |
263 if (slot[controller].fuel > tmp) { |
340 // enough fuel left to decrement? |
264 slot[controller].fuel -= tmp; // decrement fuel level |
341 if (slot[controller].fuel > tmp) { |
265 } else slot[controller].fuel = 0; |
342 slot[controller].fuel -= tmp; // decrement fuel level |
|
343 } else slot[controller].fuel = 0; |
|
344 } |
|
345 } else if (slot[controller].canrefuel) { |
|
346 // increase fuel by 5%/sec, this equals by adding 50 to the counter |
|
347 slot[controller].fuel += 50; |
|
348 if (slot[controller].fuel > FUEL_FULL) slot[controller].fuel = FUEL_FULL; |
266 } |
349 } |
267 } else if (slot[controller].canrefuel) { |
350 return 1; |
268 // increase fuel by 5%/sec, this equals by adding 50 to the counter |
351 } |
269 slot[controller].fuel += 50; |
|
270 if (slot[controller].fuel > FUEL_FULL) slot[controller].fuel = FUEL_FULL; |
|
271 } |
|
272 return 1; |
|
273 } else return 0; |
352 } else return 0; |
274 } |
353 } |
275 |
354 |
276 uint8_t mirror( uint8_t n ) { |
355 uint8_t mirror( uint8_t n ) { |
277 n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa); |
356 n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa); |
331 slot[i].fuel = FUEL_FULL; |
410 slot[i].fuel = FUEL_FULL; |
332 slot[i].jumpstart_time = 0; |
411 slot[i].jumpstart_time = 0; |
333 slot[i].laps = 0; |
412 slot[i].laps = 0; |
334 slot[i].seccnt = 0; |
413 slot[i].seccnt = 0; |
335 slot[i].accel = 15; // full acceleration per default - TODO |
414 slot[i].accel = 15; // full acceleration per default - TODO |
336 slot[i].canrefuel = 1; // TODO: only set to 1 when on a pitlane |
415 slot[i].canrefuel = 0; |
337 } |
416 } |
338 sysclk.value = 0; |
417 sysclk.value = 0; |
339 } |
418 } |
340 |
419 |
341 void countdown_progress(void) { |
420 void countdown_progress(void) { |
373 if (slot[car0-1].lap_time_start.value != 0) { |
452 if (slot[car0-1].lap_time_start.value != 0) { |
374 slot[car0-1].lap_time.value = diff.value; |
453 slot[car0-1].lap_time.value = diff.value; |
375 slot[car0-1].laps++; |
454 slot[car0-1].laps++; |
376 RS232_putc('L'); |
455 RS232_putc('L'); |
377 RS232_putc(':'); |
456 RS232_putc(':'); |
378 RS232_putc('A'); |
457 RS232_putc('B'); |
379 RS232_putc(':'); |
458 RS232_putc(':'); |
380 itoa(slot[car0-1].laps, s, 16); |
459 itoa(slot[car0-1].laps, s, 16); |
381 RS232_puts(s); |
460 RS232_puts(s); |
382 RS232_putc(':'); |
461 RS232_putc(':'); |
383 RS232_putc('0'+car0_state); |
462 RS232_putc('0'+car0_state); |
399 if (slot[car1-1].lap_time_start.value != 0) { |
478 if (slot[car1-1].lap_time_start.value != 0) { |
400 slot[car1-1].lap_time.value = diff.value; |
479 slot[car1-1].lap_time.value = diff.value; |
401 slot[car1-1].laps++; |
480 slot[car1-1].laps++; |
402 RS232_putc('L'); |
481 RS232_putc('L'); |
403 RS232_putc(':'); |
482 RS232_putc(':'); |
404 RS232_putc('B'); |
483 RS232_putc('A'); |
405 RS232_putc(':'); |
484 RS232_putc(':'); |
406 itoa(slot[car1-1].laps, s, 16); |
485 itoa(slot[car1-1].laps, s, 16); |
407 RS232_puts(s); |
486 RS232_puts(s); |
408 RS232_putc(':'); |
487 RS232_putc(':'); |
409 RS232_putc('0'+car1_state); |
488 RS232_putc('0'+car1_state); |
417 } |
496 } |
418 } car1 = 0; |
497 } car1 = 0; |
419 } |
498 } |
420 |
499 |
421 void slot_liveinfo(uint8_t idx) { |
500 void slot_liveinfo(uint8_t idx) { |
|
501 if (liveinfo == 0) return; |
422 // increment packet counter, if == 10 output some live info |
502 // increment packet counter, if == 10 output some live info |
423 if (slot[idx].seccnt == 10) { |
503 if (slot[idx].seccnt == 10) { |
424 // output current fuel status |
504 // output current fuel status |
425 RS232_putc('F'); |
505 RS232_putc('F'); |
426 RS232_putc(':'); |
506 RS232_putc(':'); |