Function Generator and Oscilloscope

Dependencies:   C12832_lcd DebounceIn mbed

Revision:
3:920cc6573be0
Parent:
2:218abf68fe93
Child:
4:7340e7a6eb14
--- a/main.cpp	Sat May 24 22:45:38 2014 +0000
+++ b/main.cpp	Fri May 30 04:07:27 2014 +0000
@@ -1,7 +1,19 @@
+//***************************************************************
+//  Function Generator - main entry and sole source file for an
+//   MBED based function generator.  The program will output
+//   waveforms sinewave, squarewave, sawtooth, and flat DC on the
+//   MBED analog out pin (P18).  The joystick buttons are used 
+//   to control the period and amplitude of the output waveforms.
+//   This is because the pots are a little too unstable to be read
+//   out in a tight update loop for the waveforms.  The exception
+//   is the DC output.  That uses the pot as it doesn't need a tight
+//   loop.
+//
+//   Author:  Terry Richards
+//   Date:    5/29/2014
+//
 #include "mbed.h"
 #include "C12832_lcd.h"
-#include "DebounceIn.h"
-//#include "rtos.h"
 
 Serial pc(USBTX, USBRX);
 C12832_LCD LCD;
@@ -9,118 +21,259 @@
 AnalogOut Aout(p18);
 AnalogIn pot1(p19);
 AnalogIn pot2(p20);
+
 DigitalIn up(p15);
 DigitalIn down(p12);
 DigitalIn left(p13);
 DigitalIn right(p16);
 BusIn joy(p15,p12,p13,p16);
 DigitalIn OnOff(p14);
-PwmOut testout(p21);
-PwmOut tled(LED1);
-/*
-DebounceIn OnOff(p14);
-DebounceIn up(p15);
-DebounceIn down(p12);
-DebounceIn left(p13);
-DebounceIn right(p16);
-*/
 
+bool first = true;
 
