The VisAO Camera
VisAOJoeCtrl.cpp
Go to the documentation of this file.
1 /************************************************************
2 * VisAOJoeCtrl.cpp
3 *
4 * Author: Jared R. Males (jrmales@email.arizona.edu)
5 *
6 * Definitions for CCD47 control from the AO Supervisor.
7 *
8 * Developed as part of the Magellan Adaptive Optics system.
9 ************************************************************/
10 
11 /** \file VisAOJoeCtrl.cpp
12  * \author Jared R. Males
13  * \brief Definitions for CCD47 control from the AO Supervisor.
14  *
15  * Based on the Arcetri JoeCtrl class.
16  *
17 */
18 
19 
20 #include "VisAOJoeCtrl.h"
21 
22 
23 extern int debug;
24 //debug=0;
25 
26 
27 namespace VisAO
28 {
29 
30 #define JOE_ADDR_LEN 15 // Length of idrive string address
31 #define ERRMSG_LEN 32 // Length of an error message
32 
33 int cur_xbin, cur_ybin, cur_speed;
34 int default_xbin, default_ybin, default_speed, default_black;
35 
36 JoeCtrl::JoeCtrl( std::string name, const std::string &conffile) throw (AOException) : AOApp(name, conffile)
37 {
38  Create();
39 }
40 
41 JoeCtrl::JoeCtrl( int argc, char **argv) throw (AOException) : AOApp( argc, argv)
42 {
43  std::cout << "Starting" << std::endl;
44  Create();
45 }
46 
47 void JoeCtrl::Create() throw (AOException)
48 {
49 
50  try
51  {
52  _ccdName = (std::string) ConfigDictionary()["ccdName"];
53  //_ccdNetAddr = (std::string) ConfigDictionary()["ccdNetAddr"];
54  //_ccdNetPort = ConfigDictionary()["ccdNetPort"];
55  _ccdDx = ConfigDictionary()["ccdXdim"];
56  _ccdDy = ConfigDictionary()["ccdYdim"];
57  _ccdDefaultXbin = ConfigDictionary()["ccdDefaultXbin"];
58  _ccdDefaultYbin = ConfigDictionary()["ccdDefaultYbin"];
59  _ccdDefaultSpeed = ConfigDictionary()["ccdDefaultSpeed"];
60  _ccdDefaultBlack = ConfigDictionary()["ccdDefaultBlack"];
61  _ccdBlacksNum = ConfigDictionary()["ccdBlacksNum"];
62  _minRep = ConfigDictionary()["minRep"];
63  _maxRep = ConfigDictionary()["maxRep"];
64  _maxNumSpeeds = ConfigDictionary()["maxNumSpeeds"];
65  _maxNumBins = ConfigDictionary()["maxNumBins"];
66  _maxNumWins = ConfigDictionary()["maxNumWins"];
67  //_filePrefix = (std::string) ConfigDictionary()["filePrefix"];
68  _startProgramSet = ConfigDictionary()["startProgramSet"];
69  _fanCtrlActive = ConfigDictionary()["fanCtrlActive"];
70 
71  wait_to = ConfigDictionary()["wait_to"];
72  if (_fanCtrlActive)
73  {
74  _fanOnTemp = ConfigDictionary()["fanOnTemp"];
75  _fanOffTemp = ConfigDictionary()["fanOffTemp"];
76  }
77  }
78  catch (Config_File_Exception &e)
79  {
80  _logger->log( Logger::LOG_LEV_FATAL, "%s", e.what().c_str());
81  throw AOException("Fatal: Missing configuration data");
82  }
83 
84  _ccdBlacks.resize( _ccdBlacksNum);
85 
86  //_tempsLogger = Logger::get( _ccdName+"Temperature", Logger::LOG_LEV_INFO, "TELEMETRY");
87 
88  // Create the specific LittleJoe arrays
89  LoadJoeDiskFiles();
90  EraseLocalMemory();
91 
92  setup_fifo_list(1);
93 
94  std::string ccd47_fifo_in = "/home/aosup/visao/fifos/ccd47ctrl_com_remote_in";
95  std::string ccd47_fifo_out = "/home/aosup/visao/fifos/ccd47ctrl_com_remote_out";
96 
97  set_fifo_list_channel(&fl, 0, RWBUFF_SZ, ccd47_fifo_out.c_str(), ccd47_fifo_in.c_str(), 0, 0);
98 
99  signal(SIGIO, SIG_IGN);
101 
102  global_fifo_list = &fl;
103 
104 
105 }
106 
107 
109 {
110  // ----------- Initial status
111  setCurState(STATE_NOCONNECTION);
112  var_errmsg.Set("Starting up");
113 }
114 
116 {
117  try
118  {
119  var_name = RTDBvar( MyFullName(), "NAME", NO_DIR, CHAR_VARIABLE, _ccdName.size()+1);
120  var_name.Set(_ccdName);
121 
122 
123  var_enable_req = RTDBvar( MyFullName(), "ENABLE", REQ_VAR);
124  var_enable_cur = RTDBvar( MyFullName(), "ENABLE", CUR_VAR);
125 
126  var_enable_cur.Set(0);
127 
128  var_errmsg = RTDBvar( MyFullName(), "ERRMSG", NO_DIR, CHAR_VARIABLE, ERRMSG_LEN);
129 
130  var_dx = RTDBvar( MyFullName(), "DX");
131  var_dx_cur = RTDBvar( MyFullName(), "DX", CUR_VAR);
132  var_dx_req = RTDBvar( MyFullName(), "DX", REQ_VAR);
133  var_dy = RTDBvar( MyFullName(), "DY");
134  var_dy_cur = RTDBvar( MyFullName(), "DY", CUR_VAR);
135  var_dy_req = RTDBvar( MyFullName(), "DY", REQ_VAR);
136  var_windowxs = RTDBvar( MyFullName(), "WINDOWXS", NO_DIR, INT_VARIABLE, _maxNumWins);
137  var_windowys = RTDBvar( MyFullName(), "WINDOWYS", NO_DIR, INT_VARIABLE, _maxNumWins);
138 
139  var_xbins = RTDBvar( MyFullName(), "XBINS", NO_DIR, INT_VARIABLE, _maxNumBins);
140  var_ybins = RTDBvar( MyFullName(), "YBINS", NO_DIR, INT_VARIABLE, _maxNumBins);
141  var_speeds = RTDBvar( MyFullName(), "SPEEDS", NO_DIR, INT_VARIABLE, _maxNumSpeeds);
142 
143  var_xbin_req = RTDBvar( MyFullName(), "XBIN", REQ_VAR);
144  var_ybin_req = RTDBvar( MyFullName(), "YBIN", REQ_VAR);
145  var_xbin_cur = RTDBvar( MyFullName(), "XBIN", CUR_VAR);
146  var_ybin_cur = RTDBvar( MyFullName(), "YBIN", CUR_VAR);
147 
148  var_speed_cur = RTDBvar( MyFullName(), "SPEED", CUR_VAR);
149  var_speed_req = RTDBvar( MyFullName(), "SPEED", REQ_VAR);
150 
151  var_black_cur = RTDBvar( MyFullName(), "BLACK", CUR_VAR, INT_VARIABLE, _ccdBlacks.size());
152  var_black_req = RTDBvar( MyFullName(), "BLACK", REQ_VAR, INT_VARIABLE, _ccdBlacks.size());
153 
154  var_framerate_cur = RTDBvar( MyFullName(), "FRMRT", CUR_VAR, REAL_VARIABLE);
155  var_framerate_req = RTDBvar( MyFullName(), "FRMRT", REQ_VAR, REAL_VARIABLE);
156 
157  var_rep_cur = RTDBvar( MyFullName(), "REP", CUR_VAR);
158  var_rep_req = RTDBvar( MyFullName(), "REP", REQ_VAR);
159 
160  var_gain_cur = RTDBvar( MyFullName(), "GAIN", CUR_VAR, INT_VARIABLE);
161  var_gain_req = RTDBvar( MyFullName(), "GAIN", REQ_VAR, INT_VARIABLE);
162 
163  var_temps = RTDBvar( MyFullName(), "TEMPS", NO_DIR, INT_VARIABLE, 3);
164 
165  var_fanReq = RTDBvar( (std::string)ConfigDictionary()["fanReqVar"], INT_VARIABLE, 1, false);
166 
167  var_dx.Set( _ccdDx);
168  var_dy.Set( _ccdDy);
169  var_dx_cur.Set( _ccdDx);
170  var_dy_cur.Set( _ccdDy);
171 
172  // Fill the XBINS and YBINS array up to the maximum length
173  unsigned i;
174  vector<int> binning;
175  for ( i=0; i < _ccdXbins.size(); i++)
176  if(_ccdXbins[i] > 0) binning.push_back( _ccdXbins[i]);
177  for ( i = _ccdXbins.size(); i< (unsigned) _maxNumBins; i++)
178  binning.push_back(-1);
179  var_xbins.Set( binning);
180 
181  binning.clear();
182  for ( i=0; i < _ccdYbins.size(); i++)
183  if(_ccdYbins[i] > 0) binning.push_back( _ccdYbins[i]);
184  for ( i = _ccdYbins.size(); i< (unsigned)_maxNumBins; i++)
185  binning.push_back(-1);
186 
187  var_ybins.Set( binning);
188 
189  Notify( var_enable_req, EnableReqChanged);
190  Notify( var_xbin_req, XbinReqChanged);
191  Notify( var_ybin_req, YbinReqChanged);
192  Notify( var_speed_req, SpeedReqChanged);
193  Notify( var_black_req, BlackReqChanged);
194  Notify( var_framerate_req, FrameRateReqChanged);
195  Notify( var_rep_req, RepReqChanged);
196  Notify( var_gain_req, GainReqChanged);
197 
198  setCurState(STATE_NOCONNECTION);
199 
200  var_cmode_cur = RTDBvar( MyFullName(), "ConMode", CUR_VAR, INT_VARIABLE, 1,1);
201  var_cmode_req = RTDBvar( MyFullName(), "ConMode", REQ_VAR, INT_VARIABLE, 1,1);
202 
203  Notify( var_cmode_req, CModeReqChanged);
204 
205  var_preset_req = RTDBvar( MyFullName(), "Preset", REQ_VAR, INT_VARIABLE, 1,1);
207 
208  }
209  catch (AOVarException &e)
210  {
211  _logger->log(Logger::LOG_LEV_FATAL, "%s:%d: %s", __FILE__, __LINE__, e.what().c_str());
212  throw AOException("Error creating RTDB variables");
213  }
214 
215 
216 }
217 
218 void JoeCtrl::StateChange( int oldstate, int state)
219 {
220  if ((state == STATE_NOCONNECTION) && (oldstate != STATE_NOCONNECTION))
221  {
222  var_enable_cur.Set( 0,0, FORCE_SEND);
223  var_xbin_cur.Set( 0, 0, FORCE_SEND);
224  var_ybin_cur.Set( 0, 0, FORCE_SEND);
225  var_speed_cur.Set( 0, 0, FORCE_SEND);
226  //var_framerate_cur.Set( 0, 0, FORCE_SEND);
227  var_rep_cur.Set( 0, 0, FORCE_SEND);
228 
229  for (unsigned int i=0; i< _ccdBlacks.size(); i++)
230  var_black_cur.Set( 0, i, NO_SEND);
231  var_black_cur.Send();
232  }
233 }
234 
236 {
237  while(!TimeToDie())
238  {
239  try
240  {
241  // Do iterative step of the controller
242 
243  DoFSM();
244 
245  // Read temperatures every now and then
246  //if (iterations++ % 5 == 0)
247  // ReadJoeTemps();
248  }
249  catch (AOException &e)
250  {
251  _logger->log( Logger::LOG_LEV_ERROR, "Caught exception: %s", e.what().c_str());
252  }
253  }
254  exit(0);
255 }
256 
257 int JoeCtrl::DoFSM(void)
258 {
259  int status;
260  int stat = NO_ERROR;
261 
262  status = getCurState();
263 
264  if (TestCCD47CtrlLink() != NO_ERROR)
265  {
266  //setCurState(STATE_NOCONNECTION);
267  EraseLocalMemory();
268  }
269 
270  status = getCurState();
271 
272  switch(status)
273  {
274  // At first, try to start network
275  case STATE_NOCONNECTION:
276  msleep(1000);
277  break;
278 
279  // After network start, configure LittleJoe
280  // Configuration ensures at the end that LittleJoe is turned off
281  // When ready to go, do nothing
282  case STATE_CONNECTED:
283  case STATE_OFF:
284  case STATE_CONFIGURING:
285  case STATE_READY:
286  case STATE_OPERATING:
287  msleep(1000);
288  break;
289 
290  // Unknown states should not exist
291  default:
292  msleep(1000);
293  break;
294  }
295 
296  // Always set state again (for watchdogs)
297  setCurState(getCurState());
298 
299  // Return the generated error code, if any
300  return stat;
301 }
302 
303 
304 
305 
307 {
308  try
309  {
310  //std::cout << "Testing CCD47 Link\n";
311  std::string resp = send_ccd47_command("state?");
312 
313  //std::cout << "Got: " << resp << "\n";
314 
315  if(resp == "")
316  {
317  setCurState(STATE_NOCONNECTION);
318  //Ok, we timed out. So flush the fifo channel
319  sleep(1);
321  return -1;
322  }
323 
324  int cmode;
325 
326  switch(resp[0])
327  {
328  case 'N':
329  cmode = 0;
330  break;
331  case 'R':
332  cmode = 1;
333  break;
334  case 'L':
335  cmode = 2;
336  break;
337  case 'S':
338  cmode = 3;
339  break;
340  case 'A':
341  cmode = 4;
342  break;
343  default:
344  cmode = -1;
345  //We got garbage, try flushing the fifo channel.
346  sleep(1);
348  break;
349  }
350  var_cmode_cur.Set(cmode, 0, CHECK_SEND);
351 
352  if(cmode == -1)
353  {
354  setCurState(STATE_NOCONNECTION);
355  return -1;
356  }
357 
358  if(resp[2] == '3')
359  {
360  setCurState(STATE_CONFIGURING);
361  return NO_ERROR;
362  }
363 
364  if(resp[2] == '0')
365  {
366  setCurState(STATE_NOCONNECTION);
367  return NO_ERROR;
368  }
369 
370  if(resp[2] == '1')
371  {
372  setCurState(STATE_READY);
373  var_enable_cur.Set(0, 0, CHECK_SEND);
374  }
375 
376  if(resp[2] == '2')
377  {
378  setCurState(STATE_OPERATING);
379  var_enable_cur.Set(1, 0, CHECK_SEND);
380  }
381 
382  //If connected get the speed.
383  write_fifo_channel(0, "set?\n", 5, &resp);
384  if(resp == "" || resp.length() < 1)
385  {
386  setCurState(STATE_NOCONNECTION);
387  return -1;
388  }
389  int program_set = cur_ProgramSet;
390  cur_ProgramSet = atoi(resp.c_str());
391  if(program_set != cur_ProgramSet) UpdateJoeMemory(cur_ProgramSet);
392 
393  write_fifo_channel(0, "prog?\n", 7, &resp);
394 
395  if(resp == "" || resp.length() < 1)
396  {
397  setCurState(STATE_NOCONNECTION);
398  return -1;
399  }
400  cur_Program = atoi(resp.c_str());
401 
402  write_fifo_channel(0, "speed?\n", 8, &resp);
403  if(resp == "" || resp.length() < 1)
404  {
405  setCurState(STATE_NOCONNECTION);
406  return -1;
407  }
408  int speed;
409  speed = atoi(resp.c_str());
410  var_speed_cur.Set(speed, 0, CHECK_SEND);
411 
412  write_fifo_channel(0, "xbin?\n", 7, &resp);
413  if(resp == "" || resp.length() < 1)
414  {
415  setCurState(STATE_NOCONNECTION);
416  return -1;
417  }
418  int xbin = atoi(resp.c_str());
419  var_xbin_cur.Set(xbin, 0, CHECK_SEND);
420 
421  write_fifo_channel(0, "ybin?\n", 7, &resp);
422  if(resp == "" || resp.length() < 1)
423  {
424  setCurState(STATE_NOCONNECTION);
425  return -1;
426  }
427  int ybin = atoi(resp.c_str());
428  var_ybin_cur.Set(ybin, 0, CHECK_SEND);
429 
430  write_fifo_channel(0, "windowx?\n", 9, &resp);
431  if(resp == "" || resp.length() < 1)
432  {
433  setCurState(STATE_NOCONNECTION);
434  return -1;
435  }
436  int xwin = atoi(resp.c_str());
437  var_dx.Set(xwin, 0, CHECK_SEND);
438  var_dx_cur.Set(xwin, 0, CHECK_SEND);
439 
440  write_fifo_channel(0, "windowy?\n", 9, &resp);
441  if(resp == "" || resp.length() < 1)
442  {
443  setCurState(STATE_NOCONNECTION);
444  return -1;
445  }
446  int ywin = atoi(resp.c_str());
447  var_dy.Set(ywin,0,CHECK_SEND);
448  var_dy_cur.Set(ywin, 0, CHECK_SEND);
449 
450  write_fifo_channel(0, "rep?\n", 6, &resp);
451  if(resp == "" || resp.length() < 1)
452  {
453  setCurState(STATE_NOCONNECTION);
454  return -1;
455  }
456  int reps = atoi(resp.c_str());
457  var_rep_cur.Set(reps, 0, CHECK_SEND);
458 
459  write_fifo_channel(0, "gain?\n", 7, &resp);
460  if(resp == "" || resp.length() < 1)
461  {
462  setCurState(STATE_NOCONNECTION);
463  return -1;
464  }
465  int gain = atoi(resp.c_str());
466  var_gain_cur.Set(gain, 0, CHECK_SEND);
467 
468  ExposeSpeeds();
469  ExposeWindows();
470  ComputeFramerate();
471 
472  //If connected, get temperatures
473  int temps[3];
474  double t1, t2, t3;
475 
476  write_fifo_channel(0, "temps?\n", 8, &resp);
477  if(resp == "" || resp.length() < 19)
478  {
479  setCurState(STATE_NOCONNECTION);
480  return -1;
481  }
482  t1 = strtod(resp.substr(0,6).c_str(),0);
483  t2 = strtod(resp.substr(7,6).c_str(),0);
484  t3 = strtod(resp.substr(14,6).c_str(),0);
485 
486  temps[0] = (int) t1;
487  temps[1] = (int) t2;
488  temps[2] = (int) t3;
489 
490  var_temps.Set(temps, CHECK_SEND);
491 
492  write_fifo_channel(0, "blacks?\n", 8, &resp);
493  if(resp == "" || resp.length() < 9)
494  {
495  std::cout << resp << "\n";
496  setCurState(STATE_NOCONNECTION);
497  return -1;
498  }
499  int blacks[2];
500  //std::cout << "resp:" << resp << "|\n";
501  blacks[0] = atoi(resp.substr(0,4).c_str());
502  //std::cout << "1\n";
503  blacks[1] = atoi(resp.substr(5,4).c_str());
504  var_black_cur.Set(blacks, CHECK_SEND);
505 
506  // Fan management
507  if (_fanCtrlActive)
508  {
509  if (t1< _fanOffTemp)
510  {
511  var_fanReq.Set(0, 0, CHECK_SEND);
512  }
513  if (t1> _fanOnTemp)
514  {
515  var_fanReq.Set(1, 0, CHECK_SEND);
516  }
517  }
518  return NO_ERROR;
519  }
520  catch(...)
521  {
522  setCurState(STATE_NOCONNECTION);
523  return -1;
524  }
525 }
526 
528 {
529  std::string resp;
530 
531  if(write_fifo_channel(0, "stop", 5, &resp) < 0)
532  {
533  ERROR_REPORT("Error sending stop command to CCD47Ctrl");
534  return -1;
535  }
536  return 0;
537 
538 }
539 
541 {
542  std::string resp;
543 
544  if(write_fifo_channel(0, "start", 6, &resp) < 0)
545  {
546  ERROR_REPORT("Error sending start command to CCD47Ctrl");
547  return -1;
548  }
549  return 0;
550 
551 }
552 
553 int JoeCtrl::EnableReqChanged( void *pt, Variable *var)
554 {
555  int enable, enabled, stat;
556  JoeCtrl *ctrl = (JoeCtrl *)pt;
557 
558  #ifdef _debug
559  std::cerr << "EnableReqChanged" << std::endl;
560  #endif
561 
562  stat = NO_ERROR;
563  enable = var->Value.Lv[0];
564  ctrl->var_enable_req.Set(enable, 0, NO_SEND); // Mirror value locally
565  ctrl->var_enable_cur.Get(&enabled); // Current value
566 
567  // Ignore invalid values
568  if ((enable != 0) && (enable != 1))
569  return NO_ERROR;
570 
571  // Switch on if requested
572  if ((enable == 1) && (enabled == 0))
573  stat = ctrl->Start();
574 
575  // Switch off if requested
576  if ((enable == 0) && (enabled == 1))
577  stat = ctrl->Stop();
578 
579  //if (stat == NO_ERROR)
580  //ctrl->var_enable_cur.Set(enable);
581  return stat;
582 }
583 
584 int JoeCtrl::XbinReqChanged( void *pt, Variable *var)
585 {
586  #ifdef _debug
587  std::cerr << "XbinReqChanged" << std::endl;
588  #endif
589  JoeCtrl *ctrl = (JoeCtrl *)pt;
590  ctrl->var_xbin_req.Set( var->Value.Lv[0], 0, NO_SEND);
591  return ctrl->ReprogramJoe();
592 }
593 
594 int JoeCtrl::YbinReqChanged( void *pt, Variable *var)
595 {
596  #ifdef _debug
597  std::cerr << "YbinReqChanged" << std::endl;
598  #endif
599  JoeCtrl *ctrl = (JoeCtrl *)pt;
600  ctrl->var_ybin_req.Set( var->Value.Lv[0], 0, NO_SEND);
601  return ctrl->ReprogramJoe();
602 }
603 
604 int JoeCtrl::SpeedReqChanged( void *pt, Variable *var)
605 {
606  #ifdef _debug
607  std::cerr << "SpeedReqChanged" << std::endl;
608  #endif
609  JoeCtrl *ctrl = (JoeCtrl *)pt;
610  ctrl->var_speed_req.Set( var->Value.Lv[0], 0, NO_SEND);
611  return ctrl->ReprogramJoe();
612 }
613 
614  // --------------------------------------
615  // Black levels (CCDnBLACKS variable)
616  //
617 
618 int JoeCtrl::BlackReqChanged( void *pt, Variable *var)
619 {
620  #ifdef _debug
621  std::cerr << "BlackReqChanged" << std::endl;
622  #endif
623 
624  int black,cur_black,stat;
625  JoeCtrl *ctrl = (JoeCtrl *)pt;
626  unsigned int i;
627  char cmstr[50];
628  // Set the new black levels, if different from the current ones
629  for (i=0; i< ctrl->_ccdBlacks.size(); i++)
630  {
631  black = var->Value.Lv[i];
632  ctrl->var_black_cur.Get(i, &cur_black);
633 
634  Logger::get()->log( Logger::LOG_LEV_DEBUG, "Setting black level %d to %d", i, black);
635  if (black != cur_black)
636  {
637  snprintf(cmstr, 50, "black %d %d", i, black);
638  std::cout << cmstr << "\n";
639  ctrl->send_ccd47_command(cmstr);
640  sleep(1);
641 
642  }
643  //ctrl->var_black_cur.Set( black, (int)i,FORCE_SEND);
644  }
645 
646  var = 0;
647  return NO_ERROR;
648 }
649 
650 int JoeCtrl::RepReqChanged( void *pt, Variable *var)
651 {
652 
653  #ifdef _debug
654  std::cerr << "RepReqChanged" << std::endl;
655  #endif
656 
657  int stat;
658  JoeCtrl *ctrl = (JoeCtrl *)pt;
659  int rep = var->Value.Lv[0];
660 
661  if ((rep>= ctrl->_minRep) && (rep<= ctrl->_maxRep))
662  {
663  stat = 0;
664  char cmstr[50];
665  snprintf(cmstr, 50, "set %i %i %i %i", ctrl->cur_ProgramSet, ctrl->cur_Program, ctrl->cur_Gain, rep);
666  std::cout << cmstr << "\n";
667  ctrl->send_ccd47_command(cmstr);
668  sleep(1);
669 
670  return stat;
671  }
672  else return JOE_OUT_OF_RANGE_ERROR;
673 
674 }
675 
676 int JoeCtrl::GainReqChanged( void *pt, Variable *var)
677 {
678 
679  #ifdef _debug
680  std::cerr << "GainReqChanged" << std::endl;
681  #endif
682 
683  int stat;
684  JoeCtrl *ctrl = (JoeCtrl *)pt;
685  int gain = var->Value.Lv[0];
686 
687  if ((gain>= 0) && (gain<= 3))
688  {
689  stat = 0;
690  char cmstr[50];
691  snprintf(cmstr, 50, "set %i %i %i %i", ctrl->cur_ProgramSet, ctrl->cur_Program, gain, ctrl->cur_Reps);
692  std::cout << cmstr << "\n";
693  ctrl->send_ccd47_command(cmstr);
694  sleep(1);
695 
696  return stat;
697  }
698  else return JOE_OUT_OF_RANGE_ERROR;
699 
700 }
701 
702 
703 int JoeCtrl::CModeReqChanged(void *pt, Variable *msgb)
704 {
705  std::string rstr;
706  int stat, newstate;
707 
708  #ifdef _debug
709  std::cerr << "CModeReqChanged" << std::endl;
710  #endif
711  JoeCtrl * jc = (JoeCtrl *) pt;
712 
713  /*** Don't lock threadMutex here, it is done in request_control ****/
714 
715  newstate = msgb->Value.Lv[0];
716  //std::cout << newstate << "\n";
717 
718  if(newstate == 1) rstr = jc->send_ccd47_command("REMOTE");
719  if(newstate == 10) rstr = jc->send_ccd47_command("XREMOTE");
720  if(newstate == 0) rstr = jc->send_ccd47_command("~REMOTE");
721 
722  if(rstr == "") stat = -1;
723  else stat = 0;
724 
725  return stat;
726 }
727 
728 int JoeCtrl::PresetReqChanged(void *pt, Variable *msgb)
729 {
730  std::string rstr;
731  int stat, newstate;
732 
733 #ifdef _debug
734  std::cerr << "PresetReqChanged" << std::endl;
735 #endif
736  JoeCtrl * jc = (JoeCtrl *) pt;
737 
738  /*** Don't lock threadMutex here, it is done in request_control ****/
739 
740  //newstate = msgb->Value.Lv[0];
741  //std::cout << newstate << "\n";
742 
743  rstr = jc->send_ccd47_command("set 0 0 0 0");
744  rstr = jc->send_ccd47_command("serve 1");
745 // if(newstate == 10) rstr = jc->send_ccd47_command("XREMOTE");
746 // if(newstate == 0) rstr = jc->send_ccd47_command("~REMOTE");
747 
748  if(rstr == "") stat = -1;
749  else stat = 0;
750 
751  return stat;
752 }
753 
754 std::string JoeCtrl::send_ccd47_command(std::string com)
755 {
756  std::string resp;
757  if(write_fifo_channel(0, com.c_str(), com.length()+1, &resp) < 0)
758  {
759  ERROR_REPORT("Error sending command to CCD47");
760  }
761  return resp;
762 }
763 
764 
765 int JoeCtrl::FrameRateReqChanged( void *pt, Variable *var)
766 {
767  #ifdef _debug
768  std::cerr << "FrameRateReqChanged" << std::endl;
769  #endif
770 
771  JoeCtrl *ctrl = (JoeCtrl *)pt;
772  return ctrl->ChangeFramerate( var->Value.Dv[0], 0);
773 }
774 
775 //+Function: ChangeFramerate
776 //
777 // Changes the framerate selecting the most convenient readout speed
778 // and repetition number, without changing the binning.
779 // Updates the CURSPEED, CURREP e CURFRMRT variables.
780 // Can be called at any time.
781 //
782 // If bestspeed is set, it will search for the most convenient readout. Otherwise,
783 // the readout is not changed.
784 //-
785 
786 int JoeCtrl::ChangeFramerate( double framerate, int bestspeed)
787 {
788  int xbin, ybin, cur_speed, cur_winx, cur_winy;
789  int found_speed=-1;
790  int found_set=-1;
791  int found_program=-1;
792  unsigned int i,j;
793 
794  // Safety check (avoid division by zero and nonsensical framerates)
795  if (framerate <=0)
796  return VALUE_OUT_OF_RANGE_ERROR;
797 
798  var_xbin_cur.Get(&xbin);
799  var_ybin_cur.Get(&ybin);
800  var_speed_cur.Get(&cur_speed);
801  var_dx_cur.Get(&cur_winx);
802  var_dy_cur.Get(&cur_winy);
803 
804  _logger->log( Logger::LOG_LEV_DEBUG, "Requested frequency: %5.2f", framerate);
805 
806  for (i=0; i<ondisk.size(); i++)
807  for (j=0; j< ondisk[i].programs.size(); j++)
808  {
809  // Skip programs with the wrong binning or window
810  if ((xbin != ondisk[i].programs[j].binx) ||
811  (ybin != ondisk[i].programs[j].biny) ||
812  (ondisk[i].programs[j].windowx != cur_winx) ||
813  (ondisk[i].programs[j].windowx != cur_winy))
814  continue;
815 
816  // Delays are in microseconds
817  double mintime = ondisk[i].programs[j].delay_base;
818  double maxtime = mintime + ondisk[i].programs[j].delay_inc * 65535;
819 
820  double max_framerate = 1e6/mintime;
821  double min_framerate = 1e6/maxtime;
822 
823  _logger->log( Logger::LOG_LEV_DEBUG, "Program %d %d: max,min = %5.2f, %5.2f", i, j, max_framerate, min_framerate);
824 
825 
826  // Skip programs not able to reach the desired framerate
827  if (bestspeed)
828  if ((framerate < min_framerate) || (framerate > max_framerate))
829  continue;
830 
831  int readout_speed = ondisk[i].programs[j].readout_speed;
832 
833  // Skip programs with a different readout speed from our one (if bestspeed is not set)
834  if ((!bestspeed) && (readout_speed != cur_speed))
835  continue;
836 
837  // Skip programs with a readout speed equal or bigger than the one already found
838  if (found_program>=0)
839  if ( readout_speed >= ondisk[found_set].programs[found_program].readout_speed)
840  continue;
841 
842  // Program passed all tests
843  found_set = i;
844  found_program = j;
845  found_speed = readout_speed;
846 
847  _logger->log( Logger::LOG_LEV_DEBUG, "Found program: %d %d %d", found_set, found_program, found_speed);
848  }
849 
850  // See if we have found one
851  if (found_program <0)
852  return VALUE_OUT_OF_RANGE_ERROR;
853 
854  // Calculate new repetition number
855  double base = ondisk[found_set].programs[found_program].delay_base;
856  double inc = ondisk[found_set].programs[found_program].delay_inc;
857  double goal = 1e6/framerate;
858 
859  goal = goal - base;
860  goal = goal / inc;
861 
862  // May happen if the requested speed is not able to go so fast...
863  if (goal<0)
864  goal=0;
865 
866  // Apply new settings (will call the appropriate handlers in order...)
867  //var_speed_req.Set(found_speed, 0, CHECK_SEND);
868  //var_rep_req.Set((int)goal, 0, CHECK_SEND);
869 
870  _logger->log( Logger::LOG_LEV_DEBUG, "Base %5.2f, inc %5.2f, goal %5.2f", base, inc, goal);
871  _logger->log( Logger::LOG_LEV_DEBUG, "Setting speed %d, repetitions %d", found_speed, (int)goal);
872 
873  char cmstr[50];
874  snprintf(cmstr, 50, "set %i %i %i %i", found_set, found_program, cur_Gain, (int) goal);
875 
876  std::cout << cmstr << "\n";
877  send_ccd47_command(cmstr);
878  sleep(1);
879 
880  return NO_ERROR;
881 }
882 
883 
884 //+Function: ComputeFramerate
885 //
886 // Computes the current framerate from the current state of LittleJoe control variables.
887 // Refreshes the MsgD-RTDB CCDnCURFRMRT variable.
888 //-
889 
890 int JoeCtrl::ComputeFramerate()
891 {
892  std::string resp;
893 
894  write_fifo_channel(0, "framerate?\n", 12, &resp);
895 
896  if(resp == "" || resp.length() < 1)
897  {
898  setCurState(STATE_NOCONNECTION);
899  return -1;
900  }
901  double framerate = strtod(resp.c_str(), 0);
902  var_framerate_cur.Set(framerate, 0, CHECK_SEND);
903  return NO_ERROR;
904 }
905 
906 //+Entry: ExposeSpeeds
907 //
908 // Fills the CCDxxSPEEDS variable with each possible
909 // speed of the current binning, as available in the current programset
910 
911 int JoeCtrl::ExposeSpeeds()
912 {
913  int xbin, ybin;
914  unsigned int i;
915 
916  var_xbin_cur.Get(&xbin);
917  var_ybin_cur.Get(&ybin);
918 
919  int *speeds = new int[ _maxNumSpeeds];
920  memset( speeds, 0, sizeof(int) * _maxNumSpeeds);
921 
922  int counter=0;
923  for (i=0; i< memory.programs.size(); i++)
924  {
925  //_logger->log( Logger::LOG_LEV_DEBUG, "Checking program %dx%d, %d kpixel/sec", memory.programs[i].binx, memory.programs[i].biny, memory.programs[i].readout_speed);
926  if ((memory.programs[i].binx == xbin) &&
927  (memory.programs[i].biny == ybin) &&
928  (memory.programs[i].windowx == 1024) &&
929  (memory.programs[i].windowy == 1024))
930  speeds[ counter++ ] = memory.programs[i].readout_speed;
931  }
932 
933  var_speeds.Set(speeds);
934 
935  delete speeds;
936  return NO_ERROR;
937 }
938 
939  //+Entry: ExposeWindows
940 //
941 // Fills the CCDxxWINDOWS variable with each possible
942 // window of the current binning, as available in the current programset
943 
944 int JoeCtrl::ExposeWindows()
945 {
946  int xbin, ybin;
947  unsigned int i;
948 
949  var_xbin_cur.Get(&xbin);
950  var_ybin_cur.Get(&ybin);
951 
952  int *winxs = new int[ _maxNumWins];
953  int *winys = new int[ _maxNumWins];
954  memset( winxs, 0, sizeof(int) * _maxNumWins);
955  memset( winys, 0, sizeof(int) * _maxNumWins);
956 
957  int counter=0;
958  int found;
959  for (i=0; i< memory.programs.size(); i++)
960  {
961  if ((memory.programs[i].binx == xbin) && (memory.programs[i].biny == ybin) )
962  {
963  found=0;
964  for(int j=0; j< counter; j++)
965  {
966 
967  if(winxs[j] == memory.programs[i].windowx && winys[j] == memory.programs[i].windowy) found = 1;
968  }
969  if(!found)
970  {
971  winxs[ counter ] = memory.programs[i].windowx;
972  winys[ counter ] = memory.programs[i].windowy;
973  }
974  counter++;
975  }
976  }
977 
978  var_windowxs.Set(winxs);
979  var_windowys.Set(winys);
980  delete winxs;
981  delete winys;
982 
983  return NO_ERROR;
984 }
985 //+Entry: ReprogramJoe
986 //
987 // This function switches between the different LittleJoe programs (waveforms)
988 //
989 // If the requested parameters are not valid, it fails silently
990 //
991 // Watch out: this routine calls itself recursively when an upload if needed. Always take this
992 // into consideration with changing something.
993 //
994 // LittleJoe can only be reprogrammed in the SWITCHEDOFF state. If a request is made when
995 // not in this state it will be refused, unless the <force> flag is nonzero. In this case
996 // the routine will attempt to reprogram the LittleJoe anyway (this is necessary, for example,
997 // for the first configuration)
998 //-
999 
1000 int JoeCtrl::ReprogramJoe( int force)
1001 {
1002  int need_upload;
1003  int speed;
1004  int xbin;
1005  int ybin;
1006  int reps;
1007  int pos;
1008  int cur_speed;
1009  int cur_xbin;
1010  int cur_ybin;
1011 
1012  //unsigned int i;
1013  char cmstr[50];
1014 
1015  var_speed_req.Get(&speed);
1016  var_xbin_req.Get(&xbin);
1017  var_ybin_req.Get(&ybin);
1018  var_rep_req.Get(&reps);
1019 
1020  var_speed_cur.Get(&cur_speed);
1021  var_xbin_cur.Get(&cur_xbin);
1022  var_ybin_cur.Get(&cur_ybin);
1023 
1024  var_rep_cur.Get(&cur_Reps);
1025 
1026  // Nothing to do?
1027  if ((speed == cur_speed) && (xbin == cur_xbin) && (ybin == cur_ybin) && (reps==cur_Reps))
1028  {
1029  _logger->log( Logger::LOG_LEV_INFO, "SetJoeProgram(): current settings are OK, nothing to do.");
1030  return NO_ERROR;
1031  }
1032 
1033 
1034 /* // Stop ccd integration
1035  stat = Stop();
1036  if (stat != NO_ERROR)
1037  return stat;
1038 */
1039  _logger->log( Logger::LOG_LEV_DEBUG, "Checking program %d, %dx%d", speed, xbin, ybin);
1040 
1041  // See if we already have the program in memory, or if we have to upload it
1042  // For the VisAO version, this really just means updating memory from ondisk
1043  pos = GetProgramPos( speed, xbin, ybin, &need_upload);
1044  _logger->log( Logger::LOG_LEV_DEBUG, "Pos in memory=%d, need_upload = %d", pos, need_upload);
1045 
1046 
1047 
1048  //At this point should just be able to issue a "set x x x x" to CCD47Ctrl
1049 
1050 
1051  //but need to track current program_set
1052 
1053  // If not in current memory
1054  if (pos == -1)
1055  {
1056  // If not in disk files
1057  if (need_upload == -1)
1058  {
1059  _logger->log( Logger::LOG_LEV_WARNING, "Program %d, %dx%d is not valid", speed, xbin, ybin);
1060  return NO_ERROR;
1061  }
1062 
1063  // If in disk files, upload the new program set
1064 
1065 
1066  UpdateJoeMemory( need_upload);
1067  cur_ProgramSet = need_upload;
1068 
1069  // Call again this routine, now it will find the program inside the LittleJoe memory
1070  return ReprogramJoe( force);
1071  }
1072 
1073  // Program found in current memory
1074  _logger->log( Logger::LOG_LEV_INFO, "Program in memory at position %d", pos);
1075 
1076  cur_Program = pos;
1077 
1078  snprintf(cmstr, 50, "set %i %i %i %i", cur_ProgramSet, cur_Program, cur_Gain, cur_Reps);
1079 
1080  std::cout << "Sending command: " << cmstr << "\n";
1081  send_ccd47_command(cmstr);
1082  sleep(2);
1083  // Update status variables
1084 
1085  //in VisAO these will happen as part of event loop.
1086 
1087  //var_xbin_cur.Set(xbin, 0, FORCE_SEND);
1088  //var_ybin_cur.Set(ybin, 0, FORCE_SEND);
1089  //var_speed_cur.Set(speed, 0, FORCE_SEND);
1090 
1091  /*// Set default black levels, if specified
1092  littlejoe_program *program = GetProgram(speed, xbin, ybin);
1093 
1094  if (program)
1095  for (i=0; i< _ccdBlacks.size(); i++)
1096  if (program->black_levels[i] >=0)
1097  if ((stat = SetJoeBlack(i, program->black_levels[i])) != NO_ERROR)
1098  _logger->log( Logger::LOG_LEV_ERROR, "Error in SetJoeBlacklevels(): (%d) %s", stat, lao_strerror(stat));
1099 
1100  // Update black level variables
1101  for (i=0; i< _ccdBlacks.size(); i++)
1102  {
1103  int level = GetBlackLevel(i);
1104  if (level>=0)
1105  var_black_cur.Set( GetBlackLevel(i), (int)i, NO_SEND);
1106  else
1107  return level;
1108  }
1109 
1110  var_black_cur.Send();
1111  */
1112  // Since the program also stores run state, fix it if needed
1113  /*int enable;
1114  var_enable_req.Get(&enable);
1115  if (enable)
1116  stat = Start();
1117  else
1118  stat = Stop();
1119  if (stat != NO_ERROR)
1120  return stat;
1121 */
1122  // Show new available speeds
1123  ExposeSpeeds();
1124  // Show new available windows
1125  ExposeWindows();
1126 
1127  // Update shown framerate
1128  return ComputeFramerate();
1129 }
1130 
1131 
1132 
1133 
1134 
1135 // Adds $ADOPT_ROOT/filePrefix/ to the name
1136 /*std::string JoeCtrl::getCompletePath( std::string filename)
1137 {
1138  std::string path;
1139 
1140  path = getenv("ADOPT_ROOT");
1141  path += "/" + _filePrefix;
1142  path += filename;
1143 
1144  return path;
1145 }*/
1146 
1147 
1148 
1149 //+Function GetProgram
1150 //
1151 // Finds the program with the specified characteristics and returns a pointer to it.
1152 // Returns NULL if the program is not found.
1153 //-
1154 
1155 littlejoe_program *JoeCtrl::GetProgram( int speed, int xbin, int ybin)
1156 {
1157  unsigned int i,j;
1158 
1159  for (i=0; i<ondisk.size(); i++)
1160  for (j=0; j< ondisk[i].programs.size(); j++)
1161  if ((ondisk[i].programs[j].binx == xbin) &&
1162  (ondisk[i].programs[j].biny == ybin) &&
1163  (ondisk[i].programs[j].readout_speed == speed))
1164  return &(ondisk[i].programs[j]);
1165 
1166  return NULL;
1167 }
1168 
1169 
1170 
1171 //+Function
1172 //
1173 // GetProgramPos
1174 //
1175 // Returns the position into the LittleJoe controller memory of the specified program.
1176 // If not found, returns -1 and puts into need_upload the file number to upload.
1177 // If a file with the specified program is not found, need_upload will be -1 as well.
1178 //-
1179 
1180 
1181 int JoeCtrl::GetProgramPos( int speed, int xbin, int ybin, int *need_upload)
1182 {
1183  unsigned int i,j;
1184  i=0;
1185 
1186  // Search in the current LittleJoe memory
1187  vector<littlejoe_program>::iterator iter;
1188  for (iter= memory.programs.begin(); iter != memory.programs.end(); iter++)
1189  {
1190  if ((iter->binx == xbin) &&
1191  (iter->biny == ybin) &&
1192  (iter->readout_speed == speed))
1193  {
1194  if (need_upload)
1195  *need_upload=0;
1196  return i;
1197  }
1198  i++;
1199  }
1200 
1201  _logger->log( Logger::LOG_LEV_DEBUG, "Not in memory");
1202 
1203  // Search in the disk files
1204  if (need_upload)
1205  for (i=0; i<ondisk.size(); i++)
1206  for (j=0; j< ondisk[i].programs.size(); j++)
1207  if ((ondisk[i].programs[j].binx == xbin) &&
1208  (ondisk[i].programs[j].biny == ybin) &&
1209  (ondisk[i].programs[j].readout_speed == speed))
1210  {
1211  *need_upload = i;
1212  return -1;
1213  }
1214  _logger->log( Logger::LOG_LEV_DEBUG, "Not on disk");
1215  if (need_upload)
1216  *need_upload=-1;
1217  return -1;
1218 }
1219 
1220 //+Function
1221 //
1222 // UpdateJoeMemory
1223 //
1224 // To be called after a program has been successfully downloaded to the LittleJoe controller
1225 //-
1226 
1227 int JoeCtrl::UpdateJoeMemory( unsigned int uploaded_file)
1228 {
1229  if (uploaded_file >= ondisk.size())
1230  return JOE_OUT_OF_RANGE_ERROR;
1231 
1232  memory = ondisk[uploaded_file];
1233 
1234  return NO_ERROR;
1235 }
1236 
1237 
1238 //+Function: DumpProgramset
1239 //
1240 // Dumps a programset on screen
1241 //-
1242 
1243 int DumpProgramset( littlejoe_programset programset)
1244 {
1245  int i=0;
1246 
1247  printf("Programset: %s\n", programset.name.c_str());
1248  printf("Control filename: %s\n", programset.control_filename.c_str());
1249  printf("Pattern filename: %s\n", programset.pattern_filename.c_str());
1250  printf("Number of programs: %lu\n", (unsigned long) (programset.programs.size()));
1251 
1252  vector<littlejoe_program>::iterator iter;
1253  for (iter= programset.programs.begin(); iter != programset.programs.end(); iter++)
1254  {
1255  printf("Program %d, name:%s\n", i++, iter->name.c_str());
1256  printf("Bin, speed: %dx%d, %d\n", iter->binx, iter->biny, iter->readout_speed);
1257  printf("Delay base, inc: %f,%f\n", iter->delay_base, iter->delay_inc);
1258  }
1259 
1260  return NO_ERROR;
1261 }
1262 
1263 
1264 //@Function: EraseLocalMemory
1265 //
1266 // Erases the local copy of LittleJoe's internal memory
1267 //@
1268 
1269 int JoeCtrl::EraseLocalMemory()
1270 {
1271  memory.programs.clear();
1272 
1273  // If requested, start assuming a certain program set is available
1274  if (_startProgramSet >= 0)
1275  SetLocalMemory( _startProgramSet);
1276 
1277  return NO_ERROR;
1278 }
1279 
1280 //@Function: SetLocalMemory
1281 //
1282 // Synch the local memory information to a certain programset
1283 //@
1284 
1285 int JoeCtrl::SetLocalMemory( unsigned int programset_num)
1286 {
1287  memory = ondisk[programset_num];
1288  return NO_ERROR;
1289 }
1290 
1291 
1292 //@Function: LoadJoeDiskFiles
1293 //
1294 // Load the configuration files specifying the different
1295 // program sets that can be uploaded to LittleJoe
1296 //
1297 //@
1298 
1299 int JoeCtrl::LoadJoeDiskFiles()
1300 {
1301  int num, i;
1302  std::string prefix;
1303 
1304  num = ConfigDictionary()["num_programsets"];
1305 
1306  ondisk.resize(num);
1307 
1308  for (i=0; i<num; i++)
1309  {
1310  char param[32];
1311 
1312  sprintf( param, "programset%d", i);
1313  Config_File *subtree = ConfigDictionary().extract(param);
1314  ondisk[i] = ReadProgramSet( *subtree);
1315  delete subtree;
1316  }
1317 
1318  if (debug)
1319  for (i=0; i<num; i++)
1320  DumpProgramset(ondisk[i]);
1321 
1322  _logger->log( Logger::LOG_LEV_INFO, "%d programsets loaded.", ondisk.size());
1323  return 0;
1324 }
1325 
1326 // Reads a configuration file with the parameters of an entire LittleJoe program set
1327 
1328 littlejoe_programset JoeCtrl::ReadProgramSet( Config_File &cfg)
1329 {
1330  int size;
1331  unsigned int i;
1332 
1333  littlejoe_programset programset;
1334 
1335  programset.name = (std::string) cfg["name"];
1336  programset.control_filename = (std::string) cfg["control_filename"];
1337  programset.pattern_filename = (std::string) cfg["pattern_filename"];
1338  size = cfg["num_programs"];
1339 
1340  if ((size<=0) || (size > 1000))
1341  {
1342  _logger->log( Logger::LOG_LEV_WARNING, "Skipping programset %s because it has %d programs", programset.name.c_str(), size);
1343  return programset;
1344  }
1345 
1346  programset.programs.resize( size);
1347 
1348  for (i=0; i< programset.programs.size(); i++)
1349  {
1350  char par_name[32];
1351  sprintf( par_name, "program%d", i);
1352 
1353  _logger->log( Logger::LOG_LEV_DEBUG, "Reading program %d of %d", i, programset.programs.size());
1354  Config_File *subtree = cfg.extract(par_name);
1355  programset.programs[i] = ReadProgram( *subtree);
1356  delete subtree;
1357  }
1358 
1359  return programset;
1360 }
1361 
1362 // Read a configuration file with the parameters of a single LittleJoe program
1363 
1364 littlejoe_program JoeCtrl::ReadProgram( Config_File &cfg)
1365 {
1366  littlejoe_program program;
1367 
1368  program.name = (std::string) cfg["name"];
1369  program.readout_speed = cfg["readout_speed"];
1370  program.binx = cfg["binx"];
1371  program.biny = cfg["biny"];
1372  program.windowx = cfg["windowx"];
1373  program.windowy = cfg["windowy"];
1374  program.delay_base = cfg["delay_base"];
1375  program.delay_inc = cfg["delay_inc"];
1376 
1377  // Read default black levels if they exist, otherwise set to -1
1378  for (int i=0; i<4; i++) {
1379  try {
1380  char str[10];
1381  sprintf( str, "black%d", i+1);
1382  program.black_levels[i] = cfg[str];
1383  } catch (Config_File_Exception &e) {
1384  program.black_levels[i] = -1;
1385  }
1386  }
1387 
1388  _logger->log( Logger::LOG_LEV_DEBUG, "Found: speed %d, binx %d, biny %d, base %f, inc %f", program.readout_speed, program.binx, program.biny, program.delay_base, program.delay_inc);
1389 
1390  // Build the arrays listing each possible value
1391  insert_value( _ccdXbins, program.binx);
1392  insert_value( _ccdYbins, program.biny);
1393 // insert_value( ccd_speeds, program.readout_speed);
1394 
1395  return program;
1396 }
1397 
1398 int JoeCtrl::insert_value( vector<int> &array, int value)
1399 {
1400  vector<int>::iterator iter;
1401  for ( iter = array.begin(); iter != array.end(); iter++)
1402  if (*iter == value)
1403  return NO_ERROR;
1404 
1405  array.push_back(value);
1406  return NO_ERROR;
1407 }
1408 
1409 
1410 } //namespace VisAO
1411 
int _minRep
Minimum repititions (controls integration time)
Definition: VisAOJoeCtrl.h:70
RTDBvar var_preset_req
Preset to program set 0, program 0, for presetVisAO.
Definition: VisAOJoeCtrl.h:106
int cur_Reps
The current repititions running on the little joe.
Definition: VisAOJoeCtrl.h:76
int _maxRep
Maximum repititions (controls integration time)
Definition: VisAOJoeCtrl.h:71
void Run()
VIRTUAL - Run.
int cur_Program
The current program running on the little joe.
Definition: VisAOJoeCtrl.h:74
fifo_list * global_fifo_list
The global fifo_list, for signal handling.
Definition: dioserver.cpp:19
int cur_ProgramSet
The Current program set loaded on the little joe.
Definition: VisAOJoeCtrl.h:73
static int EnableReqChanged(void *pt, Variable *var)
RTDB handler for an enable change request form the AO Supervisor.
static int PresetReqChanged(void *pt, Variable *msgb)
RTDB handler for preset request from the AO Supervisor.
double wait_to
The timeout for waiting on responses from FIFOs in seconds.
littlejoe_programset memory
Struct representing LittleJoe's internal memory.
Definition: VisAOJoeCtrl.h:86
int read_fifo_channel(fifo_channel *fc)
Read data from the input fifo channel.
Definition: fifoutils.c:246
std::string send_ccd47_command(std::string com)
Send a command to the CCD47 and get its response.
static int SpeedReqChanged(void *pt, Variable *var)
RTDB handler for a speed change request form the AO Supervisor.
int Stop()
Send a stop command to the CCD47Ctrl.
void SetupVars(void)
VIRTUAL - Setups variables in RTDB.
std::string _ccdName
CCD name.
Definition: VisAOJoeCtrl.h:56
static int RepReqChanged(void *pt, Variable *var)
RTDB handler for a repetitions change request form the AO Supervisor.
int Start()
Send a start command to the CCD47Ctrl.
static int BlackReqChanged(void *pt, Variable *var)
RTDB handler for a black level change request form the AO Supervisor.
fifo_channel * fifo_ch
An array of fifo_channels.
Definition: fifoutils.h:207
int cur_Gain
The current gain running on the little joe.
Definition: VisAOJoeCtrl.h:75
RTDBvar var_cmode_cur
The current control mode in the RTDB.
Definition: VisAOJoeCtrl.h:103
std::vector< littlejoe_program > programs
Details of the individual programs.
Definition: CCD47Ctrl.h:88
static int CModeReqChanged(void *pt, Variable *msgb)
RTDB handler for a control mode change request from the AO Supervisor.
std::vector< int > _ccdXbins
Vector of x binnings.
Definition: VisAOJoeCtrl.h:65
int setup_fifo_list(int nfifos)
Allocate the fifo_list.
std::vector< littlejoe_programset > ondisk
Struct array representing files that can be uploaded to LittleJoe (each one is a memory dump) ...
Definition: VisAOJoeCtrl.h:89
static int XbinReqChanged(void *pt, Variable *var)
RTDB handler for an x-bin change request form the AO Supervisor.
int TestCCD47CtrlLink()
Test the link with the CCD47Ctrl, and get its state.
int _ccdDy
Size in y.
Definition: VisAOJoeCtrl.h:60
int _maxNumBins
Maximum number of binnings.
Definition: VisAOJoeCtrl.h:63
static int FrameRateReqChanged(void *pt, Variable *var)
RTDB handler for a frame rate change request form the AO Supervisor.
int ReprogramJoe(int force=0)
Calculate and send a reprogram request to the CCD47Ctrl.
int _ccdDx
Size in x.
Definition: VisAOJoeCtrl.h:59
int _ccdDefaultXbin
Default x binning.
Definition: VisAOJoeCtrl.h:80
int TimeToDie
Global set by SIGTERM.
int DoFSM(void)
Perform controller functions and manage states.
fifo_list fl
The list of named-pipe fifos used for inter-process comms.
static int YbinReqChanged(void *pt, Variable *var)
RTDB handler for a y-bin change request form the AO Supervisor.
int _ccdBlacksNum
Nuber of blacks.
Definition: VisAOJoeCtrl.h:69
int _startProgramSet
The program set currently set to load from flash on little joe power up.
Definition: VisAOJoeCtrl.h:79
std::vector< int > _ccdBlacks
Vector of black levels.
Definition: VisAOJoeCtrl.h:68
void StateChange(int oldstate, int state)
VIRTUAL - StateChange.
int _ccdDefaultSpeed
Default speed.
Definition: VisAOJoeCtrl.h:82
std::vector< int > _ccdYbins
Vector of y binnings.
Definition: VisAOJoeCtrl.h:66
Holds the details of one little joe program.
Definition: CCD47Ctrl.h:61
int _maxNumSpeeds
Maximum number of speeds.
Definition: VisAOJoeCtrl.h:62
int _ccdDefaultYbin
Default y binning.
Definition: VisAOJoeCtrl.h:81
The interface between the CCD47Ctrl class and the AO Supervisor.
Definition: VisAOJoeCtrl.h:41
int connect_fifo_list()
Connect the fifo_list with exclusive locking.
The namespace of VisAO software.
static int GainReqChanged(void *pt, Variable *var)
RTDB handler for a gain change request form the AO Supervisor.
Declarations for CCD47 control from the AO Supervisor.
void Create(void)
Read the JoeCtrl specific config vars and connect to the CCD47Ctrl.
JoeCtrl(std::string name, const std::string &conffile)
Config file constructor.
#define RWBUFF_SZ
The size of the i/o buffer.
Definition: fifoutils.h:43
RTDBvar var_cmode_req
The requested control mode in the RTDB.
Definition: VisAOJoeCtrl.h:104
int _ccdDefaultBlack
Default black levels.
Definition: VisAOJoeCtrl.h:83
void PostInit()
VIRTUAL - Perform post-initialization settings.
int set_fifo_list_channel(fifo_list *fl, int nch, int buffsz, const char *fin, const char *fout, int(*inp_hand)(fifo_channel *), void *adata)
Set the details of one channel in the list.
Definition: fifoutils.c:373
int write_fifo_channel(int ch, const char *com, int comlen, std::string *resp)
Write data to a fifo_channel, and get a response if desired.