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
48 ts5_log(TS5_LOGLEVEL_6,
"%s: ts5_check_parport\n", calling_function);
55 ts5_fatal(
"%s: parport subsystem is already running. ",
56 "This function has to be called before the (automatic) ",
57 "installation of the parallel port system.\n",
75 ts5_log(TS5_LOGLEVEL_6,
"%s: ts5_check_parport2\n", calling_function);
100 ts5_log(TS5_LOGLEVEL_1,
"%s: Installing Tscope5 parport\n",
106 ts5_fatal(
"%s: parallel port boxes not supported on Mac OS X\n",
112 if (!(hLib = LoadLibrary(
"inpout32.dll"))) {
113 ts5_fatal(
"%s: could not load inpout32.dll\n",
117 if (!(inb = (inbptr)GetProcAddress(hLib,
"Inp32"))) {
118 ts5_fatal(
"%s: could not get address for Inp32\n",
122 if (!(outb = (outbptr)GetProcAddress(hLib,
"Out32"))) {
123 ts5_fatal(
"%s: could not get address for Out32\n",
127 for (i=0; i<_ts5_status.timer.num_parports; i++) {
128 outb(_ts5_status.timer.parport_control_register[i], 0);
134 if (geteuid() != 0) {
135 ts5_fatal(
"%s: only root can open the parallel port.",
139 if (ioperm(_ts5_status.timer.parport_base_address[0], 3, 1)) {
140 ts5_fatal(
"%s: error opening parallell port 1.",
144 if (ioperm(_ts5_status.timer.parport_base_address[1], 3, 1)) {
145 ts5_fatal(
"%s: error opening parallell port 2.",
149 if (ioperm(_ts5_status.timer.parport_base_address[2], 3, 1)) {
150 ts5_fatal(
"%s: error opening parallell port 3.",
154 for (i=0; i<_ts5_status.timer.num_parports; i++) {
155 outb(0, _ts5_status.timer.parport_control_register[i]);
161 al_init_user_event_source(
162 &_ts5_data.timer.parport_response_event_source);
164 al_init_user_event_source(
165 &_ts5_data.timer.parport_trigger_event_source);
168 al_register_event_source(_ts5_data.timer.response_queue,
169 &_ts5_data.timer.parport_response_event_source);
171 al_register_event_source(_ts5_data.timer.trigger_queue,
172 &_ts5_data.timer.parport_trigger_event_source);
174 al_register_event_source(_ts5_data.timer.trigger_log,
175 &_ts5_data.timer.parport_trigger_event_source);
178 _ts5_data.timer.parport_thread =
181 al_start_thread(_ts5_data.timer.parport_thread);
184 TS5_TIMER_STATUS *timer = &_ts5_status.timer;
186 timer->num_parports = 3;
188 (TS5_PARPORT_STATUS *)al_malloc(
sizeof(TS5_PARPORT_STATUS)*
189 timer->num_parports);
191 for (i=0; i<timer->num_parports; i++) {
193 timer->parport[i].num_buttons = 5;
194 timer->parport[i].num_defined_buttons = 0;
195 timer->parport[i].num_active_buttons = 0;
196 timer->parport[i].button_debounce_time = 0.0;
198 timer->parport[i].status_register_current_state =
199 (
int *)al_malloc(
sizeof(
int)
200 * timer->parport[i].num_buttons);
202 timer->parport[i].status_register_previous_state =
203 (
int *)al_malloc(
sizeof(
int)
204 * timer->parport[i].num_buttons);
206 timer->parport[i].status_register_last_state_toggle_time =
207 (
double *)al_malloc(
sizeof(
double)
208 * timer->parport[i].num_buttons);
210 timer->parport[i].button_press_defined =
211 (
int *)al_malloc(
sizeof(
int)
212 * timer->parport[i].num_buttons);
214 timer->parport[i].button_press_active =
215 (
int *)al_malloc(
sizeof(
int)
216 * timer->parport[i].num_buttons);
218 timer->parport[i].button_release_defined =
219 (
int *)al_malloc(
sizeof(
int)
220 * timer->parport[i].num_buttons);
222 timer->parport[i].button_release_active =
223 (
int *)al_malloc(
sizeof(
int)
224 * timer->parport[i].num_buttons);
227 for (j=0; j<timer->parport[i].num_buttons; j++) {
228 timer->parport[i].status_register_current_state[j] = 0;
229 timer->parport[i].status_register_previous_state[j] = 0;
231 timer->parport[i].status_register_last_state_toggle_time[j] =
234 timer->parport[i].button_press_defined[j] = 0;
235 timer->parport[i].button_press_active[j] = 0;
236 timer->parport[i].button_release_defined[j] = 0;
237 timer->parport[i].button_release_active[j] = 0;
240 timer->parport[i].is_trigger_input_device = 0;
241 timer->parport[i].is_trigger_output_device = 0;
242 timer->parport[i].trigger_debounce_time = 0.0;
244 timer->parport[i].simulate_trigger_input = 0;
245 timer->parport[i].trigger_simulation_interval = 2.0;
247 timer->parport[i].last_trigger_simulation =
250 timer->parport[i].data_register_current_state = 0;
251 timer->parport[i].data_register_previous_state = 0;
252 timer->parport[i].trigger_output_time = 0.002;
271 ts5_log(TS5_LOGLEVEL_1,
"Uninstalling Tscope5 parport\n");
274 al_join_thread(_ts5_data.timer.parport_thread, NULL);
275 al_destroy_thread(_ts5_data.timer.parport_thread);
278 al_unregister_event_source(_ts5_data.timer.response_queue,
279 &_ts5_data.timer.parport_response_event_source);
281 al_unregister_event_source(_ts5_data.timer.trigger_queue,
282 &_ts5_data.timer.parport_trigger_event_source);
284 al_unregister_event_source(_ts5_data.timer.trigger_log,
285 &_ts5_data.timer.parport_trigger_event_source);
288 al_destroy_user_event_source(
289 &_ts5_data.timer.parport_response_event_source);
291 al_destroy_user_event_source(
292 &_ts5_data.timer.parport_trigger_event_source);
295 for (i=0; i<_ts5_status.timer.num_parports; i++) {
296 outb(_ts5_status.timer.parport_control_register[i], 0);
304 for (i=0; i<_ts5_status.timer.num_parports; i++) {
305 outb(0, _ts5_status.timer.parport_control_register[i]);
308 if (geteuid() != 0) {
310 "ts5_uninstall_parport",
311 "only root can close the parallel port");
314 if (ioperm(TS5_PARPORT_1_BASE, 3, 0)) {
316 "ts5_uninstall_parport",
317 "error closing parallell port 1");
320 if (ioperm(TS5_PARPORT_2_BASE, 3, 0)) {
322 "ts5_uninstall_parport",
323 "error closing parallell port 2");
326 if (ioperm(TS5_PARPORT_3_BASE, 3, 0)) {
328 "ts5_uninstall_parport",
329 "error closing parallell port 3");
334 TS5_TIMER_STATUS *timer = &_ts5_status.timer;
336 for (i=0; i<timer->num_parports; i++) {
338 al_free(timer->parport[i].status_register_current_state);
339 timer->parport[i].status_register_current_state = NULL;
341 al_free(timer->parport[i].status_register_previous_state);
342 timer->parport[i].status_register_previous_state = NULL;
344 al_free(timer->parport[i].status_register_last_state_toggle_time);
345 timer->parport[i].status_register_last_state_toggle_time = NULL;
347 al_free(timer->parport[i].button_press_defined);
348 timer->parport[i].button_press_defined = NULL;
350 al_free(timer->parport[i].button_press_active);
351 timer->parport[i].button_press_active = NULL;
353 al_free(timer->parport[i].button_release_defined);
354 timer->parport[i].button_release_defined = NULL;
356 al_free(timer->parport[i].button_release_active);
357 timer->parport[i].button_release_active = NULL;
360 al_free(timer->parport);
363 timer->num_parports = 0;
364 timer->parport_is_response_device = 0;
365 timer->parport_is_trigger_device = 0;
383 TS5_TIMER_STATUS *timer = &_ts5_status.timer;
385 if (!timer->parport[device-1].is_trigger_input_device) {
387 if (device<1 || device>timer->num_parports) {
390 "device argument is", device,
391 "number of parallel ports is", timer->num_parports);
394 if (timer->parport[device-1].num_defined_buttons) {
395 ts5_fatal(
"%s: %s %d %s\n", calling_function,
"parallel port",
396 device,
"is already defined as an response device");
399 if (timer->parport[device-1].is_trigger_output_device) {
400 ts5_fatal(
"%s: %s %d %s\n", calling_function,
"parallel port",
401 device,
"is already defined as a trigger output device");
404 timer->parport_is_trigger_device = 1;
405 timer->parport[device-1].is_trigger_input_device = 1;
408 outb(_ts5_status.timer.parport_control_register[device-1], 32);
410 #elif defined TS5_LINUX
411 outb(32, _ts5_status.timer.parport_control_register[device-1]);
429 TS5_TIMER_STATUS *timer = &_ts5_status.timer;
431 if (!timer->parport[device-1].is_trigger_output_device) {
433 if (device<1 || device>timer->num_parports) {
434 ts5_fatal(
"%s: %s %d, %s %d\n", calling_function,
435 "device argument is", device,
436 "number of parallel ports is", timer->num_parports);
439 if (timer->parport[device-1].num_defined_buttons) {
440 ts5_fatal(
"%s: %s %d %s\n", calling_function,
"parallel port",
441 device,
"is already defined as an response device");
444 if (timer->parport[device-1].is_trigger_input_device) {
445 ts5_fatal(
"%s: %s %d %s\n", calling_function,
"parallel port",
446 device,
"is already defined as a trigger input device");
449 timer->parport_is_trigger_device = 1;
450 timer->parport[device-1].is_trigger_output_device = 1;
453 outb(_ts5_status.timer.parport_control_register[device-1], 0);
455 #elif defined TS5_LINUX
456 outb(0, _ts5_status.timer.parport_control_register[device-1]);
471 ALLEGRO_EVENT parport_event;
472 double previous_time;
473 double current_time = al_get_time();
475 TS5_TIMER_STATUS *timer = &_ts5_status.timer;
477 while (!al_get_thread_should_stop(_ts5_data.timer.parport_thread)) {
480 for (i=0; i<timer->num_parports; i++) {
486 input = inb(_ts5_status.timer.parport_status_register[i]);
490 timer->parport[i].status_register_current_state[0] =
493 timer->parport[i].status_register_current_state[1] =
496 timer->parport[i].status_register_current_state[2] =
499 timer->parport[i].status_register_current_state[3] =
502 timer->parport[i].status_register_current_state[4] =
509 for (j=0; j<timer->parport[i].num_buttons; j++) {
511 if (timer->parport[i].status_register_current_state[j] !=
512 timer->parport[i].status_register_previous_state[j]) {
514 if (current_time - timer->parport[i]
515 .status_register_last_state_toggle_time[j] >
516 timer->parport[i].button_debounce_time) {
519 action = timer->parport[i]
520 .status_register_current_state[j];
522 timer->parport[i].status_register_previous_state[j] =
523 timer->parport[i].status_register_current_state[j];
526 .status_register_last_state_toggle_time[j] = current_time;
534 parport_event.user.type = TS5_EVENT_PARPORT_BUTTON_UP;
538 parport_event.user.type = TS5_EVENT_PARPORT_BUTTON_DOWN;
541 parport_event.user.data1 = i;
542 parport_event.user.data2 = button;
543 parport_event.user.data3 =
544 (intptr_t)((current_time-previous_time)*1000000.0);
547 &_ts5_data.timer.parport_response_event_source,
548 &parport_event, NULL);
556 input = inb(_ts5_status.timer.parport_data_register[i]);
560 timer->parport[i].data_register_current_state = input;
562 if (timer->parport[i].is_trigger_input_device &&
563 timer->parport[i].data_register_current_state &&
564 timer->parport[i].data_register_current_state !=
565 timer->parport[i].data_register_previous_state) {
568 - timer->parport[i].data_register_last_state_toggle_time
569 > timer->parport[i].trigger_debounce_time) {
571 parport_event.user.type = TS5_EVENT_PARPORT_TRIGGER;
573 parport_event.user.data1 = i;
575 parport_event.user.data2 =
576 (int)timer->parport[i].data_register_current_state;
578 parport_event.user.data3 =
579 (intptr_t)((current_time-previous_time)*1000000.0);
582 &_ts5_data.timer.parport_trigger_event_source,
583 &parport_event, NULL);
585 timer->parport[i].data_register_previous_state =
586 timer->parport[i].data_register_current_state;
588 timer->parport[i].data_register_last_state_toggle_time =
594 if (timer->parport[i].simulate_trigger_input) {
596 if (current_time - timer->parport[i].last_trigger_simulation
597 >= timer->parport[i].trigger_simulation_interval) {
599 parport_event.user.type = TS5_EVENT_PARPORT_TRIGGER;
601 parport_event.user.data1 = i;
603 parport_event.user.data2 =
604 timer->parport[i].simulate_trigger_input;
606 parport_event.user.data3 =
607 (intptr_t)((current_time-previous_time)*1000000.0);
610 &_ts5_data.timer.parport_trigger_event_source,
611 &parport_event, NULL);
613 timer->parport[i].last_trigger_simulation = current_time;
617 previous_time = current_time;
618 current_time = al_get_time();
int _ts5_is_tscope5_installed
Is Tscope5 installed?
int _ts5_is_parport_installed
Is the parport subsystem installed?
void ts5_check_parport2(char *calling_function)
Do some checks at the start of each parport function.
void ts5_set_parport_trigger_output(char *calling_function, int device)
Set the DATA register of the parallel port to output mode.
int _ts5_is_timer_installed
Is the timer subsystem installed?
void * ts5_parport_threadfunc()
Parallel port thread function.
void ts5_install_parport(char *calling_function)
Install the parport subsystem.
void ts5_check_parport(char *calling_function)
Do some checks at the start of each parport function.
void ts5_install_timer(char *calling_function)
Install the timer subsystem.
void ts5_log(const unsigned int level, const char *format,...)
Send info to a logging window.
void ts5_set_parport_trigger_input(char *calling_function, int device)
Set the DATA register of the parallel port to input mode.
void ts5_install_tscope5(char *calling_function)
Install Tscope5.
void ts5_fatal(const char *format,...)
Exit safely with an error message.
void ts5_uninstall_parport()
Uninstall the parport subsystem.