doc: add missing -lm option to command line for compiling tut1
[comedilib.git] / doc / tutorial.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3         "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4 <!ENTITY % comedilib_entities SYSTEM "comedilib.ent">
5 %comedilib_entities;
6 ]>
7
8 <section id="writingprograms" xmlns:xi="http://www.w3.org/2001/XInclude">
9   <title>
10     Writing &comedi; programs
11   </title>
12   <para>
13     This section describes how &comedi;
14     can be used in an application, to communicate data with a set
15     of &comedi; devices.
16     <xref linkend="acquisitionfunctions"/> gives more details about
17     the various acquisition functions with which the application
18     programmer can perform data acquisition in &comedi;.
19   </para>
20   <para>
21     Also don't forget to take a good look at the
22     <filename class="directory">demo</filename>
23     directory of the Comedilib source code. It contains lots of examples
24     for the basic functionalities of &comedi;.
25   </para>
26   
27   <section id="firstprogram">
28     <title>
29       Your first &comedi; program
30     </title>
31     
32     <para>
33       This example requires a card that has analog or digital input. This
34       progam opens the device, gets the data, and prints it out:
35       <programlisting>
36         <xi:include href="../demo/tut1.c" parse="text"/>
37       </programlisting>
38     </para>
39     <para>
40       The source code file for the above program can be found in Comedilib,
41       at <filename>demo/tut1.c</filename>.  You can compile the program using
42     </para>
43     
44     <screen>
45       cc tut1.c -lcomedi -lm -o tut1
46     </screen>
47     <para>
48       The
49       <function>
50         <link linkend="func-ref-comedi-open">comedi_open</link>
51       </function> call can only be successful if the
52       <filename>comedi0</filename> device file is configured with a
53       valid &comedi; driver. <xref linkend="cardconfiguration"/> explains
54       how this driver is linked to the <quote>device file</quote>.
55     </para>
56     <para>
57       The <parameter class="function">range</parameter> variable tells
58       &comedi; which gain to use when measuring an analog voltage.  Since we
59       don't know (yet) which numbers are valid, or what each means, we'll
60       use <literal>0</literal>, because it won't cause errors.  Likewise
61       with <parameter class="function">aref</parameter>, which determines the
62       analog reference used.
63     </para>
64   </section>
65
66
67   <section id="convertingsamples">
68     <title>
69       Converting between integer data and physical units
70     </title>
71     
72     <para>
73       If you selected an analog input subdevice, you probably noticed
74       that the output of <command>tut1</command> is an unsigned
75       number, for example between <literal>0</literal>
76       and <literal>65535</literal> for a 16 bit analog input. &comedi;
77       samples are unsigned, with <literal>0</literal> representing the
78       lowest voltage of the ADC, and a hardware-dependent maximum
79       value representing the highest voltage.  &comedi; compensates
80       for anything else the manual for your device says (for example,
81       many boards represent bipolar analog input voltages as signed
82       integers).  However, you probably prefer to have this number
83       translated to a voltage.  Naturally, as a good programmer, your
84       first question is: <quote>How do I do this in a
85       device-independent manner?</quote>
86     </para>
87     
88     <para>
89       The functions
90       <function><link linkend="func-ref-comedi-to-physical">comedi_to_physical</link></function>, <function><link linkend="func-ref-comedi-to-phys">comedi_to_phys</link></function>,
91       <function><link linkend="func-ref-comedi-from-physical">comedi_from_physical</link></function> and <function><link linkend="func-ref-comedi-from-phys">comedi_from_phys</link></function>
92       are used to convert between &comedi;'s integer data and floating point numbers corresponding
93       to physical values (voltages, etc.).
94     </para>
95     
96   </section>
97
98   <section id="secondprogram">
99     <title>
100       Your second &comedi; program
101     </title>
102     
103     
104     <para>
105       Actually, this is the first &comedi; program again, except
106       we've added code to convert the integer data value to physical units.
107     </para>
108     
109     <programlisting>
110       <xi:include href="../demo/tut2.c" parse="text"/>
111     </programlisting>
112     <para>
113       The source code file for the above program can be found in
114       the Comedilib source at <filename>demo/tut2.c</filename> and if
115       installed as a package usually at
116       <filename>/usr/share/doc/libcomedi-dev/demo/</filename> with all the
117       other tutorial/demo files.
118     </para>
119   </section>
120
121   <section id="asyncprogram">
122     <title>
123       Asynchronous acquisition
124     </title>
125     <para>
126       Of special importance is the so called
127       "asynchronous data acquisition" where &comedi; is sampling
128       in the background at a given sample rate. The
129       user can retrieve the data whenever it is convenient.
130       &comedi; stores the data in a ring-buffer so that
131       programs can perform other tasks in the foreground, for example
132       plotting data or interacting with the user. 
133       This technique is used in programs such
134       as <command>ktimetrace</command> or <command>comedirecord</command>.
135     </para>
136     <para>
137       There are two different ways how a sequence of channels is
138       measured during asynchronous acquisition (see also the Figure in
139       the introduction):
140     <itemizedlist>                
141       <listitem>
142         The channels are measured with the help
143         of a multiplexer which switches to the next channel after each measurement.
144         This means that the sampling rate is divided by the number
145         of channels.
146       </listitem>
147       <listitem>
148         The channels are all measured at the same time, for example
149         when every channel has its own converter. In this case the
150         sampling rate need not to be divided by the number of channels.
151       </listitem>
152     </itemizedlist>
153     How your &comedi; device handles the asynchronous acquisition can be found out
154     with the command <command>comedi_board_info -v</command>.
155     </para> 
156     <para>
157       The program <filename>demo/tut3.c</filename> demonstrates the
158       asynchronous acquisition. The general strategy is always
159       the same: first, we tell &comedi; all sampling parameters such as
160       the sampling rate,
161       the number of channels and anything it needs to know
162       so that it can run independently in the background.
163       Then &comedi; checks our request and it might
164       modify it. For example we might want to have a sampling rate of
165       16kHz but we only get 1kHz. Finally we can start
166       the asynchronous acquisition. Once it has been started we
167       need to check periodically if data is available and
168       request it from &comedi; so that its internal buffer
169       won't overrun.
170     </para>
171     <para>
172       In summary the asynchonous acquisition is performed in the following
173       way:
174     </para>
175     <itemizedlist>                
176       <listitem>
177         Create a command structure of type <type><link linkend="ref-type-comedi-cmd">comedi_cmd</link></type>
178       </listitem>  
179       <listitem>
180         Call the function <function><link linkend="func-ref-comedi-get-cmd-generic-timed">comedi_get_cmd_generic_timed</link></function>
181         to fill the command structure with your comedi device,
182         subdevice, sampling rate and number of channels.
183       </listitem>
184       <listitem>
185         Create a channel-list and store it in the command structure. This
186         tells comedi which channels should be sampled in the background.
187       </listitem>
188       <listitem>
189         Call <function><link linkend="func-ref-comedi-command-test">comedi_command_test</link></function> with your command structure. Comedi might modify your requested sampling rate and channels.
190       </listitem>
191       <listitem>
192         Call <function><link linkend="func-ref-comedi-command-test">comedi_command_test</link></function> again which now should return zero for success.
193       </listitem>
194       <listitem>
195         Call <function><link linkend="func-ref-comedi-command">comedi_command</link></function> to start the asynchronous acquisition. From now on the kernel ringbuffer will be filled at the specified sampling rate.
196       </listitem>
197       <listitem>
198         Call periodically the standard
199         function <function>read</function> and receive the data. The
200         result should always be non zero as long as the acquisition
201         is running.
202       </listitem>
203       <listitem>
204         Convert the received data either into
205         <type><link linkend="ref-type-lsampl-t">lsampl_t</link></type> or
206         <type><link linkend="ref-type-sampl-t">sampl_t</link></type> depending
207         on the subdevice flag <constant>SDF_LSAMPL</constant>.
208       </listitem>
209       <listitem>
210         Poll for data with <function>read</function> as long as it returns
211         a positive result or until the program terminates.
212       </listitem>
213     </itemizedlist>
214     
215     <para>
216       The program below is a stripped down version of the
217       program <filename>cmd.c</filename> in the demo directory. To
218       compile it run:
219     </para>
220     <screen>
221       gcc tut3.c -lcomedi -lm -o tut3
222     </screen>
223     <para>
224       It requests data from two channels at 
225       a sampling rate of 1kHz and a total of 10000 samples.
226       which are then printed to stdout. You can pipe the data
227       into a file and plot it with gnuplot. As mentioned above, central in this
228       program is the loop using the standard C <function>read</function> command
229       which receives the buffer contents. Below is an
230       extract from <filename>tut3.c</filename> showing the
231       relevant commands:
232     </para>
233     <programlisting>
234       <xi:include href="../demo/tut3_part.c" parse="text"/>
235     </programlisting>
236     <para>
237       For advanced programmers the
238       function <function><link linkend="func-ref-comedi-get-buffer-contents">comedi_get_buffer_contents</link></function>
239       is useful to check if there is actually data in the ringbuffer
240       so that a call of <function>read</function> can be avoided for example
241       when the data readout is called by a timer call-back function.
242     </para>
243   </section>
244   
245   <section>
246     <title>Further examples</title>
247     <para>
248       See the <filename>demo</filename> subdirectory of Comedilib
249       for more example programs.  The directory contains a
250       <filename>README</filename> file with descriptions of the various
251       demo programs.
252     </para>
253   </section>
254   
255 </section>