--- a/blackbox/main.c Sat Dec 03 14:25:06 2011 +0100 +++ b/blackbox/main.c Sat Dec 03 16:42:53 2011 +0100 @@ -13,8 +13,28 @@ #include "main.h" #include "lowlevel.h" -#define MAX_SLOTS 5 -uint8_t speedlimit[MAX_SLOTS]; +char ok[] PROGMEM="OK\n"; +char busy[] PROGMEM="BUSY\n"; +char prepare[] PROGMEM="!RACE PREPARE\n"; +char countdownstart[] PROGMEM="!COUNTDOWN\n"; +char racestart[] PROGMEM="!RACE START\n"; + + +static uint8_t countdown, countdown_loops; +uint8_t mode = 0; +// valid race modes: +// 0: free drive / idle +// 1: waiting for countdown start +// 2: race countdown initiated +// 3: Race start condition + + +#define MAX_SLOTS 6 +volatile uint8_t speedlimit[MAX_SLOTS]; +volatile uint8_t fuel[MAX_SLOTS]; +volatile uint8_t jumpstart_time[MAX_SLOTS]; + + volatile uint8_t program_count = 0; volatile uint8_t program_id; @@ -48,8 +68,6 @@ return 0; } -char ok[] PROGMEM="OK\n"; -char busy[] PROGMEM="BUSY\n"; ISR ( USART_RXC_vect ) { @@ -91,6 +109,18 @@ RS232_puts_p(ok); break; + case 'I': // get Information data (incl. important global parameter dump) + RS232_puts(VERSION); + RS232_putc(':'); + for (tmp=0;tmp<MAX_SLOTS;tmp++) RS232_putc(speedlimit[tmp]); // output speed limits + RS232_putc(':'); + for (tmp=0;tmp<MAX_SLOTS;tmp++) RS232_putc(fuel[tmp]); // output fuel levels (0=empty, 100=full, 0xff=no fuel option) + RS232_putc(':'); + for (tmp=0;tmp<MAX_SLOTS;tmp++) RS232_putc(jumpstart_time[tmp]); // output jumpstart times + RS232_putc(':'); + RS232_putc('\n'); + break; + } // wait for the next packet @@ -102,48 +132,61 @@ } +void jumpstart(uint8_t controller) { + if (jumpstart_time[controller] == 0) { + jumpstart_time[controller] = 1; + // todo: later the timestamp should written instead of just "1" + RS232_putc('~'); + RS232_putc('0'-controller); + RS232_putc('\n'); + } +} int do_controller(uint8_t controller) { // read controller X speed & encode controller data packet - uint16_t tmp; + uint16_t tmp = 0; switch (controller) { case 0: - tmp = ((getADC(CONTROLLER1_SPEED) / CONTROLLER_DIVISOR) & 0x0F); + if (mode!=1) tmp = ((getADC(CONTROLLER1_SPEED) / CONTROLLER_DIVISOR) & 0x0F); + if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; } if (tmp > speedlimit[controller]) tmp = speedlimit[controller]; tmp = tmp << 1; if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER1_SW)) != 0) { tmp |= (1<<5); - LED(1,0); - } else LED(1,1); + if (mode == 0) LED(1,0); + } else if (mode == 0) LED(1,1); break; case 1: - tmp = ((getADC(CONTROLLER2_SPEED) / CONTROLLER_DIVISOR) & 0x0F); + if (mode!=1) tmp = ((getADC(CONTROLLER2_SPEED) / CONTROLLER_DIVISOR) & 0x0F); + if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; } if (tmp > speedlimit[controller]) tmp = speedlimit[controller]; tmp = tmp << 1; if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER2_SW)) != 0) { tmp |= (1<<5); - LED(2,0); - } else LED(2,1); + if (mode == 0) LED(2,0); + } else if (mode == 0) LED(2,1); break; case 2: - tmp = ((getADC(CONTROLLER3_SPEED) / CONTROLLER_DIVISOR) & 0x0F); + if (mode!=1) tmp = ((getADC(CONTROLLER3_SPEED) / CONTROLLER_DIVISOR) & 0x0F); + if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; } if (tmp > speedlimit[controller]) tmp = speedlimit[controller]; tmp = tmp << 1; if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER3_SW)) != 0) { tmp |= (1<<5); - LED(3,0); - } else LED(3,1); + if (mode == 0) LED(4,0); + } else if (mode == 0) LED(4,1); break; case 3: - tmp = ((getADC(CONTROLLER4_SPEED) / CONTROLLER_DIVISOR) & 0x0F); + if (mode!=1) tmp = ((getADC(CONTROLLER4_SPEED) / CONTROLLER_DIVISOR) & 0x0F); + if ((mode == 2) && (tmp != 0)) { jumpstart(controller); tmp = 0; } if (tmp > speedlimit[controller]) tmp = speedlimit[controller]; tmp = tmp << 1; if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER4_SW)) != 0) { tmp |= (1<<5); - LED(4,0); - } else LED(4,1); + if (mode == 0) LED(5,0); + } else if (mode == 0) LED(5,1); break; case 4: tmp = (1<<5); break; // todo regler 5 case 5: tmp = (1<<5); break; // todo regler 6 @@ -197,8 +240,6 @@ ISR ( TIMER1_COMPA_vect ) { // trigger packet transfer: transmit_len = transmit_len_next; - //LED(2,2); - // here is some more time to do something else... } @@ -241,15 +282,12 @@ if (transmit_len == 0) transmit_len = 0xFE; else transmit_len--; // next bit } } - - //LED(3,2); } ISR ( TIMER0_OVF_vect ) { // TODO: last bit should be set by the sender, not from us! TCNT0 = TIMER0_250US; - //LED(1,2); if (timer0_delay == 0) { RAIL_POWER_PORT &= ~_BV(RAIL_POWER); // pull rails low _delay_us(28); // wait some cycles @@ -280,13 +318,37 @@ ISR (INT2_vect) { // Lap counter Interrupt - LED(5,2); + // do not know if this ever occurs ?! this is normally an output pin to trigger the counter start } void reset_vars(void) { uint8_t i; for (i=0; i<MAX_SLOTS; i++) { speedlimit[i] = 15; + fuel[i] = 100; + jumpstart_time[i] = 0; + } +} + +void countdown_progress(void) { + // decrement COUNTDOWN_LOOPS + if (countdown_loops>0) { + countdown_loops--; + } else { + countdown--; + countdown_loops = COUNTDOWN_DELAY; + } + switch (countdown) { + case 5: LED(1, 1); break; + case 4: LED(2, 1); break; + case 3: LED(3, 1); break; + case 2: LED(4, 1); break; + case 1: LED(5, 1); break; + case 0: { // RACE START! + LEDS_OFF(); + LED(3, 1); + mode = 3; + } break; } } @@ -294,27 +356,15 @@ int main(void) { - unsigned char s[30]; - uint16_t tmp; + unsigned char s[10]; uint8_t packet_index = 1; uint8_t btn_start = _BV(SW_START); uint8_t old_start = btn_start; - uint8_t mode = 0; - // valid race modes: - // 0: free drive - // 1: race countdown initiated - // 2: countdown 5 - // 3: countdown 4 - // 4: countdown 3 - // 5: countdown 2 - // 6: countdown 1 - // 7: race start initiated (next mode will be zero = free drive) - - init_hardware(); reset_vars(); + LED(3, 1); // enable middle led == idle mode // switch on rails power RAIL_POWER_PORT |= _BV(RAIL_POWER); @@ -339,28 +389,45 @@ if (btn_start == 0) { // start button press active if (mode == 0) { + mode = 1; // set wait for race start mode + reset_vars(); + LED(1, 1); + LED(2, 1); + LED(3, 1); + LED(4, 1); + LED(5, 1); + RS232_puts_p(prepare); + } else if (mode == 1) { // Initiate race countdown - mode = 0; // todo: set to 1 - // issue reset command to lap counter - program_command = 6; - program_parameter = 9; - program_id = 0; - program_count = 1; - LAP_COUNTER_PORT |= _BV(LAP_COUNTER); - } else { - // do a reset, switch back to free drive mode 0 - mode = 0; - // issue reset command - program_command = 19; - program_parameter = 0; - program_id = 7; - program_count = 1; - LAP_COUNTER_PORT &= ~_BV(LAP_COUNTER); + countdown = 5; + countdown_loops = COUNTDOWN_DELAY; + mode = 2; + LED(1, 0); + LED(2, 0); + LED(3, 0); + LED(4, 0); + LED(5, 0); + RS232_puts_p(countdownstart); } } - //LAP_COUNTER_PORT |= _BV(LAP_COUNTER); - } else old_start = btn_start; - // LAP_COUNTER_PORT &= ~_BV(LAP_COUNTER); + old_start = btn_start; + } + + if (mode==3) { + // RACE START! + // issue reset command to lap counter + mode = 0; + RS232_puts_p(racestart); + program_command = 6; + program_parameter = 9; + program_id = 0; + program_count = 1; + LAP_COUNTER_PORT |= _BV(LAP_COUNTER); + // TODO: beep long + _delay_us(50); + LAP_COUNTER_PORT &= ~_BV(LAP_COUNTER); + } + switch (packet_index) { case 1: @@ -376,6 +443,9 @@ //if (do_program(7, 20, 15)) packet_index++; // reset / pitstop detect //if (insert_queue(0, 0)) packet_index++; // null command } + + if ( (packet_index>1) && (mode == 2) ) countdown_progress(); + break; case 2: if (do_pace_ghost()) packet_index++;