package com.lushprojects.circuitjs1.client; import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.core.client.GWT; /* Copyright (C) Paul Falstad and Iain Sharp This file is part of CircuitJS1. CircuitJS1 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. CircuitJS1 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with CircuitJS1. If not, see <http://www.gnu.org/licenses/>. TestPointElm by Bill Collis */ class TestPointElm extends CircuitElm { int meter; final int TP_VOL = 0; final int TP_RMS = 1; final int TP_MAX = 2; final int TP_MIN = 3; final int TP_P2P = 4; final int TP_BIN = 5; final int TP_FRQ = 6; final int TP_PER = 7; final int TP_PWI = 8; final int TP_DUT = 9; //mark to space ratio int zerocount=0; double rmsV=0, total, count; double maxV=0, lastMaxV; double minV=0, lastMinV; double frequency=0; double period=0; double binaryLevel=0;//0 or 1 - double because we only pass doubles back to the web page double pulseWidth=0; double dutyCycle=0; double selectedValue=0; double voltages[]; boolean increasingV=true, decreasingV=true; long periodStart, periodLength, pulseStart;//time between consecutive max values public TestPointElm(int xx, int yy) { super(xx, yy); meter = TP_VOL; } public TestPointElm(int xa, int ya, int xb, int yb, int f, StringTokenizer st) { super(xa, ya, xb, yb, f); meter = new Integer(st.nextToken()).intValue(); //get meter type from saved dump } int getDumpType() { return 368; } int getPostCount() { return 1; } void setPoints() { super.setPoints(); lead1 = new Point(); } String dump() { return super.dump() + " " + meter ; } String getMeter(){ switch (meter) { case TP_VOL: return "V"; case TP_RMS: return "V(rms)"; case TP_MAX: return "Vmax"; case TP_MIN: return "Vmin"; case TP_P2P: return "Peak to peak"; case TP_BIN: return "Binary"; case TP_FRQ: return "Frequency"; case TP_PER: return "Period"; case TP_PWI: return "Pulse width"; case TP_DUT: return "Duty cycle"; } return ""; } void draw(Graphics g) { boolean selected = needsHighlight(); Font f = new Font("SansSerif", selected ? Font.BOLD : 0, 14); g.setFont(f); g.setColor(selected ? selectColor : whiteColor); //depending upon flags show voltage or TP String s = "TP"; interpPoint(point1, point2, lead1, 1-((int)g.context.measureText(s).getWidth()/2+8)/dn); setBbox(point1, lead1, 0); drawCenteredText(g, s, x2, y2, true); //draw label TPx //draw selected value switch (meter) { case TP_VOL: s = myGetUnitText(volts[0],"V",false); break; case TP_RMS: s = myGetUnitText(rmsV,"V(rms)",false); break; case TP_MAX: s = myGetUnitText(lastMaxV,"Vpk",false); break; case TP_MIN: s = myGetUnitText(lastMinV,"Vmin",false); break; case TP_P2P: s = myGetUnitText(lastMaxV-lastMinV,"Vp2p",false); break; case TP_BIN: s= binaryLevel + ""; break; case TP_FRQ: s = myGetUnitText(frequency, "Hz", false); break; case TP_PER: // s = "percent:"+period + " " + sim.timeStep + " " + sim.simTime + " " + sim.getIterCount(); break; case TP_PWI: s = myGetUnitText(pulseWidth, "S", false); break; case TP_DUT: s = showFormat.format(dutyCycle); break; } drawCenteredText(g, s, x2, y2+12, true); //draw selected value TPx setVoltageColor(g, volts[0]); if (selected) g.setColor(selectColor); drawThickLine(g, point1, lead1); drawPosts(g); } void stepFinished(){ count++;//how many counts are in a cycle total += volts[0]*volts[0]; //sum of squares if (volts[0]<2.5) binaryLevel = 0; else binaryLevel = 1; //V going up, track maximum value with if (volts[0]>maxV && increasingV){ maxV = volts[0]; increasingV = true; decreasingV = false; } if (volts[0]<maxV && increasingV){//change of direction V now going down - at start of waveform lastMaxV=maxV; //capture last maximum //capture time between periodLength = System.currentTimeMillis() - periodStart; periodStart = System.currentTimeMillis(); period = periodLength; pulseWidth = System.currentTimeMillis() - pulseStart; dutyCycle = pulseWidth / periodLength; minV=volts[0]; //track minimum value with V increasingV=false; decreasingV=true; //rms data total = total/count; rmsV = Math.sqrt(total); if (Double.isNaN(rmsV)) rmsV=0; count=0; total=0; } if (volts[0]<minV && decreasingV){ //V going down, track minimum value with V minV=volts[0]; increasingV=false; decreasingV=true; } if (volts[0]>minV && decreasingV){ //change of direction V now going up lastMinV=minV; //capture last minimum pulseStart = System.currentTimeMillis(); maxV = volts[0]; increasingV = true; decreasingV = false; //rms data total = total/count; rmsV = Math.sqrt(total); if (Double.isNaN(rmsV)) rmsV=0; count=0; total=0; } //need to zero the rms value if it stays at 0 for a while if (volts[0]==0){ zerocount++; if (zerocount > 5){ total=0; rmsV=0; maxV=0; minV=0; } }else{ zerocount=0; } switch (meter) { case TP_VOL: selectedValue = volts[0]; break; case TP_RMS: selectedValue = rmsV; break; case TP_MAX: selectedValue = lastMaxV; break; case TP_MIN: selectedValue = lastMinV; break; case TP_P2P: selectedValue = lastMaxV-lastMinV; break; case TP_BIN: selectedValue = binaryLevel; break; case TP_FRQ: selectedValue = frequency; break; case TP_PER: selectedValue = period ; break; case TP_PWI: selectedValue = pulseWidth; break; case TP_DUT: selectedValue = dutyCycle; break; } } //alert the user public static native void alert(String msg) /*-{ $wnd.alert(msg); }-*/; double getScopeValue(int x){ return selectedValue; } double getVoltageDiff() { return volts[0]; } void getInfo(String arr[]) { arr[0] = "Test Point"; switch (meter) { case TP_VOL: arr[1] = "V = " + myGetUnitText(volts[0], "V", false); break; case TP_RMS: arr[1] = "V(rms) = " + myGetUnitText(rmsV, "V", false); break; case TP_MAX: arr[1] = "Vmax = " + myGetUnitText(lastMaxV, "Vpk", false); break; case TP_MIN: arr[1] = "Vmin = " + myGetUnitText(lastMinV, "Vmin", false); break; case TP_P2P: arr[1] = "Vp2p = " + myGetUnitText(lastMaxV-lastMinV, "Vp2p", false); break; case TP_BIN: arr[1] = "Binary:" + binaryLevel + ""; break; case TP_FRQ: arr[1] = "Freq = " + myGetUnitText(frequency, "Hz", false); break; case TP_PER: arr[1] = "Period = " + myGetUnitText(period*sim.timeStep/sim.getIterCount(), "S", false); break; case TP_PWI: arr[1] = "Pulse width = " + myGetUnitText(pulseWidth*sim.timeStep*sim.getIterCount(), "S", false); break; case TP_DUT: arr[1] = "Duty cycle = " + showFormat.format(dutyCycle); break; } } // void drawHandles(Graphics g, Color c) { // g.setColor(c); // g.fillRect(x-3, y-3, 7, 7); // } public EditInfo getEditInfo(int n) { if (n==0){ EditInfo ei = new EditInfo("Value", selectedValue, -1, -1); ei.choice = new Choice(); ei.choice.add("Voltage"); ei.choice.add("RMS Voltage"); ei.choice.add("Max Voltage"); ei.choice.add("Min Voltage"); ei.choice.add("P2P Voltage"); ei.choice.add("Binary Value"); //ei.choice.add("Frequency"); //ei.choice.add("Period"); //ei.choice.add("Pulse Width"); //ei.choice.add("Duty Cycle"); ei.choice.select(meter); return ei; } return null; } public void setEditValue(int n, EditInfo ei) { if (n==0){ meter = ei.choice.getSelectedIndex(); } } }