14 #include "../include/tscope5/parport_internal.h"
15 #include "../include/tscope5/system_internal.h"
16 #include "../include/tscope5/timer_internal.h"
24 typedef short (_stdcall *inbptr)(
short portaddr);
25 typedef short (_stdcall *outbptr)(
short portaddr,
short value);
29 #elif defined TS5_LINUX
47 ts5_log(TS5_LOGLEVEL_6,
"%s: ts5_check_parport\n", calling_function);
72 ts5_log(TS5_LOGLEVEL_1,
"%s: Installing Tscope5 parport\n",
76 ts5_fatal(
"%s: parallel port boxes not supported on Mac OS X\n",
82 if (!(hLib = LoadLibrary(
"inpout32.dll"))) {
83 ts5_fatal(
"%s: could not load inpout32.dll\n",
87 if (!(inb = (inbptr)GetProcAddress(hLib,
"Inp32"))) {
88 ts5_fatal(
"%s: could not get address for Inp32\n",
92 if (!(outb = (outbptr)GetProcAddress(hLib,
"Out32"))) {
93 ts5_fatal(
"%s: could not get address for Out32\n",
97 outb((
short)TS5_PARPORT_1_CONTROL, 0);
98 outb((
short)TS5_PARPORT_2_CONTROL, 0);
99 outb((
short)TS5_PARPORT_3_CONTROL, 0);
104 if (geteuid() != 0) {
105 ts5_fatal(
"%s: only root can open the parallel port.",
109 if (ioperm(TS5_PARPORT_1_DATA, 3, 1)) {
110 ts5_fatal(
"%s: error opening parallell port 1.",
114 if (ioperm(TS5_PARPORT_2_DATA, 3, 1)) {
115 ts5_fatal(
"%s: error opening parallell port 2.",
119 if (ioperm(TS5_PARPORT_3_DATA, 3, 1)) {
120 ts5_fatal(
"%s: error opening parallell port 3.",
124 outb(0, (
short)TS5_PARPORT_1_CONTROL);
125 outb(0, (
short)TS5_PARPORT_2_CONTROL);
126 outb(0, (
short)TS5_PARPORT_3_CONTROL);
131 al_init_user_event_source(
132 &_ts5_data.timer.parport_response_event_source);
134 al_init_user_event_source(
135 &_ts5_data.timer.parport_trigger_event_source);
138 al_register_event_source(_ts5_data.timer.response_queue,
139 &_ts5_data.timer.parport_response_event_source);
141 al_register_event_source(_ts5_data.timer.trigger_queue,
142 &_ts5_data.timer.parport_trigger_event_source);
144 al_register_event_source(_ts5_data.timer.trigger_log,
145 &_ts5_data.timer.parport_trigger_event_source);
148 _ts5_data.timer.parport_thread =
151 al_start_thread(_ts5_data.timer.parport_thread);
154 TS5_TIMER_STATUS *timer = &_ts5_status.timer;
156 timer->num_parports = 3;
158 (TS5_PARPORT_STATUS *)al_malloc(
sizeof(TS5_PARPORT_STATUS)*
159 timer->num_parports);
162 for (i=0; i<timer->num_parports; i++) {
164 timer->parport[i].num_buttons = 5;
165 timer->parport[i].num_defined_buttons = 0;
166 timer->parport[i].num_active_buttons = 0;
167 timer->parport[i].button_debounce_time = 0.0;
169 timer->parport[i].status_register_current_state =
170 (
int *)al_malloc(
sizeof(
int)
171 * timer->parport[i].num_buttons);
173 timer->parport[i].status_register_previous_state =
174 (
int *)al_malloc(
sizeof(
int)
175 * timer->parport[i].num_buttons);
177 timer->parport[i].status_register_last_state_toggle_time =
178 (
double *)al_malloc(
sizeof(
double)
179 * timer->parport[i].num_buttons);
181 timer->parport[i].button_press_defined =
182 (
int *)al_malloc(
sizeof(
int)
183 * timer->parport[i].num_buttons);
185 timer->parport[i].button_press_active =
186 (
int *)al_malloc(
sizeof(
int)
187 * timer->parport[i].num_buttons);
189 timer->parport[i].button_release_defined =
190 (
int *)al_malloc(
sizeof(
int)
191 * timer->parport[i].num_buttons);
193 timer->parport[i].button_release_active =
194 (
int *)al_malloc(
sizeof(
int)
195 * timer->parport[i].num_buttons);
198 for (j=0; j<timer->parport[i].num_buttons; j++) {
199 timer->parport[i].status_register_current_state[j] = 0;
200 timer->parport[i].status_register_previous_state[j] = 0;
202 timer->parport[i].status_register_last_state_toggle_time[j] =
205 timer->parport[i].button_press_defined[j] = 0;
206 timer->parport[i].button_press_active[j] = 0;
207 timer->parport[i].button_release_defined[j] = 0;
208 timer->parport[i].button_release_active[j] = 0;
211 timer->parport[i].is_trigger_input_device = 0;
212 timer->parport[i].is_trigger_output_device = 0;
213 timer->parport[i].trigger_debounce_time = 0.0;
215 timer->parport[i].simulate_trigger_input = 0;
216 timer->parport[i].trigger_simulation_interval = 2.0;
218 timer->parport[i].last_trigger_simulation =
221 timer->parport[i].data_register_current_state = 0;
222 timer->parport[i].data_register_previous_state = 0;
223 timer->parport[i].trigger_output_time = 0.002;
240 ts5_log(TS5_LOGLEVEL_1,
"Uninstalling Tscope5 parport\n");
243 al_join_thread(_ts5_data.timer.parport_thread, NULL);
244 al_destroy_thread(_ts5_data.timer.parport_thread);
247 al_unregister_event_source(_ts5_data.timer.response_queue,
248 &_ts5_data.timer.parport_response_event_source);
250 al_unregister_event_source(_ts5_data.timer.trigger_queue,
251 &_ts5_data.timer.parport_trigger_event_source);
253 al_unregister_event_source(_ts5_data.timer.trigger_log,
254 &_ts5_data.timer.parport_trigger_event_source);
257 al_destroy_user_event_source(
258 &_ts5_data.timer.parport_response_event_source);
260 al_destroy_user_event_source(
261 &_ts5_data.timer.parport_trigger_event_source);
264 outb((
short)TS5_PARPORT_1_CONTROL, 0);
265 outb((
short)TS5_PARPORT_2_CONTROL, 0);
266 outb((
short)TS5_PARPORT_3_CONTROL, 0);
273 outb(0, (
short)TS5_PARPORT_1_CONTROL);
274 outb(0, (
short)TS5_PARPORT_2_CONTROL);
275 outb(0, (
short)TS5_PARPORT_3_CONTROL);
277 if (geteuid() != 0) {
279 "ts5_uninstall_parport",
280 "only root can close the parallel port");
283 if (ioperm(TS5_PARPORT_1_DATA, 3, 0)) {
285 "ts5_uninstall_parport",
286 "error closing parallell port 1");
289 if (ioperm(TS5_PARPORT_2_DATA, 3, 0)) {
291 "ts5_uninstall_parport",
292 "error closing parallell port 2");
295 if (ioperm(TS5_PARPORT_3_DATA, 3, 0)) {
297 "ts5_uninstall_parport",
298 "error closing parallell port 3");
303 TS5_TIMER_STATUS *timer = &_ts5_status.timer;
306 for (i=0; i<timer->num_parports; i++) {
308 al_free(timer->parport[i].status_register_current_state);
309 timer->parport[i].status_register_current_state = NULL;
311 al_free(timer->parport[i].status_register_previous_state);
312 timer->parport[i].status_register_previous_state = NULL;
314 al_free(timer->parport[i].status_register_last_state_toggle_time);
315 timer->parport[i].status_register_last_state_toggle_time = NULL;
317 al_free(timer->parport[i].button_press_defined);
318 timer->parport[i].button_press_defined = NULL;
320 al_free(timer->parport[i].button_press_active);
321 timer->parport[i].button_press_active = NULL;
323 al_free(timer->parport[i].button_release_defined);
324 timer->parport[i].button_release_defined = NULL;
326 al_free(timer->parport[i].button_release_active);
327 timer->parport[i].button_release_active = NULL;
330 al_free(timer->parport);
333 timer->num_parports = 0;
334 timer->parport_is_response_device = 0;
352 TS5_TIMER_STATUS *timer = &_ts5_status.timer;
354 if (!timer->parport[device-1].is_trigger_input_device) {
356 if (device<1 || device>timer->num_parports) {
359 "device argument is", device,
360 "number of parallel ports is", timer->num_parports);
363 if (timer->parport[device-1].num_defined_buttons) {
364 ts5_fatal(
"%s: %s %d %s\n", calling_function,
"parallel port",
365 device,
"is already defined as an response device");
368 if (timer->parport[device-1].is_trigger_output_device) {
369 ts5_fatal(
"%s: %s %d %s\n", calling_function,
"parallel port",
370 device,
"is already defined as a trigger output device");
373 timer->parport_is_trigger_device = 1;
374 timer->parport[device-1].is_trigger_input_device = 1;
377 short control_register[] =
378 {TS5_PARPORT_1_CONTROL,
379 TS5_PARPORT_2_CONTROL,
380 TS5_PARPORT_3_CONTROL};
385 outb((
short)control_register[device-1], 32);
387 #elif defined TS5_LINUX
388 outb(32, (
short)control_register[device-1]);
406 TS5_TIMER_STATUS *timer = &_ts5_status.timer;
408 if (!timer->parport[device-1].is_trigger_output_device) {
410 if (device<1 || device>timer->num_parports) {
411 ts5_fatal(
"%s: %s %d, %s %d\n", calling_function,
412 "device argument is", device,
413 "number of parallel ports is", timer->num_parports);
416 if (timer->parport[device-1].num_defined_buttons) {
417 ts5_fatal(
"%s: %s %d %s\n", calling_function,
"parallel port",
418 device,
"is already defined as an response device");
421 if (timer->parport[device-1].is_trigger_input_device) {
422 ts5_fatal(
"%s: %s %d %s\n", calling_function,
"parallel port",
423 device,
"is already defined as a trigger input device");
426 timer->parport_is_trigger_device = 1;
427 timer->parport[device-1].is_trigger_output_device = 1;
430 short control_register[] =
431 {TS5_PARPORT_1_CONTROL,
432 TS5_PARPORT_2_CONTROL,
433 TS5_PARPORT_3_CONTROL};
438 outb((
short)control_register[device-1], 0);
440 #elif defined TS5_LINUX
441 outb(0, (
short)control_register[device-1]);
456 ALLEGRO_EVENT parport_event;
457 double looptime = al_get_time();
459 TS5_TIMER_STATUS *timer = &_ts5_status.timer;
461 while (!al_get_thread_should_stop(_ts5_data.timer.parport_thread)) {
464 for (i=0; i<timer->num_parports; i++) {
472 short status_register[] =
473 {TS5_PARPORT_1_STATUS,
474 TS5_PARPORT_2_STATUS,
475 TS5_PARPORT_3_STATUS};
477 input = inb((
short)status_register[i]);
481 timer->parport[i].status_register_current_state[0] =
484 timer->parport[i].status_register_current_state[1] =
487 timer->parport[i].status_register_current_state[2] =
490 timer->parport[i].status_register_current_state[3] =
493 timer->parport[i].status_register_current_state[4] =
500 for (j=0; j<timer->parport[i].num_buttons; j++) {
502 if (timer->parport[i].status_register_current_state[j] !=
503 timer->parport[i].status_register_previous_state[j]) {
505 if (now - timer->parport[i]
506 .status_register_last_state_toggle_time[j] >
507 timer->parport[i].button_debounce_time) {
510 action = timer->parport[i]
511 .status_register_current_state[j];
513 timer->parport[i].status_register_previous_state[j] =
514 timer->parport[i].status_register_current_state[j];
517 .status_register_last_state_toggle_time[j] = now;
525 parport_event.user.type = TS5_EVENT_PARPORT_BUTTON_UP;
529 parport_event.user.type = TS5_EVENT_PARPORT_BUTTON_DOWN;
532 parport_event.user.data1 = i;
533 parport_event.user.data2 = button;
534 parport_event.user.data3 =
535 (intptr_t)((now-looptime)*1000000.0);
538 &_ts5_data.timer.parport_response_event_source,
539 &parport_event, NULL);
547 short data_register[] =
552 input = inb((
short)data_register[i]);
556 timer->parport[i].data_register_current_state = input;
558 if (timer->parport[i].is_trigger_input_device &&
559 timer->parport[i].data_register_current_state &&
560 timer->parport[i].data_register_current_state !=
561 timer->parport[i].data_register_previous_state) {
564 - timer->parport[i].data_register_last_state_toggle_time
565 > timer->parport[i].trigger_debounce_time) {
567 parport_event.user.type = TS5_EVENT_PARPORT_TRIGGER;
569 parport_event.user.data1 = i;
571 parport_event.user.data2 =
572 (int)timer->parport[i].data_register_current_state;
574 parport_event.user.data3 =
575 (intptr_t)((now-looptime)*1000000.0);
578 &_ts5_data.timer.parport_trigger_event_source,
579 &parport_event, NULL);
581 timer->parport[i].data_register_previous_state =
582 timer->parport[i].data_register_current_state;
584 timer->parport[i].data_register_last_state_toggle_time =
590 if (timer->parport[i].simulate_trigger_input) {
592 if (now - timer->parport[i].last_trigger_simulation
593 >= timer->parport[i].trigger_simulation_interval) {
595 parport_event.user.type = TS5_EVENT_PARPORT_TRIGGER;
597 parport_event.user.data1 = i;
599 parport_event.user.data2 =
600 timer->parport[i].simulate_trigger_input;
602 parport_event.user.data3 =
603 (intptr_t)((now-looptime)*1000000.0);
606 &_ts5_data.timer.parport_trigger_event_source,
607 &parport_event, NULL);
609 timer->parport[i].last_trigger_simulation = now;