1 // lp_main.cpp   light panel main interface
2 
3 /* Copyright (c) 2007-2015, John Kichury
4 
5    This software is freely distributable free of charge and without license fees with the
6    following conditions:
7 
8    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
11    JOHN KICHURY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
12    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
13    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14 
15    The above copyright notice must be included in any copies of this software.
16 
17 */
18 
19 /* Fixed portability problems, March 2014, Udo Munk */
20 
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 
26 #include <pthread.h>
27 #include <sys/types.h>
28 #if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
29 #include <windows.h>
30 #else
31 #include <sys/signal.h>
32 #endif
33 #ifdef __linux__
34 #include <sys/prctl.h>
35 #endif
36 #include <sys/stat.h>
37 
38 #include "lpanel.h"
39 #include "lp_main.h"
40 #include "lp_utils.h"
41 
42 
43 //static pthread_mutex_t data_lock;
44 pthread_mutex_t data_lock;
45 pthread_mutex_t data_sample_lock;
46 extern pthread_mutex_t data_sample_lock;
47 
48 static thread_info_t thread_info;
49 static Lpanel *panel = new Lpanel;
50 static int samplecount = 0;
51 
52 void *
lp_mainloop_thread(void * n)53 lp_mainloop_thread(void *n)
54 {
55   int quit = 0;
56   double t1, t2;
57   int framecount = 0;
58 
59  //printf("mainloop thread starting\n");
60  thread_info.running = 1;
61  panel->openWindow("FrontPanel");
62 
63  t1 = frate_gettime();
64  framerate_start_frame();
65 
66  while(!quit)
67  {
68   // lock
69   pthread_mutex_lock(&data_lock);
70 
71   //  proc events
72 
73 //  panel->sampleData();
74   panel->procEvents();
75 
76   // draw
77 
78   pthread_mutex_lock(&data_sample_lock);
79   panel->draw();
80   pthread_mutex_unlock(&data_sample_lock);
81 
82   // unlock
83   pthread_mutex_unlock(&data_lock);
84 
85   // sleep remainder of fps time
86   glFinish();
87   framerate_wait();
88   t2 = frate_gettime();
89   framecount++;
90   framerate_start_frame();
91 
92   if(t2 - t1 > 1.0)
93    {
94      panel->frames_per_second = framecount;
95      panel->samples_per_second = samplecount;
96      t1 = frate_gettime();
97      framecount = 0;
98      samplecount = 0;
99    }
100 
101   if( !thread_info.run ) quit = 1;
102 
103  } // end while(!quit)
104   pthread_mutex_lock(&data_lock);
105   panel->Quit();
106   panel->destroyWindow();
107   pthread_mutex_unlock(&data_lock);
108   thread_info.running = 0;
109   return NULL;
110 }
111 
start_threads(void)112 int start_threads(void)
113 {
114   // don't use unitialised attr, use NULL pointer instead. **UM**
115   //static pthread_attr_t attr;
116   int n;
117 
118   pthread_mutex_init(&data_lock,NULL);
119   pthread_mutex_init(&data_sample_lock,NULL);
120   thread_info.run = 1;
121   //n = pthread_create(&thread_info.thread_id, &attr, lp_mainloop_thread, &thread_info.thread_no);
122   n = pthread_create(&thread_info.thread_id, NULL, lp_mainloop_thread, &thread_info.thread_no);
123   if(n)
124    { fprintf(stderr,"error %d starting mainloop thread\n",n);
125      return 0;
126    }
127 
128   //fprintf(stderr,"FrontPanel mainloop thread start (PID=%d)\n",thread_info.thread_id);
129 
130   return 1;
131 }
132 
133 // bind functions
134 
fp_bindLight64(char * name,uint64 * bits,int bitnum)135 int fp_bindLight64(char *name, uint64 *bits, int bitnum)
136 {
137 //printf("fp_bindLight64: name=%s *bits=%lx  bitnum=%d\n",name,*bits,bitnum);
138  panel->bindLight64(name,bits,bitnum);
139  return 1;
140 }
141 
fp_bindLight32(char * name,uint32 * bits,int bitnum)142 int fp_bindLight32(char *name, uint32 *bits, int bitnum)
143 {
144  panel->bindLight32(name,bits,bitnum);
145  return 1;
146 }
147 
fp_bindLight16(char * name,uint16 * bits,int bitnum)148 int fp_bindLight16(char *name, uint16 *bits, int bitnum)
149 {
150  panel->bindLight16(name,bits,bitnum);
151  return 1;
152 }
153 
fp_bindLightfv(char * name,float * bits)154 int fp_bindLightfv(char *name, float *bits)
155 {
156  panel->bindLightfv(name,bits);
157  return 1;
158 }
159 
fp_bindLight8(char * name,uint8 * bits,int bitnum)160 int fp_bindLight8(char *name, uint8 *bits, int bitnum)
161 {
162  panel->bindLight8(name,bits,bitnum);
163  return 1;
164 }
165 
fp_bindLight8invert(char * name,uint8 * bits,int bitnum,uint8 mask)166 int fp_bindLight8invert(char *name, uint8 *bits, int bitnum, uint8 mask)
167 {
168  panel->bindLight8invert(name,bits,bitnum, mask);
169  return 1;
170 }
171 
fp_bindLight16invert(char * name,uint16 * bits,int bitnum,uint16 mask)172 int fp_bindLight16invert(char *name, uint16 *bits, int bitnum, uint16 mask)
173 {
174  panel->bindLight16invert(name,bits,bitnum, mask);
175  return 1;
176 }
177 
fp_bindLight32invert(char * name,uint32 * bits,int bitnum,uint32 mask)178 int fp_bindLight32invert(char *name, uint32 *bits, int bitnum, uint32 mask)
179 {
180  panel->bindLight32invert(name,bits,bitnum, mask);
181  return 1;
182 }
183 
fp_bindLight64invert(char * name,uint64 * bits,int bitnum,uint64 mask)184 int fp_bindLight64invert(char *name, uint64 *bits, int bitnum, uint64 mask)
185 {
186  panel->bindLight64invert(name,bits,bitnum, mask);
187  return 1;
188 }
189 
fp_smoothLight(char * name,int nframes)190 int fp_smoothLight(char *name, int nframes)
191 {
192  panel->smoothLight(name,nframes);
193  return 1;
194 }
195 
fp_bindRunFlag(uint8 * addr)196 void fp_bindRunFlag(uint8 *addr)
197 {
198  panel->bindRunFlag(addr);
199 }
200 
fp_bindSimclock(uint64 * addr)201 void fp_bindSimclock( uint64 *addr)
202 {
203  panel->bindSimclock(addr);
204 }
205 
fp_bindSwitch8(char * name,uint8 * loc_down,uint8 * loc_up,int bitnum)206 int fp_bindSwitch8(char *name, uint8 *loc_down, uint8 *loc_up, int bitnum)
207 {
208  panel->bindSwitch8(name, loc_down, loc_up, bitnum);
209  return 1;
210 }
211 
fp_bindSwitch16(char * name,uint16 * loc_down,uint16 * loc_up,int bitnum)212 int fp_bindSwitch16(char *name, uint16 *loc_down, uint16 *loc_up, int bitnum)
213 {
214  panel->bindSwitch16(name, loc_down, loc_up, bitnum);
215  return 1;
216 }
217 
fp_bindSwitch32(char * name,uint32 * loc_down,uint32 * loc_up,int bitnum)218 int fp_bindSwitch32(char *name, uint32 *loc_down, uint32 *loc_up, int bitnum)
219 {
220  panel->bindSwitch32(name, loc_down, loc_up, bitnum);
221  return 1;
222 }
fp_bindSwitch64(char * name,uint64 * loc_down,uint64 * loc_up,int bitnum)223 int fp_bindSwitch64(char *name, uint64 *loc_down, uint64 *loc_up, int bitnum)
224 {
225  panel->bindSwitch64(name, loc_down, loc_up, bitnum);
226  return 1;
227 }
228 
fp_ignoreBindErrors(int n)229 void fp_ignoreBindErrors(int n)
230 { panel->ignoreBindErrors(n);
231 }
232 
fp_framerate(float v)233 void fp_framerate(float v)
234 {
235  if(panel) panel->framerate_set(v);
236  framerate_set(v);
237 }
238 
fp_init(char * cfg_fname)239 int fp_init(char *cfg_fname)
240 {
241   return (fp_init2(NULL, cfg_fname, 800));
242 }
243 
244 
fp_init2(char * cfg_root_path,char * cfg_fname,int size)245 int fp_init2(char *cfg_root_path, char *cfg_fname, int size)
246 {
247  printf("FrontPanel Simulator v2.1 Copyright (C) 2007-2015 by John Kichury\n");
248 #if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
249  printf("Windows version Copyright (C) 2014 by Stefano Bodrato\n");
250 #endif
251 
252  if(panel == NULL) panel = new Lpanel;
253 
254   // set a default framerate
255 
256   if(cfg_root_path) panel->setConfigRootPath(cfg_root_path);
257 
258   fp_framerate(30.);
259 
260   // set initial window size
261   panel->window_xsize = size;
262 
263   if(!panel->readConfig(cfg_fname))
264    { fprintf(stderr, "fp_init: error initializing the panel\n");
265      return 0;
266    }
267 
268   start_threads();
269   return 1;
270 }
271 
fp_openWindow(char * title)272 int  fp_openWindow(char *title)
273 {
274    start_threads();
275    return 1;
276 }
277 
fp_procEvents(void)278 void fp_procEvents(void)
279 {
280  panel->procEvents();
281 }
fp_draw(void)282 void fp_draw(void)
283 {
284  panel->draw();
285 }
286 
fp_sampleData(void)287 void fp_sampleData(void)
288 { panel->sampleData();
289   samplecount++;
290 }
291 
fp_sampleLightGroup(int groupnum,int clockwarp)292 void fp_sampleLightGroup(int groupnum, int clockwarp)
293 { panel->sampleLightGroup(groupnum, clockwarp);
294   samplecount++;
295 }
296 
fp_sampleSwitches(void)297 void fp_sampleSwitches(void)
298 { panel->sampleSwitches();
299 }
300 
301 // callback functions
302 
fp_addSwitchCallback(char * name,void (* cbfunc)(int state,int val),int userval)303 int fp_addSwitchCallback(char *name, void (*cbfunc)(int state, int val), int userval)
304 {
305  panel->addSwitchCallback(name, cbfunc, userval);
306  return 1;
307 }
308 
fp_addQuitCallback(void (* cbfunc)(void))309 void fp_addQuitCallback(void (*cbfunc)(void))
310 {
311  panel->addQuitCallback(cbfunc);
312 }
313 
fp_quit(void)314 void fp_quit(void)
315 {
316  int i, okay=0;
317 
318   pthread_mutex_lock(&data_lock);
319  thread_info.run = 0;
320   pthread_mutex_unlock(&data_lock);
321 
322  for(i=0;i<10;i++)
323   {
324   pthread_mutex_lock(&data_lock);
325     if(thread_info.running == 0)
326      {  okay = 1;
327 	break;
328      }
329   pthread_mutex_unlock(&data_lock);
330 #if defined (__MINGW32__) || defined (_WIN32) || defined (_WIN32_) || defined (__WIN32__)
331     Sleep(1000);
332 #else
333     sleep(1);
334 #endif
335   }
336 
337  if(!okay) fprintf(stderr, "Error. lightpanel draw thread did not terminate\n");
338 
339 }
340 
341 
342 int
fp_test(int n)343 fp_test(int n)
344 {
345  return(panel->test(n));
346 }
347 
348