2036 student lab assignment - students must add code where shown
Dependencies: FFT Terminal_VT100 mbed
main.cpp@0:257c8b623a6f, 2012-11-01 (annotated)
- Committer:
- 4180_1
- Date:
- Thu Nov 01 19:10:56 2012 +0000
- Revision:
- 0:257c8b623a6f
ver 1.0 4180 student lab assignment - more code must be added by students
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
4180_1 | 0:257c8b623a6f | 1 | // mymbedDAQ - Electronic Test Instrument Concept Demo & Lab assignment |
4180_1 | 0:257c8b623a6f | 2 | // CODE MUST BE ADDED BY STUDENTS WHERE INDICATED!!!!!!!!!!!!!!! |
4180_1 | 0:257c8b623a6f | 3 | // Uses VT100 terminal application on PC |
4180_1 | 0:257c8b623a6f | 4 | // Needs terminal and FFT libs |
4180_1 | 0:257c8b623a6f | 5 | // |
4180_1 | 0:257c8b623a6f | 6 | // NOTE: for test signals must connect |
4180_1 | 0:257c8b623a6f | 7 | // P18 to P16 (sine wave from D/A to A/D) |
4180_1 | 0:257c8b623a6f | 8 | // P13 to P12 (digital test signal from serial port to LA digital input) |
4180_1 | 0:257c8b623a6f | 9 | // P21 to P15 (PWM for square wave to A/D) |
4180_1 | 0:257c8b623a6f | 10 | // |
4180_1 | 0:257c8b623a6f | 11 | #include "mbed.h" |
4180_1 | 0:257c8b623a6f | 12 | #include "FFT.h" |
4180_1 | 0:257c8b623a6f | 13 | #include "Terminal.h" |
4180_1 | 0:257c8b623a6f | 14 | #include <vector> |
4180_1 | 0:257c8b623a6f | 15 | using namespace std; |
4180_1 | 0:257c8b623a6f | 16 | |
4180_1 | 0:257c8b623a6f | 17 | // ********************************************************************************************** |
4180_1 | 0:257c8b623a6f | 18 | #define N 128 //number of analog samples to take - need power of two for FFT |
4180_1 | 0:257c8b623a6f | 19 | float FFT_Data[N*2]; //complex data space for analog signal's FFT-1D array with real & imag pairs |
4180_1 | 0:257c8b623a6f | 20 | float Data[N]; //data space for (real) analog signal samples |
4180_1 | 0:257c8b623a6f | 21 | float Analog_Voltage; //used for DMM voltage reading |
4180_1 | 0:257c8b623a6f | 22 | float Analog_out_value[N]; // Analog values of precomputed sine wave for D/A (function generator) |
4180_1 | 0:257c8b623a6f | 23 | unsigned char PowerInt[N/2]; //used to store scaled magnitude of FFT bars (positive only) |
4180_1 | 0:257c8b623a6f | 24 | |
4180_1 | 0:257c8b623a6f | 25 | // note use of volatile for an interrupt set global variable! |
4180_1 | 0:257c8b623a6f | 26 | volatile int take_sample; //sample period timer flag - set by interrupt |
4180_1 | 0:257c8b623a6f | 27 | |
4180_1 | 0:257c8b623a6f | 28 | vector <int> Digital_Signal (100); // use a vector for sample data for Logic Analyzer |
4180_1 | 0:257c8b623a6f | 29 | |
4180_1 | 0:257c8b623a6f | 30 | char input_char; //character read from PC terminal application window |
4180_1 | 0:257c8b623a6f | 31 | bool sine=true; //sine or square wave flag for test signal input |
4180_1 | 0:257c8b623a6f | 32 | bool square=true; //50% or 25% duty cycle on square wave test signal |
4180_1 | 0:257c8b623a6f | 33 | |
4180_1 | 0:257c8b623a6f | 34 | |
4180_1 | 0:257c8b623a6f | 35 | //Digital Signals for Logic Analyzer |
4180_1 | 0:257c8b623a6f | 36 | |
4180_1 | 0:257c8b623a6f | 37 | // Used to read in digital signals |
4180_1 | 0:257c8b623a6f | 38 | DigitalIn LogicAnalyzer_test_signal_in(p12); |
4180_1 | 0:257c8b623a6f | 39 | // Used for digital test signal output |
4180_1 | 0:257c8b623a6f | 40 | Serial LogicAnalyzer_test_signal_out(p13,p14); |
4180_1 | 0:257c8b623a6f | 41 | |
4180_1 | 0:257c8b623a6f | 42 | //Analog I/O Signals for DMM, Oscilloscope, and Spectrum Analyzer |
4180_1 | 0:257c8b623a6f | 43 | |
4180_1 | 0:257c8b623a6f | 44 | // Analog A/D Input |
4180_1 | 0:257c8b623a6f | 45 | AnalogIn Analog_test_signal_in(p16); |
4180_1 | 0:257c8b623a6f | 46 | // Analog D/A output test signal (for sine wave function generation) |
4180_1 | 0:257c8b623a6f | 47 | AnalogOut Analog_test_signal_out(p18); |
4180_1 | 0:257c8b623a6f | 48 | |
4180_1 | 0:257c8b623a6f | 49 | |
4180_1 | 0:257c8b623a6f | 50 | // PWM is used for alternate analog square wave signal source |
4180_1 | 0:257c8b623a6f | 51 | |
4180_1 | 0:257c8b623a6f | 52 | // Analog A/D Input used for square wave |
4180_1 | 0:257c8b623a6f | 53 | AnalogIn PWM_test_signal(p15); |
4180_1 | 0:257c8b623a6f | 54 | // PWM output pint that generates a square wave |
4180_1 | 0:257c8b623a6f | 55 | PwmOut PWM_Output(p21); |
4180_1 | 0:257c8b623a6f | 56 | |
4180_1 | 0:257c8b623a6f | 57 | //unsed Analog input pins set to digital to reduce A/D noise |
4180_1 | 0:257c8b623a6f | 58 | DigitalOut d2(p17); |
4180_1 | 0:257c8b623a6f | 59 | DigitalOut d3(p19); |
4180_1 | 0:257c8b623a6f | 60 | DigitalOut d4(p20); |
4180_1 | 0:257c8b623a6f | 61 | |
4180_1 | 0:257c8b623a6f | 62 | //VT100 ANSI Terminal connected to PC |
4180_1 | 0:257c8b623a6f | 63 | Terminal PC(USBTX, USBRX); |
4180_1 | 0:257c8b623a6f | 64 | |
4180_1 | 0:257c8b623a6f | 65 | |
4180_1 | 0:257c8b623a6f | 66 | // ********************************************************************************************** |
4180_1 | 0:257c8b623a6f | 67 | |
4180_1 | 0:257c8b623a6f | 68 | void Take_Analog_Signal_Samples(float Analogs[]); |
4180_1 | 0:257c8b623a6f | 69 | void Graphic_Display_Spectrum(unsigned char *Data); |
4180_1 | 0:257c8b623a6f | 70 | void Graphic_Display_Time(float *Data); |
4180_1 | 0:257c8b623a6f | 71 | void Digital_Multimeter(); |
4180_1 | 0:257c8b623a6f | 72 | void Logic_Analyzer(); |
4180_1 | 0:257c8b623a6f | 73 | void Oscilloscope(); |
4180_1 | 0:257c8b623a6f | 74 | void Spectrum_Analyzer(); |
4180_1 | 0:257c8b623a6f | 75 | void Function_Select(); |
4180_1 | 0:257c8b623a6f | 76 | void Duty_Cycle(); |
4180_1 | 0:257c8b623a6f | 77 | |
4180_1 | 0:257c8b623a6f | 78 | // ********************************************************************************************** |
4180_1 | 0:257c8b623a6f | 79 | |
4180_1 | 0:257c8b623a6f | 80 | int main() |
4180_1 | 0:257c8b623a6f | 81 | { |
4180_1 | 0:257c8b623a6f | 82 | // Start PWM hardware for a continuous square wave signal ouput with a 50% duty cycle |
4180_1 | 0:257c8b623a6f | 83 | PWM_Output=0.5; |
4180_1 | 0:257c8b623a6f | 84 | PWM_Output.period(0.0128); |
4180_1 | 0:257c8b623a6f | 85 | while(1) { |
4180_1 | 0:257c8b623a6f | 86 | // clear screen and print user menu selections |
4180_1 | 0:257c8b623a6f | 87 | PC.cls(); |
4180_1 | 0:257c8b623a6f | 88 | PC.locate(0,5); |
4180_1 | 0:257c8b623a6f | 89 | PC.printf(" 1 - Digital Multimeter\n\r"); |
4180_1 | 0:257c8b623a6f | 90 | PC.printf(" 2 - Logic Analyzer\n\r"); |
4180_1 | 0:257c8b623a6f | 91 | PC.printf(" 3 - Oscilloscope\n\r"); |
4180_1 | 0:257c8b623a6f | 92 | PC.printf(" 4 - Spectrum Analyzer \n\r"); |
4180_1 | 0:257c8b623a6f | 93 | PC.printf(" 5 - Function Generation - toggles between sine & square wave signal\n\r"); |
4180_1 | 0:257c8b623a6f | 94 | PC.printf(" 6 - Duty Cycle - toggles between 50%% and 25%% duty cycle on square wave"); |
4180_1 | 0:257c8b623a6f | 95 | PC.locate(0,0); |
4180_1 | 0:257c8b623a6f | 96 | PC.printf(" Select Electronic Test Instrument (type 1...5)"); |
4180_1 | 0:257c8b623a6f | 97 | // reads a character from the PC terminal appication window |
4180_1 | 0:257c8b623a6f | 98 | input_char=PC.getc(); |
4180_1 | 0:257c8b623a6f | 99 | // echo back selection char for human display on PC |
4180_1 | 0:257c8b623a6f | 100 | PC.putc(input_char); |
4180_1 | 0:257c8b623a6f | 101 | // delay for slow human to see character |
4180_1 | 0:257c8b623a6f | 102 | wait(.5); |
4180_1 | 0:257c8b623a6f | 103 | //ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 104 | // select instrument demo using input_char switch statement |
4180_1 | 0:257c8b623a6f | 105 | // case for each function below |
4180_1 | 0:257c8b623a6f | 106 | // 1 Digital_Multimeter(); |
4180_1 | 0:257c8b623a6f | 107 | // 2 Logic_Analyzer(); |
4180_1 | 0:257c8b623a6f | 108 | // 3 Oscilloscope(); |
4180_1 | 0:257c8b623a6f | 109 | // 4 Spectrum_Analyzer(); |
4180_1 | 0:257c8b623a6f | 110 | // 5 Function Select(); |
4180_1 | 0:257c8b623a6f | 111 | // 6 Duty Cycle(); |
4180_1 | 0:257c8b623a6f | 112 | |
4180_1 | 0:257c8b623a6f | 113 | |
4180_1 | 0:257c8b623a6f | 114 | |
4180_1 | 0:257c8b623a6f | 115 | |
4180_1 | 0:257c8b623a6f | 116 | |
4180_1 | 0:257c8b623a6f | 117 | //END ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 118 | } |
4180_1 | 0:257c8b623a6f | 119 | } |
4180_1 | 0:257c8b623a6f | 120 | |
4180_1 | 0:257c8b623a6f | 121 | //********************************************************************************************* |
4180_1 | 0:257c8b623a6f | 122 | // toggles a flag between a sine or square wave test output |
4180_1 | 0:257c8b623a6f | 123 | // sine flag is used in Take_Analog_Signal_Samples |
4180_1 | 0:257c8b623a6f | 124 | void Function_Select() |
4180_1 | 0:257c8b623a6f | 125 | { |
4180_1 | 0:257c8b623a6f | 126 | sine=!sine; |
4180_1 | 0:257c8b623a6f | 127 | } |
4180_1 | 0:257c8b623a6f | 128 | |
4180_1 | 0:257c8b623a6f | 129 | //********************************************************************************************** |
4180_1 | 0:257c8b623a6f | 130 | // Toggles the hardware PWM output between a 25% and 50% duty cycle square wave |
4180_1 | 0:257c8b623a6f | 131 | // square flag stores state |
4180_1 | 0:257c8b623a6f | 132 | void Duty_Cycle() |
4180_1 | 0:257c8b623a6f | 133 | { |
4180_1 | 0:257c8b623a6f | 134 | if (square) |
4180_1 | 0:257c8b623a6f | 135 | PWM_Output=0.25; |
4180_1 | 0:257c8b623a6f | 136 | else |
4180_1 | 0:257c8b623a6f | 137 | PWM_Output=0.5; |
4180_1 | 0:257c8b623a6f | 138 | square=!square; |
4180_1 | 0:257c8b623a6f | 139 | //PWM hardware needs a bit of setup time to adjust |
4180_1 | 0:257c8b623a6f | 140 | wait(.25); |
4180_1 | 0:257c8b623a6f | 141 | } |
4180_1 | 0:257c8b623a6f | 142 | |
4180_1 | 0:257c8b623a6f | 143 | // ********************************************************************************************** |
4180_1 | 0:257c8b623a6f | 144 | |
4180_1 | 0:257c8b623a6f | 145 | void Digital_Multimeter() |
4180_1 | 0:257c8b623a6f | 146 | { |
4180_1 | 0:257c8b623a6f | 147 | // PC.readable() indicates another character is available to read |
4180_1 | 0:257c8b623a6f | 148 | // but it does not read the character or wait for a character |
4180_1 | 0:257c8b623a6f | 149 | // It is a handy way to break out of a loop if any key is hit |
4180_1 | 0:257c8b623a6f | 150 | while(!PC.readable()) { |
4180_1 | 0:257c8b623a6f | 151 | // Digital Multimeter - reads an analog voltage on pin 16 |
4180_1 | 0:257c8b623a6f | 152 | // D/A output is connected to A/D input (0..3.3V range only!) |
4180_1 | 0:257c8b623a6f | 153 | PC.cls(); //clear screen |
4180_1 | 0:257c8b623a6f | 154 | PC.locate(9,0); // move cursor to 9,0 |
4180_1 | 0:257c8b623a6f | 155 | PC.printf("Digital Multimeter"); // print title |
4180_1 | 0:257c8b623a6f | 156 | PC.locate(22,12); |
4180_1 | 0:257c8b623a6f | 157 | PC.printf(" volts DC"); // label for voltage reading |
4180_1 | 0:257c8b623a6f | 158 | // Plot Y Axis tick marks with labels |
4180_1 | 0:257c8b623a6f | 159 | for(int i=21; i>3; i--) { |
4180_1 | 0:257c8b623a6f | 160 | PC.locate(7,i); |
4180_1 | 0:257c8b623a6f | 161 | // put a label every 1 volt on axis |
4180_1 | 0:257c8b623a6f | 162 | if((i-1)%5==0) { |
4180_1 | 0:257c8b623a6f | 163 | PC.putc('+'); |
4180_1 | 0:257c8b623a6f | 164 | PC.locate(1,i); |
4180_1 | 0:257c8b623a6f | 165 | PC.printf("%d.0V",int((21.0-i)/16.0*3.3)); |
4180_1 | 0:257c8b623a6f | 166 | } else PC.putc('-'); |
4180_1 | 0:257c8b623a6f | 167 | } |
4180_1 | 0:257c8b623a6f | 168 | for(int i=0; i<=64; i++) { |
4180_1 | 0:257c8b623a6f | 169 | // Output the Analog test signal using D/A output 'Analog_test_signal_out |
4180_1 | 0:257c8b623a6f | 170 | // makes D/A outputvoltage increase linear from 0 to 3.3 |
4180_1 | 0:257c8b623a6f | 171 | // (but scaled from 0 to 1.0 in C/C++) using loop value i to change it |
4180_1 | 0:257c8b623a6f | 172 | //ADD CODE HERE - 1 line |
4180_1 | 0:257c8b623a6f | 173 | |
4180_1 | 0:257c8b623a6f | 174 | //END ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 175 | // Print voltage at 15,12 |
4180_1 | 0:257c8b623a6f | 176 | PC.locate(15,12); |
4180_1 | 0:257c8b623a6f | 177 | //ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 178 | // read in the analog voltage using A/D input "Analog_test_signal_in" |
4180_1 | 0:257c8b623a6f | 179 | // multiply value by 3.3 to convert to actual voltage level |
4180_1 | 0:257c8b623a6f | 180 | // save in "Analog_Voltage" |
4180_1 | 0:257c8b623a6f | 181 | |
4180_1 | 0:257c8b623a6f | 182 | // Print Analog_Voltage*3.3 in "%7.3F" format |
4180_1 | 0:257c8b623a6f | 183 | |
4180_1 | 0:257c8b623a6f | 184 | // Display Analog Level Bar but only every four display updates (i%4) for faster updates |
4180_1 | 0:257c8b623a6f | 185 | // on PC use char(219) for a solid bar graphics character or a space ' ' to erase |
4180_1 | 0:257c8b623a6f | 186 | // use locate to draw a vertical bar |
4180_1 | 0:257c8b623a6f | 187 | |
4180_1 | 0:257c8b623a6f | 188 | |
4180_1 | 0:257c8b623a6f | 189 | |
4180_1 | 0:257c8b623a6f | 190 | |
4180_1 | 0:257c8b623a6f | 191 | |
4180_1 | 0:257c8b623a6f | 192 | } |
4180_1 | 0:257c8b623a6f | 193 | //END ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 194 | } |
4180_1 | 0:257c8b623a6f | 195 | // delay to allow time to view each display |
4180_1 | 0:257c8b623a6f | 196 | wait(1); |
4180_1 | 0:257c8b623a6f | 197 | } |
4180_1 | 0:257c8b623a6f | 198 | |
4180_1 | 0:257c8b623a6f | 199 | // ********************************************************************************************** |
4180_1 | 0:257c8b623a6f | 200 | |
4180_1 | 0:257c8b623a6f | 201 | void Logic_Analyzer() |
4180_1 | 0:257c8b623a6f | 202 | { |
4180_1 | 0:257c8b623a6f | 203 | // Logic Analyzer |
4180_1 | 0:257c8b623a6f | 204 | // Reads in a serial digital output pin (0 or 3.3V) |
4180_1 | 0:257c8b623a6f | 205 | // pin 13 TX serial output tied to pin12 digital input |
4180_1 | 0:257c8b623a6f | 206 | while(!PC.readable()) { |
4180_1 | 0:257c8b623a6f | 207 | // Loop through several ASCII characters for display test |
4180_1 | 0:257c8b623a6f | 208 | for(int c='A'; c<='z'&&!PC.readable(); c=c+1) { |
4180_1 | 0:257c8b623a6f | 209 | PC.cls(); |
4180_1 | 0:257c8b623a6f | 210 | Digital_Signal.clear(); |
4180_1 | 0:257c8b623a6f | 211 | PC.locate(15,0); |
4180_1 | 0:257c8b623a6f | 212 | PC.printf("Logic Analyzer Display - RS-232 Serial ASCII character %c 0x%X",char(c), int(c)); |
4180_1 | 0:257c8b623a6f | 213 | // Sample digital data for display - need 80 samples (have 80 display cols) |
4180_1 | 0:257c8b623a6f | 214 | for(int i=0; i<80; i++) { |
4180_1 | 0:257c8b623a6f | 215 | // Test signal for Logic Analyzer |
4180_1 | 0:257c8b623a6f | 216 | // Send out a new character char(c) using the serial port |
4180_1 | 0:257c8b623a6f | 217 | // after a small delay so that it will show up in middle of display |
4180_1 | 0:257c8b623a6f | 218 | if(i==6) LogicAnalyzer_test_signal_out.putc(char(c)); |
4180_1 | 0:257c8b623a6f | 219 | //ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 220 | // Use "Digital_Signal" vector to store data from "LogicAnalyzer_test_signal_in" (DigitalIn pin) |
4180_1 | 0:257c8b623a6f | 221 | |
4180_1 | 0:257c8b623a6f | 222 | // time delay is used to adjust sample time interval |
4180_1 | 0:257c8b623a6f | 223 | // a hardware timer would be more accurate |
4180_1 | 0:257c8b623a6f | 224 | // that will be explained later in the oscilloscope example |
4180_1 | 0:257c8b623a6f | 225 | // some adjustment to time delay here might be needed for your code |
4180_1 | 0:257c8b623a6f | 226 | // scale so that you can see entire ASCII character on display |
4180_1 | 0:257c8b623a6f | 227 | wait(.00002); |
4180_1 | 0:257c8b623a6f | 228 | } |
4180_1 | 0:257c8b623a6f | 229 | //Display data |
4180_1 | 0:257c8b623a6f | 230 | //Move cursor to 0,15 or 0,5 based on first digital bit from Digital_Signal[i] |
4180_1 | 0:257c8b623a6f | 231 | //Scan through data samples from left to right and draw the high or low line |
4180_1 | 0:257c8b623a6f | 232 | //Locate is only needed when changing between high or low value |
4180_1 | 0:257c8b623a6f | 233 | //loop through 80 sample values |
4180_1 | 0:257c8b623a6f | 234 | PC.locate(0,(15 - int(float(Digital_Signal[0])*10.0))); |
4180_1 | 0:257c8b623a6f | 235 | for(int i=0; i<80; i++) { |
4180_1 | 0:257c8b623a6f | 236 | // If no change in digital signal, or fist bit just output a horiz bar char(196)? |
4180_1 | 0:257c8b623a6f | 237 | |
4180_1 | 0:257c8b623a6f | 238 | // if A 1 to 0 transisition occured |
4180_1 | 0:257c8b623a6f | 239 | // draw a vertical line with correct bar and corner characters (191, 179, 192) |
4180_1 | 0:257c8b623a6f | 240 | // PC.locate(col,row) is needed for vertical line drawing |
4180_1 | 0:257c8b623a6f | 241 | |
4180_1 | 0:257c8b623a6f | 242 | |
4180_1 | 0:257c8b623a6f | 243 | |
4180_1 | 0:257c8b623a6f | 244 | |
4180_1 | 0:257c8b623a6f | 245 | |
4180_1 | 0:257c8b623a6f | 246 | //if A 0 to 1 transisiton occured |
4180_1 | 0:257c8b623a6f | 247 | // draw a vertical line with correct bar and corner characters (217, 179, 218) |
4180_1 | 0:257c8b623a6f | 248 | |
4180_1 | 0:257c8b623a6f | 249 | |
4180_1 | 0:257c8b623a6f | 250 | |
4180_1 | 0:257c8b623a6f | 251 | |
4180_1 | 0:257c8b623a6f | 252 | |
4180_1 | 0:257c8b623a6f | 253 | } |
4180_1 | 0:257c8b623a6f | 254 | //plot X axis tick marks and labels |
4180_1 | 0:257c8b623a6f | 255 | //only initial locate needed |
4180_1 | 0:257c8b623a6f | 256 | PC.locate(0,20); |
4180_1 | 0:257c8b623a6f | 257 | |
4180_1 | 0:257c8b623a6f | 258 | |
4180_1 | 0:257c8b623a6f | 259 | |
4180_1 | 0:257c8b623a6f | 260 | |
4180_1 | 0:257c8b623a6f | 261 | |
4180_1 | 0:257c8b623a6f | 262 | |
4180_1 | 0:257c8b623a6f | 263 | //END ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 264 | // delay to allow time to view each display |
4180_1 | 0:257c8b623a6f | 265 | wait(1); |
4180_1 | 0:257c8b623a6f | 266 | } |
4180_1 | 0:257c8b623a6f | 267 | } |
4180_1 | 0:257c8b623a6f | 268 | } |
4180_1 | 0:257c8b623a6f | 269 | // ********************************************************************************************** |
4180_1 | 0:257c8b623a6f | 270 | |
4180_1 | 0:257c8b623a6f | 271 | void Oscilloscope() |
4180_1 | 0:257c8b623a6f | 272 | { |
4180_1 | 0:257c8b623a6f | 273 | while(!PC.readable()) { |
4180_1 | 0:257c8b623a6f | 274 | // Oscilloscope |
4180_1 | 0:257c8b623a6f | 275 | // D/A sends out a sine wave and the A/D reads it back in |
4180_1 | 0:257c8b623a6f | 276 | // PWM hardware sends out a square wave to another A/D input |
4180_1 | 0:257c8b623a6f | 277 | // loop through increasing the frequency of the test signals for each display |
4180_1 | 0:257c8b623a6f | 278 | for(int i=1; i<11&&!PC.readable(); i++) { |
4180_1 | 0:257c8b623a6f | 279 | //Setup square wave signal source period - increase each loop iteration |
4180_1 | 0:257c8b623a6f | 280 | PWM_Output.period(0.0128/i); |
4180_1 | 0:257c8b623a6f | 281 | wait(0.25); |
4180_1 | 0:257c8b623a6f | 282 | // Precompute sine wave values for faster D/A output to save execution time |
4180_1 | 0:257c8b623a6f | 283 | // Need to add DC bias and scale sine wave from 0...1.0 for analog out function |
4180_1 | 0:257c8b623a6f | 284 | // (i.e. not just -1..1) |
4180_1 | 0:257c8b623a6f | 285 | // need N samples of one sine cycle first time - then make it i times faster each |
4180_1 | 0:257c8b623a6f | 286 | // loop iteration - samples go in Analog_out_value[k] |
4180_1 | 0:257c8b623a6f | 287 | for(int k=0; k<N; k++) { |
4180_1 | 0:257c8b623a6f | 288 | //ADD CODE HERE - 1 line to compute sine values |
4180_1 | 0:257c8b623a6f | 289 | |
4180_1 | 0:257c8b623a6f | 290 | //END ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 291 | } |
4180_1 | 0:257c8b623a6f | 292 | //Reads analog samples using test signals setup above |
4180_1 | 0:257c8b623a6f | 293 | Take_Analog_Signal_Samples(Data); |
4180_1 | 0:257c8b623a6f | 294 | //Displays an analog signal in time |
4180_1 | 0:257c8b623a6f | 295 | Graphic_Display_Time(Data); |
4180_1 | 0:257c8b623a6f | 296 | // delay to allow time to view each display |
4180_1 | 0:257c8b623a6f | 297 | wait(2); |
4180_1 | 0:257c8b623a6f | 298 | } |
4180_1 | 0:257c8b623a6f | 299 | } |
4180_1 | 0:257c8b623a6f | 300 | } |
4180_1 | 0:257c8b623a6f | 301 | |
4180_1 | 0:257c8b623a6f | 302 | // ********************************************************************************************** |
4180_1 | 0:257c8b623a6f | 303 | void Spectrum_Analyzer() |
4180_1 | 0:257c8b623a6f | 304 | { |
4180_1 | 0:257c8b623a6f | 305 | while(!PC.readable()) { |
4180_1 | 0:257c8b623a6f | 306 | // Spectrum Analyzer |
4180_1 | 0:257c8b623a6f | 307 | // Compute FFT of sampled signal |
4180_1 | 0:257c8b623a6f | 308 | // D/A sends out a sine wave and the A/D reads it back in |
4180_1 | 0:257c8b623a6f | 309 | // loop through increasing the frequency of test signals for each display |
4180_1 | 0:257c8b623a6f | 310 | for(int i=1; i<11&&!PC.readable(); i++) { |
4180_1 | 0:257c8b623a6f | 311 | //Setup square wave signal source with correct period |
4180_1 | 0:257c8b623a6f | 312 | PWM_Output.period(.0128/i); |
4180_1 | 0:257c8b623a6f | 313 | wait(0.25); |
4180_1 | 0:257c8b623a6f | 314 | //Precompute sine wave values for D/A output to save execution time |
4180_1 | 0:257c8b623a6f | 315 | //same as Oscilloscope code earlier |
4180_1 | 0:257c8b623a6f | 316 | for(int k=0; k<N; k++) { |
4180_1 | 0:257c8b623a6f | 317 | //ADD CODE HERE - line |
4180_1 | 0:257c8b623a6f | 318 | |
4180_1 | 0:257c8b623a6f | 319 | //END ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 320 | } |
4180_1 | 0:257c8b623a6f | 321 | //Reads analog samples |
4180_1 | 0:257c8b623a6f | 322 | Take_Analog_Signal_Samples(Data); |
4180_1 | 0:257c8b623a6f | 323 | // put data in complex format for FFT code (real followed by imag=0 in 2*N 1D array) |
4180_1 | 0:257c8b623a6f | 324 | // Required by Numerical Recipes in C++ Algorithm for FFT used in in vFFT.cpp |
4180_1 | 0:257c8b623a6f | 325 | for(int k=0; k<N; k++) { |
4180_1 | 0:257c8b623a6f | 326 | FFT_Data[k*2]=Data[k]; |
4180_1 | 0:257c8b623a6f | 327 | FFT_Data[k*2+1] = 0.0; |
4180_1 | 0:257c8b623a6f | 328 | } |
4180_1 | 0:257c8b623a6f | 329 | Graphic_Display_Time(Data); |
4180_1 | 0:257c8b623a6f | 330 | // delay to allow time to view each time display |
4180_1 | 0:257c8b623a6f | 331 | wait(2); |
4180_1 | 0:257c8b623a6f | 332 | // Spectrum Analyzer |
4180_1 | 0:257c8b623a6f | 333 | // Compute FFT of sampled signal |
4180_1 | 0:257c8b623a6f | 334 | vFFT(FFT_Data-1,N); |
4180_1 | 0:257c8b623a6f | 335 | // Compute magnitude for positive frequency display |
4180_1 | 0:257c8b623a6f | 336 | // scaled and returned in a char array |
4180_1 | 0:257c8b623a6f | 337 | vCalPowerInt(FFT_Data,PowerInt,N/2); |
4180_1 | 0:257c8b623a6f | 338 | // Display Frequency content of sampled signal |
4180_1 | 0:257c8b623a6f | 339 | Graphic_Display_Spectrum(PowerInt); |
4180_1 | 0:257c8b623a6f | 340 | // delay to allow time to view each frequency display |
4180_1 | 0:257c8b623a6f | 341 | wait(2); |
4180_1 | 0:257c8b623a6f | 342 | } |
4180_1 | 0:257c8b623a6f | 343 | } |
4180_1 | 0:257c8b623a6f | 344 | } |
4180_1 | 0:257c8b623a6f | 345 | |
4180_1 | 0:257c8b623a6f | 346 | |
4180_1 | 0:257c8b623a6f | 347 | // ********************************************************************************************** |
4180_1 | 0:257c8b623a6f | 348 | // Functions to sample Analog input data at an accurate 10Khz rate (every 100 us) |
4180_1 | 0:257c8b623a6f | 349 | // used by Oscilloscope and Spectrum Analyzer |
4180_1 | 0:257c8b623a6f | 350 | void Sample_timer_interrupt(void) |
4180_1 | 0:257c8b623a6f | 351 | { |
4180_1 | 0:257c8b623a6f | 352 | // Sets flag when time to read in another analog sample |
4180_1 | 0:257c8b623a6f | 353 | // Timer interrupt comes here when a it hits every sample time interval |
4180_1 | 0:257c8b623a6f | 354 | take_sample=1; |
4180_1 | 0:257c8b623a6f | 355 | } |
4180_1 | 0:257c8b623a6f | 356 | void Take_Analog_Signal_Samples(float Analogs[]) |
4180_1 | 0:257c8b623a6f | 357 | { |
4180_1 | 0:257c8b623a6f | 358 | // setup a timer to determine accurate sample time |
4180_1 | 0:257c8b623a6f | 359 | Ticker Sample_Period; |
4180_1 | 0:257c8b623a6f | 360 | // reset sample time interval flag |
4180_1 | 0:257c8b623a6f | 361 | take_sample=0; |
4180_1 | 0:257c8b623a6f | 362 | // output first D/A value for sine wave |
4180_1 | 0:257c8b623a6f | 363 | Analog_test_signal_out=Analog_out_value[0]; |
4180_1 | 0:257c8b623a6f | 364 | // Start periodic timer interrupts to ensure accurate control of sample time interval |
4180_1 | 0:257c8b623a6f | 365 | // Sample_timer_interrupt is "called" every 100 us by hardware interrupt signal |
4180_1 | 0:257c8b623a6f | 366 | Sample_Period.attach_us(&Sample_timer_interrupt,100); // 100 us, 10.000 KHz |
4180_1 | 0:257c8b623a6f | 367 | // Take N analog samples at sample period |
4180_1 | 0:257c8b623a6f | 368 | // timing is critical inside loop here - needs to be fast |
4180_1 | 0:257c8b623a6f | 369 | for(int k=0; k<N; k++) { |
4180_1 | 0:257c8b623a6f | 370 | // wait and spin here until sample timer interrupt routine sets take sample flag |
4180_1 | 0:257c8b623a6f | 371 | while(take_sample==0) {}; |
4180_1 | 0:257c8b623a6f | 372 | // next sample period reached (timer interrupt has set take_sample==1) |
4180_1 | 0:257c8b623a6f | 373 | // reset take sample |
4180_1 | 0:257c8b623a6f | 374 | take_sample=0; |
4180_1 | 0:257c8b623a6f | 375 | |
4180_1 | 0:257c8b623a6f | 376 | // select sine or square input source using "sine" bool flag in if - two A/D input channels |
4180_1 | 0:257c8b623a6f | 377 | //read in next sample into Analogs[k] |
4180_1 | 0:257c8b623a6f | 378 | //ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 379 | |
4180_1 | 0:257c8b623a6f | 380 | |
4180_1 | 0:257c8b623a6f | 381 | |
4180_1 | 0:257c8b623a6f | 382 | |
4180_1 | 0:257c8b623a6f | 383 | |
4180_1 | 0:257c8b623a6f | 384 | //END ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 385 | } |
4180_1 | 0:257c8b623a6f | 386 | // got the N analog samples |
4180_1 | 0:257c8b623a6f | 387 | // so turn off sample timer interrupts |
4180_1 | 0:257c8b623a6f | 388 | Sample_Period.detach(); |
4180_1 | 0:257c8b623a6f | 389 | return; |
4180_1 | 0:257c8b623a6f | 390 | } |
4180_1 | 0:257c8b623a6f | 391 | |
4180_1 | 0:257c8b623a6f | 392 | // ********************************************************************************************** |
4180_1 | 0:257c8b623a6f | 393 | void Graphic_Display_Spectrum(unsigned char *Data) |
4180_1 | 0:257c8b623a6f | 394 | // plots frequency bars using data array - 64 values |
4180_1 | 0:257c8b623a6f | 395 | { |
4180_1 | 0:257c8b623a6f | 396 | char max_value=0; |
4180_1 | 0:257c8b623a6f | 397 | // clear screen |
4180_1 | 0:257c8b623a6f | 398 | PC.cls(); |
4180_1 | 0:257c8b623a6f | 399 | PC.locate(15,0); |
4180_1 | 0:257c8b623a6f | 400 | // print title |
4180_1 | 0:257c8b623a6f | 401 | PC.printf("Spectrum Analyzer - Frequency Domain Display"); |
4180_1 | 0:257c8b623a6f | 402 | //ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 403 | //plot X axis tick marks with labels |
4180_1 | 0:257c8b623a6f | 404 | |
4180_1 | 0:257c8b623a6f | 405 | |
4180_1 | 0:257c8b623a6f | 406 | |
4180_1 | 0:257c8b623a6f | 407 | |
4180_1 | 0:257c8b623a6f | 408 | |
4180_1 | 0:257c8b623a6f | 409 | //END ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 410 | // Find max Data[i] value for autoscaling feature |
4180_1 | 0:257c8b623a6f | 411 | // max value bar should fill the screen display area |
4180_1 | 0:257c8b623a6f | 412 | for (int i=0; i<N/2; i++) { |
4180_1 | 0:257c8b623a6f | 413 | if (Data[i] > max_value) max_value = Data[i]; |
4180_1 | 0:257c8b623a6f | 414 | } |
4180_1 | 0:257c8b623a6f | 415 | //ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 416 | // Plot Y Axis tick marks with labels |
4180_1 | 0:257c8b623a6f | 417 | |
4180_1 | 0:257c8b623a6f | 418 | |
4180_1 | 0:257c8b623a6f | 419 | |
4180_1 | 0:257c8b623a6f | 420 | |
4180_1 | 0:257c8b623a6f | 421 | |
4180_1 | 0:257c8b623a6f | 422 | |
4180_1 | 0:257c8b623a6f | 423 | // use max value for Y axis auto scaling and axis label value calculations |
4180_1 | 0:257c8b623a6f | 424 | // draw the frequency bars using Data[i] values (0..N/2 i.e., the positive spectrum only) |
4180_1 | 0:257c8b623a6f | 425 | // loop though 20 lines starting at top left of bar display area (lines 1-20) |
4180_1 | 0:257c8b623a6f | 426 | for(int i=2; i<=21; i++) { |
4180_1 | 0:257c8b623a6f | 427 | // then loop through each display bar across 64 cols of display area |
4180_1 | 0:257c8b623a6f | 428 | // if scaled Data[col] value> current line (height) move cursor and print a bar char(222) |
4180_1 | 0:257c8b623a6f | 429 | // values in Data[col] are in range from 0 to max_value |
4180_1 | 0:257c8b623a6f | 430 | // scale so that max_value bar height is number of characters in display area |
4180_1 | 0:257c8b623a6f | 431 | // loop through 64 columns across display |
4180_1 | 0:257c8b623a6f | 432 | for(int k=0; k<(N/2); k++) { |
4180_1 | 0:257c8b623a6f | 433 | // if( Data[k]... |
4180_1 | 0:257c8b623a6f | 434 | } |
4180_1 | 0:257c8b623a6f | 435 | //END ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 436 | } |
4180_1 | 0:257c8b623a6f | 437 | |
4180_1 | 0:257c8b623a6f | 438 | } |
4180_1 | 0:257c8b623a6f | 439 | |
4180_1 | 0:257c8b623a6f | 440 | //************************************************************************************************ |
4180_1 | 0:257c8b623a6f | 441 | void Graphic_Display_Time(float *Data) |
4180_1 | 0:257c8b623a6f | 442 | // displays Data vs time for Oscilloscope style display |
4180_1 | 0:257c8b623a6f | 443 | { |
4180_1 | 0:257c8b623a6f | 444 | // clear screen |
4180_1 | 0:257c8b623a6f | 445 | PC.cls(); |
4180_1 | 0:257c8b623a6f | 446 | PC.locate(20,0); |
4180_1 | 0:257c8b623a6f | 447 | // print title |
4180_1 | 0:257c8b623a6f | 448 | PC.printf("Oscilloscope - Time Domain Display"); |
4180_1 | 0:257c8b623a6f | 449 | //ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 450 | // Plot Y Axis tick marks with labels |
4180_1 | 0:257c8b623a6f | 451 | |
4180_1 | 0:257c8b623a6f | 452 | |
4180_1 | 0:257c8b623a6f | 453 | |
4180_1 | 0:257c8b623a6f | 454 | |
4180_1 | 0:257c8b623a6f | 455 | |
4180_1 | 0:257c8b623a6f | 456 | // plot X axis tick marks with labels |
4180_1 | 0:257c8b623a6f | 457 | |
4180_1 | 0:257c8b623a6f | 458 | |
4180_1 | 0:257c8b623a6f | 459 | |
4180_1 | 0:257c8b623a6f | 460 | |
4180_1 | 0:257c8b623a6f | 461 | |
4180_1 | 0:257c8b623a6f | 462 | |
4180_1 | 0:257c8b623a6f | 463 | // loop through each sampled Data[i] value (0..N) |
4180_1 | 0:257c8b623a6f | 464 | // scale to display area, move to proper col,row |
4180_1 | 0:257c8b623a6f | 465 | // and plot each point using a '.' (period) |
4180_1 | 0:257c8b623a6f | 466 | // 128 points in 64 display columns so two samples per column |
4180_1 | 0:257c8b623a6f | 467 | // (but likely value is in a different row) |
4180_1 | 0:257c8b623a6f | 468 | // loop through data values |
4180_1 | 0:257c8b623a6f | 469 | for(int i=0; i<N; i++ ) { |
4180_1 | 0:257c8b623a6f | 470 | |
4180_1 | 0:257c8b623a6f | 471 | } |
4180_1 | 0:257c8b623a6f | 472 | //END ADD CODE HERE |
4180_1 | 0:257c8b623a6f | 473 | } |
4180_1 | 0:257c8b623a6f | 474 |