--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/blackbox/main.c Mon Nov 14 20:31:32 2011 +0100 @@ -0,0 +1,362 @@ +#include <avr/interrupt.h> +#include <avr/io.h> +#include <avr/wdt.h> +#include <avr/eeprom.h> +#include <stdlib.h> +#include <stdint.h> +#include <avr/pgmspace.h> +#include <util/delay.h> + +#include "main.h" + +#include "driver/rs232.h" +#include "driver/adc.h" + +#include "lowlevel.h" + +//#include "driver/manchester.h" + +/* +// Hardware config +#define LAP_COUNTER_PORT PORTB +#define LAP_COUNTER PB2 + +#define MODUL_PORT PORTD +#define MODUL_ST4 PD5 +#define MODUL_ST6 PD6 + +#define I2C_PORT PORTC +#define I2C_SDA PC0 +#define I2C_SCL PC1 + + +#define SW_PACECAR_PORT PORTC +#define SW_START_PORT PORTB +#define SW_TANK_PORT PORTB +#define SW_PACECAR PC6 +#define SW_TANK PB0 +#define SW_START PB1 + +#define SPEAKER_PORT PORTD +#define SPEAKER PD7 + +*/ + + +void init_hardware(void) { + RS232_init(); // initialize RS485 interface + RS232_puts_p(PSTR("CARRERA beta loading\n")); + + initADC(); + + // set LED output + DDR(LED1_PORT) |= _BV(LED1); + DDR(LED2_PORT) |= _BV(LED2); + DDR(LED3_PORT) |= _BV(LED3); + DDR(LED4_PORT) |= _BV(LED4); + DDR(LED5_PORT) |= _BV(LED5); + + // set Controller Input Pull-UPs + CONTROLLER_PORT |= (_BV(CONTROLLER1_SW) | _BV(CONTROLLER2_SW) | _BV(CONTROLLER3_SW) | _BV(CONTROLLER4_SW)); + + // switch pull-ups + SW_FUEL_PORT |= _BV(SW_FUEL); + + //RAIL_DETECT_PORT |= _BV(RAIL_DETECT); // enable internal pull-up + DDR(RAIL_POWER_PORT) |= _BV(RAIL_POWER); + + + LED(1, 1); _delay_ms(50); + LED(2, 1); _delay_ms(50); + LED(3, 1); _delay_ms(50); + LED(4, 1); _delay_ms(50); + LED(5, 1); _delay_ms(50); + LED(1, 0); _delay_ms(50); + LED(2, 0); _delay_ms(50); + LED(3, 0); _delay_ms(50); + LED(4, 0); _delay_ms(50); + LED(5, 0); _delay_ms(50); + + //TCCR0 = (1<<CS01); //divide by 8 + + + // setup data bit timer + TCCR2 = (1<<CS21); //divide by 8 + TCCR2 |= (1<<WGM21); // set compare match + OCR2 = TIMER2_50US; + TIMSK |= 1<<OCIE2; //enable timer2 interrupt + + // setup data packet timer + //TCCR1A = (1<<COM1A1); + TCCR1B = (1<<CS11); //divide by 8 + TCCR1B |= (1<<WGM12); // set compare match + //TCCR1B = (1<<CS11) | (1<<CS10); //divide by 64 + //TCNT1 = TIMER_7500NS; + OCR1A = TIMER1_7500NS; + TIMSK |= 1<<OCIE1A; //enable timer1 interrupt + + RS232_puts_p(PSTR("INIT OK\n")); + +} + + + +volatile uint8_t datalen = 0; +char data[10]; // 8 bytes data buffer + string termination + +static char buffer[RS232_BUFSIZE+1]; +static uint8_t buffer_len; + + +// USART0 RX interrupt +ISR ( USART_RXC_vect ) { + char c = UDR; + + // check for buffer overflow + if (buffer_len==sizeof(buffer)) { + buffer_len=0; + if (c == 27) { + // escape sequence, store to empty buffer + buffer[buffer_len++] = c; + } + } else { + // collect characters until end of line + if (c == 27) { + // escape sequence, clear buffer + buffer_len = 0; + buffer[buffer_len++] = c; + } else if ( (c==0xff) && (buffer_len > 3) ) { + buffer[buffer_len]=0; + + // packet end received, parse the received packet + + // wait for the next packet + buffer_len=0; + } else { + buffer[buffer_len++]=c; + } + } +} + + +volatile uint16_t transmit_buffer; +volatile uint16_t transmit_buffer_queue; +volatile uint8_t transmit_len; +volatile uint8_t transmit_len_next; +volatile uint8_t transmit_len_queue; +ISR ( TIMER2_COMP_vect ) { + //OCR2 = TIMER2_50US; // make sure that timer2 is 50µs !!! + // data packet timer 100µs pro bit... + if (transmit_len >= 0xFE) { + if (transmit_len != 0xFF) { + RAIL_POWER_PORT |= _BV(RAIL_POWER); // end of transmission + transmit_len = 0xFF; + transmit_buffer = transmit_buffer_queue; + transmit_buffer_queue = 0; + transmit_len_next = transmit_len_queue; + } + } else { + uint16_t bit = (1<<(transmit_len & 0b01111111)); + uint16_t clock; + if ((transmit_len & 0b10000000) == 0) clock = 0; else clock = 0xffff; + if ( ((transmit_buffer ^ clock) & bit) != 0 ) + RAIL_POWER_PORT |= _BV(RAIL_POWER); else + RAIL_POWER_PORT &= ~_BV(RAIL_POWER); + if ( (transmit_len & 0b10000000) == 0 ) { + // block 0 + //if (transmit_len == 0) transmit_len = 0xFF; else transmit_len |= 0b10000000; // set clock + transmit_len |= 0b10000000; // set clock + } else { + // block 1, output the current bit + transmit_len &= 0b01111111; // reset clock + //if (transmit_len != 0) transmit_len--; // next bit + if (transmit_len == 0) transmit_len = 0xFE; else transmit_len--; // next bit + } + } +} + +int insert_queue(uint16_t tmp, uint8_t len) { + if (transmit_buffer_queue == 0) { + transmit_buffer_queue = tmp; + transmit_len_queue = len; + return 1; + } + return 0; +} + + +int do_controller(uint8_t controller) { + // read controller X speed & encode controller data packet + uint16_t tmp; + switch (controller) { + case 0: tmp = getADC(CONTROLLER1_SPEED) / CONTROLLER_DIVISOR; break; + case 1: tmp = getADC(CONTROLLER2_SPEED) / CONTROLLER_DIVISOR; break; + case 2: tmp = getADC(CONTROLLER3_SPEED) / CONTROLLER_DIVISOR; break; + case 3: tmp = getADC(CONTROLLER4_SPEED) / CONTROLLER_DIVISOR; break; + case 4: tmp = 0; break; // todo regler 5 + case 5: tmp = 0; break; // todo regler 6 + } + tmp = 0b1000000000 | (controller << 6) | ((tmp & 0xF) << 1); + if ( (PIN(SW_FUEL_PORT) & _BV(SW_FUEL)) != 0) tmp |= 1; // benzinstand aktiv - tankmodusschalter + if ( (PIN(CONTROLLER_PORT) & _BV(CONTROLLER1_SW)) != 0) { + tmp |= (1<<5); + LED(controller+1, 0); + } else LED(controller+1, 1); + + return insert_queue(tmp, 9); +} + +unsigned char mirror( unsigned char n ) { + // mirror all 8 bits + n = ((n >> 1) & 0x55) | ((n << 1) & 0xaa); + n = ((n >> 2) & 0x33) | ((n << 2) & 0xcc); + n = ((n >> 4) & 0x0f) | ((n << 4) & 0xf0); + return n; +} + + +int do_program(uint8_t controller, uint8_t command, uint8_t parameter) { + // send program data packet + uint16_t tmp; + tmp = 0b1000000000000 | (mirror(parameter) << 4) | mirror(command)| (mirror(controller) >> 5); + + return insert_queue(tmp, 12); +} + +int do_active(void) { + // send controller active data packet + uint16_t tmp = 0b10000000; + if ((getADC(CONTROLLER1_SPEED) / CONTROLLER_DIVISOR) > 0) tmp |= 0b11000001; + if ((getADC(CONTROLLER2_SPEED) / CONTROLLER_DIVISOR) > 0) tmp |= 0b10100001; + if ((getADC(CONTROLLER3_SPEED) / CONTROLLER_DIVISOR) > 0) tmp |= 0b10010001; + if ((getADC(CONTROLLER4_SPEED) / CONTROLLER_DIVISOR) > 0) tmp |= 0b10001001; + // todo: regler 5 und 6 + + return insert_queue(tmp, 7); +} + +int do_pace_ghost(void) { + // send ghost and pacecar data packet + // todo: at the moment, both disabled! + uint16_t tmp = 0b1111100000; + if ( (PIN(SW_FUEL_PORT) & _BV(SW_FUEL)) != 0) tmp |= 1; // benzinstand aktiv - tankmodusschalter + // todo: PC, NH, TK, (KFR, FR) + + return insert_queue(tmp, 9); +} + +/* +TODO: DIE TIMER1 ISR DARF DIE ADC NICHT ABFRAGEN, NICHTMAL PAKETE BAUEN, NUR TRIGGERN +DIE PAKETE MÜSSEN IN DER MAIN UNIT GEBAUT WERDEN UND IN EINE QUEUE GESCHOBEN WERDEN +EINES VORBAUEN IN Q+1, DIE TIMER2 ISR MUSS DANN Q = Q+1 und Q+1 = 0 SETZEN, ERST DANN DARF +NEUES PAKET IN Q+1 EINGEFÜGT WERDEN +*/ + + +ISR ( TIMER1_COMPA_vect ) { + //OCR2 = 0xFF; // make sure that timer2 is synced to timer1, give enough cycles to prepare + LED(4,2); + // trigger packet transfer: + transmit_len = transmit_len_next; + + // here is some more time to do something else... +} + + +int main(void) +{ + + unsigned char s[30]; + uint16_t tmp; + uint8_t packet_index = 1; + + + init_hardware(); + + itoa(TIMER2_50US, s, 10); + RS232_puts(s); + + // switch on rails power + RAIL_POWER_PORT |= _BV(RAIL_POWER); + + while (1) { + //RS232_putc(PIN(RAIL_DETECT_PORT)); + + // check for short circuit on the rails + if ((PIN(RAIL_DETECT_PORT) & _BV(RAIL_DETECT)) == 0) { + _delay_ms(1); + if ((PIN(RAIL_DETECT_PORT) & _BV(RAIL_DETECT)) == 0) { + cli(); // disable ALL Interrupts + RAIL_POWER_PORT &= ~_BV(RAIL_POWER); // disable rails power + RS232_puts_p(PSTR("!!! SHORT CIRCUIT ON RAILS, POWERED OFF !!!\n")); + while (1) { + LED(1, 0); + _delay_ms(100); + LED(1, 1); + _delay_ms(100); + } + } + } + + + + + switch (packet_index) { + case 1: + if (do_program(7, 19, 0)) packet_index++; // reset + //do_program(7, 16, 3); // led an startampel + //do_program(0, 4, 0); // + break; + case 2: + if (do_pace_ghost()) packet_index++; + break; + case 3: + if (do_active()) packet_index++; + break; + case 4: + if (do_controller(0)) packet_index++; + break; + case 5: + if (do_controller(4)) packet_index++; + break; + case 6: + if (do_controller(1)) packet_index++; + break; + case 7: + if (do_controller(5)) packet_index++; + break; + case 8: + if (do_controller(2)) packet_index++; + break; + case 9: + if (do_active()) packet_index++; + break; + case 10: + if (do_controller(3)) packet_index = 1; + // last packet, so reset packet index + break; + } + + + + +/* + do_controller(0); + itoa (transmit_len_queue, s, 10); + RS232_puts(s); + RS232_putc(' '); + itoa (transmit_buffer_queue, s, 2); + RS232_puts(s); + + RS232_putc('\n'); +*/ +/* + itoa (tmp, s, 2); + RS232_puts(s); + RS232_putc('\n'); +*/ + + + } // main loop end +}; +