1 // Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the
14 // * All advertising materials mentioning features or use of this
15 // software must display the following acknowledgement: This product
16 // includes software developed by tm3d.de and its contributors.
17 // * Neither the name of tm3d.de nor the names of its contributors may
18 // be used to endorse or promote products derived from this software
19 // without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/types.h>
36 #include <sys/select.h>
39 #include <sys/ioctl.h>
44 #include "owARDUINOInterface.h"
46 #define MODE_DATA 0xE1
47 #define MODE_COMMAND 0xE3
50 #define PARMSET_9600 0x00
51 #define PARMSET_19200 0x02
52 #define PARMSET_57600 0x04
53 #define PARMSET_115200 0x06
57 #define COM_IDENTIFER 1
59 #define COM_SEARCH_INIT 3
60 #define COM_SEARCH_NEXT 4
67 //---------------------------------------------------------------------------
69 // flush the rx and tx buffers
71 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
72 // OpenCOM to indicate the port number.
74 void owARDUINOInterface::FlushCOM() {
75 tcflush(fd, TCIOFLUSH);
79 int owARDUINOInterface::OpenCOM(uint8_t comnr) {
80 struct termios t; // see man termios - declared as above
84 if (com_init) return fd;
86 sprintf(port_zstr,"/dev/ttyUSB%i",comnr);
88 fd = open(port_zstr, O_RDWR|O_NONBLOCK| O_NOCTTY );
91 log->set(OWLOG_ERROR,"ERROR open Com %s return %i",port_zstr,fd);
94 rc = tcgetattr (fd, &t);
101 log->set(OWLOG_ERROR,"OWERROR_SYSTEM_RESOURCE_INIT_FAILED %s",port_zstr);
102 return rc; // changed (2.00), used to return rc;
105 cfsetospeed(&t, B9600);
106 cfsetispeed (&t, B9600);
108 // Get terminal parameters. (2.00) removed raw
110 // Save original settings.
113 t.c_cflag &= ~PARENB; // Make 8n1
114 t.c_cflag &= ~CSTOPB;
118 t.c_cflag &= ~CRTSCTS; // no flow control
119 t.c_cc[VMIN] = 1; // read doesn't block
120 t.c_cc[VTIME] = 5; // 0.5 seconds read timeout
121 t.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
122 t.c_cflag &= ~CRTSCTS; // no flow control
123 t.c_iflag &= ~(IXON | IXOFF | IXANY);// turn off s/w flow ctrl
126 tcflush(fd,TCIOFLUSH);
128 rc = tcsetattr(fd, TCSAFLUSH, &t);
136 log->set(OWLOG_ERROR,"OWERROR_SYSTEM_RESOURCE_INIT_FAILED %s",port_zstr);
137 return rc; // changed (2.00), used to return rc;
140 return fd; // changed (2.00), used to return fd;
144 //---------------------------------------------------------------------------
145 // Closes the connection to the port.
147 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
148 // OpenCOM to indicate the port number.
150 void owARDUINOInterface::CloseCOM()
152 // restore tty settings
153 tcsetattr(fd, TCSAFLUSH, &origterm);
161 //--------------------------------------------------------------------------
162 // Write an array of bytes to the COM port, verify that it was
163 // sent out. Assume that baud rate has been set.
165 // 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will
166 // be used to indicate the port number desired when calling
167 // all other functions in this library.
168 // Returns 1 for success and 0 for failure
170 int owARDUINOInterface::WriteCOM( int outlen, uint8_t *outbuf)
174 for (int k=0;k<outlen;k++) {
175 i+= write(fd, outbuf+k, 1);
184 //--------------------------------------------------------------------------
185 // Read an array of bytes to the COM port, verify that it was
186 // sent out. Assume that baud rate has been set.
188 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
189 // OpenCOM to indicate the port number.
190 // 'outlen' - number of bytes to write to COM port
191 // 'outbuf' - pointer ot an array of bytes to write
193 // Returns: TRUE(1) - success
194 // FALSE(0) - failure
196 int owARDUINOInterface::ReadCOM( int inlen, uint8_t *inbuf)
202 // loop to wait until each byte is available and read it
203 for (cnt = 0; cnt < inlen; cnt++)
205 // set a descriptor to wait for a character available
207 FD_SET(fd,&filedescr);
208 // set timeout to 10ms
210 tval.tv_usec = 10000;
212 // if byte available read or return bytes read
213 if (select(fd+1,&filedescr,NULL,NULL,&tval) != 0)
215 if (read(fd,&inbuf[cnt],1) != 1) {
216 log->set(OWLOG_ERROR,"Read Error on Serial");
222 log->set(OWLOG_ERROR,"Read Error on Serial (select)");
228 // success, so return desired length
235 //--------------------------------------------------------------------------
237 // Send a break on the com port for at least 2 ms
239 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
240 // OpenCOM to indicate the port number.
242 void owARDUINOInterface::BreakCOM()
244 int duration = 0; // see man termios break may be
245 tcsendbreak(fd, duration); // too long
249 //--------------------------------------------------------------------------
250 // Set the baud rate on the com port.
252 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
253 // OpenCOM to indicate the port number.
254 // 'new_baud' - new baud rate defined as
256 // PARMSET_19200 0x02
257 // PARMSET_57600 0x04
258 // PARMSET_115200 0x06
260 void owARDUINOInterface::SetBaudCOM( uint8_t new_baud)
266 // read the attribute structure
267 rc = tcgetattr(fd, &t);
271 log->set(OWLOG_ERROR,"Error on Serial (set Boudrate)");
276 // convert parameter to linux baud rate
296 // set baud in structure
297 cfsetospeed(&t, baud);
298 cfsetispeed(&t, baud);
300 // change baud on port
301 rc = tcsetattr(fd, TCSAFLUSH, &t);
303 log->set(OWLOG_ERROR,"Error on Serial (set Boudrate)");
325 int owARDUINOInterface::InitAdapter(uint8_t nr) {
326 // attempt to open the communications port
327 if ((fd = OpenCOM(nr)) < 0)
329 log->set(OWLOG_ERROR,"OWERROR_OPENCOM_FAILED");
333 uint8_t readbuffer[20],sendpacket[20];
335 sendpacket[sendlen++]=0x01;
336 sendpacket[sendlen++]=0x00;
337 sendpacket[sendlen++]=0x03;
338 if (WriteCOM(sendlen,sendpacket)) {
339 if ((sendlen=ReadCOM(3,readbuffer)) == 3) {
341 // printf("%02X %02X %02X\n",readbuffer[0],readbuffer[1],readbuffer[2] );
346 //printf("%i\n",sendlen);
347 log->set(OWLOG_ERROR,"OWERROR_READCOM_FAILED");
349 } else log->set(OWLOG_ERROR,"OWERROR_WRITECOM_FAILED");
358 int owARDUINOInterface::owFirst() {
359 uint8_t readbuffer[20],sendpacket[20];
361 sendpacket[sendlen++]=0x03;
362 sendpacket[sendlen++]=0x00;
363 sendpacket[sendlen++]=0x08;
364 if (WriteCOM(sendlen,sendpacket)) {
365 if ((sendlen=ReadCOM(8,readbuffer)) == 8) {
366 if (readbuffer[0]!=0) {
367 for (int i=0;i<8;i++) ROM_NO[i]=readbuffer[i];
375 int owARDUINOInterface::owNext() {
376 uint8_t readbuffer[20],sendpacket[20];
378 sendpacket[sendlen++]=0x04;
379 sendpacket[sendlen++]=0x00;
380 sendpacket[sendlen++]=0x08;
381 if (WriteCOM(sendlen,sendpacket)) {
382 if ((sendlen=ReadCOM(8,readbuffer)) == 8) {
383 if (readbuffer[0]!=0) {
384 for (int i=0;i<8;i++) ROM_NO[i]=readbuffer[i];
394 void owARDUINOInterface::ReleaseAdapter() {
399 int owARDUINOInterface::Reset() {
400 uint8_t readbuffer[5],sendpacket[5];
404 if ((l=read(fd,readbuffer,5))>0) {
405 printf("in buf %i bytes %02X %02X %02X %02X %02X\n",l,readbuffer[0],readbuffer[1],readbuffer[2],readbuffer[3],readbuffer[4]);
408 sendpacket[sendlen++]=0x02;
409 sendpacket[sendlen++]=0x00;
410 sendpacket[sendlen++]=0x01;
411 if (WriteCOM(sendlen,sendpacket)) {
412 if ((sendlen=ReadCOM(1,readbuffer)) == 1) {
413 // printf("Reset %i\n",readbuffer[0]);
414 if (readbuffer[0]) return 1;
423 uint8_t owARDUINOInterface::sendrecivByte(uint8_t byte) {
425 uint8_t readbuffer[5],sendpacket[5];
428 if ((l=read(fd,readbuffer,5))>0) {
429 printf("in buf %i bytes %02X %02X %02X %02X %02X\n",l,readbuffer[0],readbuffer[1],readbuffer[2],readbuffer[3],readbuffer[4]);
433 sendpacket[sendlen++]=COM_SBYTE;
434 sendpacket[sendlen++]=0x01;
435 sendpacket[sendlen++]=0x01;
436 sendpacket[sendlen++]=byte;
437 if (WriteCOM(sendlen,sendpacket)) {
438 if ((sendlen=ReadCOM(1,readbuffer)) == 1) {
439 // printf("Send %02X %02X \n",byte,readbuffer[0]);
446 sendpacket[sendlen++]=COM_RBYTE;
447 sendpacket[sendlen++]=0x00;
448 sendpacket[sendlen++]=0x01;
449 if (WriteCOM(sendlen,sendpacket)) {
450 if ((sendlen=ReadCOM(1,readbuffer)) == 1) {
451 // printf("Recive %02X\n",readbuffer[0]);
452 return readbuffer[0];
460 uint8_t owARDUINOInterface::sendrecivBit(uint8_t bit) {
464 int owARDUINOInterface::Communicate(std::vector<uint8_t> *data, int scount, int rcount) {
466 data->resize(scount);
467 uint8_t readbuffer[128],sendpacket[128+3];
469 sendpacket[sendlen++]=COM_BLOCK;
470 sendpacket[sendlen++]=scount;
471 sendpacket[sendlen++]=rcount;
472 for(uint8_t v:*data) {
473 sendpacket[sendlen++]=v;
476 if (WriteCOM(sendlen,sendpacket)) {
477 if ((sendlen=ReadCOM(rcount,readbuffer)) == rcount) {
478 for(i=0;i<rcount;i++) {
479 //printf("%02X ",readbuffer[i]);
480 data->push_back(readbuffer[i]);