/* compute all values */ public static void compute_res_net_all(out std.vector <rgb_t> rgb, ListBytesPointer prom, res_net_decode_info rdi, res_net_info di) //std::vector<rgb_t> &rgb, const u8 *prom, const res_net_decode_info &rdi, const res_net_info &di); { u8 r; u8 g; u8 b; int i; int j; int k; rgb = new std.vector <rgb_t>(); rgb.resize(rdi.end - rdi.start + 1); for (i = rdi.start; i <= rdi.end; i++) { u8 [] t = new u8[3] { 0, 0, 0 }; int s; for (j = 0; j < rdi.numcomp; j++) { for (k = 0; k < 3; k++) { s = rdi.shift[3 * j + k]; if (s > 0) { t[k] = (u8)(t[k] | ((prom[i + rdi.offset[3 * j + k]] >> s) & rdi.mask[3 * j + k])); } else { t[k] = (u8)(t[k] | ((prom[i + rdi.offset[3 * j + k]] << (0 - s)) & rdi.mask[3 * j + k])); } } } r = (u8)compute_res_net(t[0], RES_NET_CHAN_RED, di); g = (u8)compute_res_net(t[1], RES_NET_CHAN_GREEN, di); b = (u8)compute_res_net(t[2], RES_NET_CHAN_BLUE, di); rgb[i - rdi.start] = new rgb_t(r, g, b); } }
/* return a single value for one channel */ public static int compute_res_net(int inputs, int channel, res_net_info di) { double rTotal = 0.0; double v = 0; int i; double vBias = di.rgb[channel].vBias; double vOH = di.vOH; double vOL = di.vOL; double minout = di.rgb[channel].minout; double cut = di.rgb[channel].cut; double vcc = di.vcc; double ttlHRes = 0; double rGnd = di.rgb[channel].rGnd; u8 OpenCol = di.OpenCol; /* Global options */ switch (di.options & RES_NET_AMP_MASK) { case RES_NET_AMP_USE_GLOBAL: /* just ignore */ break; case RES_NET_AMP_NONE: minout = 0.0; cut = 0.0; break; case RES_NET_AMP_DARLINGTON: minout = 0.9; cut = 0.0; break; case RES_NET_AMP_EMITTER: minout = 0.0; cut = 0.7; break; case RES_NET_AMP_CUSTOM: /* Fall through */ break; default: global_object.fatalerror("compute_res_net: Unknown amplifier type\n"); break; } switch (di.options & RES_NET_VCC_MASK) { case RES_NET_VCC_5V: vcc = 5.0; break; case RES_NET_VCC_CUSTOM: /* Fall through */ break; default: global_object.fatalerror("compute_res_net: Unknown vcc type\n"); break; } switch (di.options & RES_NET_VBIAS_MASK) { case RES_NET_VBIAS_USE_GLOBAL: /* just ignore */ break; case RES_NET_VBIAS_5V: vBias = 5.0; break; case RES_NET_VBIAS_TTL: vBias = TTL_VOH; break; case RES_NET_VBIAS_CUSTOM: /* Fall through */ break; default: global_object.fatalerror("compute_res_net: Unknown vcc type\n"); break; } switch (di.options & RES_NET_VIN_MASK) { case RES_NET_VIN_OPEN_COL: OpenCol = 1; vOL = TTL_VOL; break; case RES_NET_VIN_VCC: vOL = 0.0; vOH = vcc; OpenCol = 0; break; case RES_NET_VIN_TTL_OUT: vOL = TTL_VOL; vOH = TTL_VOH; /* rough estimation from 82s129 (7052) datasheet and from various sources * 1.4k / 30 */ ttlHRes = 50; OpenCol = 0; break; case RES_NET_VIN_CUSTOM: /* Fall through */ break; default: global_object.fatalerror("compute_res_net: Unknown vin type\n"); break; } /* Per channel options */ switch (di.rgb[channel].options & RES_NET_AMP_MASK) { case RES_NET_AMP_USE_GLOBAL: /* use global defaults */ break; case RES_NET_AMP_NONE: minout = 0.0; cut = 0.0; break; case RES_NET_AMP_DARLINGTON: minout = 0.7; cut = 0.0; break; case RES_NET_AMP_EMITTER: minout = 0.0; cut = 0.7; break; case RES_NET_AMP_CUSTOM: /* Fall through */ break; default: global_object.fatalerror("compute_res_net: Unknown amplifier type\n"); break; } switch (di.rgb[channel].options & RES_NET_VBIAS_MASK) { case RES_NET_VBIAS_USE_GLOBAL: /* use global defaults */ break; case RES_NET_VBIAS_5V: vBias = 5.0; break; case RES_NET_VBIAS_TTL: vBias = TTL_VOH; break; case RES_NET_VBIAS_CUSTOM: /* Fall through */ break; default: global_object.fatalerror("compute_res_net: Unknown vcc type\n"); break; } /* Input impedances */ switch (di.options & RES_NET_MONITOR_MASK) { case RES_NET_MONITOR_INVERT: case RES_NET_MONITOR_SANYO_EZV20: /* Nothing */ break; case RES_NET_MONITOR_ELECTROHOME_G07: if (rGnd != 0.0) { rGnd = rGnd * 5600 / (rGnd + 5600); } else { rGnd = 5600; } break; } /* compute here - pass a / low inputs */ for (i = 0; i < di.rgb[channel].num; i++) { int level = ((inputs >> i) & 1); if (di.rgb[channel].R[i] != 0.0 && level == 0) { // There is no difference in the calculation of the "low" input // (transistor conducting to ground) between TTL output and // open collector output. This is documented explicitly in the // code below (no difference if / else. if (OpenCol != 0) { rTotal += 1.0 / di.rgb[channel].R[i]; v += vOL / di.rgb[channel].R[i]; } else { rTotal += 1.0 / di.rgb[channel].R[i]; v += vOL / di.rgb[channel].R[i]; } } } /* Mix in rbias and rgnd */ if (di.rgb[channel].rBias != 0.0) { rTotal += 1.0 / di.rgb[channel].rBias; v += vBias / di.rgb[channel].rBias; } if (rGnd != 0.0) { rTotal += 1.0 / rGnd; } /* if the resulting voltage after application of all low inputs is * greater than vOH, treat high inputs as open collector/high impedance * There will be now current into/from the TTL gate */ if ((di.options & RES_NET_VIN_MASK) == RES_NET_VIN_TTL_OUT) { if (v / rTotal > vOH) { OpenCol = 1; } } /* Second pass - high inputs */ for (i = 0; i < di.rgb[channel].num; i++) { int level = ((inputs >> i) & 1); if (di.rgb[channel].R[i] != 0.0 && level != 0) { if (OpenCol != 0) { rTotal += 0; v += 0; } else { rTotal += 1.0 / (di.rgb[channel].R[i] + ttlHRes); v += vOH / (di.rgb[channel].R[i] + ttlHRes); } } } rTotal = 1.0 / rTotal; v *= rTotal; v = Math.Max(minout, v - cut); switch (di.options & RES_NET_MONITOR_MASK) { case RES_NET_MONITOR_INVERT: v = vcc - v; break; case RES_NET_MONITOR_SANYO_EZV20: v = vcc - v; v = Math.Max((double)0, v - 0.7); v = Math.Min(v, vcc - 2 * 0.7); v = v / (vcc - 1.4); v = v * vcc; break; case RES_NET_MONITOR_ELECTROHOME_G07: /* Nothing */ break; } return((int)(v * 255 / vcc + 0.4)); }