charinterface.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #include "charinterface.h"
15 //---------------------------------------------------------------------------
16 #include "measure.h"
17 #include "xnodeconnector.h"
18 #include <string>
19 #include <stdarg.h>
20 #include "driver.h"
21 #include "gpib.h"
22 #include "serial.h"
23 #include "tcp.h"
24 #include "dummyport.h"
25 
26 //---------------------------------------------------------------------------
27 #define SNPRINT_BUF_SIZE 128
28 
29 XThreadLocal<std::vector<char> > XCustomCharInterface::s_tlBuffer;
30 
31 XCustomCharInterface::XCustomCharInterface(const char *name, bool runtime, const shared_ptr<XDriver> &driver) :
32  XInterface(name, runtime, driver) {
33 
34 }
35 void
36 XCustomCharInterface::setEOS(const char *str) {
37  m_eos = str;
38 }
39 
40 int
41 XCustomCharInterface::scanf(const char *fmt, ...) const {
42  if( !buffer().size())
43  throw XConvError(__FILE__, __LINE__);
44  bool addednull = false;
45  if(buffer().back() != '\0') {
46  buffer_receive().push_back('\0');
47  addednull = true;
48  }
49 
50  int ret;
51  va_list ap;
52 
53  va_start(ap, fmt);
54 
55  ret = vsscanf( &buffer()[0], fmt, ap);
56 
57  va_end(ap);
58 
59  if(addednull)
60  buffer_receive().pop_back();
61  return ret;
62 }
63 double
64 XCustomCharInterface::toDouble() const throw (XConvError &) {
65  double x;
66  int ret = this->scanf("%lf", &x);
67  if(ret != 1)
68  throw XConvError(__FILE__, __LINE__);
69  return x;
70 }
71 int
72 XCustomCharInterface::toInt() const throw (XConvError &) {
73  int x;
74  int ret = this->scanf("%d", &x);
75  if(ret != 1)
76  throw XConvError(__FILE__, __LINE__);
77  return x;
78 }
79 unsigned int
80 XCustomCharInterface::toUInt() const throw (XConvError &) {
81  unsigned int x;
82  int ret = this->scanf("%u", &x);
83  if(ret != 1)
84  throw XConvError(__FILE__, __LINE__);
85  return x;
86 }
87 
88 XString
89 XCustomCharInterface::toStr() const {
90  return XString( &buffer()[0]);
91 }
92 XString
94  return QString( &buffer()[0]).simplified();
95 }
96 void
97 XCustomCharInterface::query(const XString &str) throw (XCommError &) {
98  query(str.c_str());
99 }
100 
101 void
102 XCustomCharInterface::sendf(const char *fmt, ...) throw (XInterfaceError &) {
103  va_list ap;
104  int buf_size = SNPRINT_BUF_SIZE;
105  std::vector<char> buf;
106  for(;;) {
107  buf.resize(buf_size);
108  int ret;
109 
110  va_start(ap, fmt);
111 
112  ret = vsnprintf(&buf[0], buf_size, fmt, ap);
113 
114  va_end(ap);
115 
116  if(ret < 0) throw XConvError(__FILE__, __LINE__);
117  if(ret < buf_size) break;
118 
119  buf_size *= 2;
120  }
121 
122  this->send(&buf[0]);
123 }
124 
125 void
126 XCustomCharInterface::query(const char *str) throw (XCommError &) {
127  XScopedLock<XInterface> lock(*this);
128  send(str);
129  receive();
130 }
131 void
132 XCustomCharInterface::queryf(const char *fmt, ...) throw (XInterfaceError &) {
133  va_list ap;
134  int buf_size = SNPRINT_BUF_SIZE;
135  std::vector<char> buf;
136  for(;;) {
137  buf.resize(buf_size);
138  int ret;
139 
140  va_start(ap, fmt);
141 
142  ret = vsnprintf(&buf[0], buf_size, fmt, ap);
143 
144  va_end(ap);
145 
146  if(ret < 0) throw XConvError(__FILE__, __LINE__);
147  if(ret < buf_size) break;
148 
149  buf_size *= 2;
150  }
151 
152  this->query(&buf[0]);
153 }
154 
155 
156 XCharInterface::XCharInterface(const char *name, bool runtime, const shared_ptr<XDriver> &driver) :
157  XCustomCharInterface(name, runtime, driver),
158  m_serialEOS("\n"),
159  m_bGPIBUseSerialPollOnWrite(true),
160  m_bGPIBUseSerialPollOnRead(true),
161  m_gpibWaitBeforeWrite(1),
162  m_gpibWaitBeforeRead(2),
163  m_gpibWaitBeforeSPoll(1),
164  m_gpibMAVbit(0x10),
165  m_serialBaudRate(9600),
166  m_serialStopBits(2),
167  m_serialParity(PARITY_NONE),
168  m_serial7Bits(false),
169  m_serialFlushBeforeWrite(true),
170  m_serialHasEchoBack(false),
171  m_script_send(create<XStringNode>("Send", true)),
172  m_script_query(create<XStringNode>("Query", true)) {
173 
174  iterate_commit([=](Transaction &tr){
175  #ifdef USE_GPIB
176  tr[ *device()].add("GPIB");
177  #endif
178  #ifdef USE_SERIAL
179  tr[ *device()].add("SERIAL");
180  #endif
181  #ifdef USE_TCP
182  tr[ *device()].add("TCP/IP");
183  #endif
184  tr[ *device()].add("DUMMY");
185 
186  m_lsnOnSendRequested = tr[ *m_script_send].onValueChanged().connectWeakly(
187  shared_from_this(), &XCharInterface::onSendRequested);
188  m_lsnOnQueryRequested = tr[ *m_script_query].onValueChanged().connectWeakly(
189  shared_from_this(), &XCharInterface::onQueryRequested);
190  });
191 }
192 
193 void
194 XCharInterface::open() throw (XInterfaceError &) {
195  m_xport.reset();
196  Snapshot shot( *this);
197  {
198  shared_ptr<XPort> port;
199  #ifdef USE_GPIB
200  if(shot[ *device()].to_str() == "GPIB") {
201  port.reset(new XGPIBPort(this));
202  port->setEOS(eos().c_str());
203  }
204  #endif
205  #ifdef USE_SERIAL
206  if(shot[ *device()].to_str() == "SERIAL") {
207  port.reset(new XSerialPort(this));
208  const char *seos = eos().length() ? eos().c_str() : serialEOS().c_str();
209  port->setEOS(seos);
210  }
211  #endif
212  #ifdef USE_TCP
213  if(shot[ *device()].to_str() == "TCP/IP") {
214  port.reset(new XTCPPort(this));
215  port->setEOS(eos().c_str());
216  }
217  #endif
218  if(shot[ *device()].to_str() == "DUMMY") {
219  port.reset(new XDummyPort(this));
220  port->setEOS(eos().c_str());
221  }
222 
223  if( !port) {
224  throw XOpenInterfaceError(__FILE__, __LINE__);
225  }
226  port->open(this);
227  m_xport.swap(port);
228  }
229 }
230 void
231 XCharInterface::close() throw (XInterfaceError &) {
232  m_xport.reset();
233 }
234 
235 void
236 XCharInterface::send(const XString &str) throw (XCommError &) {
237  this->send(str.c_str());
238 }
239 
240 void
241 XCharInterface::send(const char *str) throw (XCommError &) {
242  XScopedLock<XCharInterface> lock(*this);
243  try {
244  dbgPrint(driver()->getLabel() + " Sending:\"" + dumpCString(str) + "\"");
245  m_xport->send(str);
246  }
247  catch (XCommError &e) {
248  e.print(driver()->getLabel() + i18n(" SendError, because "));
249  throw e;
250  }
251 }
252 void
253 XCharInterface::write(const char *sendbuf, int size) throw (XCommError &) {
254  XScopedLock<XCharInterface> lock(*this);
255  try {
256  dbgPrint(driver()->getLabel() + formatString(" Sending %d bytes", size));
257  m_xport->write(sendbuf, size);
258  }
259  catch (XCommError &e) {
260  e.print(driver()->getLabel() + i18n(" SendError, because "));
261  throw e;
262  }
263 }
264 void
265 XCharInterface::receive() throw (XCommError &) {
266  XScopedLock<XCharInterface> lock(*this);
267  try {
268  dbgPrint(driver()->getLabel() + " Receiving...");
269  m_xport->receive();
270  assert(buffer().size());
271  dbgPrint(driver()->getLabel() + " Received;\"" +
272  dumpCString((const char*)&buffer()[0]) + "\"");
273  }
274  catch (XCommError &e) {
275  e.print(driver()->getLabel() + i18n(" ReceiveError, because "));
276  throw e;
277  }
278 }
279 void
280 XCharInterface::receive(unsigned int length) throw (XCommError &) {
281  XScopedLock<XCharInterface> lock(*this);
282  try {
283  dbgPrint(driver()->getLabel() + QString(" Receiving %1 bytes...").arg(length));
284  m_xport->receive(length);
285  dbgPrint(driver()->getLabel() + QString(" %1 bytes Received.").arg(buffer().size()));
286  }
287  catch (XCommError &e) {
288  e.print(driver()->getLabel() + i18n(" ReceiveError, because "));
289  throw e;
290  }
291 }
292 void
293 XCharInterface::onSendRequested(const Snapshot &shot, XValueNodeBase *) {
294  XScopedLock<XCharInterface> lock( *this);
295  if(!isOpened())
296  throw XInterfaceError(i18n("Port is not opened."), __FILE__, __LINE__);
297  this->send(shot[ *m_script_send].to_str());
298 }
299 void
300 XCharInterface::onQueryRequested(const Snapshot &shot, XValueNodeBase *) {
301  XScopedLock<XCharInterface> lock( *this);
302  if(!isOpened())
303  throw XInterfaceError(i18n("Port is not opened."), __FILE__, __LINE__);
304  this->query(shot[ *m_script_query].to_str());
305  iterate_commit([=](Transaction &tr){
306  tr[ *m_script_query] = XString(&buffer()[0]);
307  tr.unmark(m_lsnOnQueryRequested);
308  });
309 }

Generated for KAME4 by  doxygen 1.8.3