Line data Source code
1 :
2 :
3 : #ifndef siglentSDG_hpp
4 : #define siglentSDG_hpp
5 :
6 :
7 : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
8 : #include "../../magaox_git_version.h"
9 :
10 : #include "siglentSDG_parsers.hpp"
11 :
12 : namespace MagAOX
13 : {
14 : namespace app
15 : {
16 :
17 : /** MagAO-X application to control a Siglent SDG series function generator
18 : *
19 : * \todo need to recognize signals in tty polls and not return errors, etc.
20 : * \todo need to implement an onDisconnect() to update values to unknown indicators.
21 : * \todo need a frequency-dependent max amp facility.
22 : * \todo convert to ioDevice
23 : * \todo need telnet device, with optional username/password.
24 : *
25 : */
26 : class siglentSDG : public MagAOXApp<>, public dev::telemeter<siglentSDG>
27 : {
28 :
29 : friend class siglentSDG_test;
30 :
31 : friend class dev::telemeter<siglentSDG>;
32 :
33 : //constexpr static double cs_MaxAmp = 0.87;//2.1;//0.87;
34 : constexpr static double cs_MaxOfst = 10.0;
35 : constexpr static double cs_MaxVolts = 10.0;
36 : //constexpr static double cs_MaxFreq = 3622.0;//101;//3622.0;
37 :
38 : private:
39 : std::vector<double> m_ampMax = {1.2801, 1.2801, 1.0201};//0.71, 0.83, 0.88, 1.05, 1.15, 3.45}; //1.5, 1.2, 1.1 };
40 : std::vector<double> m_maxFreq = {0.0, 2000, 3000};//100.0, 150, 200, 250, 300, 1000}; //2999.99, 3499.99, 3500.01};
41 : //todo: do we need to add max and min pulse variables?
42 : protected:
43 :
44 : /** \name Configurable Parameters
45 : * @{
46 : */
47 :
48 : std::string m_deviceAddr; ///< The device address
49 : std::string m_devicePort; ///< The device port
50 :
51 : double m_bootDelay {10}; ///< Time in seconds it takes the device to boot.
52 :
53 : int m_writeTimeOut {10000}; ///< The timeout for writing to the device [msec].
54 : int m_readTimeOut {10000}; ///< The timeout for reading from the device [msec].
55 :
56 : double m_C1setVoltage {5.0}; ///< the set position voltage of Ch. 1.
57 : double m_C2setVoltage {5.0}; ///< the set position voltage of Ch. 2.
58 :
59 : bool m_C1outpOn {false}; /**< Flag controlling if C1 output is on after normalization. */
60 : bool m_C2outpOn {false}; /**< Flag controlling if C2 output is on after normalization.
61 : This will only have an effect if m_C1wvtp is "pulse" */
62 :
63 : ///@}
64 :
65 : tty::telnetConn m_telnetConn; ///< The telnet connection manager
66 :
67 : std::string m_waveform; ///< The chosen funciton to generate
68 : /// std::string m_clock; ///<INTernal or EXTernal
69 :
70 : uint8_t m_C1outp {0}; ///< The output status channel 1
71 : double m_C1frequency {0}; ///< The output frequency of channel 1
72 : double m_C1vpp {0}; ///< The peak-2-peak voltage of channel 1
73 : double m_C1vppDefault {0}; ///< default value for vpp of channel 1
74 : double m_C1ofst {0}; ///< The offset voltage of channel 1
75 : double m_C1phse {0}; ///< The phase of channel 1 (SINE only)
76 : double m_C1wdth {0}; ///< The width of channel 1 (PULSE only)
77 : std::string m_C1wvtp; ///< The wave type of channel 1
78 : double m_C1ampMax {10.0}; ///< The maximum voltage output for channel 1
79 :
80 : uint8_t m_C2outp {0}; ///< The output status channel 2
81 : double m_C2frequency {0}; ///< The output frequency of channel 2
82 : double m_C2vpp {0}; ///< The peak-2-peak voltage of channel 2
83 : double m_C2vppDefault {0}; ///< default value for vpp of channel 2
84 : double m_C2ofst {0}; ///< The offset voltage of channel 2
85 : double m_C2phse {0}; ///< The phase of channel 2 (SINE only)
86 : double m_C2wdth {0}; ///< The width of channel 2 (PULSE only)
87 : std::string m_C2wvtp; ///< The wave type of channel 2
88 : double m_C2ampMax {10.0}; ///< The maximum voltage output for channel 2
89 :
90 : double m_C1frequency_tgt {-1};
91 : double m_C1vpp_tgt {-1};
92 :
93 : double m_C2frequency_tgt {-1};
94 : double m_C2vpp_tgt {-1};
95 :
96 : bool m_C1sync {false};
97 : bool m_C2sync {false};
98 :
99 : private:
100 :
101 : bool m_poweredOn {false};
102 :
103 : double m_powerOnCounter {0}; ///< Counts the number of loops since power-on, used to control logging of connect failures.
104 :
105 : public:
106 :
107 : /// Default c'tor.
108 : siglentSDG();
109 :
110 : /// D'tor, declared and defined for noexcept.
111 48 : ~siglentSDG() noexcept
112 48 : {}
113 :
114 : /// Setup the configuration system (called by MagAOXApp::setup())
115 : virtual void setupConfig();
116 :
117 : /// load the configuration system results (called by MagAOXApp::setup())
118 : virtual void loadConfig();
119 :
120 : /// Startup functions
121 : /** Setsup the INDI vars.
122 : *
123 : */
124 : virtual int appStartup();
125 :
126 : /// Implementation of the FSM for the Siglent SDG
127 : virtual int appLogic();
128 :
129 : /// Implementation of the on-power-off FSM logic
130 : virtual int onPowerOff();
131 :
132 : /// Implementation of the while-powered-off FSM
133 : virtual int whilePowerOff();
134 :
135 : /// Do any needed shutdown tasks. Currently nothing in this app.
136 : virtual int appShutdown();
137 :
138 : /// Write a command to the device and get the response. Not mutex-ed.
139 : /** We assume this is called after the m_indiMutex is locked.
140 : *
141 : * \returns 0 on success
142 : * \returns -1 on an error. May set DISCONNECTED.
143 : */
144 : int writeRead( std::string & strRead, ///< [out] The string responseread in
145 : const std::string & command ///< [in] The command to send.
146 : );
147 :
148 : /// Write a command to the device.
149 : /**
150 : * \returns 0 on success
151 : * \returns -1 on error
152 : */
153 : int writeCommand( const std::string & commmand /**< [in] the complete command string to send to the device */);
154 :
155 : /// Send the MDWV? query and get the response state.
156 : /** This does not update internal state.
157 : *
158 : * \returns 0 on success
159 : * \returns -1 on an error.
160 : */
161 : int queryMDWV( std::string & state, ///< [out] the MDWV state, ON or OFF
162 : int channel ///< [in] the channel to query
163 : );
164 :
165 : /// Send the SWWV? query and get the response state.
166 : /** This does not update internal state.
167 : *
168 : * \returns 0 on success
169 : * \returns -1 on an error.
170 : */
171 : int querySWWV( std::string & state, ///< [out] the SWWV state, ON or OFF
172 : int channel ///< [in] the channel to query
173 : );
174 :
175 : /// Send the BTWV? query and get the response state.
176 : /** This does not update internal state.
177 : *
178 : * \returns 0 on success
179 : * \returns -1 on an error.
180 : */
181 : int queryBTWV( std::string & state, ///< [out] the BTWV state, ON or OFF
182 : int channel ///< [in] the channel to query
183 : );
184 :
185 : /// Send the ARWV? query and get the response index.
186 : /** This does not update internal state.
187 : *
188 : * \returns 0 on success
189 : * \returns -1 on an error.
190 : */
191 : int queryARWV( int & index, ///< [out] the ARWV index
192 : int channel ///< [in] the channel to query
193 : );
194 :
195 : /// Send the BSWV? query for a channel.
196 : /** This updates member variables and INDI.
197 : *
198 : * \returns 0 on success
199 : * \returns -1 on an error.
200 : */
201 : int queryBSWV( int channel /** < [in] the channel to query */ );
202 :
203 : /// Send the SYNC? query for a channel.
204 : /** This updates member variables and INDI.
205 : *
206 : * \returns 0 on success
207 : * \returns -1 on an error.
208 : */
209 : int querySYNC( bool & sync, /// < [in] the sync state for this channel
210 : int channel /// < [in] the channel to query
211 : );
212 :
213 : /// Check the setup is correct and safe for PI TTM control.
214 : /**
215 : * \returns 0 if the fxn gen is setup for safe operation
216 : * \returns 1 if a non-normal setup is detected.
217 : * \returns -1 on an error, e.g. comms or parsing.
218 : */
219 : int checkSetup();
220 :
221 : /// Normalize the setup, called during connection if checkSetup shows a problem, or on power-up.
222 : int normalizeSetup();
223 :
224 : /// Send the OUTP? query for a channel.
225 : /**
226 : * \returns 0 on success
227 : * \returns -1 on an error.
228 : */
229 : int queryOUTP( int channel /**< [in] the channel to query */);
230 :
231 : /// Change the output status (on/off) of one channel.
232 : /**
233 : * \returns 0 on success
234 : * \returns -1 on error.
235 : */
236 : int changeOutp( int channel, ///< [in] the channel to send the command to.
237 : const std::string & newOutp ///< [in] The requested output state [On/Off]
238 : );
239 :
240 : /// Change the output status (on/off) of one channel in response to an INDI property. This locks the mutex.
241 : /**
242 : * \returns 0 on success
243 : * \returns -1 on error.
244 : */
245 : int changeOutp( int channel, ///< [in] the channel to send the command to.
246 : const pcf::IndiProperty &ipRecv ///< [in] INDI property containing the requested output state [On/Off]
247 : );
248 :
249 : /// Send a change frequency command to the device.
250 : /**
251 : * \returns 0 on success
252 : * \returns -1 on error
253 : */
254 : int changeFreq( int channel, ///< [in] the channel to send the command to.
255 : double newFreq ///< [in] The requested new frequency [Hz]
256 : );
257 :
258 : /// Send a change frequency command to the device in response to an INDI property. This locks the mutex.
259 : /**
260 : * \returns 0 on success
261 : * \returns -1 on error
262 : */
263 : int changeFreq( int channel, ///< [in] the channel to send the command to.
264 : const pcf::IndiProperty &ipRecv ///< [in] INDI property containing the requested new frequency [Hz]
265 : );
266 :
267 : /// Send a change amplitude command to the device.
268 : /**
269 : * \returns 0 on success
270 : * \returns -1 on error
271 : */
272 : int changeAmp( int channel, ///< [in] the channel to send the command to.
273 : double newAmp ///< [in] The requested new amplitude [V p2p]
274 : );
275 :
276 : /// Send a change amplitude command to the device in response to an INDI property.
277 : /**
278 : * \returns 0 on success
279 : * \returns -1 on error
280 : */
281 : int changeAmp( int channel, ///< [in] the channel to send the command to.
282 : const pcf::IndiProperty &ipRecv ///< [in] INDI property containing the requested new amplitude [V p2p]
283 : );
284 :
285 : /// Send a change offset command to the device.
286 : /**
287 : * \returns 0 on success
288 : * \returns -1 on error
289 : */
290 : int changeOfst( int channel, ///< [in] the channel to send the command to.
291 : double newOfst ///< [in] The requested new offset [V p2p]
292 : );
293 :
294 : /// Send a change offset command to the device in response to an INDI property.
295 : /**
296 : * \returns 0 on success
297 : * \returns -1 on error
298 : */
299 : int changeOfst( int channel, ///< [in] the channel to send the command to.
300 : const pcf::IndiProperty &ipRecv ///< [in] INDI property containing the requested new offset [V p2p]
301 : );
302 :
303 : /// Send a change phase command to the device.
304 : /**
305 : * \returns 0 on success
306 : * \returns -1 on error
307 : */
308 : int changePhse( int channel, ///< [in] the channel to send the command to.
309 : double newPhse ///< [in] The requested new phase [deg]
310 : );
311 :
312 : /// Send a change phase command to the device in response to an INDI property.
313 : /**
314 : * \returns 0 on success
315 : * \returns -1 on error
316 : */
317 : int changePhse( int channel, ///< [in] the channel to send the command to.
318 : const pcf::IndiProperty &ipRecv ///< [in] INDI property containing the requested new phase [deg]
319 : );
320 :
321 : /// Send a width command to the device.
322 : /**
323 : * \returns 0 on success
324 : * \returns -1 on error
325 : */
326 : int changeWdth( int channel, ///< [in] the channel to send the command to.
327 : double newWdth ///< [in] The requested new width [s]
328 : );
329 :
330 : /// Send a change phase command to the device in response to an INDI property.
331 : /**
332 : * \returns 0 on success
333 : * \returns -1 on error
334 : */
335 : int changeWdth( int channel, ///< [in] the channel to send the command to.
336 : const pcf::IndiProperty &ipRecv ///< [in] INDI property containing the requested new width [s]
337 : );
338 :
339 :
340 : /// Send a change wavetype command to the device.
341 : /**
342 : * \returns 0 on success
343 : * \returns -1 on error
344 : */
345 : int changeWvtp( int channel, ///< [in] the channel to send the command to.
346 : const std::string & newWvtp ///< [in] The requested new wavetype
347 : );
348 :
349 : /// Send a change wavetype command to the device in response to an INDI property.
350 : /**
351 : * \returns 0 on success
352 : * \returns -1 on error
353 : */
354 : int changeWvtp( int channel, ///< [in] the channel to send the command to.
355 : const pcf::IndiProperty &ipRecv ///< [in] INDI property containing the requested new wavetype
356 : );
357 :
358 : /// Send a change sync command to the device.
359 : /**
360 : * \returns 0 on success
361 : * \returns -1 on error
362 : */
363 : int changeSync( int channel, ///< [in] the channel to send the command to.
364 : bool newSync ///< [in] The requested new sync state
365 : );
366 :
367 : /// Send a change sync command to the device in response to an INDI property.
368 : /**
369 : * \returns 0 on success
370 : * \returns -1 on error
371 : */
372 : int changeSync( int channel, ///< [in] the channel to send the command to.
373 : const pcf::IndiProperty &ipRecv ///< [in] INDI property containing the requested new sync state
374 : );
375 :
376 : /** \name INDI
377 : * @{
378 : */
379 : protected:
380 :
381 : //declare our properties
382 : pcf::IndiProperty m_indiP_status;
383 :
384 : pcf::IndiProperty m_indiP_C1outp;
385 : pcf::IndiProperty m_indiP_C1wvtp;
386 : pcf::IndiProperty m_indiP_C1freq;
387 : pcf::IndiProperty m_indiP_C1peri;
388 : pcf::IndiProperty m_indiP_C1amp;
389 : pcf::IndiProperty m_indiP_C1ampvrms;
390 : pcf::IndiProperty m_indiP_C1ofst;
391 : pcf::IndiProperty m_indiP_C1hlev;
392 : pcf::IndiProperty m_indiP_C1llev;
393 : pcf::IndiProperty m_indiP_C1phse;
394 : pcf::IndiProperty m_indiP_C1wdth;
395 : pcf::IndiProperty m_indiP_C1sync;
396 :
397 : pcf::IndiProperty m_indiP_C2outp;
398 : pcf::IndiProperty m_indiP_C2wvtp;
399 : pcf::IndiProperty m_indiP_C2freq;
400 : pcf::IndiProperty m_indiP_C2peri;
401 : pcf::IndiProperty m_indiP_C2amp;
402 : pcf::IndiProperty m_indiP_C2ampvrms;
403 : pcf::IndiProperty m_indiP_C2ofst;
404 : pcf::IndiProperty m_indiP_C2hlev;
405 : pcf::IndiProperty m_indiP_C2llev;
406 : pcf::IndiProperty m_indiP_C2phse;
407 : pcf::IndiProperty m_indiP_C2wdth;
408 : pcf::IndiProperty m_indiP_C2sync;
409 :
410 : public:
411 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C1outp);
412 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C1freq);
413 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C1amp);
414 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C1ofst);
415 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C1phse);
416 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C1wdth);
417 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C1wvtp);
418 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C1sync);
419 :
420 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C2outp);
421 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C2freq);
422 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C2amp);
423 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C2ofst);
424 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C2phse);
425 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C2wdth);
426 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C2wvtp);
427 0 : INDI_NEWCALLBACK_DECL(siglentSDG, m_indiP_C2sync);
428 : ///@}
429 :
430 :
431 : /** \name Telemeter Interface
432 : *
433 : * @{
434 : */
435 :
436 : int checkRecordTimes();
437 :
438 : int recordTelem( const telem_fxngen * );
439 :
440 : int recordParams(bool force = false);
441 :
442 : /// @}
443 :
444 : };
445 :
446 : inline
447 336 : siglentSDG::siglentSDG() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
448 : {
449 48 : m_powerMgtEnabled = true;
450 48 : m_telnetConn.m_prompt = "\n";
451 48 : return;
452 0 : }
453 :
454 : inline
455 0 : void siglentSDG::setupConfig()
456 : {
457 0 : config.add("device.address", "a", "device.address", argType::Required, "device", "address", false, "string", "The device address.");
458 0 : config.add("device.port", "p", "device.port", argType::Required, "device", "port", false, "string", "The device port.");
459 :
460 0 : config.add("timeouts.write", "", "timeouts.write", argType::Required, "timeouts", "write", false, "int", "The timeout for writing to the device [msec]. Default = 1000");
461 0 : config.add("timeouts.read", "", "timeouts.read", argType::Required, "timeouts", "read", false, "int", "The timeout for reading the device [msec]. Default = 2000");
462 :
463 0 : config.add("fxngen.waveform", "w", "fxngen.waveform", argType::Required, "fxngen", "waveform", false, "string", "The waveform to populate function.");
464 :
465 0 : config.add("fxngen.C1outpOn", "", "fxngen.C1outpOn", argType::Required, "fxngen", "C1outpOn", false, "bool", "Whether (true) or not (false) C1 output is enabled at startup. Only effective wavefrom is pulse. Default is false.");
466 0 : config.add("fxngen.C2outpOn", "", "fxngen.C2outpOn", argType::Required, "fxngen", "C2outpOn", false, "bool", "Whether (true) or not (false) C2 output is enabled at startup. Only effective wavefrom is pulse. Default is false.");
467 :
468 0 : config.add("fxngen.C1ampDefault", "", "fxngen.C1ampDefault", argType::Required, "fxngen", "C1ampDefault", false, "float", "C1 Default P2V Amplitude of waveform. Default = 0.0");
469 0 : config.add("fxngen.C2ampDefault", "", "fxngen.C2ampDefault", argType::Required, "fxngen", "C2ampDefault", false, "float", "C2 Default P2V Amplitude of waveform. Default = 0.0");
470 :
471 0 : config.add("fxngen.C1ofstDefault", "", "fxngen.C1ofstDefault", argType::Required, "fxngen", "C1ofstDefault", false, "float", "C1 Default Offset Amplitude of waveform. Default = 0.0");
472 0 : config.add("fxngen.C2ofstDefault", "", "fxngen.C2ofstDefault", argType::Required, "fxngen", "C2ofstDefault", false, "float", "C2 Default Offset Amplitude of waveform. Default = 0.0");
473 :
474 0 : config.add("fxngen.C1ampMax", "", "fxngen.C1ampMax", argType::Required, "fxngen", "C1ampMax", false, "float", "C1 Maximum amplitude");
475 0 : config.add("fxngen.C2ampMax", "", "fxngen.C2ampMax", argType::Required, "fxngen", "C2ampMax", false, "float", "C2 Maximum amplitude");
476 :
477 0 : dev::telemeter<siglentSDG>::setupConfig(config);
478 0 : }
479 :
480 : inline
481 0 : void siglentSDG::loadConfig()
482 : {
483 0 : config(m_deviceAddr, "device.address");
484 0 : config(m_devicePort, "device.port");
485 :
486 0 : config(m_writeTimeOut, "timeouts.write");
487 0 : config(m_readTimeOut, "timeouts.read");
488 :
489 0 : config(m_waveform, "fxngen.waveform"); // todo: check if this is a valid waveform?
490 0 : config(m_C1outpOn, "fxngen.C1outpOn");
491 0 : config(m_C2outpOn, "fxngen.C2outpOn");
492 :
493 0 : config(m_C1vppDefault, "fxngen.C1ampDefault");
494 0 : config(m_C2vppDefault, "fxngen.C2ampDefault");
495 :
496 0 : config(m_C1ofst, "fxngen.C1ofstDefault");
497 0 : config(m_C2ofst, "fxngen.C2ofstDefault");
498 :
499 0 : config(m_C1ampMax, "fxngen.C1ampMax");
500 0 : config(m_C2ampMax, "fxngen.C2ampMax");
501 : /// config(m_clock, "fxngen.clock");
502 :
503 0 : dev::telemeter<siglentSDG>::loadConfig(config);
504 0 : }
505 :
506 : inline
507 0 : int siglentSDG::appStartup()
508 : {
509 : // set up the INDI properties
510 0 : REG_INDI_NEWPROP_NOCB(m_indiP_status, "status", pcf::IndiProperty::Text);
511 0 : m_indiP_status.add (pcf::IndiElement("value"));
512 0 : m_indiP_status["value"].set(0);
513 :
514 0 : REG_INDI_NEWPROP(m_indiP_C1outp, "C1outp", pcf::IndiProperty::Text);
515 0 : m_indiP_C1outp.add (pcf::IndiElement("value"));
516 0 : m_indiP_C1outp["value"].set("");
517 :
518 : //REG_INDI_NEWPROP(m_indiP_C1freq, "C1freq", pcf::IndiProperty::Number);
519 0 : CREATE_REG_INDI_NEW_NUMBERF( m_indiP_C1freq, "C1freq", -1e15, 1e15, 1, "%g", "C1freq", "C1freq");
520 : //m_indiP_C1freq.add (pcf::IndiElement("value"));
521 0 : m_indiP_C1freq["current"].set(0);
522 0 : m_indiP_C1freq["target"].set(0);
523 :
524 : //REG_INDI_NEWPROP(m_indiP_C1amp, "C1amp", pcf::IndiProperty::Number);
525 0 : CREATE_REG_INDI_NEW_NUMBERF( m_indiP_C1amp, "C1amp", -1e15, 1e15, 1, "%g", "C1amp", "C1amp");
526 : //m_indiP_C1amp.add (pcf::IndiElement("value"));
527 0 : m_indiP_C1amp["current"].set(0);
528 0 : m_indiP_C1amp["target"].set(0);
529 :
530 0 : REG_INDI_NEWPROP(m_indiP_C1ofst, "C1ofst", pcf::IndiProperty::Number);
531 0 : m_indiP_C1ofst.add (pcf::IndiElement("value"));
532 0 : m_indiP_C1ofst["value"].set(0);
533 :
534 0 : if(m_waveform == "SINE"){
535 0 : REG_INDI_NEWPROP(m_indiP_C1phse, "C1phse", pcf::IndiProperty::Number);
536 0 : m_indiP_C1phse.add (pcf::IndiElement("value"));
537 0 : m_indiP_C1phse["value"].set(0);
538 : }
539 :
540 0 : if(m_waveform == "PULSE"){
541 0 : REG_INDI_NEWPROP(m_indiP_C1wdth, "C1wdth", pcf::IndiProperty::Number);
542 0 : m_indiP_C1wdth.add (pcf::IndiElement("value"));
543 0 : m_indiP_C1wdth["value"].set(0);
544 : }
545 :
546 0 : REG_INDI_NEWPROP(m_indiP_C1wvtp, "C1wvtp", pcf::IndiProperty::Text);
547 0 : m_indiP_C1wvtp.add (pcf::IndiElement("value"));
548 0 : m_indiP_C1wvtp["value"].set("");
549 :
550 0 : REG_INDI_NEWPROP_NOCB(m_indiP_C1peri, "C1peri", pcf::IndiProperty::Number);
551 0 : m_indiP_C1peri.add (pcf::IndiElement("value"));
552 0 : m_indiP_C1peri["value"].set(0);
553 :
554 0 : REG_INDI_NEWPROP_NOCB(m_indiP_C1ampvrms, "C1ampvrms", pcf::IndiProperty::Number);
555 0 : m_indiP_C1ampvrms.add (pcf::IndiElement("value"));
556 0 : m_indiP_C1ampvrms["value"].set(0);
557 :
558 0 : REG_INDI_NEWPROP_NOCB(m_indiP_C1hlev, "C1hlev", pcf::IndiProperty::Number);
559 0 : m_indiP_C1hlev.add (pcf::IndiElement("value"));
560 0 : m_indiP_C1hlev["value"].set(0);
561 :
562 0 : REG_INDI_NEWPROP_NOCB(m_indiP_C1llev, "C1llev", pcf::IndiProperty::Number);
563 0 : m_indiP_C1llev.add (pcf::IndiElement("value"));
564 0 : m_indiP_C1llev["value"].set(0);
565 :
566 0 : createStandardIndiToggleSw( m_indiP_C1sync, "C1synchro", "C1 Sync Output", "C1 Sync Output");
567 0 : if(registerIndiPropertyNew( m_indiP_C1sync, st_newCallBack_m_indiP_C1sync) < 0)
568 : {
569 0 : log<software_error>({__FILE__,__LINE__});
570 0 : return -1;
571 : }
572 :
573 0 : REG_INDI_NEWPROP(m_indiP_C2outp, "C2outp", pcf::IndiProperty::Text);
574 0 : m_indiP_C2outp.add (pcf::IndiElement("value"));
575 0 : m_indiP_C2outp["value"].set("");
576 :
577 0 : CREATE_REG_INDI_NEW_NUMBERF( m_indiP_C2freq, "C2freq", -1e15, 1e15, 1, "%g", "C2freq", "C2freq");
578 0 : m_indiP_C2freq["current"].set(0);
579 0 : m_indiP_C2freq["target"].set(0);
580 :
581 0 : CREATE_REG_INDI_NEW_NUMBERF( m_indiP_C2amp, "C2amp", -1e15, 1e15, 1, "%g", "C2amp", "C2amp");
582 0 : m_indiP_C2amp["current"].set(0);
583 0 : m_indiP_C2amp["target"].set(0);
584 :
585 0 : REG_INDI_NEWPROP(m_indiP_C2ofst, "C2ofst", pcf::IndiProperty::Number);
586 0 : m_indiP_C2ofst.add (pcf::IndiElement("value"));
587 0 : m_indiP_C2ofst["value"].set(0);
588 :
589 0 : if(m_waveform == "SINE")
590 : {
591 0 : REG_INDI_NEWPROP(m_indiP_C2phse, "C2phse", pcf::IndiProperty::Number);
592 0 : m_indiP_C2phse.add (pcf::IndiElement("value"));
593 0 : m_indiP_C2phse["value"].set(0);
594 : }
595 :
596 0 : if(m_waveform == "PULSE")
597 : {
598 0 : REG_INDI_NEWPROP(m_indiP_C2wdth, "C2wdth", pcf::IndiProperty::Number);
599 0 : m_indiP_C2wdth.add (pcf::IndiElement("value"));
600 0 : m_indiP_C2wdth["value"].set(0);
601 : }
602 :
603 0 : REG_INDI_NEWPROP(m_indiP_C2wvtp, "C2wvtp", pcf::IndiProperty::Text);
604 0 : m_indiP_C2wvtp.add (pcf::IndiElement("value"));
605 0 : m_indiP_C2wvtp["value"].set("");
606 :
607 0 : REG_INDI_NEWPROP_NOCB(m_indiP_C2peri, "C2peri", pcf::IndiProperty::Number);
608 0 : m_indiP_C2peri.add (pcf::IndiElement("value"));
609 0 : m_indiP_C2peri["value"].set(0);
610 :
611 0 : REG_INDI_NEWPROP_NOCB(m_indiP_C2ampvrms, "C2ampvrms", pcf::IndiProperty::Number);
612 0 : m_indiP_C2ampvrms.add (pcf::IndiElement("value"));
613 0 : m_indiP_C2ampvrms["value"].set(0);
614 :
615 0 : REG_INDI_NEWPROP_NOCB(m_indiP_C2hlev, "C2hlev", pcf::IndiProperty::Number);
616 0 : m_indiP_C2hlev.add (pcf::IndiElement("value"));
617 0 : m_indiP_C2hlev["value"].set(0);
618 :
619 0 : REG_INDI_NEWPROP_NOCB(m_indiP_C2llev, "C2llev", pcf::IndiProperty::Number);
620 0 : m_indiP_C2llev.add (pcf::IndiElement("value"));
621 0 : m_indiP_C2llev["value"].set(0);
622 :
623 0 : createStandardIndiToggleSw( m_indiP_C2sync, "C2synchro", "C2 Sync Output", "C2 Sync Output");
624 0 : if(registerIndiPropertyNew( m_indiP_C2sync, st_newCallBack_m_indiP_C2sync) < 0)
625 : {
626 0 : log<software_error>({__FILE__,__LINE__});
627 0 : return -1;
628 : }
629 :
630 0 : if(dev::telemeter<siglentSDG>::appStartup() < 0)
631 : {
632 0 : return log<software_error,-1>({__FILE__,__LINE__});
633 : }
634 :
635 0 : return 0;
636 : }
637 :
638 : inline
639 0 : int siglentSDG::appLogic()
640 : {
641 :
642 0 : if( state() == stateCodes::POWERON )
643 : {
644 0 : m_poweredOn = true; //So we reset the device.
645 :
646 0 : state(stateCodes::NOTCONNECTED);
647 0 : m_powerOnCounter = 0;
648 : }
649 :
650 : //If we enter this loop in state ERROR, we wait 1 sec and then check power state.
651 0 : if( state() == stateCodes::ERROR )
652 : {
653 0 : sleep(1);
654 :
655 : //This allows for the case where the device powers off causing a comm error
656 : //But we haven't gotten the update from the power controller before going through
657 : //the main loop after the error.
658 0 : if( (m_powerState != 1 || m_powerTargetState != 1) == true)
659 : {
660 0 : return 0;
661 : }
662 : }
663 :
664 0 : if( state() == stateCodes::NOTCONNECTED || state() == stateCodes::ERROR )
665 : {
666 0 : int rv = m_telnetConn.connect(m_deviceAddr, m_devicePort);
667 :
668 0 : if(rv == 0)
669 : {
670 : ///\todo the connection process in siglentSDG is a total hack. Figure out why this is needed to clear the channel, especially on a post-poweroff/on reconnect.
671 :
672 : //The sleeps here seem to be necessary to make sure there is a good
673 : //comm with device. Probably a more graceful way.
674 0 : state(stateCodes::CONNECTED);
675 0 : m_telnetConn.noLogin();
676 : //sleep(1);//Wait for the connection to take.
677 :
678 0 : m_telnetConn.read(">>", m_readTimeOut);
679 :
680 0 : m_telnetConn.m_strRead.clear();
681 0 : m_telnetConn.write("\n", m_writeTimeOut);
682 :
683 0 : m_telnetConn.read(">>", m_readTimeOut);
684 :
685 0 : int n = 0;
686 0 : while( m_telnetConn.m_strRead != ">>")
687 : {
688 0 : if(n>9)
689 : {
690 0 : log<software_critical>({__FILE__, __LINE__, "No response from device. Time to power cycle."});
691 0 : return -1;
692 : }
693 0 : m_telnetConn.write("\n", m_writeTimeOut);
694 0 : sleep(1);
695 0 : m_telnetConn.read(">>", m_readTimeOut);
696 0 : ++n;
697 : }
698 :
699 0 : if(!stateLogged())
700 : {
701 0 : std::stringstream logs;
702 0 : logs << "Connected to " << m_deviceAddr << ":" << m_devicePort;
703 0 : log<text_log>(logs.str());
704 0 : }
705 0 : return 0;//We cycle out to give connection time to settle.
706 : }
707 : else
708 : {
709 :
710 0 : if(m_powerOnCounter > m_bootDelay && !stateLogged())
711 : {
712 0 : std::stringstream logs;
713 0 : logs << "Failed to connect to " << m_deviceAddr << ":" << m_devicePort;
714 0 : log<text_log>(logs.str());
715 0 : }
716 :
717 0 : m_powerOnCounter += 1 + m_loopPause/1e9;
718 :
719 0 : return 0;
720 : }
721 : }
722 :
723 0 : if(state() == stateCodes::CONNECTED )
724 : {
725 : //Do Initial Checks Here.
726 0 : std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
727 0 : if(lock.owns_lock())
728 : {
729 0 : if(m_poweredOn)
730 : {
731 : //This means we need to do the power-on setup.
732 0 : if(normalizeSetup() < 0 )
733 : {
734 0 : log<software_critical>({__FILE__, __LINE__});
735 0 : return -1;
736 : }
737 :
738 0 : m_poweredOn = false;
739 : }
740 :
741 0 : int cs = checkSetup();
742 :
743 0 : if(cs < 0) return 0; //This means we aren't really connected yet.
744 :
745 : int rv;
746 :
747 0 : rv = queryBSWV(1);
748 :
749 0 : if( rv < 0 )
750 : {
751 0 : if(rv != SDG_PARSEERR_WVTP ) return 0; //This means we aren't really connected yet.
752 :
753 0 : cs = 1; //Trigger normalizeSetup
754 : }
755 :
756 0 : rv = queryBSWV(2);
757 :
758 0 : if( rv < 0 )
759 : {
760 0 : if(rv != SDG_PARSEERR_WVTP ) return 0; //This means we aren't really connected yet.
761 :
762 0 : cs = 1; //Trigger normalizeSetup
763 : }
764 :
765 0 : if(cs > 0)
766 : {
767 0 : log<text_log>("Failed setup check, normalizing setup.", logPrio::LOG_NOTICE);
768 0 : if(normalizeSetup() < 0)
769 : {
770 0 : log<software_critical>({__FILE__, __LINE__});
771 0 : return -1;
772 : }
773 :
774 0 : return 0;
775 : }
776 :
777 0 : if( queryOUTP(1) < 0 ) return 0; //This means we aren't really connected yet.
778 0 : if( queryOUTP(2) < 0 ) return 0; //This means we aren't really connected yet.
779 :
780 :
781 :
782 0 : if( m_C1outp == 1 || m_C2outp == 1)
783 : {
784 0 : state(stateCodes::OPERATING);
785 : }
786 : else
787 : {
788 0 : state(stateCodes::READY);
789 : }
790 :
791 0 : recordParams(true);
792 :
793 : }
794 : else
795 : {
796 0 : log<text_log>("Could not get mutex after connecting.", logPrio::LOG_CRITICAL);
797 0 : return -1;
798 : }
799 0 : }
800 :
801 0 : if(state() == stateCodes::READY || state() == stateCodes::OPERATING)
802 : {
803 : // Do this right away to avoid a different thread updating something after we get it.
804 0 : std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
805 0 : if(lock.owns_lock())
806 : {
807 0 : int cs = checkSetup();
808 :
809 0 : if(cs < 0)
810 : {
811 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown)
812 : {
813 0 : log<software_error>({__FILE__, __LINE__});
814 0 : state(stateCodes::ERROR);
815 : }
816 0 : return 0;
817 : }
818 :
819 : int rv;
820 :
821 0 : rv = queryBSWV(1);
822 :
823 0 : if( rv < 0 )
824 : {
825 0 : if(rv != SDG_PARSEERR_WVTP )
826 : {
827 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown)
828 : {
829 0 : log<software_error>({__FILE__, __LINE__});
830 0 : state(stateCodes::ERROR);
831 : }
832 0 : return 0;
833 : }
834 :
835 0 : cs = 1; //Trigger normalizeSetup
836 : }
837 :
838 0 : if(m_C1sync)
839 : {
840 0 : updateSwitchIfChanged(m_indiP_C1sync, "toggle", pcf::IndiElement::On, INDI_OK);
841 : }
842 : else
843 : {
844 0 : updateSwitchIfChanged(m_indiP_C1sync, "toggle", pcf::IndiElement::Off, INDI_IDLE);
845 : }
846 :
847 0 : rv = queryBSWV(2);
848 :
849 0 : if( rv < 0 )
850 : {
851 0 : if(rv != SDG_PARSEERR_WVTP )
852 : {
853 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown)
854 : {
855 0 : log<software_error>({__FILE__, __LINE__});
856 0 : state(stateCodes::ERROR);
857 : }
858 0 : return 0;
859 : }
860 :
861 0 : cs = 1; //Trigger normalizeSetup
862 : }
863 :
864 0 : if(m_C2sync)
865 : {
866 0 : updateSwitchIfChanged(m_indiP_C2sync, "toggle", pcf::IndiElement::On, INDI_OK);
867 : }
868 : else
869 : {
870 0 : updateSwitchIfChanged(m_indiP_C2sync, "toggle", pcf::IndiElement::Off, INDI_IDLE);
871 : }
872 :
873 0 : if(cs > 0)
874 : {
875 0 : log<text_log>("Failed setup check, normalizing setup.", logPrio::LOG_NOTICE);
876 0 : normalizeSetup();
877 :
878 0 : return 0;
879 : }
880 :
881 :
882 0 : if( queryOUTP(1) < 0 )
883 : {
884 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown)
885 : {
886 0 : log<software_error>({__FILE__, __LINE__});
887 0 : state(stateCodes::ERROR);
888 : }
889 0 : return 0;
890 : }
891 :
892 0 : if( queryOUTP(2) < 0 )
893 : {
894 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown)
895 : {
896 0 : log<software_error>({__FILE__, __LINE__});
897 0 : state(stateCodes::ERROR);
898 : }
899 0 : return 0;
900 : }
901 :
902 0 : if( m_C1outp == 1 || m_C2outp == 1)
903 : {
904 0 : state(stateCodes::OPERATING);
905 : }
906 : else
907 : {
908 0 : state(stateCodes::READY);
909 : }
910 :
911 0 : recordParams(); //This will check if anything changed.
912 : }
913 :
914 0 : if(telemeter<siglentSDG>::appLogic() < 0)
915 : {
916 0 : log<software_error>({__FILE__, __LINE__});
917 0 : return 0;
918 : }
919 :
920 0 : return 0;
921 :
922 0 : }
923 :
924 0 : if( state() == stateCodes::CONFIGURING )
925 : {
926 0 : return 0;
927 : }
928 :
929 : //It's possible to get here because other threads are changing states.
930 : //These are the only valid states for this APP at this point. Anything else and we'll log it.
931 0 : if( state() == stateCodes::READY || state() == stateCodes::OPERATING || state() == stateCodes::CONFIGURING )
932 : {
933 0 : return 0;
934 : }
935 :
936 :
937 0 : log<software_error>({__FILE__, __LINE__, "appLogic fell through in state " + stateCodes::codeText(state())});
938 0 : return 0;
939 :
940 : }
941 :
942 : inline
943 0 : int siglentSDG::onPowerOff()
944 : {
945 0 : std::lock_guard<std::mutex> lock(m_indiMutex);
946 :
947 0 : m_C1wvtp = "NONE";
948 0 : m_C1frequency = 0.0;
949 0 : m_C1vpp = 0.0;
950 0 : m_C1ofst = 0.0;
951 0 : m_C1outp = 0;
952 :
953 0 : m_C1frequency_tgt = -1;
954 0 : m_C1vpp_tgt = -1;
955 :
956 0 : updateIfChanged(m_indiP_C1wvtp, "value", m_C1wvtp);
957 :
958 0 : updateIfChanged(m_indiP_C1freq, "current", 0.0);
959 0 : updateIfChanged(m_indiP_C1freq, "target", 0.0);
960 :
961 0 : updateIfChanged(m_indiP_C1peri, "value", 0.0);
962 :
963 0 : updateIfChanged(m_indiP_C1amp, "current", 0.0);
964 0 : updateIfChanged(m_indiP_C1amp, "target", 0.0);
965 :
966 0 : updateIfChanged(m_indiP_C1ampvrms, "value", 0.0);
967 0 : updateIfChanged(m_indiP_C1ofst, "value", 0.0);
968 0 : updateIfChanged(m_indiP_C1hlev, "value", 0.0);
969 0 : updateIfChanged(m_indiP_C1llev, "value", 0.0);
970 0 : if(m_waveform == "SINE"){updateIfChanged(m_indiP_C1phse, "value", 0.0);}
971 0 : if(m_waveform == "PULSE"){updateIfChanged(m_indiP_C1wdth, "value", 0.0);}
972 0 : updateIfChanged(m_indiP_C1outp, "value", std::string("Off"));
973 0 : updateSwitchIfChanged(m_indiP_C1sync, "toggle", pcf::IndiElement::Off, INDI_IDLE);
974 :
975 :
976 0 : m_C2wvtp = "NONE";
977 0 : m_C2frequency = 0.0;
978 0 : m_C2vpp = 0.0;
979 0 : m_C2ofst = 0.0;
980 0 : m_C2outp = 0;
981 :
982 0 : m_C2frequency_tgt = -1;
983 0 : m_C2vpp_tgt = -1;
984 :
985 0 : updateIfChanged(m_indiP_C2wvtp, "value", m_C2wvtp);
986 :
987 0 : updateIfChanged(m_indiP_C2freq, "current", 0.0);
988 0 : updateIfChanged(m_indiP_C2freq, "target", 0.0);
989 :
990 0 : updateIfChanged(m_indiP_C2peri, "value", 0.0);
991 :
992 0 : updateIfChanged(m_indiP_C2amp, "current", 0.0);
993 0 : updateIfChanged(m_indiP_C2amp, "target", 0.0);
994 :
995 0 : updateIfChanged(m_indiP_C2ampvrms, "value", 0.0);
996 0 : updateIfChanged(m_indiP_C2ofst, "value", 0.0);
997 0 : updateIfChanged(m_indiP_C2hlev, "value", 0.0);
998 0 : updateIfChanged(m_indiP_C2llev, "value", 0.0);
999 0 : if(m_waveform == "SINE"){updateIfChanged(m_indiP_C2phse, "value", 0.0);}
1000 0 : if(m_waveform == "PULSE"){updateIfChanged(m_indiP_C2wdth, "value", 0.0);}
1001 0 : updateIfChanged(m_indiP_C1outp, "value", std::string("Off"));
1002 0 : updateSwitchIfChanged(m_indiP_C2sync, "toggle", pcf::IndiElement::Off, INDI_IDLE);
1003 :
1004 0 : return 0;
1005 0 : }
1006 :
1007 : inline
1008 0 : int siglentSDG::whilePowerOff()
1009 : {
1010 0 : return onPowerOff();
1011 : }
1012 :
1013 : inline
1014 0 : int siglentSDG::appShutdown()
1015 : {
1016 0 : dev::telemeter<siglentSDG>::appShutdown();
1017 :
1018 0 : return 0;
1019 : }
1020 :
1021 : inline
1022 0 : int siglentSDG::writeRead( std::string & strRead,
1023 : const std::string & command
1024 : )
1025 : {
1026 : int rv;
1027 0 : rv = m_telnetConn.writeRead(command, false, m_writeTimeOut, m_readTimeOut);
1028 0 : strRead = m_telnetConn.m_strRead;
1029 :
1030 0 : if(rv < 0)
1031 : {
1032 0 : std::cout << command << "\n";
1033 0 : std::cout << "writeRead return val was " << rv << "\n";
1034 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__, __LINE__, 0, rv, tty::ttyErrorString(rv)});
1035 0 : state(stateCodes::NOTCONNECTED);
1036 0 : return -1;
1037 : }
1038 :
1039 : //Clear the newline
1040 0 : rv = m_telnetConn.write("\n", m_writeTimeOut);
1041 0 : if(rv < 0)
1042 : {
1043 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__, __LINE__, 0, rv, tty::ttyErrorString(rv)});
1044 0 : return -1;
1045 : }
1046 :
1047 0 : rv = m_telnetConn.read(">>", m_readTimeOut);
1048 0 : if(rv < 0)
1049 : {
1050 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__, __LINE__, 0, rv, tty::ttyErrorString(rv)});
1051 0 : return -1;
1052 : }
1053 0 : return 0;
1054 :
1055 : }
1056 :
1057 : inline
1058 0 : int siglentSDG::writeCommand( const std::string & command )
1059 : {
1060 :
1061 0 : int rv = m_telnetConn.write(command, m_writeTimeOut);
1062 0 : if(rv < 0)
1063 : {
1064 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__, __LINE__, 0, rv, tty::ttyErrorString(rv)});
1065 0 : return -1;
1066 : }
1067 :
1068 : //Clear the newline
1069 0 : rv = m_telnetConn.write("\n", m_writeTimeOut);
1070 0 : if(rv < 0)
1071 : {
1072 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__, __LINE__, 0, rv, tty::ttyErrorString(rv)});
1073 0 : return -1;
1074 : }
1075 :
1076 0 : rv = m_telnetConn.read(">>", m_readTimeOut);
1077 0 : if(rv < 0)
1078 : {
1079 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__, __LINE__, 0, rv, tty::ttyErrorString(rv)});
1080 0 : return -1;
1081 : }
1082 :
1083 0 : return 0;
1084 : }
1085 :
1086 : inline
1087 0 : std::string makeCommand( int channel,
1088 : const std::string & afterColon
1089 : )
1090 : {
1091 0 : std::string command = "C";
1092 0 : command += mx::ioutils::convertToString<int>(channel);
1093 0 : command += ":";
1094 0 : command += afterColon;
1095 0 : command += "\r\n";
1096 :
1097 0 : return command;
1098 0 : }
1099 :
1100 : inline
1101 0 : int siglentSDG::queryMDWV( std::string & state,
1102 : int channel
1103 : )
1104 : {
1105 : int rv;
1106 :
1107 0 : if(channel < 1 || channel > 2) return -1;
1108 :
1109 0 : std::string strRead;
1110 :
1111 0 : std::string com = makeCommand(channel, "MDWV?");
1112 :
1113 0 : rv = writeRead( strRead, com);
1114 :
1115 0 : if(rv < 0)
1116 : {
1117 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<text_log>("Error on MDWV? for channel " + mx::ioutils::convertToString<int>(channel), logPrio::LOG_ERROR);
1118 0 : return -1;
1119 : }
1120 :
1121 : int resp_channel;
1122 0 : std::string resp_state;
1123 :
1124 0 : rv = parseMDWV(resp_channel, resp_state, strRead );
1125 :
1126 0 : if(rv == 0)
1127 : {
1128 0 : if(resp_channel != channel)
1129 : {
1130 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, "wrong channel returned"});
1131 0 : return -1;
1132 : }
1133 :
1134 0 : state = resp_state;
1135 : }
1136 : else
1137 : {
1138 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, 0, rv, "parse error"});
1139 0 : return -1;
1140 : }
1141 :
1142 0 : return 0;
1143 0 : }
1144 :
1145 : inline
1146 0 : int siglentSDG::querySWWV( std::string & state,
1147 : int channel
1148 : )
1149 : {
1150 : int rv;
1151 :
1152 0 : if(channel < 1 || channel > 2) return -1;
1153 :
1154 0 : std::string strRead;
1155 :
1156 0 : std::string com = makeCommand(channel, "SWWV?");
1157 :
1158 0 : rv = writeRead( strRead, com);
1159 :
1160 0 : if(rv < 0)
1161 : {
1162 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<text_log>("Error on SWWV? for channel " + mx::ioutils::convertToString<int>(channel), logPrio::LOG_ERROR);
1163 0 : return -1;
1164 : }
1165 :
1166 : int resp_channel;
1167 0 : std::string resp_state;
1168 :
1169 0 : rv = parseSWWV(resp_channel, resp_state, strRead );
1170 :
1171 0 : if(rv == 0)
1172 : {
1173 0 : if(resp_channel != channel)
1174 : {
1175 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, "wrong channel returned"});
1176 0 : return -1;
1177 : }
1178 :
1179 0 : state = resp_state;
1180 : }
1181 : else
1182 : {
1183 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, 0, rv, "parse error"});
1184 0 : return -1;
1185 : }
1186 :
1187 0 : return 0;
1188 0 : }
1189 :
1190 : inline
1191 0 : int siglentSDG::queryBTWV( std::string & state,
1192 : int channel
1193 : )
1194 : {
1195 : int rv;
1196 :
1197 0 : if(channel < 1 || channel > 2) return -1;
1198 :
1199 0 : std::string strRead;
1200 :
1201 0 : std::string com = makeCommand(channel, "BTWV?");
1202 :
1203 0 : rv = writeRead( strRead, com);
1204 :
1205 0 : if(rv < 0)
1206 : {
1207 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<text_log>("Error on BTWV? for channel " + mx::ioutils::convertToString<int>(channel), logPrio::LOG_ERROR);
1208 0 : return -1;
1209 : }
1210 :
1211 : int resp_channel;
1212 0 : std::string resp_state;
1213 :
1214 0 : rv = parseBTWV(resp_channel, resp_state, strRead );
1215 :
1216 0 : if(rv == 0)
1217 : {
1218 0 : if(resp_channel != channel)
1219 : {
1220 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, "wrong channel returned"});
1221 0 : return -1;
1222 : }
1223 :
1224 0 : state = resp_state;
1225 : }
1226 : else
1227 : {
1228 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, 0, rv, "parse error"});
1229 0 : return -1;
1230 : }
1231 :
1232 0 : return 0;
1233 0 : }
1234 :
1235 : inline
1236 0 : int siglentSDG::queryARWV( int & index,
1237 : int channel
1238 : )
1239 : {
1240 : int rv;
1241 :
1242 0 : if(channel < 1 || channel > 2) return -1;
1243 :
1244 0 : std::string strRead;
1245 :
1246 0 : std::string com = makeCommand(channel, "ARWV?");
1247 :
1248 0 : rv = writeRead( strRead, com);
1249 :
1250 0 : if(rv < 0)
1251 : {
1252 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<text_log>("Error on ARWV? for channel " + mx::ioutils::convertToString<int>(channel), logPrio::LOG_ERROR);
1253 0 : return -1;
1254 : }
1255 :
1256 : int resp_channel;
1257 : int resp_index;
1258 :
1259 0 : rv = parseARWV(resp_channel, resp_index, strRead );
1260 :
1261 0 : if(rv == 0)
1262 : {
1263 0 : if(resp_channel != channel)
1264 : {
1265 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, "wrong channel returned"});
1266 0 : return -1;
1267 : }
1268 :
1269 0 : index = resp_index;
1270 : }
1271 : else
1272 : {
1273 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, 0, rv, "parse error"});
1274 0 : return -1;
1275 : }
1276 :
1277 0 : return 0;
1278 0 : }
1279 :
1280 : inline
1281 0 : int siglentSDG::queryBSWV( int channel)
1282 : {
1283 : int rv;
1284 :
1285 0 : if(channel < 1 || channel > 2) return -1;
1286 :
1287 0 : std::string strRead;
1288 :
1289 0 : std::string com = makeCommand(channel, "BSWV?");
1290 :
1291 0 : rv = writeRead( strRead, com);
1292 :
1293 0 : if(rv < 0)
1294 : {
1295 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<text_log>("Error on BSWV? for channel " + mx::ioutils::convertToString<int>(channel), logPrio::LOG_ERROR);
1296 0 : return -1;
1297 : }
1298 :
1299 : int resp_channel;
1300 0 : std::string resp_wvtp;
1301 : double resp_freq, resp_peri, resp_amp, resp_ampvrms, resp_ofst, resp_hlev, resp_llev, resp_phse, resp_wdth;
1302 :
1303 0 : rv = parseBSWV(resp_channel, resp_wvtp, resp_freq, resp_peri, resp_amp, resp_ampvrms, resp_ofst, resp_hlev, resp_llev, resp_phse, resp_wdth, strRead );
1304 :
1305 0 : if(rv == 0)
1306 : {
1307 0 : if(resp_channel != channel)
1308 : {
1309 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, "wrong channel returned"});
1310 0 : return -1;
1311 : }
1312 :
1313 0 : if(channel == 1)
1314 : {
1315 0 : m_C1wvtp = resp_wvtp;
1316 0 : m_C1frequency = resp_freq;
1317 0 : m_C1vpp = resp_amp;
1318 0 : m_C1ofst = resp_ofst;
1319 0 : m_C1phse = resp_phse;
1320 0 : m_C1wdth = resp_wdth;
1321 :
1322 0 : if(m_C1frequency_tgt == -1) m_C1frequency_tgt = m_C1frequency;
1323 0 : if(m_C1vpp_tgt == -1) m_C1vpp_tgt = m_C1vpp;
1324 :
1325 0 : recordParams();
1326 :
1327 0 : updateIfChanged(m_indiP_C1wvtp, "value", resp_wvtp);
1328 0 : updateIfChanged(m_indiP_C1freq, "current", resp_freq);
1329 0 : updateIfChanged(m_indiP_C1peri, "value", resp_peri);
1330 :
1331 0 : updateIfChanged(m_indiP_C1amp, "current", resp_amp);
1332 :
1333 0 : updateIfChanged(m_indiP_C1ampvrms, "value", resp_ampvrms);
1334 0 : updateIfChanged(m_indiP_C1ofst, "value", resp_ofst);
1335 0 : updateIfChanged(m_indiP_C1hlev, "value", resp_hlev);
1336 0 : updateIfChanged(m_indiP_C1llev, "value", resp_llev);
1337 0 : if(m_waveform == "SINE"){updateIfChanged(m_indiP_C1phse, "value", resp_phse);}
1338 0 : if(m_waveform == "PULSE"){updateIfChanged(m_indiP_C1wdth, "value", resp_wdth);}
1339 : }
1340 0 : else if(channel == 2)
1341 : {
1342 0 : m_C2wvtp = resp_wvtp;
1343 0 : m_C2frequency = resp_freq;
1344 0 : m_C2vpp = resp_amp;
1345 0 : m_C2ofst = resp_ofst;
1346 0 : m_C2phse = resp_phse;
1347 0 : m_C2wdth = resp_wdth;
1348 :
1349 0 : if(m_C2frequency_tgt == -1) m_C2frequency_tgt = m_C2frequency;
1350 0 : if(m_C2vpp_tgt == -1) m_C2vpp_tgt = m_C2vpp;
1351 :
1352 0 : recordParams();
1353 :
1354 0 : updateIfChanged(m_indiP_C2wvtp, "value", resp_wvtp);
1355 0 : updateIfChanged(m_indiP_C2freq, "current", resp_freq);
1356 0 : updateIfChanged(m_indiP_C2peri, "value", resp_peri);
1357 0 : updateIfChanged(m_indiP_C2amp, "current", resp_amp);
1358 0 : updateIfChanged(m_indiP_C2ampvrms, "value", resp_ampvrms);
1359 0 : updateIfChanged(m_indiP_C2ofst, "value", resp_ofst);
1360 0 : updateIfChanged(m_indiP_C2hlev, "value", resp_hlev);
1361 0 : updateIfChanged(m_indiP_C2llev, "value", resp_llev);
1362 0 : if(m_waveform == "SINE"){updateIfChanged(m_indiP_C2phse, "value", resp_phse);}
1363 0 : if(m_waveform == "PULSE"){updateIfChanged(m_indiP_C2wdth, "value", resp_wdth);}
1364 : }
1365 : }
1366 : else
1367 : {
1368 0 : log<software_error>({__FILE__,__LINE__, 0, rv, "parse error"});
1369 0 : return -1;
1370 : }
1371 :
1372 0 : return 0;
1373 0 : }
1374 :
1375 : inline
1376 0 : int siglentSDG::querySYNC( bool & sync,
1377 : int channel
1378 : )
1379 : {
1380 : int rv;
1381 :
1382 0 : if(channel < 1 || channel > 2) return -1;
1383 :
1384 0 : std::string strRead;
1385 :
1386 0 : std::string com = makeCommand(channel, "SYNC?");
1387 :
1388 0 : rv = writeRead( strRead, com);
1389 :
1390 0 : if(rv < 0)
1391 : {
1392 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<text_log>("Error on SYNC? for channel " + mx::ioutils::convertToString<int>(channel), logPrio::LOG_ERROR);
1393 0 : return -1;
1394 : }
1395 :
1396 : int resp_channel;
1397 : bool resp_sync;
1398 :
1399 0 : rv = parseSYNC(resp_channel, resp_sync, strRead );
1400 :
1401 0 : if(rv == 0)
1402 : {
1403 0 : if(resp_channel != channel)
1404 : {
1405 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, "wrong channel returned"});
1406 0 : return -1;
1407 : }
1408 :
1409 0 : sync = resp_sync;
1410 : }
1411 : else
1412 : {
1413 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, 0, rv, "parse error"});
1414 0 : return -1;
1415 : }
1416 :
1417 0 : return 0;
1418 0 : }
1419 :
1420 : inline
1421 0 : int siglentSDG::queryOUTP( int channel )
1422 : {
1423 : int rv;
1424 :
1425 0 : if(channel < 1 || channel > 2) return -1;
1426 :
1427 0 : std::string strRead;
1428 :
1429 0 : std::string com = makeCommand(channel, "OUTP?");
1430 :
1431 0 : rv = writeRead( strRead, com);
1432 :
1433 0 : if(rv < 0)
1434 : {
1435 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<text_log>("Error on OUTP? for channel " + mx::ioutils::convertToString<int>(channel), logPrio::LOG_ERROR);
1436 0 : return -1;
1437 : }
1438 :
1439 : int resp_channel;
1440 : int resp_output;
1441 :
1442 0 : rv = parseOUTP(resp_channel, resp_output, strRead );
1443 :
1444 0 : if(rv == 0)
1445 : {
1446 0 : if(resp_channel != channel)
1447 : {
1448 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, "wrong channel returned"});
1449 0 : return -1;
1450 : }
1451 :
1452 0 : std::string ro;
1453 0 : if(resp_output > 0) ro = "On";
1454 0 : else if(resp_output == 0 ) ro = "Off";
1455 0 : else ro = "UNK";
1456 :
1457 0 : if(channel == 1)
1458 : {
1459 0 : m_C1outp = resp_output;
1460 0 : recordParams();
1461 0 : updateIfChanged(m_indiP_C1outp, "value", ro);
1462 : }
1463 :
1464 0 : else if(channel == 2)
1465 : {
1466 0 : m_C2outp = resp_output;
1467 0 : recordParams();
1468 0 : updateIfChanged(m_indiP_C2outp, "value", ro);
1469 : }
1470 0 : }
1471 : else
1472 : {
1473 0 : if((m_powerState != 1 || m_powerTargetState != 1) && !m_shutdown) log<software_error>({__FILE__,__LINE__, 0, rv, "parse error"});
1474 0 : return -1;
1475 : }
1476 :
1477 0 : return 0;
1478 0 : }
1479 :
1480 : inline
1481 0 : int siglentSDG::checkSetup()
1482 : {
1483 0 : std::string state;
1484 : int index;
1485 : int rv;
1486 :
1487 0 : rv = queryMDWV(state, 1);
1488 :
1489 0 : if(rv < 0)
1490 : {
1491 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<software_error>({__FILE__,__LINE__});
1492 0 : return rv;
1493 : }
1494 :
1495 0 : if(state != "OFF")
1496 : {
1497 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<text_log>("Channel 1 MDWV not OFF");
1498 0 : return 1;
1499 : }
1500 :
1501 0 : rv = queryMDWV(state, 2);
1502 :
1503 0 : if(rv < 0)
1504 : {
1505 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<software_error>({__FILE__,__LINE__});
1506 0 : return rv;
1507 : }
1508 :
1509 0 : if(state != "OFF")
1510 : {
1511 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<text_log>("Channel 2 MDWV not OFF");
1512 0 : return 1;
1513 : }
1514 :
1515 0 : rv = querySWWV(state, 1);
1516 :
1517 0 : if(rv < 0)
1518 : {
1519 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<software_error>({__FILE__,__LINE__});
1520 0 : return rv;
1521 : }
1522 :
1523 0 : if(state != "OFF")
1524 : {
1525 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<text_log>("Channel 1 SWWV not OFF");
1526 0 : return 1;
1527 : }
1528 :
1529 0 : rv = querySWWV(state, 2);
1530 :
1531 0 : if(rv < 0)
1532 : {
1533 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<software_error>({__FILE__,__LINE__});
1534 0 : return rv;
1535 : }
1536 :
1537 0 : if(state != "OFF")
1538 : {
1539 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<text_log>("Channel 2 SWWV no OFF");
1540 0 : return 1;
1541 : }
1542 :
1543 0 : rv = queryBTWV(state, 1);
1544 :
1545 0 : if(rv < 0)
1546 : {
1547 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<software_error>({__FILE__,__LINE__});
1548 0 : return rv;
1549 : }
1550 :
1551 0 : if(state != "OFF")
1552 : {
1553 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<text_log>("Channel 1 BTWV not OFF");
1554 0 : return 1;
1555 : }
1556 :
1557 0 : rv = queryBTWV(state, 2);
1558 :
1559 0 : if(rv < 0)
1560 : {
1561 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<software_error>({__FILE__,__LINE__});
1562 0 : return rv;
1563 : }
1564 :
1565 0 : if(state != "OFF")
1566 : {
1567 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<text_log>("Channel 2 BTWV not OFF");
1568 0 : return 1;
1569 : }
1570 :
1571 0 : rv = queryARWV(index, 1);
1572 :
1573 0 : if(rv < 0)
1574 : {
1575 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<software_error>({__FILE__,__LINE__});
1576 0 : return rv;
1577 : }
1578 :
1579 0 : if(index != 0)
1580 : {
1581 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<text_log>("Channel 1 ARWV not 1");
1582 0 : return 1;
1583 : }
1584 :
1585 0 : rv = queryARWV(index, 2);
1586 :
1587 0 : if(rv < 0)
1588 : {
1589 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<software_error>({__FILE__,__LINE__});
1590 0 : return rv;
1591 : }
1592 :
1593 0 : if(index != 0)
1594 : {
1595 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<text_log>("Channel 2 ARWV not 1");
1596 0 : return 1;
1597 : }
1598 :
1599 0 : rv = querySYNC(m_C1sync, 1);
1600 :
1601 0 : if(rv < 0)
1602 : {
1603 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<software_error>({__FILE__,__LINE__});
1604 0 : return rv;
1605 : }
1606 :
1607 0 : rv = querySYNC(m_C2sync, 2);
1608 :
1609 0 : if(rv < 0)
1610 : {
1611 0 : if((m_powerState != 1 || m_powerTargetState != 1) > 0 && !m_shutdown) log<software_error>({__FILE__,__LINE__});
1612 0 : return rv;
1613 : }
1614 :
1615 :
1616 0 : return 0;
1617 0 : }
1618 :
1619 : inline
1620 0 : int siglentSDG::normalizeSetup()
1621 : {
1622 :
1623 0 : std::cerr << "Normalizing . . .";
1624 :
1625 0 : recordParams(true);
1626 :
1627 0 : changeOutp(1, "OFF");
1628 0 : changeOutp(2, "OFF");
1629 :
1630 0 : std::string afterColon;
1631 0 : std::string command;
1632 :
1633 0 : afterColon = "MDWV STATE,OFF";
1634 0 : command = makeCommand(1, afterColon);
1635 0 : writeCommand(command);
1636 :
1637 0 : command = makeCommand(2, afterColon);
1638 0 : writeCommand(command);
1639 :
1640 0 : afterColon = "SWWV STATE,OFF";
1641 0 : command = makeCommand(1, afterColon);
1642 0 : writeCommand(command);
1643 :
1644 0 : command = makeCommand(2, afterColon);
1645 0 : writeCommand(command);
1646 :
1647 0 : afterColon = "BTWV STATE,OFF";
1648 0 : command = makeCommand(1, afterColon);
1649 0 : writeCommand(command);
1650 :
1651 0 : command = makeCommand(2, afterColon);
1652 0 : writeCommand(command);
1653 :
1654 0 : afterColon = "ARWV INDEX,0";
1655 0 : command = makeCommand(1, afterColon);
1656 0 : writeCommand(command);
1657 :
1658 0 : command = makeCommand(2, afterColon);
1659 0 : writeCommand(command);
1660 :
1661 0 : changeWvtp(1, m_waveform);
1662 0 : changeWvtp(2, m_waveform);
1663 :
1664 0 : changeFreq(1, 0);
1665 0 : changeFreq(2, 0);
1666 :
1667 0 : changeAmp(1, m_C1vppDefault);
1668 0 : changeAmp(2, m_C2vppDefault);
1669 :
1670 0 : if(m_waveform == "SINE")
1671 : {
1672 0 : changePhse(1, 0);
1673 0 : changePhse(2, 0);
1674 : }
1675 0 : else if(m_waveform == "PULSE")
1676 : {
1677 0 : changeWdth(1, 0);
1678 0 : changeWdth(2, 0);
1679 : }
1680 :
1681 0 : changeOfst(1, m_C1ofst);
1682 0 : changeOfst(2, m_C2ofst);
1683 :
1684 0 : changeWvtp(1, "DC");
1685 0 : changeWvtp(2, "DC");
1686 :
1687 :
1688 0 : if(m_C1outpOn && m_waveform == "PULSE")
1689 : {
1690 0 : changeOutp(1, "ON");
1691 : }
1692 : else
1693 : {
1694 0 : changeOutp(1, "OFF");
1695 : }
1696 0 : if(m_C2outpOn && m_waveform == "PULSE")
1697 : {
1698 0 : changeOutp(2, "ON");
1699 : }
1700 : else
1701 : {
1702 0 : changeOutp(2, "OFF");
1703 : }
1704 :
1705 0 : changeWvtp(1, m_waveform);
1706 0 : changeWvtp(2, m_waveform);
1707 :
1708 0 : recordParams(true);
1709 :
1710 0 : std::cerr << "Done\n";
1711 0 : return 0;
1712 0 : }
1713 :
1714 : inline
1715 0 : int siglentSDG::changeOutp( int channel,
1716 : const std::string & newOutp
1717 : )
1718 : {
1719 0 : if(channel < 1 || channel > 2) return -1;
1720 :
1721 0 : std::string no;
1722 :
1723 0 : if(newOutp == "Off" || newOutp == "OFF" || newOutp == "off") no = "OFF";
1724 0 : else if(newOutp == "On" || newOutp == "ON" || newOutp == "on") no = "ON";
1725 : else
1726 : {
1727 0 : log<software_error>({__FILE__, __LINE__, "Invalid OUTP spec: " + newOutp});
1728 0 : return -1;
1729 : }
1730 :
1731 0 : std::string afterColon = "OUTP " + no;
1732 0 : std::string command = makeCommand(channel, afterColon);
1733 :
1734 0 : log<text_log>("Ch. " + std::to_string(channel) + " OUTP to " + newOutp, logPrio::LOG_NOTICE);
1735 :
1736 0 : recordParams(true);
1737 0 : int rv = writeCommand(command);
1738 0 : recordParams(true);
1739 :
1740 0 : if(rv < 0)
1741 : {
1742 0 : if((m_powerState != 1 || m_powerTargetState != 1)) log<software_error>({__FILE__, __LINE__});
1743 0 : return -1;
1744 : }
1745 :
1746 :
1747 0 : if(channel == 1 && no == "ON")
1748 : {
1749 0 : if(changeSync(1, true) < 0)
1750 : {
1751 0 : return log<software_error,-1>({__FILE__, __LINE__});
1752 : }
1753 : }
1754 0 : return 0;
1755 0 : }
1756 :
1757 : inline
1758 : int siglentSDG::changeOutp( int channel,
1759 : const pcf::IndiProperty &ipRecv
1760 : )
1761 : {
1762 : if(channel < 1 || channel > 2) return -1;
1763 :
1764 : if(state() != stateCodes::READY && state() != stateCodes::OPERATING) return 0;
1765 :
1766 : std::string newOutp;
1767 : try
1768 : {
1769 : newOutp = ipRecv["value"].get<std::string>();
1770 : }
1771 : catch(...)
1772 : {
1773 : log<software_error>({__FILE__, __LINE__, "Exception caught."});
1774 : return -1;
1775 : }
1776 :
1777 : //Make sure we don't change things while other things are being updated.
1778 : std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before conducting any communications.
1779 :
1780 : stateCodes::stateCodeT enterState = state();
1781 : state(stateCodes::CONFIGURING);
1782 :
1783 : int rv = changeOutp(channel, newOutp);
1784 : if(rv < 0) log<software_error>({__FILE__, __LINE__});
1785 :
1786 : state(enterState);
1787 :
1788 : return rv;
1789 : }
1790 :
1791 : inline
1792 0 : int siglentSDG::changeFreq( int channel,
1793 : double newFreq
1794 : )
1795 : {
1796 0 : if(channel < 1 || channel > 2) return -1;
1797 :
1798 0 : if(newFreq > m_maxFreq.back())
1799 : {
1800 0 : newFreq = m_maxFreq.back();
1801 : }
1802 :
1803 0 : if(newFreq < 0)
1804 : {
1805 0 : newFreq = 0;
1806 : }
1807 :
1808 0 : if(m_waveform != "PULSE"){
1809 : // Do not limit amp if a PULSE wave
1810 :
1811 0 : double amp = m_C1vpp_tgt;
1812 0 : if(channel == 2) amp = m_C2vpp_tgt;
1813 :
1814 0 : size_t i =0;
1815 0 : while( i < m_ampMax.size())
1816 : {
1817 0 : if(m_maxFreq[i] >= newFreq) break;
1818 0 : ++i;
1819 : }
1820 :
1821 0 : std::cerr << "Max Amp @ " << amp << " = " << m_ampMax[i] << " (freq)\n";
1822 :
1823 0 : if( amp > m_ampMax[i] )
1824 : {
1825 0 : log<text_log>("Ch. " + std::to_string(channel) + " FREQ not set due to amplitude exceeding limit for " + std::to_string(newFreq), logPrio::LOG_WARNING);
1826 0 : return 0;
1827 : }
1828 :
1829 : }
1830 :
1831 : //Now we update target
1832 0 : if(channel==1)
1833 : {
1834 0 : m_C1frequency_tgt = newFreq;
1835 : }
1836 : else
1837 : {
1838 0 : m_C2frequency_tgt = newFreq;
1839 : }
1840 :
1841 :
1842 0 : std::string afterColon = "BSWV FRQ," + mx::ioutils::convertToString<double>(newFreq);
1843 0 : std::string command = makeCommand(channel, afterColon);
1844 :
1845 0 : log<text_log>("Ch. " + std::to_string(channel) + " FREQ to " + std::to_string(newFreq), logPrio::LOG_NOTICE);
1846 :
1847 0 : recordParams(true);
1848 0 : int rv = writeCommand(command);
1849 0 : recordParams(true);
1850 :
1851 0 : if(rv < 0)
1852 : {
1853 0 : if((m_powerState != 1 || m_powerTargetState != 1)) log<software_error>({__FILE__, __LINE__});
1854 0 : return -1;
1855 : }
1856 :
1857 : // we want to automatically set the pulse width when setting a new frequency
1858 0 : if(m_waveform == "PULSE"){
1859 : // we want to auto change the pulse duration, want either 0.000250 or 0.5%
1860 0 : double wdthLim = 0.5 / newFreq ; // this is the limit if we don't have long enough frequencies
1861 0 : double wdth250 = 0.000250; // this is the ideal length of low dip WHACK THINGS.. it's doubling, want to be 0.00025
1862 0 : double newWdth = wdthLim;
1863 :
1864 0 : if(wdthLim > wdth250){
1865 0 : newWdth = wdth250;
1866 0 : log<text_log>("Ch. " + std::to_string(channel) + " WDTH auto-changing to duty cycle limit: " + std::to_string(newWdth), logPrio::LOG_NOTICE);
1867 : }else{
1868 0 : log<text_log>("Ch. " + std::to_string(channel) + " WDTH auto-changing to 250us ideal case: " + std::to_string(newWdth), logPrio::LOG_NOTICE);
1869 : }
1870 :
1871 : //changing pulse width
1872 0 : changeWdth(channel, newWdth);
1873 : }
1874 :
1875 0 : return 0;
1876 0 : }
1877 :
1878 : inline
1879 : int siglentSDG::changeFreq( int channel,
1880 : const pcf::IndiProperty &ipRecv
1881 : )
1882 : {
1883 : if(channel < 1 || channel > 2) return -1;
1884 :
1885 : if(state() != stateCodes::READY && state() != stateCodes::OPERATING) return 0;
1886 :
1887 : double newFreq;
1888 : try
1889 : {
1890 : newFreq = ipRecv["target"].get<double>();
1891 : }
1892 : catch(...)
1893 : {
1894 : log<software_error>({__FILE__, __LINE__, "Exception caught."});
1895 : return -1;
1896 : }
1897 :
1898 : //Make sure we don't change things while other things are being updated.
1899 : std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before conducting any communications.
1900 : stateCodes::stateCodeT enterState = state();
1901 : state(stateCodes::CONFIGURING);
1902 :
1903 : int rv = changeFreq(channel,newFreq);
1904 : if(rv < 0) log<software_error>({__FILE__, __LINE__});
1905 :
1906 : state(enterState);
1907 :
1908 : return rv;
1909 : }
1910 :
1911 : inline
1912 0 : int siglentSDG::changeAmp( int channel,
1913 : double newAmp
1914 : )
1915 : {
1916 0 : if(channel < 1 || channel > 2) return -1;
1917 :
1918 0 : double offst = m_C1ofst;
1919 0 : if(channel == 2) offst = m_C2ofst;
1920 :
1921 0 : double confAmpMax = m_C1ampMax;
1922 0 : if(channel == 2) confAmpMax = m_C2ampMax;
1923 :
1924 0 : if (0.5 * newAmp + offst > confAmpMax)
1925 : {
1926 0 : newAmp = 2 * (confAmpMax - offst);
1927 0 : log<text_log>("Ch. " + std::to_string(channel) + " AMP max-limited by config value to " + std::to_string(newAmp), logPrio::LOG_WARNING);
1928 :
1929 : }
1930 :
1931 : // Do not limit freq if a PULSE wave
1932 0 : if(m_waveform != "PULSE")
1933 : {
1934 :
1935 : //Ensure we won't excede the 0-10V range for SINE
1936 0 : if(offst + 0.5*newAmp > 10)
1937 : {
1938 0 : newAmp = 2.*(10.0 - offst);
1939 0 : log<text_log>("Ch. " + std::to_string(channel) + " AMP limited at 10 V by OFST to " + std::to_string(newAmp), logPrio::LOG_WARNING);
1940 : }
1941 :
1942 0 : if(offst - 0.5*newAmp < 0)
1943 : {
1944 0 : newAmp = 2*(offst);
1945 0 : log<text_log>("Ch. " + std::to_string(channel) + " AMP limited at 0 V by OFST to " + std::to_string(newAmp), logPrio::LOG_WARNING);
1946 : }
1947 :
1948 0 : double freq = m_C1frequency_tgt;
1949 0 : if(channel == 2) freq = m_C2frequency_tgt;
1950 :
1951 : double ampMax;
1952 0 : size_t i=0;
1953 0 : while(i < m_ampMax.size())
1954 : {
1955 0 : if( m_maxFreq[i] >= freq ) break;
1956 0 : ++i;
1957 : }
1958 :
1959 0 : std::cerr << "Max Amp @ " << freq << " = " << ampMax << "\n";
1960 :
1961 : //Ensure we don't exced safe ranges for device
1962 0 : if(newAmp > ampMax)
1963 : {
1964 0 : newAmp = ampMax;
1965 0 : log<text_log>("Ch. " + std::to_string(channel) + " AMP max-limited to " + std::to_string(newAmp), logPrio::LOG_WARNING);
1966 : }
1967 :
1968 0 : if(newAmp < 0)
1969 : {
1970 0 : newAmp = 0;
1971 0 : log<text_log>("Ch. " + std::to_string(channel) + " AMP min-limited to " + std::to_string(newAmp), logPrio::LOG_WARNING);
1972 : }
1973 : }
1974 :
1975 : //Now update target
1976 0 : if(channel==1)
1977 : {
1978 0 : m_C1vpp_tgt = newAmp;
1979 : }
1980 : else
1981 : {
1982 0 : m_C2vpp_tgt = newAmp;
1983 : }
1984 :
1985 :
1986 0 : std::string afterColon = "BSWV AMP," + mx::ioutils::convertToString<double>(newAmp);
1987 0 : std::string command = makeCommand(channel, afterColon);
1988 :
1989 0 : log<text_log>("Ch. " + std::to_string(channel) + " AMP set to " + std::to_string(newAmp), logPrio::LOG_NOTICE);
1990 :
1991 0 : recordParams(true);
1992 0 : int rv = writeCommand(command);
1993 0 : recordParams(true);
1994 :
1995 0 : if(rv < 0)
1996 : {
1997 0 : if((m_powerState != 1 || m_powerTargetState != 1)) log<software_error>({__FILE__, __LINE__});
1998 0 : return -1;
1999 : }
2000 :
2001 0 : return 0;
2002 0 : }
2003 :
2004 : inline
2005 : int siglentSDG::changeAmp( int channel,
2006 : const pcf::IndiProperty &ipRecv
2007 : )
2008 : {
2009 : if(channel < 1 || channel > 2) return -1;
2010 :
2011 : if(state() != stateCodes::READY && state() != stateCodes::OPERATING) return 0;
2012 :
2013 : double newAmp;
2014 : try
2015 : {
2016 : newAmp = ipRecv["target"].get<double>();
2017 : }
2018 : catch(...)
2019 : {
2020 : log<software_error>({__FILE__, __LINE__, "Exception caught."});
2021 : return -1;
2022 : }
2023 :
2024 : //Make sure we don't change things while other things are being updated.
2025 : std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before conducting any communications.
2026 :
2027 : stateCodes::stateCodeT enterState = state();
2028 : state(stateCodes::CONFIGURING);
2029 :
2030 : int rv = changeAmp(channel, newAmp);
2031 : if(rv < 0) log<software_error>({__FILE__, __LINE__});
2032 :
2033 : state(enterState);
2034 :
2035 : return rv;
2036 : }
2037 :
2038 : inline
2039 0 : int siglentSDG::changeOfst( int channel,
2040 : double newOfst
2041 : )
2042 : {
2043 0 : if(channel < 1 || channel > 2) return -1;
2044 :
2045 0 : double amp = m_C1vpp;
2046 0 : if(channel == 2) amp = m_C2vpp;
2047 :
2048 0 : double ampMax = m_C1ampMax;
2049 0 : if(channel == 2) ampMax = m_C2ampMax;
2050 :
2051 :
2052 0 : if(newOfst + 0.5*amp > ampMax)
2053 : {
2054 0 : newOfst = ampMax - 0.5*amp;
2055 0 : log<text_log>("Ch. " + std::to_string(channel) + " OFST limited at " + std::to_string(ampMax) + " V by AMP to " + std::to_string(newOfst), logPrio::LOG_WARNING);
2056 : }
2057 :
2058 0 : if(newOfst - 0.5*amp < 0)
2059 : {
2060 0 : newOfst = 0.5*amp;
2061 0 : log<text_log>("Ch. " + std::to_string(channel) + " OFST limited at 0 V by AMP to " + std::to_string(newOfst), logPrio::LOG_WARNING);
2062 : }
2063 :
2064 0 : if(newOfst > cs_MaxOfst)
2065 : {
2066 0 : newOfst = cs_MaxOfst;
2067 0 : log<text_log>("Ch. " + std::to_string(channel) + " OFST max-limited to " + std::to_string(newOfst), logPrio::LOG_WARNING);
2068 : }
2069 :
2070 0 : if(newOfst < 0.0)
2071 : {
2072 0 : newOfst = 0.0;
2073 0 : log<text_log>("Ch. " + std::to_string(channel) + " OFST min-limited to " + std::to_string(newOfst), logPrio::LOG_WARNING);
2074 : }
2075 :
2076 0 : std::string afterColon = "BSWV OFST," + mx::ioutils::convertToString<double>(newOfst);
2077 0 : std::string command = makeCommand(channel, afterColon);
2078 :
2079 0 : log<text_log>("Ch. " + std::to_string(channel) + " OFST set to " + std::to_string(newOfst), logPrio::LOG_NOTICE);
2080 :
2081 0 : int rv = writeCommand(command);
2082 :
2083 0 : if(rv < 0)
2084 : {
2085 0 : if((m_powerState != 1 || m_powerTargetState != 1)) log<software_error>({__FILE__, __LINE__});
2086 0 : return -1;
2087 : }
2088 :
2089 0 : return 0;
2090 0 : }
2091 :
2092 : inline
2093 : int siglentSDG::changeOfst( int channel,
2094 : const pcf::IndiProperty &ipRecv
2095 : )
2096 : {
2097 : if(channel < 1 || channel > 2) return -1;
2098 :
2099 : if(state() != stateCodes::READY && state() != stateCodes::OPERATING) return 0;
2100 :
2101 : double newOfst;
2102 : try
2103 : {
2104 : newOfst = ipRecv["value"].get<double>();
2105 : }
2106 : catch(...)
2107 : {
2108 : log<software_error>({__FILE__, __LINE__, "Exception caught."});
2109 : return -1;
2110 : }
2111 :
2112 : //Make sure we don't change things while other things are being updated.
2113 : std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before conducting any communications.
2114 :
2115 : stateCodes::stateCodeT enterState = state();
2116 : state(stateCodes::CONFIGURING);
2117 :
2118 : int rv = changeOfst(channel, newOfst);
2119 : if(rv < 0) log<software_error>({__FILE__, __LINE__});
2120 :
2121 : state(enterState);
2122 :
2123 : return rv;
2124 : }
2125 :
2126 : inline
2127 0 : int siglentSDG::changePhse( int channel,
2128 : double newPhse
2129 : )
2130 : {
2131 0 : if(channel < 1 || channel > 2) return -1;
2132 :
2133 0 : if(m_waveform == "PULSE"){
2134 0 : log<text_log>("Ch. " + std::to_string(channel) + " PHSE not set for PULSE waveform.", logPrio::LOG_WARNING);
2135 0 : return 0;
2136 : }
2137 :
2138 0 : std::string afterColon = "BSWV PHSE," + mx::ioutils::convertToString<double>(newPhse);
2139 0 : std::string command = makeCommand(channel, afterColon);
2140 :
2141 0 : log<text_log>("Ch. " + std::to_string(channel) + " PHSE to " + std::to_string(newPhse), logPrio::LOG_NOTICE);
2142 :
2143 0 : int rv = writeCommand(command);
2144 :
2145 0 : if(rv < 0)
2146 : {
2147 0 : if((m_powerState != 1 || m_powerTargetState != 1)) log<software_error>({__FILE__, __LINE__});
2148 0 : return -1;
2149 : }
2150 :
2151 0 : return 0;
2152 0 : }
2153 :
2154 : inline
2155 : int siglentSDG::changePhse( int channel,
2156 : const pcf::IndiProperty &ipRecv
2157 : )
2158 : {
2159 : if(channel < 1 || channel > 2) return -1;
2160 :
2161 : if(state() != stateCodes::READY && state() != stateCodes::OPERATING) return 0;
2162 :
2163 : double newPhse;
2164 : try
2165 : {
2166 : newPhse = ipRecv["value"].get<double>();
2167 : }
2168 : catch(...)
2169 : {
2170 : log<software_error>({__FILE__, __LINE__, "Exception caught."});
2171 : return -1;
2172 : }
2173 :
2174 : //Make sure we don't change things while other things are being updated.
2175 : std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before conducting any communications.
2176 :
2177 : stateCodes::stateCodeT enterState = state();
2178 : state(stateCodes::CONFIGURING);
2179 :
2180 : int rv = changePhse(channel, newPhse);
2181 : if(rv < 0) log<software_error>({__FILE__, __LINE__});
2182 :
2183 : state(enterState);
2184 :
2185 : return rv;
2186 : }
2187 :
2188 : inline
2189 0 : int siglentSDG::changeWdth( int channel,
2190 : double newWdth
2191 : )
2192 : {
2193 0 : if(channel < 1 || channel > 2) return -1;
2194 :
2195 0 : if(m_waveform != "PULSE"){
2196 0 : log<text_log>("Ch. " + std::to_string(channel) + " WDTH can not be set, waveforem not PULSE.", logPrio::LOG_WARNING);
2197 0 : return 0;
2198 : }
2199 :
2200 0 : std::string afterColon = "BSWV WIDTH," + mx::ioutils::convertToString<double>(newWdth);
2201 0 : std::string command = makeCommand(channel, afterColon);
2202 :
2203 0 : log<text_log>("Ch. " + std::to_string(channel) + " WDTH to " + std::to_string(newWdth), logPrio::LOG_NOTICE);
2204 :
2205 0 : int rv = writeCommand(command);
2206 :
2207 0 : if(rv < 0)
2208 : {
2209 0 : if((m_powerState != 1 || m_powerTargetState != 1)) log<software_error>({__FILE__, __LINE__});
2210 0 : return -1;
2211 : }
2212 :
2213 0 : return 0;
2214 0 : }
2215 :
2216 : inline
2217 : int siglentSDG::changeWdth( int channel,
2218 : const pcf::IndiProperty &ipRecv
2219 : )
2220 : {
2221 : if(channel < 1 || channel > 2) return -1;
2222 :
2223 : if(state() != stateCodes::READY && state() != stateCodes::OPERATING) return 0;
2224 :
2225 : double newWdth;
2226 : try
2227 : {
2228 : newWdth = ipRecv["value"].get<double>();
2229 : }
2230 : catch(...)
2231 : {
2232 : log<software_error>({__FILE__, __LINE__, "Exception caught."});
2233 : return -1;
2234 : }
2235 :
2236 : //Make sure we don't change things while other things are being updated.
2237 : std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before conducting any communications.
2238 :
2239 : stateCodes::stateCodeT enterState = state();
2240 : state(stateCodes::CONFIGURING);
2241 :
2242 : int rv = changeWdth(channel, newWdth);
2243 : if(rv < 0) log<software_error>({__FILE__, __LINE__});
2244 :
2245 : state(enterState);
2246 :
2247 : return rv;
2248 : }
2249 :
2250 :
2251 : inline
2252 0 : int siglentSDG::changeWvtp( int channel,
2253 : const std::string & newWvtp
2254 : )
2255 : {
2256 0 : if(channel < 1 || channel > 2) return -1;
2257 :
2258 0 : std::string afterColon = "BSWV WVTP," + newWvtp;
2259 0 : std::string command = makeCommand(channel, afterColon);
2260 :
2261 0 : log<text_log>("Ch. " + std::to_string(channel) + " WVTP to " + newWvtp, logPrio::LOG_NOTICE);
2262 :
2263 0 : int rv = writeCommand(command);
2264 :
2265 0 : if(rv < 0)
2266 : {
2267 0 : if((m_powerState != 1 || m_powerTargetState != 1)) log<software_error>({__FILE__, __LINE__});
2268 0 : return -1;
2269 : }
2270 :
2271 0 : return 0;
2272 0 : }
2273 :
2274 : inline
2275 : int siglentSDG::changeWvtp( int channel,
2276 : const pcf::IndiProperty &ipRecv
2277 : )
2278 : {
2279 : if(channel < 1 || channel > 2) return -1;
2280 :
2281 : if(state() != stateCodes::READY && state() != stateCodes::OPERATING) return 0;
2282 :
2283 : std::string newWvtp;
2284 : try
2285 : {
2286 : newWvtp = ipRecv["value"].get<std::string>();
2287 : }
2288 : catch(...)
2289 : {
2290 : log<software_error>({__FILE__, __LINE__, "Exception caught."});
2291 : return -1;
2292 : }
2293 :
2294 : //Make sure we don't change things while other things are being updated.
2295 : std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before conducting any communications.
2296 :
2297 : stateCodes::stateCodeT enterState = state();
2298 : state(stateCodes::CONFIGURING);
2299 :
2300 : int rv = changeWvtp(channel, newWvtp);
2301 : if(rv < 0) log<software_error>({__FILE__, __LINE__});
2302 :
2303 : state(enterState);
2304 :
2305 : return rv;
2306 : }
2307 :
2308 : inline
2309 0 : int siglentSDG::changeSync( int channel,
2310 : const bool newSync
2311 : )
2312 : {
2313 0 : if(channel < 1 || channel > 2) return -1;
2314 :
2315 0 : std::string afterColon = "SYNC ";
2316 0 : if(newSync) afterColon += "ON";
2317 0 : else afterColon += "OFF";
2318 :
2319 0 : std::string command = makeCommand(channel, afterColon);
2320 :
2321 0 : if(newSync) log<text_log>("Ch. " + std::to_string(channel) + " SYNC to ON", logPrio::LOG_NOTICE);
2322 0 : else log<text_log>("Ch. " + std::to_string(channel) + " SYNC to OFF", logPrio::LOG_NOTICE);
2323 :
2324 0 : recordParams(true);
2325 0 : int rv = writeCommand(command);
2326 0 : recordParams(true);
2327 :
2328 0 : if(rv < 0)
2329 : {
2330 0 : if((m_powerState != 1 || m_powerTargetState != 1)) log<software_error>({__FILE__, __LINE__});
2331 0 : return -1;
2332 : }
2333 :
2334 0 : return 0;
2335 0 : }
2336 :
2337 : inline
2338 : int siglentSDG::changeSync( int channel,
2339 : const pcf::IndiProperty &ipRecv
2340 : )
2341 : {
2342 : if(channel < 1 || channel > 2) return -1;
2343 :
2344 : if(state() != stateCodes::READY && state() != stateCodes::OPERATING) return 0;
2345 :
2346 : bool newSync;
2347 :
2348 : if(!ipRecv.find("toggle")) return 0;
2349 :
2350 : if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off )
2351 : {
2352 : newSync = false;
2353 : }
2354 :
2355 : if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
2356 : {
2357 : newSync = true;
2358 : }
2359 :
2360 : //Make sure we don't change things while other things are being updated.
2361 : std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before conducting any communications.
2362 :
2363 : stateCodes::stateCodeT enterState = state();
2364 : state(stateCodes::CONFIGURING);
2365 :
2366 : int rv = changeSync(channel, newSync);
2367 : if(rv < 0) log<software_error>({__FILE__, __LINE__});
2368 :
2369 : state(enterState);
2370 :
2371 : return rv;
2372 : }
2373 :
2374 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C1outp)(const pcf::IndiProperty &ipRecv)
2375 : {
2376 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C1outp, ipRecv);
2377 :
2378 : return changeOutp(1, ipRecv);
2379 :
2380 : }
2381 :
2382 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C1freq)(const pcf::IndiProperty &ipRecv)
2383 : {
2384 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C1freq, ipRecv);
2385 :
2386 : return changeFreq(1, ipRecv);
2387 : }
2388 :
2389 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C1amp)(const pcf::IndiProperty &ipRecv)
2390 : {
2391 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C1amp, ipRecv);
2392 :
2393 : return changeAmp(1, ipRecv);
2394 : }
2395 :
2396 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C1ofst)(const pcf::IndiProperty &ipRecv)
2397 : {
2398 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C1ofst, ipRecv);
2399 :
2400 : return changeOfst(1, ipRecv);
2401 : }
2402 :
2403 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C1phse)(const pcf::IndiProperty &ipRecv)
2404 : {
2405 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C1phse, ipRecv);
2406 :
2407 : return changePhse(1, ipRecv);
2408 : }
2409 :
2410 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C1wdth)(const pcf::IndiProperty &ipRecv)
2411 : {
2412 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C1wdth, ipRecv);
2413 :
2414 : return changeWdth(1, ipRecv);
2415 : }
2416 :
2417 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C1wvtp)(const pcf::IndiProperty &ipRecv)
2418 : {
2419 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C1wvtp, ipRecv);
2420 :
2421 : return changeWvtp(1, ipRecv);
2422 : }
2423 :
2424 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C1sync)(const pcf::IndiProperty &ipRecv)
2425 : {
2426 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C1sync, ipRecv);
2427 :
2428 : return changeSync(1, ipRecv);
2429 : }
2430 :
2431 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C2outp)(const pcf::IndiProperty &ipRecv)
2432 : {
2433 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C2outp, ipRecv);
2434 :
2435 : return changeOutp(2, ipRecv);
2436 : }
2437 :
2438 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C2freq)(const pcf::IndiProperty &ipRecv)
2439 : {
2440 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C2freq, ipRecv);
2441 :
2442 : return changeFreq(2, ipRecv);
2443 : }
2444 :
2445 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C2amp)(const pcf::IndiProperty &ipRecv)
2446 : {
2447 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C2amp, ipRecv);
2448 :
2449 : return changeAmp(2, ipRecv);
2450 : }
2451 :
2452 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C2ofst)(const pcf::IndiProperty &ipRecv)
2453 : {
2454 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C2ofst, ipRecv);
2455 :
2456 : return changeOfst(2, ipRecv);
2457 : }
2458 :
2459 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C2phse)(const pcf::IndiProperty &ipRecv)
2460 : {
2461 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C2phse, ipRecv);
2462 :
2463 : return changePhse(2, ipRecv);
2464 : }
2465 :
2466 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C2wdth)(const pcf::IndiProperty &ipRecv)
2467 : {
2468 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C2wdth, ipRecv);
2469 :
2470 : return changeWdth(2, ipRecv);
2471 : }
2472 :
2473 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C2wvtp)(const pcf::IndiProperty &ipRecv)
2474 : {
2475 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C2wvtp, ipRecv);
2476 :
2477 : return changeWvtp(2, ipRecv);
2478 : }
2479 :
2480 3 : INDI_NEWCALLBACK_DEFN(siglentSDG, m_indiP_C2sync)(const pcf::IndiProperty &ipRecv)
2481 : {
2482 3 : INDI_VALIDATE_CALLBACK_PROPS(m_indiP_C2sync, ipRecv);
2483 :
2484 : return changeSync(2, ipRecv);
2485 : }
2486 :
2487 : // todo: add change width INDI
2488 :
2489 : // todo: add change edge INDI
2490 :
2491 : inline
2492 0 : int siglentSDG::checkRecordTimes()
2493 : {
2494 0 : return telemeter<siglentSDG>::checkRecordTimes(telem_fxngen());
2495 : }
2496 :
2497 : inline
2498 0 : int siglentSDG::recordTelem( const telem_fxngen * )
2499 : {
2500 0 : return recordParams(true);
2501 : }
2502 :
2503 : inline
2504 0 : int siglentSDG::recordParams(bool force)
2505 : {
2506 : static double old_C1outp = -1e30; //Ensure first time writes
2507 0 : static double old_C1frequency = m_C1frequency;
2508 0 : static double old_C1vpp = m_C1vpp;
2509 0 : static double old_C1ofst = m_C1ofst;
2510 0 : static double old_C1phse = m_C1phse;
2511 0 : static double old_C1wdth = m_C1wdth;
2512 0 : static std::string old_C1wvtp = m_C1wvtp;
2513 0 : static bool old_C1sync = m_C1sync;
2514 0 : static double old_C2outp = m_C2outp;
2515 0 : static double old_C2frequency = m_C2frequency;
2516 0 : static double old_C2vpp = m_C2vpp;
2517 0 : static double old_C2ofst = m_C2ofst;
2518 0 : static double old_C2phse = m_C2phse;
2519 0 : static double old_C2wdth = m_C2wdth;
2520 0 : static std::string old_C2wvtp = m_C2wvtp;
2521 0 : static bool old_C2sync = m_C2sync;
2522 :
2523 0 : bool write = false;
2524 :
2525 0 : if(!force)
2526 : {
2527 0 : if( old_C1outp != m_C1outp ) write = true;
2528 0 : else if( old_C1frequency != m_C1frequency ) write = true;
2529 0 : else if( old_C1vpp != m_C1vpp ) write = true;
2530 0 : else if( old_C1ofst != m_C1ofst ) write = true;
2531 0 : else if( old_C1phse != m_C1phse ) write = true;
2532 0 : else if( old_C1wdth != m_C1wdth ) write = true;
2533 0 : else if( old_C1wvtp != m_C1wvtp ) write = true;
2534 0 : else if( old_C1sync != m_C1sync ) write = true;
2535 0 : else if( old_C2outp != m_C2outp ) write = true;
2536 0 : else if( old_C2frequency != m_C2frequency ) write = true;
2537 0 : else if( old_C2vpp != m_C2vpp ) write = true;
2538 0 : else if( old_C2ofst != m_C2ofst ) write = true;
2539 0 : else if( old_C2phse != m_C2phse ) write = true;
2540 0 : else if( old_C2wdth != m_C2wdth ) write = true;
2541 0 : else if( old_C2wvtp != m_C2wvtp ) write = true;
2542 0 : else if( old_C2sync != m_C2sync ) write = true;
2543 : }
2544 :
2545 : // todo: add if statement for all of the write??
2546 :
2547 0 : if(force || write)
2548 : {
2549 0 : uint8_t C1wvtp = 3;
2550 0 : if(m_C1wvtp == "DC") C1wvtp = TELEM_FXNGEN_WVTP_DC;
2551 0 : else if(m_C1wvtp == "SINE") C1wvtp = TELEM_FXNGEN_WVTP_SINE;
2552 0 : else if(m_C1wvtp == "PULSE") C1wvtp = TELEM_FXNGEN_WVTP_PULSE;
2553 :
2554 0 : uint8_t C2wvtp = 3;
2555 0 : if(m_C2wvtp == "DC") C2wvtp = TELEM_FXNGEN_WVTP_DC;
2556 0 : else if(m_C2wvtp == "SINE") C2wvtp = TELEM_FXNGEN_WVTP_SINE;
2557 0 : else if(m_C2wvtp == "PULSE") C2wvtp = TELEM_FXNGEN_WVTP_PULSE;
2558 :
2559 0 : telem<telem_fxngen>({m_C1outp, m_C1frequency, m_C1vpp, m_C1ofst, m_C1phse, C1wvtp,
2560 0 : m_C2outp, m_C2frequency, m_C2vpp, m_C2ofst, m_C2phse, C2wvtp,
2561 0 : m_C1sync, m_C2sync, m_C1wdth, m_C2wdth});
2562 :
2563 0 : old_C1outp = m_C1outp;
2564 0 : old_C1frequency = m_C1frequency;
2565 0 : old_C1vpp = m_C1vpp;
2566 0 : old_C1ofst = m_C1ofst;
2567 0 : old_C1phse = m_C1phse;
2568 0 : old_C1wdth = m_C1wdth;
2569 0 : old_C1wvtp = m_C1wvtp;
2570 0 : old_C1sync = m_C1sync;
2571 :
2572 0 : old_C2outp = m_C2outp;
2573 0 : old_C2frequency = m_C2frequency;
2574 0 : old_C2vpp = m_C2vpp;
2575 0 : old_C2ofst = m_C2ofst;
2576 0 : old_C2phse = m_C2phse;
2577 0 : old_C2wdth = m_C2wdth;
2578 0 : old_C2wvtp = m_C2wvtp;
2579 0 : old_C2sync = m_C2sync;
2580 : }
2581 :
2582 0 : return 0;
2583 : }
2584 :
2585 : } //namespace app
2586 : } //namespace MagAOX
2587 :
2588 : #endif //siglentSDG_hpp
|