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