tweaked include directives so gcc -MM generates better dependency files
[comedilib.git] / lib / timer.c
1 /*
2     lib/timer.c
3     legacy timer crap
4
5     COMEDILIB - Linux Control and Measurement Device Interface Library
6     Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
7
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation, version 2.1
11     of the License.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Lesser General Public License for more details.
17
18     You should have received a copy of the GNU Lesser General Public
19     License along with this library; if not, write to the Free Software
20     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
21     USA.
22 */
23
24 #include <stdio.h>
25 #include <math.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <sys/ioctl.h>
32 #include <errno.h>
33 #include <string.h>
34
35 #include "libinternal.h"
36
37
38
39 /* dt282x timer */
40
41 static int dt282x_timer(double freq,unsigned int *trigvar,double *actual_freq)
42 {
43         int divider,prescaler;
44         double basefreq=4e6;
45         
46         divider=floor(4e6/(freq));
47         prescaler=0;
48         while(divider>255){
49                 prescaler++;
50                 divider>>=1;
51                 basefreq/=2;
52         }
53         if(prescaler==1){
54                 prescaler++;
55                 divider>>=1;
56                 basefreq/=2;
57         }
58         if(prescaler>=16)return -1;
59         *trigvar=(prescaler<<8)|(255-divider);
60         *actual_freq=basefreq/divider;
61         
62         return 0;
63 }
64
65
66 /* dt2814 timer */
67 static int dt2814_timer(double freq,unsigned int *trigvar,double *actual_freq)
68 {
69         double f;
70         int  i;
71         
72         f=1e5;
73         for(i=0;i<8;i++){
74                 if(f-freq<freq-f/10){
75                         *trigvar=i;
76                         *actual_freq=f;
77                         return 0;
78                 }
79                 f/=10;
80         }
81         *trigvar=i;
82         *actual_freq=f;
83         
84         return 0;
85 }
86
87 /* atmio/pcimio timer */
88 static int atmio_timer(double freq,unsigned int *trigvar,double *actual_freq)
89 {
90         unsigned int divider;
91         
92         divider=floor(20e6/(freq));
93         *actual_freq=20e6/divider;
94         *trigvar=divider-1;
95         
96         return 0;
97 }
98
99 /* acl8112 timer */
100 static int acl8112_timer(double freq,unsigned int *trigvar,double *actual_freq)
101 {
102         int divider,prescaler;
103         double basefreq=2e6;
104
105         /* XXX my notes say that the prescaler and divider cannot
106            be 1.  This needs to be checked.  --ds */
107         
108         /* Force at least one division to get something in CTR2. */
109         prescaler=1;
110         divider = basefreq/(freq);
111
112         while(divider>32767){
113                 prescaler*=2;
114                 divider>>=1;
115         }
116
117         *trigvar = (prescaler<<16) | divider;
118         *actual_freq=basefreq/(divider*prescaler);
119         
120         return 0;
121 }
122
123 /* nanosec timer */
124 static int nanosec_timer(double freq,unsigned int *trigvar,double *actual_freq)
125 {
126         *trigvar=(1e9/freq);
127         *actual_freq=1e9/(*trigvar);
128
129         return 0;
130 }
131
132 typedef int (*timerfunc)(double freq,unsigned int *trigvar,double *actual_freq);
133
134 static timerfunc timer_functions[]={
135         NULL,
136         dt282x_timer,
137         dt2814_timer,
138         atmio_timer,
139         acl8112_timer,
140         nanosec_timer,
141 };
142 #define N_TIMERTYPES 6
143
144 EXPORT_SYMBOL(comedi_get_timer,0.7.18);
145 int comedi_get_timer(comedi_t *it,unsigned int subdev,double freq,
146         unsigned int *trigvar,double *actual_freq)
147 {
148         int timer_type;
149         
150         if(!it || !trigvar || !actual_freq)
151                 return -1;
152
153         timer_type=it->subdevices[subdev].timer_type;
154         
155         if(timer_type==0 || timer_type>=N_TIMERTYPES)
156                 return -1;
157         
158         return (timer_functions[timer_type])(freq,trigvar,actual_freq);
159 }
160