blackbox/main.c

changeset 0
9b7de464f0ea
child 2
6c59b4293fa9
--- /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
+};
+

mercurial