001 package edu.nrao.sss.electronics; 002 003 import java.math.BigDecimal; 004 005 import edu.nrao.sss.measure.Frequency; 006 import edu.nrao.sss.measure.FrequencyRange; 007 008 /** 009 * A device that multiplies the current frequencies of a signal. 010 * <p> 011 * <b>Version Info:</b> 012 * <table style="margin-left:2em"> 013 * <tr><td>$Revision: 1241 $</td></tr> 014 * <tr><td>$Date: 2008-04-25 14:37:37 -0600 (Fri, 25 Apr 2008) $</td></tr> 015 * <tr><td>$Author: dharland $ (last person to modify)</td></tr> 016 * </table></p> 017 * 018 * @author David M. Harland 019 * @since 2007-10-24 020 */ 021 public class SignalMultiplier 022 implements SignalProcessor, SignalSource 023 { 024 private String name; 025 026 private BigDecimal multiplier; 027 028 private Signal inputSignal; 029 private Signal outputSignal; 030 031 private SignalPipe inputPipe; 032 private SignalPipe outputPipe; 033 034 //============================================================================ 035 // OBJECT CREATION 036 //============================================================================ 037 038 /** 039 * Creates a new multiplier that uses the given {@code multiplicationFactor}. 040 * 041 * @param deviceName 042 * an optional name for this multiplier. If this value is <i>null</i> 043 * a default name will be used in its place. 044 * 045 * @param multiplicationFactor 046 * the amount by which this device will multiply its input signals. 047 */ 048 public SignalMultiplier(String deviceName, BigDecimal multiplicationFactor) 049 { 050 //TODO check value of multiplicationFactor? 051 052 name = (deviceName == null) ? "x"+multiplicationFactor : deviceName; 053 multiplier = multiplicationFactor; 054 inputSignal = null; 055 outputSignal = null; 056 inputPipe = SignalPipe.makeAndWeldOutputTo(this); 057 outputPipe = SignalPipe.makeAndWeldInputTo(this); 058 } 059 060 /** 061 * Creates a new multiplier that uses the given {@code multiplicationFactor}. 062 * 063 * @param deviceName 064 * an optional name for this multiplier. If this value is <i>null</i> 065 * a default name will be used in its place. 066 * 067 * @param multiplicationFactor 068 * the amount by which this device will multiply its input signals. 069 */ 070 public SignalMultiplier(String deviceName, String multiplicationFactor) 071 { 072 this(deviceName, new BigDecimal(multiplicationFactor)); 073 } 074 075 //============================================================================ 076 // 077 //============================================================================ 078 079 /** 080 * Returns the amount by which this device multiplies its input signals. 081 * @return the amount by which this device multiplies its input signals. 082 */ 083 public BigDecimal getMultiplicationFactor() 084 { 085 return multiplier; 086 } 087 088 /** 089 * Returns the input pipe of this device. 090 * A typical usage pattern for this method is:<pre> 091 * myMultiplier.getInputPipe().connectInputTo(mySource);</pre> 092 * 093 * @return the input pipe of this device. 094 */ 095 public SignalPipe getInputPipe() 096 { 097 return inputPipe; 098 } 099 100 /** 101 * Returns the output pipe of this device. 102 * A typical usage pattern for this method is:<pre> 103 * myMultiplier.getOutputPipe().connectOutputTo(myProcessor);</pre> 104 * 105 * @return the output pipe of this device. 106 */ 107 public SignalPipe getOutputPipe() 108 { 109 return outputPipe; 110 } 111 112 /** 113 * Returns a copy of the input signal most recently {@link #execute() 114 * processed} by this device. 115 * If this processor has never been executed, or if the input signal 116 * it processed most recently was <i>null</i>, the returned value will 117 * be <i>null</i>. 118 * 119 * @return the input signal most recently sent into this multiplier. 120 */ 121 public Signal getMostRecentInput() 122 { 123 return inputSignal == null ? null : inputSignal.clone(); 124 } 125 126 /** 127 * Returns a copy of the output signal most recently {@link #execute() 128 * produced} by this device. 129 * If this processor has never been executed, or if the input signal 130 * it processed most recently was <i>null</i>, the returned value will 131 * be <i>null</i>. 132 * 133 * @return the output signal most recently produced by this multiplier. 134 */ 135 public Signal getMostRecentOutput() 136 { 137 return outputSignal == null ? null : outputSignal.clone(); 138 } 139 140 /** 141 * Erases this device's memory of its most recent execution. 142 * @see #getMostRecentInput() 143 * @see #getMostRecentOutput() 144 * @see #getSignal() 145 */ 146 public void eraseSignalMemory() 147 { 148 inputSignal = null; 149 outputSignal = null; 150 } 151 152 //============================================================================ 153 // INTERFACE SignalSource 154 //============================================================================ 155 156 /** 157 * Returns a copy of the signal produced by the most recent {@link #execute() 158 * execution} of this device. 159 * If this device has never been run, or if the input signal 160 * it processed most recently was <i>null</i>, the returned value will 161 * be <i>null</i>. 162 */ 163 public Signal getSignal() 164 { 165 return outputSignal == null ? null : outputSignal.clone(); 166 } 167 168 //============================================================================ 169 // INTERFACE FrequencyProcessor AND SUPPORT THEREOF 170 //============================================================================ 171 172 /** 173 * Runs this device on the signal received from its input pipe and 174 * then executes the processor connected to its output pipe, if any. 175 * Both the input signal and the output produced by multiplying it are 176 * remembered by this multiplier and are available via the 177 * {@link #getMostRecentInput()} and {@link #getMostRecentOutput()} methods. 178 */ 179 public void execute() 180 { 181 updateOutputSignal(); 182 183 outputPipe.execute(); 184 } 185 186 public void executeUpTo(SignalProcessor firstUnexecutedDevice) 187 { 188 //Quick exit if execution should not occur 189 if (firstUnexecutedDevice == this) 190 return; 191 192 updateOutputSignal(); 193 194 //Tell text element of chain to do its work 195 outputPipe.executeUpTo(firstUnexecutedDevice); 196 } 197 198 private void updateOutputSignal() 199 { 200 //Do the work and remember results 201 inputSignal = inputPipe.getSignal(); 202 203 if (inputSignal != null) 204 { 205 outputSignal = multiply(inputSignal); 206 207 if (!outputSignal.getDevicePath().endsWith(name)) 208 outputSignal.appendToDevicePath(name); 209 } 210 else 211 { 212 outputSignal = null; 213 } 214 } 215 216 public void executeFromStartOfChainUpTo(SignalProcessor firstUnexecutedDevice) 217 { 218 inputPipe.executeFromStartOfChainUpTo(firstUnexecutedDevice); 219 } 220 221 /** 222 * Multiplies {@code input} by this multiplier's factor and returns 223 * the multiplied signal. 224 * <p> 225 * Note that the {@code input} signal and this multiplier are 226 * not affected by calls to this method. In other words this multiplier 227 * will not remember the input signal sent in or the output 228 * signal produced. This is in contrast to a call to the 229 * {@link #execute()} methods.</p> 230 * 231 * @param input 232 * the signal to be multiplied. 233 * 234 * @return a new signal that is the result of multiplying {@code input} 235 * by this multiplier's factor. 236 */ 237 public Signal multiply(Signal input) 238 { 239 //Quick exit for null input 240 if (input == null) 241 return null; 242 243 FrequencyRange currRange = input.getCurrentRange(); 244 245 //Only the current frequency range is modified 246 FrequencyRange newRange = new FrequencyRange 247 ( 248 currRange.getLowFrequency().multiplyBy(multiplier), 249 currRange.getHighFrequency().multiplyBy(multiplier) 250 ); 251 252 return input.clone().transform(newRange, input.getProxiedRange(), false); 253 } 254 255 /** 256 * Multiplies {@code input} by this multiplier's factor and returns 257 * the multiplied frequency. 258 * <p> 259 * Note that the {@code input} frequency and this multiplier are 260 * not affected by calls to this method. In other words this multiplier 261 * will not remember the input signal sent in or the output 262 * signal produced. This is in contrast to a call to the 263 * {@link #execute()} methods.</p> 264 * 265 * @param input 266 * the frequency to be multiplied. 267 * 268 * @return a new frequency that is the result of multiplying {@code input} 269 * by this multiplier's factor. 270 */ 271 public Frequency multiply(Frequency input) 272 { 273 Frequency output = input.clone(); 274 275 output.multiplyBy(multiplier); 276 277 return output; 278 } 279 }