Program the control the fischertechnik robo interface or intelligent interface via tcp socket or via a java gui.

Dependencies:   mbed ConfigFile

Revision:
0:7f26f0680202
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rs485.c	Fri Dec 31 14:01:14 2010 +0000
@@ -0,0 +1,160 @@
+//#define DEBUG //switches PB2 in interrupts and timeouts
+#if 0 //for reference only
+#define ALLOW_NESTING
+
+#include "data.h"
+#include "rs485.h"
+
+
+#define BAUD 921600
+#define DIRPORT    PORTD
+#define DIRBIT    PD4
+#define DIRDIR    DDRD
+#define TRANSMIT  asm("sbi    %0, %1"::"I" (_SFR_IO_ADDR(DIRPORT)),"I" (DIRBIT));
+#define RECEIVE      asm("cbi    %0, %1"::"I" (_SFR_IO_ADDR(DIRPORT)),"I" (DIRBIT));
+
+
+uint8_t /*wpos = 0,*/ rpos = 0;
+volatile uint8_t rs485_timeout = 0;
+volatile uint8_t rs485_delay = 0;
+static char* wposp = (char*)&msg.hdr.snd;
+static char state = 0;
+
+void init_rs485()
+{
+/*Set baud rate */
+//Enable receiver and transmitter (also interrupts)
+//  UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) /*| _BV(UDRIE0)*/;
+/* Set frame format: 8data, 1stop bit */
+//  UCSR0C = (3<<UCSZ00);
+//set tranceiver
+//  RECEIVE;
+//  DIRDIR  |= _BV(DIRBIT); //set enable as output
+}
+
+void enable_rx_rs485()
+{
+  UCSR0B |= _BV(RXEN0)  | _BV(RXCIE0); //enable uart rx
+  RECEIVE;
+}
+
+void send_rs485()
+{ rpos = 0;
+//set RS485 tranceiver in send mode
+  TRANSMIT;
+//disable rx interrupt
+  UCSR0B &= ~(_BV(RXCIE0) | _BV(RXEN0));
+//enable tx interrupt, will immediately generate int
+  UCSR0B |= _BV(UDRIE0);
+//kick off transmission
+//  UDR0 = ((char*)&msg)[rpos++];//not necessary, will start by itself
+  rs485_timeout = sizeof(msg)/8; //just a precaution, transmit should not timeout, timeout is approx. 110% of expected time
+}
+
+ISR(USART_RX_vect)
+{ 
+  SETPIN12;
+#ifdef ALLOW_NESTING
+  MASK_TIMER_INT();
+  MASK_EXTENSION_INT();
+  MASK_DISTANCE_INT();
+  MASK_IR_INT();
+  //MASK_EEPROM_INT();
+  sei(); 
+#endif
+  register char *wp asm("r30") = wposp;
+  register char data asm("r1");
+  do
+  { data = UDR0;
+    rs485_timeout = 2;//set a timeout of 100-200us equiv. to 10-20 bytes
+    switch (state)
+    { case 0: //idle
+             if (data == 0x02) 
+               state = 1;
+             else if (data == 0xA0)//this is really a hack, it avoids timeouts in case of a bad start
+               state = 5;
+             break;
+      case 1: //stx
+             if (data == 0x55) 
+               state = 2;
+             else
+               state = 0;
+             break;
+      case 2://length H, high byte comes first
+             msg.hdr.bytesL = data;
+             state = 3;
+             break;
+      case 3://length L, low byte
+             msg.hdr.bytesH = data;
+             if (msg.hdr.bytes > sizeof(msg)-7)
+               state = 0; //message structure cannot accomodate message this size
+             else
+               state = 4;
+             break;
+      case 4://store
+             *wp++ = data;
+             if (wp >= ((char*)&msg.hdr.snd + sizeof(trailer)) + msg.hdr.bytes
+                 && wp <= (char*)&msg + sizeof(message) + 1
+                )
+             { //message complete
+               wp = (char*)&msg.hdr.snd;
+               rs485_timeout = 0;
+               //tx_message = find_ad(msg.hdr.rec) > 0;
+               tx_message = msg.hdr.rec - 3;
+               if (tx_message >= 0)
+               { UCSR0B &= ~(_BV(RXCIE0) | _BV(RXEN0)); //disable rec to avoid corruption by new messages
+               }
+               state = 0;
+             }
+             break;
+      case 5://wrong start
+             if (data == 0x15)//after a wrong start A0 i.o. 02, the 55 gets read as 15
+             { msg.hdr.bytesL = 0;
+               state = 3;
+             }
+             else
+               state = 0;
+      default:
+             break;
+    }
+  } while (UCSR0A & _BV(RXC0)); //see if another char is available, now it is fast enough so this is normally not the case
+  wposp = wp;
+#ifdef ALLOW_NESTING
+  cli();
+  UNMASK_TIMER_INT();
+  UNMASK_EXTENSION_INT();
+  UNMASK_DISTANCE_INT();
+  UNMASK_IR_INT();
+  //UNMASK_EEPROM_INT();
+#endif
+  CLRPIN12;
+}
+
+
+ISR(USART_UDRE_vect)
+{ SETPIN12;
+  if (rpos > BYTES()+7)
+  { //last byte was sent
+    RECEIVE;
+    UCSR0B &= ~_BV(UDRIE0); //disable tx int
+    UCSR0B |= _BV(RXCIE0) | _BV(RXEN0); //re-enable rx int
+    rs485_timeout = 0;
+  }
+  else//send 1 byte too many in order to detect that the etx char was sent
+    UDR0 = ((char*)&msg)[rpos++];
+  CLRPIN12;
+}
+
+void timeout_rs485()
+{ SETPIN12;
+  //reset receiver
+  wposp = (char*)&msg.hdr.snd;
+  state = 0;
+  //reset transmitter
+  rpos = 0;
+  RECEIVE;
+  UCSR0B &= ~_BV(UDRIE0); //disable tx int
+  UCSR0B |= _BV(RXCIE0) | _BV(RXEN0); //re-enable rx int
+  CLRPIN12;
+}
+#endif