/** * Tuned Circuit Attenuation Function Generator * @author Robert John Morton Email * @version 29 October 2007 UK-YE572246C Traces a graph of a tuned circuit's attenuation of a signal over the range 1000000 to 11000000 Rz (radians per second). Vertical scale is logarithmic and ranges from zero attenuation at the top to the value for the minimum displayed frequency. Resonant frequency of tuned circuit is 6000000 Rz. */ import java.awt.*; public class tuning extends java.applet.Applet implements Runnable { private boolean firstpass=true, // indicates first pass of program finished=false; // indicates when curve has been completed /* Width & height of graph, current x,y plot, previous x,y plot, x & y margins to set the graph in the middle of the applet pane. */ private int X = 200, x = 0, px = 0, mx = 14, Y = 200, y = 0, py = 0, my = 15; private double W = 6000000, // resonant frequency Rz ~= 954930 Hz B = 5000000, // semi-bandspread of graph (in Rz) Q = 4, // SQUARE of Q of tuned circuit (Q=1/R) M = W - B, // minimum frequency P = M/W - W/M, // minimum reactance R, // Rz per pixel for horizontal graph axis K; // dB per pixel for vertical graph axis private Image I = null; // reference for an off-screen image I private Graphics i = null; // graphics context for off-screen image private long TF = 100; // total Time Frame for plot update cycle private long T; // time at which next cycle is due to begin private volatile Thread TH; // declare a thread reference variable private Color tr = new Color(0,255,128), // trace colour bg = new Color(0,0,0); // background colour // choose lettering font for applet private Font font = new Font("Dialog",Font.PLAIN,12); public void init(){ // INITIALISE THE APPLET setBackground(bg); // set background colour of the applet // Dimension d = getSize(); // get window size given in HTML applet tag // X = d.width; Y = d.height; // establish window width and height R = (B + B + B) / X; // Rz per pixel scaling for graph // constant: dB per pixel K = 20 * Math.log(Math.sqrt(Q * (P * P + 1 / Q))) / Y; I = createImage(X,Y); // create the off-screen image I i = I.getGraphics(); // graphics context for off-screen image i.setColor(bg); // set background colour of off-screen img i.fillRect(0, 0, X, Y); // fill with transparent background colour // Set colour for the graph axes and then draw them. i.setColor(Color.white); i.drawLine(0,Y - 1,X,Y - 1); i.drawLine(0,0,0,Y); // Set the annotation font and draw the axis and annotate it. i.setFont(font); i.drawString("kHz",X - 30,Y - 5); i.drawString("dB",5,10); i.setColor(tr); // set colour to paint the trace on the image T = System.currentTimeMillis() + TF; // set end of the first time frame } public void newplot(){ // PLOT THE TUNING CURVE if(x > X || y > Y) // if plot has reached edge of graph, finished = true; // set the 'finished' flag else{ // else, while not finished plotting the graph /* Compute the square of the circuit's impedance at angular frequency 'w': 'q' is the reactance of the tuned circuit. */ double p = (R * x + M) / W, q = p -1 / p, Z = Q * (q * q + 1 / Q); // attenuation in y-pixels y = (int)(20 * Math.log(Math.sqrt(Z)) / K); if(firstpass) { px = x; py = y; firstpass = false; } i.drawLine(px,py,x,y); // do next plot on off-screen image px = x; py = y; x++; // advance to next pixel right } } /* Set up the graphics by re-drawing from the off-screen image I in the event that the applet becomes un-eclipsed. */ public void paint(Graphics g){ g.drawImage(I,mx,my,null); } /* Set up the graphics by re-drawing from the off-screen image I whenever repaint() is called. */ public void update(Graphics g){ g.drawImage(I,mx,my,null); } public void run(){ // run the plotting thread while(TH != null){ // loop while thread is alive newplot(); if(!finished) // if not yet finished, repaint(); // do next plot /* Get the time left in the current time frame, imposing a minimum limit of 5 milliseconds, then put the thread to sleep for this remaining time. */ long s = T - System.currentTimeMillis(); if(s < 5) s = 5; try{ TH.sleep(s); } /* Catch any events that occur during the thread's sleep time but do nothing because they are normal external events. Then set the finishing time of the next time frame. */ catch (InterruptedException e) { } T = System.currentTimeMillis() + TF; } } /* Start the program thread by creating the thread object and starting it running [returns a call to run()]. */ public void start(){ TH = new Thread(this); TH.start(); } public void stop() { TH = null; } // kill the program thread }