2036 student lab assignment - students must add code where shown

Dependencies:   FFT Terminal_VT100 mbed

Revision:
0:257c8b623a6f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Nov 01 19:10:56 2012 +0000
@@ -0,0 +1,474 @@
+// mymbedDAQ - Electronic Test Instrument Concept Demo & Lab assignment
+// CODE MUST BE ADDED BY STUDENTS WHERE INDICATED!!!!!!!!!!!!!!!
+// Uses VT100 terminal application on PC
+// Needs terminal and FFT libs
+//
+// NOTE: for test signals must connect
+// P18 to P16 (sine wave from D/A to A/D)
+// P13 to P12 (digital test signal from serial port to LA digital input)
+// P21 to P15 (PWM for square wave to A/D)
+//
+#include "mbed.h"
+#include "FFT.h"
+#include "Terminal.h"
+#include <vector>
+using namespace std;
+
+// **********************************************************************************************
+#define N 128 //number of analog samples to take - need power of two for FFT
+float FFT_Data[N*2]; //complex data space for analog signal's FFT-1D array with real & imag pairs
+float Data[N]; //data space for (real) analog signal samples
+float Analog_Voltage; //used for DMM voltage reading
+float Analog_out_value[N]; // Analog values of precomputed sine wave for D/A (function generator)
+unsigned char PowerInt[N/2]; //used to store scaled magnitude of FFT bars (positive only)
+
+// note use of volatile for an interrupt set global variable!
+volatile int take_sample; //sample period timer flag - set by interrupt
+
+vector <int> Digital_Signal (100); // use a vector for sample data for Logic Analyzer
+
+char input_char; //character read from PC terminal application window
+bool sine=true; //sine or square wave flag for test signal input
+bool square=true; //50% or 25% duty cycle on square wave test signal
+
+
+//Digital Signals for Logic Analyzer
+
+// Used to read in digital signals
+DigitalIn   LogicAnalyzer_test_signal_in(p12);
+// Used for digital test signal output
+Serial      LogicAnalyzer_test_signal_out(p13,p14);
+
+//Analog I/O Signals for DMM, Oscilloscope, and Spectrum Analyzer
+
+// Analog A/D Input
+AnalogIn    Analog_test_signal_in(p16);
+// Analog D/A output test signal (for sine wave function generation)
+AnalogOut   Analog_test_signal_out(p18);
+
+
+// PWM is used for alternate analog square wave signal source
+
+// Analog A/D Input used for square wave
+AnalogIn    PWM_test_signal(p15);
+// PWM output pint that generates a square wave
+PwmOut PWM_Output(p21);
+
+//unsed Analog input pins set to digital to reduce A/D noise
+DigitalOut  d2(p17);
+DigitalOut  d3(p19);
+DigitalOut  d4(p20);
+
+//VT100 ANSI Terminal connected to PC
+Terminal PC(USBTX, USBRX);
+
+
+// **********************************************************************************************
+
+void Take_Analog_Signal_Samples(float Analogs[]);
+void Graphic_Display_Spectrum(unsigned char *Data);
+void Graphic_Display_Time(float *Data);
+void Digital_Multimeter();
+void Logic_Analyzer();
+void Oscilloscope();
+void Spectrum_Analyzer();
+void Function_Select();
+void Duty_Cycle();
+
+// **********************************************************************************************
+
+int main()
+{
+// Start PWM hardware for a continuous square wave signal ouput with a 50% duty cycle
+    PWM_Output=0.5;
+    PWM_Output.period(0.0128);
+    while(1) {
+// clear screen and print user menu selections
+        PC.cls();
+        PC.locate(0,5);
+        PC.printf("       1 - Digital Multimeter\n\r");
+        PC.printf("       2 - Logic Analyzer\n\r");
+        PC.printf("       3 - Oscilloscope\n\r");
+        PC.printf("       4 - Spectrum Analyzer \n\r");
+        PC.printf("       5 - Function Generation - toggles between sine & square wave signal\n\r");
+        PC.printf("       6 - Duty Cycle - toggles between 50%% and 25%% duty cycle on square wave");
+        PC.locate(0,0);
+        PC.printf("   Select Electronic Test Instrument (type 1...5)");
+        // reads a character from the PC terminal appication window
+        input_char=PC.getc();
+        // echo back selection char for human display on PC
+        PC.putc(input_char);
+        // delay for slow human to see character
+        wait(.5);
+//ADD CODE HERE
+        // select instrument demo using input_char switch statement
+        // case for each function below
+        //  1 Digital_Multimeter();
+        //  2 Logic_Analyzer();
+        //  3 Oscilloscope();
+        //  4 Spectrum_Analyzer();
+        //  5 Function Select();
+        //  6 Duty Cycle();
+
+
+
+
+
+//END ADD CODE HERE
+    }
+}
+
+//*********************************************************************************************
+// toggles a flag between a sine or square wave test output
+// sine flag is used in Take_Analog_Signal_Samples
+void Function_Select()
+{
+    sine=!sine;
+}
+
+//**********************************************************************************************
+// Toggles the hardware PWM output between a 25% and 50% duty cycle square wave
+// square flag stores state
+void Duty_Cycle()
+{
+    if (square)
+        PWM_Output=0.25;
+    else
+        PWM_Output=0.5;
+    square=!square;
+    //PWM hardware needs a bit of setup time to adjust
+    wait(.25);
+}
+
+// **********************************************************************************************
+
+void Digital_Multimeter()
+{
+// PC.readable() indicates another character is available to read
+// but it does not read the character or wait for a character
+// It is a handy way to break out of a loop if any key is hit
+    while(!PC.readable()) {
+        // Digital Multimeter - reads an analog voltage on pin 16
+        // D/A output is connected to A/D input  (0..3.3V range only!)
+        PC.cls(); //clear screen
+        PC.locate(9,0); // move cursor to 9,0
+        PC.printf("Digital Multimeter"); // print title
+        PC.locate(22,12);
+        PC.printf("  volts DC"); // label for voltage reading
+        // Plot Y Axis tick marks with labels
+        for(int i=21; i>3; i--) {
+            PC.locate(7,i);
+            // put a label every 1 volt on axis
+            if((i-1)%5==0) {
+                PC.putc('+');
+                PC.locate(1,i);
+                PC.printf("%d.0V",int((21.0-i)/16.0*3.3));
+            } else PC.putc('-');
+        }
+        for(int i=0; i<=64; i++) {
+            // Output the Analog test signal using D/A output 'Analog_test_signal_out
+            // makes D/A outputvoltage increase linear from 0 to 3.3
+            // (but scaled from 0 to 1.0 in C/C++) using loop value i to change it
+//ADD CODE HERE - 1 line
+
+//END ADD CODE HERE
+            // Print voltage at 15,12
+            PC.locate(15,12);
+//ADD CODE HERE
+            // read in the analog voltage using A/D input "Analog_test_signal_in"
+            // multiply value by 3.3 to convert to actual voltage level
+            // save in "Analog_Voltage"
+
+            // Print Analog_Voltage*3.3 in "%7.3F" format
+
+            // Display Analog Level Bar but only every four display updates (i%4) for faster updates
+            // on PC use char(219) for a solid bar graphics character or a space ' ' to erase
+            // use locate to draw a vertical bar
+
+
+
+
+
+        }
+//END ADD CODE HERE
+    }
+    // delay to allow time to view each display
+    wait(1);
+}
+
+// **********************************************************************************************
+
+void Logic_Analyzer()
+{
+    // Logic Analyzer
+    // Reads in a serial digital output pin (0 or 3.3V)
+    // pin 13 TX serial output tied to pin12 digital input
+    while(!PC.readable()) {
+        // Loop through several ASCII characters for display test
+        for(int c='A'; c<='z'&&!PC.readable(); c=c+1) {
+            PC.cls();
+            Digital_Signal.clear();
+            PC.locate(15,0);
+            PC.printf("Logic Analyzer Display - RS-232 Serial ASCII character %c 0x%X",char(c), int(c));
+            // Sample digital data for display - need 80 samples (have 80 display cols)
+            for(int i=0; i<80; i++) {
+                // Test signal for Logic Analyzer
+                // Send out a new character char(c) using the serial port
+                // after a small delay so that it will show up in middle of display
+                if(i==6) LogicAnalyzer_test_signal_out.putc(char(c));
+//ADD CODE HERE
+// Use "Digital_Signal" vector to store data from "LogicAnalyzer_test_signal_in" (DigitalIn pin)
+
+                // time delay is used to adjust sample time interval
+                // a hardware timer would be more accurate
+                // that will be explained later in the oscilloscope example
+                // some adjustment to time delay here might be needed for your code
+                // scale so that you can see entire ASCII character on display
+                wait(.00002);
+            }
+            //Display data
+            //Move cursor to 0,15 or 0,5 based on first digital bit from Digital_Signal[i]
+            //Scan through data samples from left to right and draw the high or low line
+            //Locate is only needed when changing between high or low value
+            //loop through 80 sample values
+            PC.locate(0,(15 - int(float(Digital_Signal[0])*10.0)));
+            for(int i=0; i<80; i++) {
+                // If no change in digital signal, or fist bit just output a horiz bar char(196)?
+
+                // if A 1 to 0 transisition occured
+                // draw a vertical line with correct bar and corner characters (191, 179, 192)
+                // PC.locate(col,row) is needed for vertical line drawing
+
+
+
+
+
+                //if A 0 to 1 transisiton occured
+                // draw a vertical line with correct bar and corner characters (217, 179, 218)
+
+
+
+
+
+            }
+            //plot X axis tick marks and labels
+            //only initial locate needed
+            PC.locate(0,20);
+
+
+
+
+
+
+//END ADD CODE HERE
+            // delay to allow time to view each display
+            wait(1);
+        }
+    }
+}
+// **********************************************************************************************
+
+void Oscilloscope()
+{
+    while(!PC.readable()) {
+        // Oscilloscope
+        // D/A sends out a sine wave and the A/D reads it back in
+        // PWM hardware sends out a square wave to another A/D input
+        // loop through increasing the frequency of the test signals for each display
+        for(int i=1; i<11&&!PC.readable(); i++) {
+            //Setup square wave signal source period - increase each loop iteration
+            PWM_Output.period(0.0128/i);
+            wait(0.25);
+            // Precompute sine wave values for faster D/A output to save execution time
+            // Need to add DC bias and scale sine wave from 0...1.0 for analog out function
+            // (i.e. not just -1..1)
+            // need N samples of one sine cycle first time - then make it i times faster each
+            // loop iteration - samples go in Analog_out_value[k]
+            for(int k=0; k<N; k++) {
+//ADD CODE HERE - 1 line to compute sine values
+
+//END ADD CODE HERE
+            }
+            //Reads analog samples using test signals setup above
+            Take_Analog_Signal_Samples(Data);
+            //Displays an analog signal in time
+            Graphic_Display_Time(Data);
+            // delay to allow time to view each display
+            wait(2);
+        }
+    }
+}
+
+// **********************************************************************************************
+void Spectrum_Analyzer()
+{
+    while(!PC.readable()) {
+        // Spectrum Analyzer
+        // Compute FFT of sampled signal
+        // D/A sends out a sine wave and the A/D reads it back in
+        // loop through increasing the frequency of test signals for each display
+        for(int i=1; i<11&&!PC.readable(); i++) {
+            //Setup square wave signal source with correct period
+            PWM_Output.period(.0128/i);
+            wait(0.25);
+            //Precompute sine wave values for D/A output to save execution time
+            //same as Oscilloscope code earlier
+            for(int k=0; k<N; k++) {
+//ADD CODE HERE - line
+
+//END ADD CODE HERE
+            }
+            //Reads analog samples
+            Take_Analog_Signal_Samples(Data);
+            // put data in complex format for FFT code (real followed by imag=0 in 2*N 1D array)
+            // Required by Numerical Recipes in C++ Algorithm for FFT used in in vFFT.cpp
+            for(int k=0; k<N; k++) {
+                FFT_Data[k*2]=Data[k];
+                FFT_Data[k*2+1] = 0.0;
+            }
+            Graphic_Display_Time(Data);
+            // delay to allow time to view each time display
+            wait(2);
+            // Spectrum Analyzer
+            // Compute FFT of sampled signal
+            vFFT(FFT_Data-1,N);
+            // Compute magnitude for positive frequency display
+            // scaled and returned in a char array
+            vCalPowerInt(FFT_Data,PowerInt,N/2);
+            // Display Frequency content of sampled signal
+            Graphic_Display_Spectrum(PowerInt);
+            // delay to allow time to view each frequency display
+            wait(2);
+        }
+    }
+}
+
+
+// **********************************************************************************************
+// Functions to sample Analog input data at an accurate 10Khz rate (every 100 us)
+// used by Oscilloscope and Spectrum Analyzer
+void Sample_timer_interrupt(void)
+{
+    // Sets flag when time to read in another analog sample
+    // Timer interrupt comes here when a it hits every sample time interval
+    take_sample=1;
+}
+void Take_Analog_Signal_Samples(float Analogs[])
+{
+    // setup a timer to determine accurate sample time
+    Ticker Sample_Period;
+    // reset sample time interval flag
+    take_sample=0;
+    // output first D/A value for sine wave
+    Analog_test_signal_out=Analog_out_value[0];
+    // Start periodic timer interrupts to ensure accurate control of sample time interval
+    // Sample_timer_interrupt is "called" every 100 us by hardware interrupt signal
+    Sample_Period.attach_us(&Sample_timer_interrupt,100); // 100 us, 10.000 KHz
+    // Take N analog samples at sample period
+    // timing is critical inside loop here - needs to be fast
+    for(int k=0; k<N; k++) {
+        // wait and spin here until sample timer interrupt routine sets take sample flag
+        while(take_sample==0) {};
+        // next sample period reached (timer interrupt has set take_sample==1)
+        // reset take sample
+        take_sample=0;
+
+        // select sine or square input source using "sine" bool flag in if - two A/D input channels
+        //read in next sample into Analogs[k]
+//ADD CODE HERE
+
+
+
+
+
+//END ADD CODE HERE
+    }
+    // got the N analog samples
+    // so turn off sample timer interrupts
+    Sample_Period.detach();
+    return;
+}
+
+// **********************************************************************************************
+void Graphic_Display_Spectrum(unsigned char *Data)
+// plots frequency bars using data array - 64 values
+{
+    char max_value=0;
+// clear screen
+    PC.cls();
+    PC.locate(15,0);
+// print title
+    PC.printf("Spectrum Analyzer - Frequency Domain Display");
+//ADD CODE HERE
+    //plot X axis tick marks with labels
+
+
+
+
+
+//END ADD CODE HERE
+    // Find max Data[i] value for autoscaling feature
+    // max value bar should fill the screen display area
+    for (int i=0; i<N/2; i++) {
+        if (Data[i] > max_value) max_value = Data[i];
+    }
+//ADD CODE HERE
+    // Plot Y Axis tick marks with labels
+
+
+
+
+
+
+// use max value for Y axis auto scaling and axis label value calculations
+// draw the frequency bars using Data[i] values (0..N/2 i.e., the positive spectrum only)
+// loop though 20 lines starting at top left of bar display area (lines 1-20)
+    for(int i=2; i<=21; i++) {
+        // then loop through each display bar across 64 cols of display area
+        // if scaled Data[col] value> current line (height) move cursor and print a bar char(222)
+        // values in Data[col] are in range from 0 to max_value
+        // scale so that max_value bar height is number of characters in display area
+        // loop through 64 columns across display
+        for(int k=0; k<(N/2); k++) {
+//            if( Data[k]...
+        }
+//END ADD CODE HERE
+    }
+
+}
+
+//************************************************************************************************
+void Graphic_Display_Time(float *Data)
+// displays Data vs time for Oscilloscope style display
+{
+// clear screen
+    PC.cls();
+    PC.locate(20,0);
+// print title
+    PC.printf("Oscilloscope - Time Domain Display");
+//ADD CODE HERE
+    // Plot Y Axis tick marks with labels
+
+
+
+
+
+    // plot X axis tick marks with labels
+
+
+
+
+
+
+    // loop through each sampled Data[i] value (0..N)
+    // scale to display area, move to proper col,row
+    // and plot each point using a '.' (period)
+    // 128 points in 64 display columns so two samples per column
+    // (but likely value is in a different row)
+    // loop through data values
+    for(int i=0; i<N; i++ ) {
+
+    }
+//END ADD CODE HERE
+}
+