/* * Name: PCA0Plotter.java * Author: Jason Schwier, Rensselaer Polytechnic Institute * Date: 7 October 2005 * * Description: This class provides the master framework to link the CounterCanvas2 and PulseCanvas plots to * the data. All labels, text fields, and canvases are created here. This class will call the * data transferring functions of CounterCanvas2 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.*; //package PCA0Plotter; public class PCA0Plotter extends Applet { // "Global" variables in the class TextField period, frequency, duty, compare, start; Choice sysclk; Button graph, quit; CounterCanvas2 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 application 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 - * ---------------------------------------------------------------------------------------------------------------------------------- * - PCA0H & PCA0L | | PCA0CPHn & PCA0CPLn - * ---------------------------------------------------------------------------------------------------------------------------------- */ // 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 CounterCanvas2(); 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.gridheight = 1; // c.weightx = 1.0; c.weightx = 0.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 );*/ // Blank label to expand with window size c.weighty = 1.0; // makeLabel( "", gridbag, c ); // These constraints are for the final row c.gridwidth = 5; c.gridheight = GridBagConstraints.REMAINDER; c.weightx = 0.0; c.weighty = 0.0; c.gridx = 0; // Start register label makeLabel("(From PCA0H & PCA0L Value) (From PCA0CPHn & PCA0CPLn Value)", gridbag, c ); // c.gridx = 1; // Compare register label // makeLabel("From PCA0CPHn & PCA0CPLn Value", gridbag, c ); // 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" ); PCA0Plotter litec = new PCA0Plotter(); litec.init(); f.add( "Center", litec ); f.setResizable( false ); f.pack(); f.setSize(f.getPreferredSize()); f.show(); } } //****************************************************************************** /* * Name: CounterCanvas2.java * Author: Jason Schwier, Rensselaer Polytechnic Institute; David Benjamin, The WERCS * Date: 7 October 2005 * * Description: This class provides the variables and functions to plot the output of PCA0 given * the value of the registers PCA0L and PCA0H to start counting and the system clock. A * triangular waveform is produced by calculating the period of the counter from the * system clock and the start value. This plot does not take input directly from the user, it * only provides the functions for painting the single canvas. * * Changes: From 19 July - corrected the period from doing Integer division to Double division * 5/25/09 Added a visual line at the PCA0 Compare Value * * 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 CounterCanvas2 extends Canvas class CounterCanvas2 extends Canvas { // Canvas size values private int xSize = 500; private int ySize = 250; // Graphic axis size values private int xAxisStart = 10; private int xAxisEnd = xSize - 20; private int yAxisStart = 40; private int yAxisEnd = ySize - 10; private int maxRealXAxis = 20; // set in drawAxes() private int maxRealYAxis = 68000; // in counter value // Input / derived values from the applet private static int compareValue = 32768; private static int startValue = 0; private static double period = (double)65536 / (double)1000 / 22.1184; private static String systemClock = "SYSCLK"; // Determine where the origin is private int horizontalAxisUp = 40; private int verticalAxisLeft = 40; // Function called from the applet to tranfer the input values and derived values // from the user to this function public void captureValues( int compare, int start, double periodValue, String sysClock ) { compareValue = compare; startValue = start; period = periodValue; systemClock = sysClock; } // Draw both axes, hash marks on the axes, and labels for the hash marks private void drawAxes( Graphics g ) { // Horizontal Axis g.drawLine( xAxisStart, ySize-horizontalAxisUp, xAxisEnd, ySize-horizontalAxisUp ); // Vertical Axis g.drawLine( verticalAxisLeft, yAxisStart, verticalAxisLeft, yAxisEnd ); // Vertical Axis Hashes // Hashes at 16384, 32768, 49152, 65535 int hashHalfLength = 5; for( int i = 16384; i <= 65536; i += 16384 ) { int hashTemp = realToGraphicYAxis( i, maxRealYAxis, yAxisStart, ySize-horizontalAxisUp ); g.drawLine( verticalAxisLeft-hashHalfLength, hashTemp, verticalAxisLeft+hashHalfLength, hashTemp ); String hashLabel = Integer.toString( (i / 1024) ) + "K"; g.drawString( hashLabel, hashHalfLength, hashTemp+hashHalfLength ); } // Allow for a variable X axis scale based on which system clock is chosen // These values should match the corresponding values for the pulse plot int hashInterval; if( systemClock == "SYSCLK" ) { maxRealXAxis = 12; hashInterval = 2; } else if( systemClock == "SYSCLK/4" ) { maxRealXAxis = 50; hashInterval = 10; } else //if( systemClock == "SYSCLK/12" ) { maxRealXAxis = 150; hashInterval = 30; } // Horizontal Axis Hashes // Hashes every specified interval for( int i = hashInterval; i <= maxRealXAxis; i += hashInterval ) { int hashTemp = realToGraphicXAxis( i, maxRealXAxis, verticalAxisLeft, xAxisEnd ); g.drawLine( hashTemp, ySize-horizontalAxisUp-hashHalfLength, hashTemp, ySize-horizontalAxisUp+hashHalfLength ); String hashLabel = Integer.toString( i ) + " ms"; g.drawString( hashLabel, hashTemp-(4*hashHalfLength), ySize-(2*hashHalfLength) ); } } // Draw the triangular plot of the counter itself private void drawPlot( Graphics g ) { int skipInitial = 0; // Millisecond value of the start register double startMS = period * startValue / (double)65536; // Millisecond value of the time between starting and the period of the count double periodFraction = period - startMS; g.setColor( Color.blue ); // Draw the first line to start from zero to the counter maximum g.drawLine( realToGraphicXAxis(0, maxRealXAxis, verticalAxisLeft, xAxisEnd), realToGraphicYAxis(0, maxRealYAxis, yAxisStart, ySize-horizontalAxisUp), realToGraphicXAxis(period, maxRealXAxis, verticalAxisLeft, xAxisEnd), realToGraphicYAxis(65536, maxRealYAxis, yAxisStart, ySize-horizontalAxisUp) ); // Minimum counting value will be the start register value int minY = realToGraphicYAxis( startValue, maxRealYAxis, yAxisStart, ySize-horizontalAxisUp ); // Maximum counting value will be the full 16-bit value int maxY = realToGraphicYAxis( 65536, maxRealYAxis, yAxisStart, ySize-horizontalAxisUp ); for( double startVal = startMS; startVal < maxRealXAxis; startVal += periodFraction ) { // Determine the two X coordinates for the each end of the line int minX = realToGraphicXAxis( startVal, maxRealXAxis, verticalAxisLeft, xAxisEnd ); int maxX = realToGraphicXAxis( startVal+periodFraction, maxRealXAxis, verticalAxisLeft, xAxisEnd ); if( maxX <= xAxisEnd ) { // This prevents the initial line from being drawn here, but draws all times afterward // Since it was drawn already above if( skipInitial == 0 ) { skipInitial = 1; } else { // Draw the angled line demonstrating the counter g.drawLine( minX, minY, maxX, maxY ); } // Draw the vertical line connecting each triangle g.drawLine( maxX, maxY, maxX, minY ); } } //dMb 5/25/09 Draw a line in green to show the PCA0 Compare Value g.setColor( Color.green ); //g.drawLine(int x1, int y1, int x2, int y2) // 0, compareValue, end, compareValue g.drawLine( realToGraphicXAxis(0, maxRealXAxis, verticalAxisLeft, xAxisEnd), realToGraphicYAxis(compareValue, maxRealYAxis, yAxisStart, ySize-horizontalAxisUp), realToGraphicXAxis(maxRealXAxis, maxRealXAxis, verticalAxisLeft, xAxisEnd), realToGraphicYAxis(compareValue, maxRealYAxis, yAxisStart, ySize-horizontalAxisUp) ); g.setColor( Color.black ); } // Convert between the real X axis and the graphical X axis of the plot private int realToGraphicXAxis( double realCoord, double maxRealCoord, int axisStart, int axisEnd ) { // Calculate the multiplicative scalar which is determined by the ending coordinate of both // the real axis and the length of the graphical axis double axisScalar = (axisEnd - axisStart) / maxRealCoord; // Include the additive factor which is determined by the starting place of the graphical axis // to account for a zero real coordinate double graphicCoord = (realCoord * axisScalar) + axisStart; return ( (int) graphicCoord ); } // Convert between the real Y axis and the graphical Y axis of the plot private int realToGraphicYAxis( int realCoord, int maxRealCoord, int axisStart, int axisEnd ) { // Calculate the multiplicative scalar which is determined by the ending coordinate of both // the real axis and the length of the graphical axis, remember the vertical axis is inverted double axisScalar = (axisStart - axisEnd) / ((double)maxRealCoord); // Include the additive factor which is determined by the ending point of the graphical axis // to account for a zero real coordinate. It is end because of the inverted graphical axis. double graphicCoord = (realCoord * axisScalar) + axisEnd; return ( (int) graphicCoord ); } // Overridden default paint routine for Canvas public void paint( Graphics g ) { // Draw the title FontMetrics fontmetric = getFontMetrics( g.getFont() ); String title = " Count Value PCA0 Counter Plot"; int xRel = fontmetric.stringWidth( title ) / 2; // g.drawString( title, (xSize/2)-xRel, 30 ); g.drawString( title, (xSize/2)-xRel-85, 30 ); // Draw the axes, hashes, and the hash labels drawAxes( g ); // Draw the plot itself drawPlot( g ); } } //***************************************************************************** /* * Name: PulseCanvas.java * Author: Jason Schwier, Rensselaer Polytechnic Institute * Date: 7 October 2005 * * Description: This class provides the variables and functions to plot the PWM output of PCA0 given * the value of the registers PCA0CMPL and PCA0CMPH for comparison and the system clock. A * square wave is produced by calculating the period of the counter from the system clock * and the start value to determine the length between pulses. The rising edge of the pulse * is determined from the compare value specified by the user. This class does not take input * directly from the user, it only provides the functions for painting the single canvas. * * Changes: From 19 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 PulseCanvas extends Canvas class PulseCanvas extends Canvas { // Canvas size variables private int xSize = 500; private int ySize = 250; // Graphical axis size variables private int xAxisStart = 10; private int xAxisEnd = xSize - 20; private int yAxisStart = 40; private int yAxisEnd = ySize - 10; // Real axis size variables private int maxRealXAxis = 20; private int maxRealYAxis = 2; // this will put logic 1 about half way up // User / derived values from the applet private static int compareValue = 32768; private static int startValue = 0; private static double period = (double)65536 / (double)1000 / 22.1184; private static String systemClock = "SYSCLK"; // Determine how far in the axes sit from the edge private int horizontalAxisUp = 40; private int verticalAxisLeft = 40; // Import the user / derived values from the applet into this canvas public void captureValues( int compare, int start, double periodValue, String sysclock ) { compareValue = compare; startValue = start; period = periodValue; systemClock = sysclock; } // Draw both axes, hash marks, and labels for the hashes private void drawAxes( Graphics g ) { // Horizontal axis g.drawLine( xAxisStart, ySize-horizontalAxisUp, xAxisEnd, ySize-horizontalAxisUp ); // Vertical axis g.drawLine( verticalAxisLeft, yAxisStart, verticalAxisLeft, yAxisEnd ); // Vertical hash for logic 1 int hashHalfLength = 5; int hashTemp = realToGraphicYAxis( 1, maxRealYAxis, yAxisStart, ySize-horizontalAxisUp ); g.drawLine( verticalAxisLeft-hashHalfLength, hashTemp, verticalAxisLeft+hashHalfLength, hashTemp ); g.drawString( "Logic 1", hashHalfLength, hashTemp-hashHalfLength ); // Allow for a variable amount of hashes depending on the user choice of system clock // These values should match the corresponding values for the counter plot int hashInterval; if( systemClock == "SYSCLK" ) { maxRealXAxis = 12; hashInterval = 2; } else if( systemClock == "SYSCLK/4" ) { maxRealXAxis = 50; hashInterval = 10; } else //if( systemClock == "SYSCLK/12" ) { maxRealXAxis = 150; hashInterval = 30; } // Horizontal hashes and labels for( int i = hashInterval; i <= maxRealXAxis; i += hashInterval ) { hashTemp = realToGraphicXAxis( i, maxRealXAxis, verticalAxisLeft, xAxisEnd ); g.drawLine( hashTemp, ySize-horizontalAxisUp-hashHalfLength, hashTemp, ySize-horizontalAxisUp+hashHalfLength ); String hashLabel = Integer.toString( i ) + " ms"; g.drawString( hashLabel, hashTemp-(4*hashHalfLength), ySize-(2*hashHalfLength) ); } } // Create the pulse width modulation plot private void drawPlot( Graphics g ) { // Millisecond value of the start register value double startMS = startValue * period / (double)65536; // Millisecond value of the compare register value double compareMS = compareValue * period / (double)65536; // Logic 0 and logic 1 int minY = realToGraphicYAxis( 0, maxRealYAxis, yAxisStart, ySize-horizontalAxisUp ); int maxY = realToGraphicYAxis( 1, maxRealYAxis, yAxisStart, ySize-horizontalAxisUp ); g.setColor( Color.red ); // Case where the counter starts above the compare value, obviously zero will output for entire time if( compareValue < startValue ) { int minX = realToGraphicXAxis( 0, maxRealXAxis, verticalAxisLeft, xAxisEnd ); int compareX = realToGraphicXAxis( compareMS, maxRealXAxis, verticalAxisLeft, xAxisEnd ); int pulseLowX = realToGraphicXAxis( period, maxRealXAxis, verticalAxisLeft, xAxisEnd ); int maxX = realToGraphicXAxis( maxRealXAxis, maxRealXAxis, verticalAxisLeft, xAxisEnd ); g.drawLine( minX, minY, compareX, minY ); g.drawLine( compareX, minY, compareX, maxY ); g.drawLine( compareX, maxY, pulseLowX, maxY ); g.drawLine( pulseLowX, maxY, pulseLowX, minY ); g.drawLine( pulseLowX, minY, maxX, minY ); } // Case where the counter starts at the compare value, undefined results, let's say it will output one // to provide an opposite case to the previous else if( compareValue == startValue ) { int minX = realToGraphicXAxis( 0, maxRealXAxis, verticalAxisLeft, xAxisEnd ); int startX = realToGraphicXAxis( startMS, maxRealXAxis, verticalAxisLeft, xAxisEnd ); int maxX = realToGraphicXAxis( maxRealXAxis, maxRealXAxis, verticalAxisLeft, xAxisEnd ); g.drawLine( minX, minY, startX, minY ); g.drawLine( startX, minY, startX, maxY ); g.drawLine( startX, maxY, maxX, maxY ); } // Normal case where the compare value is greater than the start value else { // Variable that tells where the start value is on the graphical axis int pixelStartValue = realToGraphicXAxis( startMS, maxRealXAxis, verticalAxisLeft, xAxisEnd ); // Variable that tells where the pulse will start for this period on the graphical axis int pulseStart = realToGraphicXAxis( 0, maxRealXAxis, verticalAxisLeft, xAxisEnd ); // Variable that tells where the pulse goes high for this period on the graphical axis int pulseToHigh = realToGraphicXAxis( compareMS, maxRealXAxis, verticalAxisLeft, xAxisEnd ); // Variable that tells where the pulse goes low for this period on the graphical axis int pulseToLow = realToGraphicXAxis( period, maxRealXAxis, verticalAxisLeft, xAxisEnd ); // Variable that tells the distance in pixels that the pulse was high int pulseHigh = pulseToLow - pulseToHigh; // Variable that tells the distance in pixels that the pulse was low int pulseLow = pulseToHigh - pixelStartValue; // Continue drawing pulses while the falling edge does not exceed the axis range while( pulseToLow < xAxisEnd ) { // Draw the pulse g.drawLine( pulseStart, minY, pulseToHigh, minY ); g.drawLine( pulseToHigh, minY, pulseToHigh, maxY ); g.drawLine( pulseToHigh, maxY, pulseToLow, maxY ); g.drawLine( pulseToLow, maxY, pulseToLow, minY ); // Update the period start point to the falling edge pulseStart = pulseToLow; // Update the rising edge by adding in the pixel distance the pulse is low pulseToHigh = pulseStart + pulseLow; // Update the falling edge by adding in the pixel distance the pulse is high pulseToLow = pulseToHigh + pulseHigh; } } g.setColor( Color.black ); } // Convert between the real X axis and the graphical X axis of the plot private int realToGraphicXAxis( double realCoord, int maxRealCoord, int axisStart, int axisEnd ) { // Determine the multiplicative scalar which is primarily determined by the ending coordinate of the real axis double axisScalar = (axisEnd - axisStart) / ((double)maxRealCoord); // Determine the additive scalar which is determined by the starting coordinate of the graphical axis double graphicCoord = (realCoord * axisScalar) + axisStart; return ( (int) graphicCoord ); } // Convert between the real Y axis and the graphical Y axis of the plot private int realToGraphicYAxis( int realCoord, int maxRealCoord, int axisStart, int axisEnd ) { // Determine the multiplicative scalar which is primarily determined by the ending coordinate of the real axis. // Remember the graphical axis is inverted. double axisScalar = (axisStart - axisEnd) / ((double)maxRealCoord); // Determine the additive scalar which is determined by the ending coordinate of the graphical axis double graphicCoord = (realCoord * axisScalar) + axisEnd; return ( (int) graphicCoord ); } public void paint( Graphics g ) { // Draw the title FontMetrics fontmetric = getFontMetrics( g.getFont() ); String title = "PCA0 Pulse Output (CEXn)"; int xRel = fontmetric.stringWidth( title ) / 2; g.drawString( title, (xSize/2)-xRel, 30 ); // Place the axes, hashes, and hash labels drawAxes( g ); // Draw the plot itself drawPlot( g ); } }