15 #include "usermagnetps.h"
18 REGISTER_TYPE(
XDriverList, PS120,
"Oxford PS-120 magnet power supply");
19 REGISTER_TYPE(
XDriverList, IPS120,
"Oxford IPS-120 magnet power supply");
20 REGISTER_TYPE(
XDriverList, CryogenicSMS,
"Cryogenic SMS10/30/120C magnet power supply");
22 XPS120::XPS120(
const char *name,
bool runtime,
23 Transaction &tr_meas,
const shared_ptr<XMeasure> &meas) :
31 for(
int i = 0; i < 3; i++) {
33 interface()->query(
"X");
34 if(interface()->scanf(
"X%*2dA%1dC%*1dH%*1dM%*2dP%*2d", &ret) != 1)
37 interface()->sendf(
"A%u", val);
43 XPS120::toPersistent() {
46 interface()->send(
"A0");
57 interface()->query(
"X");
58 if(interface()->scanf(
"X%*2dA%1dC%*1dH%*1dM%*2dP%*2d", &ret) != 1)
70 XPS120::toNonPersistent() {
73 for(
int i = 0; i < 3; i++) {
76 interface()->query(
"X");
77 if(interface()->scanf(
"X%*2dA%*1dC%*1dH%*1dM%*1d%1dP%*2d", &ret) != 1)
83 i18n(
"Cannot enter non-persistent mode. Output is busy."), __FILE__, __LINE__);
91 XPS120::toSetPoint() {
95 interface()->query(
"X");
96 if(interface()->scanf(
"X%*2dA%1dC%*1dH%*1dM%*2dP%*2d", &ret) != 1)
108 XPS120::setPoint(
double field) {
109 for(
int i = 0; i < 2; i++) {
111 if(fabs(getTargetField() - field) < fieldResolution())
break;
113 interface()->sendf(
"P%d", ((field >= 0) ? 1 : 2));
114 df = lrint(fabs(field) / fieldResolution());
115 interface()->sendf(
"J%d", df);
119 XIPS120::setPoint(
double field) {
120 for(
int i = 0; i < 2; i++) {
121 if(fabs(getTargetField() - field) < fieldResolution())
break;
123 interface()->sendf(
"J%f", field);
128 XIPS120::getSweepRate() {
132 XPS120::getSweepRate() {
133 return read(9) * fieldResolution();
136 XIPS120::getTargetField() {
140 XPS120::getTargetField() {
142 interface()->query(
"X");
143 if(interface()->scanf(
"X%*2dA%*1dC%*1dH%*1dM%*2dP%1d%*1d", &ret) != 1)
145 return ((ret & 4) ? -1 : 1) * fabs(read(8) * fieldResolution());
148 XIPS120::getPersistentField() {
152 XPS120::getPersistentField() {
154 interface()->query(
"X");
155 if(interface()->scanf(
"X%*2dA%*1dC%*1dH%*1dM%*2dP%1d%*1d", &ret) != 1)
157 return ((ret & 2) ? -1 : 1) * fabs(read(18) * fieldResolution());
160 XIPS120::getOutputField() {
164 XPS120::getOutputField() {
166 interface()->query(
"X");
167 if(interface()->scanf(
"X%*2dA%*1dC%*1dH%*1dM%*2dP%1d%*1d", &ret) != 1)
169 return ((ret & 1) ? -1 : 1) * fabs(read(7) * fieldResolution());
172 XIPS120::getOutputVolt() {
176 XPS120::getOutputVolt() {
177 return read(1) * voltageResolution();
180 XIPS120::getOutputCurrent() {
184 XPS120::getOutputCurrent() {
186 interface()->query(
"X");
187 if(interface()->scanf(
"X%*2dA%*1dC%*1dH%*1dM%*2dP%1d%*1d", &ret) != 1)
189 return ((ret & 1) ? -1 : 1) * fabs(read(0) * currentResolution());
194 interface()->query(
"X");
195 if(interface()->scanf(
"X%*2dA%*1dC%*1dH%1dM%*2dP%*2d", &ret) != 1)
197 return (ret == 1) || (ret == 8) || (ret == 5);
202 interface()->query(
"X");
203 if(interface()->scanf(
"X%*2dA%*1dC%*1dH%1dM%*2dP%*2d", &ret) != 1)
209 interface()->sendf(
"H%u", (
unsigned int)(val ? 1 : 0));
213 i18n(
"Persistent Switch Heater not responding"), __FILE__, __LINE__);
216 XIPS120::setRate(
double hpm) {
217 for(
int i = 0; i < 2; i++) {
218 if(fabs(getSweepRate() - hpm) < fieldResolution())
break;
219 interface()->sendf(
"T%f", hpm);
225 XPS120::setRate(
double hpm) {
226 int ihpm = lrint(hpm / fieldResolution());
227 for(
int i = 0; i < 2; i++) {
228 if(fabs(getSweepRate() - hpm) < fieldResolution())
break;
229 interface()->sendf(
"T%d", ihpm);
236 interface()->send(
"$Q6");
240 XCryogenicSMS::XCryogenicSMS(
const char *name,
bool runtime,
241 Transaction &tr_meas,
const shared_ptr<XMeasure> &meas) :
244 interface()->setSerialFlushBeforeWrite(
false);
258 interface()->setEOS(
"\r\n");
262 XCryogenicSMS::receiveMessage(
const char *title,
bool is_stamp_required) {
264 interface()->receive();
265 bool has_stamp =
false;
266 const char *pbuf = &interface()->buffer()[0];
269 if(strncmp(pbuf,
"........", 8)) {
270 if( !strncmp(pbuf,
"------->", 8)) {
276 if(sscanf( pbuf,
"%*2d:%*2d:%2d", &ss) != 1)
280 auto cl_pos = std::find(interface()->buffer().begin() + 8, interface()->buffer().end(),
':');
281 if(cl_pos == interface()->buffer().end())
283 int cnt = cl_pos - interface()->buffer().begin();
286 if( !strncmp( pbuf + 9, title, strlen(title))) {
287 if(is_stamp_required && !has_stamp)
290 while(cl_pos != interface()->buffer().end()) {
302 interface()->send(
"SET TPA");
303 if(sscanf(receiveMessage(
"FIELD CONSTANT").c_str(),
"%lf", &m_tpa) != 1)
306 interface()->send(
"TESLA ON");
307 receiveMessage(
"UNITS");
312 XCryogenicSMS::changePauseState(
bool pause) {
315 interface()->send(
"PAUSE");
317 if(sscanf(receiveMessage(
"PAUSE STATUS").c_str(),
"%4s", buf) != 1)
319 if( !strncmp(
"ON", buf, 2)) {
322 interface()->send(
"PAUSE OFF");
323 receiveMessage(
"PAUSE STATUS",
true);
328 interface()->send(
"PAUSE ON");
329 receiveMessage(
"PAUSE STATUS",
true);
333 XCryogenicSMS::toPersistent() {
335 changePauseState(
true);
336 interface()->send(
"HEATER OFF");
337 receiveMessage(
"HEATER STATUS");
342 XCryogenicSMS::toNonPersistent() {
344 setRate(
Snapshot( *
this)[ *sweepRate()]);
345 changePauseState(
true);
346 interface()->send(
"HEATER ON");
347 receiveMessage(
"HEATER STATUS");
350 XCryogenicSMS::ramp(
const char *str) {
351 interface()->sendf(
"RAMP %s", str);
355 XCryogenicSMS::toZero() {
358 changePauseState(
false);
361 XCryogenicSMS::toSetPoint() {
364 changePauseState(
false);
367 XCryogenicSMS::changePolarity(
int p) {
368 for(
int tcnt = 0; tcnt < 3; ++tcnt) {
369 interface()->sendf(
"DIRECTION %c", (p > 0) ?
'+' :
'-');
371 interface()->sendf(
"GET OUTPUT");
373 if(sscanf(receiveMessage(
"OUTPUT").c_str(),
"%c", &c) != 1)
375 int x = (c !=
'-') ? 1 : -1;
382 XCryogenicSMS::setPoint(
double field) {
384 interface()->send(
"TESLA ON");
385 receiveMessage(
"UNITS");
387 double x = getOutputField();
389 if(fabs(x) < fieldResolution() * 10) {
394 if( !isOutputPositive())
398 else if(x * field < 0) {
402 interface()->sendf(
"SET MID %.5f", fabs(field));
403 if(sscanf(receiveMessage(
"MID SETTING",
true).c_str(),
"%lf", &x) != 1)
407 XCryogenicSMS::setRate(
double hpm) {
409 double amp_per_sec = hpm / 60.0 / teslaPerAmp();
410 interface()->sendf(
"SET RAMP %.5g", amp_per_sec);
412 if(sscanf(receiveMessage(
"RAMP RATE",
true).c_str(),
"%lf", &x) != 1)
416 XCryogenicSMS::isOutputPositive() {
418 interface()->send(
"GET OUTPUT");
420 if(sscanf(receiveMessage(
"OUTPUT").c_str(),
"%c", &c) != 1)
425 XCryogenicSMS::getTargetField() {
427 interface()->send(
"SET MID");
430 if(sscanf(receiveMessage(
"MID SETTING").c_str(),
"%lf %9s", &x, unit) != 2)
432 if(strncmp(unit,
"TESLA", 5))
434 return x * (isOutputPositive() ? 1 : -1);
437 XCryogenicSMS::getSweepRate() {
440 interface()->send(
"SET RATE");
441 if(sscanf(receiveMessage(
"RAMP RATE").c_str(),
"%lf", &x) != 1)
443 return x * teslaPerAmp() * 60.0;
446 XCryogenicSMS::getOutputField() {
448 interface()->send(
"GET OUTPUT");
451 if(sscanf(receiveMessage(
"OUTPUT").c_str(),
"%lf %9s", &x, unit) != 2)
453 if(strncmp(unit,
"TESLA", 5))
458 XCryogenicSMS::getPersistentField() {
460 interface()->send(
"HEATER");
461 std::string buf = receiveMessage(
"HEATER STATUS");
462 if( !strncmp(
"ON", buf.c_str(), 2))
464 if( !strncmp(
"OFF", buf.c_str(), 3))
468 if(sscanf(buf.c_str(),
"SWITCHED OFF AT %lf %9s", &x, unit) != 2)
470 if(strncmp(unit,
"TESLA", 5))
475 XCryogenicSMS::getOutputVolt() {
477 interface()->send(
"GET OUTPUT");
479 if(sscanf(receiveMessage(
"OUTPUT").c_str(),
"%*s %*s AT %lf", &x) != 1)
484 XCryogenicSMS::getOutputCurrent() {
486 double x = getOutputField();
488 return x / teslaPerAmp();
491 XCryogenicSMS::fieldResolution() {
492 return std::min(0.01, 0.15 * teslaPerAmp());
498 interface()->send(
"HEATER");
500 if(sscanf(receiveMessage(
"HEATER STATUS").c_str(),
"%5s", buf) != 1)
502 if( !strncmp(
"ON", buf, 2))
510 interface()->send(
"SET HEATER");
512 if(sscanf(receiveMessage(
"HEATER OUTPUT").c_str(),
"%lf", &x) != 1)