Program the control the fischertechnik robo interface or intelligent interface via tcp socket or via a java gui.
rs485.cpp@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 | #include "mbed.h" |
networker | 0:7f26f0680202 | 2 | #include "data.h" |
networker | 0:7f26f0680202 | 3 | |
networker | 0:7f26f0680202 | 4 | #define TXMODE true /* level of eg. MAX485 input to switch to transmit mode */ |
networker | 0:7f26f0680202 | 5 | #define RXMODE (!TXMODE) |
networker | 0:7f26f0680202 | 6 | |
networker | 0:7f26f0680202 | 7 | class rs485: public Serial, DigitalOut { //since communication is half duplex we use only one buffer for both reading and writing |
networker | 0:7f26f0680202 | 8 | char *buffer; |
networker | 0:7f26f0680202 | 9 | int index, length; //index is the buffer pointer, length is the length of the buffer |
networker | 0:7f26f0680202 | 10 | //bool receiving; |
networker | 0:7f26f0680202 | 11 | bool _done; |
networker | 0:7f26f0680202 | 12 | virtual void rx() { //ISR that stashes bytes until the buffer is full and then disables itself |
networker | 0:7f26f0680202 | 13 | //if (!receiving)return; |
networker | 0:7f26f0680202 | 14 | if (index<length) |
networker | 0:7f26f0680202 | 15 | buffer[index++] = getc(); |
networker | 0:7f26f0680202 | 16 | else { |
networker | 0:7f26f0680202 | 17 | //receiving = false; |
networker | 0:7f26f0680202 | 18 | attach(0); |
networker | 0:7f26f0680202 | 19 | _done = true; |
networker | 0:7f26f0680202 | 20 | } |
networker | 0:7f26f0680202 | 21 | } |
networker | 0:7f26f0680202 | 22 | virtual void tx() { //ISR that sends out the entire buffer and then switches to receive mode |
networker | 0:7f26f0680202 | 23 | if (index<length) |
networker | 0:7f26f0680202 | 24 | putc(buffer[index++]); |
networker | 0:7f26f0680202 | 25 | else { |
networker | 0:7f26f0680202 | 26 | DigitalOut::write(RXMODE); |
networker | 0:7f26f0680202 | 27 | attach(this,&rs485::rx, RxIrq); |
networker | 0:7f26f0680202 | 28 | _done = true; |
networker | 0:7f26f0680202 | 29 | } |
networker | 0:7f26f0680202 | 30 | } |
networker | 0:7f26f0680202 | 31 | public: |
networker | 0:7f26f0680202 | 32 | enum mode_t { rec, trans}; |
networker | 0:7f26f0680202 | 33 | rs485(PinName out, PinName in, PinName dir): Serial(out, in), DigitalOut(dir) { |
networker | 0:7f26f0680202 | 34 | //attach(this, rx, RxIrq); |
networker | 0:7f26f0680202 | 35 | attach(this, &rs485::tx, TxIrq); |
networker | 0:7f26f0680202 | 36 | DigitalOut::write(RXMODE); |
networker | 0:7f26f0680202 | 37 | buffer = 0; |
networker | 0:7f26f0680202 | 38 | length = 0; |
networker | 0:7f26f0680202 | 39 | //receiving = false; |
networker | 0:7f26f0680202 | 40 | } |
networker | 0:7f26f0680202 | 41 | //void init(int br) {} |
networker | 0:7f26f0680202 | 42 | void send(char *buf, int len) { |
networker | 0:7f26f0680202 | 43 | DigitalOut::write(TXMODE); |
networker | 0:7f26f0680202 | 44 | buffer = buf; |
networker | 0:7f26f0680202 | 45 | length = len; |
networker | 0:7f26f0680202 | 46 | putc(*buffer); |
networker | 0:7f26f0680202 | 47 | index = 1; |
networker | 0:7f26f0680202 | 48 | } |
networker | 0:7f26f0680202 | 49 | void receive(char *buf, int len) { |
networker | 0:7f26f0680202 | 50 | buffer = buf; |
networker | 0:7f26f0680202 | 51 | length = len; |
networker | 0:7f26f0680202 | 52 | //receiving = true; |
networker | 0:7f26f0680202 | 53 | attach(this,&rs485::rx, RxIrq); |
networker | 0:7f26f0680202 | 54 | } |
networker | 0:7f26f0680202 | 55 | bool done() { |
networker | 0:7f26f0680202 | 56 | bool tmp = _done; |
networker | 0:7f26f0680202 | 57 | _done=false; |
networker | 0:7f26f0680202 | 58 | return tmp; |
networker | 0:7f26f0680202 | 59 | } |
networker | 0:7f26f0680202 | 60 | void setmode(enum mode_t m) { |
networker | 0:7f26f0680202 | 61 | if (m==rec) |
networker | 0:7f26f0680202 | 62 | DigitalOut::write(RXMODE); |
networker | 0:7f26f0680202 | 63 | else |
networker | 0:7f26f0680202 | 64 | DigitalOut::write(TXMODE); |
networker | 0:7f26f0680202 | 65 | } |
networker | 0:7f26f0680202 | 66 | }; |
networker | 0:7f26f0680202 | 67 | |
networker | 0:7f26f0680202 | 68 | |
networker | 0:7f26f0680202 | 69 | //class specialized for use with the fischertechnik TXC |
networker | 0:7f26f0680202 | 70 | class TXC_rs485: public rs485 { |
networker | 0:7f26f0680202 | 71 | message *msg; //pointer to a TXC message buffer |
networker | 0:7f26f0680202 | 72 | char *wp; //pointer where the receiver will write the data |
networker | 0:7f26f0680202 | 73 | int rpos; //index where the transmitter will read the data |
networker | 0:7f26f0680202 | 74 | virtual void rx(); //ISR |
networker | 0:7f26f0680202 | 75 | virtual void tx(); //ISR |
networker | 0:7f26f0680202 | 76 | char state; //receiver state |
networker | 0:7f26f0680202 | 77 | int rs485_timeout; // a timeout period, intended to reset the receiver when interrupts stop before the end of a message |
networker | 0:7f26f0680202 | 78 | int tx_message; //the destination of a received message, i.e. the slave address |
networker | 0:7f26f0680202 | 79 | public: |
networker | 0:7f26f0680202 | 80 | TXC_rs485(PinName out, PinName in, PinName dir): rs485(out, in, dir) { |
networker | 0:7f26f0680202 | 81 | baud(921600); |
networker | 0:7f26f0680202 | 82 | } |
networker | 0:7f26f0680202 | 83 | void receive(message *m) { |
networker | 0:7f26f0680202 | 84 | state = 0; |
networker | 0:7f26f0680202 | 85 | msg = m; |
networker | 0:7f26f0680202 | 86 | wp = (char*)&msg->hdr.snd; |
networker | 0:7f26f0680202 | 87 | } |
networker | 0:7f26f0680202 | 88 | void send(message *m) { |
networker | 0:7f26f0680202 | 89 | #if 1 |
networker | 0:7f26f0680202 | 90 | rs485::send((char*)m, BYTES(msg)+7);//use base class for transmission |
networker | 0:7f26f0680202 | 91 | #else |
networker | 0:7f26f0680202 | 92 | rpos = 0; |
networker | 0:7f26f0680202 | 93 | msg = m; |
networker | 0:7f26f0680202 | 94 | //set RS485 tranceiver in send mode |
networker | 0:7f26f0680202 | 95 | setmode(trans); |
networker | 0:7f26f0680202 | 96 | //disable rx interrupt |
networker | 0:7f26f0680202 | 97 | attach(0); |
networker | 0:7f26f0680202 | 98 | //enable tx interrupt, will immediately generate int |
networker | 0:7f26f0680202 | 99 | attach(this, &TXC_rs485::tx, TxIrq); |
networker | 0:7f26f0680202 | 100 | //kick off transmission |
networker | 0:7f26f0680202 | 101 | // putc((char*)msg)[rpos++];//not necessary, will start by itself |
networker | 0:7f26f0680202 | 102 | rs485_timeout = sizeof(message)/8; //just a precaution, transmit should not timeout, timeout is approx. 110% of expected time |
networker | 0:7f26f0680202 | 103 | #endif |
networker | 0:7f26f0680202 | 104 | } |
networker | 0:7f26f0680202 | 105 | |
networker | 0:7f26f0680202 | 106 | int Slave(bool clear=false) {//return the destination of the received packet, functions also as reception complete flag, is <0 when not yet available |
networker | 0:7f26f0680202 | 107 | int tmp = tx_message; |
networker | 0:7f26f0680202 | 108 | if (clear) |
networker | 0:7f26f0680202 | 109 | tx_message = -3; |
networker | 0:7f26f0680202 | 110 | return tmp; |
networker | 0:7f26f0680202 | 111 | } |
networker | 0:7f26f0680202 | 112 | void timeout(); |
networker | 0:7f26f0680202 | 113 | }; |
networker | 0:7f26f0680202 | 114 | |
networker | 0:7f26f0680202 | 115 | void TXC_rs485::rx() { |
networker | 0:7f26f0680202 | 116 | // SETPIN12; |
networker | 0:7f26f0680202 | 117 | char data; |
networker | 0:7f26f0680202 | 118 | do { |
networker | 0:7f26f0680202 | 119 | data = getc(); |
networker | 0:7f26f0680202 | 120 | rs485_timeout = 2;//set a timeout of 100-200us equiv. to 10-20 bytes |
networker | 0:7f26f0680202 | 121 | switch (state) { |
networker | 0:7f26f0680202 | 122 | case 0: //idle |
networker | 0:7f26f0680202 | 123 | if (data == 0x02)//stx |
networker | 0:7f26f0680202 | 124 | state = 1; |
networker | 0:7f26f0680202 | 125 | break; |
networker | 0:7f26f0680202 | 126 | case 1: //stx |
networker | 0:7f26f0680202 | 127 | if (data == 0x55) |
networker | 0:7f26f0680202 | 128 | state = 2; |
networker | 0:7f26f0680202 | 129 | else |
networker | 0:7f26f0680202 | 130 | state = 0; |
networker | 0:7f26f0680202 | 131 | break; |
networker | 0:7f26f0680202 | 132 | case 2://length H, high byte comes first |
networker | 0:7f26f0680202 | 133 | msg->hdr.bytesL = data; |
networker | 0:7f26f0680202 | 134 | //length = (unsigned)data<<8; |
networker | 0:7f26f0680202 | 135 | state = 3; |
networker | 0:7f26f0680202 | 136 | break; |
networker | 0:7f26f0680202 | 137 | case 3://length L, low byte |
networker | 0:7f26f0680202 | 138 | msg->hdr.bytesH = data; |
networker | 0:7f26f0680202 | 139 | //length += data; |
networker | 0:7f26f0680202 | 140 | if (msg->hdr.bytes > sizeof(msg)-7) |
networker | 0:7f26f0680202 | 141 | state = 0; //message structure cannot accomodate message this size |
networker | 0:7f26f0680202 | 142 | else |
networker | 0:7f26f0680202 | 143 | state = 4; |
networker | 0:7f26f0680202 | 144 | break; |
networker | 0:7f26f0680202 | 145 | case 4://store |
networker | 0:7f26f0680202 | 146 | *wp++ = data; |
networker | 0:7f26f0680202 | 147 | if (wp >= ((char*)&msg->hdr.snd + sizeof(trailer)) + msg->hdr.bytes |
networker | 0:7f26f0680202 | 148 | && wp <= (char*)msg + sizeof(message) + 1 |
networker | 0:7f26f0680202 | 149 | ) { //message complete |
networker | 0:7f26f0680202 | 150 | wp = (char*)&msg->hdr.snd;//ready for next message to receive |
networker | 0:7f26f0680202 | 151 | rs485_timeout = 0; |
networker | 0:7f26f0680202 | 152 | tx_message = msg->hdr.rec - 3;//slave address tx_message==0 means Ext.1 etc |
networker | 0:7f26f0680202 | 153 | if (tx_message >= 0) { |
networker | 0:7f26f0680202 | 154 | attach(0); //disable rec to avoid corruption by new messages |
networker | 0:7f26f0680202 | 155 | } |
networker | 0:7f26f0680202 | 156 | state = 0; |
networker | 0:7f26f0680202 | 157 | } |
networker | 0:7f26f0680202 | 158 | break; |
networker | 0:7f26f0680202 | 159 | default: |
networker | 0:7f26f0680202 | 160 | break; |
networker | 0:7f26f0680202 | 161 | } |
networker | 0:7f26f0680202 | 162 | } while (readable()); //see if another char is available, now it is fast enough so this is normally not the case |
networker | 0:7f26f0680202 | 163 | // CLRPIN12; |
networker | 0:7f26f0680202 | 164 | } |
networker | 0:7f26f0680202 | 165 | |
networker | 0:7f26f0680202 | 166 | void TXC_rs485::tx() {// SETPIN12; |
networker | 0:7f26f0680202 | 167 | if (rpos > BYTES(msg)+7) { //last byte was sent |
networker | 0:7f26f0680202 | 168 | attach(0, TxIrq); //disable tx int |
networker | 0:7f26f0680202 | 169 | attach(this,&TXC_rs485::rx, RxIrq); //re-enable rx int |
networker | 0:7f26f0680202 | 170 | rs485_timeout = 0; |
networker | 0:7f26f0680202 | 171 | } else//send 1 byte too many in order to detect that the etx char was sent |
networker | 0:7f26f0680202 | 172 | putc(((char*)msg)[rpos++]); |
networker | 0:7f26f0680202 | 173 | // CLRPIN12; |
networker | 0:7f26f0680202 | 174 | } |
networker | 0:7f26f0680202 | 175 | |
networker | 0:7f26f0680202 | 176 | void TXC_rs485::timeout() { |
networker | 0:7f26f0680202 | 177 | //SETPIN12; |
networker | 0:7f26f0680202 | 178 | //reset receiver |
networker | 0:7f26f0680202 | 179 | wp = (char*)&msg->hdr.snd; |
networker | 0:7f26f0680202 | 180 | state = 0; |
networker | 0:7f26f0680202 | 181 | //reset transmitter |
networker | 0:7f26f0680202 | 182 | rpos = 0; |
networker | 0:7f26f0680202 | 183 | setmode(rec); |
networker | 0:7f26f0680202 | 184 | attach(0, TxIrq); //disable tx int |
networker | 0:7f26f0680202 | 185 | attach(this,&TXC_rs485::rx, RxIrq); //re-enable rx int |
networker | 0:7f26f0680202 | 186 | //CLRPIN12; |
networker | 0:7f26f0680202 | 187 | } |