Program the control the fischertechnik robo interface or intelligent interface via tcp socket or via a java gui.
rs485.cpp
- Committer:
- networker
- Date:
- 2010-12-31
- Revision:
- 0:7f26f0680202
File content as of revision 0:7f26f0680202:
#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; }