The VisAO Camera
CCD47Ctrl.cpp
Go to the documentation of this file.
1 /************************************************************
2 * CCD47Ctrl.cpp
3 *
4 * Author: Jared R. Males (jrmales@email.arizona.edu)
5 *
6 * Definitions for the VisAO CCD47 controller.
7 *
8 * Developed as part of the Magellan Adaptive Optics system.
9 ************************************************************/
10 
11 /** \file CCD47Ctrl.cpp
12  * \author Jared R. Males
13  * \brief Definitions for the VisAO CCD47 controller.
14  *
15 */
16 
17 #include "CCD47Ctrl.h"
18 
19 #define JOE_ADDR_LEN 15 // Length of idrive string address
20 #define ERRMSG_LEN 32 // Length of an error message
21 
22 //#define NOPDV
23 //#define _debug
24 
25 #define FG_FIFO 0
26 #define FW_FIFO 1
27 
28 namespace VisAO
29 {
30 
31 
32 CCD47Ctrl::CCD47Ctrl( std::string name, const std::string &conffile) throw (AOException) : VisAOApp_standalone(name, conffile)
33 {
34  Create();
35 }
36 
37 CCD47Ctrl::CCD47Ctrl( int argc, char **argv) throw (AOException) : VisAOApp_standalone( argc, argv)
38 {
39  Create();
40 }
41 
42 void CCD47Ctrl::Create() throw (AOException)
43 {
44  try
45  {
46  adopt_cfg_file = (std::string)ConfigDictionary()["ccd47_name"];
47  adopt_cfg = new Config_File(Utils::getConffile(adopt_cfg_file));
48  }
49  catch (Config_File_Exception &e)
50  {
51  _logger->log( Logger::LOG_LEV_FATAL, "%s", e.what().c_str());
52  throw AOException("Fatal: cannot find adopt ccd47 configuration");
53  }
54 
55  //adopt_cfg = &ConfigDictionary();
56 
57  try
58  {
59  //_ccdNum = (*adopt_cfg)["ID"];
60  _ccdName = (std::string) (*adopt_cfg)["ccdName"];
61  _ccdNetAddr = (std::string) (*adopt_cfg)["ccdNetAddr"];
62  _ccdNetPort = (*adopt_cfg)["ccdNetPort"];
63  _ccdDx = (*adopt_cfg)["ccdXdim"];
64  _ccdDy = (*adopt_cfg)["ccdYdim"];
65  _ccdDefaultXbin = (*adopt_cfg)["ccdDefaultXbin"];
66  _ccdDefaultYbin = (*adopt_cfg)["ccdDefaultYbin"];
67  _ccdDefaultSpeed = (*adopt_cfg)["ccdDefaultSpeed"];
68  _ccdDefaultBlack = (*adopt_cfg)["ccdDefaultBlack"];
69  _ccdBlacksNum = (*adopt_cfg)["ccdBlacksNum"];
70  _minRep = (*adopt_cfg)["minRep"];
71  _maxRep = (*adopt_cfg)["maxRep"];
72  _maxNumSpeeds = (*adopt_cfg)["maxNumSpeeds"];
73  _maxNumBins = (*adopt_cfg)["maxNumBins"];
74  //_filePrefix = (std::string) (*adopt_cfg)["filePrefix"];
75  _startProgramSet = (*adopt_cfg)["startProgramSet"];
76  _startProgram = (*adopt_cfg)["startProgram"];
77  _startGain = (*adopt_cfg)["startGain"];
78  _startReps = (*adopt_cfg)["startReps"];
79 
80  EDT_cfgdir = (std::string)ConfigDictionary()["EDT_cfgdir"];
81 
82  init_VisAOApp();
83 
84  }
85  catch (Config_File_Exception &e)
86  {
87  _logger->log( Logger::LOG_LEV_FATAL, "%s", e.what().c_str());
88  throw AOException("Fatal: Missing configuration data");
89  }
90 
91 
92 
93  _tempsLogger = Logger::get( _ccdName+"Temperature", Logger::LOG_LEV_INFO, "TELEMETRY");
94 
95  // Create the specific LittleJoe arrays
97 
98  cur_State = STATE_UNDEFINED;
99 
100  cur_ProgramSet = _startProgramSet;
101  cur_Program = _startProgram;
102  cur_Gain = _startGain;
103  cur_Reps = _startReps;
104 
105  cur_speed = ondisk[cur_ProgramSet].programs[cur_Program].readout_speed;
106  cur_xbin = ondisk[cur_ProgramSet].programs[cur_Program].binx;
107  cur_ybin = ondisk[cur_ProgramSet].programs[cur_Program].biny;
108  cur_windowx = ondisk[cur_ProgramSet].programs[cur_Program].windowx;
109  cur_windowy = ondisk[cur_ProgramSet].programs[cur_Program].windowy;
110 
111 
112  // Update shown framerate
114 
115  FGsaving = 0;
116  FGrunning = 0;
117 
118  imtype = 0; //Default imtype is science
119 
120  //Init the status board
122  if(create_statusboard(sizeof(ccd47_status_board)) != 0)
123  {
125  _logger->log(Logger::LOG_LEV_ERROR, "Could not create status board.");
126  }
127  else
128  {
130  strncpy(bsb->appname, MyFullName().c_str(), 25);
131  bsb->max_update_interval = pause_time;
132  }
133 
134  size_t sz;
136 }
137 
138 
139 
141 {
142  std::string fifo_path, visao_root, fgin, fgout;
143 
144  try
145  {
146  fifo_path = (std::string) ConfigDictionary()["fifo_path"];
147  }
148  catch (Config_File_Exception &e)
149  {
150  fifo_path = "fifos";
151  }
152 
153  try
154  {
155  FrameGrabberName = (std::string)ConfigDictionary()["FrameGrabberName"];
156  }
157  catch (Config_File_Exception &e)
158  {
159  FrameGrabberName = "framegrabber47";
160  }
161 
162  try
163  {
164  FrameWriterName = (std::string)ConfigDictionary()["FrameWriterName"];
165  }
166  catch (Config_File_Exception &e)
167  {
168  FrameWriterName = "framewriter47";
169  }
170 
171  visao_root = getenv("VISAO_ROOT");
172 
173 
174 
175 
176  setup_fifo_list(5);
177  setup_baseApp(1,1,1,0,false);
178 
179 
180  fgin = visao_root + "/" + fifo_path + "/" + FrameGrabberName + "_com_auto_in";
181  fgout = visao_root + "/" + fifo_path + "/" + FrameGrabberName + "_com_auto_out";
182  set_fifo_list_channel(&fl, FG_FIFO, RWBUFF_SZ, fgout.c_str(),fgin.c_str(), 0, 0);
183 
184  fgin = visao_root + "/" + fifo_path + "/" + FrameWriterName + "_com_auto_in";
185  fgout = visao_root + "/" + fifo_path + "/" + FrameWriterName + "_com_auto_out";
186  set_fifo_list_channel(&fl, FW_FIFO, RWBUFF_SZ, fgout.c_str(),fgin.c_str(), 0, 0);
187 
188  //::global_fifo_list = &fl;
189 
190  pthread_mutex_init(&reprogMutex, 0);
191 }
192 
194 {
195  int num, i;
196  std::string prefix;
197 
198  num = (*adopt_cfg)["num_programsets"];
199 
200  ondisk.resize(num);
201 
202  for (i=0; i<num; i++)
203  {
204  char param[32];
205  sprintf( param, "programset%d", i);
206  Config_File *subtree = (*adopt_cfg).extract(param);
207  ondisk[i] = ReadProgramSet( *subtree);
208  delete subtree;
209  }
210 
211  //if (debug) for (i=0; i<num; i++) DumpProgramset(ondisk[i]);
212 
213  _logger->log( Logger::LOG_LEV_INFO, "%d programsets loaded.", ondisk.size());
214  return 0;
215 }//int CCD47Ctrl::LoadJoeDiskFiles()
216 
218 {
219  int size;
220  unsigned int i;
221 
222  littlejoe_programset programset;
223 
224  programset.name = (std::string) cfg["name"];
225  programset.control_filename = (std::string) cfg["control_filename"];
226  programset.pattern_filename = (std::string) cfg["pattern_filename"];
227  size = cfg["num_programs"];
228 
229  if ((size<=0) || (size > 1000))
230  {
231  _logger->log( Logger::LOG_LEV_WARNING, "Skipping programset %s because it has %d programs", programset.name.c_str(), size);
232  return programset;
233  }
234 
235  programset.programs.resize( size);
236 
237  for (i=0; i< programset.programs.size(); i++)
238  {
239  char par_name[32];
240  sprintf( par_name, "program%d", i);
241 
242  _logger->log( Logger::LOG_LEV_DEBUG, "Reading program %d of %d", i, programset.programs.size());
243  Config_File *subtree = cfg.extract(par_name);
244  programset.programs[i] = ReadProgram( *subtree);
245  delete subtree;
246  }
247 
248  return programset;
249 }//littlejoe_programset CCD47Ctrl::ReadProgramSet( Config_File &cfg)
250 
251 
253 {
254  littlejoe_program program;
255 
256  program.name = (std::string) cfg["name"];
257  program.readout_speed = cfg["readout_speed"];
258  program.binx = cfg["binx"];
259  program.biny = cfg["biny"];
260  program.windowx = cfg["windowx"];
261  program.windowy = cfg["windowy"];
262  program.delay_base = cfg["delay_base"];
263  program.delay_inc = cfg["delay_inc"];
264 
265  // Read default black levels if they exist, otherwise set to -1
266  for (int i=0; i<4; i++)
267  {
268  try
269  {
270  char str[10];
271  sprintf( str, "black%d", i+1);
272  program.black_levels[i] = cfg[str];
273  }
274  catch (Config_File_Exception &e)
275  {
276  program.black_levels[i] = -1;
277  }
278  }
279 
280  program.EDT_cfg_fname = (std::string) cfg["EDT_cfg_fname"];
281 
282  _logger->log( Logger::LOG_LEV_DEBUG, "Found: speed %d, binx %d, biny %d, windowx %d, windowy %d, base %f, inc %f, EDT config %s", program.readout_speed, program.binx, program.biny, program.windowx, program.windowy, program.delay_base, program.delay_inc, program.EDT_cfg_fname.c_str());
283 
284  return program;
285 }//littlejoe_program CCD47Ctrl::ReadProgram( Config_File &cfg)
286 
288 {
289  int stat;
290  std::string resp;
291 
292  _logger->log( Logger::LOG_LEV_DEBUG, "Stopping CCD");
293 
294  //Stop framegrabber here.
295 
296  write_fifo_channel(FG_FIFO, "AUTO", 4, &resp);
297  write_fifo_channel(FG_FIFO, "stop", 4, &resp);
298 
299 
300  stat = StopJoe();
301 
302  if (stat == NO_ERROR)
303  {
304  if(cur_State != STATE_CONFIGURING)
305  {
306  cur_State = STATE_READY;
307  }
308  }
309 
310  return stat;
311 }
312 
314 {
315  std::string resp;
316 
317  write_fifo_channel(FG_FIFO, "save?", 6, &resp);
318 
319  if(resp[0] == '1')
320  {
321  FGsaving = 1;
322  write_fifo_channel(FG_FIFO, "remaining?", 10, &resp);
323  FGremaining = atoi(resp.c_str());
324  }
325  else
326  {
327  FGsaving = 0;
328  FGremaining = 0;
329  }
330 
331  write_fifo_channel(FG_FIFO, "skip?", 6, &resp);
332 
333  FGskipping = atoi(resp.c_str());
334 
335  write_fifo_channel(FG_FIFO, "running?", 9, &resp);
336  if(resp[0] == '1') FGrunning = 1;
337  else FGrunning = 0;
338 
339  write_fifo_channel(FW_FIFO, "subdir?", 8, &resp);
340  FWsubdir = resp;
341 
342 
343  return 0;
344 }
345 
347 {
348 
349  int stat;
350  std::string resp;
351  _logger->log( Logger::LOG_LEV_DEBUG, "Starting CCD");
352  #ifdef _debug
353  std::cerr << "Starting CCD\n";
354  #endif
355  stat = StartJoe();
356 
357  if (stat == NO_ERROR)
358  {
359  _logger->log( Logger::LOG_LEV_DEBUG, "CCD Started");
360  #ifdef _debug
361  std::cerr << "CCD Started\n";
362  #endif
363  cur_State = STATE_OPERATING;
364 
365  //Start up the framegrabber
366  write_fifo_channel(FG_FIFO, "AUTO", 5, &resp);
367 
368  write_fifo_channel(FG_FIFO, "start", 6, &resp);
369 
371  }
372  else
373  {
374  _logger->log( Logger::LOG_LEV_ERROR, "Error starting CCD");
375  #ifdef _debug
376  std::cerr << "Not Started\n";
377  #endif
378  }
379 
380  return stat;
381 
382 }
383 
385 {
386 
387  //This should query
388 
389  cur_ProgramSet = _startProgramSet;
390  cur_Program = _startProgram;
391  cur_Gain = _startGain;
392  cur_Reps = _startReps;
393 
394  //int stat;
395  //unsigned int i;
396 
397  //StopJoe();
398 
399  //return ReprogramJoe(_startProgramSet, 0, 0, 0, 1);
400 
401 /* cur_ProgramSet = _startProgramSet;
402  cur_Program = 0;
403  cur_Gain = 0;
404 
405  cur_xbin = ondisk[cur_ProgramSet].programs[cur_Program].binx;
406  cur_ybin = ondisk[cur_ProgramSet].programs[cur_Program].biny;
407  cur_windowx = ondisk[cur_ProgramSet].programs[cur_Program].windowx;
408  cur_windowy = ondisk[cur_ProgramSet].programs[cur_Program].windowy;
409  cur_rep = 0;
410 
411  // Update shown framerate
412  ComputeFramerate();
413 
414 
415  load_EDT_config(ondisk[cur_ProgramSet].programs[cur_Program].EDT_cfg_fname);*/
416 
417 /* for (i=0; i< _ccdBlacks.size(); i++)
418  {
419  if ((stat=SetJoeBlack( i, default_black)) != NO_ERROR)
420  {
421  return stat;
422  }
423  } */
424 
425  return NO_ERROR;
426 
427 } //int CCD47Ctrl::FirstJoeConfig()
428 
430 {
431  if(it <0 || it > 4) it = 0;
432 
433  imtype = it;
434 
436  {
437 
439 
440  csb->imtype = imtype;
441  }
442  return 0;
443 }
444 
445 
447 {
448 
449  int xbin, ybin, speed, rep;
450 
451  xbin = cur_xbin;
452  ybin = cur_ybin;
453  speed = cur_speed;
454  rep = cur_Reps;
455 
456  double framerate;
457 
458  littlejoe_program *program = &(ondisk[cur_ProgramSet].programs[cur_Program]);
459 
460  if (!program)
461  {
462  return VALUE_OUT_OF_RANGE_ERROR;
463  }
464 
465  framerate = 1.0e6/ (program->delay_base + program->delay_inc * rep);
466 
467  _logger->log( Logger::LOG_LEV_DEBUG, "Delay base: %f - Delay_inc: %f - Rep: %d - framerate: %f", program->delay_base, program->delay_inc, rep, framerate);
468 
469  cur_framerate = framerate;
470 
471  return NO_ERROR;
472 }//int CCD47Ctrl::ComputeFramerate()
473 
475 {
476  int xbin, ybin, speed, rep;
477 
478  xbin = cur_xbin;
479  ybin = cur_ybin;
480  speed = cur_speed;
481 
482  littlejoe_program *program = &(ondisk[cur_ProgramSet].programs[cur_Program]);
483 
484  if (!program)
485  {
486  return VALUE_OUT_OF_RANGE_ERROR;
487  }
488 
489 
490  rep = ((1.0e6/fr) - program->delay_base)/program->delay_inc;
491 
492  return rep;
493 }
494 
496 {
497  return ComputeRepsFrameRate(1./et);
498 }
499 
500 
501 
502 //Structure to hold instructions to pass to the reprogram thread.
504 {
505  CCD47Ctrl * ctrl;
506  int program_set;
507  int program;
508  int gain;
509  int rep;
510  int force;
511 };
512 
513 ReprogramData rpd;
514 
515 
516 //This is the thread start function for reprogramming the little joe
517 // First blocks SIGIO so uploads aren't interrupted
518 // Then calls __ReprogramJoe
519 void * ReprogramJoeThreadWorker(void * adata)
520 {
521  static int rv;
522  sigset_t set;
523  sigemptyset(&set);
524  sigaddset(&set, SIGIO);
525  sigaddset(&set, RTSIGIO);
526  pthread_sigmask(SIG_BLOCK, &set, 0);
527 
528  ReprogramData * rpd = (ReprogramData *) adata;
529 
530  rv = rpd->ctrl->__ReprogramJoe(rpd->program_set, rpd->program, rpd->gain, rpd->rep, rpd->force);
531 
532  return (void *) (&rv);
533 
534 }//void * ReprogramJoeThreadWorker(void * adata)
535 
536 
537 int CCD47Ctrl::ReprogramJoe(int program_set, int program, int gain, int rep, int force)
538 {
539 
540  pthread_mutex_lock(&reprogMutex);
541 
542  rpd.ctrl = this;
543  rpd.program_set = program_set;
544  rpd.program = program;
545  rpd.gain = gain;
546  rpd.rep = rep;
547  rpd.force = force;
548 
549  pthread_attr_t attr;
550  pthread_attr_init(&attr);
551  pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
552 
553  joe_loading = 1;
554 
555  pthread_create(&load_thread, &attr, &ReprogramJoeThreadWorker, (void *) &rpd);
556 
557  return 0;
558 
559 }//int CCD47Ctrl::ReprogramJoe(int program_set, int program, int gain, int rep, int force)
560 
561 int CCD47Ctrl::__ReprogramJoe(int program_set, int program, int gain, int rep, int force)
562 {
563  int stat;
564 
565  int AstronomerWantsItRunning;
566 
567  if(cur_State == STATE_OPERATING) AstronomerWantsItRunning = 1;
568  else AstronomerWantsItRunning = 0;
569 
570  // Stop ccd integration
571  stat = Stop();
572  cur_State = STATE_CONFIGURING;
573 
574  if (stat != NO_ERROR)
575  {
576  pthread_mutex_unlock(&reprogMutex);
577  return stat;
578  }
579 
580  _logger->log( Logger::LOG_LEV_DEBUG, "Checking program set: %d program %d", program_set, program);
581 
582  // If not in current memory
583  if (program_set != cur_ProgramSet || force)
584  {
585  // If not in disk files
586  if ((unsigned) program_set >= ondisk.size())
587  {
588  _logger->log( Logger::LOG_LEV_WARNING, "Program set %d is not valid", program_set);
589  pthread_mutex_unlock(&reprogMutex);
590  return NO_ERROR;
591  }
592 
593  // If in disk files, upload the new program set
594  _logger->log( Logger::LOG_LEV_INFO, "Program selection requires upload of program set %d", program_set);
595 
596  _logger->log( Logger::LOG_LEV_INFO, "Starting control file upload (%s)", getCompletePath(ondisk[program_set].control_filename).c_str());
597 
598  if ((stat = SendXmodemFile( "XMC 1", (char *) getCompletePath( ondisk[program_set].control_filename).c_str())) != NO_ERROR)
599  {
600  pthread_mutex_unlock(&reprogMutex);
601  _logger->log( Logger::LOG_LEV_ERROR, "Xmodem upload returned error");
602  std::cerr << "Xmodem upload returned error at " << __LINE__ << "\n";
603  return stat;
604  }
605 
606  _logger->log( Logger::LOG_LEV_INFO, "Starting pattern file upload (%s)", getCompletePath(ondisk[program_set].pattern_filename).c_str());
607 
608  if ((stat = SendXmodemFile( "XMP 1", (char *) getCompletePath( ondisk[program_set].pattern_filename).c_str())) != NO_ERROR)
609  {
610  pthread_mutex_unlock(&reprogMutex);
611  _logger->log( Logger::LOG_LEV_ERROR, "Xmodem upload returned error");
612  std::cerr << "Xmodem upload returned error at " << __LINE__ << "\n";
613  return stat;
614  }
615 
616  cur_ProgramSet = program_set;
617 
618  _logger->log( Logger::LOG_LEV_INFO, "Upload complete");
619 
620  }
621 
622  if(program < 0 || program > 7 || gain < 0 || gain > 3)
623  {
624  _logger->log( Logger::LOG_LEV_ERROR, "Program %d, gain %d is not valid", program, gain);
625  pthread_mutex_unlock(&reprogMutex);
626  return NO_ERROR;
627  }
628 
629  #ifdef _debug
630  std::cout << "Setting program " << program + gain*8 << std::endl;
631  #endif
632 
633  if ((stat = SetJoeRCL(program + gain*8)) != NO_ERROR)
634  {
635  _logger->log( Logger::LOG_LEV_ERROR, "Error in SetJoeRCL(): %d", stat);
636  pthread_mutex_unlock(&reprogMutex);
637  return stat;
638  }
639 
640  //rep = 0;/*
641  char buffer[25];
642  if(rep < 0) rep = 0;
643  if(rep > 65535) rep = 65535;
644 
645  #ifdef _debug
646  std::cout << "Setting repetitions" << std::endl;
647  #endif
648 
649  sprintf( buffer, "@REP %d", rep);
650  if ((SendJoeCommand( buffer, NULL, 25, 0)) != NO_ERROR)
651  {
652  std::cerr << "Error setting repetitions\n";
653  }
654  /*if((stat == SetJoeRepetitions(rep)) != NO_ERROR)
655  {
656  _logger->log( Logger::LOG_LEV_ERROR, "Error in SetJoeRepititions(): %d", stat);
657  return stat;
658  }*/
659 
660  cur_Program = program;
661  cur_Gain = gain;
662 
663  cur_speed = ondisk[cur_ProgramSet].programs[cur_Program].readout_speed;
664 
665  cur_xbin = ondisk[cur_ProgramSet].programs[cur_Program].binx;
666  cur_ybin = ondisk[cur_ProgramSet].programs[cur_Program].biny;
667  cur_windowx = ondisk[cur_ProgramSet].programs[cur_Program].windowx;
668  cur_windowy = ondisk[cur_ProgramSet].programs[cur_Program].windowy;
669  cur_Reps = rep;
670 
671  #ifdef _debug
672  std::cout << "Loading EDT conf at " << __LINE__ << std::endl;
673  #endif
674 
675  //Stop() seems to be required here to get everything synched up. Not sure why . . .
676  #ifdef _debug
677  std::cout << "Stopping at " << __LINE__ << std::endl;
678  #endif
679  Stop();
680 
681 //Now load the new config file
682  load_EDT_config(ondisk[cur_ProgramSet].programs[cur_Program].EDT_cfg_fname);
683 
684  // Update shown framerate
686 
687 
688  if(AstronomerWantsItRunning)
689  {
690 
691  //For whatever reason have to sleep for a bit before restarting.
692  //double st = get_curr_time();
693  /*while(get_curr_time() - st < 1.)
694  {
695  sleep(1);
696  }*/
697 
698  #ifdef _debug
699  std::cout << "Starting at " << __LINE__ << std::endl;
700  #endif
701  Start();
702  /*st = get_curr_time();
703  while(get_curr_time() - st < 1.)
704  {
705  sleep(1);
706  }*/
707  }
708  else cur_State = STATE_READY;
709 
710  pthread_mutex_unlock(&reprogMutex);
711  #ifdef _debug
712  std::cout << "Leaving _ReprogramJoe()\n";
713  #endif
714  return 0;
715 
716 }//int CCD47Ctrl::__ReprogramJoe(int program_set, int program, int gain, int rep, int force)
717 
718 int CCD47Ctrl::swonly_reprogram(int program_set, int program, int gain, int rep)
719 {
720 
721  #ifdef _debug
722  std::cout << "s/w only reprogram" << std::endl;
723  #endif
724 
725  cur_ProgramSet = program_set;
726  cur_Program = program;
727  cur_Gain = gain;
728 
729  cur_speed = ondisk[cur_ProgramSet].programs[cur_Program].readout_speed;
730 
731  cur_xbin = ondisk[cur_ProgramSet].programs[cur_Program].binx;
732  cur_ybin = ondisk[cur_ProgramSet].programs[cur_Program].biny;
733  cur_windowx = ondisk[cur_ProgramSet].programs[cur_Program].windowx;
734  cur_windowy = ondisk[cur_ProgramSet].programs[cur_Program].windowy;
735  cur_Reps = rep;
736 
737  // Update shown framerate
739 
740  return 0;
741 
742 }//int CCD47Ctrl::swonly_reprogram(int program_set, int program, int gain, int rep)
743 
744 void * __SetupNetwork(void * ctrl)
745 {
746  //First block the async I/O signals
747  sigset_t set;
748  sigemptyset(&set);
749  sigaddset(&set, SIGIO);
750  sigaddset(&set, RTSIGIO);
751 
752  pthread_sigmask(SIG_BLOCK, &set, 0);
753 
754  int * result = new int;
755 
756  CCD47Ctrl * ctrl47 = (CCD47Ctrl *) ctrl;
757 
758  *result = InitJoeLink( (char *)ctrl47->get_ccdNetAddr().c_str(), ctrl47->get_ccdNetPort());
759 
760  return (void *) result;
761 }//void * __SetupNetwork(void * ctrl)
762 
764 {
765 
766  int result, stat;
767 
768  // Close the previous connection, if any
769  SerialClose();
770  msleep(1000);
771 
772  _logger->log( Logger::LOG_LEV_INFO, "Connecting to %s:%d", (char *)_ccdNetAddr.c_str(), _ccdNetPort);
773 
774  // Setup serial/network interface
775  if (( result = InitJoeLink( (char *)_ccdNetAddr.c_str(), _ccdNetPort)) != NO_ERROR)
776  {
777  _logger->log( Logger::LOG_LEV_ERROR, "Error configuring network: (%d) %s", result, lao_strerror(result));
778  return NETWORK_ERROR;
779  }
780  _logger->log( Logger::LOG_LEV_INFO, "Network reconfigured OK");
781 
782 
783  // Now check our friend Joe
784  stat = PLAIN_ERROR(CheckJoe());
785  if (stat)
786  {
787  _logger->log( Logger::LOG_LEV_ERROR, "Error during LittleJoe testing: (%d) %s", stat, (char *)lao_strerror( stat));
788  return stat;
789  }
790 
791  return NO_ERROR;
792 }//int CCD47Ctrl::SetupNetwork()
793 
795 {
796  int stat;
797 
798  int state;
799  state = cur_State;
800 
801  if (state == STATE_NOCONNECTION)
802  {
803  return NO_ERROR;
804  }
805 
806  #ifdef _debug
807  std::cout << "Getting joe status" << std::endl;
808  #endif
809  stat = GetJoeStatus();
810  #ifdef _debug
811  std::cout << "Done getting joe status" << std::endl;
812  #endif
813 
814  if(stat < 0)
815  {
816  return stat;
817  }
818 
819  blackLevel[0] = GetBlackLevel(0);
820  blackLevel[1] = GetBlackLevel(1);
821 
823 
824  if(stat == 0 && cur_State == STATE_OPERATING)
825  {
826  //We think we're running, but we're not, so restart.
827  #ifdef _debug
828  std::cout << "Not running, restarting.\n";
829  #endif
830  //load_EDT_config(ondisk[cur_ProgramSet].programs[cur_Program].EDT_cfg_fname);
831  //sleep(1);
832  //return Start();
833  }
834 
835  if(stat == 1 && cur_State == STATE_READY)
836  {
837  //We think we've stopped, but we haven't, so restop.
838  #ifdef _debug
839  std::cout << "Running, restopping.\n";
840  #endif
841  return Stop();
842  }
843 
845 
846  //If we're just starting up, don't change state but do setup the framegrabber
847  if(stat == 0 && cur_State == STATE_CONNECTED)
848  {
849  #ifdef _debug
850  std::cout << "STATE_CONNECTED, Stopping FG.\n";
851  #endif
852  cur_State = STATE_READY;
853  if(FGrunning) return Stop(); //Frame grabber was running.
854  return 0;
855  }
856 
857  if(stat == 1 && cur_State == STATE_CONNECTED)
858  {
859  cur_State = STATE_OPERATING;
860 
861  if(!FGrunning)
862  {
863  #ifdef _debug
864  std::cout << "STATE_CONNECTED, Starting FG.\n";
865  #endif
866  //Now load the new config file
867  load_EDT_config(ondisk[cur_ProgramSet].programs[cur_Program].EDT_cfg_fname);
868  return Start();
869  }
870  return 0;
871  }
872 
873 
874  return NO_ERROR;
875 
876 }//int CCD47Ctrl::ReadJoeStatus()
877 
879 {
880  float t1, t2, t3;
881 
882  int stat;
883 
884  int state;
885  state = cur_State;
886 
887  if (state == STATE_NOCONNECTION)
888  {
889  temps[0] = -1;
890  temps[1] = -1;
891  temps[2] = -1;
892  return NO_ERROR;
893  }
894 
895  #ifdef _debug
896  std::cout << "Getting temperatures" << std::endl;
897  #endif
898  stat = GetJoeTemperature( &t1, &t2, &t3);
899  #ifdef _debug
900  std::cout << "Done getting temperatures" << std::endl;
901  #endif
902 
903  if (stat != NO_ERROR)
904  {
905  return stat;
906  }
907 
908  temps[0] = (double)t1;
909  temps[1] = (double)t2;
910  temps[2] = (double)t3;
911 
912  _tempsLogger->log(Logger::LOG_LEV_INFO, "%06.2f %06.2f %06.2f", temps[0], temps[1], temps[2]);
913 
914  return NO_ERROR;
915 
916 } //int CCD47Ctrl::ReadJoeTemps()
917 
918 std::string CCD47Ctrl::getCompletePath( std::string filename)
919 {
920  std::string path;
921 
922  path = Utils::getConffile(filename);
923 
924  int i = path.find(".conf");
925 
926  path.erase(i, path.length()-i);
927 
928  return path;
929 }//std::string CCD47Ctrl::getCompletePath( std::string filename)
930 
932 {
933  std::string resp;
934  int status;
935  int stat = NO_ERROR;
936 
937  status = cur_State;
938 
939  #ifdef _debug
940  std::cout << "DoFSM" << std::endl;
941  #endif
942 
943  // Always check if we can reach the LittleJoe
944  // If not, reset everything and start again
945  if (status != STATE_NOCONNECTION)
946  {
947  #ifdef _debug
948  std::cout << "Testing Joe Link" << std::endl;
949  #endif
950 
951  if ((stat=TestJoeLink()) != NO_ERROR)
952  {
953  #ifdef _debug
954  std::cerr << "TestJoeLink Failed " << stat << std::endl;
955  #endif
956  if(cur_State == STATE_OPERATING)
957  {
958  write_fifo_channel(FG_FIFO, "AUTO", 5, &resp);
959  write_fifo_channel(FG_FIFO, "stop", 5, &resp);
960  }
961  cur_State = STATE_NOCONNECTION;
962  }
963  }
964  status = cur_State;
965 
966  switch(status)
967  {
968  // At first, try to start network
969  case STATE_NOCONNECTION:
970  #ifdef _debug
971  std::cout << "Setting up network" << std::endl;
972  #endif
973  stat = SetupNetwork();
974 
975  if (stat == NO_ERROR) cur_State = STATE_CONNECTED;
976 
977  #ifdef _debug
978  std::cout << "Network is setup" << std::endl;
979  if(cur_State == STATE_CONNECTED) std::cout << "STATE_CONNECTED" << std::endl;
980  else std::cout << "STATE_NOCONNECTION" << std::endl;
981  #endif
982 
983  break;
984 
985  // After network start, discover configuration of LittleJoe
986 
987  case STATE_CONNECTED:
988  #ifdef _debug
989  //std::cerr << "First configing" << std::endl;
990  #endif
991  //stat = FirstJoeConfig(); //First try to figure out what state we're in.
992 
993  #ifdef _debug
994  std::cout << "reading joe status" << std::endl;
995  #endif
996  stat = ReadJoeStatus(); //Find out what we're doing.
997  break;
998 
999  case STATE_CONFIGURING:
1000  break;
1001  // When ready to go, do nothing
1002  case STATE_READY:
1003  case STATE_OPERATING:
1004  #ifdef _debug
1005  std::cout << "reading joe status" << std::endl;
1006  #endif
1007 
1008  ReadJoeStatus();
1009 
1010  #ifdef _debug
1011  std::cout << "reading joe temps" << std::endl;
1012  #endif
1013  stat = ReadJoeTemps();
1014 
1015  break;
1016 
1017  // Unknown states should not exist
1018  default:
1019  break;
1020  }
1021 
1022  #ifdef _debug
1023  std::cout << "done with DoFSM" << std::endl;
1024  #endif
1025  // Return the generated error code, if any
1026  return stat;
1027 }//int CCD47Ctrl::DoFSM(void)
1028 
1029 
1031 {
1032  double t0 = 0, dt;
1033 
1034  signal(SIGIO, SIG_IGN);
1035 
1037  {
1038  ERROR_REPORT("Error installing main thread catcher.");
1039  return -1;
1040  }
1041 
1042  //Startup the I/O signal handling thread
1043  if(start_signal_catcher(true) != 0)
1044  {
1045  ERROR_REPORT("Error starting signal catching thread.");
1046  return -1;
1047  }
1048 
1049  //Now Block all I/O signals in this thread.
1050  if(block_sigio() != 0)
1051  {
1052  ERROR_REPORT("Error blocking SIGIO in main thread.");
1053  return -1;
1054  }
1055 
1056  LOG_INFO("starting up . . .");
1057 
1058  joe_loading = 0;
1059 
1060  while(!TimeToDie)
1061  {
1062 
1063  if(joe_loading)
1064  {
1065  void * thrdretval;
1066 
1067  if(pthread_tryjoin_np(load_thread, &thrdretval) == 0)
1068  {
1069  joe_loading = 0;
1070  if(*((int *) thrdretval) != 0)
1071  {
1072  error_report(Logger::LOG_LEV_ERROR, "Program load thread returned error.");
1073  }
1074  }
1075 
1076  }
1077 
1078  if(!joe_loading)
1079  {
1080  if(DoFSM() != 0 && cur_State != STATE_NOCONNECTION) //don't report if we just aren't connected.
1081  {
1082  error_report(Logger::LOG_LEV_ERROR, "Error in DoFSM.");
1083  }
1084  }
1085 
1086 
1087  t0 = get_curr_time();
1088 
1089  while((dt = get_curr_time() - t0) < pause_time && !TimeToDie)
1090  {
1091  //check_fifo_list_RTpending();
1092  if(pause_time - dt >= 1) sleep((int)(pause_time - dt));
1093  else usleep((int)((pause_time-dt)*1e6 * .99));
1094 
1095  }
1096  //update_statusboard();
1097  }
1098  return 0;
1099 }//int CCD47Ctrl::Run()
1100 
1101 int CCD47Ctrl::load_EDT_config(std::string fname)
1102 {
1103 #ifndef NOPDV
1104  std::string visao_root;
1105  std::string edt_dir;
1106  std::string cfgtmp, bittmp;
1107 
1108  //visao_root = getenv("VISAO_ROOT");
1109  edt_dir = getenv("EDTDIR");
1110 
1111  cfgtmp = Utils::getConffile(EDT_cfgdir);
1112  int idx = cfgtmp.find(".conf");
1113  if(idx > -1) cfgtmp.erase(idx, cfgtmp.length()-idx);
1114 
1115  cfgtmp = cfgtmp + fname; //visao_root + "/" + EDT_cfgdir + "/" + fname;
1116  bittmp = edt_dir + "/camera_config";
1117 
1118  #ifdef _debug
1119  std::cout << "Loading EDT Config\n" << cfgtmp << "\n" << bittmp << "\n";
1120  #endif
1121 
1122  return initcam(cfgtmp.c_str(), bittmp.c_str());
1123 #endif
1124 
1125  return 0;
1126 }//int CCD47Ctrl::load_EDT_config(std::string fname)
1127 
1128 std::string CCD47Ctrl::remote_command(std::string com)
1129 {
1130  return common_command(com, CMODE_REMOTE);
1131 }
1132 
1133 std::string CCD47Ctrl::local_command(std::string com)
1134 {
1135  return common_command(com, CMODE_LOCAL);
1136 }
1137 
1138 std::string CCD47Ctrl::script_command(std::string com)
1139 {
1140  return common_command(com, CMODE_SCRIPT);
1141 }
1142 
1143 std::string CCD47Ctrl::common_command(std::string com, int cmode)
1144 {
1145  std::string resp;
1146  char rstr[50];
1147  int rv;
1148 
1149  if(com == "state?")
1150  {
1151  int cstate = 0;
1152  if(cur_State == STATE_READY) cstate = 1;
1153  if(cur_State == STATE_OPERATING) cstate = 2;
1154  if(cur_State == STATE_CONFIGURING) cstate = 3;
1155  snprintf(rstr, 50, "%c %i\n", control_mode_response()[0], cstate);
1156  return rstr;
1157  }
1158 
1159  if(com == "set?")
1160  {
1161  snprintf(rstr, 50, "%i\n", cur_ProgramSet);
1162  return rstr;
1163  }
1164 
1165  if(com == "prog?")
1166  {
1167  snprintf(rstr, 50, "%i\n", cur_Program);
1168  return rstr;
1169  }
1170 
1171  if(com == "speed?")
1172  {
1173  snprintf(rstr, 50, "%i\n", cur_speed);
1174  return rstr;
1175  }
1176 
1177  if(com == "gain?")
1178  {
1179  snprintf(rstr, 50, "%i\n", cur_Gain);
1180  return rstr;
1181  }
1182 
1183  if(com == "xbin?")
1184  {
1185  snprintf(rstr, 50, "%i\n", cur_xbin);
1186  return rstr;
1187  }
1188 
1189  if(com == "ybin?")
1190  {
1191  snprintf(rstr, 50, "%i\n", cur_ybin);
1192  return rstr;
1193  }
1194 
1195  if(com == "windowx?")
1196  {
1197  snprintf(rstr, 50, "%i\n", cur_windowx);
1198  return rstr;
1199  }
1200 
1201  if(com == "windowy?")
1202  {
1203  snprintf(rstr, 50, "%i\n", cur_windowy);
1204  return rstr;
1205  }
1206 
1207  if(com == "framerate?")
1208  {
1209  snprintf(rstr, 50, "%f\n", cur_framerate);
1210  return rstr;
1211  }
1212 
1213  if(com == "rep?")
1214  {
1215  snprintf(rstr, 50, "%i\n", cur_Reps);
1216  return rstr;
1217  }
1218 
1219  if(com == "temps?")
1220  {
1221  snprintf(rstr, 50, "%06.2f %06.2f %06.2f\n", temps[0], temps[1], temps[2]);
1222  return rstr;
1223  }
1224 
1225  if(com == "blacks?")
1226  {
1227  snprintf(rstr, 50, "%04i %04i\n", blackLevel[0], blackLevel[1]);
1228  return rstr;
1229  }
1230 
1231  if(com == "start")
1232  {
1233  if(control_mode == cmode)
1234  {
1235  rv = Start();
1236  snprintf(rstr, 50, "%i\n", rv);
1237  return rstr;
1238  }
1239  else return control_mode_response();
1240  }
1241 
1242  if(com == "stop")
1243  {
1244  if(control_mode == cmode)
1245  {
1246  rv = Stop();
1247  snprintf(rstr, 50, "%i\n", rv);
1248  return rstr;
1249  }
1250  else return control_mode_response();
1251  }
1252 
1253  if(com == "save?")
1254  {
1255  if(FGsaving) return "1\n";
1256  else return "0\n";
1257  }
1258 
1259  if(com == "remaining?")
1260  {
1261  snprintf(rstr, 50, "%i\n", FGremaining);
1262  return rstr;
1263  }
1264 
1265  if(com == "skip?")
1266  {
1267  snprintf(rstr, 50, "%i\n", FGskipping);
1268  return rstr;
1269  }
1270 
1271  if(com == "imtype?")
1272  {
1273  snprintf(rstr, 50, "%i\n", imtype);
1274  return rstr;
1275  }
1276 
1277  if(com == "subdir?")
1278  {
1279  return FWsubdir;
1280  }
1281 
1282  if(com.substr(0,4) == "skip")
1283  {
1284  if(cmode == control_mode)
1285  {
1286  int nsk = atoi(com.substr(5, com.length()-5).c_str());
1287  if(nsk < 0) nsk = 0;
1288  snprintf(rstr, 50, "skip %i", nsk);
1289  write_fifo_channel(FG_FIFO, "AUTO", 5, &resp);
1290  write_fifo_channel(FG_FIFO, rstr, strlen(rstr)+1, &resp);
1291  FGskipping = nsk;
1292  return resp;
1293  }
1294  else return control_mode_response();
1295  }
1296 
1297  if(com.substr(0,8) == "savedark")
1298  {
1299  if(cmode == control_mode)
1300  {
1301  int nsav = atoi(com.substr(9, com.length()-9).c_str());
1302 
1303  if(!fw47sb)
1304  {
1305  size_t sz;
1307  _logger->log( Logger::LOG_LEV_ERROR, "framewriter47 is not running. no images saved.");
1308  if(!fw47sb) return "-2\n";
1309  }
1310 
1311  if(get_curr_time() - ts_to_curr_time(&fw47sb->last_update) > 3.*fw47sb->max_update_interval)
1312  {
1313  _logger->log( Logger::LOG_LEV_ERROR, "framewriter47 appears to not be running. no images saved.");
1314  return "-2\n";
1315  }
1316  if(nsav != 0)
1317  {
1318  FGremaining = nsav;
1319  set_imtype(2);
1320  snprintf(rstr, 50, "savedark %i", nsav);
1321  write_fifo_channel(FG_FIFO, "AUTO", 5, &resp);
1322  write_fifo_channel(FG_FIFO, rstr, strlen(rstr)+1, &resp);
1323  FGsaving = 1;
1324  return resp;
1325  }
1326 
1327  if(nsav == 0)
1328  {
1329  write_fifo_channel(FG_FIFO, "AUTO", 5, &resp);
1330  write_fifo_channel(FG_FIFO, "savedark 0", 11, &resp);
1331  FGsaving = 0;
1332  return resp;
1333  }
1334 
1335  return "0\n";
1336  }
1337  else return control_mode_response();
1338  }
1339 
1340  if(com.substr(0,4) == "save")
1341  {
1342  if(cmode == control_mode)
1343  {
1344  int nsav = atoi(com.substr(5, com.length()-5).c_str());
1345 
1346  if(!fw47sb)
1347  {
1348  size_t sz;
1350  _logger->log( Logger::LOG_LEV_ERROR, "framewriter47 is not running. no images saved.");
1351  if(!fw47sb) return "-2\n";
1352  }
1353 
1354  if(get_curr_time() - ts_to_curr_time(&fw47sb->last_update) > 3.*fw47sb->max_update_interval)
1355  {
1356  _logger->log( Logger::LOG_LEV_ERROR, "framewriter47 appears to not be running. no images saved.");
1357  return "-2\n";
1358  }
1359  if(nsav != 0)
1360  {
1361  FGremaining = nsav;
1362  snprintf(rstr, 50, "save %i", nsav);
1363  write_fifo_channel(FG_FIFO, "AUTO", 5, &resp);
1364  write_fifo_channel(FG_FIFO, rstr, strlen(rstr)+1, &resp);
1365  FGsaving = 1;
1366  return resp;
1367  }
1368 
1369  if(nsav == 0)
1370  {
1371  write_fifo_channel(FG_FIFO, "AUTO", 5, &resp);
1372  write_fifo_channel(FG_FIFO, "save 0", 7, &resp);
1373  FGsaving = 0;
1374  return resp;
1375  }
1376 
1377  return "0\n";
1378  }
1379  else return control_mode_response();
1380  }
1381 
1382  if(com.substr(0,5) == "serve")
1383  {
1384  if(cmode == control_mode)
1385  {
1386  int nsrv = atoi(com.substr(6, com.length()-6).c_str());
1387 
1388 // if(!fw47sb)
1389 // {
1390 // size_t sz;
1391 // fw47sb = (VisAO::filterwheel_status_board*) attach_shm(&sz, 7100, 0);
1392 // _logger->log( Logger::LOG_LEV_ERROR, "framewriter47 is not running. no images saved.");
1393 // if(!fw47sb) return "-2\n";
1394 // }
1395 
1396 // if(get_curr_time() - ts_to_curr_time(&fw47sb->last_update) > 3.*fw47sb->max_update_interval)
1397 // {
1398 // _logger->log( Logger::LOG_LEV_ERROR, "framewriter47 appears to not be running. no images saved.");
1399 // return "-2\n";
1400 // }
1401  if(nsrv != 0)
1402  {
1403  snprintf(rstr, 50, "serve %i", nsrv);
1404  write_fifo_channel(FG_FIFO, "AUTO", 5, &resp);
1405  write_fifo_channel(FG_FIFO, rstr, strlen(rstr)+1, &resp);
1406  FGsaving = 1;
1407  return resp;
1408  }
1409 
1410  if(nsrv == 0)
1411  {
1412  write_fifo_channel(FG_FIFO, "AUTO", 5, &resp);
1413  write_fifo_channel(FG_FIFO, "serve 0", 7, &resp);
1414  FGsaving = 0;
1415  return resp;
1416  }
1417 
1418  return "0\n";
1419  }
1420  else return control_mode_response();
1421  }
1422 
1423  if(com.substr(0,3) == "set")
1424  {
1425  if(control_mode == cmode)
1426  {
1427  if(com.length() < 11)
1428  {
1429  return "not enough arguments in set";
1430  }
1431 
1432  int ns, np, ng, nrep;
1433 
1434  ns = atoi(com.substr(4,1).c_str());
1435  np = atoi(com.substr(6,1).c_str());
1436  ng = atoi(com.substr(8,1).c_str());
1437  nrep = atoi(com.substr(10, com.length() - 10).c_str());
1438 
1439  #ifdef _debug
1440  std::cout << "Reprogram: " << ns << " " << np << " " << ng << " " << nrep << "\n";
1441  #endif
1442  ReprogramJoe(ns, np, ng, nrep, 0);
1443 
1444  return "1\n";
1445  }
1446  else return control_mode_response();
1447  }
1448 
1449  if(com.substr(0,4) == "reps")
1450  {
1451  if(control_mode == cmode)
1452  {
1453  if(com.length() < 5)
1454  {
1455  return "not enough arguments in reps";
1456  }
1457 
1458  int ns, np, ng, nrep;
1459 
1460  ns = cur_ProgramSet;
1461  np = cur_Program;
1462  ng = cur_Gain;
1463  nrep = atoi(com.substr(4, com.length() - 4).c_str());
1464 
1465  #ifdef _debug
1466  std::cout << "Reprogram: " << ns << " " << np << " " << ng << " " << nrep << "\n";
1467  #endif
1468  ReprogramJoe(ns, np, ng, nrep, 0);
1469 
1470  return "1\n";
1471  }
1472  else return control_mode_response();
1473  }
1474 
1475 
1476  if(com.substr(0,9) == "framerate")
1477  {
1478  if(control_mode == cmode)
1479  {
1480  if(com.length() < 10)
1481  {
1482  return "not enough arguments in framerate";
1483  }
1484 
1485  int ns, np, ng, nrep;
1486 
1487  ns = cur_ProgramSet;
1488  np = cur_Program;
1489  ng = cur_Gain;
1490  nrep = ComputeRepsFrameRate(strtod(com.substr(9, com.length() - 9).c_str(),0));
1491 
1492  #ifdef _debug
1493  std::cout << "Reprogram: " << ns << " " << np << " " << ng << " " << nrep << "\n";
1494  #endif
1495  ReprogramJoe(ns, np, ng, nrep, 0);
1496 
1497  return "1\n";
1498  }
1499  else return control_mode_response();
1500  }
1501 
1502  if(com.substr(0,7) == "exptime")
1503  {
1504  if(control_mode == cmode)
1505  {
1506  if(com.length() < 8)
1507  {
1508  return "not enough arguments in exptime";
1509  }
1510 
1511  int ns, np, ng, nrep;
1512 
1513  ns = cur_ProgramSet;
1514  np = cur_Program;
1515  ng = cur_Gain;
1516  nrep = ComputeRepsExpTime(strtod(com.substr(8, com.length() - 8).c_str(),0));
1517 
1518  #ifdef _debug
1519  std::cout << "Reprogram: " << ns << " " << np << " " << ng << " " << nrep << "\n";
1520  #endif
1521  ReprogramJoe(ns, np, ng, nrep, 0);
1522 
1523  return "1\n";
1524  }
1525  else return control_mode_response();
1526  }
1527 
1528  if(com.substr(0,4) == "fset")
1529  {
1530  if(control_mode == cmode)
1531  {
1532  if(com.length() < 12)
1533  {
1534  return "not enough arguments in fset";
1535  }
1536 
1537  int ns, np, ng, nrep;
1538 
1539  ns = atoi(com.substr(5,1).c_str());
1540  np = atoi(com.substr(7,1).c_str());
1541  ng = atoi(com.substr(9,1).c_str());
1542  nrep = atoi(com.substr(11, com.length() - 10).c_str());
1543  #ifdef _debug
1544  std::cout << "Force Reprogram: " << ns << " " << np << " " << ng << " " << nrep << "\n";
1545  #endif
1546  ReprogramJoe(ns, np, ng, nrep, 1);
1547 
1548  return "1\n";
1549  }
1550  else return control_mode_response();
1551  }
1552 
1553  if(com.substr(0,5) == "swset")
1554  {
1555  if(control_mode == cmode)
1556  {
1557  if(com.length() < 13)
1558  {
1559  return "not enough arguments in swset";
1560  }
1561 
1562  int ns, np, ng, nrep;
1563 
1564  ns = atoi(com.substr(6,1).c_str());
1565  np = atoi(com.substr(8,1).c_str());
1566  ng = atoi(com.substr(10,1).c_str());
1567  nrep = atoi(com.substr(12, com.length() - 10).c_str());
1568  #ifdef _debug
1569  std::cout << "SW only Reprogram: " << ns << " " << np << " " << ng << " " << nrep << "\n";
1570  #endif
1571  swonly_reprogram(ns, np, ng, nrep);
1572 
1573  return "1\n";
1574  }
1575  else return control_mode_response();
1576  }
1577 
1578  if(com.substr(0,5) == "black")
1579  {
1580  if(control_mode == cmode)
1581  {
1582  if(com.length() < 9)
1583  {
1584  return "not enough arguments to set black\n";
1585  }
1586 
1587  int bchan, blev;
1588 
1589  bchan = atoi(com.substr(6,1).c_str());
1590 
1591  if(bchan <0 || bchan > 1) return "-1\n";
1592 
1593  blev = atoi(com.substr(8,4).c_str());
1594 
1595  if(blev < 0) blev = 0;
1596  if(blev > 1023) blev = 1023;
1597 
1598  if(pthread_mutex_trylock(&reprogMutex) == 0)
1599  {
1600  #ifdef _debug
1601  std::cout << "Setting black: " << bchan << " " << blev << "\n";
1602  #endif
1603  if(blev != blackLevel[bchan]) SetJoeBlack(bchan, blev);
1604  pthread_mutex_unlock(&reprogMutex);
1605  return "0\n";
1606  }
1607  return "-1\n";
1608  }
1609  else return control_mode_response();
1610  }
1611 
1612  if(com.substr(0,6) == "subdir")
1613  {
1614  if(control_mode == cmode)
1615  {
1616  write_fifo_channel(FW_FIFO, "AUTO", 4, &resp);
1617  write_fifo_channel(FW_FIFO, com.c_str(), com.length(), &resp);
1618  return "0\n";
1619  }
1620  else return control_mode_response();
1621  }
1622 
1623  if(com.substr(0,4) == "dark")
1624  {
1625  if(control_mode == cmode)
1626  {
1627  write_fifo_channel(FG_FIFO, "AUTO", 4, &resp);
1628  write_fifo_channel(FG_FIFO, com.c_str(), com.length(), &resp);
1629  return "0\n";
1630  }
1631  else return control_mode_response();
1632  }
1633 
1634  if(com.substr(0,6) == "imtype")
1635  {
1636  if(com.length() >= 7)
1637  {
1638  if(control_mode == cmode)
1639  {
1640  int nsav = atoi(com.substr(7, com.length()-7).c_str());
1641  set_imtype(nsav);
1642  return "0\n";
1643  }
1644  else return control_mode_response();
1645  }
1646  }
1647 
1648  resp = "Unkown Command: " + com ;
1649  return resp;
1650 }//std::string CCD47Ctrl::common_command(std::string com, int cmode)
1651 
1652 
1654 {
1656  {
1658 
1660 
1661  csb->status = cur_State;
1662  csb->speed = cur_speed;
1663  csb->xbin = cur_xbin;
1664  csb->ybin = cur_ybin;
1665  csb->windowx = cur_windowx;
1666  csb->windowy = cur_windowy;
1667  csb->repetitions = cur_Reps;
1668  csb->framerate = cur_framerate;
1669  csb->gain = cur_Gain;
1670 
1671  csb->joe_temp = temps[0];
1672  csb->head_temp1 = temps[1];
1673  csb->head_temp2 = temps[2];
1674 
1675  csb->black0 = blackLevel[0];
1676  csb->black1 = blackLevel[1];
1677 
1678  csb->saving = FGsaving;
1679  csb->skipping = FGskipping;
1680  csb->remaining = FGremaining;
1681 
1682  csb->imtype = imtype;
1683 
1684  }
1685  return 0;
1686 }//int CCD47Ctrl::update_statusboard()
1687 
1688 int SetJoeRCL( int rcl)
1689 {
1690  char buffer[32];
1691  int cur_rcl, error;
1692 
1693  if(rcl < 0 || rcl > 31)
1694  {
1695  return -1;
1696  }
1697 
1698  error = SendJoeCommand("@RCL?", buffer, 31, 1);
1699  if (error != NO_ERROR)
1700  {
1701  return error;
1702  }
1703  cur_rcl = atoi(buffer+6);
1704 
1705  // If the selected program is already active, stop here
1706  if (cur_rcl == rcl)
1707  {
1708  return NO_ERROR;
1709  }
1710 
1711  sprintf( buffer, "@RCL %1d", rcl);
1712  if ((error = SendJoeCommand( buffer, NULL, 0, 0)) != NO_ERROR)
1713  {
1714  return error;
1715  }
1716 
1717  return error;
1718 }
1719 
1720 
1721 
1722 } //namespace VisAO
std::string EDT_cfg_fname
Name of the EDT config file for this program.
Definition: CCD47Ctrl.h:76
void Create(void)
Common creation tasks, called by constructors.
Definition: CCD47Ctrl.cpp:42
littlejoe_program ReadProgram(Config_File &cfg)
Read a configuration file with the parameters of a single LittleJoe program.
Definition: CCD47Ctrl.cpp:252
Config_File * adopt_cfg
The dictionary of config details from the adopt config file.
Definition: CCD47Ctrl.h:149
std::string adopt_cfg_file
Name of the adopt config file (this is specified in the main config file)
Definition: CCD47Ctrl.h:147
int black_levels[4]
Array of default black levels.
Definition: CCD47Ctrl.h:74
Holds the details of a little joe program set (i.e. a pattern/con file pair)
Definition: CCD47Ctrl.h:83
int load_EDT_config(std::string)
Loads the EDT configuration file.
Definition: CCD47Ctrl.cpp:1101
int FGrunning
Whether or not the framegrabber is running.
Definition: CCD47Ctrl.h:185
pthread_t load_thread
Identifier for the __ReprogramJoe thread.
Definition: CCD47Ctrl.h:286
int readout_speed
Program readout speed, pixel rate in khz.
Definition: CCD47Ctrl.h:64
double get_curr_time(void)
Gets the current CLOCK_REALTIME time, returns it in seconds to double precision.
Definition: libvisaoc.c:40
int cur_xbin
Current x binning.
Definition: CCD47Ctrl.h:211
virtual int start_signal_catcher(bool inherit_sched=true)
Starts the signal catching loop.
int joe_loading
Tells the main thread that the __ReprogramJoe thread is working.
Definition: CCD47Ctrl.h:296
int cur_State
Current state.
Definition: CCD47Ctrl.h:182
int _minRep
Minimum repetitions.
Definition: CCD47Ctrl.h:167
int _ccdDx
CCD x dimension.
Definition: CCD47Ctrl.h:160
The standalone VisAO application, does not interface with the AO Supervisor.
std::string control_filename
Name of the control file.
Definition: CCD47Ctrl.h:86
std::string FrameWriterName
Process name of the relevant framewriter.
Definition: CCD47Ctrl.h:174
int Stop(void)
Stop sequencing and stop the framegrabber.
Definition: CCD47Ctrl.cpp:287
int SetupNetwork(void)
Setup network connection with LittleJoe.
Definition: CCD47Ctrl.cpp:763
The controller for the VisAO CCD47 via its Little Joe.
Definition: CCD47Ctrl.h:128
basic_status_board * fw47sb
The Framewriter47 status board is used to check if framewriter is running before saving.
Definition: CCD47Ctrl.h:205
void * statusboard_shmemptr
The pointer to the shared memory block for the statusboard.
int cur_Program
The currently running program.
Definition: CCD47Ctrl.h:208
virtual void error_report(int LogLevel, std::string emsg)
Report an error. Also calls log_msg.
Logger * _tempsLogger
Temperature logger.
Definition: CCD47Ctrl.h:335
double cur_framerate
Current frame rate.
Definition: CCD47Ctrl.h:217
virtual int update_statusboard()
Update the status board.
virtual int setup_baseApp(bool usethreads=false)
Install fifo channels.
int FGremaining
How many saves are remaining.
Definition: CCD47Ctrl.h:193
virtual int update_statusboard()
Update the CCD47 Status Board shared memory.
Definition: CCD47Ctrl.cpp:1653
virtual std::string remote_command(std::string com)
Called by __remote_command after control state logic.
Definition: CCD47Ctrl.cpp:1128
int FGskipping
Whether or not the framegrabber is skipping, and how many frames to skip.
Definition: CCD47Ctrl.h:196
#define STATUS_framewriter47
Shared memory key for the ccd47 framewriter status board.
Definition: statusboard.h:45
std::vector< littlejoe_program > programs
Details of the individual programs.
Definition: CCD47Ctrl.h:88
virtual std::string local_command(std::string com)
Called by __local_command after control state logic.
Definition: CCD47Ctrl.cpp:1133
int cur_ProgramSet
The currently loaded program set.
Definition: CCD47Ctrl.h:207
int setup_fifo_list(int nfifos)
Allocate the fifo_list.
int cur_windowx
Current x window size.
Definition: CCD47Ctrl.h:213
int cur_ybin
Current y binning.
Definition: CCD47Ctrl.h:212
std::string get_ccdNetAddr()
Return the network address of the CCD.
Definition: CCD47Ctrl.h:301
int _ccdDefaultYbin
Default y binning.
Definition: CCD47Ctrl.h:177
pthread_mutex_t reprogMutex
Mutex for the __ReprogramJoe thread.
Definition: CCD47Ctrl.h:291
std::string name
Program name.
Definition: CCD47Ctrl.h:63
int DoFSM(void)
Performs controller functions and manages states.
Definition: CCD47Ctrl.cpp:931
int windowx
x window size
Definition: CCD47Ctrl.h:67
double temps[3]
Current temperatures.
Definition: CCD47Ctrl.h:218
key_t statusboard_shmemkey
The key used to lookup the shared memory.
int Start(void)
Start sequencing and start the framegrabber.
Definition: CCD47Ctrl.cpp:346
int SetJoeRCL(int rcl)
Set the recall "RCL" parameter on the little joe (pixel readout, gain & related settings) ...
Definition: CCD47Ctrl.cpp:1688
int ComputeRepsFrameRate(double fr)
Computes the reps required to match a requested framerate.
Definition: CCD47Ctrl.cpp:474
CCD47Ctrl(std::string name, const std::string &conffile)
Name and config file constructor.
Definition: CCD47Ctrl.cpp:32
int FirstJoeConfig(void)
Sets the LittleJoe controller in a known state.
Definition: CCD47Ctrl.cpp:384
virtual int block_sigio()
Sets the signal mask to block SIGIO and RTSIGIO.
virtual std::string script_command(std::string com)
Called by __script_command after control state logic.
Definition: CCD47Ctrl.cpp:1138
int TimeToDie
Global set by SIGTERM.
int imtype
0=science, 1=acquisition, 2=dark, 3=sky, 4=flat
Definition: statusboard.h:130
int _maxRep
Maximum repetitions.
Definition: CCD47Ctrl.h:168
std::string control_mode_response()
Convenience function to return the control type response string, e.g. "A\n".
int ReprogramJoe(int program_set, int program, int gain, int rep, int force=0)
Reprogram the little joe, including file uploads as necessary.
Definition: CCD47Ctrl.cpp:537
void * attach_shm(size_t *sz, key_t mkey, int shmemid)
Attach to a shared memory buffer and get its size.
Definition: libvisaoc.c:90
fifo_list fl
The list of named-pipe fifos used for inter-process comms.
int LoadJoeDiskFiles(void)
Load the configuration files specifying the different program sets that can be uploaded to LittleJoe...
Definition: CCD47Ctrl.cpp:193
int _ccdDefaultXbin
Default x binning.
Definition: CCD47Ctrl.h:176
std::string common_command(std::string com, int cmode)
Called by all the command handlers, to perform common command processing.
Definition: CCD47Ctrl.cpp:1143
int windowy
y window size
Definition: CCD47Ctrl.h:68
int ComputeFramerate()
Computes the current framerate from the current state of LittleJoe control variables.
Definition: CCD47Ctrl.cpp:446
int _ccdDefaultBlack
Default black levels.
Definition: CCD47Ctrl.h:179
int set_imtype(int it)
Set the image type.
Definition: CCD47Ctrl.cpp:429
double pause_time
Time to pause during application main loop.
Definition: VisAOApp_base.h:84
int cur_speed
Current speed.
Definition: CCD47Ctrl.h:215
std::string _ccdNetAddr
CCD network address.
Definition: CCD47Ctrl.h:155
std::vector< littlejoe_programset > ondisk
Struct array representing files that can be uploaded to LittleJoe.
Definition: CCD47Ctrl.h:223
int ReadJoeStatus()
Check the LittleJoe CCD camera status.
Definition: CCD47Ctrl.cpp:794
Holds the details of one little joe program.
Definition: CCD47Ctrl.h:61
int ReadJoeTemps(void)
Read the LittleJoe CCD camera temperatures.
Definition: CCD47Ctrl.cpp:878
int create_statusboard(size_t sz)
Creates and attaches to the statusboard shared memory.
std::string EDT_cfgdir
EDT configuration files directory.
Definition: CCD47Ctrl.h:171
Declarations for the VisAO CCD47 controller.
int _maxNumBins
Maximum number of bins.
Definition: CCD47Ctrl.h:164
std::string getCompletePath(std::string filename)
Get the complete path of a program/pattern file.
Definition: CCD47Ctrl.cpp:918
int biny
y binning
Definition: CCD47Ctrl.h:66
int binx
x binning
Definition: CCD47Ctrl.h:65
double ts_to_curr_time(struct timespec *tsp)
Convert a timespec structure to double seconds.
Definition: libvisaoc.c:30
static int control_mode
The current control mode.
std::string FWsubdir
The current subdirectory of the framewriter.
Definition: CCD47Ctrl.h:199
int _ccdNetPort
The TCP/IP port of the CCD at its network address.
Definition: CCD47Ctrl.h:158
std::string pattern_filename
Name of the pattern file.
Definition: CCD47Ctrl.h:87
int _maxNumSpeeds
Maximum number of speeds.
Definition: CCD47Ctrl.h:163
virtual int install_sig_mainthread_catcher()
Install the SIG_MAINTHREAD signal catcher.
int cur_windowy
Current y window size.
Definition: CCD47Ctrl.h:214
int blackLevel[2]
Current blacklevels.
Definition: CCD47Ctrl.h:220
int initcam(const char *fname, const char *bdir)
A local version of initcam.
Definition: EDTutils.c:46
int FGsaving
Whether or not the framegrabber is saving, and how many to save.
Definition: CCD47Ctrl.h:190
int swonly_reprogram(int program_set, int program, int gain, int rep)
Only change the settings in this software, do not reprogram the little joe.
Definition: CCD47Ctrl.cpp:718
std::string FrameGrabberName
Process name of the relevant framegrabber.
Definition: CCD47Ctrl.h:173
int get_ccdNetPort()
Returns the TCP/IP port of the CCD at its network address.
Definition: CCD47Ctrl.h:304
int GetFramegrabberStatus()
Checks whether the framegrabber process is running, and what its current status is.
Definition: CCD47Ctrl.cpp:313
int cur_Gain
The currently loaded gain.
Definition: CCD47Ctrl.h:209
The namespace of VisAO software.
int imtype
Image type, 0=science (default), 1=acquisition, 2=dark, 3=sky.
Definition: CCD47Ctrl.h:202
int _ccdDy
CCD y dimension.
Definition: CCD47Ctrl.h:161
int __ReprogramJoe(int program_set, int program, int gain, int rep, int force=0)
This function does the actual reprogramming, based on the adopt version.
Definition: CCD47Ctrl.cpp:561
int cur_Reps
The currently loaded repetitions.
Definition: CCD47Ctrl.h:210
int _ccdBlacksNum
Number of blacks.
Definition: CCD47Ctrl.h:166
void init_VisAOApp()
Initialize the details of the VisAOApp.
Definition: CCD47Ctrl.cpp:140
littlejoe_programset ReadProgramSet(Config_File &cfg)
Read a configuration file with the parameters of a little Joe Program SET.
Definition: CCD47Ctrl.cpp:217
int _ccdDefaultSpeed
Default speed.
Definition: CCD47Ctrl.h:178
int ComputeRepsExpTime(double et)
Computes the reps required to match a requested exptime.
Definition: CCD47Ctrl.cpp:495
std::string name
Name of the program set.
Definition: CCD47Ctrl.h:85
#define RWBUFF_SZ
The size of the i/o buffer.
Definition: fifoutils.h:43
std::string _ccdName
CCD name.
Definition: CCD47Ctrl.h:152
#define STATUS_ccd47
Shared memory key for the ccd47 controller status board.
Definition: statusboard.h:41
void * ReprogramJoeThreadWorker(void *adata)
This is the thread start function for reprogramming the little joe.
Definition: CCD47Ctrl.cpp:519
int Run()
Overriden virtual function, called by Exec().
Definition: CCD47Ctrl.cpp:1030
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.