car004f/main.c

Sat, 21 Dec 2013 21:01:55 +0100

author
Malte Bayer <mbayer@neo-soft.org>
date
Sat, 21 Dec 2013 21:01:55 +0100
changeset 147
f66c5b3b3ed2
child 148
08cb88614d69
permissions
-rw-r--r--

started firmware for car004f hardware

#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 "main.h"
#include "util/delay.h"


ISR ( USART_RXC_vect ) {
}

#define PULSE_PORT      PORTD
#define PULSE_BIT       PD2

#define RESPONSE_PORT   PORTC
#define RESPONSE_PIN    PC1

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 my_id; // Die ID des Autos!

uint8_t my_switch;
uint8_t my_speed;
uint8_t light_mode;

ISR ( INT0_vect ) {
    GICR &= ~_BV(INT0) ; // Disable INT0
    // Startsignal erkannt, ab hier den Timer2 starten,
    // der liest dann alle 50µs den Zustand ein und schreibt das
    // empfangene Bit in den Puffer
    bitbuf = 0; // init
    bitbuf_len = 0b10000000; // init 1 pulse received
    TCNT2 = 0;
    TIMSK |= _BV(OCIE2); //enable timer2 interrupt
}

ISR ( TIMER2_COMP_vect ) {
    uint8_t clock;
    uint8_t state;
    uint8_t state2;
    if ((bitbuf_len & 0b10000000) == 0) clock = 0; else clock = 0xff;
    if ((bitbuf_len & 0b01000000) == 0) state = 0; else state = 0xff;
    if ((PIN(PULSE_PORT) & _BV(PULSE_BIT)) == 0) state2 = 0xff; else state2 = 0;

    if (clock) {
        bitbuf_len &= ~_BV(7); // switch clock to low
        // second pulse of bit
        if ((state==state2) & state2) {
            // 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
            if (data_len == 10) { // controller data packet
                clock = (bitbuf >> 6) & 0b00000111;
                car_speed[clock] = (bitbuf >> 1) & 0x0F;
                car_switch[clock] = (bitbuf >> 5) & 1;
                // current response for this car?
                /*
                if (response != 0) {
                    if ( ((response & 0b00001110) >> 1) == clock) {
                        // add our ID to response:
                        send_response(response | self_id << 6);
                        response = 0;
                    }
                }
                */
            }


        } else {
            bitbuf_len++; // increment bit counter
            bitbuf = bitbuf << 1; // shift bits
            if (state2 == 0) bitbuf |= 1; // receive logic one
        }
    } else {
        bitbuf_len |= _BV(7); // switch clock to high
        // first pulse of bit
        if (state2) {
            bitbuf_len |= _BV(6); // store new state
        } else {
            bitbuf_len &= ~_BV(6); // store new state
        }
    }
}

ISR (TIMER1_OVF_vect) {
}

ISR (INT1_vect) {
}

#define LIGHT_PORT      PORTC
#define LIGHT_FRONT     2
#define LIGHT_BRAKE     4

#define IR_PORT         PORTB
#define IR_LED          3


#define LIGHT_MODES     1       // anzahl der lichtmodi (ohne den modus "aus")



int main(void)
{
    uint8_t car0_state, car1_state;

    // setup data bit timer2
    TCCR2 = (1<<CS21) | (1<<WGM21); //divide by 8, set compare match
    OCR2 = TIMER2_50US;


    // enable both external interrupts
    // int 0 = data RX
    MCUCR = _BV(ISC00) | _BV(ISC01) | _BV(ISC10) | _BV(ISC11); // INT0/1 rising edge
    GICR = _BV(INT0) | _BV(INT1) ; // Enable INT0 + INT1

    // oscillator calibration
    // atmega8@1mhz = 0xac
    // @4mhz = ca 0xa0
    //OSCCAL = 0xa0;
    //OSCCAL = 0x9A;
    //OSCCAL = 0xa0; // internal oscillator @ 4 mhz.... doesnt work accurate!
    sei();

    DDR(LIGHT_PORT) |= (_BV(LIGHT_FRONT) | _BV(LIGHT_BRAKE));

    //defaults (from eeprom!)
    my_id = 1;
    light_mode = 0;

    while (1) {
        // main loop

        // Light cycle if switch pressed without speed
        if (my_speed == 0) {
            if (my_switch != car_switch[my_id]) {
                my_switch = car_switch[my_id];
                if (my_switch != 0) {
                    // cycle light
                    if (light_mode == LIGHT_MODES) light_mode = 0; else light_mode++;
                }
            }
        }

        switch (light_mode) {
            case 0:
                LIGHT_PORT &= ~_BV(LIGHT_FRONT); // switch lights off
                break;
            case 1:
                LIGHT_PORT |= _BV(LIGHT_FRONT); // switch lights on
                break;
        }

        _delay_ms(100);
        LIGHT_PORT |= _BV(LIGHT_BRAKE); // brake light on
        _delay_ms(100);
        LIGHT_PORT &= ~_BV(LIGHT_BRAKE); // brake light off
        



    } // main loop end
};

mercurial