001    package edu.nrao.sss.model.resource;
002    
003    import java.awt.event.ActionListener;
004    import java.util.Collection;
005    import java.util.List;
006    import java.util.Map;
007    import java.util.Set;
008    import java.util.SortedMap;
009    import java.util.SortedSet;
010    
011    import edu.nrao.sss.electronics.DigitalSignal;
012    import edu.nrao.sss.electronics.Digitizer;
013    import edu.nrao.sss.electronics.LocalOscillator;
014    import edu.nrao.sss.electronics.SignalProcessor;
015    import edu.nrao.sss.electronics.SignalSwitch;
016    import edu.nrao.sss.electronics.SignalTransferSwitch;
017    import edu.nrao.sss.measure.Frequency;
018    
019    /**
020     * The electronics system of a radio antenna.
021     * <p>
022     * The main job of the antenna electronics is to produce a collection
023     * of {@link DigitalSignal digital signals}.  Those signals may then
024     * be used by down stream electronics, such as the correlator of
025     * an interferometer.  These electronics can be expected to configure
026     * themselves for a particular receiver band, or to produce
027     * a given set of outputs.  In this context "configure" will usually
028     * mean the setting of switches and the tuning of local oscillators.</p>
029     * <h3 style="font-variant:small-caps"><u>How To Use This Class</u></h3>
030     * <div style="margin-left:1.5em; margin-right:2em; text-align:justify;">
031     * <p>
032     * <i><b>Getting an Instance</b></i><br/>
033     * Clients are discouraged from creating new instances of this type by
034     * using the constructors of implementing classes.  The preferred way to get
035     * an instance of this type is to use the
036     * {@link TelescopeType#makeElectronics() makeElectronics} method of the
037     * {@link TelescopeType} class.</p>
038     * <p>
039     * <i><b>Getting Output Signals</b></i><br/>
040     * Three methods return a collection of digital signals:
041     * {@link #execute()}, {@link #getSignals()}, and {@link #getSignalPairs()}.
042     * The <tt>getSignal<i>Xxx</i></tt> methods return the signals produced by
043     * the most recent call to the {@code execute} method.  Calling either of the
044     * <tt>getSignal<i>Xxx</i></tt> methods does not
045     * rerun this device.  If this device has never been run, the
046     * returned collection of signals will be empty.  The signals returned
047     * by the <tt>getSignal<i>Xxx</i></tt> methods are copies of the true outputs,
048     * so changes made to them by clients will not be reflected in subsequent calls
049     * to those methods.
050     * The {@code execute} method, on the other hand, runs this device based
051     * on its current configuration, remembers the outputs produced
052     * (so that the <tt>getSignal<i>Xxx</i></tt> methods can quickly retrieve them),
053     * and returns copies of those output signals.
054     * The normal sequence is for a client to acquire the
055     * electronics for their telescope of choice, configure those
056     * electronics, and then execute them.  Concrete implementations of
057     * this interface, though, are expected to be created with
058     * a default configuration that could be executed immediately.
059     * Execution without client-specified configuration instructions, however,
060     * will not generally be useful.</p>
061     * <p>
062     * <i><b>Configuring the Electronics Using Internal Intelligence</b></i><br/>
063     * There are two main categories of configuration methods: those that configure
064     * the electronics immediately, and those that give directions that the
065     * electronics may use when one of the immediate configuration methods
066     * is called.  Let us cover the latter first.</p>
067     * <p>
068     * The two {@code submitTuningPlan} methods provide this device with 
069     * instructions that it can use when one of the {@code configureXxx} methods
070     * is called.  They provide, on a receiver-by-receiver basis, a
071     * set of frequency tunings for the local oscillators that feed
072     * this device.  Concrete implementations are expected to
073     * come with a default set of tuning instructions for each of
074     * their receivers.</p>
075     * <p>
076     * Of the immediate configuration methods, the
077     * {@link #configureToProduce(Collection)} method
078     * is the most generic, as it does not rely on even knowing the
079     * receivers that feed these electronics.  It is expected that implementing
080     * classes will use the requested output signals to choose one or more
081     * receivers, set internal switches, and tune local oscillators according
082     * to either default plans or plans submitted by clients.
083     * The {@link #configureFor(ReceiverBand)} methods ask clients to specify
084     * the receiver band(s) they want to use, but do not expect them to know
085     * anything else about the electronics.</p>
086     * <p>
087     * <i><b>Configuring the Electronics Manually</b></i><br/>
088     * Knowledgable clients may use the
089     * {@link #configureFrom(AntennaElectronicsConfiguration)} method to set
090     * switches, tune local oscillators, and select the number of bits for the
091     * digital samplers directly.  This method gives clients the most control
092     * over the internal settings of these electronics.</p>
093     * <p>
094     * <i><b>Tuning the Local Oscillators Manually</b></i><br/>
095     * In addition to the configuration methods mentioned above, clients
096     * may fetch the local oscillators and tune them independently.
097     * The LOs returned by this method are the LOs referenced internally
098     * by this device, so changes made to them by clients will be
099     * reflected herein.  Note that the LOs can also be tuned somewhat
100     * directly by using the {@link #configureFrom(AntennaElectronicsConfiguration)}
101     * method.  Fetching the local oscillators directly and then tuning them
102     * can be useful for those clients who want to first take advantage
103     * of the intelligence used in the other <tt>configureXxx</tt> for setting
104     * switches, but tweak the LO setting themselves.</p>
105     * <p>
106     * <i><b>Interaction of the Configuration Methods</b></i><br/>
107     * In general, the configuration method called just prior to the execution
108     * of this device dominates.  For example, if a client were to call
109     * {@code configureToProduce} and then fetch and tune the local oscillators,
110     * some or all of the work done by {@code configureToProduce} would be
111     * overridden.  Tuning the LOs manually after a call to one of the
112     * {@code configureFor} methods could make sense, though, as one of the main
113     * jobs of the {@code configureFor} methods is to ensure that this device
114     * takes its input from a given receiver(s).  Clients may wish to
115     * then tweak the LO settings determined by this device.
116     * This is most useful for testing and debugging.  In general, clients
117     * will not need to tweak the LO settings themselves.</p>
118     * </div>
119     * <p>
120     * <b>Version Info:</b>
121     * <table style="margin-left:2em">
122     *   <tr><td>$Revision: 1699 $</td></tr>
123     *   <tr><td>$Date: 2008-11-07 13:27:05 -0700 (Fri, 07 Nov 2008) $</td></tr>
124     *   <tr><td>$Author: dharland $ (last person to modify)</td></tr>
125     * </table></p>
126     * 
127     * @author David M. Harland
128     * @since 2007-10-30
129     */
130    public interface AntennaElectronics
131      extends Cloneable
132    {
133      //============================================================================
134      // EXECUTION AND OUTPUT
135      //============================================================================
136      
137      /**
138       * Runs these electronics and returns a collection of the signals produced.
139       * @return the signals produced by running these electronics.
140       */
141      public Collection<DigitalSignal> execute();
142      
143      /**
144       * Returns the digital signals produced by the most recent
145       * {@link SignalProcessor#execute() execution} of these electronics.
146       * The returned collection will never be <i>null</i>, but could be
147       * empty.  None of the elements contained in the returned collection
148       * will be <i>null</i>.
149       * 
150       * @return the digital signals produced by the most recent execution
151       *         of these electronics.
152       */
153      public Collection<DigitalSignal> getSignals();
154      
155      /**
156       * Returns the digital signals produced by the most recent
157       * {@link SignalProcessor#execute() execution} of these electronics,
158       * organized into pairs.
159       * <p>
160       * The returned collection will never be <i>null</i>, but could be
161       * empty.  Each element of the collection is a list of size two.
162       * Normally both elements of the inner lists are non-null.  However,
163       * it is possible for one, but not both, of the elements of the
164       * inner lists to be <i>null</i>.  This occurs when a signal
165       * has no partner.</p>
166       * 
167       * @return the digital signals produced by the most recent execution
168       *         of these electronics, organized into pairs.
169       */
170      public List<List<DigitalSignal>> getSignalPairs();
171    
172      /**
173       * Registers a new listener that will be notified whenever the
174       * {@link #execute()} method is called.  Listeners will be notified
175       * <i>after</i> the <tt>execute</tt> method has already performed its
176       * work and may not be notified at all if there is an unexpected failure.
177       * 
178       * @param newListener
179       *   an object that will be notified upon successful completion of the
180       *   {@link #execute()} method.
181       */
182      public void addExecutionListener(ActionListener newListener);
183      
184      /**
185       * Removes {@code formerListener} from this electronics' list of
186       * execution listeners.  If {@code formerListener} is not currently
187       * a registered execution listener, this method does nothing.
188       * 
189       * @param formerListener
190       *   an object that no longer wishes to be notified upon successful
191       *   completion of the {@link #execute()} method.
192       */
193      public void removeExecutionListener(ActionListener formerListener);
194      
195      //============================================================================
196      // INTELLIGENT CONFIGURATION
197      //============================================================================
198      
199      /**
200       * Configures these electronics to work with the given receiver band.
201       * Configuration can take several forms and may include the setting of
202       * switches and the tuning of local oscillators.
203       * <p>
204       * Once these electronics have been configured, the
205       * {@link SignalProcessor#execute()} may be run to produce signals
206       * from this band.</p>
207       * 
208       * @param band
209       *   the receiver band, or frequency range, for which these electronics
210       *   should be configured.
211       *   
212       * @return
213       *   <i>true</i> if the configuration occurred without any problems.
214       *   If any problems were encountered, they will be listed in
215       *   {@link #getConfigurationProblems()}.
216       */
217      public boolean configureFor(ReceiverBand band);
218      
219      /**
220       * Configures these electronics to work with the given set of receiver bands.
221       * If these electronics cannot work simultaneously with all the bands in the
222       * set, the return value will be <i>false</i> and the problems encountered
223       * listed in {@link #getConfigurationProblems()}.
224       * 
225       * @param bands
226       *   the receiver bands, or frequency ranges, for which these electronics
227       *   should be configured.
228       *   
229       * @return
230       *   <i>true</i> if the configuration occurred without any problems.
231       *   If any problems were encountered, they will be listed in
232       *   {@link #getConfigurationProblems()}.
233       */
234      public boolean configureFor(Set<ReceiverBand> bands);
235      
236      /**
237       * Attempts to configure these electronics to produce the given signals.
238       * This method will configure these electronics to come as close as it
239       * can to creating the desired signals.
240       * 
241       * @param signals
242       *   the digital output for which these electronics should be configured.
243       *   
244       * @return
245       *   <i>true</i> if the configuration occurred without any problems.
246       *   If any problems were encountered, they will be listed in
247       *   {@link #getConfigurationProblems()}.
248       */
249      public boolean configureToProduce(Collection<DigitalSignal> signals);
250      
251      //============================================================================
252      // MANUAL CONFIGURATION
253      //============================================================================
254      
255      /**
256       * Configures these electronics by setting switches and tuning local
257       * oscillators according to the instructions in the given configuration.
258       * 
259       * @param configuration
260       *   a container of switch settings and local oscillator tunings that
261       *   should be used to configure these electronics.
262       *   
263       * @return
264       *   <i>true</i> if the configuration occurred without any problems.
265       *   If any problems were encountered, they will be listed in
266       *   {@link #getConfigurationProblems()}.
267       */
268      public boolean configureFrom(AntennaElectronicsConfiguration configuration);
269      
270      /**
271       * Returns a configuration that contains the current settings of the
272       * switches and local oscillators of these electronics.
273       * 
274       * @return an object that represents the current configuration of
275       *         these electronics.
276       */
277      public AntennaElectronicsConfiguration getConfiguration();
278      
279      /**
280       * Returns the local oscillators used in these electronics.
281       * The returned map is keyed by the names of the local oscillators.
282       * While the local oscillators in the map are references to those
283       * held internally by these electronics,
284       * the returned map is not referenced internally, so changes made
285       * to it will have no effect on these electronics.
286       * <p>
287       * This method is normally used for discovering the frequencies
288       * to which the internal oscillators are tuned.
289       * This method also gives clients the opportunity to change the LO tunings.
290       * Clients must have some knowledge of the implementing class in order to
291       * do this in a meaningful way.  Thus, this method is not generally used
292       * for manipulating the tunings.</p>
293       * 
294       * @return a map containing the local oscillators used in these electronics,
295       *         keyed by the names of those LOs.
296       */
297      public SortedMap<String, LocalOscillator> getLocalOscillators();
298      
299      /**
300       * Returns those switches in these electronics that may be set externally.
301       * The returned map is keyed by the names of the switches.
302       * While the switches in the map are references to those
303       * held internally by these electronics,
304       * the returned map is not referenced internally, so changes made
305       * to it will have no effect on these electronics.
306       * <p>
307       * This method is normally used for discovering the 
308       * input and output poles to which the internal switches are set.
309       * This method also gives clients the opportunity to change
310       * the switch settings.
311       * Clients must have some knowledge of the implementing class in order to
312       * do this in a meaningful way.  Thus, this method is not generally used
313       * for manipulating the switches.</p>
314       * 
315       * @return a map containing the internal switches of these electronics,
316       *         keyed by the names of those switches.
317       */
318      public SortedMap<String, SignalSwitch> getSwitches();
319      
320      /**
321       * Returns those transfer switches in these electronics that may be
322       * set externally.
323       * The returned map is keyed by the names of the switches.
324       * While the switches in the map are references to those
325       * held internally by these electronics,
326       * the returned map is not referenced internally, so changes made
327       * to it will have no effect on these electronics.
328       * <p>
329       * This method is normally used for discovering the 
330       * orientation to which the internal switches are set.
331       * This method also gives clients the opportunity to change
332       * the orientations.
333       * Clients must have some knowledge of the implementing class in order to
334       * do this in a meaningful way.  Thus, this method is not generally used
335       * for manipulating the switches.</p>
336       * 
337       * @return a map containing the internal transfer switches of these
338       *         electronics, keyed by the names of those switches.
339       */
340      public SortedMap<String, SignalTransferSwitch> getTransferSwitches();
341      
342      /**
343       * Returns the digitizers used in these electronics.
344       * The returned map is keyed by the names of the digitizers.
345       * While the digitizers in the map are references to those
346       * held internally by these electronics,
347       * the returned map is not referenced internally, so changes made
348       * to it will have no effect on these electronics.
349       * <p>
350       * This method is normally used for discovering the bit-per-sample
351       * values that the digitizers are set to produce.
352       * This method also gives clients the opportunity to change those values.
353       * Clients must have some knowledge of the implementing class in order to
354       * do this in a meaningful way.  Thus, this method is not generally used
355       * for manipulating the valuess.</p>
356       * 
357       * @return a map containing the digitizers used in these electronics,
358       *         keyed by the names of those digitizers.
359       */
360      public SortedMap<String, Digitizer> getDigitizers();
361      
362      /**
363       * Allows clients to tell this electronics how to tune its oscillators
364       * for a set of receiver bands.
365       * <p>
366       * It is expected that implementing classes will already know how to
367       * configure themselves, including tuning their LOs, for a given band.
368       * However, this method exists for those clients who have enough
369       * knowledge to meaningfully change that plan.  The submitted map
370       * need not contain a plan for every receiver band handled by this
371       * electronics.</p>
372       * <p>
373       * Note that a tuning plan as specified may be unimplementable.
374       * This can happen when a specified frequency is too high or too low
375       * for a given LO, or when a specified frequency is in between the
376       * tunable frequencies of a discretely tunable LO.  In both these
377       * situations the LOs will be tuned as closely as they can to
378       * the plan.</p>
379       * 
380       * @param plans
381       *   a set of LO tuning plans for particular receiver bands.  The
382       *   map that is the value object of the outer map has a key whose
383       *   value is the name of a contained LO.  The value object of this
384       *   inner map is the frequency to which that LO should be tuned.
385       */
386      public void submitTuningPlan(Map<ReceiverBand, Map<String, Frequency>> plans);
387      
388      /**
389       * Allows clients to tell this electronics how to tune its oscillators
390       * for a particular receiver band.
391       * <p>
392       * See {@link #submitTuningPlan(Map)} for more information concerning
393       * the use of this method.</p>
394       * 
395       * @param band
396       *   the band for which the {@code plan} applies.
397       *   
398       * @param plan
399       *   A map whose key is the name of local oscillator contained by this
400       *   electronics, and whose value is the frequency to which that LO
401       *   should be tuned.
402       */
403      public void submitTuningPlan(ReceiverBand band, Map<String, Frequency> plan);
404      
405      //============================================================================
406      // QUERIES
407      //============================================================================
408      
409      /**
410       * Returns receiver(s) for which these electronics were most recently
411       * configured. 
412       * <p>
413       * Note that the returned set is not held internally by this class, therefore
414       * changes made to it will not be reflected herein.  To change the active
415       * receivers, use one of the {@link #configureFor(ReceiverBand) configureFor}
416       * methods.</p>
417       * 
418       * @return the receivers these electronics are configured to use.
419       */
420      public SortedSet<ReceiverBand> getActiveReceivers();
421      
422      /**
423       * Returns front end(s) for which these electronics were most recently
424       * configured. 
425       * <p>
426       * Note that the returned set is not held internally by this class, therefore
427       * changes made to it will not be reflected herein.  To change the active
428       * front ends, use one of the {@link #configureFor(ReceiverBand) configureFor}
429       * methods.</p>
430       * 
431       * @return the front ends these electronics are configured to use.
432       * 
433       * @see #getActiveReceivers()
434       */
435      public SortedSet<AntennaFrontEnd> getActiveFrontEnds();
436      
437      /**
438       * Returns a list of problems associated with the most recent attempt to
439       * configure these electronics.
440       * <p>
441       * The returned list will never be <i>null</i>, but it will be empty
442       * if there were no problems with the latest configuration or if no
443       * attempt at configuration has ever been made.  The returned list is
444       * <i>not</i> held internally by this object, so changes made to it
445       * will have no effect on this object.</p>
446       * 
447       * @return
448       *   a list of problems with the most recent configuration attempt.
449       */
450      public List<String> getConfigurationProblems();
451      
452      //============================================================================
453      // 
454      //============================================================================
455      
456      public AntennaElectronics clone();
457    }