package jesse.calculate; import innards.*; import innards.provider.iFloatProvider; import innards.util.InnardsDefaults; import ui.cocoawidgets.Inflator; import jesse.visualizer.PointViewer; import java.util.*; /** * User: jg * Date: Nov 16, 2005 * Time: 7:52:18 PM */ public class ResistorLadder implements iLaunchable, iUpdateable{ iFloatProvider[] resistorValues; PointViewer pv; int numResistors; float[] resistorDefaults = new float[]{561, 1000, 2200, 499}; public void launch(){ numResistors = InnardsDefaults.getIntProperty("ResistorLadder.numResistors", 3); resistorValues = new iFloatProvider[numResistors]; for(int i = 0; i < numResistors; i++){ resistorValues[i] = Inflator.getFloatProvider("R"+i, 0, 3000, i>=resistorDefaults.length?100:resistorDefaults[i]); } int permutations = Math.round((float)Math.pow(3, numResistors)); pv = new PointViewer(permutations+3, 0.005f); pv.setLocation(permutations, -0.005f, 0); pv.setSize(permutations, 0.05f); pv.setColor(permutations, 0, 1, 0, 1); pv.setLocation(permutations+1, -0.005f, 0.3f); pv.setSize(permutations+1, 0.05f); pv.setColor(permutations+1, 0, 1, 0, 1); pv.setLocation(permutations+2, -0.005f, 1f); pv.setSize(permutations+2, 0.05f); pv.setColor(permutations+2, 0, 1, 0, 1); pv.setInternalBounds(-.1f, .1f, -0.1f, 1.1f); Launcher.getLauncher().registerUpdateable(this); } public static class PinsState implements Comparable{ int[] states; float voltage; public PinsState(int[] states, float voltage){ this.states = (int[])states.clone(); this.voltage = voltage; } public float getVoltage(){ return voltage; } public int[] getStates(){ return states; } public int compareTo(Object o){ PinsState p = (PinsState)o; if(p.voltage > voltage){ return -1; } if(p.voltage < voltage){ return 1; } return 0; } public String toString(){ String r = "["; for(int i = 0; i < states.length; i++){ r+=states[i]; if(i < states.length-1){ r+=", "; } } r+="], "+voltage; return r; } } public static final int OFF = 0; public static final int ON = 1; public static final int FLOAT = 2; public void update(){ int[] combination = new int[numResistors]; Arrays.fill(combination, OFF); int i = 0; float min = 10000, max = -100000; int numIncrements = Math.round(Inflator.getFloat("Num Increments", 0, 100, 0)); ArrayList cachedStates = null; if(Inflator.getBooleanImpulse("Print Map")){ cachedStates = new ArrayList(); } while(combination!=null){ //if(i >= Math.pow(3, numResistors)){ // System.out.println("too many combinations, probably not working!"); //} float v = voltageForPins(resistorValues, combination, 5, 75); if(cachedStates!=null)cachedStates.add(new PinsState(combination, v)); pv.setLocation(i, 0, v); if(Inflator.getBoolean("Print All Combo's", false)){ System.out.print("For Combination ["); for(int j = 0; j < numResistors; j++){ System.out.print(" "+combination[j]); } System.out.println("] the voltage is "+v); //go backwards so lsb is r0 } if(v < min && v > 0)min = v; if(v > max)max = v; combination = inc(combination, 3); i++; } if(Inflator.getBoolean("Print All Combo's", false)){ System.out.println("Min:"+min+" Max:"+max); } if(cachedStates!=null){ Collections.sort(cachedStates); float step = 0.7f/numIncrements; float target = 0; int index = 0; LinkedList asmFormatted = new LinkedList(); float totalError = 0; { index = findClosest(index, cachedStates, target); PinsState p = (PinsState)cachedStates.get(index); float e = Math.abs(target-p.getVoltage()); totalError+=e; System.out.println(target+" \tv: "+p.toString()+" \tE:"+e); String asmDataDirection = ""; String asmVal = ""; for(int j = numResistors - 1; j >= 0; j--){ asmDataDirection+=(p.getStates()[j]==2?"0":"1"); asmVal+=(p.getStates()[j]==1?"1":"0"); } String theASMString = "0b"+asmDataDirection+asmVal; if(asmFormatted.size()>0) theASMString = ", "+theASMString; asmFormatted.add(theASMString); } target = 0.3f; for(int k = 0; k < numIncrements+1; k++){ int closestIndex = findClosest(index, cachedStates, target); PinsState p = (PinsState)cachedStates.get(closestIndex); float e = Math.abs(target-p.getVoltage()); totalError+=e; System.out.println(target+" \tv: "+p.toString()+" \tE:"+e); target+=step; if(closestIndex - 1 > index){ index = closestIndex -1; } String asmDataDirection = ""; String asmVal = ""; for(int j = numResistors - 1; j >= 0; j--){ asmDataDirection+=(p.getStates()[j]==2?"0":"1"); asmVal+=(p.getStates()[j]==1?"1":"0"); } String theASMString = "0b"+asmDataDirection+asmVal; if(asmFormatted.size()>0) theASMString = ", "+theASMString; asmFormatted.add(theASMString); } System.out.println("Total Error:"+totalError); Iterator ii = asmFormatted.iterator(); System.out.print(".db "); while(ii.hasNext()){ System.out.print(ii.next().toString()); } System.out.println(); } } int findClosest(int lowIndex, ArrayList cachedList, float targetVoltage){ //System.out.println("Target:"+targetVoltage+" IncomingLow:"+((PinsState)cachedList.get(lowIndex)).getVoltage()+" IncomingHigh:"+((PinsState)cachedList.get(lowIndex+1)).getVoltage()); if(lowIndex==0 && ((PinsState)cachedList.get(lowIndex)).getVoltage()>targetVoltage){ return lowIndex; } while(((PinsState)cachedList.get(lowIndex+1)).getVoltage()= cachedList.size()){ return cachedList.size()-1; } } //System.out.println("PostLow:"+((PinsState)cachedList.get(lowIndex)).getVoltage()+" PostHigh:"+((PinsState)cachedList.get(lowIndex+1)).getVoltage()); //should be bracketing it float lowDif = targetVoltage - ((PinsState)cachedList.get(lowIndex)).getVoltage(); float highDif = ((PinsState)cachedList.get(lowIndex+1)).getVoltage() - targetVoltage; if(lowDif < 0 || highDif < 0){ throw new IllegalArgumentException("Resulting states do not bracket voltage"); } if(lowDif < highDif){ return lowIndex; }else{ return lowIndex+1; } } float voltageForPins(iFloatProvider[] resistors, int[] states, float v, float outputOhms){ float upResistanceInv = 0; float downResistanceInv = 1f/outputOhms; for(int i = 0; i < resistors.length; i++){ if(states[i]==ON){ upResistanceInv+=(1f/resistors[i].evaluate()); }else if(states[i]==OFF){ downResistanceInv+=(1f/resistors[i].evaluate()); }else if(states[i]==FLOAT){ //blah } } float upResistance = 1f/upResistanceInv; float downResistance = 1f/downResistanceInv; float totalResistance = upResistance+downResistance; float outputVoltage = (downResistance / totalResistance) * v; return outputVoltage; } /** * returns the next permutation, null if done. * assumes right (max index) is least significant digit * * @param data * @param base * @return next permutation, or null if done */ public static int[] inc(int[] data, int base){ int index = data.length -1; while(++data[index] >= base){ data[index--] = 0; if(index < 0){ return null; } } return data; } }