Program the control the fischertechnik robo interface or intelligent interface via tcp socket or via a java gui.
rs485.c@0:7f26f0680202, 2010-12-31 (annotated)
- Committer:
- networker
- Date:
- Fri Dec 31 14:01:14 2010 +0000
- Revision:
- 0:7f26f0680202
initial release: comprises ftlib (no usb), ft-over-ip socket server, and the http server (the html page and java jar I still have to publish somewhere)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
networker | 0:7f26f0680202 | 1 | //#define DEBUG //switches PB2 in interrupts and timeouts |
networker | 0:7f26f0680202 | 2 | #if 0 //for reference only |
networker | 0:7f26f0680202 | 3 | #define ALLOW_NESTING |
networker | 0:7f26f0680202 | 4 | |
networker | 0:7f26f0680202 | 5 | #include "data.h" |
networker | 0:7f26f0680202 | 6 | #include "rs485.h" |
networker | 0:7f26f0680202 | 7 | |
networker | 0:7f26f0680202 | 8 | |
networker | 0:7f26f0680202 | 9 | #define BAUD 921600 |
networker | 0:7f26f0680202 | 10 | #define DIRPORT PORTD |
networker | 0:7f26f0680202 | 11 | #define DIRBIT PD4 |
networker | 0:7f26f0680202 | 12 | #define DIRDIR DDRD |
networker | 0:7f26f0680202 | 13 | #define TRANSMIT asm("sbi %0, %1"::"I" (_SFR_IO_ADDR(DIRPORT)),"I" (DIRBIT)); |
networker | 0:7f26f0680202 | 14 | #define RECEIVE asm("cbi %0, %1"::"I" (_SFR_IO_ADDR(DIRPORT)),"I" (DIRBIT)); |
networker | 0:7f26f0680202 | 15 | |
networker | 0:7f26f0680202 | 16 | |
networker | 0:7f26f0680202 | 17 | uint8_t /*wpos = 0,*/ rpos = 0; |
networker | 0:7f26f0680202 | 18 | volatile uint8_t rs485_timeout = 0; |
networker | 0:7f26f0680202 | 19 | volatile uint8_t rs485_delay = 0; |
networker | 0:7f26f0680202 | 20 | static char* wposp = (char*)&msg.hdr.snd; |
networker | 0:7f26f0680202 | 21 | static char state = 0; |
networker | 0:7f26f0680202 | 22 | |
networker | 0:7f26f0680202 | 23 | void init_rs485() |
networker | 0:7f26f0680202 | 24 | { |
networker | 0:7f26f0680202 | 25 | /*Set baud rate */ |
networker | 0:7f26f0680202 | 26 | //Enable receiver and transmitter (also interrupts) |
networker | 0:7f26f0680202 | 27 | // UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) /*| _BV(UDRIE0)*/; |
networker | 0:7f26f0680202 | 28 | /* Set frame format: 8data, 1stop bit */ |
networker | 0:7f26f0680202 | 29 | // UCSR0C = (3<<UCSZ00); |
networker | 0:7f26f0680202 | 30 | //set tranceiver |
networker | 0:7f26f0680202 | 31 | // RECEIVE; |
networker | 0:7f26f0680202 | 32 | // DIRDIR |= _BV(DIRBIT); //set enable as output |
networker | 0:7f26f0680202 | 33 | } |
networker | 0:7f26f0680202 | 34 | |
networker | 0:7f26f0680202 | 35 | void enable_rx_rs485() |
networker | 0:7f26f0680202 | 36 | { |
networker | 0:7f26f0680202 | 37 | UCSR0B |= _BV(RXEN0) | _BV(RXCIE0); //enable uart rx |
networker | 0:7f26f0680202 | 38 | RECEIVE; |
networker | 0:7f26f0680202 | 39 | } |
networker | 0:7f26f0680202 | 40 | |
networker | 0:7f26f0680202 | 41 | void send_rs485() |
networker | 0:7f26f0680202 | 42 | { rpos = 0; |
networker | 0:7f26f0680202 | 43 | //set RS485 tranceiver in send mode |
networker | 0:7f26f0680202 | 44 | TRANSMIT; |
networker | 0:7f26f0680202 | 45 | //disable rx interrupt |
networker | 0:7f26f0680202 | 46 | UCSR0B &= ~(_BV(RXCIE0) | _BV(RXEN0)); |
networker | 0:7f26f0680202 | 47 | //enable tx interrupt, will immediately generate int |
networker | 0:7f26f0680202 | 48 | UCSR0B |= _BV(UDRIE0); |
networker | 0:7f26f0680202 | 49 | //kick off transmission |
networker | 0:7f26f0680202 | 50 | // UDR0 = ((char*)&msg)[rpos++];//not necessary, will start by itself |
networker | 0:7f26f0680202 | 51 | rs485_timeout = sizeof(msg)/8; //just a precaution, transmit should not timeout, timeout is approx. 110% of expected time |
networker | 0:7f26f0680202 | 52 | } |
networker | 0:7f26f0680202 | 53 | |
networker | 0:7f26f0680202 | 54 | ISR(USART_RX_vect) |
networker | 0:7f26f0680202 | 55 | { |
networker | 0:7f26f0680202 | 56 | SETPIN12; |
networker | 0:7f26f0680202 | 57 | #ifdef ALLOW_NESTING |
networker | 0:7f26f0680202 | 58 | MASK_TIMER_INT(); |
networker | 0:7f26f0680202 | 59 | MASK_EXTENSION_INT(); |
networker | 0:7f26f0680202 | 60 | MASK_DISTANCE_INT(); |
networker | 0:7f26f0680202 | 61 | MASK_IR_INT(); |
networker | 0:7f26f0680202 | 62 | //MASK_EEPROM_INT(); |
networker | 0:7f26f0680202 | 63 | sei(); |
networker | 0:7f26f0680202 | 64 | #endif |
networker | 0:7f26f0680202 | 65 | register char *wp asm("r30") = wposp; |
networker | 0:7f26f0680202 | 66 | register char data asm("r1"); |
networker | 0:7f26f0680202 | 67 | do |
networker | 0:7f26f0680202 | 68 | { data = UDR0; |
networker | 0:7f26f0680202 | 69 | rs485_timeout = 2;//set a timeout of 100-200us equiv. to 10-20 bytes |
networker | 0:7f26f0680202 | 70 | switch (state) |
networker | 0:7f26f0680202 | 71 | { case 0: //idle |
networker | 0:7f26f0680202 | 72 | if (data == 0x02) |
networker | 0:7f26f0680202 | 73 | state = 1; |
networker | 0:7f26f0680202 | 74 | else if (data == 0xA0)//this is really a hack, it avoids timeouts in case of a bad start |
networker | 0:7f26f0680202 | 75 | state = 5; |
networker | 0:7f26f0680202 | 76 | break; |
networker | 0:7f26f0680202 | 77 | case 1: //stx |
networker | 0:7f26f0680202 | 78 | if (data == 0x55) |
networker | 0:7f26f0680202 | 79 | state = 2; |
networker | 0:7f26f0680202 | 80 | else |
networker | 0:7f26f0680202 | 81 | state = 0; |
networker | 0:7f26f0680202 | 82 | break; |
networker | 0:7f26f0680202 | 83 | case 2://length H, high byte comes first |
networker | 0:7f26f0680202 | 84 | msg.hdr.bytesL = data; |
networker | 0:7f26f0680202 | 85 | state = 3; |
networker | 0:7f26f0680202 | 86 | break; |
networker | 0:7f26f0680202 | 87 | case 3://length L, low byte |
networker | 0:7f26f0680202 | 88 | msg.hdr.bytesH = data; |
networker | 0:7f26f0680202 | 89 | if (msg.hdr.bytes > sizeof(msg)-7) |
networker | 0:7f26f0680202 | 90 | state = 0; //message structure cannot accomodate message this size |
networker | 0:7f26f0680202 | 91 | else |
networker | 0:7f26f0680202 | 92 | state = 4; |
networker | 0:7f26f0680202 | 93 | break; |
networker | 0:7f26f0680202 | 94 | case 4://store |
networker | 0:7f26f0680202 | 95 | *wp++ = data; |
networker | 0:7f26f0680202 | 96 | if (wp >= ((char*)&msg.hdr.snd + sizeof(trailer)) + msg.hdr.bytes |
networker | 0:7f26f0680202 | 97 | && wp <= (char*)&msg + sizeof(message) + 1 |
networker | 0:7f26f0680202 | 98 | ) |
networker | 0:7f26f0680202 | 99 | { //message complete |
networker | 0:7f26f0680202 | 100 | wp = (char*)&msg.hdr.snd; |
networker | 0:7f26f0680202 | 101 | rs485_timeout = 0; |
networker | 0:7f26f0680202 | 102 | //tx_message = find_ad(msg.hdr.rec) > 0; |
networker | 0:7f26f0680202 | 103 | tx_message = msg.hdr.rec - 3; |
networker | 0:7f26f0680202 | 104 | if (tx_message >= 0) |
networker | 0:7f26f0680202 | 105 | { UCSR0B &= ~(_BV(RXCIE0) | _BV(RXEN0)); //disable rec to avoid corruption by new messages |
networker | 0:7f26f0680202 | 106 | } |
networker | 0:7f26f0680202 | 107 | state = 0; |
networker | 0:7f26f0680202 | 108 | } |
networker | 0:7f26f0680202 | 109 | break; |
networker | 0:7f26f0680202 | 110 | case 5://wrong start |
networker | 0:7f26f0680202 | 111 | if (data == 0x15)//after a wrong start A0 i.o. 02, the 55 gets read as 15 |
networker | 0:7f26f0680202 | 112 | { msg.hdr.bytesL = 0; |
networker | 0:7f26f0680202 | 113 | state = 3; |
networker | 0:7f26f0680202 | 114 | } |
networker | 0:7f26f0680202 | 115 | else |
networker | 0:7f26f0680202 | 116 | state = 0; |
networker | 0:7f26f0680202 | 117 | default: |
networker | 0:7f26f0680202 | 118 | break; |
networker | 0:7f26f0680202 | 119 | } |
networker | 0:7f26f0680202 | 120 | } while (UCSR0A & _BV(RXC0)); //see if another char is available, now it is fast enough so this is normally not the case |
networker | 0:7f26f0680202 | 121 | wposp = wp; |
networker | 0:7f26f0680202 | 122 | #ifdef ALLOW_NESTING |
networker | 0:7f26f0680202 | 123 | cli(); |
networker | 0:7f26f0680202 | 124 | UNMASK_TIMER_INT(); |
networker | 0:7f26f0680202 | 125 | UNMASK_EXTENSION_INT(); |
networker | 0:7f26f0680202 | 126 | UNMASK_DISTANCE_INT(); |
networker | 0:7f26f0680202 | 127 | UNMASK_IR_INT(); |
networker | 0:7f26f0680202 | 128 | //UNMASK_EEPROM_INT(); |
networker | 0:7f26f0680202 | 129 | #endif |
networker | 0:7f26f0680202 | 130 | CLRPIN12; |
networker | 0:7f26f0680202 | 131 | } |
networker | 0:7f26f0680202 | 132 | |
networker | 0:7f26f0680202 | 133 | |
networker | 0:7f26f0680202 | 134 | ISR(USART_UDRE_vect) |
networker | 0:7f26f0680202 | 135 | { SETPIN12; |
networker | 0:7f26f0680202 | 136 | if (rpos > BYTES()+7) |
networker | 0:7f26f0680202 | 137 | { //last byte was sent |
networker | 0:7f26f0680202 | 138 | RECEIVE; |
networker | 0:7f26f0680202 | 139 | UCSR0B &= ~_BV(UDRIE0); //disable tx int |
networker | 0:7f26f0680202 | 140 | UCSR0B |= _BV(RXCIE0) | _BV(RXEN0); //re-enable rx int |
networker | 0:7f26f0680202 | 141 | rs485_timeout = 0; |
networker | 0:7f26f0680202 | 142 | } |
networker | 0:7f26f0680202 | 143 | else//send 1 byte too many in order to detect that the etx char was sent |
networker | 0:7f26f0680202 | 144 | UDR0 = ((char*)&msg)[rpos++]; |
networker | 0:7f26f0680202 | 145 | CLRPIN12; |
networker | 0:7f26f0680202 | 146 | } |
networker | 0:7f26f0680202 | 147 | |
networker | 0:7f26f0680202 | 148 | void timeout_rs485() |
networker | 0:7f26f0680202 | 149 | { SETPIN12; |
networker | 0:7f26f0680202 | 150 | //reset receiver |
networker | 0:7f26f0680202 | 151 | wposp = (char*)&msg.hdr.snd; |
networker | 0:7f26f0680202 | 152 | state = 0; |
networker | 0:7f26f0680202 | 153 | //reset transmitter |
networker | 0:7f26f0680202 | 154 | rpos = 0; |
networker | 0:7f26f0680202 | 155 | RECEIVE; |
networker | 0:7f26f0680202 | 156 | UCSR0B &= ~_BV(UDRIE0); //disable tx int |
networker | 0:7f26f0680202 | 157 | UCSR0B |= _BV(RXCIE0) | _BV(RXEN0); //re-enable rx int |
networker | 0:7f26f0680202 | 158 | CLRPIN12; |
networker | 0:7f26f0680202 | 159 | } |
networker | 0:7f26f0680202 | 160 | #endif |