addi_common: don't access *data when insn->n == 0
[comedi.git] / patches / cascade-test.c
1 #include <comedi.h>
2 #include <math.h>
3 #include <stdio.h>
4 #include "../comedi/drivers/8253.h"
5
6 #if NOT
7 /* this function is meant to replace i8253_cascade_ns_to_timer_2div
8  * (which is completely broken at the moment)
9  */
10 static inline void cascade_new(int i8253_osc_base, unsigned int *d1, unsigned int *d2, unsigned int *nanosec, int round_mode)
11 {
12         unsigned int divider;
13         unsigned int div1, div2;
14         unsigned int div1_glb, div2_glb, ns_glb;
15         unsigned int div1_lub, div2_lub, ns_lub;
16         unsigned int ns;
17         unsigned int start;
18         unsigned int ns_low, ns_high;
19
20         divider = *nanosec / i8253_osc_base;
21
22         div1_lub = div2_lub = 0;
23         div1_glb = div2_glb = 0;
24
25         ns_glb = 0;
26         ns_lub = 0xffffffff;
27
28         div2 = 0x10000;
29         start = divider / div2;
30         if(start < 2) start = 2;
31         for (div1 = start; div1 <= divider / div1 + 1; div1++) {
32                 for(div2 = divider / div1; div1 * div2 <= divider + div1 + 1; div2++) {
33                         ns = i8253_osc_base * div1 * div2;
34                         if (ns <= *nanosec && ns > ns_glb) {
35                                 ns_glb = ns;
36                                 div1_glb = div1;
37                                 div2_glb = div2;
38                         }
39                         if (div2 <= 0x10000) {
40                                 ns = i8253_osc_base * div1 * div2;
41                                 if (ns >= *nanosec && ns < ns_lub) {
42                                         ns_lub = ns;
43                                         div1_lub = div1;
44                                         div2_lub = div2;
45                                 }
46                         }
47                 }
48         }
49
50         switch (round_mode) {
51         case TRIG_ROUND_NEAREST:
52         default:
53                 ns_high = div1_lub * div2_lub * i8253_osc_base;
54                 ns_low = div1_glb * div2_glb * i8253_osc_base;
55                 if( ns_high - *nanosec < *nanosec - ns_low) {
56                         div1 = div1_lub;
57                         div2 = div2_lub;
58                 } else {
59                         div1 = div1_glb;
60                         div2 = div2_glb;
61                 }
62                 break;
63         case TRIG_ROUND_UP:
64                 div1 = div1_lub;
65                 div2 = div2_lub;
66                 break;
67         case TRIG_ROUND_DOWN:
68                 div1 = div1_glb;
69                 div2 = div2_glb;
70                 break;
71         }
72
73         *nanosec = div1 * div2 * i8253_osc_base;
74         *d1 = div1;
75         *d2 = div2;
76         return;
77 }
78 #endif
79
80 #ifdef ROGI
81 int main(int argc,vhar *argv[])
82 {
83         int osc_base = 1000;
84         int round_mode = TRIG_ROUND_NEAREST;
85         int i;
86         int div1_old, div2_old, ns_old, err_old;
87         int div1_new, div2_new, ns_new, err_new;
88         int div1_pow, div2_pow, ns_pow, err_pow;
89         int err = 0;
90
91         /* loop over desired nanosecond timings to test */
92         for(i = 10000; i < 100000; i++)
93         {
94                 ns_old = ns_new = ns_pow = i;
95
96                 i8253_cascade_ns_to_timer_2div(osc_base, &div1_old, &div2_old, &ns_old, round_mode);
97                 err_old = ns_old - i;
98
99                 i8253_cascade_ns_to_timer_power(osc_base, &div1_pow, &div2_pow, &ns_pow, round_mode);
100                 err_pow = ns_pow - i;
101
102                 cascade_new(osc_base, &div1_new, &div2_new, &ns_new, round_mode);
103                 err_new = ns_new - i;
104
105                 /* print results on this condition */
106                 if(abs(err_new) > abs(err_pow))
107                         printf("nanosec %i\terr_new %i\tdiv1_new %i\tdiv2_new %i\n"
108                                 "\t\terr_pow %i\tdiv1_pow %i\tdiv2_pow %i\n",
109                                 i, err_new, div1_new, div2_new, err_pow, div1_pow, div2_pow);
110
111         /* consistency checks */
112                 if(div1_old * div2_old * osc_base != ns_old) err = 1;
113                 if(div1_pow * div2_pow * osc_base != ns_pow) err = 2;
114                 if(div1_new * div2_new * osc_base != ns_new) err = 3;
115                 if(err)
116                 {
117                         printf("err %i\n", err);
118                         err=0;
119                 }
120         }
121         return 0;
122 }
123 #endif
124
125 int main(int argc,char *argv[])
126 {
127         int osc_base = 1000;
128         unsigned int ns;
129         unsigned int div1,div2;
130         int i=0;
131
132         for(ns = 4*osc_base; ns<0x80000000;ns++){
133                 i8253_cascade_ns_to_timer_2div
134                         (osc_base, &div1, &div2, &ns, TRIG_ROUND_UP);
135
136                 i++;
137                 if(!(i&0xff))
138                         printf("ns=%d div1=%d div2=%d\n",ns,div1,div2);
139                 if(i==100000)exit(0);
140         }
141
142         return 0;
143 }
144