Cat
MSOxxxx.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 //
3 // Package : MSOxxxx
4 //
5 // Description:
6 //
7 // Author(s) : Joan Mauricio
8 // Date : 2014/06/05
9 //
10 //------------------------------------------------------------------------------
11 
12 // local include file
13 #include "MSOxxxx.h"
14 
15 //Constructor
17 {
18  setType("MSOxxxx");
19  setId(0);
20 
22  debug("MSOxxxx built.","MSOxxxx::MSOxxxx");
23 
24  ipAddress = DEFAULT_IP_ADDRESS; //We configure a default IP here. User can change it afterwards.
27 
28 }
29 
33 
34 void MSOxxxx::configTCPIP(string ip, int port) //IP and TCP port configuration.
35 {
36  if(ip!= "DEFAULT") //IP is only changed when the input string is different to "DEFAULT".
37  ipAddress = ip;
38  if(port > 0) //Port is only changed when the input value is greater than 0.
39  portNumber = port;
40 }
41 
43 {
44  struct hostent *server;
45  struct sockaddr_in servAddr;
46 
47  info("IP address / TCP Port: " + ipAddress + " / " + itos(portNumber),"MSOxxxx::open");
48 
49  sockfd = socket(AF_INET, SOCK_STREAM, 0);
50  if (sockfd < 0)
51  {
52  error("ERROR opening socket","MSOxxxx::open");
53  return StatusCode::FAILURE;
54  }
55  else
56  {
57  server = gethostbyname(ipAddress.c_str());
58  if (server == NULL)
59  {
60  error("No such host.","MSOxxxx::open");
61  return StatusCode::FAILURE;
62  }
63  else
64  {
65  bzero((char *) &servAddr, sizeof(servAddr));
66  servAddr.sin_family = AF_INET;
67  bcopy((char *)server->h_addr, (char *)&servAddr.sin_addr.s_addr, server->h_length);
68  servAddr.sin_port = htons(portNumber);
69 
70  if (connect(sockfd,(struct sockaddr *) &servAddr,sizeof(servAddr)) < 0) //Socket is opened here.
71  {
72  error("Connection could not be established.","MSOxxxx::open");
73  return StatusCode::FAILURE;
74  }
75  else
76  info("Connection established.","MSOxxxx::open");
77  return StatusCode::SUCCESS;
78  }
79  }
80 }
81 
82 //Sends the message to the oscilloscope. If something goes wrong, it will report it.
83 bool MSOxxxx::send(string msg)
84 {
85  if(debugMode)
86  info(msg,"MSOxxxx::send");
87 
88  int n = write(sockfd,msg.c_str(),msg.length());
89  if (n < 0)
90  {
91  error("Socket write error.","MSOxxxx::send");
92  return false;
93  }
94  else return true;
95 }
96 
97 int MSOxxxx::recv(string *msgItems, string spacer=",")
98 {
99  string rxMsg;
100  int nRead, nItems, buffPos=0;
101  bool endData=false;
102 
103  do //Data is stored in 'rxBuffer', a 1-MByte private char*.
104  {
105  nRead = read(sockfd,rxBuffer+buffPos,MAX_LEN); //Data is appended to 'rxBuffer'
106  buffPos += nRead;
107  if(nRead > 0) //until '\n' is found, or error.
108  {
109  if(rxBuffer[buffPos-1] == '\n') endData = true;
110  }
111  else endData = true;
112  }
113  while(!endData);
114 
115  if(nRead == -1) //Error handling.
116  {
117  error("Socket read error.","MSOxxxx::recv");
118  return -1;
119  }
120  else //The char* is converted to an array of strings.
121  {
122  rxBuffer[buffPos-1] = '\0'; //IMPORTANT!!! char* delimiter!!!
123  rxMsg = string(rxBuffer); //To string.
124  nItems = split(rxMsg,msgItems,spacer); //To an array of strings.
125 
126  if(debugMode)
127  info(rxMsg,"MSOxxxx::recv");
128 
129  return nItems;
130  }
131 }
132 
136 
137 StatusCode MSOxxxx::channelScale(int ch, double value)
138 {
139  bool ok = send(":CHANNEL" + itos(ch) + ":SCALE " + ftos(value) + "\n");
140  if(ok) return StatusCode::SUCCESS;
141  else return StatusCode::FAILURE;
142 }
143 
144 StatusCode MSOxxxx::channelOffset(int ch, double value)
145 {
146  bool ok = send(":CHANNEL" + itos(ch) + ":OFFSET " + ftos(value) + "\n");
147  if(ok) return StatusCode::SUCCESS;
148  else return StatusCode::FAILURE;
149 }
150 
151 StatusCode MSOxxxx::channelDisplay(int ch, bool display)
152 {
153  bool ok;
154  if(display)
155  ok = send(":CHANNEL" + itos(ch) + ":DISPLAY ON \n");
156  else
157  ok = send(":CHANNEL" + itos(ch) + ":DISPLAY OFF \n");
158  if(ok) return StatusCode::SUCCESS;
159  else return StatusCode::FAILURE;
160 }
161 
163 {
164  bool ok = send(":CHANNEL" + itos(ch) + ":LABEL \"" + name + "\" \n");
165  if(ok) return StatusCode::SUCCESS;
166  else return StatusCode::FAILURE;
167 }
168 
172 
174 {
175  bool ok = send(":TIMEBASE:SCALE " + ftos(secsPerDiv) + " \n");
176  if(ok) return StatusCode::SUCCESS;
177  else return StatusCode::FAILURE;
178 }
179 
181 {
182  bool ok = send(":TIMEBASE:POSITION " + ftos(seconds) + " \n");
183  if(ok) return StatusCode::SUCCESS;
184  else return StatusCode::FAILURE;
185 }
186 
187 bool MSOxxxx::getTimeBase(double *xInc, double *xOrg)
188 {
189  bool ok;
190  int nRxItems;
191 
192  ok = send(":WAVeform:XINCrement?\n");
193  nRxItems = recv(rxItems);
194  if(ok && nRxItems > 0)
195  {
196  *xInc = atof(rxItems[0].c_str());
197  send(":WAVeform:XORigin?\n");
198  nRxItems = recv(rxItems);
199 
200  if(ok && nRxItems > 0)
201  {
202  *xOrg = atof(rxItems[0].c_str());
203  return true;
204  }
205  else return false;
206  }
207  else return false;
208 }
209 
213 
215 {
216  bool ok = send(":TRIGger:SWEep AUTO\n");
217  if(ok) return StatusCode::SUCCESS;
218  else return StatusCode::FAILURE;
219 }
220 
221 StatusCode MSOxxxx::triggerConfig(bool slope, int ch, double level)
222 {
223  bool ok;
224 
225  if(slope) ok = send(":TRIGger:EDGE:SLOpe POSitive\n");
226  else ok = send(":TRIGger:EDGE:SLOpe NEGative\n");
227  ok |= send(":TRIGger:EDGE:SOURce CHANnel" + itos(ch) + " \n");
228  ok |= send(":TRIGger:LEVel CHANnel" + itos(ch) + "," + ftos(level) + " \n");
229  if(ok) return StatusCode::SUCCESS;
230  else return StatusCode::FAILURE;
231 }
232 
236 
237 //Configures Jitter measurement.
239 {
240  bool ok;
241  //Previous measures are cleared, and period measurement in statistics mode is configured.
242  ok = send(":MEASure:CLEar\n");
243  ok |= send(":SYSTem:HEADer OFF\n");
244  ok |= send(":MEASure:STATistics ON\n");
245  ok |= send(":MEASure:PERiod CHAnnel"+itos(ch)+"\n");
246 
247  if(ok) return StatusCode::SUCCESS;
248  else return StatusCode::FAILURE;
249 }
250 
251 //Configures delta time measurement.
252 StatusCode MSOxxxx::setupDeltaTime(int chA,int chB,int edge)
253 {
254  bool ok;
255  ok = send(":MEASure:CLEar\n");
256  ok |= send(":MEASure:DELTatime:DEFine RISing,1,MIDDle,RISing,"+itos(edge)+",MIDDle\n");
257  ok |= send(":MEASure:STATistics ON\n");
258  ok |= send(":MEASure:DELTatime CHANNel"+itos(chA)+",CHANNel"+itos(chB)+"\n");
259 
260  if(ok) return StatusCode::SUCCESS;
261  else return StatusCode::FAILURE;
262 }
263 
264 //Configures Average voltage measurement.
266 {
267  bool ok;
268  ok = send(":MEASure:CLEar\n");
269  ok |= send(":SYSTem:HEADer OFF\n");
270  ok |= send(":MEASure:STATistics ON\n");
271  ok |= send(":MEASURE:VAVERAGE DISPLAY,CHANNEL"+itos(ch)+"\n");
272 
273  if(ok) return StatusCode::SUCCESS;
274  else return StatusCode::FAILURE;
275 }
276 
277 PyObject* MSOxxxx::waveformCapture(int ch)
278 {
279  PyObject* waveform = PyList_New(0);
280  double xOrigin, xIncrement;
281  int nRxItems, iItems;
282  bool ok;
283 
284  ok = getTimeBase(&xIncrement, &xOrigin);
285  ok |= send(":RUN \n"); //We get sure that oscilloscope is in RUN mode.
286  ok |= send(":DIGitize CHANnel"+itos(ch)+"\n"); //Select channel
287  ok |= send(":CHANnel"+itos(ch)+":DISPlay ON\n"); //Enable display of channel
288  ok |= send(":WAVeform:FORMat ASCii\n"); //Setup transfer format
289  ok |= send(":WAVeform:BYTeorder LSBFirst\n");
290  ok |= send(":WAVeform:SOURce CHANnel"+itos(ch)+"\n"); //Waveform data source channel
291  ok |= send(":WAVeform:STReaming 1\n"); //Turn on waveform streaming of data
292  ok |= send(":WAVeform:DATA?\n"); //Retrieves data.
293 
294  nRxItems = recv(rxItems); //Data is received here.
295  ok |= send(":RUN \n"); //Once done, let's push 'run' button again.
296 
297  if(ok)
298  {
299  for(iItems=0 ; iItems<nRxItems-1 ; iItems++)
300  {
301  //Pair list items are timestamps.
302  //Odd list items are amplitude values.
303  PyList_Append(waveform, PyFloat_FromDouble(((double)iItems * xIncrement) + xOrigin));
304  PyList_Append(waveform, PyFloat_FromDouble(atof(rxItems[iItems].c_str())));
305  }
306  }
307  return waveform;
308 }
309 
310 //Returns a list with the min, max, mean and stedev of 'nMinMeas' measured samples.
311 PyObject* MSOxxxx::getStatistics(int nMinMeas)
312 {
313  bool ok = true;
314  int nRxItems=7, nMeas=0;
315  PyObject* statistics = PyList_New(0);
316 
317  //We do that until we have enough statistics and everything is ok.
318  while(ok && nRxItems == 7 && nMeas < nMinMeas)
319  {
320  sleep(1); //Wait 1 second...
321  ok |= send(":MEASure:Results?\n"); //Ask for the statistics.
322  nRxItems = recv(rxItems); //Statistics are received.
323  nMeas = (int) atof(rxItems[6].c_str()); //The last item contains #Measurements.
324  }
325  if(!ok || nRxItems != 7) //The number of Rx params is incorrect or read error.
326  {
327  error("Malformed packet. Try it again!","MSOxxxx::getJitter");
328  }
329  else //At this point everything is ok. Let's return a Python list with all the statistics.
330  {
331  PyList_Append(statistics, PyFloat_FromDouble(atof(rxItems[2].c_str()))); //Min
332  PyList_Append(statistics, PyFloat_FromDouble(atof(rxItems[3].c_str()))); //Max
333  PyList_Append(statistics, PyFloat_FromDouble(atof(rxItems[4].c_str()))); //Mean
334  PyList_Append(statistics, PyFloat_FromDouble(atof(rxItems[5].c_str()))); //Stdev
335  }
336  return statistics;
337 }
338 
339 
340 
341 
342 
343 
344 
345 
346 
347 
348 
349 
350 
354 
356 {
357  bool ok;
358  if(display)
359  ok = send(":DISPLAY:LABEL ON \n");
360  else
361  ok = send(":DISPLAY:LABEL OFF \n");
362  if(ok) return StatusCode::SUCCESS;
363  else return StatusCode::FAILURE;
364 }
365 
369 
370 PyObject* MSOxxxx::id()
371 {
372  bool ok;
373  int nRxItems;
374  PyObject* idList = PyList_New(0);
375 
376  ok = send("*IDN? \n");
377  if(ok) nRxItems = recv(rxItems);
378  if(ok && nRxItems == 4)
379  {
380  info("Oscilloscope : " + rxItems[0],"MSOxxxx::id");
381  info("Model : " + rxItems[1],"MSOxxxx::id");
382  info("Serial Number: " + rxItems[2],"MSOxxxx::id");
383  info("SW Version : " + rxItems[3],"MSOxxxx::id");
384  for(int i=0; i<4; i++)
385  PyList_Append(idList, PyString_FromString(rxItems[i].c_str()));
386  }
387  return idList;
388 }
389 
391 {
392  bool ok = send(":RUN \n");
393  if(ok) return StatusCode::SUCCESS;
394  else return StatusCode::FAILURE;
395 }
396 
398 {
399  bool ok = send(":STOP \n");
400  if(ok) return StatusCode::SUCCESS;
401  else return StatusCode::FAILURE;
402 }
403 
404 //Splits a string into small strings accorgint to 'delimiter'
405 int MSOxxxx::split(string str, string *splitStr, string delimiter)
406 {
407  unsigned int delimPos = str.find(delimiter);
408  int nStrings = 0;
409 
410  while(delimPos != string::npos) //While there is a "," , "." , " " or whatever...
411  {
412  splitStr[nStrings++] = str.substr(0,delimPos); //We put the previous characters to the delimiter to a string array.
413  str = str.substr(delimPos+1,string::npos); //We remove that characters and the delimiter.
414  delimPos = str.find(delimiter); //The new position of the delimiter in the string.
415  }
416  splitStr[nStrings++] = str; //The last string (with no more delimitters) are put to the last string array.
417  return nStrings;
418 }
419 
420 string MSOxxxx::ftos(double f)
421 {
422  std::ostringstream buffer;
423  buffer << std::setprecision(7) << std::scientific << f;
424  return buffer.str();
425 }
426 
428 {
429 
430 }
431 
void info(std::string mymsg)
Definition: Object.h:38
std::string itos(int)
Definition: Tools.cpp:46
PyObject * getStatistics(int nMinMeas)
Definition: MSOxxxx.cpp:311
#define DEFAULT_PORT
Definition: MSOxxxx.h:34
f
Definition: cat.py:54
StatusCode triggerConfig(bool slope, int ch, double level)
Definition: MSOxxxx.cpp:221
int split(string str, string *splitStr, string delimiter)
Definition: MSOxxxx.cpp:405
int portNumber
Definition: MSOxxxx.h:120
StatusCode open()
Definition: MSOxxxx.cpp:42
void add(int attribut)
Definition: Attrib.h:67
StatusCode channelDisplay(int ch, bool display)
Definition: MSOxxxx.cpp:151
string ipAddress
Definition: MSOxxxx.h:115
MSOxxxx()
Definition: MSOxxxx.cpp:16
bool debugMode
Definition: MSOxxxx.h:126
StatusCode channelScale(int ch, double value)
Definition: MSOxxxx.cpp:137
void setType(std::string type)
Definition: Object.h:52
void error(std::string mymsg)
Definition: Object.h:40
void setId(unsigned char id)
Definition: Object.h:53
void debug(std::string mymsg)
Definition: Object.h:37
StatusCode labelDisplay(bool display)
Definition: MSOxxxx.cpp:355
StatusCode setupAvgVoltage(int ch)
Definition: MSOxxxx.cpp:265
void configTCPIP(string ip, int port)
Definition: MSOxxxx.cpp:34
StatusCode stop()
Definition: MSOxxxx.cpp:397
void msg(std::string mymsg)
Definition: Object.h:35
#define MAX_LEN
Definition: MSOxxxx.h:37
StatusCode setupJitter(int ch)
Definition: MSOxxxx.cpp:238
string rxItems[65536]
Definition: MSOxxxx.h:124
StatusCode channelOffset(int ch, double value)
Definition: MSOxxxx.cpp:144
StatusCode run()
Definition: MSOxxxx.cpp:390
std::string name() const
Definition: Object.h:28
PyObject * waveformCapture(int ch)
Definition: MSOxxxx.cpp:277
bool getTimeBase(double *xInc, double *xOrg)
Definition: MSOxxxx.cpp:187
bool send(string msg)
Definition: MSOxxxx.cpp:83
#define DEBUG_MODE
Definition: MSOxxxx.h:35
void reset()
Definition: MSOxxxx.cpp:427
string ftos(double)
Definition: MSOxxxx.cpp:420
int recv(string *rxItems, string spacer)
Definition: MSOxxxx.cpp:97
#define DEFAULT_IP_ADDRESS
Definition: MSOxxxx.h:33
StatusCode setupDeltaTime(int chA, int chB, int edge)
Definition: MSOxxxx.cpp:252
StatusCode timeBaseOffset(double seconds)
Definition: MSOxxxx.cpp:180
StatusCode timeBaseScale(double secsPerDiv)
Definition: MSOxxxx.cpp:173
int sockfd
Definition: MSOxxxx.h:121
char rxBuffer[10485760]
Definition: MSOxxxx.h:123
PyObject * id()
Definition: MSOxxxx.cpp:370
StatusCode channelDisplayName(int ch, string name)
Definition: MSOxxxx.cpp:162
StatusCode triggerAuto()
Definition: MSOxxxx.cpp:214