# HG changeset patch # User mbayer # Date 1387803953 -3600 # Node ID e787f47c084b49152a4d606b80bb87474e3ca165 # Parent 0e71b51c83a554403dc75b625c90c69e3251b4d2 finished car id programming and brake function diff -r 0e71b51c83a5 -r e787f47c084b .hgignore --- a/.hgignore Mon Dec 23 10:59:14 2013 +0100 +++ b/.hgignore Mon Dec 23 14:05:53 2013 +0100 @@ -10,5 +10,7 @@ *.apk +calibration.data + custom-sound/* dist/* \ No newline at end of file diff -r 0e71b51c83a5 -r e787f47c084b car004f/Makefile --- a/car004f/Makefile Mon Dec 23 10:59:14 2013 +0100 +++ b/car004f/Makefile Mon Dec 23 14:05:53 2013 +0100 @@ -4,6 +4,7 @@ #FUSES=-U lfuse:w:0xAE:m -U hfuse:w:0xd9:m FUSES=-U lfuse:w:0x83:m -U hfuse:w:0xd8:m # original fuses: 83 / d8 + BOOTFUSES=-U lfuse:w:0xff:m -U hfuse:w:0xce:m #F_CPU=4185600 @@ -94,6 +95,10 @@ fuse: $(AVRDUDE) $(PROGRAMMER) -p $(MCU) -V $(FUSES) +calibration: + $(AVRDUDE) $(PROGRAMMER) -p $(MCU) -U calibration:r:calibration.data:h + $(AVRDUDE) $(PROGRAMMER) -p $(MCU) -U eeprom:w:`cut -d ',' -f 3 ./calibration.data`,0xff:m + clean: rm -rf *.o *.elf *.elf.src *.s *.i rm -rf driver/*.o diff -r 0e71b51c83a5 -r e787f47c084b car004f/main.c --- a/car004f/main.c Mon Dec 23 10:59:14 2013 +0100 +++ b/car004f/main.c Mon Dec 23 14:05:53 2013 +0100 @@ -17,24 +17,27 @@ #define PULSE_BIT PD2 typedef struct { + uint8_t calibration; // AVR Chip calibration byte written by avrdude + uint8_t initialized; // if 0xff, reset config to defaults on first boot uint8_t slot; uint8_t light; uint8_t program; // 0xff = inactive ; programming mode active on slot X - uint8_t initialized; } config_t; -config_t EEMEM eeconfig = {0,0,0xff,0}; +config_t EEMEM eeconfig = {0,0,0,0xff,0}; config_t config; volatile uint16_t data = 0; volatile uint8_t data_len = 0; volatile uint8_t bitbuf_len = 0; volatile uint16_t bitbuf = 0; -volatile uint8_t car_speed[8]; -volatile uint8_t car_switch[8]; +volatile uint8_t car_speed[MAX_SLOTS]; +volatile uint8_t car_switch[MAX_SLOTS]; +volatile uint8_t car_timeout[MAX_SLOTS]; volatile uint8_t timeout = 0; volatile uint8_t brake_timeout = 0; +uint8_t old_switch[MAX_SLOTS]; uint8_t my_switch; uint8_t my_speed; @@ -46,7 +49,8 @@ // empfangene Bit in den Puffer bitbuf = 0; // init bitbuf_len = 0b10000000; // init 1 pulse received - TCNT2 = 0; + + TCNT2 = 10; TIMSK |= _BV(OCIE2); //enable timer2 interrupt } @@ -62,10 +66,10 @@ bitbuf_len &= ~_BV(7); // switch clock to low // second pulse of bit if ((state==state2) & state2) { + TIMSK &= ~_BV(OCIE2); //disable timer2 interrupt + // two cycles high: packet end received data_len = (bitbuf_len & 0b00111111); - TIMSK &= ~_BV(OCIE2); //disable timer2 interrupt - GICR |= _BV(INT0) ; // Enable INT0 //data = bitbuf; // output data // write data of controllers to array @@ -85,6 +89,11 @@ */ } + // bugfix 20131223: timing errors, CLEAR timer2 flag before enable + // if this works, apply to track switches and pitlane too! + //GIFR = _BV(INTF0); + + GICR |= _BV(INT0) ; // Enable INT0 } else { bitbuf_len++; // increment bit counter @@ -109,6 +118,8 @@ TCNT0 = 100; // TIMER0 vorladen mit 100 if (brake_timeout > 1) brake_timeout--; if (timeout > 1) timeout--; + for (uint8_t i=0; i 1) car_timeout[i]--; } #define LIGHT_PORT PORTC @@ -118,9 +129,6 @@ #define IR_PORT PORTB #define IR_LED 3 -#define BRAKE_PORT PORTB -#define BRAKE 0 - #define LIGHT_MODES 1 // anzahl der lichtmodi (ohne den modus "aus") #define BRAKE_OFF_TIMEOUT 60 // value * 10ms @@ -135,14 +143,12 @@ void brake_on(void) { LIGHT_PORT |= _BV(LIGHT_BRAKE); // brake light on - BRAKE_PORT |= _BV(BRAKE); // brake on - DDRB &= ~_BV(1); // PB1 PWM Output enable + DDRB |= _BV(1); // PB1 PWM Output enable brake_timeout = BRAKE_OFF_TIMEOUT; } void brake_off(void) { LIGHT_PORT &= ~_BV(LIGHT_BRAKE); // brake light off - BRAKE_PORT &= ~_BV(BRAKE); // brake off DDRB &= ~_BV(1); // PB1 PWM Output disable brake_timeout = 0; } @@ -187,6 +193,22 @@ int main(void) { + // config (from eeprom!) + eeprom_read_block( &config, &eeconfig, sizeof(config_t) ); + + // set the internal calibration byte + OSCCAL = config.calibration; + // TODO: Vielleicht den internen Takt des AVR anhand der Bitclock auf den Schienen synchronisieren??? + // Das Calibration byte scheint nicht zu stimmen + + if (config.initialized == 0xff) { + config.slot = 0; + config.light = 0; + config.program = 0xff; + config.initialized = 0; + config_save(); + } + uint8_t temp; // setup data bit timer2 @@ -201,7 +223,6 @@ DDR(LIGHT_PORT) |= _BV(LIGHT_FRONT) | _BV(LIGHT_BRAKE); - DDR(BRAKE_PORT) |= _BV(BRAKE); TCCR1A = (1< 5 )) { temp = set_id(); @@ -282,19 +292,37 @@ my_switch = car_switch[config.slot]; if (my_switch == 0) { // cycle light - if (config.light == LIGHT_MODES) config.light = 0; else config.light++; - if (timeout > 1) { - // zweiter Tastendruck, Program Mode im EEPROM setzen - config.program = config.slot; // TODO: hier muss der slot rein welcher doppelclicked wurde (natuerlich dann auch nicht in der Lichtschaltelogik abfragen!) - } else { - // erster Tastendruck, timeout setzen - timeout = DOUBLE_CLICK_TIMEOUT; - } + if (config.light >= LIGHT_MODES) config.light = 0; else config.light++; config_save(); } } } + // check any car switch for a double click and speed = 0 + for (temp = 0; temp 1) { + // second key press within timeout, enter program mode for this key + config.program = temp; + config_save(); + car_timeout[temp] = 0xff; // the car has to be reset within this timeout + } else { + car_timeout[temp] = DOUBLE_CLICK_TIMEOUT; + } + } + + if (car_timeout[temp] == 1) { + if (config.program == temp) { + // cancel ID programming mode + config.program = 0xff; + config_save(); + } + car_timeout[temp] = 0; + } + } + switch (config.light) { case 0: LIGHT_PORT &= ~_BV(LIGHT_FRONT); // switch lights off