The VisAO Camera
dioserver.cpp
Go to the documentation of this file.
1 /************************************************************
2 * dioserver.cpp
3 *
4 * Author: Jared R. Males (jrmales@email.arizona.edu)
5 *
6 * Definitions for the dioserver.
7 *
8 * Developed as part of the Magellan Adaptive Optics system.
9 ************************************************************/
10 
11 /** \file dioserver.cpp
12  * \author Jared R. Males
13  * \brief Definitions for the dioserver.
14  *
15 */
16 
17 #include "dioserver.h"
18 
20 
21 namespace VisAO
22 {
23 
24 dioserver::dioserver(int argc, char **argv) throw (AOException) : VisAOApp_standalone(argc, argv)
25 {
26  init_dioserver();
27 }
28 
29 dioserver::dioserver(std::string name, const std::string &conffile) throw (AOException) : VisAOApp_standalone(name, conffile)
30 {
31  init_dioserver();
32 }
33 
35 {
36  int i;
37  char chcfg[11];
38 
39  //Initialize the channel structures
40  for(i=0; i < DIO_CHANNELS; i++)
41  {
42  diosch[i].swchannel = i;
43  diosch[i].hwchannel = 0;
44  diosch[i].direction = 0;
45  diosch[i].enabled = 0;
46  diosch[i].dios = this;
47 
48  }
49  n_enabled = 0;
50 
51  std::string pathtmp;
52  std::string visao_root = getenv("VISAO_ROOT");
53 
54  //Set up the fifo_path
55  try
56  {
57  pathtmp = (std::string)(ConfigDictionary())["fifo_path"];
58  }
59  catch(Config_File_Exception)
60  {
61  pathtmp = "fifos";
62  }
63  fifo_path = visao_root + "/" + pathtmp + "/diofifo";
64 
65 
66  _logger->log(Logger::LOG_LEV_INFO, "Set dioserver fifo_path: %s", fifo_path.c_str());
67 
68  diocard_info = 0;
69  diocard_init = 0;
70  diocard_sd = 0;
71  diocard_write = 0;
72  diocard_read = 0;
73 
74  //Read the hardware channel config
75  int hwcfg, dircfg, encfg;
76  std::vector<std::string> chvec;
77 
78  for(i=0; i < DIO_CHANNELS; i++)
79  {
80  snprintf(chcfg, 11, "DIOCHAN_%02i", i);
81  try
82  {
83  chvec = (ConfigDictionary())[chcfg];
84  hwcfg = atoi(chvec[0].c_str());
85  dircfg = atoi(chvec[1].c_str());
86  encfg = atoi(chvec[2].c_str());
87  set_dioserver_channel(i, hwcfg, dircfg, encfg);
88  }
89  catch(Config_File_Exception)
90  {
91  //Don't do anything - just means the channel wasn't config-ed
92  }
93 
94  }
95 
96  //Init the status board
98  if(create_statusboard(sizeof(basic_status_board)) != 0)
99  {
101  _logger->log(Logger::LOG_LEV_ERROR, "Could not create status board.");
102  }
103  else
104  {
106  strncpy(bsb->appname, MyFullName().c_str(), 25);
107  bsb->max_update_interval = pause_time;
108  }
109 
110  return 0;
111 }//int dioserver::init_dioserver()
112 
113 int dioserver::set_dioserver_channel(int chnum, int hwchan, int dir, int enab)
114 {
115  diosch[chnum].hwchannel = hwchan;
116  diosch[chnum].direction = (dir != 0);
117  diosch[chnum].enabled = (enab != 0);
118  if(diosch[chnum].enabled) n_enabled++;
119  _logger->log(Logger::LOG_LEV_INFO, "Set dioserver channel %i: hw channel=%i dir=%i enab=%i", chnum, hwchan, dir, enab);
120  return 0;
121 }
122 
124 {
125  int i, j;
126  char rdfname[MAX_FNAME_SZ],wrfname[MAX_FNAME_SZ];
127 
128  //Setup the fifo_list
130  //Install the command fifos
131  setup_baseApp(1, 1,0,0, false);
132 
133  //Install the DIO fifos.
134  j = 0;
135  for(i = 0; i<DIO_CHANNELS; i++)
136  {
137  if(diosch[i].enabled)
138  {
139  snprintf(rdfname, MAX_FNAME_SZ, "%s_in_%02i", fifo_path.c_str(), i);
140  snprintf(wrfname, MAX_FNAME_SZ, "%s_out_%02i", fifo_path.c_str(), i);
141 
142  set_fifo_list_channel(&fl, j, RWBUFF_SZ, rdfname, wrfname, &read_diofifo, (void *)&(diosch[i]));
143  j++;
144  }
145  }
146 
147 
148  return 0;
149 }//int dioserver::setup_dioserver()
150 
151 
152 int read_diofifo(fifo_channel *fc)
153 {
154  static int ncalled = 0;
155 
156  int totbytes;
157  int xput, chnum;
158  char *rbuffer, wbuffer[RWBUFF_SZ];
159  struct timespec ts;
160  dioserver_ch * diosch;
161 
162  diosch = (dioserver_ch *) fc->auxdata;
163  chnum = diosch->swchannel;
164 
165 
166  fc->server_response[0] = '\0';
167  totbytes = read_fifo_channel(fc);
168  rbuffer = fc->server_response;
169 
170  if(totbytes == 0 || rbuffer[0] == '\0')
171  {
172  return 0;
173  }
174 
175  if(fc->seqmsg[0] && diosch->dios->get_use_profiler())
176  {
177  clock_gettime(CLOCK_REALTIME, &ts);
178  diosch->dios->get_profile()->logseqmsg(fc->seqmsg, "dio1", &ts);
179  }
180 
181  if(diosch->direction == 0)
182  {
183  xput = (rbuffer[0] != '0');
184 
185  diosch->dios->diocard_write(diosch->dios->diocard_info, chnum, xput);
186 
187  snprintf(wbuffer, RWBUFF_SZ, "%i", xput);
188  }
189  else
190  {
191  //read input here
192  xput = diosch->dios->diocard_read(diosch->dios->diocard_info, chnum);
193 
194  snprintf(wbuffer, RWBUFF_SZ, "%i", xput);
195  }
196 
197  if(fc->seqmsg[0] && diosch->dios->get_use_profiler())
198  {
199  clock_gettime(CLOCK_REALTIME, &ts);
200  diosch->dios->get_profile()->logseqmsg(fc->seqmsg, "dio2", &ts);
201  }
202 
203  write_fifo_channel(fc, wbuffer, strlen(wbuffer)+1);
204 
205  return 0;
206 }
207 
208 std::string dioserver::remote_command(std::string com)
209 {
210  if(com == "ping")
211  {
212  return "1";
213  }
214 
215  return "UNKOWN COMMAND: " + com + "\n";
216 }
217 
218 std::string dioserver::local_command(std::string com)
219 {
220  if(com == "ping")
221  {
222  return "1";
223  }
224 
225  return "UNKOWN COMMAND: " + com + "\n";
226 }
227 
229 {
230 
231  //Setup the dioserver
232  if(setup_dioserver() == 0)
233  {
234  _logger->log(Logger::LOG_LEV_INFO, "dioserver setup complete.");
235  }
236  else
237  {
238  _logger->log(Logger::LOG_LEV_ERROR, "error during dioserver setup.");
239  return -1;
240  }
241 
242  //Initialize the diocard
243  if(diocard_init(diocard_info) == 0)
244  {
245  _logger->log(Logger::LOG_LEV_INFO, "Initialized dio card.");
246  }
247  else
248  {
249  _logger->log(Logger::LOG_LEV_ERROR, "Dio card initialization failed.");
250  #ifdef NODIOCARD
251  _logger->log(Logger::LOG_LEV_WARNING, "DIO card initialization error checking disabled.");
252  std::cerr << "DIO card initialization error checking disabled." << "\n";
253  #else
254  return -1;
255  #endif
256  }
257 
258 
259  global_fifo_list = &fl;
260  signal(SIGIO, SIG_IGN);
261  if(connect_fifo_list_nolock() == 0)
262  {
263  _logger->log(Logger::LOG_LEV_INFO, "fifo_list connected.");
264  }
265  else
266  {
267  _logger->log(Logger::LOG_LEV_ERROR, "Error connecting the fifo list.");
268  return -1;
269  }
270  start_profiler();
271 
272  setup_RTsigio();
273 
274  _logger->log(Logger::LOG_LEV_INFO, "dioserver starting up . . .");
275 
276  //diocard_write(diocard_info, 9, 0);
277 
278  while(!TimeToDie)
279  {
280  if(fl.RTSIGIO_overflow)
281  {
282  //Do something here!
283  }
284  while(fl.tot_pending_reads > 0 && !TimeToDie)
285  {
287  pthread_cond_broadcast(&profile->thcond);
288  }
289 
290  //While there are no more pending reads, update the status board
292 
293  //sleep instead of pausing to make sure we keep the profile thread awake.
294  #ifdef VISAO_SIMDEV
295  sleep(1);
296  #else
297  usleep(signalth_sleeptime); //But not too long, so process doesn't get into too deep of a sleep.
298  //sleep(1); //This makes things sluggish.
299  #endif
300  pthread_cond_broadcast(&profile->thcond);
301 
302  }
303 
304  return 0;
305 }
306 
307 
308 } //namespace VisAO
309 
310 
311 
std::string local_command(std::string)
Overridden from VisAOApp_base::local_command.
Definition: dioserver.cpp:218
int fifo_list_do_pending_read(fifo_list *fl)
Runs through the pending reads, dispatching each handler in turn.
Definition: fifoutils.c:576
Declarations for the dioserver.
int write_fifo_channel(fifo_channel *fc, const char *com, int comlen)
Write data to the output channel.
Definition: fifoutils.c:194
dioserver_ch diosch[DIO_CHANNELS]
The channels being managed.
Definition: dioserver.h:82
fifo_list * global_fifo_list
The global fifo_list, for signal handling.
Definition: dioserver.cpp:19
int read_fifo_channel(fifo_channel *fc)
Read data from the input fifo channel.
Definition: fifoutils.c:246
dioserver * dios
Whether the channel is enabled or not. Disabled channels (enabled = 0) are ignored.
Definition: dioserver.h:50
int(* diocard_init)(void *)
Initialize the card.
Definition: dioserver.h:90
The standalone VisAO application, does not interface with the AO Supervisor.
std::string fifo_path
The base path names for the fifos.
Definition: dioserver.h:86
void * statusboard_shmemptr
The pointer to the shared memory block for the statusboard.
int(* diocard_sd)(void *)
Shutdown the card.
Definition: dioserver.h:91
A structure to hold a list of fifo_channels.
Definition: fifoutils.h:204
virtual int update_statusboard()
Update the status board.
virtual int setup_baseApp(bool usethreads=false)
Install fifo channels.
int init_dioserver()
Initialize the dioserver structure.
Definition: dioserver.cpp:34
int(* diocard_read)(void *card, int ch)
Read a bit from the channel.
Definition: dioserver.h:93
int setup_dioserver()
Setup the dioserver.
Definition: dioserver.cpp:123
int n_enabled
Number of channel enabled.
Definition: dioserver.h:83
int setup_fifo_list(int nfifos)
Allocate the fifo_list.
#define STATUS_dioserver
Shared memory key for the dioserver status board.
Definition: statusboard.h:71
int(* diocard_write)(void *card, int ch, int bit)
Write a bit to a channel.
Definition: dioserver.h:92
Holds the information for one digital I/O channel.
Definition: dioserver.h:44
key_t statusboard_shmemkey
The key used to lookup the shared memory.
int TimeToDie
Global set by SIGTERM.
dioserver(int argc, char **argv)
Command line constructor.
Definition: dioserver.cpp:24
fifo_list fl
The list of named-pipe fifos used for inter-process comms.
int RTSIGIO_overflow
flag indicating that the signal queue has overflown.
Definition: fifoutils.h:223
void * diocard_info
The generic DIO interface. This pointer is passed unaltered to the diocard_* functions.
Definition: dioserver.h:89
int read_diofifo(fifo_channel *fc)
Handler to read one of the dio channel fifos.
Definition: dioserver.cpp:152
double pause_time
Time to pause during application main loop.
Definition: VisAOApp_base.h:84
int set_dioserver_channel(int chnum, int hwchan, int dir, int enab)
Set a single channel of the server.
Definition: dioserver.cpp:113
int create_statusboard(size_t sz)
Creates and attaches to the statusboard shared memory.
#define MAX_FNAME_SZ
The maximum allowed filename length.
Definition: fifoutils.h:37
virtual int Run()
Take all the actions needed to start the server.
Definition: dioserver.cpp:228
int setup_RTsigio()
Setup SIGIO signal handling using realtime signals.
int connect_fifo_list_nolock()
Connect the fifo_list without exclusive locking.
int enabled
The direction, 0 for output, 1 for input.
Definition: dioserver.h:49
The namespace of VisAO software.
int hwchannel
The software channel number - used to access the channel via the dio fifos.
Definition: dioserver.h:47
std::string remote_command(std::string)
Overridden from VisAOApp_base::remote_command.
Definition: dioserver.cpp:208
int tot_pending_reads
The total number of pending reads.
Definition: fifoutils.h:215
int direction
The hardware channel number - used to access the diocard itself.
Definition: dioserver.h:48
#define RWBUFF_SZ
The size of the i/o buffer.
Definition: fifoutils.h:43
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