/* * Name: LitecGraph.java * Author: Jason Schwier, Rensselaer Polytechnic Institute * Date: 7 October 2005 * * Description: This class provides the master framework to link the CounterCanvas and PulseCanvas plots to * the data. All labels, text fields, and canvases are created here. This class will call the * data transferring functions of CounterCanvas and PulseCanvas, but will leave the plotting to * their respective paint() functions. This class will accept the input from the user as well as * control the output displayed. * * Changes: From 7 July - corrected the period from doing Integer division to Double division * * Rights: You may form derivatives of this file to fit your needs, as long as some credit is given to myself and * RPI for providing a starting basis of your work. */ import java.awt.*; import java.applet.Applet; import java.lang.*; public class LitecGraph extends Applet { // "Global" variables in the class TextField period, frequency, duty, compare, start; Choice sysclk; Button graph, quit; CounterCanvas counterPlot; PulseCanvas pulsePlot; // Create a label with the gridbag constraints protected void makeLabel( String name, GridBagLayout gridbag, GridBagConstraints c ) { Label textlabel = new Label( name ); gridbag.setConstraints( textlabel, c ); add( textlabel ); } // Overridden function from Applet to start the application public void start() { super.start(); } // Overridden function from Applet to create the appliation public void init() { // Create gridbag constraints and the layout itself GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); /* Gridbag Layout created in this function * ---------------------------------------------------------------------------------------------------------------------------------- * - - Period Label - * - ----------------------------- * - - Period Text Field - * - ----------------------------- * - - Blank Label - * - ----------------------------- * - Counter Canvas - Frequency Label - * - ----------------------------- * - - Frequency Text Field - * - ----------------------------- * - - Blank Label - * ---------------------------------------------------------------------------------------------------------------------------------- * - - Duty Cycle Label - * - ----------------------------- * - - Duty Cycle Text Field - * - ----------------------------- * - - Blank Label - * - ----------------------------- * - Pulse Canvas - System Clock Label - * - ----------------------------- * - - System Clock Choice Menu - * - ----------------------------- * - - Blank Label - * ---------------------------------------------------------------------------------------------------------------------------------- * - Start Reg Label | Start Reg Text Field | Blank Label | Compare Reg Label | Compare Reg Text Field | Graph Button | Quit Button - * ---------------------------------------------------------------------------------------------------------------------------------- */ // Use the gridbag layout setFont( new Font( "Times", Font.PLAIN, 14 ) ); setLayout( gridbag ); // These constraints are for the top canvas c.fill = GridBagConstraints.BOTH; c.gridwidth = 5; c.gridheight = 6; c.weighty = 1.0; c.weightx = 1.0; // Counter plot canvas counterPlot = new CounterCanvas(); gridbag.setConstraints( counterPlot, c ); counterPlot.setSize( 500, 250 ); add( counterPlot ); // These constraints are for the period and frequency blocks c.fill = GridBagConstraints.NONE; c.gridwidth = GridBagConstraints.REMAINDER; c.gridheight = 1; // Weighty = 0 for all objects that are visible, the invisible labels have weighty=1 because // they will expand with the window size, this puts little to no distance between the label // and its corresponding text box // Period squares c.weighty = 0.0; c.weightx = 0.0; makeLabel( "Period (ms):", gridbag, c ); period = new TextField( "", 10 ); gridbag.setConstraints( period, c ); add( period ); // A blank spot for expansion with the window size c.weighty = 1.0; makeLabel( "", gridbag, c ); // Frequency squares c.weighty = 0.0; makeLabel( "Frequency (Hz):", gridbag, c ); frequency = new TextField( "", 10 ); gridbag.setConstraints( frequency, c ); add( frequency ); // A blank spot for expansion with the window size c.weighty = 1.0; makeLabel( "", gridbag, c ); // These constraints are for the pulse canvas c.weightx = 1.0; c.fill = GridBagConstraints.BOTH; c.gridwidth = 5; c.gridheight = 6; // Pulse plot canvas pulsePlot = new PulseCanvas(); gridbag.setConstraints( pulsePlot, c ); pulsePlot.setSize( 500, 250 ); add( pulsePlot ); // These constraints are for the duty cycle and system clock choice c.fill = GridBagConstraints.NONE; c.gridwidth = GridBagConstraints.REMAINDER; c.gridheight = 1; // Duty cycle squares c.weighty = 0.0; c.weightx = 0.0; makeLabel( "Duty Cycle:", gridbag, c ); duty = new TextField( "", 10 ); gridbag.setConstraints( duty, c ); add( duty ); // Blank label to expand with window size c.weighty = 1.0; makeLabel( "", gridbag, c ); // System clock menu c.weighty = 0.0; makeLabel( "System Clock:", gridbag, c ); sysclk = new Choice(); // Can add more choices to the system clock menu here // make the corresponding adjustments in the canvas and pulse plots and the // getChoiceValue() function below sysclk.addItem("SYSCLK"); sysclk.addItem("SYSCLK/4"); sysclk.addItem("SYSCLK/12"); gridbag.setConstraints( sysclk, c ); add( sysclk ); // Blank label to expand with window size c.weighty = 1.0; makeLabel( "", gridbag, c ); // These constraints are for the final row c.gridwidth = 1; c.gridheight = GridBagConstraints.REMAINDER; c.weightx = 1.0; c.weighty = 0.0; // Start register squares makeLabel( "PCA0 Start Value (0-65535):", gridbag, c ); start = new TextField( "0", 7 ); gridbag.setConstraints( start, c ); add( start ); // Blank space between register squares makeLabel( "", gridbag, c ); // Compare register squares makeLabel( "PCA0 Compare Value (0-65535):", gridbag, c ); compare = new TextField( "32768", 7 ); gridbag.setConstraints( compare, c ); add( compare ); // Graph button graph = new Button( "Graph" ); gridbag.setConstraints( graph, c ); add( graph ); /*// Quit Button: Only used for standalone applications quit = new Button( "Quit" ); gridbag.setConstraints( graph, c ); add( quit );*/ // Set some boxes with initial values setDutyCycle( getCompareValue(compare), getStartValue(start) ); setPeriodFreq( getCompareValue(compare), getStartValue(start), getChoiceValue(sysclk) ); } private double getChoiceValue( Choice choice ) { double SYSCLK = 22.1184, sysclk; String item = choice.getSelectedItem(); if( item == "SYSCLK" ) { sysclk = SYSCLK; } else if( item == "SYSCLK/4" ) { sysclk = SYSCLK/4; } else //if( item == "SYSCLK/12" ) { sysclk = SYSCLK/12; } return sysclk; } // From the compare and the start values determine the duty signal of the pulse width modulated output private void setDutyCycle( int compare, int start ) { // Normal case if( start < compare ) { // Number of counts the signal will be high double numerator = (double)65535 - compare; // Number of counts the signal occurs double denominator = (double)65535 - start; // Take the ratio, multiply by 100 to get a percentage, output as a string String textOut = Double.toString(100*numerator/denominator); duty.setText(textOut); } // Undefined case when start is at the compare value, we are saying it will produce a 100.0% duty cycle else if( start == compare ) { duty.setText("100.0"); } // Case when start is greater than compare, obviously no signal will output else { duty.setText("0.0"); } } // Determine the period and frequency of the input clock signal private void setPeriodFreq( int compare, int start, double sysclk ) { double T; //period double f; //frequency // period calculation in milliseconds T = (double)(65536-start) / (double)1000 / sysclk; period.setText(Double.toString(T)); if( T == 0 ) { // Prevents a divide by zero error frequency.setText("infinity"); } else { // Convert the frequency to Hertz so we have a larger number frequency.setText(Double.toString( 1000 / T )); } } // Turn the string of the start text field into an integer // Includes error checking private int getStartValue( TextField start ) { String input = start.getText(); int startInt; try{ startInt = Integer.parseInt(input); } catch( NumberFormatException e) { // this will catch invalid characters start.setText("0"); startInt = 0; } if( (startInt > 65535) || (startInt < 0) ) { // this will catch invalid integers start.setText("0"); startInt = 0; } return startInt; } // Turn the string of the compare text field into an integer // This does error checking private int getCompareValue( TextField compare ) { String input = compare.getText(); int compareInt; try{ compareInt = Integer.parseInt(input); } catch( NumberFormatException e ) { // this will catch invalid characters compare.setText("32768"); compareInt = 32768; } if( (compareInt < 0) || (compareInt > 65535) ) { // this will catch invalid integers compare.setText("32768"); compareInt = 32768; } return compareInt; } // Overridden action function of Component to allow us to use the graph and quit buttons public boolean action( Event evt, Object button ) { // Enter here if we are to graph new numbers if( evt.target == graph ) { // Draw the plots two times because of latency in setting the variables before plotting the first // time. This solves a problem where a variable may not be set completely before being used in the // paint() function of the canvas. for( int i = 0; i < 2; i++ ) { // Get the values from all of the control fields int compareValue = getCompareValue(compare), startValue = getStartValue(start); double systemClock = getChoiceValue(sysclk); // we don't need error checking here since the values should not be changed by the user double periodValue = Double.parseDouble( period.getText() ); String selection = sysclk.getSelectedItem(); // Update the duty cycle, period, and frequency fields setDutyCycle( compareValue, startValue ); setPeriodFreq( compareValue, startValue, systemClock ); // Pass the new values to the two plots counterPlot.captureValues( compareValue, startValue, periodValue, selection ); pulsePlot.captureValues( compareValue, startValue, periodValue, selection ); // Redraw the plots based on the new values counterPlot.repaint(); pulsePlot.repaint(); } return true; } // Enter here to quit the applet else if( evt.target == quit ) { System.exit(0); return true; } else return false; } // This function allows for a standalone application to be built, not necessary for a web applet public static void main( String args[] ) { Frame f = new Frame("LITEC PCA0 Grapher" ); LitecGraph litec = new LitecGraph(); litec.init(); f.add( "Center", litec ); f.setResizable( false ); f.pack(); f.setSize(f.getPreferredSize()); f.show(); } }