Tscope5
parport.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // __ ______
4 // / /_______________ ____ ___ / ____/
5 // / __/ ___/ ___/ __ \/ __ \/ _ \ /___ )
6 // / /_(__ ) /__/ /_/ / /_/ / __/ ____/ /
7 // \__/____/\___/\____/ .___/\___/ /_____/
8 // /_/
9 //
10 /// \file parport.c
11 /// Definitions of parallel port functions
12 /// \example parport01.c
13 /// \example parport02.c
14 /// \example parport03.c
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 
18 #include "../include/tscope5/parport.h"
19 #include "../include/tscope5/timer.h"
20 #include "../include/tscope5/parport_internal.h"
21 #include "../include/tscope5/system_internal.h"
22 
23 #ifdef TS5_WINDOWS
24  #include <windows.h>
25  HINSTANCE hLib;
26  typedef short (_stdcall *inbptr)(short portaddr);
27  typedef short (_stdcall *outbptr)(short portaddr, short value);
28  inbptr inb;
29  outbptr outb;
30 
31 #elif defined TS5_LINUX
32  #include <unistd.h>
33  #include <sys/io.h>
34 
35 #endif
36 
37 
38 ////////////////////////////////////////////////////////////////////////////////
39 /// @name Response registration
40 /// Parallel port boxes can be used as response devices.
41 /// See timer.c for more information about response registration.
42 //@{
43 ////////////////////////////////////////////////////////////////////////////////
44 
45 
46 ////////////////////////////////////////////////////////////////////////////////
47 /// Define a parallel port button as a response button.
48 ///
49 /// \param device Number of the parallel port (devices are numbered from 1).
50 /// \param button Number of the button (buttons are counted from 1).
51 ///
52 /// \return The reponse number associated with the button.
53 ///
54 /// Give a positive number for the button if you want to monitor button press events,
55 /// a negative number if you want to monitor button release events.
56 ////////////////////////////////////////////////////////////////////////////////
57 int ts5_define_parport_button(int device, int button)
58 {
59  ts5_check_parport("ts5_define_parport_button");
60  ts5_log(TS5_LOGLEVEL_3, "ts5_define_parport_button(%d,%d)\n", device, button);
61 
62  if (device<1 || device>_ts5_status.timer.num_parports) {
63  ts5_fatal("%s: %s %d %s %d\n", "ts5_define_parport_button",
64  "device argument is", device,
65  "number of parallel ports is",
66  _ts5_status.timer.num_parports);
67  }
68 
69  if (_ts5_status.timer.parport[device-1].is_trigger_input_device) {
70  ts5_fatal("%s: %s %d %s\n", "ts5_define_parport_button",
71  "parallel port", device,
72  "is already defined as a trigger input device");
73  }
74 
75  if (_ts5_status.timer.parport[device-1].is_trigger_output_device) {
76  ts5_fatal("%s: %s %d %s\n", "ts5_define_parport_button",
77  "parallel port", device,
78  "is already defined as a trigger output device");
79  }
80 
81  if (button==0) {
82  ts5_fatal("%s: %s\n", "ts5_define_parport_button",
83  "button argument is 0, response buttons are numbered from 1");
84  }
85 
86  if (abs(button)>_ts5_status.timer.parport[device-1].num_buttons) {
87  ts5_fatal("%s: %s %d, %s %d is %d\n", "ts5_define_parport_button",
88  "button argument is", button,
89  "number of parport buttons for device", device,
90  _ts5_status.timer.parport[device-1].num_buttons);
91  }
92 
93  if (button>0 && _ts5_status.timer.parport[device-1]
94  .button_press_defined[button-1]!=0) {
95  ts5_fatal("%s: %s %d %s\n", "ts5_define_parport_button",
96  "button press", button, "is already defined");
97  }
98 
99  if (button<0 && _ts5_status.timer.parport[device-1]
100  .button_release_defined[-button-1]!=0) {
101  ts5_fatal("%s: %s %d %s\n", "ts5_define_parport_button",
102  "button release", button, "is already defined");
103  }
104 
105  _ts5_status.timer.parport_is_response_device = 1;
106  _ts5_status.timer.num_defined_buttons++;
107  _ts5_status.timer.num_active_buttons++;
108  _ts5_status.timer.parport[device-1].num_defined_buttons++;
109  _ts5_status.timer.parport[device-1].num_active_buttons++;
110 
111  if (button>0) {
112  _ts5_status.timer.parport[device-1]
113  .button_press_defined[button-1] =
114  _ts5_status.timer.num_defined_buttons;
115 
116  _ts5_status.timer.parport[device-1]
117  .button_press_active[button-1] =
118  _ts5_status.timer.num_defined_buttons;
119  }
120  else {
121  _ts5_status.timer.parport[device-1]
122  .button_release_defined[-button-1] =
123  _ts5_status.timer.num_defined_buttons;
124 
125  _ts5_status.timer.parport[device-1]
126  .button_release_active[-button-1] =
127  _ts5_status.timer.num_defined_buttons;
128  }
129 
130  return _ts5_status.timer.num_defined_buttons;
131 }
132 
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// Get then number of parallel ports that are connected to the system.
136 ///
137 /// \return The number of parallel ports that are connected to the system.
138 ////////////////////////////////////////////////////////////////////////////////
140 {
141  ts5_check_parport("ts5_get_num_parports");
142  ts5_log(TS5_LOGLEVEL_4, "ts5_get_num_parports()\n");
143 
144  return _ts5_status.timer.num_parports;
145 }
146 
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 /// Get then number of buttons available on a parallel port.
150 ///
151 /// \param device Number of the parallel port (devices are numbered from 1).
152 ///
153 /// \return The number of buttons on the parallel port.
154 ////////////////////////////////////////////////////////////////////////////////
156 {
157  ts5_check_parport("ts5_get_num_parport_buttons");
158  ts5_log(TS5_LOGLEVEL_4, "ts5_get_num_parport_buttons(%d)\n", device);
159 
160  return _ts5_status.timer.parport[device-1].num_buttons;
161 }
162 
163 
164 ////////////////////////////////////////////////////////////////////////////////
165 /// Set the button debounce time of a parallel port response box.
166 ///
167 /// \param device Number of the parallel port
168 /// \param button_debounce_time Debounce time in seconds
169 ///
170 /// \return The previous setting
171 ///
172 ///
173 /// The debounce time is the minimum amount of time between two state changes of
174 /// the buttons of the box before Tscope5 really counts it as a state change.
175 /// On some button boxes it is necessary to set this value because
176 /// the press or release of a button causes a ripple in the electrical current
177 /// sent to the parallel port
178 /// (instead of a single state change between on and off).
179 ///
180 /// The debounce time is the amount of time between the press and the release
181 /// of a button (or vice versa).
182 /// So the minimum amount of time between two presses (or two releases)
183 /// will be twice the debounce time set here.
184 ///
185 /// The default debounce time is set to 0.0
186 /// (The button boxes at our department have an internal debouncing circuit).
187 ////////////////////////////////////////////////////////////////////////////////
189  double button_debounce_time)
190 {
191  ts5_check_parport("ts5_set_parport_button_debounce_time");
192  ts5_log(TS5_LOGLEVEL_4, "ts5_set_parport_button_debounce_time(%d,%f)\n",
193  device, button_debounce_time);
194 
195  if (device<1 || device>_ts5_status.timer.num_parports) {
196  ts5_fatal("%s: %s %d %s %d\n", "ts5_set_parport_button_debounce_time",
197  "device argument is", device,
198  "number of parallel ports is",
199  _ts5_status.timer.num_parports);
200  }
201 
202  if (button_debounce_time < 0.0) {
203  ts5_fatal("%s: %s (is %f)\n", "ts5_set_parport_button_debounce_time",
204  "debounce time should be positive", button_debounce_time);
205  }
206 
207  double retval =
208  _ts5_status.timer.parport[device-1].button_debounce_time;
209 
210  _ts5_status.timer.parport[device-1].button_debounce_time =
211  button_debounce_time;
212 
213  ts5_log(TS5_LOGLEVEL_4, "%s: %s %d to %f (was %f)\n",
214  "ts5_set_parport_button_debounce_time",
215  "set debounce time of device",
216  device,
217  _ts5_status.timer.parport[device-1].button_debounce_time,
218  retval);
219 
220  return retval;
221 }
222 
223 
224 ////////////////////////////////////////////////////////////////////////////////
225 /// Get the button debounce time of a parallel port response box.
226 ///
227 /// \param device Number of the parallel port
228 ///
229 /// \return The debounce time
230 ////////////////////////////////////////////////////////////////////////////////
232 {
233  ts5_check_parport("ts5_get_parport_button_debounce_time");
234  ts5_log(TS5_LOGLEVEL_4, "ts5_get_parport_button_debounce_time(%d)\n",
235  device);
236 
237  if (device<1 || device>_ts5_status.timer.num_parports) {
238  ts5_fatal("%s: %s %d %s %d\n", "ts5_get_parport_button_debounce_time",
239  "device argument is", device,
240  "number of parallel ports is",
241  _ts5_status.timer.num_parports);
242 
243  }
244 
245  return _ts5_status.timer.parport[device-1].button_debounce_time;
246 }
247 
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 //@}
251 ////////////////////////////////////////////////////////////////////////////////
252 
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 /// @name Trigger input/output
256 /// The parallel ports can be used as trigger input/output devices.
257 /// See timer.c for more information about trigger input/output.
258 //@{
259 ////////////////////////////////////////////////////////////////////////////////
260 
261 
262 ////////////////////////////////////////////////////////////////////////////////
263 /// Define a parallel port as a trigger input device
264 ///
265 /// \param device Number of the parallel port (devices are numbered from 1).
266 ////////////////////////////////////////////////////////////////////////////////
268 {
269  ts5_check_parport("ts5_define_parport_trigger_input");
270  ts5_log(TS5_LOGLEVEL_3, "ts5_define_parport_trigger_input(%d)\n", device);
271 
272  if (device<1 || device>_ts5_status.timer.num_parports) {
273  ts5_fatal("%s: %s %d %s %d\n", "ts5_define_parport_trigger_input",
274  "device argument is", device,
275  "number of parallel ports is",
276  _ts5_status.timer.num_parports);
277  }
278 
279  ts5_set_parport_trigger_input("ts5_define_parport_trigger_input", device);
280 }
281 
282 
283 ////////////////////////////////////////////////////////////////////////////////
284 /// Turn on parallel port input simulation.
285 ///
286 /// \param device Number of the parallel port (devices are numbered from 1).
287 /// \param value Input value that has to be simulated
288 /// (0-255, 0 turns the simulation off).
289 /// \param interval Interval in seconds between two triggers.
290 ////////////////////////////////////////////////////////////////////////////////
291 void ts5_simulate_parport_trigger_input(int device, unsigned char value,
292  double interval)
293 {
294  ts5_check_parport("ts5_simulate_parport_trigger_input");
295  ts5_log(TS5_LOGLEVEL_3, "ts5_simulate_parport_trigger_input(%d,%d,%f)\n",
296  device, value, interval);
297 
298  if (device<1 || device>_ts5_status.timer.num_parports) {
299  ts5_fatal("%s: %s %d %s %d\n", "ts5_simulate_parport_trigger_input",
300  "device argument is", device,
301  "number of parallel ports is",
302  _ts5_status.timer.num_parports);
303  }
304 
305  _ts5_status.timer.parport[device-1].simulate_trigger_input =
306  value;
307 
308  _ts5_status.timer.parport[device-1].trigger_simulation_interval =
309  interval;
310 }
311 
312 
313 ////////////////////////////////////////////////////////////////////////////////
314 /// Set the trigger debounce time of a parallel port.
315 ///
316 /// \param device Number of the parallel port
317 /// \param trigger_debounce_time Debounce time in seconds
318 ///
319 /// \return The previous setting
320 ///
321 /// The default debounce time is set to 0.0
322 ////////////////////////////////////////////////////////////////////////////////
324  double trigger_debounce_time)
325 {
326  ts5_check_parport("ts5_set_parport_trigger_debounce_time");
327  ts5_log(TS5_LOGLEVEL_4, "ts5_set_parport_trigger_debounce_time(%d,%f)\n",
328  device, trigger_debounce_time);
329 
330  if (device<1 || device>_ts5_status.timer.num_parports) {
331  ts5_fatal("%s: %s %d %s %d\n", "ts5_set_parport_trigger_debounce_time",
332  "device argument is", device,
333  "number of parallel ports is",
334  _ts5_status.timer.num_parports);
335  }
336 
337  if (trigger_debounce_time < 0.0) {
338  ts5_fatal("%s: %s (is %f)\n", "ts5_set_parport_trigger_debounce_time",
339  "debounce time should be positive", trigger_debounce_time);
340  }
341 
342  double retval = _ts5_status.timer.parport[device-1]
343  .trigger_debounce_time;
344 
345  _ts5_status.timer.parport[device-1].trigger_debounce_time =
346  trigger_debounce_time;
347 
348  ts5_log(TS5_LOGLEVEL_4, "%s: %s %d to %f (was %f)\n",
349  "ts5_set_parport_trigger_debounce_time",
350  "set debounce time of device",
351  device, _ts5_status.timer.parport[device-1]
352  .trigger_debounce_time, retval);
353 
354  return retval;
355 }
356 
357 
358 ////////////////////////////////////////////////////////////////////////////////
359 /// Get the trigger debounce time of a parallel port.
360 ///
361 /// \param device Number of the parallel port
362 ///
363 /// \return The debounce time
364 ////////////////////////////////////////////////////////////////////////////////
366 {
367  ts5_check_parport("ts5_get_parport_trigger_debounce_time");
368  ts5_log(TS5_LOGLEVEL_4, "ts5_get_parport_trigger_debounce_time(%d)\n",
369  device);
370 
371  if (device<1 || device>_ts5_status.timer.num_parports) {
372  ts5_fatal("%s: %s %d %s %d\n", "ts5_get_parport_trigger_debounce_time",
373  "device argument is", device,
374  "number of parallel ports is",
375  _ts5_status.timer.num_parports);
376  }
377 
378  return _ts5_status.timer.parport[device-1].trigger_debounce_time;
379 }
380 
381 
382 ////////////////////////////////////////////////////////////////////////////////
383 /// Send a trigger trough a parallel port
384 ///
385 /// \param device Number of the parallel port (devices are numbered from 1).
386 /// \param value The trigger value that has to be sent (0-255).
387 ////////////////////////////////////////////////////////////////////////////////
388 void ts5_send_parport_trigger(int device, unsigned char value)
389 {
390  ts5_check_parport("ts5_send_parport_trigger");
391  ts5_log(TS5_LOGLEVEL_3, "ts5_send_parport_trigger(%d,%d)\n", device, value);
392 
393  if (device<1 || device>_ts5_status.timer.num_parports) {
394  ts5_fatal("%s: %s %d %s %d\n", "ts5_send_parport_trigger",
395  "device argument is", device,
396  "number of parallel ports is",
397  _ts5_status.timer.num_parports);
398  }
399 
400  ts5_set_parport_trigger_output("ts5_send_parport_trigger", device);
401 
402  #ifndef TS5_MACOSX
403  short data_register[] = {TS5_PARPORT_1_DATA,
404  TS5_PARPORT_2_DATA,
405  TS5_PARPORT_3_DATA};
406 
407  #endif
408 
409  #ifdef TS5_WINDOWS
410  outb((short)data_register[device-1], value);
411 
412  ts5_wait(_ts5_status.timer.parport[device-1]
413  .trigger_output_time);
414 
415  outb((short)data_register[device-1], 0);
416 
417  #elif defined TS5_LINUX
418  outb(value, (short)data_register[device-1]);
419 
420  ts5_wait(_ts5_status.timer.parport[device-1]
421  .trigger_output_time);
422 
423  outb(0, (short)data_register[device-1]);
424 
425  #endif
426 }
427 
428 
429 ////////////////////////////////////////////////////////////////////////////////
430 /// Set the trigger output time of a parallel port.
431 ///
432 /// \param device Number of the parallel port
433 /// \param trigger_output_time Output time in seconds
434 ///
435 /// \return The previous setting
436 ///
437 /// The default output time is 0.002 seconds.
438 ////////////////////////////////////////////////////////////////////////////////
440  double trigger_output_time)
441 {
442  ts5_check_parport("ts5_set_parport_trigger_output_time");
443  ts5_log(TS5_LOGLEVEL_4, "ts5_set_parport_trigger_output_time(%d,%f)\n",
444  device, trigger_output_time);
445 
446  if (device<1 || device>_ts5_status.timer.num_parports) {
447  ts5_fatal("%s: %s %d %s %d\n", "ts5_set_parport_trigger_output_time",
448  "device argument is", device,
449  "number of parallel ports is",
450  _ts5_status.timer.num_parports);
451  }
452 
453  if (trigger_output_time < 0.0) {
454  ts5_fatal("%s: %s (is %f)\n", "ts5_set_parport_trigger_output_time",
455  "output time should be positive", trigger_output_time);
456  }
457 
458  double retval = _ts5_status.timer.parport[device-1]
459  .trigger_output_time;
460 
461  _ts5_status.timer.parport[device-1].trigger_output_time =
462  trigger_output_time;
463 
464  ts5_log(TS5_LOGLEVEL_4, "%s: %s %d to %f (was %f)\n",
465  "ts5_set_parport_trigger_output_time",
466  "set output time of device", device,
467  _ts5_status.timer.parport[device-1].trigger_output_time,
468  retval);
469 
470  return retval;
471 }
472 
473 
474 ////////////////////////////////////////////////////////////////////////////////
475 /// Get the trigger output time of a parallel port.
476 ///
477 /// \param device Number of the parallel port
478 ///
479 /// \return The output time
480 ////////////////////////////////////////////////////////////////////////////////
482 {
483  ts5_check_parport("ts5_get_parport_trigger_output_time");
484  ts5_log(TS5_LOGLEVEL_4, "ts5_get_parport_trigger_output_time(%d)\n",
485  device);
486 
487  if (device<1 || device>_ts5_status.timer.num_parports) {
488  ts5_fatal("%s: %s %d %s %d\n", "ts5_get_parport_trigger_output_time",
489  "device argument is", device,
490  "number of parallel ports is",
491  _ts5_status.timer.num_parports);
492  }
493 
494  return _ts5_status.timer.parport[device-1].trigger_output_time;
495 }
496 
497 
498 ////////////////////////////////////////////////////////////////////////////////
499 //@}
500 ////////////////////////////////////////////////////////////////////////////////