Mon, 14 Nov 2011 20:31:32 +0100
initial commit - controller1 working
#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 };