-// SineWave thread - is initiated when the user selects sinewave output
-// print a sin function in a small window
-// the value of pot 1 changes the period of the sine wave
-// The value of pot 2 changes the height of the sine wave
-void sineWave(void)
-{
-    double i, vert, horiz, outval;
-    while(!OnOff) {       // thread loop
-       	horiz = pot1.read();  // get value of pot 1
-       	vert = pot2.read();	// scale the height of wave
-       	for (i=0; i<2; i=i+0.05) {
-       		outval = 0.5 + 0.5*vert*sin(i*3.14159);
-       		Aout.write(outval);  // Compute the sine value, + half the range
-       		wait_ms(0.0002*horiz);          	         // Controls the sine wave period
-       	}
+// check_update - checks the buttons to see if the user wants
+// to update either the vertical (in volts) or the horizontal
+// (in uS) for the currently selected waveform.  It also updates
+// the LCD
+// **** The joystick is used instead of the pots because *****
+// **** I found that the pots were to unstable ***************
+// Inputs - the vert and horiz from the calling waveform routine
+// Outputs - the updated vert and horiz based on the button presses
+//
+#define SINE		1
+#define SQUARE		2
+#define DC			3
+#define SAW			4
+void check_update( 	int type, 	//what type of waveform
+					double *vert, 	//vertical in volts
+					int *horiz, 	//horizontal in us
+					float vertmax, 	//max vertical in volts
+					int horizmax, 	//max horizontal in us
+					bool init )		//put initial vert and horiz
+{									//on LCD screen if set
+	if( type ) {	//The header is static once the waveform is chosen
+		LCD.locate(0, 3);
+		switch( type ) {	//only done if type is set
+			case SINE:
+				LCD.printf("Current WaveForm: Sine    ");
+				break;
+			case SQUARE:
+				LCD.printf("Current WaveForm: Square  ");
+				break;
+			case DC:
+				LCD.printf("Current WaveForm: DC      ");
+				break;
+			case SAW:
+				LCD.printf("Current WaveForm: SawTooth");
+		}
+	}
+	if( up ) {		//if user pushes up button
+		if( *vert < (1.0 - 0.001) )
+			*vert += 0.01;	//update the vertical
+		LCD.locate(0, 23);	//vert is a percentage between 0 and 1
+		LCD.printf("Height: %5.3f V", *vert*3.3);
+	}
+	if( down ) {
+		if( *vert > 0.01 )
+			*vert -= 0.01;	//update the vertical down
+		LCD.locate(0, 23);
+		LCD.printf("Height: %5.3f V", *vert*3.3);
+	}
+	if( right ) {	//right updates the horizontal in us
+		if( *horiz < 100 )	//fine grain if below 100
+			*horiz += 1;
+		else if( *horiz < 1000 )	//little coarser
+			*horiz += 100;
+		else
+			*horiz += 1000;
+		if( *horiz > 100000 )	//most coarse
+			*horiz = 100000;
+		LCD.locate(0, 13);
+		LCD.printf("PW/Period: %d uS     ", *horiz);
+	}
+	if( left ) {	//left updates horizontal down
+		if( *horiz < 100 )
+			*horiz -= 1;
+		else if( *horiz < 1000 )
+			*horiz -= 100;
+		else
+			*horiz -= 1000;
+		if( *horiz <= 0 )
+			*horiz = 1;
+		LCD.locate(0, 13);
+		LCD.printf("PW/Period: %d uS     ", *horiz);
+	}
+	if( init ) {	//only done if bool init is true
+		LCD.locate(0, 13);	//used for initial LCD update
+		LCD.printf("PW/Period: %d uS     ", *horiz);
+		LCD.locate(0, 23);
+		LCD.printf("Height: %5.3f V", *vert*3.3);
 	}
 }
 
-// Thread squareWave - called if user selects squarewave
-// pot1 controls the width of pulse
-// pot2 controls the height of pulse
+// SineWave - is initiated when the user selects sinewave output
+// Sends a sine wave to the Aout pin.
+// The up and down buttons of the joystick control the amplitude
+// The right and left buttons control the period
+void sineWave(void)
+{
+    int  horiz=1000;
+    double vert=1.0, outval, i;
+    while( OnOff )
+    	wait_ms(10);
+    check_update( SINE, &vert, &horiz, 1.0, 10000, true );
+    while(!OnOff) {       // thread loop
+       	check_update( 0, &vert, &horiz, 1.0, 10000, false );
+       	for (i=0; i<2; i=i+0.05) {
+       		outval = 0.5 + 0.5*vert*sin(i*3.14159);
+       		Aout.write(outval);  // Compute the sine value, + half the range
+       		wait_us(horiz);          	         // Controls the sine wave period
+       	}
+	}
+    while( OnOff )
+    	first = true;
+}
+
+// squareWave - called if user selects squarewave. Sends the
+// square wave to the Aout pin.
+// The up and down buttons of the joystick control the amplitude
+// The right and left buttons control the period
 void squareWave(void)
 {
-	float height=0;
-	unsigned int width=0, cnt=0;
+	static double height = 1.0;
+	static int width = 20;
+	check_update( SQUARE, &height, &width, 1.0, 10000, true );
     while(!OnOff) {       // thread loop
-   		if( cnt == 1000 ) {
-       		width = pot1.read_u16();  // get value of
-       		height = pot2.read();	// scale the height of wave
-       		cnt = 0;
-       	}
+    	check_update( 0, &height, &width, 1.0, 100000, false );
       	Aout.write(height);
-       	wait_ms(0.1*width);
+       	wait_us(width);
        	Aout.write(0);
-       	wait_ms(0.1*width);
-       	cnt++;
+       	wait_us(width);
     }
+    while( OnOff )
+    	first = true;
 }
 
-// Thread flatdc - called if user selects dc sig
+// flatdc - called if user selects dc sig
 // pot2 controls the height of dc signal
+// The check_update is not used here because the
+// pot does not interrupt dc operation.
 void flatdc(void)
 {
+    float current = pot2.read();
+ 	LCD.locate(0, 3);
+	LCD.printf("Current WaveForm: DC      ");
+    LCD.locate(0, 13);
+	LCD.printf("DC Volts: %f V", current*3.3);
+	LCD.locate(0, 23);
+	LCD.printf("                      ");
     while(!OnOff) {       // thread loop
        	Aout.write(pot2.read());	// scale the height of wave
-       	wait_ms(10);
+       	if( current != pot2.read() ) {
+       		current = pot2.read();
+       		LCD.locate(0, 13);
+			LCD.printf("DC Volts: %f V", current*3.3);
+		}
+       	wait_ms(2);
     }
+    while( OnOff )
+    	first = true;
 }
 
+// SawTooth - called if the user selects sawTooth.  Sends the
+// saw tooth waveform out to the Aout pin.
+// The up and down buttons of the joystick control the amplitude
+// The right and left buttons control the period
 void sawTooth(void)
 {
+ 	static double height = 1.0, inc;
+	static int width = 200, i;
+	check_update( SAW, &height, &width, 1.0, 10000, true );
+    while(!OnOff) {       // thread loop
+    	check_update( 0, &height, &width, 1.0, 100000, false );
+    	inc = height/width;
+ 		for( i=0; i<width; i++) {    	
+      		Aout.write(i*inc);
+       		//wait_us(1);
+       	}
+    }
+    while( OnOff )
+    	first = true;
 }
-	
+// Banner - Output a welcome and select screen for
+// the user to select the desired waveform to 
+// output.
+// Inputs: none
+// Outputs: none
+void banner(void)
+{
+    LCD.locate(0,3);
+    LCD.printf("Select Waveform:          ");
+    LCD.locate(0,13);
+    LCD.printf("UP=Sawtooth, DOWN=DC");
+    LCD.locate(0,23);
+    LCD.printf("LEFT=Sine , RIGHT=Square");
+}
+
+// main - main entry point to program and where the 
+// user selects the desired waveform.	
 int main()
 {
+    //booleans to select waveform
     bool do_sine=false, do_saw=false;
-    bool do_dc=false, do_square=false;
-    pc.baud(19200);
+    bool do_dc=false, do_square=false; 
+    pc.baud(19200);		//debug
+    banner();	//put the selection banner on LCD
     while(1)  {
-		if( up ) {
-			do_saw=true;
-			do_sine=false;
+		if( up ) {	//is UP pressed?
+			do_saw=true;	//select Sawtooth
+			do_sine=false;	//ensure nothing else selected
 			do_dc=false;
 			do_square=false;
 		}
-		if( down ) {
+		if( down ) {	//is DOWN pressed?
 			do_saw=false;
 			do_sine=false;
-			do_dc=true;
+			do_dc=true;	//user wants DC
 			do_square=false;
 		}
-		if( right ) {
+		if( right ) {	//is RIGHT pressed?
 			do_saw=false;
 			do_sine=false;
 			do_dc=false;
-			do_square=true;
+			do_square=true;	//user wants squarewave
 		}
-		if( left ) {
+		if( left ) {	//is LEFT pressed?
 			do_saw=false;
-			do_sine=true;
+			do_sine=true;	//user wants sinewave
 			do_dc=false;
 			do_square=false;
 		}
  
- 		if( OnOff ) {
- 			if( do_saw )
+ 		if( OnOff && first ) {	//pressing center button starts
+ 			while( OnOff )		//ensure we only get in here once
+ 				first = false;	//sync signal
+ 			if( do_saw ) {
+ 				pc.printf("I'm doing saw\r\n");
 				sawTooth();
-			else if( do_dc )
+			}
+			else if( do_dc ) {
+ 				pc.printf("I'm doing dc\r\n");
 				flatdc();
-			else if( do_square )
+			}
+			else if( do_square ) {
+ 				pc.printf("I'm doing square\r\n");
 				squareWave();
-			else if( do_sine )
+			}
+			else if( do_sine ) {
+ 				pc.printf("I'm doing sine\r\n");
 				sineWave();
-			else
+			}
+			else {
+ 				pc.printf("I'm doing default (sine)\r\n");
 				sineWave();
+			}
+			banner();	//we came back, ask user what next
 		}
 	}
 }