1 #ifndef _res_net_h_
2 #define _res_net_h_
3
4 /*****************************************************************************
5
6 Compute weights for resistors networks.
7
8 Function can evaluate from one to three networks at a time.
9
10 The output weights can be either scaled with automatically calculated scaler
11 or scaled with 'scaler' provided on entry.
12
13 On entry
14 --------
15
16 'minval','maxval' specify range of output signals (sum of weights).
17 'scaler' if negative, function will calculate proper scaler,
18 otherwise it will use the one provided here.
19 'count_x' is a number of resistors in this network
20 'resistances_x' is a pointer to a table containing the resistances
21 'weights_x' is a pointer to a table to be filled with weights
22 (can contain negative values if 'minval' is below zero).
23 'pulldown_x' is a resistance of a pulldown resistor (0 means no pulldown resistor)
24 'pullup_x' is a resistance of a pullup resistor (0 means no pullup resistor)
25
26
27 Return value
28 ------------
29
30 Value of the scaler that was used to fit the output within the expected range.
31 Note that if you provide your own scaler on entry, it will be returned here.
32
33 All resistances expected in Ohms.
34
35
36 Hint
37 ----
38
39 If there is no need to calculate three networks at a time, just specify '0'
40 for the 'count_x' for unused network.
41
42 *****************************************************************************/
43
44 static double compute_resistor_weights(
45 int minval, int maxval, double scaler,
46 int count_1, const int * resistances_1, double * weights_1, int pulldown_1, int pullup_1,
47 int count_2, const int * resistances_2, double * weights_2, int pulldown_2, int pullup_2,
48 int count_3, const int * resistances_3, double * weights_3, int pulldown_3, int pullup_3 );
49
50 #define combine_8_weights(tab,w0,w1,w2,w3,w4,w5,w6,w7) ((int)((tab[0]*w0 + tab[1]*w1 + tab[2]*w2 + tab[3]*w3 + tab[4]*w4 + tab[5]*w5 + tab[6]*w6 + tab[7]*w7) + 0.5))
51 #define combine_7_weights(tab,w0,w1,w2,w3,w4,w5,w6) ((int)((tab[0]*w0 + tab[1]*w1 + tab[2]*w2 + tab[3]*w3 + tab[4]*w4 + tab[5]*w5 + tab[6]*w6) + 0.5))
52 #define combine_6_weights(tab,w0,w1,w2,w3,w4,w5) ((int)((tab[0]*w0 + tab[1]*w1 + tab[2]*w2 + tab[3]*w3 + tab[4]*w4 + tab[5]*w5) + 0.5))
53 #define combine_5_weights(tab,w0,w1,w2,w3,w4) ((int)((tab[0]*w0 + tab[1]*w1 + tab[2]*w2 + tab[3]*w3 + tab[4]*w4) + 0.5))
54 #define combine_4_weights(tab,w0,w1,w2,w3) ((int)((tab[0]*w0 + tab[1]*w1 + tab[2]*w2 + tab[3]*w3) + 0.5))
55 #define combine_3_weights(tab,w0,w1,w2) ((int)((tab[0]*w0 + tab[1]*w1 + tab[2]*w2) + 0.5))
56 #define combine_2_weights(tab,w0,w1) ((int)((tab[0]*w0 + tab[1]*w1) + 0.5))
57
58
59
60 /* this should be moved to one of the core files */
61
62 #define MAX_NETS 3
63 #define MAX_RES_PER_NET 18
64 #define old_MAX_RES_PER_NET 32
65
66
67 /* for the open collector outputs PROMs */
68
69 static double compute_resistor_net_outputs(
70 int minval, int maxval, double scaler,
71 int count_1, const int * resistances_1, double * outputs_1, int pulldown_1, int pullup_1,
72 int count_2, const int * resistances_2, double * outputs_2, int pulldown_2, int pullup_2,
73 int count_3, const int * resistances_3, double * outputs_3, int pulldown_3, int pullup_3 );
74
75
compute_resistor_weights(int minval,int maxval,double scaler,int count_1,const int * resistances_1,double * weights_1,int pulldown_1,int pullup_1,int count_2,const int * resistances_2,double * weights_2,int pulldown_2,int pullup_2,int count_3,const int * resistances_3,double * weights_3,int pulldown_3,int pullup_3)76 static double compute_resistor_weights(
77 int minval, int maxval, double scaler,
78 int count_1, const int * resistances_1, double * weights_1, int pulldown_1, int pullup_1,
79 int count_2, const int * resistances_2, double * weights_2, int pulldown_2, int pullup_2,
80 int count_3, const int * resistances_3, double * weights_3, int pulldown_3, int pullup_3 )
81 {
82
83 int networks_no;
84
85 int rescount[MAX_NETS]; /* number of resistors in each of the nets */
86 double r[MAX_NETS][old_MAX_RES_PER_NET]; /* resistances */
87 double w[MAX_NETS][old_MAX_RES_PER_NET]; /* calulated weights */
88 double ws[MAX_NETS][old_MAX_RES_PER_NET]; /* calulated, scaled weights */
89 int r_pd[MAX_NETS]; /* pulldown resistances */
90 int r_pu[MAX_NETS]; /* pullup resistances */
91
92 double max_out[MAX_NETS];
93 double * out[MAX_NETS];
94
95 int i,j,n;
96 double scale;
97 double max;
98
99 /* parse input parameters */
100
101 networks_no = 0;
102 for (n = 0; n < MAX_NETS; n++)
103 {
104 int count, pd, pu;
105 const int * resistances;
106 double * weights;
107
108 switch(n){
109 case 0:
110 count = count_1;
111 resistances = resistances_1;
112 weights = weights_1;
113 pd = pulldown_1;
114 pu = pullup_1;
115 break;
116 case 1:
117 count = count_2;
118 resistances = resistances_2;
119 weights = weights_2;
120 pd = pulldown_2;
121 pu = pullup_2;
122 break;
123 case 2:
124 default:
125 count = count_3;
126 resistances = resistances_3;
127 weights = weights_3;
128 pd = pulldown_3;
129 pu = pullup_3;
130 break;
131 }
132
133 /* parameters validity check */
134 if (count > old_MAX_RES_PER_NET)
135 {
136 logerror(" ERROR: res_net.h: compute_resistor_weights(): too many resistors in net #%i. The maximum allowed is %i, the number requested was: %i\n",n, old_MAX_RES_PER_NET, count);
137 /* quit */
138 return (0.0);
139 }
140
141
142 if (count > 0)
143 {
144 rescount[networks_no] = count;
145 for (i=0; i < count; i++)
146 {
147 r[networks_no][i] = 1.0 * resistances[i];
148 }
149 out[networks_no] = weights;
150 r_pd[networks_no] = pd;
151 r_pu[networks_no] = pu;
152 networks_no++;
153 }
154 }
155 if (networks_no < 1)
156 {
157 /* error - no networks to anaylse */
158 logerror(" ERROR: res_net.h: compute_resistor_weights(): no input data\n");
159 return (0.0);
160 }
161
162 /* calculate outputs for all given networks */
163 for( i = 0; i < networks_no; i++ )
164 {
165 double R0, R1, Vout, dst;
166
167 /* of n resistors */
168 for(n = 0; n < rescount[i]; n++)
169 {
170 R0 = ( r_pd[i] == 0 ) ? 1.0/1e12 : 1.0/r_pd[i];
171 R1 = ( r_pu[i] == 0 ) ? 1.0/1e12 : 1.0/r_pu[i];
172
173 for( j = 0; j < rescount[i]; j++ )
174 {
175 if( j==n ) /* only one resistance in the network connected to Vcc */
176 {
177 if (r[i][j] != 0.0)
178 R1 += 1.0/r[i][j];
179 }
180 else
181 if (r[i][j] != 0.0)
182 R0 += 1.0/r[i][j];
183 }
184
185 /* now determine the voltage */
186 R0 = 1.0/R0;
187 R1 = 1.0/R1;
188 Vout = (maxval - minval) * R0 / (R1 + R0) + minval;
189
190 /* and convert it to a destination value */
191 dst = (Vout < minval) ? minval : (Vout > maxval) ? maxval : Vout;
192
193 w[i][n] = dst;
194 }
195 }
196
197 /* calculate maximum outputs for all given networks */
198 j = 0;
199 max = 0.0;
200 for( i = 0; i < networks_no; i++ )
201 {
202 double sum = 0.0;
203
204 /* of n resistors */
205 for( n = 0; n < rescount[i]; n++ )
206 sum += w[i][n]; /* maximum output, ie when each resistance is connected to Vcc */
207
208 max_out[i] = sum;
209 if (max < sum)
210 {
211 max = sum;
212 j = i;
213 }
214 }
215
216
217 if (scaler < 0.0) /* use autoscale ? */
218 /* calculate the output scaler according to the network with the greatest output */
219 scale = ((double)maxval) / max_out[j];
220 else /* use scaler provided on entry */
221 scale = scaler;
222
223 /* calculate scaled output and fill the output table(s)*/
224 for(i = 0; i < networks_no;i++)
225 {
226 for (n = 0; n < rescount[i]; n++)
227 {
228 ws[i][n] = w[i][n]*scale; /* scale the result */
229 (out[i])[n] = ws[i][n]; /* fill the output table */
230 }
231 }
232
233 /* debug code */
234 #ifdef MAME_DEBUG
235 logerror("compute_resistor_weights(): scaler = %15.10f\n",scale);
236 logerror("min val :%i max val:%i Total number of networks :%i\n", minval, maxval, networks_no );
237
238 for(i = 0; i < networks_no;i++)
239 {
240 double sum = 0.0;
241
242 logerror(" Network no.%i=> resistances: %i", i, rescount[i] );
243 if (r_pu[i] != 0)
244 logerror(", pullup resistor: %i Ohms",r_pu[i]);
245 if (r_pd[i] != 0)
246 logerror(", pulldown resistor: %i Ohms",r_pd[i]);
247 logerror("\n maximum output of this network:%10.5f (scaled to %15.10f)\n", max_out[i], max_out[i]*scale );
248 for (n = 0; n < rescount[i]; n++)
249 {
250 logerror(" res %2i:%9.1f Ohms weight=%10.5f (scaled = %15.10f)\n", n, r[i][n], w[i][n], ws[i][n] );
251 sum += ws[i][n];
252 }
253 logerror(" sum of scaled weights = %15.10f\n", sum );
254 }
255 #endif
256 /* debug end */
257
258 return (scale);
259
260 }
261
262
compute_resistor_net_outputs(int minval,int maxval,double scaler,int count_1,const int * resistances_1,double * outputs_1,int pulldown_1,int pullup_1,int count_2,const int * resistances_2,double * outputs_2,int pulldown_2,int pullup_2,int count_3,const int * resistances_3,double * outputs_3,int pulldown_3,int pullup_3)263 static double compute_resistor_net_outputs(
264 int minval, int maxval, double scaler,
265 int count_1, const int * resistances_1, double * outputs_1, int pulldown_1, int pullup_1,
266 int count_2, const int * resistances_2, double * outputs_2, int pulldown_2, int pullup_2,
267 int count_3, const int * resistances_3, double * outputs_3, int pulldown_3, int pullup_3 )
268 {
269
270 int networks_no;
271
272 int rescount[MAX_NETS]; /* number of resistors in each of the nets */
273 double r[MAX_NETS][MAX_RES_PER_NET]; /* resistances */
274 double *o; /* calulated outputs */
275 double *os; /* calulated, scaled outputss */
276 int r_pd[MAX_NETS]; /* pulldown resistances */
277 int r_pu[MAX_NETS]; /* pullup resistances */
278
279 double max_out[MAX_NETS];
280 double min_out[MAX_NETS];
281 double * out[MAX_NETS];
282
283 int i,j,n;
284 double scale;
285 double min;
286 double max;
287
288 /* parse input parameters */
289
290 o = (double *) malloc( sizeof(double) * (1<<MAX_RES_PER_NET) * MAX_NETS);
291 os = (double *) malloc( sizeof(double) * (1<<MAX_RES_PER_NET) * MAX_NETS);
292
293 networks_no = 0;
294 for (n = 0; n < MAX_NETS; n++)
295 {
296 int count, pd, pu;
297 const int * resistances;
298 double * weights;
299
300 switch(n){
301 case 0:
302 count = count_1;
303 resistances = resistances_1;
304 weights = outputs_1;
305 pd = pulldown_1;
306 pu = pullup_1;
307 break;
308 case 1:
309 count = count_2;
310 resistances = resistances_2;
311 weights = outputs_2;
312 pd = pulldown_2;
313 pu = pullup_2;
314 break;
315 case 2:
316 default:
317 count = count_3;
318 resistances = resistances_3;
319 weights = outputs_3;
320 pd = pulldown_3;
321 pu = pullup_3;
322 break;
323 }
324
325 /* parameters validity check */
326 if (count > MAX_RES_PER_NET)
327 {
328 logerror(" ERROR: res_net.h: compute_resistor_net_outputs(): too many resistors in net #%i. The maximum allowed is %i, the number requested was: %i\n",n, MAX_RES_PER_NET, count);
329 /* quit */
330 free(o);
331 free(os);
332 return (0.0);
333 }
334
335 if (count > 0)
336 {
337 rescount[networks_no] = count;
338 for (i=0; i < count; i++)
339 {
340 r[networks_no][i] = 1.0 * resistances[i];
341 }
342 out[networks_no] = weights;
343 r_pd[networks_no] = pd;
344 r_pu[networks_no] = pu;
345 networks_no++;
346 }
347 }
348
349 if (networks_no<1)
350 {
351 /* error - no networks to anaylse */
352 logerror(" ERROR: res_net.h: compute_resistor_net_outputs(): no input data\n");
353 free(o);
354 free(os);
355 return (0.0);
356 }
357
358 /* calculate outputs for all given networks */
359 for( i = 0; i < networks_no; i++ )
360 {
361 double R0, R1, Vout, dst;
362
363 /* of n resistors, generating 1<<n possible outputs */
364 for(n = 0; n < (1<<rescount[i]); n++)
365 {
366 R0 = ( r_pd[i] == 0 ) ? 1.0/1e12 : 1.0/r_pd[i];
367 R1 = ( r_pu[i] == 0 ) ? 1.0/1e12 : 1.0/r_pu[i];
368
369 for( j = 0; j < rescount[i]; j++ )
370 {
371 if( (n & (1<<j)) == 0 )/* only when this resistance in the network connected to GND */
372 if (r[i][j] != 0.0)
373 R0 += 1.0/r[i][j];
374 }
375
376 /* now determine the voltage */
377 R0 = 1.0/R0;
378 R1 = 1.0/R1;
379 Vout = (maxval - minval) * R0 / (R1 + R0) + minval;
380
381 /* and convert it to a destination value */
382 dst = (Vout < minval) ? minval : (Vout > maxval) ? maxval : Vout;
383
384 o[i*(1<<MAX_RES_PER_NET)+n] = dst;
385 }
386 }
387
388 /* calculate minimum outputs for all given networks */
389 j = 0;
390 min = maxval;
391 max = minval;
392 for( i = 0; i < networks_no; i++ )
393 {
394 double val = 0.0;
395 double max_tmp = minval;
396 double min_tmp = maxval;
397
398 for (n = 0; n < (1<<rescount[i]); n++)
399 {
400 if (min_tmp > o[i*(1<<MAX_RES_PER_NET)+n])
401 min_tmp = o[i*(1<<MAX_RES_PER_NET)+n];
402 if (max_tmp < o[i*(1<<MAX_RES_PER_NET)+n])
403 max_tmp = o[i*(1<<MAX_RES_PER_NET)+n];
404 }
405
406 max_out[i] = max_tmp; /* maximum output */
407 min_out[i] = min_tmp; /* minimum output */
408
409 val = min_out[i]; /* minimum output of this network */
410 if (min > val)
411 {
412 min = val;
413 }
414 val = max_out[i]; /* maximum output of this network */
415 if (max < val)
416 {
417 max = val;
418 }
419 }
420
421
422 if (scaler < 0.0) /* use autoscale ? */
423 /* calculate the output scaler according to the network with the smallest output */
424 scale = ((double)maxval) / (max-min);
425 else /* use scaler provided on entry */
426 scale = scaler;
427
428 /* calculate scaled output and fill the output table(s) */
429 for(i = 0; i < networks_no; i++)
430 {
431 for (n = 0; n < (1<<rescount[i]); n++)
432 {
433 os[i*(1<<MAX_RES_PER_NET)+n] = (o[i*(1<<MAX_RES_PER_NET)+n] - min) * scale; /* scale the result */
434 (out[i])[n] = os[i*(1<<MAX_RES_PER_NET)+n]; /* fill the output table */
435 }
436 }
437
438 /* debug code */
439 #ifdef MAME_DEBUG
440 logerror("compute_resistor_net_outputs(): scaler = %15.10f\n",scale);
441 logerror("min val :%i max val:%i Total number of networks :%i\n", minval, maxval, networks_no );
442
443 for(i = 0; i < networks_no;i++)
444 {
445 logerror(" Network no.%i=> resistances: %i", i, rescount[i] );
446 if (r_pu[i] != 0)
447 logerror(", pullup resistor: %i Ohms",r_pu[i]);
448 if (r_pd[i] != 0)
449 logerror(", pulldown resistor: %i Ohms",r_pd[i]);
450 logerror("\n maximum output of this network:%10.5f", max_out[i] );
451 logerror("\n minimum output of this network:%10.5f\n", min_out[i] );
452 for (n = 0; n < rescount[i]; n++)
453 {
454 logerror(" res %2i:%9.1f Ohms\n", n, r[i][n]);
455 }
456 for (n = 0; n < (1<<rescount[i]); n++)
457 {
458 logerror(" combination %2i out=%10.5f (scaled = %15.10f)\n", n, o[i*(1<<MAX_RES_PER_NET)+n], os[i*(1<<MAX_RES_PER_NET)+n] );
459 }
460 }
461 #endif
462 /* debug end */
463
464 free(o);
465 free(os);
466 return (scale);
467
468 }
469
470 #endif /*_res_net_h_*/
471