Mon, 14 Nov 2011 21:15:11 +0100
finished: rails short circuit check
#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 "driver/rs232.h" #include "driver/adc.h" #include "main.h" #include "lowlevel.h" 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); } 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) { // check for short circuit on the rails check_rails_shortcut(); 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; } } // main loop end };