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