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.cpp	Fri Dec 31 14:01:14 2010 +0000
@@ -0,0 +1,187 @@
+#include "mbed.h"
+#include "data.h"
+
+#define TXMODE  true        /* level of eg. MAX485 input to switch to transmit mode */
+#define RXMODE  (!TXMODE)
+
+class rs485: public Serial, DigitalOut { //since communication is half duplex we use only one buffer for both reading and writing
+    char *buffer;
+    int index, length; //index is the buffer pointer, length is the length of the buffer
+    //bool receiving;
+    bool _done;
+    virtual void rx() { //ISR that stashes bytes until the buffer is full and then disables itself
+        //if (!receiving)return;
+        if (index<length)
+            buffer[index++] = getc();
+        else {
+            //receiving = false;
+            attach(0);
+            _done = true;
+        }
+    }
+    virtual void tx() { //ISR that sends out the entire buffer and then switches to receive mode
+        if (index<length)
+            putc(buffer[index++]);
+        else {
+            DigitalOut::write(RXMODE);
+            attach(this,&rs485::rx, RxIrq);
+            _done = true;
+        }
+    }
+public:
+    enum mode_t { rec, trans};
+    rs485(PinName out, PinName in, PinName dir): Serial(out, in), DigitalOut(dir) {
+        //attach(this, rx, RxIrq);
+        attach(this, &rs485::tx, TxIrq);
+        DigitalOut::write(RXMODE);
+        buffer = 0;
+        length = 0;
+        //receiving = false;
+    }
+    //void init(int br) {}
+    void send(char *buf, int len) {
+        DigitalOut::write(TXMODE);
+        buffer = buf;
+        length = len;
+        putc(*buffer);
+        index = 1;
+    }
+    void receive(char *buf, int len) {
+        buffer = buf;
+        length = len;
+        //receiving = true;
+        attach(this,&rs485::rx, RxIrq);
+    }
+    bool done() {
+        bool tmp = _done;
+        _done=false;
+        return tmp;
+    }
+    void setmode(enum mode_t m) {
+        if (m==rec)
+            DigitalOut::write(RXMODE);
+        else
+            DigitalOut::write(TXMODE);
+    }
+};
+
+
+//class specialized for use with the fischertechnik TXC
+class TXC_rs485: public rs485 {
+    message *msg; //pointer to a TXC message buffer
+    char *wp; //pointer where the receiver will write the data
+    int rpos; //index where the transmitter will read the data
+    virtual void rx(); //ISR
+    virtual void tx(); //ISR 
+    char state;  //receiver state
+    int rs485_timeout; // a timeout period, intended to reset the receiver when interrupts stop before the end of a message
+    int tx_message; //the destination of a received message, i.e. the slave address
+public:
+    TXC_rs485(PinName out, PinName in, PinName dir): rs485(out, in, dir) {
+        baud(921600);
+    }
+    void receive(message *m) {
+        state = 0;
+        msg = m;
+        wp = (char*)&msg->hdr.snd;
+    }
+    void send(message *m) {
+#if 1
+        rs485::send((char*)m, BYTES(msg)+7);//use base class for transmission
+#else
+        rpos = 0;
+        msg = m;
+//set RS485 tranceiver in send mode
+        setmode(trans);
+//disable rx interrupt
+        attach(0);
+//enable tx interrupt, will immediately generate int
+        attach(this, &TXC_rs485::tx, TxIrq);
+//kick off transmission
+//  putc((char*)msg)[rpos++];//not necessary, will start by itself
+        rs485_timeout = sizeof(message)/8; //just a precaution, transmit should not timeout, timeout is approx. 110% of expected time
+#endif
+    }
+
+    int Slave(bool clear=false) {//return the destination of the received packet, functions also as reception complete flag, is <0 when not yet available
+        int tmp = tx_message;
+        if (clear)
+            tx_message = -3;
+        return tmp;
+    }
+    void timeout();
+};
+
+void TXC_rs485::rx() {
+//  SETPIN12;
+    char data;
+    do {
+        data = getc();
+        rs485_timeout = 2;//set a timeout of 100-200us equiv. to 10-20 bytes
+        switch (state) {
+            case 0: //idle
+                if (data == 0x02)//stx
+                    state = 1;
+                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;
+                //length = (unsigned)data<<8;
+                state = 3;
+                break;
+            case 3://length L, low byte
+                msg->hdr.bytesH = data;
+                //length += 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;//ready for next message to receive
+                    rs485_timeout = 0;
+                    tx_message = msg->hdr.rec - 3;//slave address tx_message==0 means Ext.1 etc
+                    if (tx_message >= 0) {
+                        attach(0); //disable rec to avoid corruption by new messages
+                    }
+                    state = 0;
+                }
+                break;
+            default:
+                break;
+        }
+    } while (readable()); //see if another char is available, now it is fast enough so this is normally not the case
+//  CLRPIN12;
+}
+
+void TXC_rs485::tx() {// SETPIN12;
+    if (rpos > BYTES(msg)+7) { //last byte was sent
+        attach(0, TxIrq); //disable tx int
+        attach(this,&TXC_rs485::rx, RxIrq); //re-enable rx int
+        rs485_timeout = 0;
+    } else//send 1 byte too many in order to detect that the etx char was sent
+        putc(((char*)msg)[rpos++]);
+// CLRPIN12;
+}
+
+void TXC_rs485::timeout() {
+    //SETPIN12;
+    //reset receiver
+    wp = (char*)&msg->hdr.snd;
+    state = 0;
+    //reset transmitter
+    rpos = 0;
+    setmode(rec);
+    attach(0, TxIrq); //disable tx int
+    attach(this,&TXC_rs485::rx, RxIrq); //re-enable rx int
+    //CLRPIN12;
+}