/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: PowerChannelResistorVoltageReadable.java * Written by Michael Dayringer and Adam Megacz, Sun Microsystems. * * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. * * Electric(tm) 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 3 of the License, or * (at your option) any later version. * * Electric(tm) 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 Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.tool.simulation.test; /** * Assuming you have a PowerChannel with a resistor attached to the * output and a VoltageReadable across the resistor, this will act * like a PowerChannel+CurrentReadable that lets you set the voltage * across the load as long as it maintains a reasonably stable current * draw. * * +--------------+ resistor +------+ * +--| PowerChannel |---------/\/\/\/\---------| load |---+ * | +--------------+ ^ ^ +------+ | * | | | | * | +- VoltageReadable -+ | * | | * +-------------------------------------------------------+ */ public class PowerChannelResistorVoltageReadable extends PowerChannel { private boolean fastConvergence; private PowerChannel pc; private double ohms; private VoltageReadable vr; private static float EPSILON_VOLTS = 0.01f; public void setCurrent(float amps) { pc.setCurrent(amps); } public float getCurrentSetpoint() { return pc.getCurrentSetpoint(); } public float readCurrent() { double pc_current = pc.readCurrent(); double vr_current = vr.readVoltage() / ohms; if (Math.abs(pc_current - vr_current) > EPSILON_VOLTS * ohms) throw new RuntimeException("PowerChannel and VoltageReadable disagree on current; perhaps you gave the wrong resistor value?\n" + " PowerChannel says: " + pc_current + "\n" + " VoltageReadable says: " + vr_current); return (float)vr_current; } public float readVoltage() { readCurrent(); // to force the sanity check return pc.readVoltage() - vr.readVoltage(); } public void setVoltageNoWait(float volts) { throw new RuntimeException("cannot do this in a "+this.getClass().getName()); } public void waitForVoltage(float setVolts) { throw new RuntimeException("cannot do this in a "+this.getClass().getName()); } public float getVoltageSetpoint() { throw new RuntimeException("cannot do this in a "+this.getClass().getName()); } public void setVoltageWait(float v) { readCurrent(); // to force the sanity check while(true) { double vs = pc.readVoltage(); double vread = vr.readVoltage(); double i = vread/1000; double vl = (vs-ohms*i); System.err.print("\r\033[0K\r"); System.err.print(this.getClass().getSimpleName()+ ".setVoltageWait():"+ " desired/actual="+v+"/"+vl); if (vl+EPSILON_VOLTS < v || vl-EPSILON_VOLTS > v) { if (fastConvergence) { double delta = v+i*ohms - vs; delta *= 1.5; vs = vs + delta; } else { vs = v+i*ohms; } pc.setVoltageWait((float)vs); } else { readCurrent(); // to force the sanity check System.err.print("\r\033[0K\r"); break; } } } public PowerChannelResistorVoltageReadable(PowerChannel pc, float ohmsOfResistor, VoltageReadable voltMeterAcrossResistor, boolean fastConvergence) { this.pc = pc; this.ohms = ohmsOfResistor; this.vr = voltMeterAcrossResistor; this.fastConvergence = fastConvergence; } }